运行时钩子
Lingchu Bot 通过统一的 hooks/ 包注册全部 NoneBot 运行时钩子。导入该包会解析平台适配层、暴露共享钩子接口,并触发各个 handler 模块的注册。业务逻辑与 NoneBot 装饰器分离,便于单独测试 handler。
运行时钩子按能力分组,每个分类对应 hooks/handlers/ 下的一个模块。
| 分类 | 模块 | NoneBot 钩子 |
|---|---|---|
| 生命周期 | hooks/handlers/lifecycle.py |
driver.on_startup、driver.on_shutdown |
| Bot 连接 | hooks/handlers/bot_connection.py |
driver.on_bot_connect、driver.on_bot_disconnect |
| 消息存储 | hooks/handlers/message_store.py |
event_preprocessor、event_postprocessor、run_preprocessor、run_postprocessor |
| API 审计 | hooks/handlers/api_audit.py |
Bot.on_calling_api、Bot.on_called_api |
生命周期钩子在 NoneBot 驱动器启动时初始化 Lingchu 运行时服务,在驱动器停止时关闭服务。
on_startup调用start.startup.startup(),加载配置、菜单、权限和调度器。on_shutdown依次调用shutdown_scheduler_service()和shutdown_message_store()。
Bot 连接
Section titled “Bot 连接”Bot 连接钩子记录生命周期事件并发送待处理的重启反馈。
on_bot_connect记录bot_connected并触发send_pending_restart_feedback(bot)。on_bot_disconnect记录bot_disconnected。
消息存储钩子记录事件接收与匹配器执行结果。它使用 hooks/adapters.normalize_message_event 将适配器事件转换为稳定的 NormalizedMessageEvent,并把生成的 MessageIdentity 存入 state,供下游钩子关联记录。
event_preprocessor归一化事件并 fire-and-forget 调用services.message_store.handle_event_received。run_postprocessor从state读取 identity 并 fire-and-forget 调用services.message_store.handle_matcher_result。event_postprocessor与run_preprocessor为预留占位符,当前无操作。
API 审计
Section titled “API 审计”API 审计钩子记录平台 API 调用完成后的摘要。
on_called_api解析平台上下文,并在消息存储与 API 调用记录均启用时 fire-and-forget 调用services.message_store.handle_api_called。on_calling_api为预留占位符,当前无操作。
hooks/adapters.py 承载运行时钩子所需的全部平台相关逻辑。
| 导出 | 用途 |
|---|---|
resolve_platform_context(bot) |
将 Bot 实例映射为 PlatformContext(platform_id, adapter_id, bot_id, protocol_id);未知适配器返回 None。 |
normalize_message_event(bot, event) |
返回包含 identity、事件类型、消息类型、文本摘要和原始 payload 的 NormalizedMessageEvent。 |
MessageIdentity / NormalizedMessageEvent |
被 services.message_store 消费的稳定 dataclass。 |
字段提取辅助函数(如 _conversation_id、_user_id、_message_id、_plain_text)也集中在此模块,避免 handler 重复编写适配器专属逻辑。
新增钩子处理器
Section titled “新增钩子处理器”新增运行时钩子处理器的步骤如下:
-
选择匹配目标生命周期的 NoneBot2 原生装饰器。每个 handler 模块在导入时注册自身的装饰器,因此插件入口只需
from . import hooks。能力 NoneBot2 装饰器 参考模块 驱动器启动 / 关闭 @driver.on_startup、@driver.on_shutdownhooks/handlers/lifecycle.pyBot 连接 / 断开 @driver.on_bot_connect、@driver.on_bot_disconnecthooks/handlers/bot_connection.py事件 / matcher 处理 @event_preprocessor、@event_postprocessor、@run_preprocessor、@run_postprocessorhooks/handlers/message_store.pyBot API 调用 @Bot.on_calling_api、@Bot.on_called_apihooks/handlers/api_audit.py -
实现 handler:按 NoneBot2 装饰器签名实现。需要适配器无关身份时调用
hooks/adapters.py中的resolve_platform_context(bot),需要稳定消息封装时调用normalize_message_event(bot, event):from nonebot import get_driverfrom nonebot.adapters import Botfrom ..adapters import resolve_platform_contextdriver = get_driver()@driver.on_bot_connectasync def on_bot_connect(bot: Bot) -> None:ctx = resolve_platform_context(bot)if ctx is None:return... -
在
hooks/handlers/下创建模块,例如hooks/handlers/my_feature.py。在该模块中注册 NoneBot2 装饰器,业务调用保留在services/或repositories/中。 -
在
hooks/handlers/__init__.py导出模块,确保from . import hooks能加载它:from . import my_feature as my_feature