| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- package chat
- import (
- "encoding/json"
- "os"
- "sort"
- "sync"
- "time"
- "bet24.com/log"
- "bet24.com/servers/common"
- "bet24.com/servers/coreservice/keyword"
- "bet24.com/servers/coreservice/serviceconfig"
- inventory "bet24.com/servers/micros/item_inventory/proto"
- item "bet24.com/servers/micros/item_inventory/proto"
- cash "bet24.com/servers/micros/money/proto"
- notification "bet24.com/servers/micros/notification/proto"
- platformconfig "bet24.com/servers/micros/platformconfig/proto"
- task "bet24.com/servers/micros/task/proto"
- user "bet24.com/servers/micros/userservices/proto"
- )
- const (
- Channel_World = iota // 世界频道, 目前只有一个世界频道,后续有需求再加
- Channel_Speaker // 大喇叭频道
- channel_Max
- )
- const (
- MessageType_Normal = iota // 普通消息
- MessageType_Gift // 1礼物消息
- MessageType_Room // 2房间消息
- )
- type Chat_MSg struct {
- ChannelID int //聊天频道, 目前只有世界频道
- SendUserID int //发送者ID
- Vip int //VIP等级
- NickName string //昵称
- FaceUrl string //头像URL
- FaceId int //头像ID
- Sex int //性别
- RecvUserID int //接收者ID,私聊备用
- ChatMsg string //内容
- SendTime string
- Decorations []user.UserDecoration
- MsgType int
- VipExpire int
- }
- type chatmgr struct {
- chatMsgList map[int][]Chat_MSg //key: ChannelID
- lock *sync.RWMutex
- robotChats []robot_chat
- }
- type robot_chat struct {
- UserId int // 用户id
- Msg string // 消息
- Seconds int // 间隔时间(秒)
- BeginTime string // 开始时间
- EndTime string // 截止时间
- SendTime string // 发送时间
- }
- const config_key = "robotchat_config"
- const refresh_config_sec = 600
- func newChatMgr() *chatmgr {
- cm := &chatmgr{}
- cm.chatMsgList = make(map[int][]Chat_MSg)
- for i := Channel_World; i < channel_Max; i++ {
- var l []Chat_MSg
- cm.chatMsgList[i] = l
- }
- cm.lock = &sync.RWMutex{}
- cm.loadRobotChats()
- go cm.sendRefresh()
- log.Debug("chat manager running")
- return cm
- }
- func (m *chatmgr) loadRobotChats() {
- defer func() {
- time.AfterFunc(refresh_config_sec*time.Second, m.loadRobotChats)
- }()
- configString := platformconfig.GetConfig(config_key)
- if configString == "" {
- data, err := os.ReadFile("fishconf/robotchats.json")
- if err != nil {
- log.Release("gold2chipwheelmgr.loadData read robotchats failed")
- return
- }
- configString = string(data)
- platformconfig.SetConfig(config_key, configString)
- } else {
- log.Debug("chat.chatmgr loading config from redis")
- }
- m.lock.Lock()
- defer m.lock.Unlock()
- err := json.Unmarshal([]byte(configString), &m.robotChats)
- if err != nil {
- log.Release("chat.chatmgr.loadData Unmarshal robotchats failed err:%v", err)
- return
- }
- }
- // 获取机器人信息
- func (cm *chatmgr) getRobotChatInfo(userId int) robot_chat {
- cm.lock.RLock()
- defer cm.lock.RUnlock()
- for _, v := range cm.robotChats {
- if v.UserId == userId {
- return v
- }
- }
- return robot_chat{}
- }
- // 获取机器人列表
- func (cm *chatmgr) getRobotChatList() []robot_chat {
- cm.lock.RLock()
- defer cm.lock.RUnlock()
- sort.SliceStable(cm.robotChats, func(i, j int) bool {
- return cm.robotChats[i].EndTime > cm.robotChats[j].EndTime
- })
- return cm.robotChats
- }
- // 添加机器人信息
- func (cm *chatmgr) addRobotChat(userId int, msg string, seconds int, beginTime, endTime string) bool {
- if info := cm.getRobotChatInfo(userId); info.UserId > 0 {
- return cm.updateRobotChat(userId, msg, seconds, beginTime, endTime)
- }
- cm.lock.Lock()
- defer cm.lock.Unlock()
- cm.robotChats = append(cm.robotChats, robot_chat{
- UserId: userId,
- Msg: msg,
- Seconds: seconds,
- BeginTime: beginTime,
- EndTime: endTime,
- SendTime: time.Now().Format(common.Layout),
- })
- go cm.setRobotChatConfig()
- return true
- }
- // 修改机器人信息
- func (cm *chatmgr) updateRobotChat(userId int, msg string, seconds int, beginTime, endTime string) bool {
- cm.lock.Lock()
- defer cm.lock.Unlock()
- for i := 0; i < len(cm.robotChats); i++ {
- if cm.robotChats[i].UserId != userId {
- continue
- }
- cm.robotChats[i].Msg = msg
- cm.robotChats[i].Seconds = seconds
- cm.robotChats[i].BeginTime = beginTime
- cm.robotChats[i].EndTime = endTime
- go cm.setRobotChatConfig()
- return true
- }
- return false
- }
- // 删除机器人
- func (cm *chatmgr) delRobotChat(userId int) bool {
- for i := 0; i < len(cm.robotChats); i++ {
- if cm.robotChats[i].UserId != userId {
- continue
- }
- cm.robotChats = append(cm.robotChats[:i], cm.robotChats[i+1:]...)
- go cm.setRobotChatConfig()
- return true
- }
- return false
- }
- // 写入redis
- func (cm *chatmgr) setRobotChatConfig() {
- cm.lock.RLock()
- d, _ := json.Marshal(cm.robotChats)
- cm.lock.RUnlock()
- platformconfig.SetConfig(config_key, string(d))
- }
- // 按条件发送机器人聊天信息
- func (cm *chatmgr) sendRobotChatMsg() {
- now := common.GetNowTime()
- cm.lock.RLock()
- defer cm.lock.RUnlock()
- for i := 0; i < len(cm.robotChats); i++ {
- v := &cm.robotChats[i]
- begin := common.ParseTime(v.BeginTime)
- // log.Debug("chatmgr.sendRobotChatMsg v=%+v now=%v begin=%v", v, now, begin)
- if now.Before(begin) {
- continue
- }
- end := common.ParseTime(v.EndTime)
- // log.Debug("chatmgr.sendRobotChatMsg v=%+v now=%v end=%v", v, now, end)
- if now.After(end) {
- continue
- }
- send := common.ParseTime(v.SendTime)
- // log.Debug("chatmgr.sendRobotChatMsg v=%+v now=%v send=%v", v, now, send)
- if now.Sub(send).Seconds() < float64(v.Seconds) {
- continue
- }
- // log.Debug("chatmgr.sendRobotChatMsg now=%v v=%+v 已发送", now, v)
- v.SendTime = now.Format(common.Layout)
- u := user.GetUserInfo(v.UserId)
- if u == nil {
- log.Release("chatmgr.sendRefresh userId=%d ==> %+v", v.UserId, u)
- continue
- }
- go cm.sendChatMsg(Channel_Speaker, u.UserId, u.FaceId, u.Sex, u.Vip, -1, u.NickName,
- u.FaceUrl, v.Msg, "127.0.0.1", true, MessageType_Normal, u.VipExpire)
- }
- }
- func (cm *chatmgr) sendRefresh() {
- ticker := time.NewTicker(1 * time.Second)
- go func(t *time.Ticker) {
- for {
- select {
- case <-t.C:
- cm.sendRobotChatMsg()
- }
- }
- }(ticker)
- }
- func (cm *chatmgr) getChatMsg(userId, channelID int) string {
- cm.lock.RLock()
- defer cm.lock.RUnlock()
- for k, l := range cm.chatMsgList {
- if k == channelID {
- d, _ := json.Marshal(l)
- // go notification.AddNotification(userId, notification.Notification_Chat, string(d))
- return string(d)
- }
- }
- return ""
- }
- func (cm *chatmgr) dump(param string) {
- log.Release("chatmgr.dump ----------")
- defer log.Release("chatmgr.dump end ++++++++++++++++")
- log.Release(" %s", cm.getChatMsg(0, 0))
- }
- func (cm *chatmgr) sendChatMsg(channelID, userId, faceId, sex, vipLevel, recvID int,
- nickName, faceUrl, chatMsg, ipAddress string, isRobot bool, messageType, vipExpire int) bool {
- if channelID >= channel_Max || channelID < 0 {
- return false
- }
- // 大喇叭,需要扣道具
- if channelID == Channel_Speaker && !isRobot {
- ok, errMsg := inventory.Consume(userId, item.Item_Speaker, 0, 1, 0)
- if !ok {
- log.Release("chatMgr.sendChatMsg sending speaker comsume item failed %s", errMsg)
- return false
- }
- } else {
- //非vip用户要扣金币
- cost := serviceconfig.SpecialCfg.ChatCost
- if isRobot {
- cost = 0
- }
- if cost > 0 && userId > 0 && vipLevel < 1 {
- _, m := cash.GetMoney(userId)
- if m < cost {
- return false
- }
- cash.ReduceMoney(userId, serviceconfig.SpecialCfg.ChatCost, common.LOGTYPE_CHAT, "聊天", "聊天", ipAddress)
- }
- }
- if channelID == Channel_World && !isRobot {
- task.DoTaskAction(userId, task.TaskAction_worldchat, 1, task.TaskScope{})
- }
- var msg Chat_MSg
- msg.ChannelID = channelID
- msg.SendUserID = userId
- msg.Vip = vipLevel
- msg.NickName = nickName
- msg.FaceUrl = faceUrl
- msg.FaceId = faceId
- msg.Decorations = user.GetUserDecoration(userId)
- msg.RecvUserID = recvID
- msg.ChatMsg = chatMsg
- msg.Sex = sex
- msg.MsgType = messageType
- msg.SendTime = time.Now().Format("2006-01-02 15:04:05")
- msg.VipExpire = vipExpire
- msg.ChatMsg = keyword.ParseKeyword(msg.ChatMsg)
- cm.lock.Lock()
- l := cm.chatMsgList[channelID]
- l = append(l, msg)
- //只保留50条
- if len(l) > 50 {
- l = append(l[:0], l[1:]...)
- }
- cm.chatMsgList[channelID] = l
- cm.lock.Unlock()
- //广播聊天消息
- d, _ := json.Marshal(msg)
- //世界频道,广播给所有人
- //if channelID == Channel_World {
- log.Debug("add notification of world chat")
- go notification.AddNotification(-1, notification.Notification_Chat, string(d))
- //}
- return true
- }
|