package milky import ( "cellbot/internal/engine" "cellbot/internal/protocol" "cellbot/pkg/net" "context" "fmt" "go.uber.org/zap" ) // Bot Milky Bot 实例 type Bot struct { id string adapter *Adapter logger *zap.Logger status protocol.BotStatus } // NewBot 创建 Milky Bot 实例 func NewBot(id string, config *Config, eventBus *engine.EventBus, wsManager *net.WebSocketManager, logger *zap.Logger) *Bot { adapter := NewAdapter(config, id, eventBus, wsManager, logger) return &Bot{ id: id, adapter: adapter, logger: logger.Named("milky-bot").With(zap.String("bot_id", id)), status: protocol.BotStatusStopped, } } // GetID 获取机器人 ID func (b *Bot) GetID() string { return b.id } // GetProtocol 获取协议名称 func (b *Bot) GetProtocol() string { return "milky" } // Name 获取协议名称 func (b *Bot) Name() string { return "milky" } // Version 获取协议版本 func (b *Bot) Version() string { return "1.0" } // GetSelfID 获取机器人自身ID func (b *Bot) GetSelfID() string { return b.id } // Start 启动实例 func (b *Bot) Start(ctx context.Context) error { return b.Connect(ctx) } // Stop 停止实例 func (b *Bot) Stop(ctx context.Context) error { return b.Disconnect(ctx) } // HandleEvent 处理事件 func (b *Bot) HandleEvent(ctx context.Context, event protocol.Event) error { // Milky 适配器通过事件总线自动处理事件 // 这里不需要额外处理 return nil } // GetStatus 获取状态 func (b *Bot) GetStatus() protocol.BotStatus { return b.status } // Connect 连接 func (b *Bot) Connect(ctx context.Context) error { b.logger.Info("Connecting Milky bot") if err := b.adapter.Connect(ctx); err != nil { b.status = protocol.BotStatusError return fmt.Errorf("failed to connect: %w", err) } b.status = protocol.BotStatusRunning b.logger.Info("Milky bot connected") return nil } // Disconnect 断开连接 func (b *Bot) Disconnect(ctx context.Context) error { b.logger.Info("Disconnecting Milky bot") if err := b.adapter.Disconnect(); err != nil { return fmt.Errorf("failed to disconnect: %w", err) } b.status = protocol.BotStatusStopped b.logger.Info("Milky bot disconnected") return nil } // SendAction 发送动作 func (b *Bot) SendAction(ctx context.Context, action protocol.Action) (map[string]interface{}, error) { if b.status != protocol.BotStatusRunning { return nil, fmt.Errorf("bot is not running") } return b.adapter.SendAction(ctx, action) } // GetAdapter 获取适配器 func (b *Bot) GetAdapter() *Adapter { return b.adapter } // GetInfo 获取机器人信息 func (b *Bot) GetInfo() map[string]interface{} { return map[string]interface{}{ "id": b.id, "protocol": "milky", "status": b.status, "stats": b.adapter.GetStats(), } } // IsConnected 是否已连接 func (b *Bot) IsConnected() bool { return b.status == protocol.BotStatusRunning && b.adapter.IsConnected() } // SetStatus 设置状态 func (b *Bot) SetStatus(status protocol.BotStatus) { b.status = status } // ============================================================================ // Milky 特定的 API 方法 // ============================================================================ // SendPrivateMessage 发送私聊消息 func (b *Bot) SendPrivateMessage(ctx context.Context, userID int64, segments []OutgoingSegment) (*APIResponse, error) { params := map[string]interface{}{ "user_id": userID, "segments": segments, } return b.adapter.CallAPI(ctx, "send_private_message", params) } // SendGroupMessage 发送群消息 func (b *Bot) SendGroupMessage(ctx context.Context, groupID int64, segments []OutgoingSegment) (*APIResponse, error) { params := map[string]interface{}{ "group_id": groupID, "segments": segments, } return b.adapter.CallAPI(ctx, "send_group_message", params) } // SendTempMessage 发送临时消息 func (b *Bot) SendTempMessage(ctx context.Context, groupID, userID int64, segments []OutgoingSegment) (*APIResponse, error) { params := map[string]interface{}{ "group_id": groupID, "user_id": userID, "segments": segments, } return b.adapter.CallAPI(ctx, "send_temp_message", params) } // RecallMessage 撤回消息 func (b *Bot) RecallMessage(ctx context.Context, messageScene string, peerID, messageSeq int64) (*APIResponse, error) { params := map[string]interface{}{ "message_scene": messageScene, "peer_id": peerID, "message_seq": messageSeq, } return b.adapter.CallAPI(ctx, "recall_message", params) } // GetFriendList 获取好友列表 func (b *Bot) GetFriendList(ctx context.Context) (*APIResponse, error) { return b.adapter.CallAPI(ctx, "get_friend_list", nil) } // GetGroupList 获取群列表 func (b *Bot) GetGroupList(ctx context.Context) (*APIResponse, error) { return b.adapter.CallAPI(ctx, "get_group_list", nil) } // GetGroupMemberList 获取群成员列表 func (b *Bot) GetGroupMemberList(ctx context.Context, groupID int64) (*APIResponse, error) { params := map[string]interface{}{ "group_id": groupID, } return b.adapter.CallAPI(ctx, "get_group_member_list", params) } // GetGroupMemberInfo 获取群成员信息 func (b *Bot) GetGroupMemberInfo(ctx context.Context, groupID, userID int64) (*APIResponse, error) { params := map[string]interface{}{ "group_id": groupID, "user_id": userID, } return b.adapter.CallAPI(ctx, "get_group_member_info", params) } // SetGroupAdmin 设置群管理员 func (b *Bot) SetGroupAdmin(ctx context.Context, groupID, userID int64, isSet bool) (*APIResponse, error) { params := map[string]interface{}{ "group_id": groupID, "user_id": userID, "is_set": isSet, } return b.adapter.CallAPI(ctx, "set_group_admin", params) } // SetGroupCard 设置群名片 func (b *Bot) SetGroupCard(ctx context.Context, groupID, userID int64, card string) (*APIResponse, error) { params := map[string]interface{}{ "group_id": groupID, "user_id": userID, "card": card, } return b.adapter.CallAPI(ctx, "set_group_card", params) } // SetGroupName 设置群名 func (b *Bot) SetGroupName(ctx context.Context, groupID int64, groupName string) (*APIResponse, error) { params := map[string]interface{}{ "group_id": groupID, "group_name": groupName, } return b.adapter.CallAPI(ctx, "set_group_name", params) } // KickGroupMember 踢出群成员 func (b *Bot) KickGroupMember(ctx context.Context, groupID, userID int64, rejectAddRequest bool) (*APIResponse, error) { params := map[string]interface{}{ "group_id": groupID, "user_id": userID, "reject_add_request": rejectAddRequest, } return b.adapter.CallAPI(ctx, "kick_group_member", params) } // MuteGroupMember 禁言群成员 func (b *Bot) MuteGroupMember(ctx context.Context, groupID, userID int64, duration int32) (*APIResponse, error) { params := map[string]interface{}{ "group_id": groupID, "user_id": userID, "duration": duration, } return b.adapter.CallAPI(ctx, "mute_group_member", params) } // MuteGroupWhole 全体禁言 func (b *Bot) MuteGroupWhole(ctx context.Context, groupID int64, isMute bool) (*APIResponse, error) { params := map[string]interface{}{ "group_id": groupID, "is_mute": isMute, } return b.adapter.CallAPI(ctx, "mute_group_whole", params) } // LeaveGroup 退出群 func (b *Bot) LeaveGroup(ctx context.Context, groupID int64) (*APIResponse, error) { params := map[string]interface{}{ "group_id": groupID, } return b.adapter.CallAPI(ctx, "leave_group", params) } // HandleFriendRequest 处理好友请求 func (b *Bot) HandleFriendRequest(ctx context.Context, initiatorUID string, accept bool) (*APIResponse, error) { params := map[string]interface{}{ "initiator_uid": initiatorUID, "accept": accept, } return b.adapter.CallAPI(ctx, "handle_friend_request", params) } // HandleGroupJoinRequest 处理入群申请 func (b *Bot) HandleGroupJoinRequest(ctx context.Context, groupID, notificationSeq int64, accept bool, rejectReason string) (*APIResponse, error) { params := map[string]interface{}{ "group_id": groupID, "notification_seq": notificationSeq, "accept": accept, "reject_reason": rejectReason, } return b.adapter.CallAPI(ctx, "handle_group_join_request", params) } // HandleGroupInvitation 处理群邀请 func (b *Bot) HandleGroupInvitation(ctx context.Context, groupID, invitationSeq int64, accept bool) (*APIResponse, error) { params := map[string]interface{}{ "group_id": groupID, "invitation_seq": invitationSeq, "accept": accept, } return b.adapter.CallAPI(ctx, "handle_group_invitation", params) } // UploadFile 上传文件 func (b *Bot) UploadFile(ctx context.Context, fileType, filePath string) (*APIResponse, error) { params := map[string]interface{}{ "file_type": fileType, "file_path": filePath, } return b.adapter.CallAPI(ctx, "upload_file", params) } // GetFile 获取文件 func (b *Bot) GetFile(ctx context.Context, fileID string) (*APIResponse, error) { params := map[string]interface{}{ "file_id": fileID, } return b.adapter.CallAPI(ctx, "get_file", params) }