李寻欢 b839e4991a
All checks were successful
BuildImage / build-image (push) Successful in 8m20s
⬆️ 更新依赖gitee.ltd/lxh/xybot至v0.0.4,调整消息同步频率至每秒一次
2025-04-23 15:26:27 +08:00

122 lines
3.7 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 tasks
import (
"encoding/xml"
"gitee.ltd/lxh/wechat-robot/internal/minio"
"gitee.ltd/lxh/wechat-robot/internal/model"
"gitee.ltd/lxh/wechat-robot/internal/types"
"gitee.ltd/lxh/wechat-robot/internal/wechat"
"gitee.ltd/lxh/xybot"
"github.com/gofiber/fiber/v2/log"
"strings"
"time"
)
// syncMessage
// @description: 同步指定机器人的消息
// @param containerHost 机器人接口地址
// @param robotWxId 机器人微信Id
// @param robotId 机器人数据Id
func syncMessage(client *xybot.Client, robotId uint) {
// 获取数据库连接
db := model.GetDB()
// 获取新消息
messages, err := client.Message.Sync()
if err != nil {
// 手动处理一下是否离线了
isOffline := strings.Contains(err.Error(), "用户可能退出") || strings.Contains(err.Error(), "数据[DecryptData]失败")
if isOffline {
// 删除定时任务
DeleteJob(robotId)
// 修改机器人状态
db.Model(&model.Robot{}).Where("id = ?", robotId).Update("status", "offline")
}
return
}
if len(messages) == 0 {
// 没有消息,直接返回
return
}
//log.Debugf("当前同步机器人Id: %d消息数量: %d客户端信息: %+v", robotId, len(messages), client)
// 处理消息
var msg []model.Message
for _, message := range messages {
//log.Debugf("当前同步机器人Id: %d消息内容: %s", robotId, message.Content.String)
var m model.Message
m.RobotId = robotId
m.MsgId = message.NewMsgId
m.ClientMsgId = message.MsgId
m.CreateTime = message.CreateTime
m.CreateAt = time.Unix(int64(message.CreateTime), 0)
m.Type = types.MessageType(message.MsgType)
m.Content = message.Content.String
m.DisplayFullContent = message.PushContent
m.FromUser = message.FromUserName.String
m.ToUser = message.ToWxid.String
// 如果是群聊消息,单独处理一下
// Sys类型的消息正文不包含微信 Id所以不需要处理
if strings.HasSuffix(message.FromUserName.String, "@chatroom") && m.Type != types.MsgTypeSys {
// 群消息,处理一下消息和发信人
groupUser := strings.Split(m.Content, "\n")[0]
groupUser = strings.ReplaceAll(groupUser, ":", "")
// 如果两个id一致说明是系统发的
if m.FromUser != groupUser {
m.GroupUser = groupUser
}
// 用户的操作单独提出来处理一下
m.Content = strings.Join(strings.Split(m.Content, "\n")[1:], "\n")
}
// 处理一下如果是图片、文件、表情包等信息直接下载下来存到OSS
if m.Type == types.MsgTypeImage || m.Type == types.MsgTypeVideo {
// 解析消息xml文件
// 解析为结构体
var media wechat.MediaMessage
if err = xml.Unmarshal([]byte(m.Content), &media); err != nil {
log.Errorf("%v解析消息失败: %v", m.Type, err.Error())
continue
}
var md5Str, bs64Str string
switch m.Type {
case types.MsgTypeImage:
fileUrl := ""
md5Str = media.Img.Md5
if media.Img.CdnBigImgUrl != "" {
fileUrl = media.Img.CdnBigImgUrl
} else if media.Img.CdnMidImgUrl != "" {
fileUrl = media.Img.CdnMidImgUrl
} else if media.Img.CdnThumbUrl != "" {
fileUrl = media.Img.CdnThumbUrl
} else {
continue
}
if bs64Str, err = client.Tool.CdnDownloadImg(media.Img.AesKey, fileUrl); err != nil {
log.Errorf("图片文件下载失败: %s", err.Error())
continue
}
case types.MsgTypeVideo:
if bs64Str, err = client.Tool.DownloadVideo(m.ClientMsgId); err != nil {
log.Errorf("视频文件下载失败: %s", err.Error())
continue
}
}
// 下载完成保存到OSS
if m.FileUrl, err = minio.SaveBase64(bs64Str, md5Str); err != nil {
log.Errorf("文件保存到Minio失败: %s", err.Error())
continue
}
}
msg = append(msg, m)
}
// 保存入库
db.Save(&msg)
}