async def catch(self, interface: DispatcherInterface): # 因为 Dispatcher 的特性, 要用 yield (自动清理 self.parsed_items) if self.parsed_items is None: message_chain = (await interface.execute_with( "__kanata_messagechain_origin__", MessageChain, None)).exclude(Source, Quote, Xml, Json, App, Poke) self.parsed_items = self.allocation( self.detect_and_mapping(self.signature_list, message_chain) or {}) if self.stop_exec_if_fail and self.parsed_items is None: self.parsed_items = None self.will_clean = False raise ExecutionStop() if self.parsed_items: result = self.parsed_items.get(interface.name) if result is None: if interface.default: # 不是 None, 生成 None. yield Force(None) else: # 无默认值 None, 也无结果, 应转交控制权予下级(实际上这里必定触发 RequirementCrashed, 只不过我不想写 raise 了.) return else: yield Force(result) self.parsed_items = None
async def catch(self, interface: DispatcherInterface): if self.target_name and self.target_name != interface.name: return elif self.target_annotation and self.target_annotation != interface.annotation: return elif not self.target_name and not self.target_annotation: return result = await interface.broadcast.Executor( target=self.custom_function, event=interface.event, post_exception_event=True, use_inline_generator=True ) result_is_asyncgen = [inspect.isasyncgen, isasyncgen][isinstance(result, Hashable)](result) result_is_generator = [inspect.isgenerator, isgenerator][isinstance(result, Hashable)](result) if result_is_asyncgen or (result_is_generator and not iscoroutinefunction(self.custom_function)): if result_is_generator(result): for i in result: yield Force(i) elif result_is_asyncgen(result): async for i in result: yield Force(i) else : yield Force(result)
async def catch(self, interface: DispatcherInterface): # 因为 Dispatcher 的特性, 要用 yield (自动清理 self.parsed_items) token = None if self.parsed_items.get(None) is None: message_chain = (await interface.lookup_param( "__kanata_messagechain__", MessageChain, None )).exclude(Source, Quote, Xml, Json, App, Poke) mapping_result = self.detect_and_mapping( self.signature_list, message_chain ) if mapping_result is not None: token = self.parsed_items.set(self.allocation(mapping_result)) else: if self.stop_exec_if_fail: raise ExecutionStop() random_id = random.random() current_item = self.parsed_items.get() if current_item is not None: result = current_item.get(interface.name, random_id) yield Force(result) if result is not random_id else None else: if self.stop_exec_if_fail: raise ExecutionStop() if token is not None: self.parsed_items.reset(token)
async def catch(self, interface: DispatcherInterface): if not self.content_token: return random_id = random.random() current_item = self.parsed_items.get() if current_item is not None: result = current_item.get(interface.name, random_id) return Force(result) if result is not random_id else None else: if self.stop_exec_if_fail: raise ExecutionStop()
async def catch(self, interface: DispatcherInterface): if interface.name == "__literature_messagechain__": return result = interface.execution_contexts[-1].literature_detect_result if result: match_result, variargs = result if interface.default == "__literature_variables__": return variargs arg_fetch_result = match_result.get(interface.name) if arg_fetch_result: match_value, raw_argument = arg_fetch_result if isinstance(raw_argument, SwitchParameter): return Force(match_value) elif interface.annotation is ParamPattern: return raw_argument elif match_value is not None: return match_value
async def generator_factory(self): interface: DispatcherInterface = (yield) current_status: StatusCodeEnum = StatusCodeEnum.DISPATCHING # init stat message_chain: MessageChain = (await interface.lookup_param( "__kanata_messagechain__", MessageChain, None)).exclude(Source) if set([i.__class__ for i in message_chain.__root__ ]).intersection(BLOCKING_ELEMENTS): raise ExecutionStop() if self.allow_quote and message_chain.has(Quote): # 自动忽略自 Quote 后第一个 At # 0: Quote, 1: At, 2: Plain(一个空格, 可能会在以后的 mirai 版本后被其处理, 这里先自动处理这个了.) message_chain = message_chain[(3, None):] if self.skip_one_at_in_quote and message_chain.__root__: if message_chain.__root__[0].__class__ is At: message_chain = message_chain[(1, 1):] mapping_result = self.detect_and_mapping(self.signature_list, message_chain) if mapping_result is not None: parsed_items = self.allocation(mapping_result) else: if self.stop_exec_if_fail: raise ExecutionStop() yield while current_status is StatusCodeEnum.DISPATCHING: result = None if interface.name != "__kanata_messagechain__": random_id = random.random() if parsed_items is not None: item = parsed_items.get(interface.name, random_id) result = Force(item) if item is not random_id else None else: if self.stop_exec_if_fail: raise ExecutionStop() current_status, external = yield (ResponseCodeEnum.VALUE, result)
async def catch(self, interface: DispatcherInterface): # 因为 Dispatcher 的特性, 要用 yield (自动清理 self.parsed_items) token = None if self.parsed_items.get(None) is None: message_chain: MessageChain = (await interface.lookup_param( "__kanata_messagechain__", MessageChain, None )).exclude(Source) if set([i.__class__ for i in message_chain.__root__]).intersection(BLOCKING_ELEMENTS): raise ExecutionStop() if self.allow_quote and message_chain.has(Quote): # 自动忽略自 Quote 后第一个 At # 0: Quote, 1: At, 2: Plain(一个空格, 可能会在以后的 mirai 版本后被其处理, 这里先自动处理这个了.) message_chain = message_chain[(3, None):] if self.skip_one_at_in_quote and message_chain.__root__: if message_chain.__root__[0].__class__ is At: message_chain = message_chain[(1, 1):] # 利用 MessageIndex 可以非常快捷的实现特性. mapping_result = self.detect_and_mapping( self.signature_list, message_chain ) if mapping_result is not None: token = self.parsed_items.set(self.allocation(mapping_result)) else: if self.stop_exec_if_fail: raise ExecutionStop() random_id = random.random() current_item = self.parsed_items.get() if current_item is not None: result = current_item.get(interface.name, random_id) yield Force(result) if result is not random_id else None else: if self.stop_exec_if_fail: raise ExecutionStop() if token is not None: self.parsed_items.reset(token)
async def catch(self, interface: DispatcherInterface): # 因为 Dispatcher 的特性, 要用 yield (自动清理 self.parsed_items) token = None if self.parsed_items.get(None) is None: message_chain = (await interface.execute_with( "__kanata_messagechain_origin__", MessageChain, None)).exclude(Source, Quote, Xml, Json, App, Poke) mapping_result = self.detect_and_mapping(self.signature_list, message_chain) if mapping_result is not None: token = self.parsed_items.set(self.allocation(mapping_result)) else: if self.stop_exec_if_fail: raise ExecutionStop() _i = random.random() result = self.parsed_items.get({}).get(interface.name, _i) if result is _i: yield # 跳过.(另: Executor 应加入对 default 的不可预测行为反制措施.) else: yield Force(result) if token is not None: self.parsed_items.reset(token)
def detect_index(self, target_chain: MessageChain): target_chain = target_chain.asMerged() detect_result: Dict[str, List[Tuple[MessageIndex, MessageIndex]]] = { "_": [] # 相当于 *args. } chain_frames: List[MessageChain] = target_chain.split(self.delimiter, raw_string=True) # 前缀匹配 if len(self.prefixs) > len(chain_frames): return for index in range(len(self.prefixs)): current_prefix = self.prefixs[index] current_frame = chain_frames[index] if (not current_frame.__root__ or type(current_frame.__root__[0]) is not Plain): return if current_frame.__root__[0].text != current_prefix: return chain_frames = chain_frames[len(self.prefixs):] # 清除无关数据, 开始执行. collections: List[Element] = detect_result["_"] detecting_param = None local_iter = MultiUsageGenerator(enumerate(chain_frames)) # print(list(local_iter)) for iter_item in local_iter: print(92, iter_item) index, current_frame = iter_item current_frame: MessageChain if not current_frame.__root__: collections.append(current_frame) continue if detecting_param and isinstance( self.param_settings[detecting_param], BoxParameter): detect_result[detecting_param] = current_frame detecting_param = None continue splited = current_frame.split("=", raw_string=True) origin_data = self.param_settings_index.get(splited[0].asDisplay()) if not origin_data: if not detecting_param: if current_frame.startswith( '"'): # TODO: 我现在还需要一个更加合理的引号出现判断. # debug("ocur", index, chain_frames, current_frame) afters_root = MessageChain.create( sum( [[*i.__root__, Plain(self.delimiter)] for i in chain_frames[max(0, index - 1):]], [], )[:-1]).asMerged() print("aftersRoot", index, afters_root) break_flag_root = False param_content_root = [] for elem in afters_root.subchain( slice((0, 1), None, None), ignore_text_index=True): print(elem) if break_flag_root: break_flag_root = False break if isinstance(elem, Plain): continue_flag = False for text_index, text_i in enumerate(elem.text): if continue_flag: continue_flag = False continue if text_i == "\\": continue_flag = True if text_i == '"': param_content_root.append( Plain(elem.text[:text_index])) break_flag_root = True break else: # 没找到 param_content_root.append(elem) break else: param_content_root.append(elem) break else: if not break_flag_root: raise ValueError("no closing quotes") param_content_chain_root = MessageChain.create( param_content_root) local_iter.continue_count += len( param_content_chain_root.split(self.delimiter, raw_string=True)) collections.append(param_content_chain_root) else: collections.append(current_frame) continue param_name, setting = origin_data detecting_param = param_name if param_name in detect_result: continue # 用户重复输入了参数 if isinstance(setting, SwitchParameter): # 这里是已经被 catch 到了. if setting.auto_reverse: detect_result[param_name] = not setting.default else: detect_result[param_name] = True elif isinstance(setting, BoxParameter): afters = MessageChain.create( sum( ([i.__root__ for i in splited[1:]] + [[Plain(self.delimiter)]] if len(splited) > 1 else []) + [[*i.__root__, Plain(self.delimiter)] for i in chain_frames[index + 1:]], [], )[:-1]).asMerged() break_flag = False if afters.startswith('"'): param_content = [] for elem in afters.subchain(slice((0, 1), None, None), ignore_text_index=True): if break_flag: break_flag = False break if isinstance(elem, Plain): continue_flag = False for text_index, text_i in enumerate(elem.text): if continue_flag: continue_flag = False continue if text_i == "\\": continue_flag = True if text_i == '"': param_content.append( Plain(elem.text[:text_index])) break_flag = True break else: # 没找到 param_content.append(elem) else: param_content.append(elem) else: if not break_flag: raise ValueError("no closing quotes") param_content_chain = MessageChain.create(param_content) print( param_content, chain_frames[len( param_content_chain. split(self.delimiter, raw_string=True)) + 1:], ) local_iter.continue_count += (len( param_content_chain.split(self.delimiter, raw_string=True)) - 1) detect_result[param_name] = [ MessageChain.create(param_content) ] else: detecting_param = param_name if len(splited) > 1 and not break_flag: local_iter.insert_items.extend([ (index + l_index, value) for l_index, value in enumerate(splited[1:], 1) ]) detecting_param = None else: if detecting_param and detecting_param not in detect_result: if self.param_settings[detecting_param].default is None: raise ValueError("require for " + detecting_param) # 后处理 for k, v in self.param_settings.items(): if isinstance(v, SwitchParameter) and k not in detect_result: detect_result[k] = v.default elif isinstance(v, BoxParameter) and k not in detect_result: detect_result[k] = Force(None) return detect_result