chatmgr.go 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. package chat
  2. import (
  3. "encoding/json"
  4. "os"
  5. "sort"
  6. "sync"
  7. "time"
  8. "bet24.com/log"
  9. "bet24.com/servers/common"
  10. "bet24.com/servers/coreservice/keyword"
  11. "bet24.com/servers/coreservice/serviceconfig"
  12. inventory "bet24.com/servers/micros/item_inventory/proto"
  13. item "bet24.com/servers/micros/item_inventory/proto"
  14. cash "bet24.com/servers/micros/money/proto"
  15. notification "bet24.com/servers/micros/notification/proto"
  16. platformconfig "bet24.com/servers/micros/platformconfig/proto"
  17. task "bet24.com/servers/micros/task/proto"
  18. user "bet24.com/servers/micros/userservices/proto"
  19. )
  20. const (
  21. Channel_World = iota // 世界频道, 目前只有一个世界频道,后续有需求再加
  22. Channel_Speaker // 大喇叭频道
  23. channel_Max
  24. )
  25. const (
  26. MessageType_Normal = iota // 普通消息
  27. MessageType_Gift // 1礼物消息
  28. MessageType_Room // 2房间消息
  29. )
  30. type Chat_MSg struct {
  31. ChannelID int //聊天频道, 目前只有世界频道
  32. SendUserID int //发送者ID
  33. Vip int //VIP等级
  34. NickName string //昵称
  35. FaceUrl string //头像URL
  36. FaceId int //头像ID
  37. Sex int //性别
  38. RecvUserID int //接收者ID,私聊备用
  39. ChatMsg string //内容
  40. SendTime string
  41. Decorations []user.UserDecoration
  42. MsgType int
  43. VipExpire int
  44. }
  45. type chatmgr struct {
  46. chatMsgList map[int][]Chat_MSg //key: ChannelID
  47. lock *sync.RWMutex
  48. robotChats []robot_chat
  49. }
  50. type robot_chat struct {
  51. UserId int // 用户id
  52. Msg string // 消息
  53. Seconds int // 间隔时间(秒)
  54. BeginTime string // 开始时间
  55. EndTime string // 截止时间
  56. SendTime string // 发送时间
  57. }
  58. const config_key = "robotchat_config"
  59. const refresh_config_sec = 600
  60. func newChatMgr() *chatmgr {
  61. cm := &chatmgr{}
  62. cm.chatMsgList = make(map[int][]Chat_MSg)
  63. for i := Channel_World; i < channel_Max; i++ {
  64. var l []Chat_MSg
  65. cm.chatMsgList[i] = l
  66. }
  67. cm.lock = &sync.RWMutex{}
  68. cm.loadRobotChats()
  69. go cm.sendRefresh()
  70. log.Debug("chat manager running")
  71. return cm
  72. }
  73. func (m *chatmgr) loadRobotChats() {
  74. defer func() {
  75. time.AfterFunc(refresh_config_sec*time.Second, m.loadRobotChats)
  76. }()
  77. configString := platformconfig.GetConfig(config_key)
  78. if configString == "" {
  79. data, err := os.ReadFile("fishconf/robotchats.json")
  80. if err != nil {
  81. log.Release("gold2chipwheelmgr.loadData read robotchats failed")
  82. return
  83. }
  84. configString = string(data)
  85. platformconfig.SetConfig(config_key, configString)
  86. } else {
  87. log.Debug("chat.chatmgr loading config from redis")
  88. }
  89. m.lock.Lock()
  90. defer m.lock.Unlock()
  91. err := json.Unmarshal([]byte(configString), &m.robotChats)
  92. if err != nil {
  93. log.Release("chat.chatmgr.loadData Unmarshal robotchats failed err:%v", err)
  94. return
  95. }
  96. }
  97. // 获取机器人信息
  98. func (cm *chatmgr) getRobotChatInfo(userId int) robot_chat {
  99. cm.lock.RLock()
  100. defer cm.lock.RUnlock()
  101. for _, v := range cm.robotChats {
  102. if v.UserId == userId {
  103. return v
  104. }
  105. }
  106. return robot_chat{}
  107. }
  108. // 获取机器人列表
  109. func (cm *chatmgr) getRobotChatList() []robot_chat {
  110. cm.lock.RLock()
  111. defer cm.lock.RUnlock()
  112. sort.SliceStable(cm.robotChats, func(i, j int) bool {
  113. return cm.robotChats[i].EndTime > cm.robotChats[j].EndTime
  114. })
  115. return cm.robotChats
  116. }
  117. // 添加机器人信息
  118. func (cm *chatmgr) addRobotChat(userId int, msg string, seconds int, beginTime, endTime string) bool {
  119. if info := cm.getRobotChatInfo(userId); info.UserId > 0 {
  120. return cm.updateRobotChat(userId, msg, seconds, beginTime, endTime)
  121. }
  122. cm.lock.Lock()
  123. defer cm.lock.Unlock()
  124. cm.robotChats = append(cm.robotChats, robot_chat{
  125. UserId: userId,
  126. Msg: msg,
  127. Seconds: seconds,
  128. BeginTime: beginTime,
  129. EndTime: endTime,
  130. SendTime: time.Now().Format(common.Layout),
  131. })
  132. go cm.setRobotChatConfig()
  133. return true
  134. }
  135. // 修改机器人信息
  136. func (cm *chatmgr) updateRobotChat(userId int, msg string, seconds int, beginTime, endTime string) bool {
  137. cm.lock.Lock()
  138. defer cm.lock.Unlock()
  139. for i := 0; i < len(cm.robotChats); i++ {
  140. if cm.robotChats[i].UserId != userId {
  141. continue
  142. }
  143. cm.robotChats[i].Msg = msg
  144. cm.robotChats[i].Seconds = seconds
  145. cm.robotChats[i].BeginTime = beginTime
  146. cm.robotChats[i].EndTime = endTime
  147. go cm.setRobotChatConfig()
  148. return true
  149. }
  150. return false
  151. }
  152. // 删除机器人
  153. func (cm *chatmgr) delRobotChat(userId int) bool {
  154. for i := 0; i < len(cm.robotChats); i++ {
  155. if cm.robotChats[i].UserId != userId {
  156. continue
  157. }
  158. cm.robotChats = append(cm.robotChats[:i], cm.robotChats[i+1:]...)
  159. go cm.setRobotChatConfig()
  160. return true
  161. }
  162. return false
  163. }
  164. // 写入redis
  165. func (cm *chatmgr) setRobotChatConfig() {
  166. cm.lock.RLock()
  167. d, _ := json.Marshal(cm.robotChats)
  168. cm.lock.RUnlock()
  169. platformconfig.SetConfig(config_key, string(d))
  170. }
  171. // 按条件发送机器人聊天信息
  172. func (cm *chatmgr) sendRobotChatMsg() {
  173. now := common.GetNowTime()
  174. cm.lock.RLock()
  175. defer cm.lock.RUnlock()
  176. for i := 0; i < len(cm.robotChats); i++ {
  177. v := &cm.robotChats[i]
  178. begin := common.ParseTime(v.BeginTime)
  179. // log.Debug("chatmgr.sendRobotChatMsg v=%+v now=%v begin=%v", v, now, begin)
  180. if now.Before(begin) {
  181. continue
  182. }
  183. end := common.ParseTime(v.EndTime)
  184. // log.Debug("chatmgr.sendRobotChatMsg v=%+v now=%v end=%v", v, now, end)
  185. if now.After(end) {
  186. continue
  187. }
  188. send := common.ParseTime(v.SendTime)
  189. // log.Debug("chatmgr.sendRobotChatMsg v=%+v now=%v send=%v", v, now, send)
  190. if now.Sub(send).Seconds() < float64(v.Seconds) {
  191. continue
  192. }
  193. // log.Debug("chatmgr.sendRobotChatMsg now=%v v=%+v 已发送", now, v)
  194. v.SendTime = now.Format(common.Layout)
  195. u := user.GetUserInfo(v.UserId)
  196. if u == nil {
  197. log.Release("chatmgr.sendRefresh userId=%d ==> %+v", v.UserId, u)
  198. continue
  199. }
  200. go cm.sendChatMsg(Channel_Speaker, u.UserId, u.FaceId, u.Sex, u.Vip, -1, u.NickName,
  201. u.FaceUrl, v.Msg, "127.0.0.1", true, MessageType_Normal, u.VipExpire)
  202. }
  203. }
  204. func (cm *chatmgr) sendRefresh() {
  205. ticker := time.NewTicker(1 * time.Second)
  206. go func(t *time.Ticker) {
  207. for {
  208. select {
  209. case <-t.C:
  210. cm.sendRobotChatMsg()
  211. }
  212. }
  213. }(ticker)
  214. }
  215. func (cm *chatmgr) getChatMsg(userId, channelID int) string {
  216. cm.lock.RLock()
  217. defer cm.lock.RUnlock()
  218. for k, l := range cm.chatMsgList {
  219. if k == channelID {
  220. d, _ := json.Marshal(l)
  221. // go notification.AddNotification(userId, notification.Notification_Chat, string(d))
  222. return string(d)
  223. }
  224. }
  225. return ""
  226. }
  227. func (cm *chatmgr) dump(param string) {
  228. log.Release("chatmgr.dump ----------")
  229. defer log.Release("chatmgr.dump end ++++++++++++++++")
  230. log.Release(" %s", cm.getChatMsg(0, 0))
  231. }
  232. func (cm *chatmgr) sendChatMsg(channelID, userId, faceId, sex, vipLevel, recvID int,
  233. nickName, faceUrl, chatMsg, ipAddress string, isRobot bool, messageType, vipExpire int) bool {
  234. if channelID >= channel_Max || channelID < 0 {
  235. return false
  236. }
  237. // 大喇叭,需要扣道具
  238. if channelID == Channel_Speaker && !isRobot {
  239. ok, errMsg := inventory.Consume(userId, item.Item_Speaker, 0, 1, 0)
  240. if !ok {
  241. log.Release("chatMgr.sendChatMsg sending speaker comsume item failed %s", errMsg)
  242. return false
  243. }
  244. } else {
  245. //非vip用户要扣金币
  246. cost := serviceconfig.SpecialCfg.ChatCost
  247. if isRobot {
  248. cost = 0
  249. }
  250. if cost > 0 && userId > 0 && vipLevel < 1 {
  251. _, m := cash.GetMoney(userId)
  252. if m < cost {
  253. return false
  254. }
  255. cash.ReduceMoney(userId, serviceconfig.SpecialCfg.ChatCost, common.LOGTYPE_CHAT, "聊天", "聊天", ipAddress)
  256. }
  257. }
  258. if channelID == Channel_World && !isRobot {
  259. task.DoTaskAction(userId, task.TaskAction_worldchat, 1, task.TaskScope{})
  260. }
  261. var msg Chat_MSg
  262. msg.ChannelID = channelID
  263. msg.SendUserID = userId
  264. msg.Vip = vipLevel
  265. msg.NickName = nickName
  266. msg.FaceUrl = faceUrl
  267. msg.FaceId = faceId
  268. msg.Decorations = user.GetUserDecoration(userId)
  269. msg.RecvUserID = recvID
  270. msg.ChatMsg = chatMsg
  271. msg.Sex = sex
  272. msg.MsgType = messageType
  273. msg.SendTime = time.Now().Format("2006-01-02 15:04:05")
  274. msg.VipExpire = vipExpire
  275. msg.ChatMsg = keyword.ParseKeyword(msg.ChatMsg)
  276. cm.lock.Lock()
  277. l := cm.chatMsgList[channelID]
  278. l = append(l, msg)
  279. //只保留50条
  280. if len(l) > 50 {
  281. l = append(l[:0], l[1:]...)
  282. }
  283. cm.chatMsgList[channelID] = l
  284. cm.lock.Unlock()
  285. //广播聊天消息
  286. d, _ := json.Marshal(msg)
  287. //世界频道,广播给所有人
  288. //if channelID == Channel_World {
  289. log.Debug("add notification of world chat")
  290. go notification.AddNotification(-1, notification.Notification_Chat, string(d))
  291. //}
  292. return true
  293. }