2025-04-02 14:29:44 +08:00

149 lines
4.1 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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"
)
// ListMessages 获取联系人的聊天记录
func ListMessages(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")
}
// 获取分页参数
page, _ := strconv.Atoi(c.Query("page", "1"))
limit := 20
offset := (page - 1) * limit
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").
Offset(offset).Limit(limit).
Find(&messages).Error; err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "获取消息失败")
}
// 获取总消息数
var total int64
db.Model(&model.Message{}).Where("robot_id = ? AND contact_id = ?", robotID, contactID).Count(&total)
// 如果机器人在线并且没有消息,则从机器人获取最新消息
if robot.Status == model.RobotStatusOnline && len(messages) == 0 {
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// 调用Docker API获取消息传递容器访问地址
messagesData, err := docker.GetWechatMessages(ctx, robot.ContainerID, contact.WechatID, 50, robot.ContainerHost)
if err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "从机器人获取消息失败: "+err.Error())
}
// 解析消息数据
var response docker.APIResponse
if err := json.Unmarshal([]byte(messagesData), &response); err != nil {
return fiber.NewError(fiber.StatusInternalServerError, "解析消息数据失败: "+err.Error())
}
// 保存消息到数据库
if response.Success {
messageList, ok := response.Data.([]interface{})
if ok {
for _, m := range messageList {
msgMap, ok := m.(map[string]interface{})
if !ok {
continue
}
contentType := model.ContentTypeText
switch msgMap["type"].(string) {
case "image":
contentType = model.ContentTypeImage
case "voice":
contentType = model.ContentTypeVoice
case "video":
contentType = model.ContentTypeVideo
case "file":
contentType = model.ContentTypeFile
case "location":
contentType = model.ContentTypeLocation
}
sendTimeStr := msgMap["time"].(string)
sendTime, _ := time.Parse(time.RFC3339, sendTimeStr)
message := model.Message{
RobotID: uint(robotID),
ContactID: uint(contactID),
SenderID: msgMap["sender_id"].(string),
SenderName: msgMap["sender_name"].(string),
Content: msgMap["content"].(string),
ContentType: contentType,
SendTime: sendTime,
IsFromMe: msgMap["from_me"].(bool),
}
if mediaURL, ok := msgMap["media_url"].(string); ok {
message.MediaURL = mediaURL
}
db.Create(&message)
messages = append(messages, message)
}
}
}
}
// 计算总页数
totalPages := int(total) / limit
if int(total)%limit > 0 {
totalPages++
}
return c.Render("message/index", fiber.Map{
"Title": contact.Nickname + " 聊天记录",
"Robot": robot,
"Contact": contact,
"Messages": messages,
"Page": page,
"TotalPages": totalPages,
"HasNext": page < totalPages,
"HasPrev": page > 1,
"NextPage": page + 1,
"PrevPage": page - 1,
})
}