Esempio n. 1
0
    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
Esempio n. 2
0
    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)
Esempio n. 3
0
    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)
Esempio n. 4
0
 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()
Esempio n. 5
0
    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
Esempio n. 6
0
    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)
Esempio n. 7
0
    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)
Esempio n. 8
0
    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)
Esempio n. 9
0
    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