Skip to content

插件机制原理

字数
1657 字
阅读时间
7 分钟

在开始开发 NapCat 插件之前,了解插件系统的运作机制有助于更合理地设计和编写插件。

插件是什么?

NapCat 插件本质上是一个 TypeScript/JavaScript 模块,它被 NapCat 的插件管理器加载后,通过生命周期钩子与 NapCat 主程序进行交互。

插件的工作方式可以概括为:

NapCat 加载你的插件 → 传给你一个上下文对象 ctx → 你通过 ctx 调用 NapCat 提供的各种能力

核心架构

整个插件系统由三个关键部分组成:

ctx 能做什么?

ctx(即 NapCatPluginContext)是插件与 NapCat 交互的唯一桥梁。它提供了 三个层次 的能力:

层次一:调用 OneBot Action(最常用)

通过 ctx.actions.call(...) 调用标准的 OneBot11 协议 Action,这是最主要的使用方式。

typescript
// 发送消息
await ctx.actions.call('send_msg', params, ctx.adapterName, ctx.pluginManager.config);

// 获取群列表
await ctx.actions.call('get_group_list', void 0, ctx.adapterName, ctx.pluginManager.config);

// 撤回消息
await ctx.actions.call('delete_msg', { message_id }, ctx.adapterName, ctx.pluginManager.config);

这些 Action 就是 NapCat 对外暴露的 OneBot11 API(如 send_msgget_group_listset_group_ban 等),与通过 HTTP/WebSocket 调用的 API 完全一致,只是插件内部可以直接调用,无需走网络请求。

API 查阅方式

  • 使用 AI 查询:官方插件模板 napcat-plugin-template.vscode/mcp.json 中已预配置了 napcat.apifox.cn 的 MCP 服务器。使用 VS Code + GitHub Copilot 打开项目后,可以直接在 Copilot Chat 中用自然语言查询 OneBot 和 NapCat 提供的各种 API 接口。
  • 手动查阅:也可以直接访问 https://napcat.apifox.cn/ 浏览完整的 API 文档。

层次二:使用插件框架能力

ctx 还提供了一系列插件框架本身的能力,这些与 OneBot 协议无关:

能力通过用途
路由注册ctx.router注册 HTTP API、静态文件、WebUI 页面
日志记录ctx.logger统一格式的日志输出
数据存储ctx.dataPath / ctx.configPath插件的数据和配置持久化
配置面板ctx.NapCatConfig在 WebUI 生成配置界面
插件管理ctx.pluginManager管理其他插件(查询、启停、加载)
插件通信ctx.getPluginExports()获取其他插件的导出对象,实现插件间交互

层次三:访问 NapCat 底层(高级用法)

ctx 还暴露了 NapCat 的内部实例,允许执行标准 OneBot 协议之外的操作:

  • ctx.core — NapCat 底层核心实例
  • ctx.oneBot — OneBot11 适配器实例

注意

直接使用 ctx.corectx.oneBot 属于高级用法,这些内部 API 可能在版本升级时发生变化。一般情况下优先使用 ctx.actions.call(...) 来调用标准 OneBot Action。

插件的两种典型用途

根据你要实现的功能,NapCat 插件大致可以分为两种模式(或两者结合):

模式一:Bot 功能型插件

这是最常见的模式。监听消息/事件 → 调用 OneBot Action 做出响应。

typescript
// 典型流程:收到消息 → 处理 → 调用 OneBot Action 回复
export const plugin_onmessage = async (ctx, event) => {
    if (event.raw_message === 'ping') {
        // 通过 ctx.actions 调用 OneBot Action 发送消息
        await ctx.actions.call('send_msg', {
            message: 'pong',
            message_type: event.message_type,
            group_id: String(event.group_id),
        }, ctx.adapterName, ctx.pluginManager.config);
    }
};

适用场景:关键词回复、命令处理、定时任务、消息转发、群管理等。

模式二:WebUI 功能型插件

不处理任何 QQ 消息,仅通过 ctx.router 注册路由和页面,在 NapCat 的 WebUI 中提供额外的管理界面或工具。

typescript
export const plugin_init = async (ctx) => {
    // 注册一个 WebUI 页面
    ctx.router.page({
        path: 'dashboard',
        title: '数据面板',
        htmlFile: 'webui/index.html',
    });

    // 注册 API
    ctx.router.getNoAuth('/stats', (req, res) => {
        res.json({ code: 0, data: { visits: 42 } });
    });
};

适用场景:数据可视化面板、配置管理工具、系统监控等。

模式三:两者结合

实际开发中,很多插件会 同时 使用这两种模式 —— 处理消息的同时提供一个 WebUI 管理界面。官方插件模板 napcat-plugin-template 就是这种模式的典型示例。

关于插件模板

napcat-plugin-template 会随着 NapCat 项目的更新而持续调整(如 API 变化、最佳实践优化等)。建议开发前以模板仓库的最新版本为准,并关注仓库的 Release 和 README 以了解变更。

生命周期概览

NapCat 通过调用你导出的特定函数来驱动插件运行:

与外部 OneBot 框架的区别

既然可以通过 HTTP/WebSocket 调用 OneBot API,为什么还需要插件?以下是两种方式的对比:

对比项外部 OneBot 客户端NapCat 插件
通信方式网络请求 (HTTP/WS)直接函数调用
部署方式独立进程/独立服务嵌入 NapCat 内部
性能有网络开销零网络开销,直接调用
能力范围仅限 OneBot 协议OneBot + NapCat 内部 API
WebUI 集成需要独立搭建前端直接嵌入 NapCat WebUI
用户安装需要额外配置放入 plugins 目录即可

综上,插件是一种更轻量、集成度更高的开发方式,适用于需要与 NapCat WebUI 联动或对性能有较高要求的场景。

下一步