规则参考¶
Rule 决定事件是否进入某个 handler。它应该描述“消息或事件长什么样”,不要承担权限判断;
用户资格、角色和超级用户检查应放在 Permission。
核心模型¶
规则返回值会被归一化:
True匹配成功,没有额外 payload。
False或None不匹配。
dict匹配成功,并把字典合并进
ctx.matches,也可作为 handler 参数注入。(ok, payload)显式返回是否匹配和 payload。
规则可以用 &、|、~ 组合,也可以用更接近规则引擎写法的别名:
from iamai import when_all, when_any, none_of, word_in
deploy_rule = when_all(
word_in("deploy"),
none_of(word_in("danger")),
)
常用规则¶
事件来源:
adapter_is("onebot11")platform_is("qq")event_type_is("message")detail_type_is("group")user_id_is("10001")channel_id_is("20001")guild_id_is("20001")
文本:
startswith("hi", "hello")endswith("?")contains("token", require_all=True)text_equals("ping", ignore_case=True)word_in("deploy", "rollback")regex(r"#(?P<number>\\d+)")fullmatch(r"/issue (?P<number>\\d+)")
字段匹配¶
field 支持 dotted path,并能从不同来源读取:
source="event"Event属性,例如field("user_id", equals="10001")。source="raw"原始平台 payload,例如
raw_field("sender.role", equals="admin")。source="state"当前插件状态,例如
state_field("phase", equals="open")。source="shared_state"Runtime 共享状态,例如
field("ops.enabled", source="shared_state", equals=True)。source="matches"已捕获的匹配 payload。
source="context"Context对象本身,例如field("event.detail_type", source="context", equals="group")。
支持的比较包括:
exists=True/exists=Falseequals=value/not_equals=valuein_=[...]contains=valuestartswith="..."/endswith="..."regex=r"...(?P<name>...)..."gt/ge/lt/le
capture_as 会把字段值放进 payload:
from iamai import command, raw_field
@command("ban", rule=raw_field("sender.role", equals="admin", capture_as="role"))
async def ban(ctx, role: str) -> None:
await ctx.reply(f"allowed by {role}")
Ruleset¶
Ruleset 用来表达一组命名规则。它借鉴规则引擎的 ruleset 思路,但仍然运行在 iamai
现有 handler 规则机制内。
from iamai import message_handler, raw_field, ruleset, word_in
router = (
ruleset("intent-router")
.when("deploy", word_in("deploy").with_payload(intent="deploy"), priority=10)
.when("admin", raw_field("sender.role", equals="admin"), priority=20)
)
@message_handler(rule=router.as_rule())
async def route(ctx, intent: str) -> None:
await ctx.reply(f"intent={intent}")
默认只返回优先级最高的第一个匹配。需要收集全部匹配时:
@message_handler(rule=router.as_rule(first=False))
async def route(ctx) -> None:
names = ", ".join(ctx.matches["ruleset"])
await ctx.reply(names)
设计建议¶
规则只描述事件形态和业务入口,不描述权限。
字段规则优先使用
raw_field读取平台差异,避免把平台 payload 传进 handler 主流程。复杂路由优先用
Ruleset命名每个分支,便于日志、测试和后续维护。对外部状态、网络请求、数据库查询这类昂贵判断,优先放在依赖注入 provider 或 handler 内部。