diff --git a/nonebot/adapters/_base.py b/nonebot/adapters/_base.py index 264f69c7..f4290c36 100644 --- a/nonebot/adapters/_base.py +++ b/nonebot/adapters/_base.py @@ -17,7 +17,7 @@ from pydantic import BaseModel from nonebot.log import logger from nonebot.utils import DataclassEncoder -from nonebot.typing import T_CallingAPIHook +from nonebot.typing import T_CallingAPIHook, T_CalledAPIHook if TYPE_CHECKING: from nonebot.config import Config @@ -39,11 +39,16 @@ class Bot(abc.ABC): """Driver 对象""" config: "Config" """Config 配置对象""" - _call_api_hook: Set[T_CallingAPIHook] = set() + _calling_api_hook: Set[T_CallingAPIHook] = set() """ :类型: ``Set[T_CallingAPIHook]`` :说明: call_api 时执行的函数 """ + _called_api_hook: Set[T_CalledAPIHook] = set() + """ + :类型: ``Set[T_CalledAPIHook]`` + :说明: call_api 后执行的函数 + """ @abc.abstractmethod def __init__(self, @@ -156,7 +161,7 @@ class Bot(abc.ABC): await bot.call_api("send_msg", message="hello world") await bot.send_msg(message="hello world") """ - coros = list(map(lambda x: x(self, api, data), self._call_api_hook)) + coros = list(map(lambda x: x(self, api, data), self._calling_api_hook)) if coros: try: logger.debug("Running CallingAPI hooks...") @@ -166,13 +171,33 @@ class Bot(abc.ABC): "Error when running CallingAPI hook. " "Running cancelled!") - if "self_id" in data: - self_id = data.pop("self_id") - if self_id: - bot = self.driver.bots[str(self_id)] - return await bot._call_api(api, **data) + exception = None + result = None - return await self._call_api(api, **data) + try: + if "self_id" in data and data["self_id"]: + bot = self.driver.bots[str(data["self_id"])] + result = await bot._call_api(api, **data) + else: + result = await self._call_api(api, **data) + except Exception as e: + exception = e + + coros = list( + map(lambda x: x(self, exception, api, data, result), + self._called_api_hook)) + if coros: + try: + logger.debug("Running CalledAPI hooks...") + await asyncio.gather(*coros) + except Exception as e: + logger.opt(colors=True, exception=e).error( + "Error when running CalledAPI hook. " + "Running cancelled!") + + if exception: + raise exception + return result @abc.abstractmethod async def send(self, event: "Event", message: Union[str, "Message", @@ -193,7 +218,12 @@ class Bot(abc.ABC): @classmethod def on_calling_api(cls, func: T_CallingAPIHook) -> T_CallingAPIHook: - cls._call_api_hook.add(func) + cls._calling_api_hook.add(func) + return func + + @classmethod + def on_called_api(cls, func: T_CalledAPIHook) -> T_CalledAPIHook: + cls._called_api_hook.add(func) return func diff --git a/nonebot/typing.py b/nonebot/typing.py index a9dccc35..d73865bd 100644 --- a/nonebot/typing.py +++ b/nonebot/typing.py @@ -72,6 +72,22 @@ T_WebSocketDisconnectionHook = Callable[["Bot"], Awaitable[None]] WebSocket 连接断开时执行的函数 """ T_CallingAPIHook = Callable[["Bot", str, Dict[str, Any]], Awaitable[None]] +""" +:类型: ``Callable[[Bot, str, Dict[str, Any]], Awaitable[None]]`` + +:说明: + + ``bot.call_api`` 时执行的函数 +""" +T_CalledAPIHook = Callable[ + ["Bot", Optional[Exception], str, Dict[str, Any], Any], Awaitable[None]] +""" +:类型: ``Callable[[Bot, Optional[Exception], str, Dict[str, Any], Any], Awaitable[None]]`` + +:说明: + + ``bot.call_api`` 后执行的函数,参数分别为 bot, exception, api, data, result +""" T_EventPreProcessor = Callable[["Bot", "Event", T_State], Awaitable[None]] """ diff --git a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/bot.py b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/bot.py index bea0bcc3..15269b37 100644 --- a/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/bot.py +++ b/packages/nonebot-adapter-cqhttp/nonebot/adapters/cqhttp/bot.py @@ -58,6 +58,7 @@ async def _check_reply(bot: "Bot", event: "Event"): )) except Exception as e: log("WARNING", f"Error when getting message reply info: {repr(e)}", e) + return # ensure string comparation if str(event.reply.sender.user_id) == str(event.self_id): event.to_me = True