Skip to content

插件系统概览

AniaBot 中一切功能都是插件。本章介绍插件系统的核心概念,读完你将理解插件如何被加载、执行与管理。

插件是什么

一个插件就是一个嵌入了 plugin.Meta 的结构体:

go
type MyPlugin struct {
    plugin.Meta
}

func NewPlugin() *MyPlugin {
    return &MyPlugin{
        Meta: plugin.Meta{
            Name:      "我的插件",
            HelpWords: "这是 /help 中显示的介绍",
            Order:     plugin.LevelNormal,
            ShowFor:   plugininfo.ShowForGroup | plugininfo.ShowForFriend,
            Author:    "you",
            Version:   "1.0.0",
        },
    }
}

Meta 已经提供了 Plugin 接口全部方法的默认实现 —— 你只需按需重写关心的方法。

Meta 字段

字段类型说明
Namestring插件名,也用于存储命名空间隔离
HelpWordsstring/help 命令显示的帮助文本
AdminOnlybooltrue 时仅管理员能在 /help 中看到
ShowForShowFor显示范围:ShowForGroup / ShowForFriend / ShowForNone,可按位或
Orderint执行顺序,从小到大
Platforms[]string插件支持的平台列表(如 []string{"qq"}[]string{"qq","feishu"}[]string{"qq","feishu","telegram"});空 = 支持全部平台(默认)。core 按事件来源平台过滤,不匹配的插件收不到该平台事件
Author / Versionstring作者与版本信息

执行顺序(Order)

框架启动时按 Order 从小到大排序插件。预定义三档参考值:

go
plugin.LevelLog        = -1000  // 日志层:最先执行,如日志插件、消息拦截器
plugin.LevelNormal     = 0      // 普通业务插件(默认值)
plugin.LevelPostHandle = 1000   // 后置处理:最后执行,如 AI 对话兜底

中间件链

群聊与私聊消息事件返回 (bool, error)

  • 返回 true —— 继续传播给后续插件
  • 返回 false —— 阻断传播,后续插件收不到这条消息
go
func (p *MyPlugin) OnGroupMsg(ctx context.Context, bot bot.Bot, cmd command.Command, msg message.Message) (bool, error) {
    if cmd.Name == "hello" {
        // 处理完毕,不再传递给其他插件
        return false, nil
    }
    return true, nil // 放行
}

注意

通知事件(Notice)不走中间件链 —— 全部 14 种通知会广播给所有插件,无法被阻断。某个插件 panic 也不会影响其他插件收到通知。

生命周期

AddPlugin() 注册


Start(ctx, cfg)        ← 插件初始化(声明了 ConfigSchema 的配置结构体此时已自动填充完毕)


StartCron(ctx, bot, c) ← 注册 cron 定时任务


Awake(ctx, bot)        ← Bot 完全启动完成(此时可以发消息)


OnGroupMsg / OnFriendMsg / OnXxxNotice ...   ← 运行期事件


OnPanic(ctx, bot, name, err)  ← 任何插件 panic 时触发

依赖注入(DI)

Start() 之前,框架向每个插件注入以下依赖,直接通过 Meta 的字段使用:

字段类型用途
Storagestorage.Storage缓存层(TTL / 列表语义),已按插件名隔离
PersistentStoragestorage.PersistentStorage持久化 KV 存储,已按插件名隔离
RestyClient*resty.ClientHTTP 客户端
Logger*slog.Logger结构化日志
SystemConfigSystemConfig系统级配置(如 AdminId

事件一览

类别方法说明
消息OnGroupMsg / OnFriendMsg群聊 / 私聊消息,中间件链
通知OnGroupUpload OnGroupAdmin OnGroupDecrease OnGroupIncrease OnGroupBan OnFriendAdd OnGroupRecall OnFriendRecall OnPoke OnLuckyKing OnHonor OnGroupMsgEmojiLike OnEssence OnGroupCard14 种通知,广播制;戳一戳/运气王/荣誉/精华/名片/禁言/上传等为 QQ 专属,非 QQ 平台不触发
平台特定OnPlatformEvent(可选接口 plugin.PlatformEventHandler无法映射为公共事件/通知的平台自有事件(如飞书卡片回调、机器人入群),广播制
启动Start / StartCron / Awake生命周期钩子
异常OnPanicpanic 通知

事件字段详见 API · 事件接口

多平台能力探测

事件回调里的 bot.Bot事件来源平台能力包装后的外观。公共能力(发消息、查消息/群/历史)所有平台可用;QQ 专属能力(合并转发、戳一戳、rkey 等)在可选接口 bot.QQ 中,类型断言探测:

go
func (p *MyPlugin) OnGroupMsg(ctx context.Context, b bot.Bot, cmd command.Command, msg message.Message) (bool, error) {
    if qb, ok := b.(bot.QQ); ok { // 仅事件来源为 QQ 时断言成功
        qb.SendPokeMsg(msg.Sender.UserId, nil)
    }
    return true, nil
}

依赖 QQ 专属能力的插件应在 Meta.Platforms 声明只支持 QQ(如防撤回插件),其余平台自动跳过。

并发模型与 panic 恢复

  • 每个插件的每次调用都被 safeExecute 包裹 —— 单个插件 panic 不会影响其他插件或主进程
  • 插件内需要起协程时,使用 bot.Go(name, f) 代替裸 go f(),同样享有崩溃恢复
  • panic 发生后,所有插件的 OnPanic 会被回调,系统插件默认私聊告警管理员

注册插件

cmd/main.go 中(平台适配器由各平台包的 init() 自动注册,空白导入即可):

go
import (
    _ "github.com/jeanhua/AniaBot/bot/adapter/napcat"    // QQ 平台
    _ "github.com/jeanhua/AniaBot/bot/adapter/feishu"    // 飞书平台(可选)
    _ "github.com/jeanhua/AniaBot/bot/adapter/telegram"  // Telegram 平台(可选)
    _ "github.com/jeanhua/AniaBot/bot/adapter/discord"   // Discord 平台(可选)
    "github.com/jeanhua/AniaBot/bot/core"
    "github.com/jeanhua/AniaBot/bot/plugins/pluginsys"
    "github.com/jeanhua/AniaBot/custom/plugins/myplugin"
)

func main() {
    bot := core.NewAniaBot()

    bot.AddPlugin(pluginsys.NewPluginSys())
    bot.AddPlugin(myplugin.NewPlugin())   // ← 你的插件

    bot.Run()
}

启用的平台由配置键 bot.platform.<name>.enable 决定(默认仅 QQ),多平台可并存。新增平台只需在 bot/adapter/ 实现一个 Adapter 并在 init()adapter.Register(...),然后在此加一行空白导入,框架核心零改动。

下一步

基于 MIT 许可证发布