package docker import ( "context" "encoding/json" "fmt" "gitee.ltd/lxh/wechat-robot/internal/config" "gitee.ltd/lxh/wechat-robot/internal/model" ) const ( // WechatBotLabelKey 微信机器人容器标签键 WechatBotLabelKey = "app.type" // WechatBotLabelValue 微信机器人容器标签值 WechatBotLabelValue = "wechat-bot" ) // APIResponse API响应结构 type APIResponse struct { Success bool `json:"success"` Message string `json:"message"` Data interface{} `json:"data"` } // CreateRobotContainer 创建微信机器人容器 func CreateRobotContainer(ctx context.Context, cfg *config.DockerConfig, robotName string) (string, error) { // 创建容器标签 labels := map[string]string{ WechatBotLabelKey: WechatBotLabelValue, "robot.name": robotName, } // 创建环境变量 env := []string{ "BOT_NAME=" + robotName, } // 创建容器 containerID, err := CreateContainer(ctx, cfg, "wechat-bot-"+robotName, env, labels) if err != nil { return "", err } // 启动容器 err = StartContainer(ctx, containerID) if err != nil { // 如果启动失败,尝试删除容器 RemoveContainer(ctx, containerID, true) return "", err } return containerID, nil } // GetLoginQRCode 获取登录二维码 func GetLoginQRCode(ctx context.Context, containerID string) (string, error) { // 使用新的ExecuteCommandWithOutput函数 return ExecuteCommandWithOutput(ctx, containerID, []string{"cat", "/data/qrcode.png"}) } // LogoutWechatBot 登出微信机器人 func LogoutWechatBot(ctx context.Context, containerID string) error { // 使用新的ExecuteCommandWithOutput函数 output, err := ExecuteCommandWithOutput(ctx, containerID, []string{"curl", "-X", "POST", "http://localhost:3000/api/logout"}) if err != nil { return fmt.Errorf("failed to execute logout command: %w", err) } // 解析API响应 var response APIResponse if err := json.Unmarshal([]byte(output), &response); err != nil { return fmt.Errorf("failed to parse logout response: %w", err) } if !response.Success { return fmt.Errorf("logout failed: %s", response.Message) } return nil } // GetWechatBotStatus 获取微信机器人状态 func GetWechatBotStatus(ctx context.Context, containerID string) (model.RobotStatus, string, error) { // 检查容器状态 status, err := GetContainerStatus(ctx, containerID) if err != nil { return model.RobotStatusError, "", fmt.Errorf("failed to get container status: %w", err) } if status != "running" { return model.RobotStatusOffline, "", nil } // 使用新的ExecuteCommandWithOutput函数 output, err := ExecuteCommandWithOutput(ctx, containerID, []string{"curl", "http://localhost:3000/api/status"}) if err != nil { return model.RobotStatusError, "", fmt.Errorf("failed to get status result: %w", err) } // 解析API响应 var response APIResponse if err := json.Unmarshal([]byte(output), &response); err != nil { return model.RobotStatusError, "", fmt.Errorf("failed to parse status response: %w", err) } if !response.Success { return model.RobotStatusError, response.Message, nil } // 解析状态数据 data, ok := response.Data.(map[string]interface{}) if !ok { return model.RobotStatusError, "invalid status data format", nil } isLoggedIn, ok := data["isLoggedIn"].(bool) if !ok { return model.RobotStatusError, "invalid login status format", nil } if isLoggedIn { return model.RobotStatusOnline, "", nil } return model.RobotStatusOffline, "", nil } // ListWechatBots 列出所有微信机器人容器 func ListWechatBots(ctx context.Context) ([]ContainerInfo, error) { // 过滤条件:所有微信机器人容器 filter := map[string][]string{ "label": {fmt.Sprintf("%s=%s", WechatBotLabelKey, WechatBotLabelValue)}, } return ListContainers(ctx, filter) } // GetWechatContacts 获取微信联系人列表 func GetWechatContacts(ctx context.Context, containerID string) (string, error) { return ExecuteCommandWithOutput(ctx, containerID, []string{"curl", "http://localhost:3000/api/contacts"}) } // GetWechatGroupMembers 获取微信群成员 func GetWechatGroupMembers(ctx context.Context, containerID string, groupID string) (string, error) { return ExecuteCommandWithOutput(ctx, containerID, []string{ "curl", fmt.Sprintf("http://localhost:3000/api/group/%s/members", groupID), }) } // GetWechatMessages 获取微信消息历史 func GetWechatMessages(ctx context.Context, containerID string, contactID string, limit int) (string, error) { return ExecuteCommandWithOutput(ctx, containerID, []string{ "curl", fmt.Sprintf("http://localhost:3000/api/messages/%s?limit=%d", contactID, limit), }) }