Merge branch 'chat' into dev
This commit is contained in:
commit
b858a599d0
@ -25,7 +25,7 @@ import (
|
||||
|
||||
type AutoReply struct {
|
||||
Response string `json:"response"`
|
||||
Rules map[string]IRule `json:"rules"`
|
||||
Rules map[string]IRobotTask `json:"rules"`
|
||||
}
|
||||
type AutoReplyRule struct {
|
||||
Enable bool `json:"enable"`
|
||||
|
@ -26,3 +26,6 @@ web端和后端交互式时,增删改查的规则配置是存放在rules对象
|
||||
- keywords :关键字回复
|
||||
- joinSession:用户打开聊天窗口后
|
||||
- noReplyAfter:客服指定时间没有回复后
|
||||
|
||||
## 注意
|
||||
- 目前不支持用户多端登录,会导致用户收到重复消息
|
@ -7,28 +7,20 @@
|
||||
package robot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"fonchain-fiee/api/accountFiee"
|
||||
"fonchain-fiee/pkg/common/ws"
|
||||
"fonchain-fiee/pkg/service"
|
||||
"fonchain-fiee/pkg/service/asChat/chatCache"
|
||||
"fonchain-fiee/pkg/service/asChat/dto"
|
||||
"fonchain-fiee/pkg/service/asChat/logic"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 回复规则
|
||||
type Reply struct {
|
||||
Title string
|
||||
Response string
|
||||
Rules []IRule
|
||||
Rules []IRobotTask
|
||||
}
|
||||
|
||||
func (r *Reply) Hit(event ws.ListenEventData, robotInfo *accountFiee.ChatUserData) (hit bool, task RobotTask) {
|
||||
for _, rule := range r.Rules {
|
||||
hit, task = rule.Hit(event, robotInfo)
|
||||
func (r *Reply) Hit(event ws.ListenEventData, robotInfo *accountFiee.ChatUserData) (hit bool, rule IRobotTask) {
|
||||
for _, rule = range r.Rules {
|
||||
hit = rule.Hit(event, robotInfo)
|
||||
if hit {
|
||||
return
|
||||
}
|
||||
@ -36,47 +28,190 @@ func (r *Reply) Hit(event ws.ListenEventData, robotInfo *accountFiee.ChatUserDat
|
||||
return
|
||||
}
|
||||
|
||||
// 规则接口
|
||||
type IRule interface {
|
||||
Hit(event ws.ListenEventData, robotInfo *accountFiee.ChatUserData) (hit bool, task RobotTask)
|
||||
}
|
||||
|
||||
// KeywordsRuleChecker 关键字回复
|
||||
type ReplyWhenHitKeywords struct {
|
||||
Keywords []string `json:"keywords"`
|
||||
}
|
||||
|
||||
func NewReplyWhenHitKeywords(keywords []string) IRule {
|
||||
return &ReplyWhenHitKeywords{Keywords: keywords}
|
||||
}
|
||||
func (k ReplyWhenHitKeywords) Hit(event ws.ListenEventData, robotInfo *accountFiee.ChatUserData) (hit bool, task RobotTask) {
|
||||
if event.EventType != ws.EventChatMessage || event.Msg == "" || event.Client == nil || event.ChatUser == nil {
|
||||
return
|
||||
}
|
||||
if event.ChatUser.Role != 1 {
|
||||
return
|
||||
}
|
||||
for _, v := range k.Keywords {
|
||||
if strings.Contains(event.Msg, v) {
|
||||
hit = true
|
||||
break
|
||||
}
|
||||
}
|
||||
task = RobotTask{
|
||||
ChatUser: event.ChatUser,
|
||||
Run: func(msg string, cache *chatCache.ChatCache, Sender *accountFiee.ChatUserData) error {
|
||||
return logic.NewMessage(context.Background(), cache, Sender, dto.NewMessageRequest{
|
||||
Waiter: true,
|
||||
SessionId: event.Client.SessionId,
|
||||
Message: dto.Message{
|
||||
MsgType: 1,
|
||||
Text: msg,
|
||||
LocalStamp: time.Now().Unix(),
|
||||
},
|
||||
})
|
||||
},
|
||||
}
|
||||
//logicFunc = func(content string, cache *chatCache.ChatCache, chatUser *accountFiee.ChatUserData) error {
|
||||
//
|
||||
//// 规则接口
|
||||
//type IRule interface {
|
||||
// Hit(event ws.ListenEventData, robotInfo *accountFiee.ChatUserData) (hit bool, task RobotTask)
|
||||
//}
|
||||
//
|
||||
//// KeywordsRuleChecker 关键字回复
|
||||
//type ReplyWhenHitKeywords struct {
|
||||
// Keywords []string `json:"keywords"`
|
||||
//}
|
||||
//
|
||||
//func NewReplyWhenHitKeywords(keywords []string) IRule {
|
||||
// return &ReplyWhenHitKeywords{Keywords: keywords}
|
||||
//}
|
||||
//func (k ReplyWhenHitKeywords) Hit(event ws.ListenEventData, robotInfo *accountFiee.ChatUserData) (hit bool, task RobotTask) {
|
||||
// if event.EventType != ws.EventChatMessage || event.Msg == "" || event.Client == nil || event.ChatUser == nil {
|
||||
// return
|
||||
// }
|
||||
// if event.ChatUser.Role != 1 {
|
||||
// return
|
||||
// }
|
||||
// for _, v := range k.Keywords {
|
||||
// if strings.Contains(event.Msg, v) {
|
||||
// hit = true
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// atUserId := event.Client.UserId
|
||||
// task = RobotTask{
|
||||
// ChatUser: event.ChatUser,
|
||||
// Run: func(msg string, cache *chatCache.ChatCache, Sender *accountFiee.ChatUserData) error {
|
||||
// return logic.NewMessage(context.Background(), cache, Sender, dto.NewMessageRequest{
|
||||
// Waiter: true,
|
||||
// Robot: true,
|
||||
// AtUserId: atUserId,
|
||||
// SessionId: event.Client.SessionId,
|
||||
// Message: dto.Message{
|
||||
// MsgType: 1,
|
||||
// Text: msg,
|
||||
// LocalStamp: time.Now().Unix(),
|
||||
// },
|
||||
// })
|
||||
// },
|
||||
// }
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//// 用户打开聊天会话直接发送
|
||||
//type ReplyWhenUserJoinSession struct {
|
||||
//}
|
||||
//
|
||||
//func NewReplyWhenUserJoinSession() IRule {
|
||||
// return &ReplyWhenUserJoinSession{}
|
||||
//}
|
||||
//
|
||||
//func (k ReplyWhenUserJoinSession) Hit(event ws.ListenEventData, robotInfo *accountFiee.ChatUserData) (hit bool, task RobotTask) {
|
||||
// if event.EventType != ws.EventUserJoin {
|
||||
// return
|
||||
// }
|
||||
// if event.Client == nil {
|
||||
// return
|
||||
// }
|
||||
// clientSessionId := event.Client.SessionId
|
||||
// atUserId := event.Client.UserId
|
||||
// ctx := context.Background()
|
||||
// queryRes, err := service.AccountFieeProvider.GetChatRecordList(ctx, &accountFiee.GetChatRecordListRequest{
|
||||
// Query: &accountFiee.ChatRecordData{
|
||||
// SessionId: event.Client.SessionId,
|
||||
// },
|
||||
// Page: 1,
|
||||
// PageSize: 1,
|
||||
// Order: "created_at desc",
|
||||
// })
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// //如果最近一次的消息也是机器人发送的,就不再发送了
|
||||
// for i, v := range queryRes.List {
|
||||
// if i == 0 {
|
||||
// if v.UserId == robotInfo.ID {
|
||||
// return
|
||||
// } else {
|
||||
// break
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// hit = true
|
||||
// if event.ChatUser == nil {
|
||||
// event.ChatUser, err = service.AccountFieeProvider.GetChatUserDetail(context.Background(), &accountFiee.GetChatUserByIdRequest{Id: event.Client.UserId})
|
||||
// if err != nil {
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
// task = RobotTask{
|
||||
// ChatUser: event.ChatUser,
|
||||
// Run: func(msg string, cache *chatCache.ChatCache, Sender *accountFiee.ChatUserData) error {
|
||||
// return logic.NewMessage(ctx, cache, Sender, dto.NewMessageRequest{
|
||||
// Waiter: true,
|
||||
// Robot: true,
|
||||
// AtUserId: atUserId,
|
||||
// SessionId: clientSessionId,
|
||||
// Message: dto.Message{
|
||||
// MsgType: 1,
|
||||
// Text: msg,
|
||||
// LocalStamp: time.Now().Unix(),
|
||||
// },
|
||||
// })
|
||||
// },
|
||||
// }
|
||||
// //logicFunc = func(msg string, cache *chatCache.ChatCache, chatUser *accountFiee.ChatUserData) error {
|
||||
// // //var notice = dto.MessageListType{}
|
||||
// // //newRecord := &accountFiee.ChatRecordData{
|
||||
// // // SessionId: wsClient.SessionId,
|
||||
// // // UserId: wsClient.UserId,
|
||||
// // // Name: wsClient.SessionId,
|
||||
// // // Avatar: robotInfo.Avatar,
|
||||
// // // MsgType: 1,
|
||||
// // // Content: msg,
|
||||
// // //}
|
||||
// // //notice.BuildMessage(newRecord)
|
||||
// // //_, err = consts.ChatRoom.SendSessionMessage(robotInfo, wsClient.SessionId, ws.NewChatMsgType, notice)
|
||||
// // err = logic.NewMessage(ctx, cache, chatUser, dto.NewMessageRequest{
|
||||
// // Waiter: true,
|
||||
// // SessionId: wsClient.SessionId,
|
||||
// // Message: dto.Message{
|
||||
// // MsgType: 1,
|
||||
// // Text: msg,
|
||||
// // LocalStamp: time.Now().Unix(),
|
||||
// // },
|
||||
// // })
|
||||
// // return err
|
||||
// //}
|
||||
// return
|
||||
//}
|
||||
//
|
||||
//// 客服指定时间不回复则自动回复
|
||||
//
|
||||
//type ReplyWhenWaiterNoAction struct {
|
||||
// DelaySecond time.Duration
|
||||
//}
|
||||
//
|
||||
////func NewReplyWhenWaiterNoAction(delaySecond time.Duration) *ReplyWhenWaiterNoAction {
|
||||
//// return &ReplyWhenWaiterNoAction{
|
||||
//// DelaySecond: delaySecond,
|
||||
//// }
|
||||
////}
|
||||
//
|
||||
//func (k *ReplyWhenWaiterNoAction) Hit(event ws.ListenEventData, sender *accountFiee.ChatUserData) (hit bool, task RobotTask) {
|
||||
// if event.Client == nil || event.EventType != ws.EventChatMessage {
|
||||
// return
|
||||
// }
|
||||
// //客服和机器人的的消息不需要处理
|
||||
// if event.ChatUser.Role != 1 {
|
||||
// return
|
||||
// }
|
||||
// hit = true // 立即保存SessionId的值
|
||||
//
|
||||
// clientSessionId := event.Client.SessionId
|
||||
// atUserId := event.Client.UserId
|
||||
// fmt.Printf("闭包前: clientSessionId=%s\n", clientSessionId)
|
||||
// task = RobotTask{
|
||||
// RunTime: time.Now().Add(k.DelaySecond * time.Second),
|
||||
// Run: func(content string, cache *chatCache.ChatCache, Sender *accountFiee.ChatUserData) error {
|
||||
// // 记录闭包执行时的Client状态
|
||||
// fmt.Printf("闭包执行: clientSessionId=%s\n", clientSessionId)
|
||||
//
|
||||
// //如果客服已经回复则不发送消息
|
||||
// chatRecordListRes, err := service.AccountFieeProvider.GetChatRecordList(context.Background(), &accountFiee.GetChatRecordListRequest{
|
||||
// Query: &accountFiee.ChatRecordData{
|
||||
// SessionId: event.Client.SessionId,
|
||||
// },
|
||||
// Page: 1,
|
||||
// PageSize: 1,
|
||||
// Order: "created_at desc",
|
||||
// })
|
||||
// if err != nil || chatRecordListRes.Total == 0 {
|
||||
// return err
|
||||
// }
|
||||
// checkUserId := chatRecordListRes.List[0].UserId
|
||||
// checkChatUser, err := service.AccountFieeProvider.GetChatUserDetail(context.Background(), &accountFiee.GetChatUserByIdRequest{Id: checkUserId})
|
||||
// if err != nil || checkChatUser.Role != 1 {
|
||||
// return err
|
||||
// }
|
||||
//
|
||||
// //var notice = dto.MessageListType{}
|
||||
// //newRecord := &accountFiee.ChatRecordData{
|
||||
// // SessionId: wsClient.SessionId,
|
||||
@ -87,181 +222,25 @@ func (k ReplyWhenHitKeywords) Hit(event ws.ListenEventData, robotInfo *accountFi
|
||||
// // Content: content,
|
||||
// //}
|
||||
// //notice.BuildMessage(newRecord)
|
||||
// //_, err := consts.ChatRoom.SendSessionMessage(robotInfo, wsClient.SessionId, ws.NewChatMsgType, notice)
|
||||
// //return err
|
||||
// err := logic.NewMessage(context.Background(), cache, chatUser, dto.NewMessageRequest{
|
||||
// Waiter: true,
|
||||
// SessionId: wsClient.SessionId,
|
||||
// Message: dto.Message{
|
||||
// MsgType: 1,
|
||||
// Text: msg,
|
||||
// LocalStamp: time.Now().Unix(),
|
||||
// },
|
||||
// })
|
||||
// return err
|
||||
//}
|
||||
return
|
||||
}
|
||||
|
||||
// 用户打开聊天会话直接发送
|
||||
type ReplyWhenUserJoinSession struct {
|
||||
}
|
||||
|
||||
func NewReplyWhenUserJoinSession() IRule {
|
||||
return &ReplyWhenUserJoinSession{}
|
||||
}
|
||||
|
||||
func (k ReplyWhenUserJoinSession) Hit(event ws.ListenEventData, robotInfo *accountFiee.ChatUserData) (hit bool, task RobotTask) {
|
||||
if event.EventType != ws.EventUserJoin {
|
||||
return
|
||||
}
|
||||
if event.Client == nil {
|
||||
return
|
||||
}
|
||||
ctx := context.Background()
|
||||
queryRes, err := service.AccountFieeProvider.GetChatRecordList(ctx, &accountFiee.GetChatRecordListRequest{
|
||||
Query: &accountFiee.ChatRecordData{
|
||||
SessionId: event.Client.SessionId,
|
||||
},
|
||||
Page: 1,
|
||||
PageSize: 1,
|
||||
Order: "created_at desc",
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
//如果最近一次的消息也是机器人发送的,就不再发送了
|
||||
for i, v := range queryRes.List {
|
||||
if i == 0 {
|
||||
if v.UserId == robotInfo.ID {
|
||||
return
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
hit = true
|
||||
if event.ChatUser == nil {
|
||||
event.ChatUser, err = service.AccountFieeProvider.GetChatUserDetail(context.Background(), &accountFiee.GetChatUserByIdRequest{Id: event.Client.UserId})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
task = RobotTask{
|
||||
ChatUser: event.ChatUser,
|
||||
Run: func(msg string, cache *chatCache.ChatCache, Sender *accountFiee.ChatUserData) error {
|
||||
return logic.NewMessage(ctx, cache, Sender, dto.NewMessageRequest{
|
||||
Waiter: true,
|
||||
SessionId: event.Client.SessionId,
|
||||
Message: dto.Message{
|
||||
MsgType: 1,
|
||||
Text: msg,
|
||||
LocalStamp: time.Now().Unix(),
|
||||
},
|
||||
})
|
||||
},
|
||||
}
|
||||
//logicFunc = func(msg string, cache *chatCache.ChatCache, chatUser *accountFiee.ChatUserData) error {
|
||||
// //var notice = dto.MessageListType{}
|
||||
// //newRecord := &accountFiee.ChatRecordData{
|
||||
// // SessionId: wsClient.SessionId,
|
||||
// // UserId: wsClient.UserId,
|
||||
// // Name: wsClient.SessionId,
|
||||
// // Avatar: robotInfo.Avatar,
|
||||
// // MsgType: 1,
|
||||
// // Content: msg,
|
||||
// //}
|
||||
// //notice.BuildMessage(newRecord)
|
||||
// //_, err = consts.ChatRoom.SendSessionMessage(robotInfo, wsClient.SessionId, ws.NewChatMsgType, notice)
|
||||
// err = logic.NewMessage(ctx, cache, chatUser, dto.NewMessageRequest{
|
||||
// //return err
|
||||
// fmt.Println("延时回复 sessionID:", clientSessionId)
|
||||
// err = logic.NewMessage(context.Background(), cache, sender, dto.NewMessageRequest{
|
||||
// Waiter: true,
|
||||
// SessionId: wsClient.SessionId,
|
||||
// Robot: true,
|
||||
// AtUserId: atUserId,
|
||||
// SessionId: clientSessionId,
|
||||
// Message: dto.Message{
|
||||
// MsgType: 1,
|
||||
// Text: msg,
|
||||
// Text: content,
|
||||
// LocalStamp: time.Now().Unix(),
|
||||
// },
|
||||
// })
|
||||
// return err
|
||||
// },
|
||||
// Response: "",
|
||||
// ChatUser: event.ChatUser,
|
||||
// }
|
||||
return
|
||||
}
|
||||
|
||||
// 客服指定时间不回复则自动回复
|
||||
|
||||
type ReplyWhenWaiterNoAction struct {
|
||||
DelaySecond time.Duration
|
||||
}
|
||||
|
||||
func NewReplyWhenWaiterNoAction(delaySecond time.Duration) *ReplyWhenWaiterNoAction {
|
||||
return &ReplyWhenWaiterNoAction{
|
||||
DelaySecond: delaySecond,
|
||||
}
|
||||
}
|
||||
|
||||
func (k *ReplyWhenWaiterNoAction) Hit(event ws.ListenEventData, sender *accountFiee.ChatUserData) (hit bool, task RobotTask) {
|
||||
if event.Client == nil || event.EventType != ws.EventChatMessage {
|
||||
return
|
||||
}
|
||||
//客服和机器人的的消息不需要处理
|
||||
if event.ChatUser.Role != 1 {
|
||||
return
|
||||
}
|
||||
hit = true // 立即保存SessionId的值
|
||||
clientSessionId := event.Client.SessionId
|
||||
|
||||
fmt.Printf("闭包前: clientSessionId=%s\n", clientSessionId)
|
||||
task = RobotTask{
|
||||
RunTime: time.Now().Add(k.DelaySecond * time.Second),
|
||||
Run: func(content string, cache *chatCache.ChatCache, Sender *accountFiee.ChatUserData) error {
|
||||
// 记录闭包执行时的Client状态
|
||||
fmt.Printf("闭包执行: clientSessionId=%s\n", clientSessionId)
|
||||
|
||||
//如果客服已经回复则不发送消息
|
||||
chatRecordListRes, err := service.AccountFieeProvider.GetChatRecordList(context.Background(), &accountFiee.GetChatRecordListRequest{
|
||||
Query: &accountFiee.ChatRecordData{
|
||||
SessionId: event.Client.SessionId,
|
||||
},
|
||||
Page: 1,
|
||||
PageSize: 1,
|
||||
Order: "created_at desc",
|
||||
})
|
||||
if err != nil || chatRecordListRes.Total == 0 {
|
||||
return err
|
||||
}
|
||||
checkUserId := chatRecordListRes.List[0].UserId
|
||||
checkChatUser, err := service.AccountFieeProvider.GetChatUserDetail(context.Background(), &accountFiee.GetChatUserByIdRequest{Id: checkUserId})
|
||||
if err != nil || checkChatUser.Role != 1 {
|
||||
return err
|
||||
}
|
||||
|
||||
//var notice = dto.MessageListType{}
|
||||
//newRecord := &accountFiee.ChatRecordData{
|
||||
// SessionId: wsClient.SessionId,
|
||||
// UserId: wsClient.UserId,
|
||||
// Name: chatUser.NickName,
|
||||
// Avatar: robotInfo.Avatar,
|
||||
// MsgType: 1,
|
||||
// Content: content,
|
||||
// return
|
||||
//
|
||||
//}
|
||||
//notice.BuildMessage(newRecord)
|
||||
//_, err = consts.ChatRoom.SendSessionMessage(robotInfo, wsClient.SessionId, ws.NewChatMsgType, notice)
|
||||
//return err
|
||||
fmt.Println("延时回复 sessionID:", clientSessionId)
|
||||
err = logic.NewMessage(context.Background(), cache, sender, dto.NewMessageRequest{
|
||||
Waiter: true,
|
||||
SessionId: clientSessionId,
|
||||
Message: dto.Message{
|
||||
MsgType: 1,
|
||||
Text: content,
|
||||
LocalStamp: time.Now().Unix(),
|
||||
},
|
||||
})
|
||||
return err
|
||||
},
|
||||
Response: "",
|
||||
ChatUser: event.ChatUser,
|
||||
}
|
||||
return
|
||||
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ func NewRobot(cache *chatCache.ChatCache) *Robot {
|
||||
cache: cache,
|
||||
}
|
||||
err = r.ReloadRules(ctx)
|
||||
fmt.Println("机器人规则加载失败")
|
||||
fmt.Println("机器人规则加载完成,结果:", err)
|
||||
consts.ChatRoom.RegisterEventListener(r.EventListener)
|
||||
go r.Run()
|
||||
return r
|
||||
@ -66,7 +66,7 @@ func NewRobot(cache *chatCache.ChatCache) *Robot {
|
||||
type Robot struct {
|
||||
Info *accountFiee.ChatUserData //机器人信息
|
||||
Rules []Reply //回复规则
|
||||
DelayTask []RobotTask //演示任务
|
||||
DelayTask []IRobotTask //演示任务
|
||||
ticker *time.Ticker //定时器
|
||||
stopChan chan struct{} //停止管道
|
||||
isRunning bool //运行状态
|
||||
@ -140,12 +140,12 @@ func (r *Robot) Run() {
|
||||
//return // 没有任务时退出
|
||||
}
|
||||
now := time.Now()
|
||||
var remainingTasks []RobotTask
|
||||
var remainingTasks []IRobotTask
|
||||
for _, task := range r.DelayTask {
|
||||
if now.After(task.RunTime) {
|
||||
if now.After(task.RunTime()) {
|
||||
// 执行任务
|
||||
go func() {
|
||||
err := task.Run(task.Response, r.cache, task.ChatUser)
|
||||
err := task.Run(r.cache)
|
||||
if err != nil {
|
||||
log.Printf("聊天机器人[%d]延时回复消息失败:%v", r.Info.ID, err)
|
||||
} else {
|
||||
@ -167,16 +167,16 @@ func (r *Robot) Run() {
|
||||
hit, task := ruleResponse.Hit(event, r.Info)
|
||||
if hit {
|
||||
fmt.Println("命中规则:", ruleResponse.Title)
|
||||
if task.RunTime.IsZero() {
|
||||
err := task.Run(ruleResponse.Response, r.cache, r.Info)
|
||||
if task.RunTime().IsZero() {
|
||||
task.SetResponse(ruleResponse.Response)
|
||||
err := task.Run(r.cache)
|
||||
if err != nil {
|
||||
log.Printf("robot 执行任务失败:%v\n", err)
|
||||
}
|
||||
} else {
|
||||
ruleResponse := ruleResponse
|
||||
task.Response = ruleResponse.Response
|
||||
task.SetResponse(ruleResponse.Response)
|
||||
r.RegisterDelayTask(task)
|
||||
|
||||
}
|
||||
break
|
||||
}
|
||||
@ -193,7 +193,7 @@ func (r *Robot) Stop() {
|
||||
}
|
||||
r.mu.Unlock()
|
||||
}
|
||||
func (r *Robot) RegisterDelayTask(task RobotTask) {
|
||||
func (r *Robot) RegisterDelayTask(task IRobotTask) {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
if task.Run == nil {
|
||||
|
98
pkg/service/asChat/robot/ruler_ReplyWhenWaiterNoAction.go
Normal file
98
pkg/service/asChat/robot/ruler_ReplyWhenWaiterNoAction.go
Normal file
@ -0,0 +1,98 @@
|
||||
// Package robot -----------------------------
|
||||
// @file : ruler_ReplyWhenWaiterNoAction.go
|
||||
// @author : JJXu
|
||||
// @contact : wavingbear@163.com
|
||||
// @time : 2025/6/13 18:02
|
||||
// -------------------------------------------
|
||||
package robot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"fonchain-fiee/api/accountFiee"
|
||||
"fonchain-fiee/pkg/common/ws"
|
||||
"fonchain-fiee/pkg/service"
|
||||
"fonchain-fiee/pkg/service/asChat/chatCache"
|
||||
"fonchain-fiee/pkg/service/asChat/dto"
|
||||
"fonchain-fiee/pkg/service/asChat/logic"
|
||||
"time"
|
||||
)
|
||||
|
||||
type IRobotTask interface {
|
||||
Hit(event ws.ListenEventData, sender *accountFiee.ChatUserData) (hit bool)
|
||||
Run(cache *chatCache.ChatCache) error
|
||||
RunTime() time.Time
|
||||
SetResponse(response string)
|
||||
}
|
||||
|
||||
// 客服指定时间不回复则自动回复
|
||||
func NewReplyWhenWaiterNoAction(delaySecond time.Duration) IRobotTask {
|
||||
return &RobotTaskReplyWhenWaiterNoAction{
|
||||
delaySecond: delaySecond,
|
||||
}
|
||||
}
|
||||
|
||||
type RobotTaskReplyWhenWaiterNoAction struct {
|
||||
runTime time.Time
|
||||
Response string
|
||||
Receiver *accountFiee.ChatUserData
|
||||
Sender *accountFiee.ChatUserData
|
||||
Msg string
|
||||
Resp string
|
||||
delaySecond time.Duration
|
||||
}
|
||||
|
||||
func (r *RobotTaskReplyWhenWaiterNoAction) Hit(event ws.ListenEventData, sender *accountFiee.ChatUserData) (hit bool) {
|
||||
if event.Client == nil || event.EventType != ws.EventChatMessage {
|
||||
return
|
||||
}
|
||||
//客服和机器人的的消息不需要处理
|
||||
if event.ChatUser.Role != 1 {
|
||||
return
|
||||
}
|
||||
hit = true // 立即保存SessionId的值
|
||||
r.Sender = sender
|
||||
r.Receiver = event.ChatUser
|
||||
r.runTime = time.Now().Add(r.delaySecond * time.Second)
|
||||
return
|
||||
}
|
||||
|
||||
func (r *RobotTaskReplyWhenWaiterNoAction) Run(cache *chatCache.ChatCache) error {
|
||||
clientSessionId := fmt.Sprintf("%d", r.Receiver.ID)
|
||||
fmt.Println("延时回复 sessionID:", clientSessionId)
|
||||
//如果客服已经回复则不发送消息
|
||||
chatRecordListRes, err := service.AccountFieeProvider.GetChatRecordList(context.Background(), &accountFiee.GetChatRecordListRequest{
|
||||
Query: &accountFiee.ChatRecordData{
|
||||
SessionId: clientSessionId,
|
||||
},
|
||||
Page: 1,
|
||||
PageSize: 1,
|
||||
Order: "created_at desc",
|
||||
})
|
||||
if err != nil || chatRecordListRes.Total == 0 {
|
||||
return err
|
||||
}
|
||||
checkUserId := chatRecordListRes.List[0].UserId
|
||||
checkChatUser, err := service.AccountFieeProvider.GetChatUserDetail(context.Background(), &accountFiee.GetChatUserByIdRequest{Id: checkUserId})
|
||||
if err != nil || checkChatUser.Role != 1 {
|
||||
return err
|
||||
}
|
||||
err = logic.NewMessage(context.Background(), cache, r.Sender, dto.NewMessageRequest{
|
||||
Waiter: true,
|
||||
Robot: true,
|
||||
AtUserId: r.Receiver.ID,
|
||||
SessionId: clientSessionId,
|
||||
Message: dto.Message{
|
||||
MsgType: 1,
|
||||
Text: r.Resp,
|
||||
LocalStamp: time.Now().Unix(),
|
||||
},
|
||||
})
|
||||
return err
|
||||
}
|
||||
func (r *RobotTaskReplyWhenWaiterNoAction) RunTime() time.Time {
|
||||
return r.runTime
|
||||
}
|
||||
func (r *RobotTaskReplyWhenWaiterNoAction) SetResponse(response string) {
|
||||
r.Resp = response
|
||||
}
|
67
pkg/service/asChat/robot/ruler_keywords.go
Normal file
67
pkg/service/asChat/robot/ruler_keywords.go
Normal file
@ -0,0 +1,67 @@
|
||||
package robot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"fonchain-fiee/api/accountFiee"
|
||||
"fonchain-fiee/pkg/common/ws"
|
||||
"fonchain-fiee/pkg/service/asChat/chatCache"
|
||||
"fonchain-fiee/pkg/service/asChat/dto"
|
||||
"fonchain-fiee/pkg/service/asChat/logic"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type RobotTaskWithKeyworkds struct {
|
||||
runTime time.Time
|
||||
Response string
|
||||
Receiver *accountFiee.ChatUserData
|
||||
Sender *accountFiee.ChatUserData
|
||||
Msg string
|
||||
Resp string
|
||||
keywords []string
|
||||
}
|
||||
|
||||
func NewReplyWhenHitKeywords(keywords []string) IRobotTask {
|
||||
return &RobotTaskWithKeyworkds{keywords: keywords}
|
||||
}
|
||||
func (r *RobotTaskWithKeyworkds) Hit(event ws.ListenEventData, sender *accountFiee.ChatUserData) (hit bool) {
|
||||
if event.EventType != ws.EventChatMessage || event.Msg == "" || event.Client == nil || event.ChatUser == nil {
|
||||
return
|
||||
}
|
||||
if event.ChatUser.Role != 1 {
|
||||
return
|
||||
}
|
||||
r.Sender = sender
|
||||
r.Receiver = event.ChatUser
|
||||
for _, v := range r.keywords {
|
||||
if strings.Contains(event.Msg, v) {
|
||||
hit = true
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (r *RobotTaskWithKeyworkds) Run(cache *chatCache.ChatCache) (err error) {
|
||||
err = logic.NewMessage(context.Background(), cache, r.Sender, dto.NewMessageRequest{
|
||||
Waiter: true,
|
||||
Robot: true,
|
||||
AtUserId: r.Receiver.ID,
|
||||
SessionId: fmt.Sprintf("%d", r.Receiver.ID),
|
||||
Message: dto.Message{
|
||||
MsgType: 1,
|
||||
Text: r.Resp,
|
||||
LocalStamp: time.Now().Unix(),
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (r *RobotTaskWithKeyworkds) RunTime() time.Time {
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
func (r *RobotTaskWithKeyworkds) SetResponse(response string) {
|
||||
r.Resp = response
|
||||
}
|
86
pkg/service/asChat/robot/ruler_replyWhenUserJoinSession.go
Normal file
86
pkg/service/asChat/robot/ruler_replyWhenUserJoinSession.go
Normal file
@ -0,0 +1,86 @@
|
||||
package robot
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"fonchain-fiee/api/accountFiee"
|
||||
"fonchain-fiee/pkg/common/ws"
|
||||
"fonchain-fiee/pkg/service"
|
||||
"fonchain-fiee/pkg/service/asChat/chatCache"
|
||||
"fonchain-fiee/pkg/service/asChat/dto"
|
||||
"fonchain-fiee/pkg/service/asChat/logic"
|
||||
"time"
|
||||
)
|
||||
|
||||
func NewReplyWhenUserJoinSession() IRobotTask {
|
||||
return &ReplyWhenUserJoinSession{}
|
||||
}
|
||||
|
||||
type ReplyWhenUserJoinSession struct {
|
||||
Response string
|
||||
Receiver *accountFiee.ChatUserData
|
||||
Sender *accountFiee.ChatUserData
|
||||
Msg string
|
||||
Resp string
|
||||
}
|
||||
|
||||
func (r ReplyWhenUserJoinSession) Hit(event ws.ListenEventData, sender *accountFiee.ChatUserData) (hit bool) {
|
||||
if event.EventType != ws.EventUserJoin {
|
||||
return
|
||||
}
|
||||
if event.Client == nil {
|
||||
return
|
||||
}
|
||||
ctx := context.Background()
|
||||
queryRes, err := service.AccountFieeProvider.GetChatRecordList(ctx, &accountFiee.GetChatRecordListRequest{
|
||||
Query: &accountFiee.ChatRecordData{
|
||||
SessionId: event.Client.SessionId,
|
||||
},
|
||||
Page: 1,
|
||||
PageSize: 1,
|
||||
Order: "created_at desc",
|
||||
})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
//如果最近一次的消息也是机器人发送的,就不再发送了
|
||||
for i, v := range queryRes.List {
|
||||
if i == 0 {
|
||||
if v.UserId == sender.ID {
|
||||
return
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
hit = true
|
||||
r.Sender = sender
|
||||
r.Receiver = event.ChatUser
|
||||
return
|
||||
}
|
||||
|
||||
func (r ReplyWhenUserJoinSession) Run(cache *chatCache.ChatCache) (err error) {
|
||||
clientSessionId := fmt.Sprintf("%d", r.Receiver.ID)
|
||||
err = logic.NewMessage(context.Background(), cache, r.Sender, dto.NewMessageRequest{
|
||||
Waiter: true,
|
||||
Robot: true,
|
||||
AtUserId: r.Receiver.ID,
|
||||
SessionId: clientSessionId,
|
||||
Message: dto.Message{
|
||||
MsgType: 1,
|
||||
Text: r.Resp,
|
||||
LocalStamp: time.Now().Unix(),
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
func (r ReplyWhenUserJoinSession) RunTime() time.Time {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (r ReplyWhenUserJoinSession) SetResponse(response string) {
|
||||
//TODO implement me
|
||||
panic("implement me")
|
||||
}
|
Loading…
Reference in New Issue
Block a user