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