ecs/servers/gate/logic/manager.go

850 lines
23 KiB
Go
Raw Normal View History

2025-06-04 18:17:39 +08:00
package logic
import (
"ecs/proto"
"github.com/oylshe1314/framework/client/db"
"github.com/oylshe1314/framework/client/rpc"
"github.com/oylshe1314/framework/errors"
"github.com/oylshe1314/framework/log"
"github.com/oylshe1314/framework/server"
"github.com/oylshe1314/framework/util"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
"sort"
"sync"
"time"
)
2025-07-16 10:05:22 +08:00
type manager struct {
2025-06-04 18:17:39 +08:00
server server.Server
2025-07-16 10:05:22 +08:00
}
func (this *manager) Logger() log.Logger {
return this.server.Logger()
}
type GateManager struct {
manager
2025-06-04 18:17:39 +08:00
setting *Setting
offlineTime int64
offlineMutex sync.Mutex
offlineTimer *time.Timer
2025-07-16 10:05:22 +08:00
mongoClient db.MongoClient
httpRpcClient rpc.HttpRpcClient
2025-06-04 18:17:39 +08:00
}
2025-07-16 10:05:22 +08:00
func NewGateManager(svr server.Server, mongoClient db.MongoClient, httpRpcClient rpc.HttpRpcClient) *GateManager {
2025-06-04 18:17:39 +08:00
return &GateManager{
2025-07-16 10:05:22 +08:00
manager: manager{
server: svr,
},
2025-06-04 18:17:39 +08:00
mongoClient: mongoClient,
httpRpcClient: httpRpcClient,
}
}
func (this *GateManager) Init() error {
return nil
}
func (this *GateManager) Close() error {
return nil
}
func (this *GateManager) SetSetting(setting *Setting) error {
var updateOption = options.Update().SetUpsert(true)
_, err := this.mongoClient.Collection(tableSetting).UpdateByID(this.mongoClient.Context(), setting.Id, bson.M{"$set": setting}, updateOption)
if err != nil {
2025-07-16 10:05:22 +08:00
this.Logger().Error(err)
return proto.ErrInternalError
2025-06-04 18:17:39 +08:00
}
if setting.LoginClosed && setting.Offline {
2025-07-16 10:05:22 +08:00
var now = util.NowUnix()
2025-06-04 18:17:39 +08:00
this.offlineMutex.Lock()
if this.offlineTimer != nil {
if this.offlineTime == setting.CloseTime || now >= setting.CloseTime {
this.offlineMutex.Unlock()
return nil
}
this.offlineTimer.Stop()
this.offlineTime = 0
this.offlineTimer = nil
}
this.offlineMutex.Unlock()
var f = func() {
this.offlineMutex.Lock()
this.offlineTime = 0
this.offlineTimer = nil
this.offlineMutex.Unlock()
ar, err := this.httpRpcClient.AllPost("game_1", "/server/offline", nil, nil, nil)
if err != nil {
2025-07-16 10:05:22 +08:00
this.Logger().Errorf("Http get error, error: %v", err)
2025-06-04 18:17:39 +08:00
} else {
for appId, result := range ar {
if result.Err != nil {
2025-07-16 10:05:22 +08:00
this.Logger().Errorf("[game_1:%d] <- Server offline error, %v", appId, result.Err)
2025-06-04 18:17:39 +08:00
continue
}
if result.Res.Status != errors.StatusSuccessful {
2025-07-16 10:05:22 +08:00
this.Logger().Errorf("[game_1:%d] <- Server offline failed, %s", appId, result.Res.Message)
2025-06-04 18:17:39 +08:00
continue
}
}
}
}
2025-07-16 10:05:22 +08:00
if !setting.TimedClose || util.NowUnix() >= setting.CloseTime {
2025-06-04 18:17:39 +08:00
f()
} else {
this.offlineMutex.Lock()
this.offlineTime = setting.CloseTime
this.offlineTimer = time.AfterFunc(time.Second*time.Duration(setting.CloseTime-now), f)
this.offlineMutex.Unlock()
}
} else {
this.offlineMutex.Lock()
if this.offlineTimer != nil {
this.offlineTimer.Stop()
this.offlineTime = 0
this.offlineTimer = nil
}
this.offlineMutex.Unlock()
}
return nil
}
func (this *GateManager) GetSetting() (*Setting, error) {
var setting = this.setting
if setting == nil {
setting = &Setting{Id: 1}
var err = this.mongoClient.Collection(tableSetting).FindOne(this.mongoClient.Context(), bson.M{"_id": setting.Id}).Decode(setting)
if err != nil {
if errors.Is(err, mongo.ErrNoDocuments) {
return nil, nil
}
return nil, proto.ErrInternalError
2025-06-04 18:17:39 +08:00
}
}
return setting, nil
}
func (this *GateManager) serverRankFunc(serverList []*proto.GameServer, recentServer uint32) func(i, j int) bool {
//var guidanceConfig = this.GetConfig()
return func(i, j int) bool {
var s1, s2 = serverList[i], serverList[j]
//if s1.Id == recentServer {
// return true
//}
//if s2.Id == recentServer {
// return false
//}
//
2025-06-04 18:17:39 +08:00
//gn1, ok1 := guidanceConfig[s1.Id]
//gn2, ok2 := guidanceConfig[s2.Id]
//
//if ok1 && ok2 {
// if s1.Charges < gn1 && s2.Charges < gn2 {
// if s1.Charges != s2.Charges {
// return s1.Charges > s2.Charges
// } else {
// return s1.Id < s2.Id
// }
// }
//
// if s1.Charges < gn1 {
// return true
// }
//
// if s2.Charges < gn2 {
// return false
// }
//
// return s1.Charges < s2.Charges
//}
//
//if ok1 {
// return s1.Charges < gn1
//}
//
//if ok2 {
// return !(s2.Charges < gn2)
//}
//if s1.Online != s2.Online {
// return s1.Online < s2.Online
//} else {
return s1.Id < s2.Id
//}
2025-06-04 18:17:39 +08:00
}
}
type gameServerInfo struct {
appId uint32
address string
online uint32
}
type gameServerList struct {
id uint32
platform uint32
channel uint32
area string
name string
online uint32
serverList []*gameServerInfo
}
2025-06-04 18:17:39 +08:00
func (this *GateManager) GetServerList(platform uint32, channel uint32, recentServer uint32) ([]*proto.GameServer, error) {
var setting, err = this.GetSetting()
if err != nil {
return nil, err
}
var closedList = map[uint32]struct{}{}
if setting != nil && setting.LoginClosed {
2025-07-16 10:05:22 +08:00
if !setting.TimedClose || util.NowUnix() >= setting.CloseTime {
2025-06-04 18:17:39 +08:00
for _, closedId := range setting.ClosedList {
closedList[closedId] = struct{}{}
}
}
}
ar, err := this.httpRpcClient.AllGet("game", "/server/info", nil, &proto.MsgServerInfoAck{})
if err != nil {
return nil, proto.ErrServerMaintain
}
2025-06-04 18:17:39 +08:00
var listMap = map[uint32]*gameServerList{}
for appId, reply := range ar {
if reply.Err != nil {
2025-07-16 10:05:22 +08:00
this.Logger().Error("Get server online failed, ", reply.Err)
2025-06-04 18:17:39 +08:00
continue
}
if reply.Res.Error() != nil {
2025-07-16 10:05:22 +08:00
this.Logger().Errorf("Get server online failed, status: %d, message: %s", reply.Res.Status, reply.Res.Message)
2025-06-04 18:17:39 +08:00
continue
}
var node = this.httpRpcClient.Node("game", appId)
if node == nil {
2025-06-04 18:17:39 +08:00
continue
}
var infoAck = reply.Res.Data.(*proto.MsgServerInfoAck)
2025-06-04 18:17:39 +08:00
var gsl = listMap[infoAck.Id]
if gsl == nil {
gsl = &gameServerList{
id: infoAck.Id,
platform: infoAck.Platform,
channel: infoAck.Channel,
area: infoAck.Area,
name: infoAck.Name,
}
listMap[infoAck.Id] = gsl
2025-06-04 18:17:39 +08:00
}
gsl.online += infoAck.Online
gsl.serverList = append(gsl.serverList, &gameServerInfo{appId: appId, address: node.Exter.Address, online: infoAck.Online})
2025-06-04 18:17:39 +08:00
}
var serverList []*proto.GameServer
for _, gsl := range listMap {
if len(gsl.serverList) == 0 {
2025-06-04 18:17:39 +08:00
continue
}
sort.Slice(gsl.serverList, func(i, j int) bool {
if gsl.serverList[i].online == gsl.serverList[j].online {
return gsl.serverList[i].appId < gsl.serverList[j].appId
} else {
return gsl.serverList[i].online < gsl.serverList[j].online
}
})
serverList = append(serverList, &proto.GameServer{
Id: gsl.id,
Area: gsl.area,
Name: gsl.name,
Address: gsl.serverList[0].address,
Online: gsl.online,
})
2025-06-04 18:17:39 +08:00
}
sort.Slice(serverList, this.serverRankFunc(serverList, recentServer))
return serverList, nil
}
func (this *GateManager) GetNotice() (string, string, string) {
var setting, _ = this.GetSetting()
if setting == nil {
return "", "", ""
}
return setting.Version, setting.Title, setting.Content
}
//type UserManager struct {
// GateManager
//
// locker sync.RWMutex
// users map[string]*User
// tokens map[uint64]string
//}
//
//func NewUserManager(svr server.Server, mongoClient *db.MongoClient, httpRpcClient *rpc.HttpRpcClient, guideConfig []*util.Pair[uint32, uint32]) *UserManager {
// return &UserManager{
// GateManager: GateManager{
// _Guidance: _Guidance{config: util.Pairs[uint32, uint32](guideConfig).ToMap()},
// logger: svr.Logger(),
// server: svr,
// mongoClient: mongoClient,
// httpRpcClient: httpRpcClient,
// },
// users: map[string]*User{},
// tokens: map[uint64]string{},
// }
//}
//
//func (this *UserManager) Init() error {
// return nil
//}
//
//func (this *UserManager) Close() error {
// return nil
//}
//
//func (this *UserManager) saveUser(user *User) error {
// _, err := this.mongoClient.Collection(TableUser).InsertOne(this.mongoClient.Context(), user)
// return err
//}
//
//func (this *UserManager) queryUser(filter bson.M) (*User, error) {
// var user = new(User)
// var err = this.mongoClient.Collection(TableUser).FindOne(this.mongoClient.Context(), filter).Decode(user)
// if err != nil {
// if err == mongo.ErrNoDocuments {
// return nil, nil
// }
// return nil, err
// }
// return user, nil
//}
//
//func (this *UserManager) updateUser(id string, set bson.M) error {
// var _, err = this.mongoClient.Collection(TableUser).UpdateByID(this.mongoClient.Context(), id, bson.M{"$set": set})
// return err
//}
//
//func (this *UserManager) SignUp(origin *proto.UserOrigin, auth *proto.UserAuth) (*User, error) {
// user, err := this.queryUser(bson.M{"_id": UserKey(origin.Channel, auth.Username)})
// if err != nil {
// this.logger.Error(err)
// return nil, proto.RawErrInternalError
// }
//
// if user != nil {
// return nil, proto.RawErrUsernameExists
// }
//
// return this.signUp(origin, auth, nil)
//}
//
//func (this *UserManager) signUp(origin *proto.UserOrigin, auth *proto.UserAuth, thirdInfo map[string]interface{}) (*User, error) {
// counter, err := this.mongoClient.Counter("user_id", 1)
// if err != nil {
// this.logger.Error(err)
// return nil, err
// }
//
// var uid = util.EncryptUid(counter)
//
// if len(auth.Password) > 0 {
// password, err := bcrypt.GenerateFromPassword([]byte(auth.Password), bcrypt.DefaultCost)
// if err != nil {
// this.logger.Error(err)
// return nil, proto.RawErrInternalError
// }
//
// auth.Password = string(password)
// }
//
// var user = &User{
// Id: UserKey(origin.Channel, auth.Username),
// UserId: uid,
// Platform: origin.Platform,
// Channel: origin.Channel,
// Username: auth.Username,
// Password: auth.Password,
// CreateTime: util.Unix(),
// ThirdInfo: thirdInfo,
// }
//
// err = this.saveUser(user)
// if err != nil {
// this.logger.Error(err)
// return nil, proto.RawErrInternalError
// }
//
// return user, nil
//}
//
//func (this *UserManager) LoginThird(origin *proto.UserOrigin, third *proto.UserThird) (*LoginResult, error) {
// switch proto.Channel(origin.Channel) {
// case proto.ChannelWechatMiniGame:
// ack, err := wechat.Code2Session(third.Token)
// if err != nil {
// this.logger.Error("Code to session failed, ", err)
// return nil, proto.RawErrUserLoginFailed
// }
//
// if ack.ErrCode != 0 {
// this.logger.Error("Third user login failed, msg: ", ack.ErrMsg)
// return nil, proto.RawErrUserLoginFailed
// }
//
// return this.login(origin, &proto.UserAuth{Username: ack.OpenId}, map[string]any{"openid": ack.OpenId, "unionid": ack.UnionId, "sessionKey": ack.SessionKey})
// case proto.ChannelTapTap:
// if third.Args == nil || third.Args.TapTap == nil || third.Args.TapTap.MacKey == "" {
// return nil, proto.RawErrParameterError
// }
//
// ack, err := taptap.AccountProfile(third.Token, third.Args.TapTap.MacKey)
// if err != nil {
// this.logger.Error(err)
// return nil, proto.RawErrUserLoginFailed
// }
//
// if !ack.Success {
// return nil, proto.RawErrUserLoginFailed
// }
//
// return this.login(origin, &proto.UserAuth{Username: ack.Data.Openid}, map[string]interface{}{"name": ack.Data.Name, "avatar": ack.Data.Avatar})
// default:
// return nil, proto.ErrChannelError
// }
//}
//
//func (this *UserManager) Login(origin *proto.UserOrigin, auth *proto.UserAuth) (*LoginResult, error) {
// return this.login(origin, auth, nil)
//}
//
//func (this *UserManager) login(origin *proto.UserOrigin, auth *proto.UserAuth, thirdInfo map[string]interface{}) (*LoginResult, error) {
// user, err := this.queryUser(bson.M{"_id": UserKey(origin.Channel, auth.Username)})
// if err != nil {
// this.logger.Error(err)
// return nil, proto.RawErrInternalError
// }
//
// if user == nil {
// user, err = this.signUp(origin, auth, thirdInfo)
// if err != nil {
// return nil, err
// }
// } else {
// if user.BanLogin && user.BanLoginTime > util.Unix() {
// return nil, proto.RawErrUserBanLogin
// }
//
// if len(auth.Password) > 0 {
// err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(auth.Password))
// if err != nil {
// this.logger.Error(err)
// return nil, proto.RawErrPasswordError
// }
// }
//
// if thirdInfo != nil {
// if !reflect.DeepEqual(user.ThirdInfo, thirdInfo) {
// user.ThirdInfo = thirdInfo
// err = this.updateUser(user.Id, bson.M{"third_info": user.ThirdInfo})
// if err != nil {
// this.logger.Error(err)
// return nil, proto.RawErrInternalError
// }
// }
// }
// }
//
// var token = util.RandomToken()
//
// this.locker.Lock()
// defer this.locker.Unlock()
//
// if expired, ok := this.tokens[user.UserId]; ok {
// delete(this.users, expired)
// }
//
// this.users[token] = user
// this.tokens[user.UserId] = token
//
// return &LoginResult{Token: token, Username: user.Username, RecentServer: user.RecentServer}, nil
//}
//
//func (this *UserManager) TokenVerify(token string, serverId uint32) (*User, error) {
// this.locker.RLock()
// var user = this.users[token]
// this.locker.RUnlock()
// if user == nil {
// return nil, nil
// }
//
// if user.RecentServer != serverId {
// user.RecentServer = serverId
// var err = this.updateUser(user.Id, bson.M{"recent_server": user.RecentServer})
// if err != nil {
// return nil, err
// }
// }
//
// return user, nil
//}
//
//func (this *UserManager) Query(channel uint32, username string) (*User, error) {
// user, err := this.queryUser(bson.M{"_id": UserKey(channel, username)})
// if err != nil {
// this.logger.Error(err)
// return nil, proto.RawErrInternalError
// }
// return user, nil
//}
//
//func (this *UserManager) kick(user *User) error {
// if user.RecentServer == 0 {
// return proto.RawErrUserNotOnline
// }
//
// reply, err := this.httpRpcClient.AppIdPost("game_1", user.RecentServer, "/server/player/operate", nil, &proto.MsgPlayerOperateReq{PlayerId: user.UserId, OperateType: 3}, nil)
// if err != nil {
// this.logger.Error("Kick player error, ", err)
// return proto.RawErrInternalError
// }
//
// if reply.Status != errors.StatusSuccessful {
// this.logger.Error("Kick player failed, ", reply.Message)
// return proto.RawErrInternalError
// }
//
// return nil
//}
//
//func (this *UserManager) Kick(userId string) error {
// user, err := this.queryUser(bson.M{"_id": userId})
// if err != nil {
// this.logger.Error("Query user error, ", err)
// return proto.RawErrInternalError
// }
//
// if user == nil {
// return proto.RawErrUserNotExists
// }
//
// return this.kick(user)
//}
//
//func (this *UserManager) Ban(userId string, banDays uint32) error {
// user, err := this.queryUser(bson.M{"_id": userId})
// if err != nil {
// this.logger.Error("Query user error, ", err)
// return proto.RawErrInternalError
// }
//
// if user == nil {
// return proto.RawErrUserNotExists
// }
//
// if banDays == 0 {
// user.BanLogin = false
// user.BanLoginTime = int64(0)
// } else {
// user.BanLogin = true
// user.BanLoginTime = util.TodayBeginTime() + 86400*int64(banDays)
// }
//
// _, err = this.mongoClient.Collection(TableUser).UpdateByID(this.mongoClient.Context(), user.Id, bson.M{"$set": bson.M{"ban_login": user.BanLogin, "ban_login_time": user.BanLoginTime}})
// if err != nil {
// this.logger.Error(err)
// return proto.RawErrInternalError
// }
//
// if banDays == 0 {
// return nil
// }
//
// return this.kick(user)
//}
//
//func (this *UserManager) ResetPassword(userId string, password string) error {
// user, err := this.queryUser(bson.M{"_id": userId})
// if err != nil {
// this.logger.Error("Query user error, ", err)
// return proto.RawErrInternalError
// }
//
// if user == nil {
// return proto.RawErrUserNotExists
// }
//
// user.Password = password
//
// _, err = this.mongoClient.Collection(TableUser).UpdateByID(this.mongoClient.Context(), user.Id, bson.M{"$set": bson.M{"password": user.Password}})
// if err != nil {
// this.logger.Error(err)
// return proto.RawErrInternalError
// }
//
// return this.kick(user)
//}
//
//func (this *UserManager) ChargeCallback(status proto.PaymentStatus, orderId, sign, extOrderNo string, extend *proto.OrderExtend) error {
// var header = client.HttpHeader{"PlayerId": []string{util.IntegerToString(extend.Uid)}}
// reply, err := this.httpRpcClient.AppIdPost("game_1", extend.Sid, "/player/charge/callback", nil, &proto.MsgGateChargeCallbackReq{OrderId: orderId, Sign: sign, Status: int32(status), ExtOrderNo: extOrderNo}, nil, header)
// if err != nil {
// return err
// }
//
// if reply.Status != errors.StatusSuccessful {
// return errors.Error(reply.Message)
// }
//
// return nil
//}
//
//func (this *UserManager) WechatAccessTokenExpired(appletId string) error {
// reply, err := this.httpRpcClient.RandPost("center", "/wechat/accessToken/refresh", nil, &proto.MsgRefreshWechatAccessTokenReq{AppletId: appletId}, nil)
// if err != nil {
// return err
// }
//
// if reply.Status != errors.StatusSuccessful {
// return errors.Error(reply.Message)
// }
//
// return nil
//}
//
//func (this *UserManager) GetCdkey(key string) (*Cdkey, error) {
// var cdkey = &Cdkey{Key: key}
// var err = this.mongoClient.Collection(TableCdkey).FindOne(this.mongoClient.Context(), bson.M{"_id": cdkey.Key}).Decode(cdkey)
// if err != nil {
// if err == mongo.ErrNoDocuments {
// return nil, nil
// }
//
// this.logger.Error("Query cdkey error, ", err)
// return nil, proto.RawErrInternalError
// }
//
// return cdkey, nil
//}
//
//type PageableQueryResult[Entity any] struct {
// Total []*QueryTotal `bson:"total"`
// List []*Entity `bson:"list"`
//}
//
//func (this *UserManager) PageableQueryUser(pageNo uint32, pageSize uint32, channel uint32, userId uint64) (uint32, []*User, error) {
// var offset = int64(pageSize * (pageNo - 1))
// var limit = int64(pageSize)
//
// var pipeline bson.A
// if channel > 0 {
// pipeline = append(pipeline, bson.M{"$match": bson.M{"channel": channel}})
// }
// if userId > 0 {
// pipeline = append(pipeline, bson.M{"$match": bson.M{"user_id": userId}})
// }
// pipeline = append(pipeline, bson.M{"$facet": bson.M{"total": bson.A{bson.M{"$count": "total"}}, "list": bson.A{bson.M{"$skip": offset}, bson.M{"$limit": limit}}}})
//
// var result = new(PageableQueryResult[User])
// cur, err := this.mongoClient.Collection(TableUser).Aggregate(this.mongoClient.Context(), pipeline)
// if err != nil {
// if err == mongo.ErrNoDocuments {
// return 0, nil, nil
// }
//
// this.logger.Error("Query cdkey error, ", err)
// return 0, nil, proto.RawErrInternalError
// }
//
// if cur.Next(this.mongoClient.Context()) {
// err = cur.Decode(result)
// if err != nil {
// this.logger.Error("Query cdkey error, ", err)
// return 0, nil, proto.RawErrInternalError
// }
// }
//
// var total = uint32(0)
// if len(result.Total) > 0 {
// total = result.Total[0].Total
// }
//
// return total, result.List, nil
//}
//
//func (this *UserManager) PageableQueryCdkey(pageNo uint32, pageSize uint32, channel uint32) (uint32, []*Cdkey, error) {
// var offset = int64(pageSize * (pageNo - 1))
// var limit = int64(pageSize)
//
// var pipeline bson.A
// if channel > 0 {
// pipeline = append(pipeline, bson.M{"$match": bson.M{"channel": bson.M{"$in": bson.A{0, channel}}}})
// }
// pipeline = append(pipeline, bson.M{"$facet": bson.M{"total": bson.A{bson.M{"$count": "total"}}, "list": bson.A{bson.M{"$skip": offset}, bson.M{"$limit": limit}}}})
//
// var result = new(PageableQueryResult[Cdkey])
// cur, err := this.mongoClient.Collection(TableCdkey).Aggregate(this.mongoClient.Context(), pipeline)
// if err != nil {
// if err == mongo.ErrNoDocuments {
// return 0, nil, nil
// }
//
// this.logger.Error("Query cdkey error, ", err)
// return 0, nil, proto.RawErrInternalError
// }
//
// if cur.Next(this.mongoClient.Context()) {
// err = cur.Decode(result)
// if err != nil {
// this.logger.Error("Query cdkey error, ", err)
// return 0, nil, proto.RawErrInternalError
// }
// }
//
// var total = uint32(0)
// if len(result.Total) > 0 {
// total = result.Total[0].Total
// }
//
// return total, result.List, nil
//}
//
//func (this *UserManager) AddCdkey(channel uint32, key string, validDays int64, itemId []uint32, itemNum []uint32) (*Cdkey, error) {
// cur, err := this.mongoClient.Collection(TableCdkey).Find2(this.mongoClient.Context(), bson.M{"_id": key})
// if err != nil {
// this.logger.Error("Query cdkey error, ", err)
// return nil, proto.RawErrInternalError
// }
//
// if cur.Next(this.mongoClient.Context()) {
// this.logger.Error("Add cdkey the key has existed")
// return nil, proto.RawErrCdKeyExists
// }
//
// var expiration = int64(0)
// if validDays > 0 {
// expiration = util.TodayBeginTime() + util.DayTotalSeconds*validDays
// }
//
// var cdkey = &Cdkey{
// Key: key,
// Channel: channel,
// Expiration: expiration,
// ItemId: itemId,
// ItemNum: itemNum,
// }
//
// _, err = this.mongoClient.Collection(TableCdkey).InsertOne(this.mongoClient.Context(), cdkey)
// if err != nil {
// this.logger.Error("Insert cdkey error, ", err)
// return nil, proto.RawErrInternalError
// }
//
// return cdkey, nil
//}
//
//const cdKeyCounterMax = 0b11111111111111111111111111111111111111111 // S27TO3CV <- 2199023255551
//
//var ins = []int{
// 40, 37, 36, 39, 30, 35, 22, 33, 28, 27, 32, 29, 34, 31, 38, 17, 26, 1, 10, 5, 14, 23, 4, 11, 0, 19, 16, 21, 18, 7, 12, 25, 6, 15, 9, 2, 20, 3, 8, 13, 24,
//}
//
//var chs = []byte{
// '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
// 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
//}
//
//func (this *UserManager) transBits(n uint64) uint64 {
// var bits = make([]byte, 41)
// for i := 40; n > 0; n, i = n/2, i-1 {
// bits[i] = byte(n % 2)
// }
//
// var nits = make([]byte, 41)
// for ni, bi := range ins {
// nits[ni] = bits[bi]
// }
//
// n = 0
// var bi = len(nits) - 1
// for i := bi; i >= 0; i-- {
// n += uint64(nits[i]) * uint64(math.Pow(2, float64(bi-i)))
// }
//
// return n
//}
//
//func (this *UserManager) transTo36(n uint64) string {
// var bs [8]byte
// var i = 7
// for ; n > 0; n, i = n/36, i-1 {
// bs[i] = chs[n%36]
// }
//
// for ; i >= 0; i-- {
// bs[i] = chs[0]
// }
//
// return string(bs[:])
//}
//
//func (this *UserManager) GenerateCdkey(channel uint32, count uint32, validDays int64, itemId []uint32, itemNum []uint32) ([]*Cdkey, error) {
// var counter, err = this.mongoClient.Counter("cdkey_id", uint64(count))
// if err != nil {
// this.logger.Error("Get counter error, ", err)
// return nil, proto.RawErrInternalError
// }
//
// var expiration = int64(0)
// if validDays > 0 {
// expiration = util.TodayBeginTime() + util.DayTotalSeconds*validDays
// }
//
// var list []*Cdkey
// for i := uint64(0); i < uint64(count); i++ {
// var key = this.transTo36(this.transBits(counter + i))
// var cdkey = &Cdkey{
// Key: key,
// Channel: channel,
// Expiration: expiration,
// ItemId: itemId,
// ItemNum: itemNum,
// }
//
// list = append(list, cdkey)
// }
//
// _, err = this.mongoClient.Collection(TableCdkey).InsertMany(this.mongoClient.Context(), util.SliceConvert(list, func(cdkey *Cdkey) any {
// return cdkey
// }))
//
// return list, nil
//}
//
//func (this *UserManager) DeleteCdkey(keys []string) error {
// _, err := this.mongoClient.Collection(TableCdkey).DeleteMany(this.mongoClient.Context(), bson.M{"_id": bson.M{"$in": keys}})
// return err
//}