refactor: modernize codebase for Go 1.26 and fix adapter issues

- Upgrade Go version from 1.24 to 1.26.1 with updated dependencies
- Replace interface{} with any type throughout codebase
- Add message deduplication in OneBot11 adapter to prevent duplicate event processing
- URL-encode access token in WebSocket connections to handle special characters
- Remove duplicate bot startup hooks in DI providers (now handled by botManager.StartAll)
- Use slices.Clone and errgroup.Go patterns for cleaner concurrent code
- Apply omitzero JSON tags for optional fields (Go 1.24+ feature)
This commit is contained in:
lafay
2026-03-18 01:22:49 +08:00
parent f3a72264af
commit f3220a2381
32 changed files with 2262 additions and 296 deletions

View File

@@ -225,7 +225,7 @@ func (a *Adapter) handleEvents(eventChan <-chan []byte) {
}
// SendAction 发送动作
func (a *Adapter) SendAction(ctx context.Context, action protocol.Action) (map[string]interface{}, error) {
func (a *Adapter) SendAction(ctx context.Context, action protocol.Action) (map[string]any, error) {
// 调用 API
resp, err := a.apiClient.Call(ctx, string(action.GetType()), action.GetParams())
if err != nil {
@@ -303,8 +303,8 @@ func (a *Adapter) IsConnected() bool {
}
// GetStats 获取统计信息
func (a *Adapter) GetStats() map[string]interface{} {
stats := map[string]interface{}{
func (a *Adapter) GetStats() map[string]any {
stats := map[string]any{
"protocol": "milky",
"self_id": a.selfID,
"event_mode": a.config.EventMode,
@@ -320,7 +320,7 @@ func (a *Adapter) GetStats() map[string]interface{} {
}
// CallAPI 直接调用 API提供给 Bot 使用)
func (a *Adapter) CallAPI(ctx context.Context, endpoint string, params map[string]interface{}) (*APIResponse, error) {
func (a *Adapter) CallAPI(ctx context.Context, endpoint string, params map[string]any) (*APIResponse, error) {
return a.apiClient.Call(ctx, endpoint, params)
}

View File

@@ -47,7 +47,7 @@ func NewAPIClient(baseURL, accessToken string, timeout time.Duration, retryCount
// endpoint: API 端点名称(如 "send_private_message"
// input: 输入参数(会被序列化为 JSON
// 返回: 响应数据和错误
func (c *APIClient) Call(ctx context.Context, endpoint string, input interface{}) (*APIResponse, error) {
func (c *APIClient) Call(ctx context.Context, endpoint string, input any) (*APIResponse, error) {
// 序列化输入参数
var inputData []byte
var err error
@@ -126,7 +126,7 @@ func (c *APIClient) doRequest(ctx context.Context, url string, inputData []byte)
// CallWithoutRetry 调用 API不重试
// 注意pkg/net.HTTPClient 的通用请求已经内置了重试机制
// 这个方法保留是为了向后兼容,但仍然会使用底层的重试机制
func (c *APIClient) CallWithoutRetry(ctx context.Context, endpoint string, input interface{}) (*APIResponse, error) {
func (c *APIClient) CallWithoutRetry(ctx context.Context, endpoint string, input any) (*APIResponse, error) {
return c.Call(ctx, endpoint, input)
}

View File

@@ -105,7 +105,7 @@ func (b *Bot) Disconnect(ctx context.Context) error {
}
// SendAction 发送动作
func (b *Bot) SendAction(ctx context.Context, action protocol.Action) (map[string]interface{}, error) {
func (b *Bot) SendAction(ctx context.Context, action protocol.Action) (map[string]any, error) {
if b.status != protocol.BotStatusRunning {
return nil, fmt.Errorf("bot is not running")
}
@@ -119,8 +119,8 @@ func (b *Bot) GetAdapter() *Adapter {
}
// GetInfo 获取机器人信息
func (b *Bot) GetInfo() map[string]interface{} {
return map[string]interface{}{
func (b *Bot) GetInfo() map[string]any {
return map[string]any{
"id": b.id,
"protocol": "milky",
"status": b.status,
@@ -144,7 +144,7 @@ func (b *Bot) SetStatus(status protocol.BotStatus) {
// SendPrivateMessage 发送私聊消息
func (b *Bot) SendPrivateMessage(ctx context.Context, userID int64, segments []OutgoingSegment) (*APIResponse, error) {
params := map[string]interface{}{
params := map[string]any{
"user_id": userID,
"segments": segments,
}
@@ -153,7 +153,7 @@ func (b *Bot) SendPrivateMessage(ctx context.Context, userID int64, segments []O
// SendGroupMessage 发送群消息
func (b *Bot) SendGroupMessage(ctx context.Context, groupID int64, segments []OutgoingSegment) (*APIResponse, error) {
params := map[string]interface{}{
params := map[string]any{
"group_id": groupID,
"segments": segments,
}
@@ -162,7 +162,7 @@ func (b *Bot) SendGroupMessage(ctx context.Context, groupID int64, segments []Ou
// SendTempMessage 发送临时消息
func (b *Bot) SendTempMessage(ctx context.Context, groupID, userID int64, segments []OutgoingSegment) (*APIResponse, error) {
params := map[string]interface{}{
params := map[string]any{
"group_id": groupID,
"user_id": userID,
"segments": segments,
@@ -172,7 +172,7 @@ func (b *Bot) SendTempMessage(ctx context.Context, groupID, userID int64, segmen
// RecallMessage 撤回消息
func (b *Bot) RecallMessage(ctx context.Context, messageScene string, peerID, messageSeq int64) (*APIResponse, error) {
params := map[string]interface{}{
params := map[string]any{
"message_scene": messageScene,
"peer_id": peerID,
"message_seq": messageSeq,
@@ -192,7 +192,7 @@ func (b *Bot) GetGroupList(ctx context.Context) (*APIResponse, error) {
// GetGroupMemberList 获取群成员列表
func (b *Bot) GetGroupMemberList(ctx context.Context, groupID int64) (*APIResponse, error) {
params := map[string]interface{}{
params := map[string]any{
"group_id": groupID,
}
return b.adapter.CallAPI(ctx, "get_group_member_list", params)
@@ -200,7 +200,7 @@ func (b *Bot) GetGroupMemberList(ctx context.Context, groupID int64) (*APIRespon
// GetGroupMemberInfo 获取群成员信息
func (b *Bot) GetGroupMemberInfo(ctx context.Context, groupID, userID int64) (*APIResponse, error) {
params := map[string]interface{}{
params := map[string]any{
"group_id": groupID,
"user_id": userID,
}
@@ -209,7 +209,7 @@ func (b *Bot) GetGroupMemberInfo(ctx context.Context, groupID, userID int64) (*A
// SetGroupAdmin 设置群管理员
func (b *Bot) SetGroupAdmin(ctx context.Context, groupID, userID int64, isSet bool) (*APIResponse, error) {
params := map[string]interface{}{
params := map[string]any{
"group_id": groupID,
"user_id": userID,
"is_set": isSet,
@@ -219,7 +219,7 @@ func (b *Bot) SetGroupAdmin(ctx context.Context, groupID, userID int64, isSet bo
// SetGroupCard 设置群名片
func (b *Bot) SetGroupCard(ctx context.Context, groupID, userID int64, card string) (*APIResponse, error) {
params := map[string]interface{}{
params := map[string]any{
"group_id": groupID,
"user_id": userID,
"card": card,
@@ -229,7 +229,7 @@ func (b *Bot) SetGroupCard(ctx context.Context, groupID, userID int64, card stri
// SetGroupName 设置群名
func (b *Bot) SetGroupName(ctx context.Context, groupID int64, groupName string) (*APIResponse, error) {
params := map[string]interface{}{
params := map[string]any{
"group_id": groupID,
"group_name": groupName,
}
@@ -238,7 +238,7 @@ func (b *Bot) SetGroupName(ctx context.Context, groupID int64, groupName string)
// KickGroupMember 踢出群成员
func (b *Bot) KickGroupMember(ctx context.Context, groupID, userID int64, rejectAddRequest bool) (*APIResponse, error) {
params := map[string]interface{}{
params := map[string]any{
"group_id": groupID,
"user_id": userID,
"reject_add_request": rejectAddRequest,
@@ -248,7 +248,7 @@ func (b *Bot) KickGroupMember(ctx context.Context, groupID, userID int64, reject
// MuteGroupMember 禁言群成员
func (b *Bot) MuteGroupMember(ctx context.Context, groupID, userID int64, duration int32) (*APIResponse, error) {
params := map[string]interface{}{
params := map[string]any{
"group_id": groupID,
"user_id": userID,
"duration": duration,
@@ -258,7 +258,7 @@ func (b *Bot) MuteGroupMember(ctx context.Context, groupID, userID int64, durati
// MuteGroupWhole 全体禁言
func (b *Bot) MuteGroupWhole(ctx context.Context, groupID int64, isMute bool) (*APIResponse, error) {
params := map[string]interface{}{
params := map[string]any{
"group_id": groupID,
"is_mute": isMute,
}
@@ -267,7 +267,7 @@ func (b *Bot) MuteGroupWhole(ctx context.Context, groupID int64, isMute bool) (*
// LeaveGroup 退出群
func (b *Bot) LeaveGroup(ctx context.Context, groupID int64) (*APIResponse, error) {
params := map[string]interface{}{
params := map[string]any{
"group_id": groupID,
}
return b.adapter.CallAPI(ctx, "leave_group", params)
@@ -275,7 +275,7 @@ func (b *Bot) LeaveGroup(ctx context.Context, groupID int64) (*APIResponse, erro
// HandleFriendRequest 处理好友请求
func (b *Bot) HandleFriendRequest(ctx context.Context, initiatorUID string, accept bool) (*APIResponse, error) {
params := map[string]interface{}{
params := map[string]any{
"initiator_uid": initiatorUID,
"accept": accept,
}
@@ -284,7 +284,7 @@ func (b *Bot) HandleFriendRequest(ctx context.Context, initiatorUID string, acce
// HandleGroupJoinRequest 处理入群申请
func (b *Bot) HandleGroupJoinRequest(ctx context.Context, groupID, notificationSeq int64, accept bool, rejectReason string) (*APIResponse, error) {
params := map[string]interface{}{
params := map[string]any{
"group_id": groupID,
"notification_seq": notificationSeq,
"accept": accept,
@@ -295,7 +295,7 @@ func (b *Bot) HandleGroupJoinRequest(ctx context.Context, groupID, notificationS
// HandleGroupInvitation 处理群邀请
func (b *Bot) HandleGroupInvitation(ctx context.Context, groupID, invitationSeq int64, accept bool) (*APIResponse, error) {
params := map[string]interface{}{
params := map[string]any{
"group_id": groupID,
"invitation_seq": invitationSeq,
"accept": accept,
@@ -305,7 +305,7 @@ func (b *Bot) HandleGroupInvitation(ctx context.Context, groupID, invitationSeq
// UploadFile 上传文件
func (b *Bot) UploadFile(ctx context.Context, fileType, filePath string) (*APIResponse, error) {
params := map[string]interface{}{
params := map[string]any{
"file_type": fileType,
"file_path": filePath,
}
@@ -314,7 +314,7 @@ func (b *Bot) UploadFile(ctx context.Context, fileType, filePath string) (*APIRe
// GetFile 获取文件
func (b *Bot) GetFile(ctx context.Context, fileID string) (*APIResponse, error) {
params := map[string]interface{}{
params := map[string]any{
"file_id": fileID,
}
return b.adapter.CallAPI(ctx, "get_file", params)

View File

@@ -101,7 +101,7 @@ func (c *EventConverter) convertMessageEvent(milkyEvent *Event) (protocol.Event,
SubType: "",
Timestamp: milkyEvent.Time,
SelfID: selfID,
Data: map[string]interface{}{
Data: map[string]any{
"peer_id": msgData.PeerID,
"message_seq": msgData.MessageSeq,
"sender_id": msgData.SenderID,
@@ -145,7 +145,7 @@ func (c *EventConverter) convertFriendRequestEvent(milkyEvent *Event) (protocol.
SubType: "",
Timestamp: milkyEvent.Time,
SelfID: selfID,
Data: map[string]interface{}{
Data: map[string]any{
"initiator_id": data.InitiatorID,
"initiator_uid": data.InitiatorUID,
"comment": data.Comment,
@@ -178,7 +178,7 @@ func (c *EventConverter) convertGroupJoinRequestEvent(milkyEvent *Event) (protoc
SubType: "add",
Timestamp: milkyEvent.Time,
SelfID: selfID,
Data: map[string]interface{}{
Data: map[string]any{
"group_id": data.GroupID,
"notification_seq": data.NotificationSeq,
"is_filtered": data.IsFiltered,
@@ -212,7 +212,7 @@ func (c *EventConverter) convertGroupInvitedJoinRequestEvent(milkyEvent *Event)
SubType: "invite",
Timestamp: milkyEvent.Time,
SelfID: selfID,
Data: map[string]interface{}{
Data: map[string]any{
"group_id": data.GroupID,
"notification_seq": data.NotificationSeq,
"initiator_id": data.InitiatorID,
@@ -245,7 +245,7 @@ func (c *EventConverter) convertGroupInvitationEvent(milkyEvent *Event) (protoco
SubType: "invite_self",
Timestamp: milkyEvent.Time,
SelfID: selfID,
Data: map[string]interface{}{
Data: map[string]any{
"group_id": data.GroupID,
"invitation_seq": data.InvitationSeq,
"initiator_id": data.InitiatorID,
@@ -277,7 +277,7 @@ func (c *EventConverter) convertMessageRecallEvent(milkyEvent *Event) (protocol.
SubType: data.MessageScene,
Timestamp: milkyEvent.Time,
SelfID: selfID,
Data: map[string]interface{}{
Data: map[string]any{
"message_scene": data.MessageScene,
"peer_id": data.PeerID,
"message_seq": data.MessageSeq,
@@ -310,7 +310,7 @@ func (c *EventConverter) convertBotOfflineEvent(milkyEvent *Event) (protocol.Eve
SubType: "",
Timestamp: milkyEvent.Time,
SelfID: selfID,
Data: map[string]interface{}{
Data: map[string]any{
"reason": data.Reason,
},
},
@@ -337,7 +337,7 @@ func (c *EventConverter) convertFriendNudgeEvent(milkyEvent *Event) (protocol.Ev
SubType: "",
Timestamp: milkyEvent.Time,
SelfID: selfID,
Data: map[string]interface{}(milkyEvent.Data),
Data: map[string]any(milkyEvent.Data),
},
UserID: strconv.FormatInt(data.UserID, 10),
}
@@ -362,7 +362,7 @@ func (c *EventConverter) convertFriendFileUploadEvent(milkyEvent *Event) (protoc
SubType: "",
Timestamp: milkyEvent.Time,
SelfID: selfID,
Data: map[string]interface{}(milkyEvent.Data),
Data: map[string]any(milkyEvent.Data),
},
UserID: strconv.FormatInt(data.UserID, 10),
}
@@ -392,7 +392,7 @@ func (c *EventConverter) convertGroupAdminChangeEvent(milkyEvent *Event) (protoc
SubType: subType,
Timestamp: milkyEvent.Time,
SelfID: selfID,
Data: map[string]interface{}(milkyEvent.Data),
Data: map[string]any(milkyEvent.Data),
},
GroupID: strconv.FormatInt(data.GroupID, 10),
UserID: strconv.FormatInt(data.UserID, 10),
@@ -423,7 +423,7 @@ func (c *EventConverter) convertGroupEssenceMessageChangeEvent(milkyEvent *Event
SubType: subType,
Timestamp: milkyEvent.Time,
SelfID: selfID,
Data: map[string]interface{}(milkyEvent.Data),
Data: map[string]any(milkyEvent.Data),
},
GroupID: strconv.FormatInt(data.GroupID, 10),
}
@@ -448,7 +448,7 @@ func (c *EventConverter) convertGroupMemberIncreaseEvent(milkyEvent *Event) (pro
SubType: "",
Timestamp: milkyEvent.Time,
SelfID: selfID,
Data: map[string]interface{}(milkyEvent.Data),
Data: map[string]any(milkyEvent.Data),
},
GroupID: strconv.FormatInt(data.GroupID, 10),
UserID: strconv.FormatInt(data.UserID, 10),
@@ -478,7 +478,7 @@ func (c *EventConverter) convertGroupMemberDecreaseEvent(milkyEvent *Event) (pro
SubType: "",
Timestamp: milkyEvent.Time,
SelfID: selfID,
Data: map[string]interface{}(milkyEvent.Data),
Data: map[string]any(milkyEvent.Data),
},
GroupID: strconv.FormatInt(data.GroupID, 10),
UserID: strconv.FormatInt(data.UserID, 10),
@@ -508,7 +508,7 @@ func (c *EventConverter) convertGroupNameChangeEvent(milkyEvent *Event) (protoco
SubType: "",
Timestamp: milkyEvent.Time,
SelfID: selfID,
Data: map[string]interface{}(milkyEvent.Data),
Data: map[string]any(milkyEvent.Data),
},
GroupID: strconv.FormatInt(data.GroupID, 10),
Operator: strconv.FormatInt(data.OperatorID, 10),
@@ -539,7 +539,7 @@ func (c *EventConverter) convertGroupMessageReactionEvent(milkyEvent *Event) (pr
SubType: subType,
Timestamp: milkyEvent.Time,
SelfID: selfID,
Data: map[string]interface{}(milkyEvent.Data),
Data: map[string]any(milkyEvent.Data),
},
GroupID: strconv.FormatInt(data.GroupID, 10),
UserID: strconv.FormatInt(data.UserID, 10),
@@ -570,7 +570,7 @@ func (c *EventConverter) convertGroupMuteEvent(milkyEvent *Event) (protocol.Even
SubType: subType,
Timestamp: milkyEvent.Time,
SelfID: selfID,
Data: map[string]interface{}(milkyEvent.Data),
Data: map[string]any(milkyEvent.Data),
},
GroupID: strconv.FormatInt(data.GroupID, 10),
UserID: strconv.FormatInt(data.UserID, 10),
@@ -602,7 +602,7 @@ func (c *EventConverter) convertGroupWholeMuteEvent(milkyEvent *Event) (protocol
SubType: subType,
Timestamp: milkyEvent.Time,
SelfID: selfID,
Data: map[string]interface{}(milkyEvent.Data),
Data: map[string]any(milkyEvent.Data),
},
GroupID: strconv.FormatInt(data.GroupID, 10),
Operator: strconv.FormatInt(data.OperatorID, 10),
@@ -628,7 +628,7 @@ func (c *EventConverter) convertGroupNudgeEvent(milkyEvent *Event) (protocol.Eve
SubType: "",
Timestamp: milkyEvent.Time,
SelfID: selfID,
Data: map[string]interface{}(milkyEvent.Data),
Data: map[string]any(milkyEvent.Data),
},
GroupID: strconv.FormatInt(data.GroupID, 10),
UserID: strconv.FormatInt(data.SenderID, 10),
@@ -654,7 +654,7 @@ func (c *EventConverter) convertGroupFileUploadEvent(milkyEvent *Event) (protoco
SubType: "",
Timestamp: milkyEvent.Time,
SelfID: selfID,
Data: map[string]interface{}(milkyEvent.Data),
Data: map[string]any(milkyEvent.Data),
},
GroupID: strconv.FormatInt(data.GroupID, 10),
UserID: strconv.FormatInt(data.UserID, 10),

View File

@@ -25,14 +25,14 @@ type Boolean = bool
// IncomingSegment 接收消息段(联合类型)
type IncomingSegment struct {
Type string `json:"type"`
Data map[string]interface{} `json:"data"`
Type string `json:"type"`
Data map[string]any `json:"data"`
}
// OutgoingSegment 发送消息段(联合类型)
type OutgoingSegment struct {
Type string `json:"type"`
Data map[string]interface{} `json:"data"`
Type string `json:"type"`
Data map[string]any `json:"data"`
}
// IncomingForwardedMessage 接收转发消息
@@ -318,10 +318,10 @@ type GroupFileUploadEventData struct {
// Event Milky 事件(联合类型,使用 event_type 区分)
type Event struct {
EventType string `json:"event_type"`
Time int64 `json:"time"`
SelfID int64 `json:"self_id"`
Data map[string]interface{} `json:"data"`
EventType string `json:"event_type"`
Time int64 `json:"time"`
SelfID int64 `json:"self_id"`
Data map[string]any `json:"data"`
}
// 事件类型常量
@@ -353,10 +353,10 @@ const (
// APIResponse API 响应
type APIResponse struct {
Status string `json:"status"` // ok, failed
RetCode int `json:"retcode"`
Data map[string]interface{} `json:"data,omitempty"`
Message string `json:"message,omitempty"`
Status string `json:"status"` // ok, failed
RetCode int `json:"retcode"`
Data map[string]any `json:"data,omitempty"`
Message string `json:"message,omitempty"`
}
// 响应状态码