role_statistics.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. package model
  2. import (
  3. "github.com/gogf/gf/text/gstr"
  4. "hash/crc32"
  5. "rocommon/util"
  6. "roserver/baseserver/model"
  7. "roserver/serverproto"
  8. "unicode/utf8"
  9. )
  10. type RoleStatistic struct {
  11. SaveObject
  12. cheatData map[int32]int32
  13. //cheat chat msg
  14. cheatMsgPersonalCheckTime uint64
  15. cheatChatPersonal map[uint64]*serverproto.RoleCheatChat //恶意私聊 [消息识别码]
  16. cheatChatPersonalContentList []string
  17. cheatMsgPublicCheckTime uint64
  18. cheatChatPublic map[uint64]int //世界&公会聊天 [消息识别码,数量]
  19. cheatChatPublicContentList []string
  20. }
  21. var GlobalCheatChatPublicContentList = map[uint64]string{} //全局聊天处理
  22. const (
  23. CheatType_GMWEB = 0 //后台进行封号操作
  24. CheatType_TimeScale = 1 //时间加速
  25. CheatType_NormalLevel = 2 //普通关卡挑战时间过短
  26. CheatType_TowerLevel = 3 //爬塔关卡挑战时间过短
  27. CheatType_PersonalChat = 4 //恶意私聊:账号封停功能
  28. CheatType_PublicChat = 5 //世界频道、公会频道:账号禁言功能
  29. )
  30. func newRoleStatistic(r *Role) *RoleStatistic {
  31. roleStatistics := &RoleStatistic{
  32. SaveObject: SaveObject{
  33. role: r,
  34. },
  35. cheatChatPersonal: map[uint64]*serverproto.RoleCheatChat{},
  36. cheatChatPublic: map[uint64]int{},
  37. }
  38. roleStatistics.cheatData = make(map[int32]int32)
  39. return roleStatistics
  40. }
  41. func (this *RoleStatistic) Load(msg interface{}) bool {
  42. proRole := msg.(*serverproto.Role)
  43. if proRole.RoleStatistic != nil {
  44. if len(proRole.RoleStatistic.CheatData) > 0 {
  45. for _, data := range proRole.RoleStatistic.CheatData {
  46. this.cheatData[data.Key] = data.Value
  47. }
  48. }
  49. }
  50. return true
  51. }
  52. func (this *RoleStatistic) Save() {
  53. this.SetDirty(false)
  54. util.InfoF("uid=%v RoleStatistic save...", this.role.GetUUid())
  55. saveMsg := &serverproto.SSStatisticsDataSaveReq{
  56. Statistics: &serverproto.RoleStatistic{},
  57. }
  58. for key, value := range this.cheatData {
  59. saveMsg.Statistics.CheatData = append(saveMsg.Statistics.CheatData, &serverproto.KeyValueType{
  60. Key: key,
  61. Value: value,
  62. })
  63. }
  64. this.role.SendDb(saveMsg)
  65. }
  66. func (this *RoleStatistic) RecordCheatData(cheatType int32) {
  67. this.cheatData[cheatType] += 1
  68. this.SetDirty(true)
  69. util.ErrorF("uid=%v RoleStatistic name=%v cheat type=%v count=%v", this.role.GetUUid(), string(this.role.GetNickName()), cheatType, this.cheatData[cheatType])
  70. this.cheatKick(cheatType)
  71. }
  72. func (this *RoleStatistic) ClearCheatData() {
  73. util.InfoF("uid=%v RoleStatistic ClearCheatData cheatData=%v", this.cheatData)
  74. this.cheatData = map[int32]int32{}
  75. this.SetDirty(true)
  76. }
  77. func (this *RoleStatistic) cheatKick(cheatType int32) {
  78. //玩家作弊,踢下线
  79. var cheatNum = this.cheatData[cheatType]
  80. //for _, val := range this.cheatData {
  81. // cheatNum += val
  82. //}
  83. var banTime uint64 = 0
  84. if cheatNum >= model.GlobalMaxCheatBanNum {
  85. banTime = model.GlobalMaxCheatBanTime
  86. } else {
  87. if tmpTime, ok := model.GlobalCheatBanTime[cheatNum]; ok {
  88. banTime = tmpTime
  89. }
  90. }
  91. if banTime <= 0 {
  92. if cheatType != CheatType_PublicChat {
  93. this.role.KickWithSave(int32(serverproto.ErrorCode_ERROR_SERVER_KICK_CHEAT))
  94. }
  95. } else {
  96. if cheatType == CheatType_PublicChat {
  97. //禁言
  98. this.role.BanRoleChat(true, banTime, cheatType)
  99. } else {
  100. //封号
  101. this.role.BanRole(true, banTime, cheatType)
  102. }
  103. }
  104. }
  105. func (this *RoleStatistic) GetCheatErrorCode(cheatType int32) int32 {
  106. switch cheatType {
  107. case CheatType_TimeScale:
  108. return int32(serverproto.ErrorCode_ERROR_ROLE_BANED_TYPE_TIME)
  109. case CheatType_NormalLevel:
  110. return int32(serverproto.ErrorCode_ERROR_ROLE_BANED_TYPE_LEVEL)
  111. case CheatType_TowerLevel:
  112. return int32(serverproto.ErrorCode_ERROR_ROLE_BANED_TYPE_LEVEL)
  113. case CheatType_PersonalChat:
  114. return int32(serverproto.ErrorCode_ERROR_ROLE_BANED_TYPE_PERSONALCHAT)
  115. case CheatType_PublicChat:
  116. return int32(serverproto.ErrorCode_ERROR_ROLE_BANED_TYPE_PERSONALCHAT)
  117. }
  118. return int32(serverproto.ErrorCode_ERROR_ROLE_BANED)
  119. }
  120. //true可以发送聊天 false屏蔽发言
  121. func (this *RoleStatistic) CheckChatMsg(msgType int32, targetUid uint64, chatContent string) bool {
  122. bSendMsg := true
  123. if msgType == int32(serverproto.ChatMessageType_CMT_PERSONAL) {
  124. if this.role.GetRoleLevel() > model.GlobalCheatPersonalChat.Level ||
  125. int32(this.role.GetTotalRecharge()) >= model.GlobalCheatPersonalChat.RechargeNum {
  126. return bSendMsg
  127. }
  128. nowTime := util.GetTimeMilliseconds()
  129. if nowTime > this.cheatMsgPersonalCheckTime &&
  130. nowTime-this.cheatMsgPersonalCheckTime > model.GlobalCheatPersonalChat.ChatDuration {
  131. this.cheatMsgPersonalCheckTime = nowTime
  132. this.cheatChatPersonal = map[uint64]*serverproto.RoleCheatChat{}
  133. }
  134. //trim转义字符
  135. bMatch := SensitiveUtil.IsMatch(chatContent)
  136. if bMatch {
  137. bSendMsg = false
  138. return bSendMsg
  139. }
  140. //1,相同内容屏蔽操作
  141. chatContentCrc32 := uint64(crc32.ChecksumIEEE([]byte(chatContent)))
  142. chatCrc32Data, ok := this.cheatChatPersonal[chatContentCrc32]
  143. if ok {
  144. bFindTargetUid := false
  145. for idx := 0; idx < len(chatCrc32Data.TargetId); idx++ {
  146. if chatCrc32Data.TargetId[idx] == targetUid {
  147. bFindTargetUid = true
  148. break
  149. }
  150. }
  151. if !bFindTargetUid {
  152. chatCrc32Data.TargetId = append(chatCrc32Data.TargetId, targetUid)
  153. }
  154. //封号/踢人
  155. if len(chatCrc32Data.TargetId) >= model.GlobalCheatPersonalChat.ParamList[0] &&
  156. model.GlobalCheatPersonalChat.ParamList[0] > 0 {
  157. this.RecordCheatData(CheatType_PersonalChat)
  158. this.cheatMsgPersonalCheckTime = nowTime
  159. this.cheatChatPersonal = map[uint64]*serverproto.RoleCheatChat{}
  160. bSendMsg = false
  161. return bSendMsg
  162. }
  163. } else {
  164. chatCrc32Data = &serverproto.RoleCheatChat{
  165. ChatMsgCrc32: chatContentCrc32,
  166. }
  167. chatCrc32Data.TargetId = append(chatCrc32Data.TargetId, targetUid)
  168. this.cheatChatPersonal[chatContentCrc32] = chatCrc32Data
  169. }
  170. //2,相似度屏蔽操作
  171. msgLen := utf8.RuneCountInString(chatContent)
  172. if msgLen > 10 {
  173. similarCount := 0
  174. for idx := 0; idx < len(this.cheatChatPersonalContentList); idx++ {
  175. var tmpPercent float64 = 0
  176. gstr.SimilarText(this.cheatChatPersonalContentList[idx], chatContent, &tmpPercent)
  177. if tmpPercent >= 50.0 {
  178. similarCount++
  179. }
  180. }
  181. if similarCount >= 3 {
  182. this.RecordCheatData(CheatType_PublicChat)
  183. this.cheatMsgPublicCheckTime = nowTime
  184. bSendMsg = false
  185. }
  186. this.cheatChatPersonalContentList = append(this.cheatChatPersonalContentList, chatContent)
  187. if len(this.cheatChatPersonalContentList) >= 25 {
  188. msgLen := len(this.cheatChatPersonalContentList)
  189. this.cheatChatPersonalContentList = this.cheatChatPersonalContentList[msgLen-10:]
  190. }
  191. }
  192. } else if msgType == int32(serverproto.ChatMessageType_CMT_WORLD) ||
  193. msgType == int32(serverproto.ChatMessageType_CMT_GUILD) {
  194. if this.role.GetRoleLevel() > model.GlobalCheatPublicChat.Level ||
  195. int32(this.role.GetTotalRecharge()) >= model.GlobalCheatPublicChat.RechargeNum {
  196. return bSendMsg
  197. }
  198. nowTime := util.GetTimeMilliseconds()
  199. if this.role.GetRoleBase().roleBase.ChatBanTime*1000 > nowTime {
  200. bSendMsg = false
  201. return bSendMsg
  202. }
  203. if nowTime > this.cheatMsgPublicCheckTime &&
  204. nowTime-this.cheatMsgPublicCheckTime > model.GlobalCheatPublicChat.ChatDuration {
  205. this.cheatMsgPublicCheckTime = nowTime
  206. this.cheatChatPublic = map[uint64]int{}
  207. }
  208. //trim转义字符
  209. bMatch := SensitiveUtil.IsMatch(chatContent)
  210. if bMatch {
  211. bSendMsg = false
  212. return bSendMsg
  213. }
  214. //全局相似度匹配操作(全局中存放的消息队列为禁言玩家的消息列表)
  215. //1,相同内容屏蔽操作
  216. chatContentCrc32 := uint64(crc32.ChecksumIEEE([]byte(chatContent)))
  217. chatCrc32Data, ok := this.cheatChatPublic[chatContentCrc32]
  218. if ok {
  219. if chatCrc32Data >= model.GlobalCheatPublicChat.ParamList[0] &&
  220. model.GlobalCheatPublicChat.ParamList[0] > 0 {
  221. this.RecordCheatData(CheatType_PublicChat)
  222. this.cheatMsgPublicCheckTime = nowTime
  223. this.cheatChatPublic = map[uint64]int{}
  224. bSendMsg = false
  225. return bSendMsg
  226. } else {
  227. this.cheatChatPublic[chatContentCrc32]++
  228. }
  229. } else {
  230. this.cheatChatPublic[chatContentCrc32]++
  231. }
  232. //2,相似度屏蔽操作
  233. msgLen := utf8.RuneCountInString(chatContent)
  234. if msgLen >= 10 {
  235. similarCount := 0
  236. for idx := 0; idx < len(this.cheatChatPublicContentList); idx++ {
  237. var tmpPercent float64 = 0
  238. gstr.SimilarText(this.cheatChatPublicContentList[idx], chatContent, &tmpPercent)
  239. if tmpPercent >= 50.0 {
  240. similarCount++
  241. }
  242. }
  243. if similarCount >= 3 {
  244. this.RecordCheatData(CheatType_PublicChat)
  245. this.cheatMsgPublicCheckTime = nowTime
  246. bSendMsg = false
  247. }
  248. this.cheatChatPublicContentList = append(this.cheatChatPublicContentList, chatContent)
  249. if len(this.cheatChatPublicContentList) >= 25 {
  250. msgLen := len(this.cheatChatPublicContentList)
  251. this.cheatChatPublicContentList = this.cheatChatPublicContentList[msgLen-10:]
  252. }
  253. }
  254. //全局屏蔽字处理(不做禁止发言操作,值做自言自语)
  255. if bSendMsg {
  256. bSensitiveMatch := model.AdvSensitiveUtil.IsMatch(chatContent)
  257. if bSensitiveMatch {
  258. bSendMsg = false
  259. util.InfoF("uid=%v sensitivematch checkchatmsg=%v ", this.role.GetUUid(), string(chatContent))
  260. }
  261. }
  262. }
  263. return bSendMsg
  264. }