ProgramCX/GoQQBot:用 Go 写 QQ 机器人——从接收消息到回复 Markdown 按钮菜单
ProgramCX/GoQQBot:用 Go 写 QQ 机器人——从接收消息到回复 Markdown 按钮菜单
写 QQ 机器人时,我希望业务代码能直观表达两件事:收到什么消息,以及要回复什么内容。比如收到 /menu 就发一份菜单,收到普通文字就回复一句话。单聊和群聊如果提供同样的功能,也应该能共用一个处理函数。
这也是我在写 ProgramCX/GoQQBot 时最看重的调用体验。下面用一个最小示例,演示如何监听 QQ 消息,以及如何通过一次调用发出带按钮的 Markdown 菜单。
项目地址:https://github.com/ProgramCX/GoQQBot
使用文档:https://programcx.github.io/GoQQBot/
监听普通消息,用一行回复
已经初始化好 bot 后,监听 QQ 单聊消息只需要注册一个处理函数:
bot.OnMessage(message.C2C_MESSAGE_CREATE, func(ctx *types.Context) error {
return ctx.ReplyText("收到:" + ctx.Text())
})
OnMessage 的第一个参数是事件类型。这里监听的是普通 QQ 单聊。如果要处理群里 @机器人的消息,就注册 message.GROUP_AT_MESSAGE_CREATE。
ctx.ReplyText 会根据当前事件找到回复对象。因此,同一个处理函数可以同时注册到单聊和群聊。需要读取发送者、消息 ID 或图片附件时,可以从 ctx.Message() 返回的消息结构中取得。
对于 /menu 这种明确的命令,可以用 OnCommand 单独注册。SDK 会先匹配已注册的命令,再将其余消息交给 OnMessage。这样,普通消息处理和具体命令可以分别编写。
一次回复,同时带上 Markdown 和按钮
我希望写菜单时,能从代码里直接看出每个按钮会做什么。比如下面这份菜单有两个按钮:一个把 /help 填入输入框,另一个打开项目文档:
return ctx.ReplyMarkdown(
"## 快捷菜单\n\n请选择下方操作。",
button.Command("帮助", "/help").ID("help").Primary(),
button.Link("项目文档", "https://programcx.github.io/GoQQBot/"),
)
ReplyMarkdown 的第一个参数是 Markdown 正文,后面的参数依次传入按钮。button.Command 描述用户点击后要使用的命令,button.Link 描述要打开的地址。Primary() 用来突出主按钮。
这里的「帮助」按钮走的是消息命令流程。用户点击后,/help 会填入输入框,发送后由 OnCommand("help", ...) 处理。如果你的业务需要在点击时直接收到服务端回调,可以使用回调按钮,再用 OnButton 注册处理函数。按钮交互与回调
跑起来:让单聊和群聊共用一份菜单
准备好 QQ 机器人的 AppID 和 AppSecret 后,在项目目录安装 SDK:
go mod init qq-menu-demo
go get github.com/ProgramCX/GoQQBot@v0.3.0
在 QQ 机器人运营与管理后台选择 WebSocket 接入,再创建 config.yaml。下面的 GROUP_AND_C2C_EVENT 用于本例的 QQ 单聊和群 @消息。连接方式与订阅配置
bot:
appId: "你的 AppID"
appSecret: "你的 AppSecret"
connection:
mode: websocket
websocket:
intents:
- GROUP_AND_C2C_EVENT
把下面的程序保存为 main.go:
package main
import (
"log"
"github.com/ProgramCX/GoQQBot/pkg/goqqrobot"
"github.com/ProgramCX/GoQQBot/pkg/message"
"github.com/ProgramCX/GoQQBot/pkg/message/button"
"github.com/ProgramCX/GoQQBot/shared/types"
)
func main() {
bot, err := goqqrobot.NewBot("config.yaml", nil)
if err != nil {
log.Fatal(err)
}
menu := func(ctx *types.Context) error {
return ctx.ReplyMarkdown(
"## 快捷菜单\n\n请选择下方操作。",
button.Command("帮助", "/help").ID("help").Primary(),
button.Link("项目文档", "https://programcx.github.io/GoQQBot/"),
)
}
help := func(ctx *types.Context) error {
return ctx.ReplyText("发送 /menu 打开快捷菜单。")
}
receive := func(ctx *types.Context) error {
if ctx.Text() == "" {
return nil
}
return ctx.ReplyText("收到:" + ctx.Text())
}
for _, event := range []message.EventId{
message.C2C_MESSAGE_CREATE,
message.GROUP_AT_MESSAGE_CREATE,
} {
bot.OnMessage(event, receive)
bot.OnCommand("menu", event, menu)
bot.OnCommand("help", event, help)
}
if err := bot.StartWithGracefulShutdown(); err != nil {
log.Fatal(err)
}
}
执行 go run .,然后在 QQ 单聊里发一句「你好」,再发送 /menu。第一条会收到普通文本回复,第二条会收到 Markdown 菜单。机器人已加入测试群时,也可以在群里 @机器人 后发送 /menu。两处运行的是同一份 menu 处理函数。
这个例子里,处理函数只负责决定回复内容,SDK 负责根据事件选取发送目标、构造请求,并把发送错误返回给应用。后续要给菜单接上查询、审批或业务服务,可以从这几个处理函数继续写。
GoQQBot 还提供群聊管理、频道管理、富媒体上传和指令面板等接口。如果你已经有 Go 服务,可以先从一个消息处理函数接入,再按业务需要添加其他能力。GitHub 源码与示例
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)