friendmgr.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692
  1. package friend
  2. import (
  3. "encoding/json"
  4. "os"
  5. "sync"
  6. "time"
  7. "bet24.com/log"
  8. "bet24.com/servers/common"
  9. "bet24.com/servers/coreservice/client"
  10. notification "bet24.com/servers/micros/notification/proto"
  11. platformconfig "bet24.com/servers/micros/platformconfig/proto"
  12. user "bet24.com/servers/micros/userservices/proto"
  13. vipservice "bet24.com/servers/micros/userservices/proto"
  14. )
  15. const config_key = "friend_config"
  16. type friendmgr struct {
  17. lock *sync.RWMutex
  18. userList map[int]*user_friend
  19. MaxFriendCount int // 最大好友上限
  20. offlineList map[int]int // map[userId]expire
  21. }
  22. func newFriendMgr() *friendmgr {
  23. log.Debug("friend manager running")
  24. fm := &friendmgr{}
  25. fm.userList = make(map[int]*user_friend)
  26. fm.offlineList = make(map[int]int)
  27. fm.lock = &sync.RWMutex{}
  28. fm.checkDayRefresh()
  29. fm.checkOfflineUser()
  30. fm.loadRedisConfig()
  31. return fm
  32. }
  33. func (fm *friendmgr) checkDayRefresh() {
  34. ticker := time.NewTicker(10 * time.Minute)
  35. go func(t *time.Ticker) {
  36. lastCheck := common.GetTimeStamp()
  37. for { //循环
  38. select {
  39. case <-t.C:
  40. now := common.GetTimeStamp()
  41. if !common.IsSameDay(lastCheck, now) {
  42. fm.refreshUserList()
  43. }
  44. lastCheck = now
  45. }
  46. }
  47. }(ticker)
  48. }
  49. func (fm *friendmgr) checkOfflineUser() {
  50. time.AfterFunc(1*time.Minute, fm.checkOfflineUser)
  51. ts := common.GetTimeStamp()
  52. var toRemove []int
  53. fm.lock.RLock()
  54. for userId, expire := range fm.offlineList {
  55. if expire <= ts {
  56. toRemove = append(toRemove, userId)
  57. }
  58. }
  59. fm.lock.RUnlock()
  60. if len(toRemove) == 0 {
  61. return
  62. }
  63. log.Debug("friendmgr.checkOfflineUser toRemove = %v", toRemove)
  64. for _, userId := range toRemove {
  65. fm.onUserExit(userId)
  66. fm.lock.Lock()
  67. delete(fm.offlineList, userId)
  68. fm.lock.Unlock()
  69. }
  70. }
  71. // 0点过后去数据库刷新在线玩家数据
  72. func (fm *friendmgr) refreshUserList() {
  73. fm.lock.RLock()
  74. for _, v := range fm.userList {
  75. v.refreshGift()
  76. }
  77. fm.lock.RUnlock()
  78. }
  79. // 加载redis配置
  80. func (fm *friendmgr) loadRedisConfig() {
  81. go time.AfterFunc(5*time.Minute, fm.loadRedisConfig)
  82. if data := platformconfig.GetConfig(config_key); data != "" {
  83. if err := json.Unmarshal([]byte(data), &fm); err == nil {
  84. return
  85. }
  86. return
  87. }
  88. data, err := os.ReadFile("fishconf/friend_config.json")
  89. if err != nil {
  90. log.Release("read config failed fishconf/friend_config.json %v", err)
  91. }
  92. if err = json.Unmarshal(data, &fm); err == nil {
  93. platformconfig.SetConfig(config_key, string(data))
  94. return
  95. }
  96. log.Release("Unmarshal config [%s] err:%v", string(data), err)
  97. }
  98. func (fm *friendmgr) onUserEnter(userId int) {
  99. u := newUserFriend(userId)
  100. fm.lock.Lock()
  101. fm.userList[userId] = u
  102. fm.lock.Unlock()
  103. fm.setUserStatus(userId, 1, "")
  104. }
  105. func (fm *friendmgr) onUserExit(userId int) {
  106. fm.setUserStatus(userId, 0, "")
  107. fm.lock.Lock()
  108. delete(fm.userList, userId)
  109. fm.lock.Unlock()
  110. }
  111. func (fm *friendmgr) searchInfo(userId, toUserId int, toNickName string) []*SearchInfo {
  112. list := searchInfo(userId, toUserId, toNickName)
  113. for i := 0; i < len(list); i++ {
  114. list[i].IsFriend = fm.ifFriend(userId, list[i].FriendID)
  115. if fm.isOnline(list[i].FriendID) {
  116. list[i].GameStatus = GameStatus_Online
  117. }
  118. u := user.GetUserInfo(list[i].FriendID)
  119. if u == nil {
  120. // log.Error("friendmgr.searchInfo userId=%d", list[i].FriendID)
  121. continue
  122. }
  123. l := user.GetUserLevel(list[i].FriendID)
  124. list[i].NickName = u.NickName
  125. list[i].Sex = u.Sex
  126. list[i].FaceID = u.FaceId
  127. list[i].FaceUrl = u.FaceUrl
  128. list[i].UserWords = u.UserWords
  129. list[i].VipLevel = u.Vip
  130. list[i].VipExpire = u.VipExpire
  131. list[i].PrivateRoomCount = u.PrivateRoomCount
  132. list[i].Currency = u.Currency
  133. list[i].Level = l.Level
  134. list[i].Gold = u.Gold
  135. list[i].Decorations = u.Decorations
  136. list[i].Charm = u.Charm
  137. }
  138. return list
  139. }
  140. func (fm *friendmgr) getFriendList(userId int) []*FriendItem {
  141. fm.lock.RLock()
  142. l, ok := fm.userList[userId]
  143. fm.lock.RUnlock()
  144. if !ok {
  145. return nil
  146. }
  147. var list []*FriendItem
  148. for _, v := range l.FriendList {
  149. u := user.GetUserInfo(v.FriendID)
  150. if u == nil {
  151. log.Error("friendmgr.getFriendList userId=%d ==> %+v", v.FriendID, v)
  152. continue
  153. }
  154. list = append(list, &FriendItem{
  155. FriendBase: FriendBase{
  156. FriendID: v.FriendID,
  157. NickName: u.NickName,
  158. Sex: u.Sex,
  159. FaceID: u.FaceId,
  160. FaceUrl: u.FaceUrl,
  161. UserWords: u.UserWords,
  162. GameStatus: v.GameStatus,
  163. VipLevel: u.Vip,
  164. VipExpire: u.VipExpire,
  165. PrivateRoomCount: u.PrivateRoomCount,
  166. Decorations: u.Decorations,
  167. },
  168. IsGift: v.IsGift,
  169. GiftTime: v.GiftTime,
  170. IsGive: v.IsGive,
  171. GiveTime: v.GiveTime,
  172. })
  173. }
  174. return list
  175. }
  176. // 申请好友 0=不能申请自己 1=申请成功 2=已经是好友 3=已经申请,待审核
  177. func (fm *friendmgr) friendApply(userId, targetUserID int) int {
  178. //自己不能申请自己
  179. if userId == targetUserID {
  180. return CANNOT_ADD_ONESELF
  181. }
  182. fm.lock.RLock()
  183. u, ok := fm.userList[userId]
  184. fm.lock.RUnlock()
  185. if !ok {
  186. log.Debug("friendmgr.friendApply userId [%d] not exist", userId)
  187. return CANNOT_ADD_ONESELF
  188. }
  189. return u.friendApply(targetUserID)
  190. }
  191. func (fm *friendmgr) delFriend(userId, targetUserID int) []*FriendItem {
  192. var list []*FriendItem
  193. fm.lock.RLock()
  194. u, ok := fm.userList[userId]
  195. fm.lock.RUnlock()
  196. if !ok {
  197. list = nil
  198. } else {
  199. list, ok = u.delFriend(targetUserID)
  200. }
  201. if ok {
  202. go client.RemoveChannelChat(userId, targetUserID)
  203. }
  204. for _, v := range list {
  205. u := user.GetUserInfo(v.FriendID)
  206. if u == nil {
  207. log.Error("friendmgr.delFriend userId=%d ==> %+v", v.FriendID, v)
  208. continue
  209. }
  210. v.NickName = u.NickName
  211. v.Sex = u.Sex
  212. v.FaceID = u.FaceId
  213. v.FaceUrl = u.FaceUrl
  214. v.UserWords = u.UserWords
  215. v.VipLevel = u.Vip
  216. v.VipExpire = u.VipExpire
  217. v.PrivateRoomCount = u.PrivateRoomCount
  218. v.Decorations = u.Decorations
  219. }
  220. return list
  221. }
  222. func (fm *friendmgr) friendVerifyList(userId int) []*FriendBase {
  223. fm.lock.RLock()
  224. u, ok := fm.userList[userId]
  225. fm.lock.RUnlock()
  226. if !ok {
  227. return nil
  228. }
  229. var list []*FriendBase
  230. for _, v := range u.VerifyList {
  231. u := user.GetUserInfo(v.FriendID)
  232. if u == nil {
  233. log.Error("friendmgr.friendVerifyList userId=%d ==> %+v", v.FriendID, v)
  234. continue
  235. }
  236. list = append(list, &FriendBase{
  237. FriendID: v.FriendID,
  238. NickName: u.NickName,
  239. Sex: u.Sex,
  240. FaceID: u.FaceId,
  241. FaceUrl: u.FaceUrl,
  242. UserWords: u.UserWords,
  243. GameStatus: v.GameStatus,
  244. VipLevel: u.Vip,
  245. VipExpire: u.VipExpire,
  246. PrivateRoomCount: u.PrivateRoomCount,
  247. Decorations: u.Decorations,
  248. })
  249. }
  250. return list
  251. }
  252. // apply 状态 0=未处理 1=同意 2=拒绝
  253. func (fm *friendmgr) friendHandleApply(userId, targetUserID, apply int) []*FriendItem {
  254. fm.lock.RLock()
  255. u, ok := fm.userList[userId]
  256. fm.lock.RUnlock()
  257. if !ok {
  258. return nil
  259. }
  260. var list []*FriendItem
  261. list = u.friendHandleApply(targetUserID, apply)
  262. for _, v := range list {
  263. u := user.GetUserInfo(v.FriendID)
  264. if u == nil {
  265. log.Error("friendmgr.friendHandleApply userId=%d ==> %+v", v.FriendID, v)
  266. continue
  267. }
  268. v.NickName = u.NickName
  269. v.Sex = u.Sex
  270. v.FaceID = u.FaceId
  271. v.FaceUrl = u.FaceUrl
  272. v.UserWords = u.UserWords
  273. v.VipLevel = u.Vip
  274. v.VipExpire = u.VipExpire
  275. v.PrivateRoomCount = u.PrivateRoomCount
  276. v.Decorations = u.Decorations
  277. }
  278. return list
  279. }
  280. // 向好友赠送礼物
  281. func (fm *friendmgr) friendGiveGift(userId, targetUserID int) int {
  282. fm.lock.RLock()
  283. u, ok := fm.userList[userId]
  284. fm.lock.RUnlock()
  285. if !ok {
  286. return 0
  287. }
  288. return u.friendGiveGift(targetUserID)
  289. }
  290. func (fm *friendmgr) notifyGift(userId, toUserId int) {
  291. fm.lock.RLock()
  292. u, ok := fm.userList[toUserId]
  293. fm.lock.RUnlock()
  294. if !ok {
  295. return
  296. }
  297. //好友也在线,刷新礼物状态
  298. for _, f := range u.FriendList {
  299. if f.FriendID == userId {
  300. f.IsGift = GIFT_STATUS_HAVE
  301. break
  302. }
  303. }
  304. go func(toUserId int) {
  305. buf, _ := json.Marshal(notification.NotificationFriend{
  306. NotifyId: Friend_Notify_Gift,
  307. })
  308. //发送通知
  309. notification.AddNotification(toUserId, notification.Notification_Friend, string(buf))
  310. }(toUserId)
  311. }
  312. func (fm *friendmgr) friendGetGift(userId, targetUserID int, ipAddress string) int {
  313. fm.lock.RLock()
  314. u, ok := fm.userList[userId]
  315. fm.lock.RUnlock()
  316. if !ok {
  317. return 0
  318. }
  319. return u.friendGetGift(targetUserID, ipAddress)
  320. }
  321. func (fm *friendmgr) setUserStatus(userId, isOnline int, serverName string) {
  322. // 离线
  323. status := GameStatus_Offline
  324. // 在线
  325. if isOnline == 1 {
  326. if serverName == "广告大厅" || serverName == "游戏大厅" { // 大厅
  327. status = GameStatus_Hall
  328. } else if serverName != "" { // 游戏中
  329. status = GameStatus_Playing
  330. } else {
  331. status = GameStatus_Online
  332. }
  333. } else if isOnline == 0 && serverName != "" {
  334. status = GameStatus_Hall
  335. }
  336. // log.Debug("setUserStatus userId=%d isOnline=%d serverName=%s status=%s", userId, isOnline, serverName, status)
  337. fm.lock.RLock()
  338. u, ok := fm.userList[userId]
  339. fm.lock.RUnlock()
  340. if !ok {
  341. //log.Debug("friendmgr.setUserStatus userId [%d] not exist", userId)
  342. return
  343. }
  344. go func() {
  345. // 延迟2秒
  346. time.Sleep(2 * time.Second)
  347. // 通知我的好友
  348. for _, f := range u.FriendList {
  349. fm.lock.RLock()
  350. friend, ok := fm.userList[f.FriendID]
  351. fm.lock.RUnlock()
  352. if !ok {
  353. continue
  354. }
  355. friend.setUserStatus(userId, status)
  356. }
  357. // 通知我待通过的好友
  358. buf, _ := json.Marshal(notification.NotificationFriend{
  359. NotifyId: Friend_Notify_Status,
  360. UserId: userId,
  361. Data: status,
  362. })
  363. fm.lock.RLock()
  364. for _, u := range fm.userList {
  365. if u.UserID == userId {
  366. continue
  367. }
  368. for _, v := range u.ApplyList {
  369. v.GameStatus = status
  370. //发送通知
  371. go notification.AddNotification(u.UserID, notification.Notification_Friend, string(buf))
  372. break
  373. }
  374. }
  375. fm.lock.RUnlock()
  376. }()
  377. }
  378. func (fm *friendmgr) isOnline(userId int) bool {
  379. fm.lock.RLock()
  380. defer fm.lock.RUnlock()
  381. _, ok := fm.userList[userId]
  382. return ok
  383. }
  384. // 刷新好友及申请列表
  385. func (fm *friendmgr) refreshFriends(userId int, friendFlag, applyFlag, verifyFlag bool, fromUserId int, apply string) bool {
  386. var (
  387. giveTimes int
  388. friendlist []*FriendItem
  389. applylist []*FriendBase
  390. verifylist []*FriendBase
  391. )
  392. //获取在线好友数据
  393. fm.lock.RLock()
  394. l, ok := fm.userList[userId]
  395. fm.lock.RUnlock()
  396. if !ok {
  397. return false
  398. }
  399. //从数据库获取好友列表
  400. if friendFlag {
  401. giveTimes, friendlist = getList(userId)
  402. for _, v := range friendlist {
  403. if fm.isOnline(v.FriendID) {
  404. v.GameStatus = GameStatus_Online
  405. }
  406. }
  407. }
  408. //从数据库获取申请列表
  409. if applyFlag {
  410. applylist = getApplyList(userId)
  411. for _, v := range applylist {
  412. if fm.isOnline(v.FriendID) {
  413. v.GameStatus = GameStatus_Online
  414. }
  415. }
  416. }
  417. //从数据库获取审核列表
  418. if verifyFlag {
  419. verifylist = getVerifyList(userId)
  420. for _, v := range verifylist {
  421. if fm.isOnline(v.FriendID) {
  422. v.GameStatus = GameStatus_Online
  423. }
  424. }
  425. }
  426. fm.lock.Lock()
  427. defer fm.lock.Unlock()
  428. //刷新在线好友列表
  429. if friendFlag {
  430. l.GiveTimes = giveTimes
  431. l.FriendList = friendlist
  432. }
  433. //刷新在线申请列表
  434. if applyFlag {
  435. l.ApplyList = applylist
  436. }
  437. //刷新审核列表
  438. if verifyFlag {
  439. l.VerifyList = verifylist
  440. }
  441. notifyId := Friend_Notify_All
  442. if friendFlag {
  443. notifyId = Friend_Notify_Friend
  444. } else if verifyFlag {
  445. notifyId = Friend_Notify_Verify
  446. } else if applyFlag {
  447. return true
  448. }
  449. buf, _ := json.Marshal(notification.NotificationFriend{
  450. NotifyId: notifyId,
  451. UserId: fromUserId,
  452. Data: apply,
  453. })
  454. //发送通知
  455. notification.AddNotification(userId, notification.Notification_Friend, string(buf))
  456. return true
  457. }
  458. func (fm *friendmgr) ifFriend(userId, targetId int) int {
  459. u := fm.getUserInfo(userId)
  460. if u == nil {
  461. log.Debug("friendmgr.ifFriend userId[%d] targetId[%d] not exist", userId, targetId)
  462. return 0
  463. }
  464. return u.ifFriend(targetId)
  465. }
  466. // 获取用户信息
  467. func (fm *friendmgr) getUserInfo(userId int) *user_friend {
  468. fm.lock.RLock()
  469. u, ok := fm.userList[userId]
  470. fm.lock.RUnlock()
  471. if !ok {
  472. u = newUserFriend(userId)
  473. expire := common.GetTimeStamp() + 300
  474. fm.lock.Lock()
  475. fm.offlineList[userId] = expire
  476. fm.lock.Unlock()
  477. log.Debug("friendmgr.getUserInfo userId=%d expire=%d", userId, expire)
  478. }
  479. return u
  480. }
  481. // 邀请好友
  482. func (fm *friendmgr) roomInvite(userId int, nickName string, toUserId, roomNo int) {
  483. u := fm.getUserInfo(userId)
  484. if u == nil {
  485. log.Debug("friendmgr.roomInvite userId [%d] not exist", userId)
  486. return
  487. }
  488. if info := u.roomInvite(nickName, toUserId, roomNo); info != nil {
  489. go fm.addRoomInviteHistory(toUserId, info)
  490. }
  491. return
  492. }
  493. // 添加房间邀请历史列表
  494. func (fm *friendmgr) addRoomInviteHistory(userId int, info *RoomInviteInfo) {
  495. u := fm.getUserInfo(userId)
  496. if u == nil {
  497. log.Debug("friendmgr.addRoomInviteHistory userId [%d] not exist", userId)
  498. return
  499. }
  500. u.addRoomInviteHistory(info)
  501. }
  502. // 获取房间邀请列表
  503. func (fm *friendmgr) getRoomInviteList(userId int) []*RoomInviteInfo {
  504. u := fm.getUserInfo(userId)
  505. if u == nil {
  506. log.Debug("friendmgr.getRoomInviteList userId [%d] not exist", userId)
  507. return nil
  508. }
  509. return u.getRoomInviteList()
  510. }
  511. // 房间邀请无效
  512. func (fm *friendmgr) roomInviteInvalid(userId, roomNo int) {
  513. u := fm.getUserInfo(userId)
  514. if u == nil {
  515. log.Debug("friendmgr.roomInviteInvalid userId [%d] not exist", userId)
  516. return
  517. }
  518. u.roomInviteInvalid(roomNo)
  519. }
  520. // 获取好友上限
  521. func (fm *friendmgr) getMaxFriendCount(userId int) FriendCount {
  522. var ret FriendCount
  523. if fm.MaxFriendCount == 0 {
  524. fm.MaxFriendCount = DEFAULT_FRIEND_COUNT
  525. }
  526. ret.Base = fm.MaxFriendCount
  527. ret.Extra = vipservice.GetExtraFriendCount(userId)
  528. return ret
  529. }
  530. func (fm *friendmgr) dumpFriends() {
  531. log.Release("===== Friend List Begin ========================")
  532. for _, users := range fm.userList {
  533. for _, v := range users.FriendList {
  534. log.Release("friendList userId=%d ==> %+v", users.UserID, v)
  535. }
  536. }
  537. log.Release("===== Friend List End ========================")
  538. }
  539. // 获取房间邀请列表
  540. func (fm *friendmgr) getPotentialFriendList(userId int) string {
  541. u := fm.getUserInfo(userId)
  542. if u == nil {
  543. log.Debug("friendmgr.getPotientialList userId [%d] not exist", userId)
  544. return ""
  545. }
  546. return u.getPotentialFriendList()
  547. }
  548. func (fm *friendmgr) addPotentialFriend(userId int, toUserId int, memo string) {
  549. u := fm.getUserInfo(userId)
  550. if u == nil {
  551. log.Debug("friendmgr.addPotentialFriend userId [%d] not exist", userId)
  552. return
  553. }
  554. u.addPotentialFriend(toUserId, memo)
  555. }
  556. // 黑名单列表
  557. func (fm *friendmgr) getBlackList(userId int) (list []BlackItem) {
  558. u := fm.getUserInfo(userId)
  559. if u == nil {
  560. log.Debug("friendmgr.getBlackList userId [%d] not exist", userId)
  561. return
  562. }
  563. return u.getBlackList()
  564. }
  565. // 添加黑名单
  566. func (fm *friendmgr) addBlack(userId, toUserId int) (retCode int, message string) {
  567. u := fm.getUserInfo(userId)
  568. if u == nil {
  569. log.Debug("friendmgr.addBlack userId [%d] not exist", userId)
  570. retCode, message = 13, "Invalid user information"
  571. return
  572. }
  573. return u.addBlack(toUserId)
  574. }
  575. // 删除黑名单
  576. func (fm *friendmgr) delBlack(userId, toUserId int) (retCode int, message string) {
  577. u := fm.getUserInfo(userId)
  578. if u == nil {
  579. log.Debug("friendmgr.delBlack userId [%d] not exist", userId)
  580. retCode, message = 12, "Invalid user information"
  581. return
  582. }
  583. return u.delBlack(toUserId)
  584. }
  585. func (fm *friendmgr) isBlackListUser(userId, toUserId int) bool {
  586. u := fm.getUserInfo(userId)
  587. if u == nil {
  588. log.Debug("friendmgr.isBlackListUser userId [%d] not exist", userId)
  589. return false
  590. }
  591. return u.isBlackListUser(toUserId)
  592. }
  593. func (fm *friendmgr) isBlackListUserIn(userId int, toUserId []int) bool {
  594. u := fm.getUserInfo(userId)
  595. if u == nil {
  596. log.Debug("friendmgr.isBlackListUserIn userId [%d] not exist", userId)
  597. return false
  598. }
  599. return u.isBlackListUserIn(toUserId)
  600. }