def message_handler(self, message: Union[FriendMessage, GroupMessage]): "一句话只能触发一个指令." after_prefix = None for prefix_pattern in self.command_prefix: after_prefix = \ oit.chain_regex_match_headpop( copy.copy(message.messageChain), prefix_pattern ) if after_prefix: break else: return # 如果到了这里, 就说明这句话试图触发一个指令 matched_command_entity = None matched_command_params = None special_handle_for_raw_string = None matched_result = None for command in self.commands: matched_command_entity = command for command_match in [command.match, *command.aliases]: matched_info = oit.chain_match(command_match, MessageChain(__root__=after_prefix.__root__[1:]) ) if matched_info: # 匹配到了. matched_result, special_handle_for_raw_string = matched_info break else: # 没匹配到 return # 处理 matched_command_params optional_params = { param.name: param.default \ for param in \ argument_signature(matched_command_entity.execator) } return { "command": matched_command_entity, "parameters": { **({ # 因为蜜汁原因, 导致我们还得判断一步...但这应该在外部执行(要获取 execator 的 default...) # 多出来的这一步是因为 python-mirai 内部逻辑的缺点...我们必须克服它. k: special_handle_for_raw_string(v) if isinstance(v, str) else (v if v != None else optional_params.get(k)) for k, v in matched_result.items() }) } }
def checkFuncAnnotations(self, callable_target: Callable): restraint_mapping = self.getRestraintMapping() registered_events = self.getFuncRegisteredEvents(callable_target) for name, annotation, default in argument_signature(callable_target): if not default: if not registered_events: raise ValueError(f"error in annotations checker: {callable_target} is invaild.") for event_name in registered_events: try: if not restraint_mapping[annotation](type(event_name, (object,), {})()): raise ValueError( f"error in annotations checker: {callable_target}.[{name}:{annotation}]: {event_name}") except KeyError: raise ValueError( f"error in annotations checker: {callable_target}.[{name}:{annotation}] is invaild.") except ValueError: raise
def checkDependencies(self, depend_target: Depend): self.checkEventBodyAnnotations() for name, annotation, default in argument_signature(depend_target.func): if type(default) == Depend: self.checkDependencies(default)
async def executor(self, executor_protocol: ExecutorProtocol, event_context, extra_parameter={}, lru_cache_sets=None ): lru_cache_sets = lru_cache_sets or {} executor_protocol: ExecutorProtocol for depend in executor_protocol.dependencies: if not inspect.isclass(depend.func): depend_func = depend.func elif hasattr(depend.func, "__call__"): depend_func = depend.func.__call__ else: raise TypeError("must be callable.") if depend_func in lru_cache_sets and depend.cache: depend_func = lru_cache_sets[depend_func] else: if depend.cache: original = depend_func if inspect.iscoroutinefunction(depend_func): depend_func = alru_cache(depend_func) else: depend_func = lru_cache(depend_func) lru_cache_sets[original] = depend_func result = await self.executor_with_middlewares( depend_func, depend.middlewares, event_context, lru_cache_sets ) if result is TRACEBACKED: return TRACEBACKED ParamSignatures = argument_signature(executor_protocol.callable) PlaceAnnotation = self.get_annotations_mapping() CallParams = {} for name, annotation, default in ParamSignatures: if default: if isinstance(default, Depend): if not inspect.isclass(default.func): depend_func = default.func elif hasattr(default.func, "__call__"): depend_func = default.func.__call__ else: raise TypeError("must be callable.") if depend_func in lru_cache_sets and default.cache: depend_func = lru_cache_sets[depend_func] else: if default.cache: original = depend_func if inspect.iscoroutinefunction(depend_func): depend_func = alru_cache(depend_func) else: depend_func = lru_cache(depend_func) lru_cache_sets[original] = depend_func CallParams[name] = await self.executor_with_middlewares( depend_func, default.middlewares, event_context, lru_cache_sets ) continue else: raise RuntimeError("checked a unexpected default value.") else: if annotation in PlaceAnnotation: CallParams[name] = PlaceAnnotation[annotation](event_context) continue else: if name not in extra_parameter: raise RuntimeError(f"checked a unexpected annotation: {annotation}") try: async with AsyncExitStack() as stack: sorted_middlewares = self.sort_middlewares(executor_protocol.middlewares) for async_middleware in sorted_middlewares['async']: await stack.enter_async_context(async_middleware) for normal_middleware in sorted_middlewares['normal']: stack.enter_context(normal_middleware) return await self.run_func(executor_protocol.callable, **CallParams, **extra_parameter) except exceptions.Cancelled: return TRACEBACKED except Exception as e: await self.put_exception(event_context, e) return TRACEBACKED