149 lines
4.1 KiB
Go
149 lines
4.1 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"
|
||
)
|
||
|
||
// 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,
|
||
})
|
||
}
|