game2006go/server/imserver/friendsmgr.go

433 lines
11 KiB
Go

package main
import (
"cs"
"errors"
"f5"
"fmt"
"mt"
"q5"
"strings"
"time"
)
const (
FriendMemberCount = 200
PendingReqsCount = 20
)
type FriendsMgr struct {
cs.MsgHandlerImpl
users map[string]*User
searchCaches map[string]SearchCache
friendships map[string][]*Friendship
pendingReqs map[string]map[string]bool
blockedUser map[string][]string
}
type SearchCache struct {
Users []*User
LastModified time.Time
}
var gameDBStore *q5.Mysql
var friendDBStore *q5.Mysql
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(),
)
err := gameDBStore.Open()
if err != nil {
f5.GetSysLog().Info("mysql error:%s\n", err)
return
}
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(),
)
err = friendDBStore.Open()
if err != nil {
f5.GetSysLog().Info("mysql error:%s\n", err)
return
}
// 加载好友关系表 列表
fm.loadFriendshipsFromDB(friendDBStore)
// 加载等待验证好友请求 列表
fm.loadPendingRequestsFromDB(friendDBStore)
fm.searchCaches = make(map[string]SearchCache)
}
func (fm *FriendsMgr) unInit() {
// 1. Loop struct data
// 2. Struct Data Persist to DB
}
func (fm *FriendsMgr) searchUserByAccountId(accountId string) *User {
if user, ok := fm.users[accountId]; ok {
return user
}
return nil
}
func (fm *FriendsMgr) searchUsers(keyword string) []*User {
if len(keyword) > 42 {
return nil
}
if cachedResult, ok := fm.searchCaches[keyword]; ok {
if time.Since(cachedResult.LastModified) <= 10*time.Hour {
return cachedResult.Users
}
}
maxUsers := 20
var listFriend []*User
lowercaseQuery := strings.ToLower(keyword)
for _, u := range fm.users {
if strings.Contains(strings.ToLower(u.Username), lowercaseQuery) {
uEntity := &User{
AccountId: u.AccountId,
Username: u.Username,
}
listFriend = append(listFriend, uEntity)
}
// 显示搜索结果 20条
if len(listFriend) >= maxUsers {
break
}
}
// Add to caches
fm.searchCaches[keyword] = SearchCache{
Users: listFriend,
LastModified: time.Now(),
}
fm.clearExpiredCaches()
return listFriend
}
func (fm *FriendsMgr) addBlocked(account1Id string, account2Id string) error {
if fm.blockedUser[account1Id] == nil {
fm.blockedUser[account1Id] = []string{}
}
if len(fm.blockedUser[account1Id]) >= 50 {
return fmt.Errorf("your blacklist has reached the limit")
}
index := fm.findBlockedUserIndex(account1Id, account2Id)
if index < 0 {
fm.blockedUser[account1Id] = append(fm.blockedUser[account1Id], account2Id)
}
return nil
}
func (fm *FriendsMgr) removeBlocked(account1Id string, account2Id string) error {
if fm.blockedUser[account1Id] == nil {
return fmt.Errorf("your blacklist is emtpy")
}
index := fm.findBlockedUserIndex(account1Id, account2Id)
if index < 0 {
return fmt.Errorf("your blacklist not exists target account id")
}
blockedUsers := fm.blockedUser[account1Id]
blockedUsers = append(blockedUsers[:index], blockedUsers[index+1:]...)
fm.blockedUser[account1Id] = blockedUsers
return nil
}
// addFriendRequest 发送好友请求
func (fm *FriendsMgr) addFriendRequest(account1Id string, account2Id string) error {
_, exists1 := fm.users[account1Id]
_, exists2 := fm.users[account2Id]
if !exists1 || !exists2 {
return errors.New("users not exist")
}
// step1. check in blocked
for _, blockedAccountId := range fm.blockedUser[account1Id] {
if blockedAccountId == account2Id {
return errors.New("users in blocked")
}
}
for _, blockedAccountId := range fm.blockedUser[account2Id] {
if blockedAccountId == account2Id {
return errors.New("users in blocked")
}
}
// step2. check target user member count
if fm.getFriendCount(account1Id) >= FriendMemberCount {
return fmt.Errorf("player:%s, friends are full", account1Id)
}
if fm.getFriendCount(account2Id) >= FriendMemberCount {
return fmt.Errorf("player:%s, friends are full", account2Id)
}
// step3. check target user pending request count
if fm.getFriendRequestCount(account2Id) >= PendingReqsCount {
return fmt.Errorf("player:%s, friends are full", account2Id)
}
// 为 account2Id 创建等待验证好友请求 记录,由 account1Id 申请的
if fm.pendingReqs[account2Id] == nil {
fm.pendingReqs[account2Id] = make(map[string]bool)
}
fm.pendingReqs[account2Id][account1Id] = true
return nil
}
// acceptFriendRequest 接受好友请求
func (fm *FriendsMgr) acceptFriendRequest(account1Id string, account2Id string) error {
if !fm.pendingReqs[account1Id][account2Id] {
return errors.New("no pending friend request from account1Id to account2Id")
}
// step1. delete or update friend request record
// step2. add friend history to db
// step3. add friendship
if fm.getFriendCount(account1Id) >= FriendMemberCount {
return fmt.Errorf("player:%s, friends are full", account1Id)
}
if fm.getFriendCount(account2Id) >= FriendMemberCount {
return fmt.Errorf("player:%s, friends are full", account2Id)
}
//err := fm.acceptFriendRequestToDB(account1Id, account2Id)
//if err != nil {
// return err
//}
// Create a new friendship
friendship := &Friendship{
User1: fm.users[account1Id],
User2: fm.users[account2Id],
}
fm.friendships[account1Id] = append(fm.friendships[account1Id], friendship)
fm.friendships[account2Id] = append(fm.friendships[account2Id], friendship)
delete(fm.pendingReqs[account1Id], account2Id)
delete(fm.pendingReqs[account2Id], account1Id)
return nil
}
// rejectFriendRequest 拒绝好友请求
func (fm *FriendsMgr) rejectFriendRequest(account1Id string, account2Id string) error {
if fm.pendingReqs[account1Id] == nil {
return errors.New("no pending friend request to reject")
}
if !fm.pendingReqs[account1Id][account2Id] {
return errors.New("no pending friend request from user1 to user2")
}
delete(fm.pendingReqs[account1Id], account2Id)
if len(fm.pendingReqs[account2Id]) == 0 {
delete(fm.pendingReqs, account2Id)
}
//err := fm.acceptFriendRequestToDB(account1Id, account2Id)
//if err != nil {
// return err
//}
//fm.pendingReqs[account1Id], account2Id
//fm.pendingReqs[account2Id], account1Id
return nil
}
func (fm *FriendsMgr) deleteFriendShip(accountId string, account2Id string) {
//delete(fm.friendships[accountId], account2Id)
}
// getFriendCount 好友数量
func (fm *FriendsMgr) getFriendCount(accountId string) int {
if _, ok := fm.friendships[accountId]; ok {
return len(fm.friendships[accountId])
}
return 0
}
// getFriendRequestCount 等待请求数量
func (fm *FriendsMgr) getFriendRequestCount(accountId string) int {
if _, ok := fm.pendingReqs[accountId]; ok {
return len(fm.pendingReqs[accountId])
}
return 0
}
// listFriend 我的好友列表
func (fm *FriendsMgr) listFriend(accountId string) []*User {
// By default, Users member data count:10
var users []*User
for _, friendship := range fm.friendships[accountId] {
if friendship.User1.AccountId != accountId {
uEntity := &User{
AccountId: friendship.User1.AccountId,
Username: friendship.User1.Username,
}
users = append(users, uEntity)
} else {
uEntity := &User{
AccountId: friendship.User2.AccountId,
Username: friendship.User2.Username,
}
users = append(users, uEntity)
}
}
return users
}
func (fm *FriendsMgr) acceptFriendRequestToDB(account1Id string, account2Id string) error {
// step1. UPDATE t_friend_pending_requests
_, err := friendDBStore.Exec("UPDATE t_friend_pending_requests SET flag=1 WHERE sender_account_id = ? AND receiver_account_id = ?", account1Id, account2Id)
if err != nil {
return err
}
// step2. add t_friend_ships
compareResult := strings.Compare(account1Id, account2Id)
if compareResult > 0 {
temp := account1Id
account1Id = account2Id
account2Id = temp
}
_, err = friendDBStore.Exec("REPLACE INTO `t_friend_ships` (user1_id, user2_id, createtime, createtime) VALUES (?, ?)", account1Id, account2Id, "now()", "now()")
if err != nil {
return err
}
return nil
}
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:%s\n", 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:%s\n", 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, flag from t_friend_pending_requests;")
if err != nil {
f5.GetSysLog().Info("mysql error:%s\n", err)
return
}
pendingReqs := make(map[string]map[string]bool, 10)
for rows.Next() {
var (
senderAccountId, receiverAccountId string
requestStatus string
)
if err := rows.Scan(&senderAccountId, &receiverAccountId, &requestStatus); err != nil {
continue
}
if pendingReqs[senderAccountId] == nil {
pendingReqs[senderAccountId] = make(map[string]bool)
}
status := true
if requestStatus == "1" {
// 等待验证的好友请求, 拒绝
status = false
}
pendingReqs[senderAccountId][receiverAccountId] = status
}
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) error {
if fm.users[accountId] == nil {
fm.users[accountId] = &User{AccountId: accountId, Username: username}
return nil
}
return fmt.Errorf("user exists")
}
func (fm *FriendsMgr) clearExpiredCaches() {
expirationTime := time.Now().Add(-24 * time.Hour)
for key, entry := range fm.searchCaches {
if entry.LastModified.Before(expirationTime) {
delete(fm.searchCaches, key)
}
}
}
func PrintUsers(str string, userList []*User) {
for _, user := range userList {
fmt.Printf("[%s]:accountId:%s, username:%s \n", str, user.AccountId, user.Username)
}
}
func (fm *FriendsMgr) findBlockedUserIndex(AccountId1, AccountId2 string) int {
for i, blockedAccountId := range fm.blockedUser[AccountId1] {
if blockedAccountId == AccountId2 {
return i
}
}
return -1
}