nonebot.command

快捷导入:

此模块定义了一个内部细节可能会频繁变更而不在文档公开的 Command 类型,用户如果需要使用应该自行考虑不兼容更新产生的风险。

class CommandManager() 1.6.0+

  • 说明

    全局命令管理器。

instance-var commands

instance-var aliases

  • 类型: dict[str, Command]

  • 说明: 命令别名字典。

instance-var switches

  • 类型: dict[Command, bool]

  • 说明: 命令开关状态字典。

instance-var patterns 1.7.0+

  • 类型: dict[Pattern[str], Command]

  • 说明: 命令正则匹配字典。

classmethod add_aliases(cls, aliases, cmd)

  • 说明

    Command 添加命令别名。

  • 参数

    • aliases (Iterable[str] | str): 命令别名列表

    • cmd (nonebot.command.Command)

  • 返回

    • None
  • 用法

    cmd = Command(...)
    CommandManager.add_aliases({"别名", "test"}, cmd)
    
    1
    2

classmethod add_command(cls, cmd_name, cmd)

  • 说明

    注册一个 Command 对象。

  • 参数

    • cmd_name (CommandName_T): 命令名称

    • cmd (nonebot.command.Command): 命令对象

  • 返回

    • None
  • 用法

    cmd = Command(...)
    CommandManager.add_command(name, cmd)
    
    1
    2

classmethod reload_command(cls, cmd_name, cmd)

  • 说明

    更新一个已存在的命令。

  • 参数

    • cmd_name (CommandName_T): 命令名称

    • cmd (nonebot.command.Command): 命令对象

  • 返回

    • None
  • 用法

    cmd = Command(...)
    CommandManager.reload_command(name, cmd)
    
    1
    2

classmethod remove_command(cls, cmd_name)

  • 说明

    移除一个已存在的命令。

  • 参数

  • 返回

    • bool: 是否成功移除命令
  • 用法

    CommandManager.remove_command(("test", ))
    
    1

method switch_command(self, cmd_name, state=None)

  • 说明

    根据 state 更改 command 的状态。仅对当前消息有效。

  • 参数

    • cmd_name (CommandName_T): 命令名称

    • state (bool | None)

      • None(default): 切换状态,即 开 -> 关、关 -> 开
      • bool: 切换至指定状态,True -> 开、False -> 关
  • 返回

    • None
  • 用法

    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)
    
    1
    2
    3
    4
    5
    6

classmethod switch_command_global(cls, cmd_name, state=None)

  • 说明

    根据 state 更改 command 的全局状态。

  • 参数

    • cmd_name (CommandName_T): 命令名称

    • state (bool | None)

      • None(default): 切换状态,即 开 -> 关、关 -> 开
      • bool: 切换至指定状态,True -> 开、False -> 关
  • 返回

    • None
  • 用法

    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)
    
    1
    2
    3
    4
    5
    6
    7
    8

class CommandSession(bot, event, cmd, *, current_arg='', args=None)

  • 说明

    继承自 BaseSession 类,表示命令 Session。

  • 参数

    • bot (NoneBot)

    • event (aiocqhttp.event.Event)

    • cmd (nonebot.command.Command)

    • current_arg (str | None)

    • args (CommandArgs_T | None)

property argv

  • 类型: list[str]

  • 说明: 命令参数列表,类似于 sys.argv,本质上是 session.state.get('argv', [])需要搭配 on_command(..., shell_like=True) 使用

  • 用法

    @on_command('some_cmd', shell_like=True)
    async def _(session: CommandSession):
        argv = session.argv
    
    1
    2
    3

instance-var current_arg

  • 类型: str | None

  • 说明: 命令会话当前参数。实际上是 酷 Q 收到的消息去掉命令名的剩下部分,因此可能存在 CQ 码。

property current_arg_images

  • 类型: list[str]

  • 说明: current_arg 属性中所有图片的 URL 的列表,如果参数中没有图片,则为 []

property current_arg_text

  • 类型: str

  • 说明: current_arg 属性的纯文本部分(不包含 CQ 码),各部分使用空格连接。

instance-var current_key

  • 类型: str | None

  • 说明: 命令会话当前正在询问用户的参数的键(或称参数的名字)。第一次运行会话时,该属性为 None

property is_first_run

  • 类型: bool

  • 说明: 命令会话是否第一次运行。

property state 1.2.0+

  • 类型: State_T

  • 说明

    命令会话的状态数据(包括已获得的所有参数)。

    属性本身只读,但属性中的内容可读写。

  • 用法

    if not session.state.get('initialized'):
        # ... 初始化工作
        session.state['initialized'] = True
    
    1
    2
    3

    在命令处理函数的开头进行每次命令调用只应该执行一次的初始化操作

async method aget(self, key=..., *, prompt=None, arg_filters=None, force_update=..., **kwargs) 1.8.0+

  • 说明

    state 属性获取参数,如果参数不存在,则异步地暂停当前会话,向用户发送提示,并等待用户的进一步交互。

    当用户再次输入时,不会重新运行命令处理器,而是回到此函数调用之处继续执行。

    注意,一旦传入 arg_filters 参数(参数过滤器),则等用户再次输入时,command_func.args_parser 所注册的参数解析函数将不会被运行,而会在对 current_arg 依次运行过滤器之后直接将其放入 state 属性中。

  • 参数

    • key (str): 参数的键,若不传入则使用默认键值

    • prompt (Message_T | None): 提示的消息内容

    • arg_filters (list[Filter_T] | None): 用于处理和验证用户输入的参数的过滤器

    • force_update (bool): 是否强制获取用户新的输入,若是,则会忽略已有的当前参数,若 key 不传入则为真,否则默认为假

    • **kwargs: 其它传入 BaseSession.send() 的命名参数

  • 返回

    • Any: 参数的值
  • 用法

    from nonebot.command.argfilter import extractors, validators
    
    note = await session.aget(
        'note', prompt='你需要我提醒你什么呢',
        arg_filters=[
            extractors.extract_text,  # 取纯文本部分
            controllers.handle_cancellation(session),  # 处理用户可能的取消指令
            str.strip  # 去掉两边空白字符
        ]
    )
    
    time = await session.aget(
        'time', prompt='你需要我在什么时间提醒你呢?',
        arg_filters=[
            extractors.extract_text,  # 取纯文本部分
            controllers.handle_cancellation(session),  # 处理用户可能的取消指令
            str.strip,  # 去掉两边空白字符
            # 正则匹配输入格式
            validators.match_regex(r'^\d{4}-\d{2}-\d{2}$', '格式不对啦,请重新输入')
        ]
    )
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21

    连续获取多个参数,如果当前还不知道,则询问用户,等待用户输入之后,会依次运行 arg_filters 参数中的过滤器,以确保参数内容和格式符合要求。

async method apause(self, message=None, **kwargs) 1.8.0+

  • 说明

    异步地暂停当前命令会话,并发送消息。

    当用户再次输入时,不会重新运行命令处理器,而是回到此函数调用之处继续执行。

  • 参数

    • message (Message_T | None): 要发送的消息,若不传入则不发送

    • **kwargs: 其它传入 BaseSession.send() 的命名参数

  • 返回

    • None
  • 用法

    await session.apause('请发送要处理的图片,发送 done 结束')
    while True:
        if session.current_arg_text.strip() == 'done':
            session.finish('处理完成')
        process_images(session.current_arg_images)
        await session.apause('请继续发送要处理的图片,发送 done 结束')
    
    1
    2
    3
    4
    5
    6

    需要连续接收用户输入,并且过程中不需要改变 current_key 时,使用此函数暂停会话。

method finish(self, message=None, **kwargs)

  • 说明

    结束当前命令会话,并发送消息。此函数调用之后的语句将不会被执行(除非捕获了此函数抛出的特殊异常)。

    调用此函数后,命令将被视为已经完成,当前命令会话将被移除。

  • 参数

    • message (Message_T | None): 要发送的消息,若不传入则不发送

    • **kwargs: 其它传入 BaseSession.send() 的命名参数

  • 返回

    • NoReturn
  • 用法

    session.finish('感谢您的使用~')
    
    1

method get(self, key, *, prompt=None, arg_filters=None, **kwargs)

  • 说明

    state 属性获取参数,如果参数不存在,则暂停当前会话,向用户发送提示,并等待用户的新一轮交互。

    如果需要暂停当前会话,则命令处理器中,此函数调用之后的语句将不会被执行(除非捕获了此函数抛出的特殊异常)。

    注意,一旦传入 arg_filters 参数(参数过滤器),则等用户再次输入时,command_func.args_parser 所注册的参数解析函数将不会被运行,而会在对 current_arg 依次运行过滤器之后直接将其放入 state 属性中。

    TIP

    推荐使用 aget 方法。

  • 参数

    • key (str): 参数的键

    • prompt (Message_T | None): 提示的消息内容

    • arg_filters (list[Filter_T] | None) 1.2.0+: 用于处理和验证用户输入的参数的过滤器

    • **kwargs: 其它传入 BaseSession.send() 的命名参数

  • 返回

    • Any: 参数的值
  • 用法

    location = session.get('location', prompt='请输入要查询的地区')
    
    1

    获取位置信息,如果当前还不知道,则询问用户。

    from nonebot.command.argfilter import extractors, validators
    
    time = session.get(
        'time', prompt='你需要我在什么时间提醒你呢?',
        arg_filters=[
            extractors.extract_text,  # 取纯文本部分
            controllers.handle_cancellation(session),  # 处理用户可能的取消指令
            str.strip,  # 去掉两边空白字符
            # 正则匹配输入格式
            validators.match_regex(r'^\d{4}-\d{2}-\d{2}$', '格式不对啦,请重新输入')
        ]
    )
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12

    获取时间信息,如果当前还不知道,则询问用户,等待用户输入之后,会依次运行 arg_filters 参数中的过滤器,以确保参数内容和格式符合要求。

method pause(self, message=None, **kwargs)

  • 说明

    暂停当前命令会话,并发送消息。此函数调用之后的语句将不会被执行(除非捕获了此函数抛出的特殊异常)。

    TIP

    推荐使用 apause 方法。

  • 参数

    • message (Message_T | None): 要发送的消息,若不传入则不发送

    • **kwargs: 其它传入 BaseSession.send() 的命名参数

  • 返回

    • NoReturn
  • 用法

    if session.is_first_run:
        session.pause('请发送要处理的图片,发送 done 结束')
    if session.current_arg_text.strip() == 'done':
        session.finish('处理完成')
    process_images(session.current_arg_images)
    session.pause('请继续发送要处理的图片,发送 done 结束')
    
    1
    2
    3
    4
    5
    6

    需要连续接收用户输入,并且过程中不需要改变 current_key 时,使用此函数暂停会话。

method switch(self, new_message)

  • 说明

    结束当前会话,改变当前消息事件中的消息内容,然后重新处理消息事件。

    此函数可用于从一个命令中跳出,将用户输入的剩余部分作为新的消息来处理,例如可实现以下对话:

    用户: 帮我查下天气
    Bot: 你要查询哪里的天气呢?
    用户: 算了,帮我查下今天下午南京到上海的火车票吧
    Bot: 今天下午南京到上海的火车票有如下班次: blahblahblah
    
    1
    2
    3
    4

    这里进行到第三行时,命令期待的是一个地点,但实际发现消息的开头是「算了」,于是调用 switch('帮我查下今天下午南京到上海的火车票吧'),结束天气命令,将剩下来的内容作为新的消息来处理(触发火车票插件的自然语言处理器,进而调用火车票查询命令)。

  • 参数

    • new_message (Message_T): 要覆盖消息事件的新消息内容
  • 返回

    • NoReturn
  • 用法

    @my_cmd.args_parser
    async def _(session: CommandSession)
        if not session.is_first_run and session.current_arg.startswith('算了,'):
            session.switch(session.current_arg[len('算了,'):])
    
    1
    2
    3
    4

    使用「算了」来取消当前命令,转而进入新的消息处理流程。这个例子比较简单,实际应用中可以使用更复杂的 NLP 技术来判断。

async def call_command(bot, event, name, *, current_arg='', args=None, check_perm=True, disable_interaction=False)

  • 说明

    从内部直接调用命令。可用于在一个插件中直接调用另一个插件的命令。

  • 参数

    • bot (NoneBot): NoneBot 对象

    • event (aiocqhttp.event.Event): 事件对象

    • name (str | CommandName_T): 要调用的命令名

    • current_arg (str): 命令会话的当前输入参数

    • args (CommandArgs_T | None): 命令会话的(初始)参数(将会被并入命令会话的 state 属性)

    • check_perm (bool): 是否检查命令的权限,若否,则即使当前事件上下文并没有权限调用这里指定的命令,也仍然会调用成功

    • disable_interaction (bool): 是否禁用交互功能,若是,则该命令的会话不会覆盖任何当前已存在的命令会话,新创建的会话也不会保留

  • 返回

    • bool: 命令是否调用成功
  • 用法

    await call_command(bot, event, 'say', current_arg='[CQ:face,id=14]', check_perm=False)
    
    1

    从内部调用 say 命令,且不检查权限。

def kill_current_session(event)

  • 说明

    强行移除当前已存在的任何命令会话,即使它正在运行。该函数可用于强制移除执行时间超过预期的命令,以保证新的消息不会被拒绝服务。

  • 参数

    • event (aiocqhttp.event.Event): 事件对象
  • 返回

    • None
  • 用法

    @on_command('kill', privileged=True)
    async def _(session: CommandSession):
        kill_current_session(session.event)
    
    1
    2
    3

    在特权命令 kill 中强行移除当前正在运行的会话。