2025-03-27 16:27:41 +08:00

156 lines
4.6 KiB
Go

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