yes-core框架的核心中间件 —— 让你的业务插件脱离底层协议,实现真正的跨平台运行。
adapter-manager 扮演着“翻译官”和“调度中心”的角色。它监听底层适配器(如 adapter-onebot、adapter-telegram)抛出的原始事件,将其转换为强类型的标准事件,并注入丰富的操作闭包,让业务插件用最少的代码实现消息回复、撤回、禁言等功能。
在你的机器人 main.go 中匿名引入本插件,并确保它在业务插件之前加载:
package main
import (
"github.com/yeswearebot/yes-core/core"
_ "github.com/yeswearebot/plugin_config" // 基础配置中心
_ "github.com/yeswearebot/adapter-onebot" // 底层 QQ 协议端
_ "github.com/yeswearebot/adapter-manager" // 🌟 引入本管理器
_ "github.com/yourname/my-plugin" // 你的业务插件
)
func main() {
app := core.NewApp()
if err := app.Run(); err != nil {
panic(err)
}
}只需依赖 adapter-manager,你就可以写出跨平台的机器人逻辑:
package my_plugin
import (
"fmt"
"time"
adapter_manager "github.com/yeswearebot/adapter-manager"
"github.com/yeswearebot/yes-core/core"
)
type MyPlugin struct{}
func init() {
core.Register(func() core.Plugin { return &MyPlugin{} })
}
func (p *MyPlugin) Name() string { return "my-plugin" }
func (p *MyPlugin) DependsOn() []string { return []string{"adapter-manager"} }
func (p *MyPlugin) Init(ctx *core.SystemContext) error {
// 1. 监听标准化消息事件
ctx.Events.Subscribe("adapter.message", func(payload any) {
event, ok := payload.(*adapter_manager.MessageEvent)
if !ok {
return
}
fmt.Printf("[%s][%s] %s(%d): %s\n",
event.Platform, event.Scene, event.Nickname, event.UserID, event.PlainText)
// 🌟 极简回复:直接调用闭包
if event.PlainText == "ping" {
event.ReplyText("pong!")
}
// 🌟 跨平台群管操作
if event.PlainText == "违禁词" {
event.Delete() // 撤回消息
event.BanSender(60) // 禁言发送者 60 秒
event.ReplyText("已处理违禁词")
}
})
// 2. 主动调用示例 (定时任务等)
go func() {
time.Sleep(5 * time.Second)
// 获取 Manager 实例
manager := adapter_manager.GetManager(ctx)
if manager != nil {
// 主动给某个群发消息
manager.SendGroupMessage("adapter-onebot", 123456789, []adapter_manager.MessageSegment{
adapter_manager.Text("早安!"),
})
}
}()
return nil
}
func (p *MyPlugin) Start(ctx *core.SystemContext) error { return nil }
func (p *MyPlugin) Stop(ctx *core.SystemContext) error { return nil }当收到消息时,adapter-manager 会将原始数据封装为 MessageEvent 并发布到 adapter.message 频道。
| 字段名 | 类型 | 说明 |
|---|---|---|
Platform |
string |
适配器名称 (如 "adapter-onebot") |
EventType |
string |
事件类型 ("group_msg" 或 "private_msg") |
Scene |
string |
场景 ("group" 群聊 或 "private" 私聊) |
SceneID |
int64 |
场景 ID (群号 或 私聊对方 QQ) |
UserID |
int64 |
发送者 QQ |
MessageID |
int32 |
消息 ID (供撤回使用) |
Nickname |
string |
发送者昵称 |
Segments |
[]MessageSegment |
结构化消息段数组 |
PlainText |
string |
纯文本消息(用于指令匹配) |
LLMText |
string |
LLM 友好文本(用于大模型处理) |
RawEvent |
any |
底层原始事件结构体 |
| 方法 | 参数 | 说明 |
|---|---|---|
Reply(msg) |
[]MessageSegment |
回复当前消息发送者 (自动判断群聊/私聊) |
ReplyText(msg) |
string |
快捷纯文本回复 |
Delete() |
- | 撤回当前消息 |
BanSender(duration) |
int64 |
禁言当前发送者 (秒,仅群聊有效,0为解禁) |
在非消息上下文(如定时任务、Webhook)中,你可以通过 GetManager(ctx) 获取管理器实例,进行主动操作。
manager := adapter_manager.GetManager(ctx)manager.SendGroupMessage(platform, groupID, msg)- 主动发群消息manager.SendPrivateMessage(platform, userID, msg)- 主动发私聊消息manager.BanGroupMember(platform, groupID, userID, duration)- 主动禁言某人
manager.GetGroupInfo(platform, groupID, noCache)返回*GroupInfo(包含GroupID,GroupName,MemberCount,MaxMemberCount)manager.GetGroupMemberInfo(platform, groupID, userID, noCache)返回*GroupMemberInfo(包含GroupID,UserID,Nickname,Card,Role)manager.GetGroupMemberList(platform, groupID)返回[]GroupMemberInfo使用示例:
info, err := manager.GetGroupInfo(event.Platform, event.SceneID, false)
if err == nil {
msg := fmt.Sprintf("群名: %s\n成员数: %d / %d", info.GroupName, info.MemberCount, info.MaxMemberCount)
event.ReplyText(msg)
}MessageSegment 是结构化的消息单元,替代传统的 CQ 码字符串。
// 文本消息
textSeg := adapter_manager.Text("Hello World")
// @某人
atSeg := adapter_manager.At(123456789)
// 图片消息
imageSeg := adapter_manager.Image("https://example.com/image.png")
// 回复消息
replySeg := adapter_manager.Reply(987654321)
// QQ表情
faceSeg := adapter_manager.Face(123)// 获取字符串参数
url := imageSeg.GetString("url")
// 获取整数参数
userID := atSeg.GetInt64("user_id")adapter-manager 支持自定义消息渲染逻辑,你可以注册自己的渲染器:
// 自定义 LLM 渲染器
type MyLLMRenderer struct{}
func (r *MyLLMRenderer) Render(segments []adapter_manager.MessageSegment) string {
var sb strings.Builder
for _, seg := range segments {
switch seg.Type {
case adapter_manager.SegText:
sb.WriteString(seg.GetString("text"))
case adapter_manager.SegImage:
sb.WriteString(fmt.Sprintf("[图片:%s]", seg.GetString("url")))
case adapter_manager.SegAt:
sb.WriteString(fmt.Sprintf("[提及用户:%d]", seg.GetInt64("user_id")))
default:
sb.WriteString(fmt.Sprintf("[%s]", seg.Type))
}
}
return sb.String()
}
// 在插件初始化时注册
func (p *MyPlugin) Init(ctx *core.SystemContext) error {
adapter_manager.RegisterLLMRenderer(&MyLLMRenderer{})
return nil
}虽然 adapter-manager 抽象了通用逻辑,但如果你确实需要读取某个平台特有的字段(例如 Onebot 的群成员等级 Level),可以通过 RawEvent 进行断言获取:
ctx.Events.Subscribe("adapter.message", func(payload any) {
event, _ := payload.(*adapter_manager.MessageEvent)
// 仅在 onebot 平台下执行
if event.Platform == "adapter-onebot" {
// 假设你在 adapter-onebot 中抛出的 raw_event 是 Pichubot.MessageGroup
// 你需要引入 Pichubot 包进行断言
/*
rawGroupEvent, ok := event.RawEvent.(Pichubot.MessageGroup)
if ok {
fmt.Println("发送者群角色:", rawGroupEvent.Sender.Role)
fmt.Println("发送者群等级:", rawGroupEvent.Sender.Level)
}
*/
}
})如果你想为 yes-core 编写一个新的适配器(例如 adapter-telegram),只需实现 adapter-manager 定义的 Adapter 接口,并在内核中注册即可自动接入:
// 你的适配器必须实现以下所有方法:
type Adapter interface {
SendGroupMsg(groupID int64, message []MessageSegment) error
SendPrivateMsg(userID int64, message []MessageSegment) error
DeleteMsg(messageID int32) error
SetGroupBan(groupID, userID, duration int64) error
GetGroupInfo(groupID int64, noCache bool) (any, error)
GetGroupMemberInfo(groupID, userID int64, noCache bool) (any, error)
GetGroupMemberList(groupID int64) (any, error)
}同时,在你的适配器事件监听器中,将原始事件打包成包含 platform, event_type, scene, scene_id 等字段的 map[string]any,并发布到 adapter.raw.message 频道即可。
欢迎提交 Issue 和 Pull Request。如有任何问题,请在仓库中提出。