NoneBot2 响应规则(Rule)深度指南:从 RuleChecker 组合到内置规则实战
后端即时通讯【免费下载链接】nonebot2跨平台 Python 异步聊天机器人框架 / Asynchronous multi-platform chatbot framework written in Python项目地址https://gitcode.com/gh_mirrors/no/nonebot2点击查看免费下载导读在 NoneBot2 中机器人会接收到来自各种适配器QQ、微信、Telegram、Discord 等的多种事件而响应规则Rule正是控制“哪些事件应该被哪个事件响应器处理”的核心机制。本指南以 NoneBot2 官方文档《响应规则》为骨架结合 nonebot/internal/rule.py 与 nonebot/rule.py 的源码实现系统讲解RuleChecker依赖注入、Rule并发检查原理、运算符合并规则、主动调用规则判定事件以及全部内置响应规则的用法。读完本文你将能编写插件级开关规则、黑名单规则并熟练组合出符合业务需求的响应条件。响应规则的作用为事件处理把关机器人在实际应用中往往会接收到多种多样的事件类型普通消息、群成员变动、加好友请求、元事件等。NoneBot 通过响应规则来控制事件的处理——只有通过规则检查的事件才会交给对应的事件响应器Matcher执行后续逻辑。在指南中我们为weather命令添加了一个ruleto_me()参数这个参数就是一个响应规则确保只有在私聊或者bot时才会响应。这就是响应规则最典型的应用场景把“该事件是否与我相关”这类判断从业务逻辑中抽离出来交给框架在事件分发阶段统一完成。从源码结构看每个事件响应器都拥有一个Rule对象事件传递时会先经过规则检查再运行处理函数参见 nonebot/internal/rule.py 中Rule的类文档。响应规则是一个Rule对象它由一系列的RuleChecker函数组成每个RuleChecker函数都会检查事件是否符合条件如果所有的检查都通过则事件会被处理。RuleChecker可依赖注入的判定函数RuleChecker是一个返回值为bool类型的依赖函数即RuleChecker支持依赖注入。在 nonebot/typing.py 中其类型别名定义为_DependentCallable[bool]文档明确说明“RuleChecker 即判断是否响应事件的处理函数”且支持依赖参数。这意味着我们可以直接在RuleChecker的参数列表中声明Bot、Event、State甚至声明其他依赖如Depend和配置项。框架会像处理事件处理函数一样对RuleChecker进行依赖解析后再调用。我们可以根据配置项在weather插件目录中编写一个响应规则from nonebot import get_plugin_config from .config import Config plugin_config get_plugin_config(Config) async def is_enable() - bool: return plugin_config.weather_plugin_enabled weather on_command(天气, ruleis_enable)在上面的代码中我们定义了一个函数is_enable它会检查配置项weather_plugin_enabled是否为True。这个函数is_enable即为一个RuleChecker。这里传入rule的参数既可以是一个Rule对象也可以直接是一个RuleChecker函数——从 nonebot/internal/rule.py 可以看到Rule.__init__会对传入的每个 checker 做归一化处理如果传入的是Dependent实例则直接使用否则调用Dependent[bool].parse(callchecker, allow_types...)将其解析为依赖对象并存入self.checkers集合中。得益于依赖注入RuleChecker还可以声明事件参数例如检查用户是否在某个黑名单中from nonebot.adapters import Event BLACKLIST: set[str] set() async def is_blacklisted(event: Event) - bool: return event.get_user_id() not in BLACKLISTRuleChecker支持的所有依赖参数类型在源码中有明确约束Rule.HANDLER_PARAM_TYPES声明了DependParam、BotParam、EventParam、StateParam、DefaultParam五种见 nonebot/internal/rule.py与事件处理函数的依赖参数范围一致。Rule多个 RuleChecker 的并发集合Rule是若干个RuleChecker的集合它会并发调用每个RuleChecker只有当所有RuleChecker检查通过时匹配成功。例如我们可以组合两个RuleChecker一个用于检查插件是否启用一个用于检查用户是否在黑名单中from nonebot.rule import Rule from nonebot.adapters import Event async def is_enable() - bool: return plugin_config.weather_plugin_enabled async def is_blacklisted(event: Event) - bool: return event.get_user_id() not in BLACKLIST rule Rule(is_enable, is_blacklisted) weather on_command(天气, rulerule)并发检查的底层实现“并发调用每个RuleChecker”并非泛泛而谈源码实现位于 nonebot/internal/rule.py 的Rule.__call__当self.checkers为空时直接返回True空规则恒匹配使用anyio.create_task_group()创建任务组通过tg.start_soon(_run_checker, checker)为每个 checker 启动一个并发任务每个_run_checker将检查结果与最终结果做result is_passed累加先计算再累加以避免数据竞争若某个 checker 抛出SkippedException被catch捕获则整体结果置为False即“跳过”同样视为未通过。因此Rule的语义是严格的AND与任意一个 checker 返回False或抛出SkippedException整个规则就不通过。测试用例 tests/test_rule.py 对此有直接验证await Rule(truthy, falsy)(bot, event, {}) is False、await Rule(truthy, skipped)(bot, event, {}) is False。空 Rule 的行为从上述实现可以推断Rule()不包含任何 checker__call__直接返回True即不附加任何约束。这在动态构建规则链时很实用例如根据配置条件决定是否追加额外的 checker。合并响应规则运算符与 None 忽略在定义响应规则时我们可以将规则进行细分来更好地复用规则。而在使用时我们需要合并多个规则。除了使用Rule对象来组合多个RuleChecker外我们还可以对Rule对象进行合并。在原weather插件中我们可以将ruleto_me()与ruleis_enable使用运算符合并from nonebot.rule import to_me from nonebot import get_plugin_config from .config import Config plugin_config get_plugin_config(Config) async def is_enable() - bool: return plugin_config.weather_plugin_enabled weather on_command( 天气, ruleto_me() is_enable, aliases{weather, 查天气}, priorityplugin_config.weather_command_priority, blockTrue, )这样weather命令就只会在插件启用且在私聊或者bot时才会响应。注意to_me() is_enable中左侧是Rule对象、右侧是普通函数这种混合合并是允许的。支持的所有合并形式合并响应规则可以有多种形式例如rule1 Rule(foo_checker) rule2 Rule(bar_checker) rule rule1 rule2 rule rule1 bar_checker rule foo_checker rule2源码中的__and__与__rand__见 nonebot/internal/rule.py保证了这些写法全部合法Rule Rule把两个规则的 checker 集合合并成新RuleRule RuleChecker把单个 checker 追加进原规则RuleChecker Rule通过__rand__将 checker 置于规则之前合并操作不会修改原Rule对象而是返回新的Rule因为checkers是新建的 set。合并 None 值的安全保证同时我们也无需担心合并了一个None值Rule会忽略None值assert (rule None) is rule__and__与__rand__的第一分支就是if other is None: return self——注意这里返回的是原对象本身因此不仅是语义上忽略连对象引用都保持不变assert成立。测试用例 tests/test_rule.py 也覆盖了Rule(truthy) None、None Rule(truthy)、Rule(truthy) falsy、truthy Rule(falsy)四种组合。这一设计在“按配置项条件性追加规则”的场景中非常顺手rule to_me() if plugin_config.enable_blacklist: rule rule is_not_blacklisted无需担心if分支外的规则变量为None导致崩溃。注意Rule只支持AND合并源码中__or__被显式定义为直接抛出RuntimeError(Or operation between rules is not allowed.)即不存在|或运算请勿混用。主动使用响应规则程序化判定事件除了在事件响应器中使用响应规则外我们也可以主动使用响应规则来判断事件是否符合条件。例如rule Rule(some_checker) result: bool await rule(bot, event, state)我们只需要传入Bot对象、事件和会话状态Rule会并发调用所有RuleChecker进行检查并返回结果。从 nonebot/internal/rule.py 的签名看Rule.__call__的完整参数为(bot, event, state, stackNone, dependency_cacheNone)。其中stack异步上下文栈与dependency_cache依赖缓存为可选参数在事件响应器内部调用时由框架自动注入手动调用时通常只需提供前三个参数。这种方式非常适合在自定义分发逻辑、消息预处理管道或二次开发框架能力时复用现成的规则。内置响应规则开箱即用的规则库NoneBot 内置了一些常用的响应规则可以直接通过事件响应器辅助函数或者自行合并其他规则使用。内置响应规则列表可以参考事件响应器进阶。全部内置规则定义在 nonebot/rule.py 中每个规则都同时提供规则类如CommandRule与工厂函数如command(...)工厂函数返回Rule对象。下面分类展开命令类规则command(*cmds, force_whitespaceNone)—— 根据全局配置command_start命令起始符默认/与command_sep命令分隔符默认.判断消息是否为命令对应实现CommandRulenonebot/rule.py# 匹配 /test 开头的消息 rule command(test) # 匹配 /test.sub 开头的消息 rule command(test, sub) # force_whitespaceTrue 时命令后必须有空白才匹配如 /test xxx rule command(test, force_whitespaceTrue)命令内容与后续消息之间无需空格可通过Command()、RawCommand()、CommandArg()参数在处理器中获取匹配到的命令元组、原始命令文本和参数部分底层还会向TrieRule前缀树注册命令前缀用于消息的快速预匹配见 nonebot/rule.py注册重复前缀时会输出Duplicated prefix rule警告。shell_command(*cmds, parserNone)—— shell 风格的命令匹配支持用ArgumentParser解析参数对应ShellCommandRulenonebot/rule.pyfrom nonebot.rule import ArgumentParser parser ArgumentParser() parser.add_argument(-a, actionstore_true) rule shell_command(ls, parserparser)解析前可通过ShellCommandArgv()获取原始参数列表解析后通过ShellCommandArgs()获取参数字典若参数解析失败ShellCommandArgs()返回的将是ParserExit异常对象parser必须是nonebot.rule.ArgumentParser实例否则抛出TypeError。消息文本类规则startswith(msg, ignorecaseFalse)/endswith(msg, ignorecaseFalse)—— 匹配消息纯文本的开头 / 结尾nonebot/rule.pyrule startswith(今天, ignorecaseTrue) rule endswith((吗, 呢))匹配成功后匹配到的字符串会被写入state键分别为_prefix、_suffix对应的常量。fullmatch(msg, ignorecaseFalse)—— 消息纯文本与指定内容完全一致才匹配nonebot/rule.pyrule fullmatch(签到)ignorecaseTrue时使用str.casefold()做大小写无关比较。keyword(*keywords)—— 消息纯文本包含任意指定关键词即匹配nonebot/rule.pyrule keyword(天气, 气象)按关键词在文本中出现的顺序取第一个命中写入state。regex(regex, flags0)—— 用正则表达式匹配消息字符串注意是str(EventMessage)而非纯文本nonebot/rule.pyrule regex(r^天气(\d)$, flagsre.I)使用re.search而非re.match如需从头匹配请用r^xxx可通过RegexStr()、RegexGroup()、RegexDict()获取匹配字符串、分组元组与分组字典。事件类规则to_me()—— 匹配与机器人有关的事件私聊或bot对应ToMeRulenonebot/rule.py。它内部通过EventToMe()参数判断是文档示例中最常用的规则之一。is_type(*types)—— 检查事件是否为指定类型对应IsTypeRulenonebot/rule.pyfrom nonebot.adapters.onebot.v11 import GroupMessageEvent, PrivateMessageEvent rule is_type(GroupMessageEvent, PrivateMessageEvent)事件响应器辅助函数多数内置规则都有对应的on_*快捷注册函数定义于 nonebot/plugin/on.py每个函数都接受可选的rule参数用于追加额外规则辅助函数对应规则说明on_command(cmd, aliasesNone, force_whitespaceNone)command命令触发nonebot/plugin/on.pyon_shell_command(cmd, aliasesNone, parserNone)shell_commandshell 风格命令触发nonebot/plugin/on.pyon_startswith(msg, ignorecaseFalse)startswith文本开头触发nonebot/plugin/on.pyon_endswith(msg, ignorecaseFalse)endswith文本结尾触发nonebot/plugin/on.pyon_fullmatch(msg, ignorecaseFalse)fullmatch文本全匹配触发nonebot/plugin/on.pyon_keyword(keywords)keyword关键词触发nonebot/plugin/on.pyon_regex(pattern, flags0)regex正则触发nonebot/plugin/on.pyon_message()/on_notice()/on_request()/on_metaevent()is_type等按事件类型触发例如from nonebot import on_command weather on_command( 天气, aliases{weather, 查天气}, ruleto_me(), priority10, blockTrue, )这里的rule参数即可接收Rule对象或单个RuleChecker且可以与合并的结果配合使用。实战示例插件开关 黑名单 私聊限定将本文所有知识点串起来一个完整的 weather 插件响应规则定义如下from nonebot import get_plugin_config, on_command from nonebot.adapters import Event from nonebot.rule import Rule, to_me from .config import Config plugin_config get_plugin_config(Config) BLACKLIST {10001, 10002} async def is_enable() - bool: # 插件开关来自插件配置项 return plugin_config.weather_plugin_enabled async def is_not_blacklisted(event: Event) - bool: # 黑名单检查来自事件依赖注入 return event.get_user_id() not in BLACKLIST # 组合三个 RuleChecker插件启用、不在黑名单、私聊或 bot weather on_command( 天气, ruleRule(is_enable, is_not_blacklisted) to_me(), aliases{weather, 查天气}, priorityplugin_config.weather_command_priority, blockTrue, )规则检查会在事件分发阶段并发执行任一条件不满足插件未启用、用户在黑名单、既非私聊也未被 都会导致该事件不进入weather的处理流程。这正体现了响应规则的设计意图——把“是否响应”的决定权从业务代码中彻底剥离以声明式、可组合、可复用的方式表达。小结RuleChecker是支持依赖注入的bool判定函数可声明Bot、Event、State等依赖参数Rule是RuleChecker的集合通过anyio任务组并发执行并做 AND 累加任一失败含SkippedException即整体不通过使用运算符合并规则支持Rule Rule、Rule checker、checker Rule三种形式且自动忽略None值返回原对象可通过await rule(bot, event, state)主动调用规则判定任意事件内置command、shell_command、startswith、endswith、fullmatch、keyword、regex、to_me、is_type九类规则并有对应on_*快捷注册函数。响应规则与事件响应器进阶、权限系统共同构成了 NoneBot2 事件分发的完整控制体系是编写高质量插件时最值得熟练掌握的框架能力之一。赞分享后端即时通讯【免费下载链接】nonebot2跨平台 Python 异步聊天机器人框架 / Asynchronous multi-platform chatbot framework written in Python项目地址https://gitcode.com/gh_mirrors/no/nonebot2点击查看免费下载相关推荐NoneBot 响应规则Rule完全指南从 RuleChecker 组合到内置规则实战NoneBot 响应规则Rule完全指南从 RuleChecker 组合到内置规则实战 NoneBot 作为跨平台异步聊天机器人框架通过响应规则来决后端即时通讯NoneBot2 响应规则Rule全解析从 RuleChecker 依赖注入到内置规则与主动调用NoneBot2 响应规则Rule全解析从 RuleChecker 依赖注入到内置规则与主动调用 事件响应器Matcher是 NoneBot2 处理消后端即时通讯NoneBot2 事件响应器进阶指南响应器组成、内置规则与响应器组实战NoneBot2 事件响应器进阶指南响应器组成、内置规则与响应器组实战 本篇技术指南以 NoneBot2 的事件响应器Matcher进阶用法为核心系统讲后端即时通讯上一篇抖音无水印下载完整指南3 条命令跑通单条到主页批量下一篇5分钟掌握LinkSwift八大网盘直链下载的终极解决方案创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考