support for mock api result (resolve #605)

This commit is contained in:
yanyongyu 2021-11-28 02:29:23 +08:00
parent 37f55652d9
commit a6112fdf64
3 changed files with 85 additions and 12 deletions

View File

@ -43,11 +43,22 @@ sidebarDepth: 0
## _exception_ `IgnoredException`
## _exception_ `ProcessException`
基类:`nonebot.exception.NoneBotException`
* **说明**
事件处理过程中发生的异常基类。
## _exception_ `IgnoredException`
基类:`nonebot.exception.ProcessException`
* **说明**
指示 NoneBot 应该忽略该事件。可由 PreProcessor 抛出。
@ -61,9 +72,27 @@ sidebarDepth: 0
## _exception_ `MockApiException`
基类:`nonebot.exception.ProcessException`
* **说明**
指示 NoneBot 阻止本次 API 调用或修改本次调用返回值,并返回自定义内容。可由 api hook 抛出。
* **参数**
* `result`: 返回的内容
## _exception_ `StopPropagation`
基类:`nonebot.exception.NoneBotException`
基类:`nonebot.exception.ProcessException`
* **说明**

View File

@ -6,6 +6,7 @@ from typing import TYPE_CHECKING, Any, Set, Tuple, Union, Optional
from nonebot.log import logger
from nonebot.config import Config
from nonebot.exception import MockApiException
from nonebot.typing import T_CalledAPIHook, T_CallingAPIHook
from nonebot.drivers import Driver, HTTPResponse, HTTPConnection
@ -137,24 +138,33 @@ class Bot(abc.ABC):
await bot.call_api("send_msg", message="hello world")
await bot.send_msg(message="hello world")
"""
result: Any = None
skip_calling_api: bool = False
exception: Optional[Exception] = None
coros = list(map(lambda x: x(self, api, data), self._calling_api_hook))
if coros:
try:
logger.debug("Running CallingAPI hooks...")
await asyncio.gather(*coros)
except MockApiException as e:
skip_calling_api = True
result = e.result
logger.debug(
f"Calling API {api} is cancelled. Return {result} instead."
)
except Exception as e:
logger.opt(colors=True, exception=e).error(
"<r><bg #f8bbd0>Error when running CallingAPI hook. "
"Running cancelled!</bg #f8bbd0></r>"
)
exception = None
result = None
try:
result = await self._call_api(api, **data)
except Exception as e:
exception = e
if not skip_calling_api:
try:
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)
@ -163,6 +173,11 @@ class Bot(abc.ABC):
try:
logger.debug("Running CalledAPI hooks...")
await asyncio.gather(*coros)
except MockApiException as e:
result = e.result
logger.debug(
f"Calling API {api} result is mocked. Return {result} instead."
)
except Exception as e:
logger.opt(colors=True, exception=e).error(
"<r><bg #f8bbd0>Error when running CalledAPI hook. "

View File

@ -6,7 +6,7 @@
这些异常并非所有需要用户处理 NoneBot 内部运行时被捕获并进行对应操作
"""
from typing import Optional
from typing import Any, Optional
class NoneBotException(Exception):
@ -42,7 +42,15 @@ class ParserExit(NoneBotException):
# Processor Exception
class IgnoredException(NoneBotException):
class ProcessException(NoneBotException):
"""
:说明:
事件处理过程中发生的异常基类
"""
class IgnoredException(ProcessException):
"""
:说明:
@ -63,7 +71,28 @@ class IgnoredException(NoneBotException):
return self.__repr__()
class StopPropagation(NoneBotException):
class MockApiException(ProcessException):
"""
:说明:
指示 NoneBot 阻止本次 API 调用或修改本次调用返回值并返回自定义内容可由 api hook 抛出
:参数:
* ``result``: 返回的内容
"""
def __init__(self, result: Any):
self.result = result
def __repr__(self):
return f"<ApiCancelledException, result={self.result}>"
def __str__(self):
return self.__repr__()
class StopPropagation(ProcessException):
"""
:说明: