imbot-sdk-go 是 JuggleIM 的 Go SDK,基于 WebSocket 与 IM 服务建立长连接,适合 Bot、服务端消息代理或需要主动收发消息的 Go 程序。
当前代码已经覆盖了连接管理、消息收发、会话查询、历史消息、聊天室、用户状态、RTC 房间和文件凭证查询等常用能力。
go get github.com/juggleim/imbot-sdk-go- 连接管理:
Connect、Disconnect、Logout、心跳保活、断线自动重连 - 消息收发:单聊、群聊、聊天室、公共频道消息发送与接收
- 消息管理:历史消息查询、撤回、修改、已读标记、搜索、置顶消息
- 会话管理:会话列表、未读数、置顶、免打扰、标签
- 用户与群信息:用户资料、好友资料、群信息、在线状态订阅
- 聊天室:加入/退出聊天室、聊天室消息、聊天室属性同步
- RTC:创建/加入/查询/退出 RTC 房间
- 文件:文件凭证查询
GetFileCred
client := imbotclients.NewImBotClient("ws://127.0.0.1:9002", "your-appkey")说明:
NewImBotClient初始化的是 WebSocket 形态客户端;Webhook 形态见下文 Webhook 模式address传基础地址即可,SDK 会自动拼接为ws://host/imbot或wss://host/imbotPlatform默认是BotAutoReconnect默认是true
code, ack := client.Connect("your-token")说明:
- 连接成功时
code == utils.ClientErrorCode_Success - 成功后
ack.UserId会写入client.UserId Connect只能在断开状态下调用;重复连接会返回ClientErrorCode_ConnectExisted- 主动调用
Disconnect()或Logout()后,不会继续自动重连
推荐优先使用高层监听:
AddMessageListener(listener):收到的是已经解码后的*models.Message
如果你想拿到底层 protobuf 数据:
client.OnMessageCallBack = func(msg *pbobjs.DownMsg) {}client.OnStreamMsgCallBack = func(msg *pbobjs.StreamDownMsg) {}
发送消息的核心方法是:
code, ack := client.SendMessage(conversation, upMsg)其中:
conversation用来指定目标会话和会话类型upMsg是 protobuf 上行消息体- 成功后可以从
ack.MsgId、ack.MsgSeqNo中拿到服务端确认结果
下面是一个完整的示例:连接 IM,监听文本消息,并向单聊会话发送一条文本消息。
package main
import (
"fmt"
"log"
"os"
"os/signal"
"syscall"
"time"
"github.com/juggleim/imbot-sdk-go/imbotclients"
"github.com/juggleim/imbot-sdk-go/imbotclients/pbdefines/pbobjs"
"github.com/juggleim/imbot-sdk-go/models"
"github.com/juggleim/imbot-sdk-go/models/messages"
"github.com/juggleim/imbot-sdk-go/utils"
)
type connListener struct{}
func (connListener) OnStatusChange(status utils.ConnectState, code utils.ClientErrorCode) {
log.Printf("connection status changed: status=%d code=%d", status, code)
}
type messageListener struct{}
func (messageListener) OnMessageReceive(msg *models.Message) {
switch content := msg.MsgContent.(type) {
case *messages.TextMessage:
log.Printf(
"received text message: from=%s target=%s msgId=%s content=%s",
msg.SenderId,
msg.Conversation.Conversation,
msg.MsgId,
content.Content,
)
default:
log.Printf(
"received message: from=%s target=%s msgId=%s type=%s",
msg.SenderId,
msg.Conversation.Conversation,
msg.MsgId,
msg.MsgType,
)
}
}
func (messageListener) OnMessageRecall(msg *models.Message) {}
func (messageListener) OnMessageUpdate(msg *models.Message) {}
func (messageListener) OnMessageDelete(conver *models.Conversation, msgIds []string) {}
func (messageListener) OnMessageClear(conver *models.Conversation, t int64, senderId string) {}
func (messageListener) OnMessageReactionAdd(conver *models.Conversation, reaction *models.MessageReaction) {}
func (messageListener) OnMessageReactionRemove(conver *models.Conversation, reaction *models.MessageReaction) {}
func (messageListener) OnMessageSetTop(message *models.Message, operatorId string, isTop bool) {}
func main() {
address := "ws://127.0.0.1:9002"
appKey := "your-appkey"
token := "your-token"
targetUserID := "target-user-id"
client := imbotclients.NewImBotClient(address, appKey)
client.AddConnectionStatusChangeListener(connListener{})
client.AddMessageListener(messageListener{})
client.DisconnectCallback = func(code utils.ClientErrorCode, disMsg *pbobjs.DisconnectMsgBody) {
log.Printf("disconnect: code=%d ext=%s", code, disMsg.GetExt())
}
code, ack := client.Connect(token)
if code != utils.ClientErrorCode_Success {
log.Fatalf("connect failed: code=%d", code)
}
log.Printf("connected: userId=%s session=%s", ack.UserId, ack.Session)
defer client.Disconnect()
text := messages.NewTextMessage("hello from imbot-sdk-go")
payload, err := text.Encode()
if err != nil {
log.Fatalf("encode message failed: %v", err)
}
conversation := &models.Conversation{
ConversationType: pbobjs.ChannelType_Private,
Conversation: targetUserID,
}
upMsg := &pbobjs.UpMsg{
MsgType: text.GetContentType(),
MsgContent: payload,
Flags: int32(text.GetFlags()),
ClientUid: fmt.Sprintf("bot-%d", time.Now().UnixNano()),
}
sendCode, sendAck := client.SendMessage(conversation, upMsg)
if sendCode != utils.ClientErrorCode_Success {
log.Fatalf("send message failed: code=%d", sendCode)
}
log.Printf("send success: msgId=%s seq=%d", sendAck.MsgId, sendAck.MsgSeqNo)
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)
<-sigCh
}补充说明:
- 单聊发送时使用
pbobjs.ChannelType_Private - 群聊发送时改为
pbobjs.ChannelType_Group - 聊天室消息可以直接调用
SendChatroomMsg(chatroomId, upMsg) - 接收到的
msg.MsgContent已经按消息类型解码,可以直接做类型断言
SDK 当前内置了这些消息内容模型,位于 models/messages:
- 文本:
jg:text - 图片:
jg:img - 文件:
jg:file - 视频:
jg:video - 语音:
jg:voice - 流式文本:
jg:streamtext - 撤回通知:
jg:recallinfo - 合并消息:
jg:merge - 缩略图打包图片:
jg:tpimg - 快照打包视频:
jg:spvideo
如果收到未内置支持的消息类型,SDK 会回落为 *messages.UnknownMessage。
Connect(token string)Reconnect()Disconnect()Logout()Ping()AddConnectionStatusChangeListener(listener)
SendMessage(conversation, upMsg)QryHistoryMsgs(req)RecallMsg(req)ModifyMsg(req)MarkReadMsg(req)MsgSearch(req)MsgGlobalSearch(req)SetTopMsg(req)DelTopMsg(req)
GetConversation(req)GetConversations(req)SyncConversations(req)ClearUnreadCount(req)SetConversationTop(req)SetMute(req)DeleteConversations(req)
FetchUserInfo(userId)FetchGroupInfo(groupId)FetchFriendInfo(friendUserId)GetUserStatus(req)SubscribeUserStatus(req)UnsubscribeUserStatus(req)
JoinChatroom(chatroomId)QuitChatroom(chatroomId)SendChatroomMsg(chatroomId, upMsg)SetAttributes(chatroomId, attributes)RemoveAttributes(chatroomId, keys)
CreateRtcRoom(req)JoinRtcRoom(req)QryRtcRoom(roomId)QuitRtcRoom(roomId)RtcInvite(req)
GetFileCred(req)
说明:当前 SDK 提供的是文件凭证查询能力,文件上传/下载流程需要由业务侧结合存储服务自行处理。
除了 WebSocket 长连接,SDK 还支持 HTTP + Webhook 模式:主动能力(发消息、查用户、配置回调)通过 HTTP 调用服务端 botapigateway,被动接收消息由 SDK 内置的 HTTP server 接收 IM 服务推送的回调。
WebSocket 与 Webhook 两种实现分别位于 imbotclients/ 与 webhookclients/ 两个独立目录,互不依赖。Webhook 形态用 webhookclients.NewImBotWebhookClient 初始化,直接传入 baseURL、appKey、token,无需调用 Connect。
c := webhookclients.NewImBotWebhookClient("http://127.0.0.1:8080", "your-appkey", "your-token")
c.ApiKey = "your-webhook-apikey" // 校验回调请求头 Authorization: Bearer <ApiKey>
code, self := c.QryUserInfo("") // 查询 Bot 自身资料
c.SetWebhook("http://your-bot-host:9000/callback", c.ApiKey, false) // 配置对外回调地址
c.AddMessageListener(inboundListener{}) // webhookclients.IInboundMessageListener
go c.StartReceiver(":9000", "/callback") // 或用 c.Handler() 挂到已有 mux
code, ack := c.SendMessage(conversation, upMsg) // 与 WebSocket 端相同的 (conversation, *pbobjs.UpMsg)webhook 模式可用的网关接口:SendMessage、QryUserInfo、SetWebhook、GetWebhook、DelWebhook。
注意:回调载荷不包含群会话 id(
receiver为 Bot 自身),解码出的Conversation取消息发送方,适用于单聊回复;群聊回复请在调用SendMessage时显式指定群会话。
Publish和Query都要求当前连接状态为connected,否则会返回ClientErrorCode_ConnectClosed- 发送和查询默认等待 10 秒 ACK,超时分别返回
ClientErrorCode_SendTimeout、ClientErrorCode_QueryTimeout - SDK 内部会自动处理心跳;如果连续超过两个心跳周期未收到下行数据,会断开并尝试自动重连
- 消息监听回调里尽量不要执行长时间阻塞操作,必要时请自行起 goroutine 或投递到工作队列
- 图片、文件、语音、视频等消息体只负责内容编解码,不负责上传文件本身