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` 基类:`nonebot.exception.NoneBotException`
* **说明**
事件处理过程中发生的异常基类。
## _exception_ `IgnoredException`
基类:`nonebot.exception.ProcessException`
* **说明** * **说明**
指示 NoneBot 应该忽略该事件。可由 PreProcessor 抛出。 指示 NoneBot 应该忽略该事件。可由 PreProcessor 抛出。
@ -61,9 +72,27 @@ sidebarDepth: 0
## _exception_ `MockApiException`
基类:`nonebot.exception.ProcessException`
* **说明**
指示 NoneBot 阻止本次 API 调用或修改本次调用返回值,并返回自定义内容。可由 api hook 抛出。
* **参数**
* `result`: 返回的内容
## _exception_ `StopPropagation` ## _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.log import logger
from nonebot.config import Config from nonebot.config import Config
from nonebot.exception import MockApiException
from nonebot.typing import T_CalledAPIHook, T_CallingAPIHook from nonebot.typing import T_CalledAPIHook, T_CallingAPIHook
from nonebot.drivers import Driver, HTTPResponse, HTTPConnection 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.call_api("send_msg", message="hello world")
await bot.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)) coros = list(map(lambda x: x(self, api, data), self._calling_api_hook))
if coros: if coros:
try: try:
logger.debug("Running CallingAPI hooks...") logger.debug("Running CallingAPI hooks...")
await asyncio.gather(*coros) 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: except Exception as e:
logger.opt(colors=True, exception=e).error( logger.opt(colors=True, exception=e).error(
"<r><bg #f8bbd0>Error when running CallingAPI hook. " "<r><bg #f8bbd0>Error when running CallingAPI hook. "
"Running cancelled!</bg #f8bbd0></r>" "Running cancelled!</bg #f8bbd0></r>"
) )
exception = None if not skip_calling_api:
result = None try:
result = await self._call_api(api, **data)
try: except Exception as e:
result = await self._call_api(api, **data) exception = e
except Exception as e:
exception = e
coros = list( coros = list(
map(lambda x: x(self, exception, api, data, result), self._called_api_hook) map(lambda x: x(self, exception, api, data, result), self._called_api_hook)
@ -163,6 +173,11 @@ class Bot(abc.ABC):
try: try:
logger.debug("Running CalledAPI hooks...") logger.debug("Running CalledAPI hooks...")
await asyncio.gather(*coros) 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: except Exception as e:
logger.opt(colors=True, exception=e).error( logger.opt(colors=True, exception=e).error(
"<r><bg #f8bbd0>Error when running CalledAPI hook. " "<r><bg #f8bbd0>Error when running CalledAPI hook. "

View File

@ -6,7 +6,7 @@
这些异常并非所有需要用户处理 NoneBot 内部运行时被捕获并进行对应操作 这些异常并非所有需要用户处理 NoneBot 内部运行时被捕获并进行对应操作
""" """
from typing import Optional from typing import Any, Optional
class NoneBotException(Exception): class NoneBotException(Exception):
@ -42,7 +42,15 @@ class ParserExit(NoneBotException):
# Processor Exception # Processor Exception
class IgnoredException(NoneBotException): class ProcessException(NoneBotException):
"""
:说明:
事件处理过程中发生的异常基类
"""
class IgnoredException(ProcessException):
""" """
:说明: :说明:
@ -63,7 +71,28 @@ class IgnoredException(NoneBotException):
return self.__repr__() 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):
""" """
:说明: :说明: