| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692 |
- package friend
- import (
- "encoding/json"
- "os"
- "sync"
- "time"
- "bet24.com/log"
- "bet24.com/servers/common"
- "bet24.com/servers/coreservice/client"
- notification "bet24.com/servers/micros/notification/proto"
- platformconfig "bet24.com/servers/micros/platformconfig/proto"
- user "bet24.com/servers/micros/userservices/proto"
- vipservice "bet24.com/servers/micros/userservices/proto"
- )
- const config_key = "friend_config"
- type friendmgr struct {
- lock *sync.RWMutex
- userList map[int]*user_friend
- MaxFriendCount int // 最大好友上限
- offlineList map[int]int // map[userId]expire
- }
- func newFriendMgr() *friendmgr {
- log.Debug("friend manager running")
- fm := &friendmgr{}
- fm.userList = make(map[int]*user_friend)
- fm.offlineList = make(map[int]int)
- fm.lock = &sync.RWMutex{}
- fm.checkDayRefresh()
- fm.checkOfflineUser()
- fm.loadRedisConfig()
- return fm
- }
- func (fm *friendmgr) checkDayRefresh() {
- ticker := time.NewTicker(10 * time.Minute)
- go func(t *time.Ticker) {
- lastCheck := common.GetTimeStamp()
- for { //循环
- select {
- case <-t.C:
- now := common.GetTimeStamp()
- if !common.IsSameDay(lastCheck, now) {
- fm.refreshUserList()
- }
- lastCheck = now
- }
- }
- }(ticker)
- }
- func (fm *friendmgr) checkOfflineUser() {
- time.AfterFunc(1*time.Minute, fm.checkOfflineUser)
- ts := common.GetTimeStamp()
- var toRemove []int
- fm.lock.RLock()
- for userId, expire := range fm.offlineList {
- if expire <= ts {
- toRemove = append(toRemove, userId)
- }
- }
- fm.lock.RUnlock()
- if len(toRemove) == 0 {
- return
- }
- log.Debug("friendmgr.checkOfflineUser toRemove = %v", toRemove)
- for _, userId := range toRemove {
- fm.onUserExit(userId)
- fm.lock.Lock()
- delete(fm.offlineList, userId)
- fm.lock.Unlock()
- }
- }
- // 0点过后去数据库刷新在线玩家数据
- func (fm *friendmgr) refreshUserList() {
- fm.lock.RLock()
- for _, v := range fm.userList {
- v.refreshGift()
- }
- fm.lock.RUnlock()
- }
- // 加载redis配置
- func (fm *friendmgr) loadRedisConfig() {
- go time.AfterFunc(5*time.Minute, fm.loadRedisConfig)
- if data := platformconfig.GetConfig(config_key); data != "" {
- if err := json.Unmarshal([]byte(data), &fm); err == nil {
- return
- }
- return
- }
- data, err := os.ReadFile("fishconf/friend_config.json")
- if err != nil {
- log.Release("read config failed fishconf/friend_config.json %v", err)
- }
- if err = json.Unmarshal(data, &fm); err == nil {
- platformconfig.SetConfig(config_key, string(data))
- return
- }
- log.Release("Unmarshal config [%s] err:%v", string(data), err)
- }
- func (fm *friendmgr) onUserEnter(userId int) {
- u := newUserFriend(userId)
- fm.lock.Lock()
- fm.userList[userId] = u
- fm.lock.Unlock()
- fm.setUserStatus(userId, 1, "")
- }
- func (fm *friendmgr) onUserExit(userId int) {
- fm.setUserStatus(userId, 0, "")
- fm.lock.Lock()
- delete(fm.userList, userId)
- fm.lock.Unlock()
- }
- func (fm *friendmgr) searchInfo(userId, toUserId int, toNickName string) []*SearchInfo {
- list := searchInfo(userId, toUserId, toNickName)
- for i := 0; i < len(list); i++ {
- list[i].IsFriend = fm.ifFriend(userId, list[i].FriendID)
- if fm.isOnline(list[i].FriendID) {
- list[i].GameStatus = GameStatus_Online
- }
- u := user.GetUserInfo(list[i].FriendID)
- if u == nil {
- // log.Error("friendmgr.searchInfo userId=%d", list[i].FriendID)
- continue
- }
- l := user.GetUserLevel(list[i].FriendID)
- list[i].NickName = u.NickName
- list[i].Sex = u.Sex
- list[i].FaceID = u.FaceId
- list[i].FaceUrl = u.FaceUrl
- list[i].UserWords = u.UserWords
- list[i].VipLevel = u.Vip
- list[i].VipExpire = u.VipExpire
- list[i].PrivateRoomCount = u.PrivateRoomCount
- list[i].Currency = u.Currency
- list[i].Level = l.Level
- list[i].Gold = u.Gold
- list[i].Decorations = u.Decorations
- list[i].Charm = u.Charm
- }
- return list
- }
- func (fm *friendmgr) getFriendList(userId int) []*FriendItem {
- fm.lock.RLock()
- l, ok := fm.userList[userId]
- fm.lock.RUnlock()
- if !ok {
- return nil
- }
- var list []*FriendItem
- for _, v := range l.FriendList {
- u := user.GetUserInfo(v.FriendID)
- if u == nil {
- log.Error("friendmgr.getFriendList userId=%d ==> %+v", v.FriendID, v)
- continue
- }
- list = append(list, &FriendItem{
- FriendBase: FriendBase{
- FriendID: v.FriendID,
- NickName: u.NickName,
- Sex: u.Sex,
- FaceID: u.FaceId,
- FaceUrl: u.FaceUrl,
- UserWords: u.UserWords,
- GameStatus: v.GameStatus,
- VipLevel: u.Vip,
- VipExpire: u.VipExpire,
- PrivateRoomCount: u.PrivateRoomCount,
- Decorations: u.Decorations,
- },
- IsGift: v.IsGift,
- GiftTime: v.GiftTime,
- IsGive: v.IsGive,
- GiveTime: v.GiveTime,
- })
- }
- return list
- }
- // 申请好友 0=不能申请自己 1=申请成功 2=已经是好友 3=已经申请,待审核
- func (fm *friendmgr) friendApply(userId, targetUserID int) int {
- //自己不能申请自己
- if userId == targetUserID {
- return CANNOT_ADD_ONESELF
- }
- fm.lock.RLock()
- u, ok := fm.userList[userId]
- fm.lock.RUnlock()
- if !ok {
- log.Debug("friendmgr.friendApply userId [%d] not exist", userId)
- return CANNOT_ADD_ONESELF
- }
- return u.friendApply(targetUserID)
- }
- func (fm *friendmgr) delFriend(userId, targetUserID int) []*FriendItem {
- var list []*FriendItem
- fm.lock.RLock()
- u, ok := fm.userList[userId]
- fm.lock.RUnlock()
- if !ok {
- list = nil
- } else {
- list, ok = u.delFriend(targetUserID)
- }
- if ok {
- go client.RemoveChannelChat(userId, targetUserID)
- }
- for _, v := range list {
- u := user.GetUserInfo(v.FriendID)
- if u == nil {
- log.Error("friendmgr.delFriend userId=%d ==> %+v", v.FriendID, v)
- continue
- }
- v.NickName = u.NickName
- v.Sex = u.Sex
- v.FaceID = u.FaceId
- v.FaceUrl = u.FaceUrl
- v.UserWords = u.UserWords
- v.VipLevel = u.Vip
- v.VipExpire = u.VipExpire
- v.PrivateRoomCount = u.PrivateRoomCount
- v.Decorations = u.Decorations
- }
- return list
- }
- func (fm *friendmgr) friendVerifyList(userId int) []*FriendBase {
- fm.lock.RLock()
- u, ok := fm.userList[userId]
- fm.lock.RUnlock()
- if !ok {
- return nil
- }
- var list []*FriendBase
- for _, v := range u.VerifyList {
- u := user.GetUserInfo(v.FriendID)
- if u == nil {
- log.Error("friendmgr.friendVerifyList userId=%d ==> %+v", v.FriendID, v)
- continue
- }
- list = append(list, &FriendBase{
- FriendID: v.FriendID,
- NickName: u.NickName,
- Sex: u.Sex,
- FaceID: u.FaceId,
- FaceUrl: u.FaceUrl,
- UserWords: u.UserWords,
- GameStatus: v.GameStatus,
- VipLevel: u.Vip,
- VipExpire: u.VipExpire,
- PrivateRoomCount: u.PrivateRoomCount,
- Decorations: u.Decorations,
- })
- }
- return list
- }
- // apply 状态 0=未处理 1=同意 2=拒绝
- func (fm *friendmgr) friendHandleApply(userId, targetUserID, apply int) []*FriendItem {
- fm.lock.RLock()
- u, ok := fm.userList[userId]
- fm.lock.RUnlock()
- if !ok {
- return nil
- }
- var list []*FriendItem
- list = u.friendHandleApply(targetUserID, apply)
- for _, v := range list {
- u := user.GetUserInfo(v.FriendID)
- if u == nil {
- log.Error("friendmgr.friendHandleApply userId=%d ==> %+v", v.FriendID, v)
- continue
- }
- v.NickName = u.NickName
- v.Sex = u.Sex
- v.FaceID = u.FaceId
- v.FaceUrl = u.FaceUrl
- v.UserWords = u.UserWords
- v.VipLevel = u.Vip
- v.VipExpire = u.VipExpire
- v.PrivateRoomCount = u.PrivateRoomCount
- v.Decorations = u.Decorations
- }
- return list
- }
- // 向好友赠送礼物
- func (fm *friendmgr) friendGiveGift(userId, targetUserID int) int {
- fm.lock.RLock()
- u, ok := fm.userList[userId]
- fm.lock.RUnlock()
- if !ok {
- return 0
- }
- return u.friendGiveGift(targetUserID)
- }
- func (fm *friendmgr) notifyGift(userId, toUserId int) {
- fm.lock.RLock()
- u, ok := fm.userList[toUserId]
- fm.lock.RUnlock()
- if !ok {
- return
- }
- //好友也在线,刷新礼物状态
- for _, f := range u.FriendList {
- if f.FriendID == userId {
- f.IsGift = GIFT_STATUS_HAVE
- break
- }
- }
- go func(toUserId int) {
- buf, _ := json.Marshal(notification.NotificationFriend{
- NotifyId: Friend_Notify_Gift,
- })
- //发送通知
- notification.AddNotification(toUserId, notification.Notification_Friend, string(buf))
- }(toUserId)
- }
- func (fm *friendmgr) friendGetGift(userId, targetUserID int, ipAddress string) int {
- fm.lock.RLock()
- u, ok := fm.userList[userId]
- fm.lock.RUnlock()
- if !ok {
- return 0
- }
- return u.friendGetGift(targetUserID, ipAddress)
- }
- func (fm *friendmgr) setUserStatus(userId, isOnline int, serverName string) {
- // 离线
- status := GameStatus_Offline
- // 在线
- if isOnline == 1 {
- if serverName == "广告大厅" || serverName == "游戏大厅" { // 大厅
- status = GameStatus_Hall
- } else if serverName != "" { // 游戏中
- status = GameStatus_Playing
- } else {
- status = GameStatus_Online
- }
- } else if isOnline == 0 && serverName != "" {
- status = GameStatus_Hall
- }
- // log.Debug("setUserStatus userId=%d isOnline=%d serverName=%s status=%s", userId, isOnline, serverName, status)
- fm.lock.RLock()
- u, ok := fm.userList[userId]
- fm.lock.RUnlock()
- if !ok {
- //log.Debug("friendmgr.setUserStatus userId [%d] not exist", userId)
- return
- }
- go func() {
- // 延迟2秒
- time.Sleep(2 * time.Second)
- // 通知我的好友
- for _, f := range u.FriendList {
- fm.lock.RLock()
- friend, ok := fm.userList[f.FriendID]
- fm.lock.RUnlock()
- if !ok {
- continue
- }
- friend.setUserStatus(userId, status)
- }
- // 通知我待通过的好友
- buf, _ := json.Marshal(notification.NotificationFriend{
- NotifyId: Friend_Notify_Status,
- UserId: userId,
- Data: status,
- })
- fm.lock.RLock()
- for _, u := range fm.userList {
- if u.UserID == userId {
- continue
- }
- for _, v := range u.ApplyList {
- v.GameStatus = status
- //发送通知
- go notification.AddNotification(u.UserID, notification.Notification_Friend, string(buf))
- break
- }
- }
- fm.lock.RUnlock()
- }()
- }
- func (fm *friendmgr) isOnline(userId int) bool {
- fm.lock.RLock()
- defer fm.lock.RUnlock()
- _, ok := fm.userList[userId]
- return ok
- }
- // 刷新好友及申请列表
- func (fm *friendmgr) refreshFriends(userId int, friendFlag, applyFlag, verifyFlag bool, fromUserId int, apply string) bool {
- var (
- giveTimes int
- friendlist []*FriendItem
- applylist []*FriendBase
- verifylist []*FriendBase
- )
- //获取在线好友数据
- fm.lock.RLock()
- l, ok := fm.userList[userId]
- fm.lock.RUnlock()
- if !ok {
- return false
- }
- //从数据库获取好友列表
- if friendFlag {
- giveTimes, friendlist = getList(userId)
- for _, v := range friendlist {
- if fm.isOnline(v.FriendID) {
- v.GameStatus = GameStatus_Online
- }
- }
- }
- //从数据库获取申请列表
- if applyFlag {
- applylist = getApplyList(userId)
- for _, v := range applylist {
- if fm.isOnline(v.FriendID) {
- v.GameStatus = GameStatus_Online
- }
- }
- }
- //从数据库获取审核列表
- if verifyFlag {
- verifylist = getVerifyList(userId)
- for _, v := range verifylist {
- if fm.isOnline(v.FriendID) {
- v.GameStatus = GameStatus_Online
- }
- }
- }
- fm.lock.Lock()
- defer fm.lock.Unlock()
- //刷新在线好友列表
- if friendFlag {
- l.GiveTimes = giveTimes
- l.FriendList = friendlist
- }
- //刷新在线申请列表
- if applyFlag {
- l.ApplyList = applylist
- }
- //刷新审核列表
- if verifyFlag {
- l.VerifyList = verifylist
- }
- notifyId := Friend_Notify_All
- if friendFlag {
- notifyId = Friend_Notify_Friend
- } else if verifyFlag {
- notifyId = Friend_Notify_Verify
- } else if applyFlag {
- return true
- }
- buf, _ := json.Marshal(notification.NotificationFriend{
- NotifyId: notifyId,
- UserId: fromUserId,
- Data: apply,
- })
- //发送通知
- notification.AddNotification(userId, notification.Notification_Friend, string(buf))
- return true
- }
- func (fm *friendmgr) ifFriend(userId, targetId int) int {
- u := fm.getUserInfo(userId)
- if u == nil {
- log.Debug("friendmgr.ifFriend userId[%d] targetId[%d] not exist", userId, targetId)
- return 0
- }
- return u.ifFriend(targetId)
- }
- // 获取用户信息
- func (fm *friendmgr) getUserInfo(userId int) *user_friend {
- fm.lock.RLock()
- u, ok := fm.userList[userId]
- fm.lock.RUnlock()
- if !ok {
- u = newUserFriend(userId)
- expire := common.GetTimeStamp() + 300
- fm.lock.Lock()
- fm.offlineList[userId] = expire
- fm.lock.Unlock()
- log.Debug("friendmgr.getUserInfo userId=%d expire=%d", userId, expire)
- }
- return u
- }
- // 邀请好友
- func (fm *friendmgr) roomInvite(userId int, nickName string, toUserId, roomNo int) {
- u := fm.getUserInfo(userId)
- if u == nil {
- log.Debug("friendmgr.roomInvite userId [%d] not exist", userId)
- return
- }
- if info := u.roomInvite(nickName, toUserId, roomNo); info != nil {
- go fm.addRoomInviteHistory(toUserId, info)
- }
- return
- }
- // 添加房间邀请历史列表
- func (fm *friendmgr) addRoomInviteHistory(userId int, info *RoomInviteInfo) {
- u := fm.getUserInfo(userId)
- if u == nil {
- log.Debug("friendmgr.addRoomInviteHistory userId [%d] not exist", userId)
- return
- }
- u.addRoomInviteHistory(info)
- }
- // 获取房间邀请列表
- func (fm *friendmgr) getRoomInviteList(userId int) []*RoomInviteInfo {
- u := fm.getUserInfo(userId)
- if u == nil {
- log.Debug("friendmgr.getRoomInviteList userId [%d] not exist", userId)
- return nil
- }
- return u.getRoomInviteList()
- }
- // 房间邀请无效
- func (fm *friendmgr) roomInviteInvalid(userId, roomNo int) {
- u := fm.getUserInfo(userId)
- if u == nil {
- log.Debug("friendmgr.roomInviteInvalid userId [%d] not exist", userId)
- return
- }
- u.roomInviteInvalid(roomNo)
- }
- // 获取好友上限
- func (fm *friendmgr) getMaxFriendCount(userId int) FriendCount {
- var ret FriendCount
- if fm.MaxFriendCount == 0 {
- fm.MaxFriendCount = DEFAULT_FRIEND_COUNT
- }
- ret.Base = fm.MaxFriendCount
- ret.Extra = vipservice.GetExtraFriendCount(userId)
- return ret
- }
- func (fm *friendmgr) dumpFriends() {
- log.Release("===== Friend List Begin ========================")
- for _, users := range fm.userList {
- for _, v := range users.FriendList {
- log.Release("friendList userId=%d ==> %+v", users.UserID, v)
- }
- }
- log.Release("===== Friend List End ========================")
- }
- // 获取房间邀请列表
- func (fm *friendmgr) getPotentialFriendList(userId int) string {
- u := fm.getUserInfo(userId)
- if u == nil {
- log.Debug("friendmgr.getPotientialList userId [%d] not exist", userId)
- return ""
- }
- return u.getPotentialFriendList()
- }
- func (fm *friendmgr) addPotentialFriend(userId int, toUserId int, memo string) {
- u := fm.getUserInfo(userId)
- if u == nil {
- log.Debug("friendmgr.addPotentialFriend userId [%d] not exist", userId)
- return
- }
- u.addPotentialFriend(toUserId, memo)
- }
- // 黑名单列表
- func (fm *friendmgr) getBlackList(userId int) (list []BlackItem) {
- u := fm.getUserInfo(userId)
- if u == nil {
- log.Debug("friendmgr.getBlackList userId [%d] not exist", userId)
- return
- }
- return u.getBlackList()
- }
- // 添加黑名单
- func (fm *friendmgr) addBlack(userId, toUserId int) (retCode int, message string) {
- u := fm.getUserInfo(userId)
- if u == nil {
- log.Debug("friendmgr.addBlack userId [%d] not exist", userId)
- retCode, message = 13, "Invalid user information"
- return
- }
- return u.addBlack(toUserId)
- }
- // 删除黑名单
- func (fm *friendmgr) delBlack(userId, toUserId int) (retCode int, message string) {
- u := fm.getUserInfo(userId)
- if u == nil {
- log.Debug("friendmgr.delBlack userId [%d] not exist", userId)
- retCode, message = 12, "Invalid user information"
- return
- }
- return u.delBlack(toUserId)
- }
- func (fm *friendmgr) isBlackListUser(userId, toUserId int) bool {
- u := fm.getUserInfo(userId)
- if u == nil {
- log.Debug("friendmgr.isBlackListUser userId [%d] not exist", userId)
- return false
- }
- return u.isBlackListUser(toUserId)
- }
- func (fm *friendmgr) isBlackListUserIn(userId int, toUserId []int) bool {
- u := fm.getUserInfo(userId)
- if u == nil {
- log.Debug("friendmgr.isBlackListUserIn userId [%d] not exist", userId)
- return false
- }
- return u.isBlackListUserIn(toUserId)
- }
|