feat: 优化CDK服务器冠名逻辑与鉴权
Some checks failed
ci/woodpecker/push/my-first-workflow Pipeline failed

This commit is contained in:
xinian
2026-04-08 19:31:44 +08:00
parent 28b6386963
commit 3b35789b47
5 changed files with 248 additions and 184 deletions

View File

@@ -1,121 +1,123 @@
package coolconfig package coolconfig
import ( import (
"time" "time"
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gconv"
) )
// cool config // cool config
type sConfig struct { type sConfig struct {
AutoMigrate bool `json:"auto_migrate,omitempty"` // 是否自动创建表 AutoMigrate bool `json:"auto_migrate,omitempty"` // 是否自动创建表
Eps bool `json:"eps,omitempty"` // 是否开启eps Eps bool `json:"eps,omitempty"` // 是否开启eps
File *file `json:"file,omitempty"` // 文件上传配置 File *file `json:"file,omitempty"` // 文件上传配置
Name string `json:"name"` // 项目名称 Name string `json:"name"` // 项目名称
// LoginPort string `json:"port"` // LoginPort string `json:"port"`
GameOnlineID uint32 `json:"port_bl"` //这个是命令行输入的参数 GameOnlineID uint32 `json:"port_bl"` //这个是命令行输入的参数
ServerInfo ServerList ServerInfo ServerList
Address string //rpc端口 Address string //rpc端口
} }
type ServerList struct { type ServerList struct {
OnlineID uint32 `gorm:"column:online_id;comment:'在线ID';uniqueIndex" json:"online_id"` OnlineID uint32 `gorm:"column:online_id;comment:'在线ID';uniqueIndex" json:"online_id"`
//服务器名称Desc //服务器名称Desc
Name string `gorm:"comment:'服务器名称'" json:"name"` Name string `gorm:"comment:'服务器名称'" json:"name"`
IP string `gorm:"type:string;comment:'服务器IP'" json:"ip"` IP string `gorm:"type:string;comment:'服务器IP'" json:"ip"`
Port uint32 `gorm:"comment:'端口号,通常是小整数'" json:"port"` Port uint32 `gorm:"comment:'端口号,通常是小整数'" json:"port"`
IsOpen uint8 `gorm:"default:0;not null;comment:'是否开启'" json:"is_open"` IsOpen uint8 `gorm:"default:0;not null;comment:'是否开启'" json:"is_open"`
//登录地址 //登录地址
LoginAddr string `gorm:"type:string;comment:'登录地址'" json:"login_addr"` LoginAddr string `gorm:"type:string;comment:'登录地址'" json:"login_addr"`
//账号 //账号
Account string `gorm:"type:string;comment:'账号'" json:"account"` Account string `gorm:"type:string;comment:'账号'" json:"account"`
//密码 //密码
Password string `gorm:"type:string;comment:'密码'" json:"password"` Password string `gorm:"type:string;comment:'密码'" json:"password"`
CanPort []uint32 `gorm:"type:jsonb;comment:'可连接端口'" json:"can_port"` CanPort []uint32 `gorm:"type:jsonb;comment:'可连接端口'" json:"can_port"`
//是否测试服 //是否测试服
IsVip uint32 `gorm:"default:0;not null;comment:'是否为VIP服务器'" json:"is_vip"` IsVip uint32 `gorm:"default:0;not null;comment:'是否为VIP服务器'" json:"is_vip"`
//isdebug 是否本地服 //isdebug 是否本地服
IsDebug uint8 `gorm:"default:0;comment:'是否为调试模式'" json:"is_debug"` IsDebug uint8 `gorm:"default:0;comment:'是否为调试模式'" json:"is_debug"`
//服务器属主Desc //服务器属主Desc
Owner uint32 `gorm:"comment:'服务器属主'" json:"owner"` Owner uint32 `gorm:"comment:'服务器属主'" json:"owner"`
Desc string `gorm:"comment:'服务器描述'" json:"desc"` Desc string `gorm:"comment:'服务器描述'" json:"desc"`
OldScreen string `gorm:"comment:'服务器screen参数'" json:"old_screen"` OldScreen string `gorm:"comment:'服务器screen参数'" json:"old_screen"`
//到期时间ServerList //到期时间ServerList
ExpireTime time.Time `gorm:"default:0;comment:'到期时间'" json:"expire_time"` ExpireTime time.Time `gorm:"default:0;comment:'到期时间'" json:"expire_time"`
} //CDK冠名到期时间ServerList
CDKExpireTime time.Time `gorm:"column:cdk_expire_time;default:0;comment:'CDK冠名到期时间'" json:"cdk_expire_time"`
func (s *ServerList) GetID() string { }
return gconv.String(100000*s.OnlineID + s.Port)
} func (s *ServerList) GetID() string {
return gconv.String(100000*s.OnlineID + s.Port)
// OSS相关配置 }
type oss struct {
Endpoint string `json:"endpoint"` // OSS相关配置
AccessKeyID string `json:"accessKeyID"` type oss struct {
SecretAccessKey string `json:"secretAccessKey"` Endpoint string `json:"endpoint"`
UseSSL bool `json:"useSSL"` AccessKeyID string `json:"accessKeyID"`
BucketName string `json:"bucketName"` SecretAccessKey string `json:"secretAccessKey"`
Location string `json:"location"` UseSSL bool `json:"useSSL"`
} BucketName string `json:"bucketName"`
Location string `json:"location"`
// 文件上传配置 }
type file struct {
Mode string `json:"mode"` // 模式 local oss // 文件上传配置
Domain string `json:"domain"` // 域名 http:// type file struct {
Oss *oss `json:"oss,omitempty"` Mode string `json:"mode"` // 模式 local oss
} Domain string `json:"domain"` // 域名 http://
Oss *oss `json:"oss,omitempty"`
// NewConfig new config }
func newConfig() *sConfig {
var ctx g.Ctx // NewConfig new config
config := &sConfig{ func newConfig() *sConfig {
AutoMigrate: GetCfgWithDefault(ctx, "blazing.autoMigrate", g.NewVar(false)).Bool(), var ctx g.Ctx
Name: GetCfgWithDefault(ctx, "server.name", g.NewVar("")).String(), config := &sConfig{
AutoMigrate: GetCfgWithDefault(ctx, "blazing.autoMigrate", g.NewVar(false)).Bool(),
Eps: GetCfgWithDefault(ctx, "blazing.eps", g.NewVar(false)).Bool(), Name: GetCfgWithDefault(ctx, "server.name", g.NewVar("")).String(),
// LoginPort: string(GetCfgWithDefault(ctx, "server.port", g.NewVar("8080")).String()),
Address: GetCfgWithDefault(ctx, "server.address", g.NewVar("8080")).String(), Eps: GetCfgWithDefault(ctx, "blazing.eps", g.NewVar(false)).Bool(),
//GamePort: GetCfgWithDefault(ctx, "server.game", g.NewVar("8080")).Uint64s(), // LoginPort: string(GetCfgWithDefault(ctx, "server.port", g.NewVar("8080")).String()),
Address: GetCfgWithDefault(ctx, "server.address", g.NewVar("8080")).String(),
File: &file{ //GamePort: GetCfgWithDefault(ctx, "server.game", g.NewVar("8080")).Uint64s(),
Mode: GetCfgWithDefault(ctx, "blazing.file.mode", g.NewVar("none")).String(),
Domain: GetCfgWithDefault(ctx, "blazing.file.domain", g.NewVar("http://127.0.0.1:8300")).String(), File: &file{
Oss: &oss{ Mode: GetCfgWithDefault(ctx, "blazing.file.mode", g.NewVar("none")).String(),
Endpoint: GetCfgWithDefault(ctx, "blazing.file.oss.endpoint", g.NewVar("127.0.0.1:9000")).String(), Domain: GetCfgWithDefault(ctx, "blazing.file.domain", g.NewVar("http://127.0.0.1:8300")).String(),
AccessKeyID: GetCfgWithDefault(ctx, "blazing.file.oss.accessKeyID", g.NewVar("")).String(), Oss: &oss{
SecretAccessKey: GetCfgWithDefault(ctx, "blazing.file.oss.secretAccessKey", g.NewVar("")).String(), Endpoint: GetCfgWithDefault(ctx, "blazing.file.oss.endpoint", g.NewVar("127.0.0.1:9000")).String(),
UseSSL: GetCfgWithDefault(ctx, "blazing.file.oss.useSSL", g.NewVar(false)).Bool(), AccessKeyID: GetCfgWithDefault(ctx, "blazing.file.oss.accessKeyID", g.NewVar("")).String(),
BucketName: GetCfgWithDefault(ctx, "blazing.file.oss.bucketName", g.NewVar("blazing")).String(), SecretAccessKey: GetCfgWithDefault(ctx, "blazing.file.oss.secretAccessKey", g.NewVar("")).String(),
Location: GetCfgWithDefault(ctx, "blazing.file.oss.location", g.NewVar("us-east-1")).String(), UseSSL: GetCfgWithDefault(ctx, "blazing.file.oss.useSSL", g.NewVar(false)).Bool(),
}, BucketName: GetCfgWithDefault(ctx, "blazing.file.oss.bucketName", g.NewVar("blazing")).String(),
}, Location: GetCfgWithDefault(ctx, "blazing.file.oss.location", g.NewVar("us-east-1")).String(),
} },
},
return config }
}
return config
// qiniu 七牛云配置 }
type qiniu struct {
AccessKey string `json:"ak"` // qiniu 七牛云配置
SecretKey string `json:"sk"` type qiniu struct {
Bucket string `json:"bucket"` AccessKey string `json:"ak"`
CDN string `json:"cdn"` SecretKey string `json:"sk"`
} Bucket string `json:"bucket"`
CDN string `json:"cdn"`
// Config config }
var Config = newConfig()
// Config config
// GetCfgWithDefault get config with default value var Config = newConfig()
func GetCfgWithDefault(ctx g.Ctx, key string, defaultValue *g.Var) *g.Var {
value, err := g.Cfg().GetWithEnv(ctx, key) // GetCfgWithDefault get config with default value
if err != nil { func GetCfgWithDefault(ctx g.Ctx, key string, defaultValue *g.Var) *g.Var {
return defaultValue value, err := g.Cfg().GetWithEnv(ctx, key)
} if err != nil {
if value.IsEmpty() || value.IsNil() { return defaultValue
return defaultValue }
} if value.IsEmpty() || value.IsNil() {
return value return defaultValue
} }
return value
}

View File

@@ -1,56 +1,92 @@
package controller package controller
import "blazing/logic/service/common" import (
"blazing/cool"
"blazing/logic/service/common"
"blazing/modules/player/model"
"context"
"encoding/hex"
"fmt"
"hash/crc32"
)
type Login struct { // MAIN_LOGIN_IN 定义请求或响应数据结构。
type MAIN_LOGIN_IN struct {
Head common.TomeeHeader `cmd:"1001" struc:"skip"` Head common.TomeeHeader `cmd:"1001" struc:"skip"`
Sid []byte `struc:"[16]byte"` Sid []byte `struc:"[16]byte"`
} }
type HeartBeat struct { // CheakSession 校验登录session。
Head common.TomeeHeader `cmd:"2051" struc:"skip"` func (l *MAIN_LOGIN_IN) CheakSession() (bool, uint32) {
Time uint32 t1 := hex.EncodeToString(l.Sid)
r, err := cool.CacheManager.Get(context.Background(), fmt.Sprintf("session:%d", l.Head.UserID))
if err != nil {
return false, 0
}
if r.String() != t1 {
return false, 0
}
crc32Table := crc32.MakeTable(crc32.IEEE)
crcValue := crc32.Checksum([]byte(l.Sid), crc32Table)
cool.CacheManager.Remove(context.Background(), fmt.Sprintf("session:%d", l.Head.UserID))
return true, crcValue
} }
type KeepAlive struct { // SimUserInfoInboundInfo 定义请求或响应数据结构。
Head common.TomeeHeader `cmd:"2052" struc:"skip"` type SimUserInfoInboundInfo struct {
Time uint32 Head common.TomeeHeader `cmd:"2051" struc:"skip"`
UserId uint32 `fieldDescription:"米米号" uint:"true" codec:"true"`
} }
type UserInfo struct { // MoreUserInfoInboundInfo 定义请求或响应数据结构。
type MoreUserInfoInboundInfo struct {
Head common.TomeeHeader `cmd:"2052" struc:"skip"`
UserId uint32 `fieldDescription:"米米号" uint:"true" codec:"true"`
}
// AimatInboundInfo 定义请求或响应数据结构。
type AimatInboundInfo struct {
Head common.TomeeHeader `cmd:"2104" struc:"skip"` Head common.TomeeHeader `cmd:"2104" struc:"skip"`
UserID uint32 ItemId uint32 `description:"物品id 射击激光 物品id为0" codec:"auto" uint:"true"`
ShowNono uint8 ShootType uint32 `description:"射击类型 未知 给0" codec:"auto" uint:"true"`
RoomStyle uint32 Point model.Pos `description:"射击的坐标 x y" codec:"auto"`
} }
type UserTalk struct { // ChatInboundInfo 定义请求或响应数据结构。
type ChatInboundInfo struct {
Head common.TomeeHeader `cmd:"2102" struc:"skip"` Head common.TomeeHeader `cmd:"2102" struc:"skip"`
ReceiverID uint32 Reserve uint32 `json:"reserve" fieldDescription:"填充 默认值为0" uint:"true"`
MessageLen uint32 `struc:"sizeof=Message"` MessageLen uint32 `struc:"sizeof=Message"`
Message []byte Message string `json:"message" fieldDescription:"消息内容, 结束符为utf-8的数字0"`
} }
type ChangeTitle struct { // ChangeColorInboundInfo 定义请求或响应数据结构。
type ChangeColorInboundInfo struct {
Head common.TomeeHeader `cmd:"2063" struc:"skip"` Head common.TomeeHeader `cmd:"2063" struc:"skip"`
Title uint32 Color uint32 `codec:"color"`
} }
type ChangePlayerIcon struct { // ChangeDoodleInboundInfo 定义请求或响应数据结构。
Head common.TomeeHeader `cmd:"2062" struc:"skip"` type ChangeDoodleInboundInfo struct {
Icon uint32 Head common.TomeeHeader `cmd:"2062" struc:"skip"`
Id uint32 `codec:"id"`
Color uint32 `codec:"color"`
} }
type GetMotto struct { // ChangeNONOColorInboundInfo 定义请求或响应数据结构。
Head common.TomeeHeader `cmd:"9012" struc:"skip"` type ChangeNONOColorInboundInfo struct {
Head common.TomeeHeader `cmd:"9012" struc:"skip"`
Color uint32 `codec:"color"`
} }
type GetTask struct { // C2SDanceAction 定义请求或响应数据结构。
Head common.TomeeHeader `cmd:"2103" struc:"skip"` type C2SDanceAction struct {
TaskLen uint32 `struc:"sizeof=TaskList"` Head common.TomeeHeader `cmd:"2103" struc:"skip"`
TaskList []uint32 Reserve uint32 `struc:"uint32,big"`
Type uint32 `struc:"uint32,big"`
} }
// C2SPEOPLE_TRANSFROM 定义请求或响应数据结构。
type C2SPEOPLE_TRANSFROM struct { type C2SPEOPLE_TRANSFROM struct {
Head common.TomeeHeader `cmd:"2111" struc:"skip"` Head common.TomeeHeader `cmd:"2111" struc:"skip"`
SuitID uint32 `struc:"uint32,big"` SuitID uint32 `struc:"uint32,big"`

View File

@@ -160,7 +160,16 @@ func (s *CdkService) Set(id string) bool {
return true return true
} }
func (s *CdkService) UseServerNamingCDK(ctx context.Context, code string, ownerID, serverID uint32, serverName string) (*model.ServerList, error) { type ServerNamingCDKResult struct {
ServerID uint32
ServerName string
OwnerID uint32
ServerExpireTime time.Time
CDKExpireTime time.Time
}
// UseServerNamingCDK 使用服务器冠名类型CDK并原子化更新服务器归属和到期时间。
func (s *CdkService) UseServerNamingCDK(ctx context.Context, code string, ownerID, serverID uint32, serverName string) (*ServerNamingCDKResult, error) {
if ctx == nil { if ctx == nil {
ctx = context.TODO() ctx = context.TODO()
} }
@@ -190,7 +199,10 @@ func (s *CdkService) UseServerNamingCDK(ctx context.Context, code string, ownerI
if err := tx.Model(model.NewServerList()).Where("online_id", serverID).Scan(&server); err != nil { if err := tx.Model(model.NewServerList()).Where("online_id", serverID).Scan(&server); err != nil {
return err return err
} }
if !serverService.CanUseDonationName(server, now) { if server.OnlineID == 0 {
return gerror.New("服务器不存在")
}
if server.Owner != ownerID && !serverService.CanUseDonationName(server, now) {
return gerror.New("服务器不可冠名") return gerror.New("服务器不可冠名")
} }
@@ -203,19 +215,23 @@ func (s *CdkService) UseServerNamingCDK(ctx context.Context, code string, ownerI
return gerror.New("cdk已被使用") return gerror.New("cdk已被使用")
} }
baseTime := now
if server.ExpireTime.After(now) {
baseTime = server.ExpireTime
}
updated = server updated = server
updated.Name = serverName updated.Name = serverName
updated.Owner = ownerID updated.Owner = ownerID
updated.ExpireTime = baseTime.AddDate(0, 1, 0) if server.Owner != ownerID {
updated.CDKExpireTime = now.AddDate(0, 1, 0)
} else {
baseTime := server.CDKExpireTime
if baseTime.IsZero() {
baseTime = now
}
updated.CDKExpireTime = baseTime.AddDate(0, 1, 0)
}
_, err = tx.Model(model.NewServerList()).Where("online_id", serverID).Data(g.Map{ _, err = tx.Model(model.NewServerList()).Where("online_id", serverID).Data(g.Map{
"name": updated.Name, "name": updated.Name,
"owner": updated.Owner, "owner": updated.Owner,
"expire_time": updated.ExpireTime, "cdk_expire_time": updated.CDKExpireTime,
}).Update() }).Update()
return err return err
}) })
@@ -225,7 +241,13 @@ func (s *CdkService) UseServerNamingCDK(ctx context.Context, code string, ownerI
g.DB(s.Model.GroupName()).GetCore().ClearCache(context.TODO(), s.Model.TableName()) g.DB(s.Model.GroupName()).GetCore().ClearCache(context.TODO(), s.Model.TableName())
g.DB(model.NewServerList().GroupName()).GetCore().ClearCache(context.TODO(), model.NewServerList().TableName()) g.DB(model.NewServerList().GroupName()).GetCore().ClearCache(context.TODO(), model.NewServerList().TableName())
return &updated, nil return &ServerNamingCDKResult{
ServerID: updated.OnlineID,
ServerName: updated.Name,
OwnerID: updated.Owner,
ServerExpireTime: updated.ExpireTime,
CDKExpireTime: updated.CDKExpireTime,
}, nil
} }
func (s *CdkService) BatchGenerate(ctx context.Context, count int) (interface{}, error) { func (s *CdkService) BatchGenerate(ctx context.Context, count int) (interface{}, error) {

View File

@@ -131,9 +131,10 @@ func (s *ServerService) GetServerID(OnlineID uint32) model.ServerList {
} }
// GetDonationAvailableServerIDs 返回当前可被冠名占用的服务器ID列表。
func (s *ServerService) GetDonationAvailableServerIDs() []uint32 { func (s *ServerService) GetDonationAvailableServerIDs() []uint32 {
now := time.Now() now := time.Now()
builder := dbm_nocache_noenable(s.Model).Builder().Where("owner", 0).WhereOr("expire_time <= ?", now) builder := dbm_nocache_noenable(s.Model).Builder().Where("owner", 0).WhereOr("cdk_expire_time <= ?", now)
var rows []struct { var rows []struct {
OnlineID uint32 `json:"online_id"` OnlineID uint32 `json:"online_id"`
@@ -150,6 +151,7 @@ func (s *ServerService) GetDonationAvailableServerIDs() []uint32 {
return ids return ids
} }
// CanUseDonationName 校验目标服务器在当前时间点是否允许被冠名。
func (s *ServerService) CanUseDonationName(server model.ServerList, now time.Time) bool { func (s *ServerService) CanUseDonationName(server model.ServerList, now time.Time) bool {
if server.OnlineID == 0 { if server.OnlineID == 0 {
return false return false
@@ -157,7 +159,7 @@ func (s *ServerService) CanUseDonationName(server model.ServerList, now time.Tim
if server.Owner == 0 { if server.Owner == 0 {
return true return true
} }
return !server.ExpireTime.After(now) return !server.CDKExpireTime.After(now)
} }
// 保存版本号 // 保存版本号

View File

@@ -15,6 +15,7 @@ type CdkController struct {
*cool.Controller *cool.Controller
} }
// init 注册用户态CDK相关Web接口。
func init() { func init() {
controller := &CdkController{ controller := &CdkController{
&cool.Controller{ &cool.Controller{
@@ -27,33 +28,29 @@ func init() {
} }
type DonationServerListReq struct { type DonationServerListReq struct {
g.Meta `path:"/donation/serverIds" method:"GET"` g.Meta `path:"/donation/serverIds" method:"GET"`
UserID uint32 `json:"user_id" v:"required|min:1#用户ID不能为空|用户ID非法"`
Session string `json:"session" v:"required#session不能为空"`
} }
type DonationRedeemReq struct { type DonationRedeemReq struct {
g.Meta `path:"/donation/redeem" method:"POST"` g.Meta `path:"/donation/redeem" method:"POST"`
UserID uint32 `json:"user_id" v:"required|min:1#用户ID不能为空|用户ID非法"`
Session string `json:"session" v:"required#session不能为空"`
CDKCode string `json:"cdk_code" v:"required#CDK不能为空"` CDKCode string `json:"cdk_code" v:"required#CDK不能为空"`
ServerID uint32 `json:"server_id" v:"required|min:1#服务器ID不能为空|服务器ID非法"` ServerID uint32 `json:"server_id" v:"required|min:1#服务器ID不能为空|服务器ID非法"`
ServerName string `json:"server_name" v:"required#服务器名称不能为空"` ServerName string `json:"server_name" v:"required#服务器名称不能为空"`
} }
type DonationRedeemRes struct { type DonationRedeemRes struct {
ServerID uint32 `json:"server_id"` ServerID uint32 `json:"server_id"`
ServerName string `json:"server_name"` ServerName string `json:"server_name"`
OwnerID uint32 `json:"owner_id"` OwnerID uint32 `json:"owner_id"`
ExpireTime time.Time `json:"expire_time"` ServerExpireTime time.Time `json:"server_expire_time"`
CDKExpireTime time.Time `json:"cdk_expire_time"`
} }
// DonationServerIDs 查询当前可用于服务器绑定CDK的服务器ID列表。
func (c *CdkController) DonationServerIDs(ctx context.Context, req *DonationServerListReq) (res *cool.BaseRes, err error) { func (c *CdkController) DonationServerIDs(ctx context.Context, req *DonationServerListReq) (res *cool.BaseRes, err error) {
if err = g.Validator().Data(req).Run(ctx); err != nil { admin := cool.GetAdmin(ctx)
return cool.Fail(err.Error()), nil if admin == nil || admin.UserId == 0 {
} return cool.Fail("未登录或登录已失效"), nil
if err = validateGameSession(req.UserID, req.Session); err != nil {
return cool.Fail(err.Error()), nil
} }
return cool.Ok(g.Map{ return cool.Ok(g.Map{
@@ -61,13 +58,17 @@ func (c *CdkController) DonationServerIDs(ctx context.Context, req *DonationServ
}), nil }), nil
} }
// DonationRedeem 兑换服务器绑定类型CDK并完成冠名写入。
func (c *CdkController) DonationRedeem(ctx context.Context, req *DonationRedeemReq) (res *cool.BaseRes, err error) { func (c *CdkController) DonationRedeem(ctx context.Context, req *DonationRedeemReq) (res *cool.BaseRes, err error) {
if err = g.Validator().Data(req).Run(ctx); err != nil { if err = g.Validator().Data(req).Run(ctx); err != nil {
return cool.Fail(err.Error()), nil return cool.Fail(err.Error()), nil
} }
if err = validateGameSession(req.UserID, req.Session); err != nil {
return cool.Fail(err.Error()), nil admin := cool.GetAdmin(ctx)
if admin == nil || admin.UserId == 0 {
return cool.Fail("未登录或登录已失效"), nil
} }
ownerID := uint32(admin.UserId)
cdkCode := strings.TrimSpace(req.CDKCode) cdkCode := strings.TrimSpace(req.CDKCode)
if cdkCode == "" { if cdkCode == "" {
@@ -88,28 +89,29 @@ func (c *CdkController) DonationRedeem(ctx context.Context, req *DonationRedeemR
if cdkInfo.CDKType != configservice.CDKTypeServerNaming { if cdkInfo.CDKType != configservice.CDKTypeServerNaming {
return cool.Fail("CDK类型不匹配"), nil return cool.Fail("CDK类型不匹配"), nil
} }
if cdkInfo.BindUserId != 0 && cdkInfo.BindUserId != req.UserID { if cdkInfo.BindUserId != 0 && cdkInfo.BindUserId != ownerID {
return cool.Fail("CDK已绑定其他用户"), nil return cool.Fail("CDK已绑定其他用户"), nil
} }
if !cdkInfo.ValidEndTime.IsZero() && cdkInfo.ValidEndTime.Before(time.Now()) { if !cdkInfo.ValidEndTime.IsZero() && cdkInfo.ValidEndTime.Before(time.Now()) {
return cool.Fail("CDK已过期"), nil return cool.Fail("CDK已过期"), nil
} }
playerCdkService := playerservice.NewCdkService(req.UserID) playerCdkService := playerservice.NewCdkService(ownerID)
if !playerCdkService.CanGet(uint32(cdkInfo.ID)) { if !playerCdkService.CanGet(uint32(cdkInfo.ID)) {
return cool.Fail("CDK已领取"), nil return cool.Fail("CDK已领取"), nil
} }
serverInfo, useErr := cdkService.UseServerNamingCDK(ctx, cdkCode, req.UserID, req.ServerID, serverName) serverInfo, useErr := cdkService.UseServerNamingCDK(ctx, cdkCode, ownerID, req.ServerID, serverName)
if useErr != nil { if useErr != nil {
return cool.Fail(useErr.Error()), nil return cool.Fail(useErr.Error()), nil
} }
playerCdkService.Log(uint32(cdkInfo.ID)) playerCdkService.Log(uint32(cdkInfo.ID))
return cool.Ok(&DonationRedeemRes{ return cool.Ok(&DonationRedeemRes{
ServerID: serverInfo.OnlineID, ServerID: serverInfo.ServerID,
ServerName: serverInfo.Name, ServerName: serverInfo.ServerName,
OwnerID: serverInfo.Owner, OwnerID: serverInfo.OwnerID,
ExpireTime: serverInfo.ExpireTime, ServerExpireTime: serverInfo.ServerExpireTime,
CDKExpireTime: serverInfo.CDKExpireTime,
}), nil }), nil
} }