Files

322 lines
8.9 KiB
Go
Raw Permalink Normal View History

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)
}