async def _run_matcher( Matcher: Type[Matcher], bot: "Bot", event: "Event", state: T_State, stack: Optional[AsyncExitStack] = None, dependency_cache: Optional[T_DependencyCache] = None, ) -> None: logger.info(f"Event will be handled by {Matcher}") matcher = Matcher() coros = list( map( lambda x: run_coro_with_catch( x( matcher=matcher, bot=bot, event=event, state=state, stack=stack, dependency_cache=dependency_cache, ), (SkippedException, ), ), _run_preprocessors, )) if coros: try: await asyncio.gather(*coros) except IgnoredException: logger.opt(colors=True).info( f"Matcher {matcher} running is <b>cancelled</b>") return except Exception as e: logger.opt(colors=True, exception=e).error( "<r><bg #f8bbd0>Error when running RunPreProcessors. " "Running cancelled!</bg #f8bbd0></r>") return exception = None try: logger.debug(f"Running matcher {matcher}") await matcher.run(bot, event, state, stack, dependency_cache) except Exception as e: logger.opt(colors=True, exception=e).error( f"<r><bg #f8bbd0>Running matcher {matcher} failed.</bg #f8bbd0></r>" ) exception = e coros = list( map( lambda x: run_coro_with_catch( x( matcher=matcher, exception=exception, bot=bot, event=event, state=state, stack=stack, dependency_cache=dependency_cache, ), (SkippedException, ), ), _run_postprocessors, )) if coros: try: await asyncio.gather(*coros) except Exception as e: logger.opt(colors=True, exception=e).error( "<r><bg #f8bbd0>Error when running RunPostProcessors</bg #f8bbd0></r>" ) if matcher.block: raise StopPropagation return
async def bind_handle_first_receive(matcher: Matcher, arg: Message = CommandArg()): if arg.extract_plain_text(): matcher.set_arg("cookie", arg)
from nonebot.matcher import Matcher test_type_updater = Matcher.new(type_="test") test_custom_updater = Matcher.new(type_="test") @test_custom_updater.type_updater async def _() -> str: return "custom"
class CQHttp: message_matcher = Matcher.new("message") message_handlers = [] notice_matcher = Matcher.new("notice") notice_handlers = [] request_matcher = Matcher.new("request") request_handlers = [] metaevent_matcher = Matcher.new("meta_event") metaevent_handlers = [] _loop: asyncio.AbstractEventLoop @staticmethod async def _run_handlers(handlers: List[_NoneBotHandler], bot: CQBot, event: NoneBotEvent): asyncio.ensure_future( asyncio.gather( *map(lambda f: f(bot, event), handlers), # type: ignore return_exceptions=True)) def __init__(self): get_driver().on_startup( lambda: setattr(self, "_loop", asyncio.get_running_loop())) @self.message_matcher.handle() async def handle_message(bot: CQBot, event: NoneBotEvent): return await self._run_handlers(self.message_handlers, bot, event) @self.notice_matcher.handle() async def handle_notice(bot: CQBot, event: NoneBotEvent): return await self._run_handlers(self.notice_handlers, bot, event) @self.request_matcher.handle() async def handle_request(bot: CQBot, event: NoneBotEvent): return await self._run_handlers(self.request_handlers, bot, event) @self.metaevent_matcher.handle() async def handle_metaevent(bot: CQBot, event: NoneBotEvent): return await self._run_handlers(self.metaevent_handlers, bot, event) @property def asgi(self): return get_asgi() @property def server_app(self): return get_app() @property def logger(self): from nonetrip.log import logger return logger @property def loop(self) -> asyncio.AbstractEventLoop: assert isinstance(self._loop, asyncio.AbstractEventLoop) return self._loop @property def bot(self) -> CQBot: for bot in get_bots().values(): if not isinstance(bot, CQBot): continue return bot raise ApiNotAvailable("nonetrip") def _handler_factory( self, function: Callable[[Event], Coroutine], post_type: Optional[str] = None, ) -> _NoneBotHandler: async def handler(bot: CQBot, event: NoneBotEvent): if post_type is not None and event.post_type != post_type: return nonebot_event = Event.from_payload(event) if nonebot_event is None: return return await function(nonebot_event) return handler @singledispatchmethod def on_message(self, arg: _AsyncCallable_T) -> _AsyncCallable_T: self.message_matcher.append_handler(self._handler_factory(arg)) return arg @on_message.register # type:ignore def _on_specified_message(self, arg: str) -> _HandlerDecorator: def wrapper(function: _AsyncCallable_T) -> _AsyncCallable_T: self.message_matcher.append_handler( self._handler_factory(function, arg)) return function return wrapper @singledispatchmethod def on_notice(self, arg): self.notice_matcher.append_handler(self._handler_factory(arg)) return arg @on_notice.register # type: ignore def _on_specified_notice(self, arg: str) -> _HandlerDecorator: def wrapper(function: _AsyncCallable_T) -> _AsyncCallable_T: self.notice_matcher.append_handler( self._handler_factory(function, arg)) return function return wrapper @singledispatchmethod def on_request(self, arg: _AsyncCallable_T) -> _AsyncCallable_T: self.request_matcher.append_handler(self._handler_factory(arg)) return arg @on_request.register # type: ignore def _on_specified_request(self, arg: str) -> _HandlerDecorator: def wrapper(function: _AsyncCallable_T) -> _AsyncCallable_T: self.request_matcher.append_handler( self._handler_factory(function, arg)) return function return wrapper @singledispatchmethod def on_metaevent(self, arg: _AsyncCallable_T) -> _AsyncCallable_T: self.metaevent_matcher.append_handler(self._handler_factory(arg)) return arg @on_metaevent.register # type:ignore def _on_specified_metaevent(self, arg: str) -> _HandlerDecorator: def wrapper(function: _AsyncCallable_T) -> _AsyncCallable_T: self.metaevent_matcher.append_handler( self._handler_factory(function, arg)) return function return wrapper on_meta_event = on_metaevent async def send(self, event: Event, message: "Message_T", **kwargs): bot = get_bots().get(str(event.self_id)) assert (bot is not None) and isinstance(bot, CQBot) message = message if isinstance(message, Message) else Message(message) return await bot.send(NoneBotEvent(**event), NoneBotMessage(message), **kwargs) async def call_action(self, action: str, **kwargs): return await self.bot.call_api(action, **kwargs) def __getattr__(self, key: str) -> Callable[..., Coroutine]: return partial(self.call_action, key)