fonchain-fiee/pkg/service/asChat/robot/robot.go

263 lines
6.8 KiB
Go
Raw Normal View History

2025-06-14 06:46:01 +00:00
// Package robot -----------------------------
// @file : robot.go
// @author : JJXu
// @contact : wavingbear@163.com
// @time : 2025/6/13 17:41
// -------------------------------------------
package robot
import (
"context"
"fmt"
"fonchain-fiee/api/accountFiee"
"fonchain-fiee/pkg/common/ws"
"fonchain-fiee/pkg/service"
2025-06-16 09:58:00 +00:00
"fonchain-fiee/pkg/service/asChat/chatCache"
2025-06-14 06:46:01 +00:00
"fonchain-fiee/pkg/service/asChat/consts"
2025-06-15 08:01:55 +00:00
"fonchain-fiee/pkg/service/asChat/dto"
2025-06-14 06:46:01 +00:00
"log"
"sync"
"time"
)
2025-06-16 09:58:00 +00:00
func NewRobot(cache *chatCache.ChatCache) *Robot {
2025-06-14 06:46:01 +00:00
ctx := context.Background()
robotQuery, err := service.AccountFieeProvider.GetChatUserList(ctx, &accountFiee.GetChatUserListRequest{
Query: &accountFiee.ChatUserData{Role: 3},
Page: 1, PageSize: 1,
})
if err != nil {
panic("聊天机器人初始化失败,err:" + err.Error())
}
var robotInfo *accountFiee.ChatUserData
if robotQuery.Total > 0 {
robotInfo = robotQuery.List[0]
} else {
robotInfo = &accountFiee.ChatUserData{
NickName: "阿泰",
Role: 3,
Origin: "fontree",
}
createChatUserResp, errs := service.AccountFieeProvider.CreateChatUser(ctx, robotInfo)
if errs != nil {
panic("聊天机器人创建失败,err:" + errs.Error())
}
robotInfo = createChatUserResp.Data
}
r := &Robot{
Info: robotInfo,
EventListener: &ws.EventListener{
Name: "robot1",
ListenEvents: []ws.ListenEvent{ //只监听消息推送事件
2025-06-15 08:01:55 +00:00
{ws.EventUserJoin, ws.EventProgressAfter},
2025-06-16 07:02:35 +00:00
{ws.EventChatMessage, ws.EventProgressBefore},
2025-06-14 06:46:01 +00:00
},
Chan: make(ws.ListenEventChan),
},
2025-06-16 09:58:00 +00:00
cache: cache,
2025-06-14 06:46:01 +00:00
}
2025-06-17 01:13:20 +00:00
err = r.ReloadRules(ctx)
2025-06-18 11:47:43 +00:00
fmt.Println("机器人规则加载完成,结果:", err)
2025-06-14 06:46:01 +00:00
consts.ChatRoom.RegisterEventListener(r.EventListener)
go r.Run()
return r
}
type Robot struct {
2025-06-19 03:02:27 +00:00
Info *accountFiee.ChatUserData //机器人信息
joinSessionRules, keywordsRules, noReplyAfterRules []IRobotTask //自动回复规则
DelayTask []IRobotTask //延时任务
ticker *time.Ticker //定时器
stopChan chan struct{} //停止管道
isRunning bool //运行状态
mu sync.Mutex
2025-06-14 06:46:01 +00:00
*ws.EventListener
2025-06-16 09:58:00 +00:00
cache *chatCache.ChatCache
2025-06-14 06:46:01 +00:00
}
2025-06-15 08:01:55 +00:00
//func (r *Robot) Listen(record *accountFiee.ChatRecordData) {
// for _, replyRules := range r.Rules {
// for _, rule := range replyRules.Rules {
// hit, runTime, function := rule.Hit(record)
// if hit && function != nil {
// if runTime.IsZero() {
// go func() {
// err := function(r.Info.ID, replyRules.Response)
// if err != nil {
// log.Printf("聊天机器人[%d]回复消息失败:%v", r.Info.ID, err)
// }
// }()
// } else {
// r.mu.Lock()
// r.DelayTask = append(r.DelayTask, RobotTask{
// RunTime: runTime,
// Run: function,
// Response: replyRules.Response,
// })
// r.mu.Unlock()
// // 添加任务后启动定时任务(如果未运行)
// if !r.isRunning {
// go r.Run()
// }
// }
// break
// }
// }
// }
//}
2025-06-14 06:46:01 +00:00
func (r *Robot) Run() {
r.mu.Lock()
if r.isRunning {
r.mu.Unlock()
return
}
r.isRunning = true
r.ticker = time.NewTicker(time.Second)
r.stopChan = make(chan struct{})
r.mu.Unlock()
defer func() {
r.mu.Lock()
r.isRunning = false
if r.ticker != nil {
r.ticker.Stop()
r.ticker = nil
}
r.stopChan = nil
r.mu.Unlock()
}()
for {
select {
default:
time.Sleep(200 * time.Millisecond)
2025-06-14 06:46:01 +00:00
case <-r.ticker.C:
r.mu.Lock()
if len(r.DelayTask) == 0 {
r.mu.Unlock()
break
//return // 没有任务时退出
}
now := time.Now()
2025-06-18 11:47:43 +00:00
var remainingTasks []IRobotTask
2025-06-14 06:46:01 +00:00
for _, task := range r.DelayTask {
2025-06-18 11:47:43 +00:00
if now.After(task.RunTime()) {
2025-06-14 06:46:01 +00:00
// 执行任务
go func() {
2025-06-18 11:47:43 +00:00
err := task.Run(r.cache)
2025-06-14 06:46:01 +00:00
if err != nil {
2025-06-17 06:21:36 +00:00
log.Printf("聊天机器人[%d]延时回复消息失败:%v", r.Info.ID, err)
} else {
log.Printf("聊天机器人[%d]延时回复消息成功", r.Info.ID)
2025-06-14 06:46:01 +00:00
}
}()
} else {
// 保留未到期的任务
remainingTasks = append(remainingTasks, task)
}
}
r.DelayTask = remainingTasks
r.mu.Unlock()
case <-r.stopChan:
return
case event := <-r.EventListener.Chan:
fmt.Printf("robot listen event:%#v\n", event)
2025-06-19 01:23:08 +00:00
r.mu.Lock()
2025-06-19 03:02:27 +00:00
//加入聊天室规则
hit := false
for _, rule := range r.joinSessionRules {
hit = rule.Hit(event, r.Info)
2025-06-19 03:12:15 +00:00
fmt.Printf("规则【%s】校验结果:%v\n", rule.GetTitle(), hit)
if hit {
2025-06-19 03:02:27 +00:00
if rule.RunTime().IsZero() {
err := rule.Run(r.cache)
if err != nil {
log.Printf("robot 执行任务失败:%v\n", err)
2025-06-15 08:01:55 +00:00
}
} else {
2025-06-19 03:02:27 +00:00
r.RegisterDelayTask(rule)
}
}
}
if !hit {
for _, rule := range r.keywordsRules {
hit = rule.Hit(event, r.Info)
2025-06-19 03:12:15 +00:00
fmt.Printf("规则【%s】校验结果:%v\n", rule.GetTitle(), hit)
2025-06-19 03:02:27 +00:00
if hit {
fmt.Println("命中规则:", rule.GetTitle())
if rule.RunTime().IsZero() {
err := rule.Run(r.cache)
if err != nil {
log.Printf("robot 执行任务失败:%v\n", err)
}
} else {
r.RegisterDelayTask(rule)
}
}
}
}
if !hit {
for _, rule := range r.noReplyAfterRules {
2025-06-19 03:12:15 +00:00
hit = rule.Hit(event, r.Info)
fmt.Printf("规则【%s】校验结果:%v\n", rule.GetTitle(), hit)
2025-06-19 03:02:27 +00:00
if hit {
fmt.Println("命中规则:", rule.GetTitle())
if rule.RunTime().IsZero() {
err := rule.Run(r.cache)
if err != nil {
log.Printf("robot 执行任务失败:%v\n", err)
}
} else {
r.RegisterDelayTask(rule)
}
2025-06-15 08:01:55 +00:00
}
}
}
2025-06-19 01:23:08 +00:00
r.mu.Unlock()
2025-06-14 06:46:01 +00:00
}
}
}
// Stop 主动停止机器人的定时任务
func (r *Robot) Stop() {
r.mu.Lock()
if r.stopChan != nil {
close(r.stopChan)
}
r.mu.Unlock()
}
2025-06-18 11:47:43 +00:00
func (r *Robot) RegisterDelayTask(task IRobotTask) {
if task.Run == nil {
return
}
r.DelayTask = append(r.DelayTask, task)
}
2025-06-17 01:31:47 +00:00
// 重载回复规则
2025-06-17 01:13:20 +00:00
func (r *Robot) ReloadRules(ctx context.Context) error {
r.mu.Lock()
defer r.mu.Unlock()
2025-06-19 03:02:27 +00:00
r.joinSessionRules = []IRobotTask{}
r.keywordsRules = []IRobotTask{}
r.noReplyAfterRules = []IRobotTask{}
2025-06-17 01:13:20 +00:00
ruleListRes, err := service.AccountFieeProvider.GetChatAutoReplyRulerList(ctx, &accountFiee.GetChatAutoReplyRulerListRequest{
Query: &accountFiee.ChatAutoReplyRulerData{Status: 1},
Page: 1,
PageSize: -1,
})
if err != nil {
log.Printf("robot 查询回复规则失败:%v\n", err)
return fmt.Errorf("robot 查询回复规则失败:%v\n", err)
} else {
var data []*dto.ChatAutoReplyData
for _, v := range ruleListRes.List {
tmp := dto.ChatAutoReplyData{}
tmp.Parse(v)
data = append(data, &tmp)
}
2025-06-19 03:02:27 +00:00
ParseReplyRule(data)
2025-06-17 01:13:20 +00:00
}
return nil
}