diff --git a/nonebot/command/__init__.py b/nonebot/command/__init__.py index 3fda70af..acea977e 100644 --- a/nonebot/command/__init__.py +++ b/nonebot/command/__init__.py @@ -3,8 +3,7 @@ import re import shlex from datetime import datetime from typing import ( - Tuple, Union, Callable, Iterable, Any, Optional, List, Dict, - Awaitable + Tuple, Union, Callable, Iterable, Any, Optional, List, Dict ) from nonebot import NoneBot, permission as perm @@ -68,19 +67,8 @@ class Command: if session.current_arg_filters is not None and \ session.current_key is not None: # argument-level filters are given, use them - arg = session.current_arg - for f in session.current_arg_filters: - try: - res = f(arg) - if isinstance(res, Awaitable): - res = await res - arg = res - except ValidateError as e: - # validation failed - session.pause(e.message) - - # passed all filters - session.state[session.current_key] = arg + await argfilter.run_arg_filters( + session, session.current_arg_filters) else: # fallback to command-level args_parser_func if self.args_parser_func: diff --git a/nonebot/command/argfilter/__init__.py b/nonebot/command/argfilter/__init__.py index 507f89ac..ae6e09cc 100644 --- a/nonebot/command/argfilter/__init__.py +++ b/nonebot/command/argfilter/__init__.py @@ -1,4 +1,9 @@ -from typing import Callable, Any, Awaitable, Union +from typing import Callable, Any, Awaitable, Union, List, TYPE_CHECKING + +from nonebot.helpers import render_expression + +if TYPE_CHECKING: + from nonebot.command import CommandSession ArgFilter_T = Callable[[Any], Union[Any, Awaitable[Any]]] @@ -6,3 +11,25 @@ ArgFilter_T = Callable[[Any], Union[Any, Awaitable[Any]]] class ValidateError(ValueError): def __init__(self, message=None): self.message = message + + +async def run_arg_filters(session: 'CommandSession', + arg_filters: List[ArgFilter_T]) -> None: + arg = session.current_arg + for f in arg_filters: + try: + res = f(arg) + if isinstance(res, Awaitable): + res = await res + arg = res + except ValidateError as e: + # validation failed + failure_message = e.message + if failure_message is None: + failure_message = render_expression( + session.bot.config.DEFAULT_VALIDATION_FAILURE_EXPRESSION + ) + session.pause(failure_message) + + # passed all filters + session.state[session.current_key] = arg diff --git a/nonebot/default_config.py b/nonebot/default_config.py index 3c30901a..19cb9432 100644 --- a/nonebot/default_config.py +++ b/nonebot/default_config.py @@ -34,6 +34,7 @@ SESSION_EXPIRE_TIMEOUT: Optional[timedelta] = timedelta(minutes=5) SESSION_RUN_TIMEOUT: Optional[timedelta] = None SESSION_RUNNING_EXPRESSION: Expression_T = '您有命令正在执行,请稍后再试' SHORT_MESSAGE_MAX_LENGTH: int = 50 +DEFAULT_VALIDATION_FAILURE_EXPRESSION: Expression_T = '您的输入不符合要求,请重新输入' APSCHEDULER_CONFIG: Dict[str, Any] = { 'apscheduler.timezone': 'Asia/Shanghai'