232 lines
6.7 KiB
Go
232 lines
6.7 KiB
Go
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,
|
||
})
|
||
}
|