From ecbe465232472a4a43873d6586901e8411be663c Mon Sep 17 00:00:00 2001 From: yanyongyu Date: Sun, 27 Sep 2020 13:32:36 +0800 Subject: [PATCH] :alembic: add matcher group #11 --- nonebot/matcher.py | 169 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) diff --git a/nonebot/matcher.py b/nonebot/matcher.py index fcd70832..76465b0b 100644 --- a/nonebot/matcher.py +++ b/nonebot/matcher.py @@ -278,3 +278,172 @@ class Matcher(metaclass=MatcherMeta): logger.info(f"Matcher {self} running complete") current_bot.reset(b_t) current_event.reset(e_t) + + +class MatcherGroup: + + def __init__(self, + type_: str = "", + rule: Rule = Rule(), + permission: Permission = Permission(), + handlers: Optional[list] = None, + temp: bool = False, + priority: int = 1, + block: bool = False, + *, + module: Optional[str] = None, + default_state: Optional[dict] = None, + expire_time: Optional[datetime] = None): + self.matchers: List[Type[Matcher]] = [] + + self.type = type_ + self.rule = rule + self.permission = permission + self.handlers = handlers + self.temp = temp + self.priority = priority + self.block = block + self.module = module + self.default_state = default_state + self.expire_time = expire_time + + def __repr__(self) -> str: + return ( + f"") + + def __str__(self) -> str: + return self.__repr__() + + def new(self, + type_: str = "", + rule: Rule = Rule(), + permission: Permission = Permission(), + handlers: Optional[list] = None, + temp: bool = False, + priority: int = 1, + block: bool = False, + *, + module: Optional[str] = None, + default_state: Optional[dict] = None, + expire_time: Optional[datetime] = None) -> Type[Matcher]: + matcher = Matcher.new(type_=type_ or self.type, + rule=self.rule & rule, + permission=permission or self.permission, + handlers=handlers or self.handlers, + temp=temp or self.temp, + priority=priority or self.priority, + block=block or self.block, + module=module or self.module, + default_state=default_state or self.default_state, + expire_time=expire_time or self.expire_time) + self.matchers.append(matcher) + return matcher + + def args_parser(self, func: ArgsParser) -> ArgsParser: + for matcher in self.matchers: + matcher.args_parser(func) + return func + + def handle(self) -> Callable[[Handler], Handler]: + """直接处理消息事件""" + + def _decorator(func: Handler) -> Handler: + self.handlers.append(func) + return func + + return _decorator + + def receive(self) -> Callable[[Handler], Handler]: + """接收一条新消息并处理""" + + async def _receive(bot: Bot, event: Event, state: dict) -> NoReturn: + raise PausedException + + if self.handlers: + # 已有前置handlers则接受一条新的消息,否则视为接收初始消息 + self.handlers.append(_receive) + + def _decorator(func: Handler) -> Handler: + if not self.handlers or self.handlers[-1] is not func: + self.handlers.append(func) + + return func + + return _decorator + + def got( + self, + key: str, + prompt: Optional[str] = None, + args_parser: Optional[ArgsParser] = None + ) -> Callable[[Handler], Handler]: + + async def _key_getter(bot: Bot, event: Event, state: dict): + state["_current_key"] = key + if key not in state: + if prompt: + await bot.send(event=event, message=prompt) + raise PausedException + else: + state["_skip_key"] = True + + async def _key_parser(bot: Bot, event: Event, state: dict): + if key in state and state.get("_skip_key"): + del state["_skip_key"] + return + parser = args_parser or self._default_parser + if parser: + await parser(bot, event, state) + else: + state[state["_current_key"]] = str(event.message) + + self.handlers.append(_key_getter) + self.handlers.append(_key_parser) + + def _decorator(func: Handler) -> Handler: + if not hasattr(self.handlers[-1], "__wrapped__"): + parser = self.handlers.pop() + + @wraps(func) + async def wrapper(bot: Bot, event: Event, state: dict): + await parser(bot, event, state) + await func(bot, event, state) + if "_current_key" in state: + del state["_current_key"] + + self.handlers.append(wrapper) + + return func + + return _decorator + + async def finish( + self, + prompt: Optional[Union[str, Message, + MessageSegment]] = None) -> NoReturn: + bot: Bot = current_bot.get() + event: Event = current_event.get() + if prompt: + await bot.send(event=event, message=prompt) + raise FinishedException + + async def pause( + self, + prompt: Optional[Union[str, Message, + MessageSegment]] = None) -> NoReturn: + bot: Bot = current_bot.get() + event: Event = current_event.get() + if prompt: + await bot.send(event=event, message=prompt) + raise PausedException + + async def reject( + self, + prompt: Optional[Union[str, Message, + MessageSegment]] = None) -> NoReturn: + bot: Bot = current_bot.get() + event: Event = current_event.get() + if prompt: + await bot.send(event=event, message=prompt) + raise RejectedException