Files
customer-server/service/webhook_service.go
2026-03-14 10:02:49 +08:00

102 lines
3.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 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
}