package main import ( "cs" "f5" "mt" "q5" "strings" ) type FriendsMgr struct { cs.MsgHandlerImpl users map[string]*User friendships map[string][]*Friendship pendingReqs map[string]map[string]bool } func (fm *FriendsMgr) init() { // init gameDB gameDBStore := q5.NewMysql( mt.Table.GameDb.GetById(0).GetHost(), mt.Table.GameDb.GetById(0).GetPort(), mt.Table.GameDb.GetById(0).GetUser(), mt.Table.GameDb.GetById(0).GetPasswd(), mt.Table.GameDb.GetById(0).GetDatabase(), ) gameDBStore.Open() fm.loadUsersFromDB(gameDBStore) // init friendDB friendDBStore := q5.NewMysql( mt.Table.FriendDb.GetById(0).GetHost(), mt.Table.FriendDb.GetById(0).GetPort(), mt.Table.FriendDb.GetById(0).GetUser(), mt.Table.FriendDb.GetById(0).GetPasswd(), mt.Table.FriendDb.GetById(0).GetDatabase(), ) friendDBStore.Open() // 加载好友关系表 列表 fm.loadFriendshipsFromDB(friendDBStore) // 加载等待验证好友请求 列表 fm.loadPendingRequestsFromDB(friendDBStore) } func (fm *FriendsMgr) unInit() { // 1. Loop struct data // 2. Struct Data Persist to DB } func (fm *FriendsMgr) CMSearchFriends(hdr *f5.MsgHdr, msg *cs.CMSearchFriend) { searchKeyword := msg.GetSearchKeyword() listFriend := &cs.SMSearchFriend{} lowercaseQuery := strings.ToLower(searchKeyword) for _, user := range fm.users { if strings.Contains(strings.ToLower(user.UserName), lowercaseQuery) { friend := &cs.MFFriend{ AccountId: &user.AccountId, Username: &user.UserName, } listFriend.Friends = append(listFriend.Friends, friend) } } f5.GetSysLog().Info("CMSearchFriends search result:%d\n", len(listFriend.Friends)) // By default, Search result save to redis..., key: search keyword, value: serialization(search result), expired: 2days wspListener.sendProxyMsg(hdr.Conn, hdr.SocketHandle, listFriend) } // CMAddFriendRequest 发送好友请求 func (fm *FriendsMgr) CMAddFriendRequest(hdr *f5.MsgHdr, msg *cs.CMAddFriendRequest) { response := &cs.SMAddFriendRequest{} user1Id := msg.GetAccountId() user2Id := msg.GetAccount2Id() // Check if users exist _, exists1 := fm.users[user1Id] _, exists2 := fm.users[user2Id] if !exists1 || !exists2 { reason := "users not exist" response.Reason = &reason wspListener.sendProxyMsg(hdr.Conn, hdr.SocketHandle, response) f5.GetSysLog().Info("CMAddFriendRequest: reason:%s, params: %s or %s\n", reason, user1Id, user2Id) return } // 为 user2 创建等待验证好友请求 记录,由userid1 申请的 if fm.pendingReqs[user2Id] == nil { fm.pendingReqs[user2Id] = make(map[string]bool) } fm.pendingReqs[user2Id][user1Id] = true status := "pending" response.Status = &status wspListener.sendProxyMsg(hdr.Conn, hdr.SocketHandle, response) } // CMAcceptFriendRequest 接受好友请求 func (fm *FriendsMgr) CMAcceptFriendRequest(hdr *f5.MsgHdr, msg *cs.CMAcceptFriendRequest) { response := &cs.SMAcceptFriendRequest{} user1Id := msg.GetAccountId() user2Id := msg.GetAccount2Id() if !fm.pendingReqs[user1Id][user2Id] { reason := "no pending friend request from user1 to user2" response.Reason = &reason wspListener.sendProxyMsg(hdr.Conn, hdr.SocketHandle, response) f5.GetSysLog().Info("CMAcceptFriendRequest: reason:%s, params: %s or %s\n", reason, user1Id, user2Id) return } // Create a new friendship friendship := &Friendship{ User1: fm.users[user1Id], User2: fm.users[user2Id], } fm.friendships[user1Id] = append(fm.friendships[user1Id], friendship) fm.friendships[user2Id] = append(fm.friendships[user2Id], friendship) // step1. delete db record // step2. add friend history to db delete(fm.pendingReqs[user1Id], user2Id) if len(fm.pendingReqs[user1Id]) == 0 { delete(fm.pendingReqs, user1Id) } status := "approved" response.Status = &status wspListener.sendProxyMsg(hdr.Conn, hdr.SocketHandle, response) } // CMListFriend 我的好友列表 func (fm *FriendsMgr) CMListFriend(hdr *f5.MsgHdr, msg *cs.CMListFriend) { myAccountId := msg.GetAccountId() listFriend := &cs.SMListFriend{} for _, friendship := range fm.friendships[myAccountId] { if friendship.User1.AccountId != myAccountId { friend := &cs.MFFriend{ AccountId: &friendship.User1.AccountId, Username: &friendship.User1.UserName, } listFriend.Friends = append(listFriend.Friends, friend) } else { friend := &cs.MFFriend{ AccountId: &friendship.User2.AccountId, Username: &friendship.User2.UserName, } listFriend.Friends = append(listFriend.Friends, friend) } } f5.GetSysLog().Info("CMListFriend friends count:%d\n", len(listFriend.Friends)) wspListener.sendProxyMsg(hdr.Conn, hdr.SocketHandle, listFriend) } func (fm *FriendsMgr) loadUsersFromDB(conn *q5.Mysql) { // Load DB users to struct FriendsMgr.user rows, err := conn.Query("select account_id, name from t_user") if err != nil { f5.GetSysLog().Info("mysql error", err) return } fm.users = make(map[string]*User) for rows.Next() { user := &User{} err := rows.Scan(&user.AccountId, &user.UserName) if err != nil { continue } fm.users[user.AccountId] = user } } func (fm *FriendsMgr) loadFriendshipsFromDB(conn *q5.Mysql) { // Load DB t_friend_ships to struct FriendsMgr.friendship rows, err := conn.Query("select account1_id, account2_id from t_friend_ships;") if err != nil { f5.GetSysLog().Info("mysql error", err) return } fm.friendships = make(map[string][]*Friendship) for rows.Next() { user1 := &User{} user2 := &User{} err := rows.Scan(&user1.AccountId, &user2.AccountId) if err != nil { continue } friendship := &Friendship{} friendship.User1 = user1 friendship.User2 = user2 fm.addFriendshipToMap(user1.AccountId, friendship) fm.addFriendshipToMap(user2.AccountId, friendship) } } func (fm *FriendsMgr) loadPendingRequestsFromDB(conn *q5.Mysql) { rows, err := conn.Query("select sender_account_id, receiver_account_id from t_pending_friend_requests;") if err != nil { f5.GetSysLog().Info("mysql error", err) return } pendingReqs := make(map[string]map[string]bool) for rows.Next() { var senderAccountId, receiverAccountId string if err := rows.Scan(&senderAccountId, &receiverAccountId); err != nil { continue } if pendingReqs[senderAccountId] == nil { pendingReqs[senderAccountId] = make(map[string]bool) } pendingReqs[senderAccountId][receiverAccountId] = true } if err := rows.Err(); err != nil { return } fm.pendingReqs = pendingReqs } func (fm *FriendsMgr) addFriendshipToMap(accountID string, friendship *Friendship) { if fm.friendships[accountID] == nil { fm.friendships[accountID] = []*Friendship{friendship} } else { fm.friendships[accountID] = append(fm.friendships[accountID], friendship) } } func (fm *FriendsMgr) RegisterUser(accountId string, username string) { fm.users[accountId] = &User{AccountId: accountId, UserName: username} }