From 51a2ca0841dad8b28a2ac60b68459eac685b20e2 Mon Sep 17 00:00:00 2001 From: yanyongyu Date: Mon, 27 Apr 2020 11:38:15 +0800 Subject: [PATCH] fix remove command and update api docs --- docs/api.md | 236 +++++++++++++++++++++++++++++++----- nonebot/command/__init__.py | 5 + 2 files changed, 208 insertions(+), 33 deletions(-) diff --git a/docs/api.md b/docs/api.md index 2cb81512..5fd733d6 100644 --- a/docs/api.md +++ b/docs/api.md @@ -781,8 +781,6 @@ sidebar: auto ### _class_ `PluginManager` - - 插件管理器:用于管理插件的加载以及插件中命令、自然语言处理器、事件处理器的开关。 #### `cmd_manager` @@ -1212,6 +1210,33 @@ sidebar: auto 一个简单的复读命令。 +### _decorator_ _command_func._`args_parser` + +- **说明:** + + 将函数装饰为命令层面的参数解析器,将在命令实际处理函数之前被运行。 + + 如果已经在 `on_command` 装饰器中使用了 `shell_like=True`,则无需手动使用编写参数解析器。 + + 如果使用 `CommandSession#get()` 方法获取参数,并且传入了 `arg_filters`(相当于单个参数层面的参数解析器),则不会再运行此装饰器注册的命令层面的参数解析器;相反,如果没有传入 `arg_filters`,则会运行。 + +- **要求:** + + 对被装饰函数的要求同 `on_command` 装饰器。 + +- **用法:** + + ```python + @my_cmd.args_parser + async def _(session: CommandSession): + stripped_text = session.current_arg_text.strip() + if not session.current_key and stripped_text: + session.current_key = 'initial_arg' + session.state[session.current_key] = stripped_text # 若使用 1.1.0 及以下版本,请使用 session.args + ``` + + 一个典型的命令参数解析器。 + ### _decorator_ `on_natural_language(keywords=None, *, permission=EVERYBODY, only_to_me=True, only_short_message=True, allow_empty_message=False)` - **说明:** @@ -1321,10 +1346,10 @@ sidebar: auto - **要求:** - 被装饰函数必须是一个 async 函数,且必须接收且仅接收两个位置参数,类型分别为 `NoneBot` 和 `aiocqhttp.Event`,即形如: + 被装饰函数必须是一个 async 函数,且必须接收且仅接收三个位置参数,类型分别为 `NoneBot` 、 `aiocqhttp.Event` 和 `nonebot.plugin.PluginManager`,即形如: ```python - async def func(bot: NoneBot, event: aiocqhttp.Event): + async def func(bot: NoneBot, event: aiocqhttp.Event, plugin_manager: PluginManager): pass ``` @@ -1332,8 +1357,11 @@ sidebar: auto ```python @message_preprocessor - async def _(bot: NoneBot, event: aiocqhttp.Event): - event['preprocessed'] = True + async def _(bot: NoneBot, event: aiocqhttp.Event, plugin_manager: PluginManager): + event["preprocessed"] = True + + # 关闭某个插件,仅对当前消息生效 + plugin_manager.switch_plugin("path.to.plugin", state=False) ``` 在所有消息处理之前,向消息事件对象中加入 `preprocessed` 字段。 @@ -1846,33 +1874,6 @@ sidebar: auto 一个简单的复读命令。 -### _decorator_ _command_func._`args_parser` - -- **说明:** - - 将函数装饰为命令层面的参数解析器,将在命令实际处理函数之前被运行。 - - 如果已经在 `on_command` 装饰器中使用了 `shell_like=True`,则无需手动使用编写参数解析器。 - - 如果使用 `CommandSession#get()` 方法获取参数,并且传入了 `arg_filters`(相当于单个参数层面的参数解析器),则不会再运行此装饰器注册的命令层面的参数解析器;相反,如果没有传入 `arg_filters`,则会运行。 - -- **要求:** - - 对被装饰函数的要求同 `on_command` 装饰器。 - -- **用法:** - - ```python - @my_cmd.args_parser - async def _(session: CommandSession): - stripped_text = session.current_arg_text.strip() - if not session.current_key and stripped_text: - session.current_key = 'initial_arg' - session.state[session.current_key] = stripped_text # 若使用 1.1.0 及以下版本,请使用 session.args - ``` - - 一个典型的命令参数解析器。 - ### _class_ `CommandGroup` 命令组,用于声明一组有相同名称前缀的命令。 @@ -1958,6 +1959,175 @@ sidebar: auto 注册 `('scheduler', 'add')` 命令。 +### _class_ `CommandManager` + +#### `commands` + +- **类型:** `Dict[CommandName_T, Command]` + +- **说明:** + + 命令字典。 + +#### `aliases` + +- **类型:** `Dict[str, Command]` + +- **说明:** + + 命令别名字典。 + +#### `switches` + +- **类型:** `Dict[CommandName_T, bool]` + +- **说明:** + + 命令开关状态字典。 + +#### _class method_ `add_command(cls, cmd_name, cmd)` + +- **说明:** + + 注册一个 `Command` 对象。 + +- **参数:** + + - `cmd_name: CommandName_T`: 命令名称 + - `cmd: Command`: 命令对象 + +- **返回:** + + None + +- **用法:** + + ```python + cmd = Command(name, func, permission, only_to_me, privileged) + CommandManager.add_command(name, cmd) + ``` + +#### _class method_ `add_aliases(cls, aliases, cmd)` + +- **说明:** + + 为 `Command` 添加命令别名。 + +- **参数:** + + - `aliases: Union[Iterable[str], str]`: 命令别名列表 + +- **返回:** + + None + +- **用法:** + + ```python + cmd = Command(name, func, permission, only_to_me, privileged) + CommandManager.add_aliases({"别名", "test"}, cmd) + ``` + +#### _class method_ `reload_command(cls, cmd_name, cmd)` + +- **说明:** + + 更新一个已存在的命令。 + +- **参数:** + + - `cmd_name: CommandName_T`: 命令名称 + - `cmd: Command`: 命令对象 + +- **返回:** + + None + +- **用法:** + + ```python + cmd = Command(name, func, permission, only_to_me, privileged) + CommandManager.reload_command(name, cmd) + ``` + +#### _class method_ `remove_command(cls, cmd_name)` + +- **说明:** + + 移除一个已存在的命令。 + +- **参数:** + + - `cmd_name: CommandName_T`: 命令名称 + +- **返回:** + + - `bool`: 是否成功移除命令 + +- **用法:** + + ```python + CommandManager.remove_command(("test", )) + ``` + +#### _class method_ `switch_command_global(cls, cmd_name, state)` + +- **说明:** + + 根据 `state` 更改 command 的全局状态。 + +- **参数:** + + - `cmd_name: CommandName_T`: 命令名称 + - `state: Optional[bool]`: + - `None(default)`: 切换状态,即 开 -> 关、关 -> 开 + - `bool`: 切换至指定状态,`True` -> 开、`False` -> 关 + +- **返回:** + + None + +- **用法:** + + ```python + from nonebot import message_preprocessor + + # 全局关闭命令test, 对所有消息生效 + CommandManager.switch_command_global(("test", ), state=False) + + @message_preprocessor + async def processor(bot: NoneBot, event: CQEvent, plugin_manager: PluginManager): + plugin_manager.cmd_manager.switch_command_global(("test", ), state=False) + ``` + +#### `switch_command(self, cmd_name, state)` + +- **说明:** + + 根据 `state` 更改 command 的状态。仅对当前消息有效。 + +- **参数:** + + - `cmd_name: CommandName_T`: 命令名称 + - `state: Optional[bool]`: + - `None(default)`: 切换状态,即 开 -> 关、关 -> 开 + - `bool`: 切换至指定状态,`True` -> 开、`False` -> 关 + +- **返回:** + + None + +- **用法:** + + ```python + from nonebot import message_preprocessor + + # 关闭命令test, 仅对当前消息生效 + @message_preprocessor + async def processor(bot: NoneBot, event: CQEvent, plugin_manager: PluginManager): + plugin_manager.cmd_manager.switch_command(("test", ), state=False) + ``` + ### _class_ `CommandSession` 继承自 `BaseSession` 类,表示命令 Session。 diff --git a/nonebot/command/__init__.py b/nonebot/command/__init__.py index abc06eaa..b067a13f 100644 --- a/nonebot/command/__init__.py +++ b/nonebot/command/__init__.py @@ -183,6 +183,11 @@ class CommandManager: bool: Success or not """ if cmd_name in cls._commands: + cmd = cls._commands[cmd_name] + for alias in list( + filter(lambda x: cls._aliases[x] == cmd, + cls._aliases.keys())): + del cls._aliases[alias] del cls._commands[cmd_name] if cmd_name in cls._switches: del cls._switches[cmd_name]