Files
customer-server/service/webhook_service.go

102 lines
3.1 KiB
Go
Raw Normal View History

2026-03-14 10:02:49 +08:00
// Package service - Webhook服务
// 功能接收并处理平台小红书、抖音的webhook消息
package service
import (
"context"
"customer-server/dao"
"customer-server/model/dto"
"gitea.com/red-future/common/jaeger"
"gitea.com/red-future/common/rabbitmq"
"gitea.com/red-future/common/redis"
"gitea.com/red-future/common/utils"
"github.com/gogf/gf/v2/os/glog"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gconv"
)
var Webhook = new(webhookService)
type webhookService struct{}
// Receive 接收平台消息并写入队列
func (s *webhookService) Receive(ctx context.Context, req *dto.WebhookReceiveReq) (res *dto.WebhookReceiveRes, err error) {
glog.Infof(ctx, "收到 Webhook 消息 - 平台: %s, 用户: %s, 内容: %s", req.Platform, req.UserId, req.Content)
// 生成消息ID
now := gtime.Now()
messageId := req.Platform + "_" + req.UserId + "_" + gconv.String(now.TimestampNano())
if req.MsgId != "" {
messageId = req.MsgId // 使用平台消息ID便于去重
}
// 从 token 获取租户ID
var tenantId string
if user, userErr := utils.GetUserInfo(ctx); userErr == nil {
tenantId = gconv.String(user.TenantId)
}
// 构造消息
userId := req.Platform + "_" + req.UserId // 添加平台前缀
// 获取当前实例的动态响应队列名(自动生成,支持多实例部署)
baseQueue := GetConfigString(ctx, "rabbitmq.responseQueue")
replyQueue := rabbitmq.GetInstanceQueueName(baseQueue)
msg := &redis.SendStreamMessage{
UserId: userId,
TenantId: tenantId,
Content: req.Content,
Timestamp: now.Timestamp(),
MessageId: messageId,
Platform: req.Platform,
AccountId: req.AccountId,
ReplyQueue: replyQueue,
}
// 检查是否有 session 缓存,无缓存说明已归档,需要读取历史
if sessionId, _ := redis.GetSessionCache(ctx, tenantId, userId); sessionId == "" {
if history, histErr := dao.Conversation.GetRecentHistory(ctx, userId, redis.GetHistoryContextLimit()); histErr == nil && len(history) > 0 {
msg.History = history
glog.Infof(ctx, "用户已归档,读取 %d 轮历史对话 - 用户: %s", len(history), userId)
}
}
// 写入 Redis Stream
streamMsgId, err := redis.AddToStream(ctx, redis.RAGFlowRequestStreamKey, msg)
if err != nil {
jaeger.RecordError(ctx, err, "写入 Stream 失败")
return
}
glog.Infof(ctx, "消息已写入 Stream - MessageID: %s", streamMsgId)
res = &dto.WebhookReceiveRes{
Success: true,
MsgId: streamMsgId,
}
return
}
// GetHistory 查询用户对话记录
func (s *webhookService) GetHistory(ctx context.Context, req *dto.ConversationListReq) (res *dto.ConversationListRes, err error) {
list, err := dao.Conversation.FindByUserId(ctx, req.UserId, req.Limit)
if err != nil {
jaeger.RecordError(ctx, err, "查询对话记录失败")
return
}
res = &dto.ConversationListRes{
List: make([]*dto.ConversationItem, 0, len(list)),
}
for _, item := range list {
res.List = append(res.List, &dto.ConversationItem{
Question: item.Question,
Answer: item.Answer,
MsgTime: gtime.New(item.MsgTime).Format("Y-m-d H:i:s"),
SessionId: item.SessionId,
})
}
return
}