package handler import ( "context" "encoding/json" "strconv" "time" "github.com/gofiber/fiber/v2" "gorm.io/gorm" "gitee.ltd/lxh/wechat-robot/internal/docker" "gitee.ltd/lxh/wechat-robot/internal/model" ) // ListContacts 列出机器人的联系人 func ListContacts(c *fiber.Ctx) error { robotID, err := strconv.Atoi(c.Params("id")) if err != nil { return fiber.NewError(fiber.StatusBadRequest, "无效的机器人ID") } var robot model.Robot db := model.GetDB() if err := db.First(&robot, robotID).Error; err != nil { if err == gorm.ErrRecordNotFound { return fiber.NewError(fiber.StatusNotFound, "机器人不存在") } return fiber.NewError(fiber.StatusInternalServerError, "查询数据库失败") } // 获取联系人列表 var contacts []model.Contact if err := db.Where("robot_id = ?", robotID).Find(&contacts).Error; err != nil { return fiber.NewError(fiber.StatusInternalServerError, "获取联系人列表失败") } // 如果机器人在线并且没有联系人,则从机器人获取最新联系人 if robot.Status == model.RobotStatusOnline && len(contacts) == 0 { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() // 调用Docker API获取联系人,传递容器访问地址 contactsData, err := docker.GetWechatContacts(ctx, robot.ContainerID, robot.ContainerHost) if err != nil { return fiber.NewError(fiber.StatusInternalServerError, "从机器人获取联系人失败: "+err.Error()) } // 解析联系人数据 var response docker.APIResponse if err := json.Unmarshal([]byte(contactsData), &response); err != nil { return fiber.NewError(fiber.StatusInternalServerError, "解析联系人数据失败: "+err.Error()) } // 保存联系人到数据库 if response.Success { contactList, ok := response.Data.([]interface{}) if ok { for _, c := range contactList { contactMap, ok := c.(map[string]interface{}) if !ok { continue } contact := model.Contact{ RobotID: uint(robotID), WechatID: contactMap["id"].(string), Nickname: contactMap["name"].(string), Avatar: contactMap["avatar"].(string), Type: model.ContactTypeFriend, } if contactMap["type"].(string) == "group" { contact.Type = model.ContactTypeGroup } db.Create(&contact) contacts = append(contacts, contact) } } } } return c.Render("contact/index", fiber.Map{ "Title": "联系人列表", "Robot": robot, "Contacts": contacts, }) } // ShowContact 显示联系人详情与聊天记录 func ShowContact(c *fiber.Ctx) error { robotID, err := strconv.Atoi(c.Params("id")) if err != nil { return fiber.NewError(fiber.StatusBadRequest, "无效的机器人ID") } contactID, err := strconv.Atoi(c.Params("contactId")) if err != nil { return fiber.NewError(fiber.StatusBadRequest, "无效的联系人ID") } db := model.GetDB() // 获取机器人信息 var robot model.Robot if err := db.First(&robot, robotID).Error; err != nil { if err == gorm.ErrRecordNotFound { return fiber.NewError(fiber.StatusNotFound, "机器人不存在") } return fiber.NewError(fiber.StatusInternalServerError, "查询机器人失败") } // 获取联系人信息 var contact model.Contact if err := db.First(&contact, contactID).Error; err != nil { if err == gorm.ErrRecordNotFound { return fiber.NewError(fiber.StatusNotFound, "联系人不存在") } return fiber.NewError(fiber.StatusInternalServerError, "查询联系人失败") } // 获取聊天记录 var messages []model.Message if err := db.Where("robot_id = ? AND contact_id = ?", robotID, contactID). Order("send_time DESC").Limit(50).Find(&messages).Error; err != nil { return fiber.NewError(fiber.StatusInternalServerError, "获取聊天记录失败") } return c.Render("contact/show", fiber.Map{ "Title": contact.Nickname, "Robot": robot, "Contact": contact, "Messages": messages, }) } // ListGroupMembers 列出群成员 func ListGroupMembers(c *fiber.Ctx) error { robotID, err := strconv.Atoi(c.Params("id")) if err != nil { return fiber.NewError(fiber.StatusBadRequest, "无效的机器人ID") } contactID, err := strconv.Atoi(c.Params("contactId")) if err != nil { return fiber.NewError(fiber.StatusBadRequest, "无效的联系人ID") } db := model.GetDB() // 获取机器人信息 var robot model.Robot if err := db.First(&robot, robotID).Error; err != nil { return fiber.NewError(fiber.StatusInternalServerError, "查询机器人失败") } // 获取联系人信息(群) var contact model.Contact if err := db.First(&contact, contactID).Error; err != nil { return fiber.NewError(fiber.StatusInternalServerError, "查询群信息失败") } // 确保联系人是群组 if contact.Type != model.ContactTypeGroup { return fiber.NewError(fiber.StatusBadRequest, "指定的联系人不是群组") } // 获取群成员 var members []model.GroupMember if err := db.Where("group_id = ?", contactID).Find(&members).Error; err != nil { return fiber.NewError(fiber.StatusInternalServerError, "获取群成员失败") } // 如果机器人在线并且没有群成员,则从机器人获取 if robot.Status == model.RobotStatusOnline && len(members) == 0 { ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() // 调用Docker API获取群成员,传递容器访问地址 membersData, err := docker.GetWechatGroupMembers(ctx, robot.ContainerID, contact.WechatID, robot.ContainerHost) if err != nil { return fiber.NewError(fiber.StatusInternalServerError, "从机器人获取群成员失败: "+err.Error()) } // 解析群成员数据 var response docker.APIResponse if err := json.Unmarshal([]byte(membersData), &response); err != nil { return fiber.NewError(fiber.StatusInternalServerError, "解析群成员数据失败: "+err.Error()) } // 保存群成员到数据库 if response.Success { memberList, ok := response.Data.([]interface{}) if ok { for _, m := range memberList { memberMap, ok := m.(map[string]interface{}) if !ok { continue } role := model.MemberRoleMember if memberMap["role"].(string) == "owner" { role = model.MemberRoleOwner } else if memberMap["role"].(string) == "admin" { role = model.MemberRoleAdmin } member := model.GroupMember{ GroupID: contact.ID, WechatID: memberMap["id"].(string), Nickname: memberMap["name"].(string), Avatar: memberMap["avatar"].(string), Role: role, } db.Create(&member) members = append(members, member) } } } } return c.Render("contact/members", fiber.Map{ "Title": contact.Nickname + " 群成员", "Robot": robot, "Contact": contact, "Members": members, }) }