113 lines
2.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package operation
import (
"context"
"errors"
"fmt"
"game/common/model"
"game/common/model/user"
"game/common/proto/pb"
"game/common/serialization"
"game/common/utils"
"github.com/fox/fox/log"
"github.com/fox/fox/xrand"
"github.com/go-redis/redis/v8"
"github.com/google/uuid"
"gorm.io/gorm"
"strconv"
)
type UserOp struct {
db *gorm.DB
userRedis *redis.Client
*model.TableOp[user.User]
}
// 玩家表
func NewUserOp() *UserOp {
return &UserOp{
db: UserDB,
userRedis: UserRedis,
TableOp: model.NewTableOp[user.User](UserDB, UserRedis),
}
}
func (s *UserOp) redisKey(accountId int64) string {
return fmt.Sprintf("account_id:%v", accountId)
}
func (s *UserOp) GetUserByAccountId(accountId int64) (*user.User, pb.ErrCode) {
sUid, err := s.userRedis.Get(context.Background(), s.redisKey(accountId)).Result()
if err != nil {
if errors.Is(err, redis.Nil) {
us := &user.User{}
err = s.db.Where("account_id = ?", accountId).First(us).Error
if err != nil {
log.DebugF("find user by account id:%v err:%v", accountId, err)
return nil, pb.ErrCode_SystemErr
}
// 从db中查到后写入redis并建立索引
if us.ID > 0 {
_, _ = s.Update(us.ID, serialization.StructToMap(us))
_ = s.userRedis.Set(context.Background(), s.redisKey(accountId), us.ID, model.TableExpire).Err()
} else {
// db中没有则创建玩家
return s.createUserAccountId(accountId)
}
return us, pb.ErrCode_OK
} else {
log.ErrorF("find user by account id:%v err:%v", accountId, err)
return nil, pb.ErrCode_SystemErr
}
}
uid, _ := strconv.ParseInt(sUid, 10, 64)
if uid < 0 {
log.ErrorF("get user failed, account id:%d, uid:%v", accountId, sUid)
return nil, pb.ErrCode_SystemErr
}
return s.Find(uid)
}
func (s *UserOp) generateUniqueNickname(db *gorm.DB) (string, error) {
// 基础昵称模板
baseNick := "用户_" + uuid.New().String()[:8]
nickname := baseNick
// 检查是否唯一,不唯一则追加随机字符
for i := 0; i < 5; i++ { // 最多尝试5次
var count int64
err := db.Model(&user.User{}).Where("nickname = ?", nickname).Count(&count).Error
if err != nil {
return "", err
}
if count == 0 {
return nickname, nil
}
nickname = baseNick + xrand.RandomString(2) // 追加2位随机字符
}
return "", fmt.Errorf("无法生成唯一昵称")
}
// 创建用户
func (s *UserOp) createUserAccountId(accountId int64) (*user.User, pb.ErrCode) {
nickname, err := s.generateUniqueNickname(s.db)
if err != nil {
log.ErrorF("generate unique nickname err:%v", err)
return nil, pb.ErrCode_SystemErr
}
us := &user.User{
AccountId: accountId,
Nickname: nickname,
}
var code pb.ErrCode
us, code = s.Create(us)
log.DebugF("create user:%v", utils.JsonMarshal(us))
if code != pb.ErrCode_OK {
return nil, code
}
// 建立索引
_ = s.userRedis.Set(context.Background(), s.redisKey(us.AccountId), us.ID, model.TableExpire).Err()
return us, pb.ErrCode_OK
}