11 KiB
sidebar_position, description, options
| sidebar_position | description | options | ||||||
|---|---|---|---|---|---|---|---|---|
| 5 | 事件响应器组成与内置响应规则 |
|
事件响应器进阶
在指南与深入中,我们已经介绍了事件响应器的基本用法以及响应规则、权限控制等功能。在这一节中,我们将介绍事件响应器的组成,以及内置的响应规则。
事件响应器组成
事件响应器类型
事件响应器类型 type 即是该响应器所要响应的事件类型,只有在接收到的事件类型与该响应器的类型相同时,才会触发该响应器。如果类型为空字符串 "",则响应器将会响应所有类型的事件。事件响应器类型的检查在所有其他检查(权限控制、响应规则)之前进行。
NoneBot 内置了四种常用事件类型:meta_event、message、notice、request,分别对应元事件、消息、通知、请求。通常情况下,协议适配器会将事件合理地分类至这四种类型中。如果有其他类型的事件需要响应,可以自行定义新的类型。
事件触发权限
事件触发权限 permission 是一个 Permission 对象,这在权限控制一节中已经介绍过。事件触发权限会在事件响应器的类型检查通过后进行检查,如果权限检查通过,则执行响应规则检查。
事件响应规则
事件响应规则 rule 是一个 Rule 对象,这在响应规则一节中已经介绍过。事件响应器的响应规则会在事件响应器的权限检查通过后进行匹配,如果响应规则检查通过,则触发该响应器。
响应优先级
响应优先级 priority 是一个正整数,用于指定响应器的优先级。响应器的优先级越小,越先被触发。如果响应器的优先级相同,则按照响应器的注册顺序进行触发。
阻断
阻断 block 是一个布尔值,用于指定响应器是否阻断事件的传播。如果阻断为 True,则在该响应器被触发后,事件将不会再传播给其他下一优先级的响应器。
NoneBot 内置的事件响应器中,所有非 command 规则的 message 类型的事件响应器都会阻断事件传递,其他则不会。
在部分情况中,可以使用 stop_propagation 方法动态阻止事件传播,该方法需要 handler 在参数中获取 matcher 实例后调用方法。
有效期
事件响应器的有效期分为 temp 和 expire_time 。temp 是一个布尔值,用于指定响应器是否为临时响应器。如果为 True,则该响应器在被触发后会被自动销毁。expire_time 是一个 datetime 对象,用于指定响应器的过期时间。如果 expire_time 不为 None,则在该时间点后,该响应器会被自动销毁。
默认状态
事件响应器的默认状态 default_state 是一个 dict 对象,用于指定响应器的默认状态。在响应器被触发时,响应器将会初始化默认状态然后开始执行事件处理流程。
基本辅助函数
NoneBot 为四种类型的事件响应器提供了五个基本的辅助函数:
on:创建任何类型的事件响应器。on_metaevent:创建元事件响应器。on_message:创建消息事件响应器。on_request:创建请求事件响应器。on_notice:创建通知事件响应器。
除了 on 函数具有一个 type 参数外,其余参数均相同:
rule:响应规则,可以是Rule对象或者RuleChecker函数。permission:事件触发权限,可以是Permission对象或者PermissionChecker函数。handlers:事件处理函数列表。temp:是否为临时响应器。expire_time:响应器的过期时间。priority:响应器的优先级。block:是否阻断事件传播。state:响应器的默认状态。
在消息类型的事件响应器的基础上,NoneBot 还内置了一些常用的响应规则,并结合为辅助函数来方便我们快速创建指定功能的响应器。下面我们逐个介绍。
内置响应规则
startswith
startswith 响应规则用于匹配消息纯文本部分的开头是否与指定字符串(或一系列字符串)相同。可选参数 ignorecase 用于指定是否忽略大小写,默认为 False。
例如,我们可以创建一个匹配消息开头为 ! 或者 / 的规则:
from nonebot.rule import startswith
rule = startswith(("!", "/"), ignorecase=False)
也可以直接使用辅助函数新建一个响应器:
from nonebot import on_startswith
matcher = on_startswith(("!", "/"), ignorecase=False)
endswith
endswith 响应规则用于匹配消息纯文本部分的结尾是否与指定字符串(或一系列字符串)相同。可选参数 ignorecase 用于指定是否忽略大小写,默认为 False。
例如,我们可以创建一个匹配消息结尾为 . 或者 。 的规则:
from nonebot.rule import endswith
rule = endswith((".", "。"), ignorecase=False)
也可以直接使用辅助函数新建一个响应器:
from nonebot import on_endswith
matcher = on_endswith((".", "。"), ignorecase=False)
fullmatch
fullmatch 响应规则用于匹配消息纯文本部分是否与指定字符串(或一系列字符串)完全相同。可选参数 ignorecase 用于指定是否忽略大小写,默认为 False。
例如,我们可以创建一个匹配消息为 ping 或者 pong 的规则:
from nonebot.rule import fullmatch
rule = fullmatch(("ping", "pong"), ignorecase=False)
也可以直接使用辅助函数新建一个响应器:
from nonebot import on_fullmatch
matcher = on_fullmatch(("ping", "pong"), ignorecase=False)
keyword
keyword 响应规则用于匹配消息纯文本部分是否包含指定字符串(或一系列字符串)。
例如,我们可以创建一个匹配消息中包含 hello 或者 hi 的规则:
from nonebot.rule import keyword
rule = keyword("hello", "hi")
也可以直接使用辅助函数新建一个响应器:
from nonebot import on_keyword
matcher = on_keyword("hello", "hi")
command
command 是最常用的响应规则,它用于匹配消息是否为命令。它会根据配置中的 Command Start 和 Command Separator 来判断消息是否为命令。
例如,当我们配置了 Command Start 为 /,Command Separator 为 . 时:
from nonebot.rule import command
# 匹配 "/help" 或者 "/帮助" 开头的消息
rule = command("help", "帮助")
# 匹配 "/help.cmd" 开头的消息
rule = command(("help", "cmd"))
也可以直接使用辅助函数新建一个响应器:
from nonebot import on_command
matcher = on_command("help", aliases={"帮助"})
此外,command 响应规则默认允许消息命令与参数间不加空格,如果需要严格匹配命令与参数间的空白符,可以使用 command 函数的 force_whitespace 参数。force_whitespace 参数可以是 bool 类型或者具体的字符串,默认为 False。如果为 True,则命令与参数间必须有任意个数的空白符;如果为字符串,则命令与参数间必须有且与给定字符串一致的空白符。
rule = command("help", force_whitespace=True)
rule = command("help", force_whitespace=" ")
命令解析后的结果可以通过 Command、RawCommand、CommandArg、CommandStart、CommandWhitespace 依赖注入获取。
shell_command
shell_command 响应规则用于匹配类 shell 命令形式的消息。它首先与 command 响应规则一样进行命令匹配,如果匹配成功,则会进行进一步的参数解析。参数解析采用 argparse 标准库进行,在此基础上添加了消息序列 Message 支持。
例如,我们可以创建一个匹配 /cmd 命令并且带有 -v 选项与默认 -h 帮助选项的规则:
from nonebot.rule import shell_command, ArgumentParser
parser = ArgumentParser()
parser.add_argument("-v", "--verbose", action="store_true")
rule = shell_command("cmd", parser=parser)
更多关于 argparse 的使用方法请参考 argparse 文档。我们也可以选择不提供 parser 参数,这样 shell_command 将不会解析参数,但会提供参数列表 argv。
直接使用辅助函数新建一个响应器:
from nonebot import on_shell_command
from nonebot.rule import ArgumentParser
parser = ArgumentParser()
parser.add_argument("-v", "--verbose", action="store_true")
matcher = on_shell_command("cmd", parser=parser)
参数解析后的结果可以通过 ShellCommandArgv、ShellCommandArgs 依赖注入获取。
regex
regex 响应规则用于匹配消息是否与指定正则表达式匹配。
:::tip 提示
正则表达式匹配使用 search 而非 match,如需从头匹配请使用 r"^xxx" 模式来确保匹配开头。
:::
例如,我们可以创建一个匹配消息中包含字母并且忽略大小写的规则:
from nonebot.rule import regex
rule = regex(r"[a-z]+", flags=re.IGNORECASE)
也可以直接使用辅助函数新建一个响应器:
from nonebot import on_regex
matcher = on_regex(r"[a-z]+", flags=re.IGNORECASE)
正则匹配后的结果可以通过 RegexStr、RegexGroup、RegexDict 依赖注入获取。
to_me
to_me 响应规则用于匹配事件是否与机器人相关。
例如:
from nonebot.rule import to_me
rule = to_me()
is_type
is_type 响应规则用于匹配事件类型是否为指定类型(或者一系列类型)。
例如,我们可以创建一个匹配 OneBot v11 私聊和群聊消息事件的规则:
from nonebot.rule import is_type
from nonebot.adapters.onebot.v11 import PrivateMessageEvent, GroupMessageEvent
rule = is_type(PrivateMessageEvent, GroupMessageEvent)
响应器组
为了更方便的管理一系列功能相近的响应器,NoneBot 提供了两种响应器组,它们可以帮助我们进行响应器的统一管理。
CommandGroup
CommandGroup 可以用于管理一系列具有相同前置命令的子命令响应器。
例如,我们创建 /cmd、/cmd.sub、/cmd.help 三个命令,他们具有相同的优先级:
from nonebot import CommandGroup
group = CommandGroup("cmd", priority=10)
cmd = group.command(tuple())
sub_cmd = group.command("sub")
help_cmd = group.command("help")
MatcherGroup
MatcherGroup 可以用于管理一系列具有相同属性的响应器。
例如,我们创建一个具有相同响应规则的响应器组:
from nonebot.rule import to_me
from nonebot import MatcherGroup
group = MatcherGroup(rule=to_me())
matcher1 = group.on_message()
matcher2 = group.on_message()