refactor: 重构服务器冠名逻辑至独立表
All checks were successful
ci/woodpecker/push/my-first-workflow Pipeline was successful

This commit is contained in:
xinian
2026-04-10 19:36:59 +08:00
parent ee3f25438f
commit 90f1447d48
9 changed files with 343 additions and 147 deletions

View File

@@ -1,39 +1,40 @@
package model
import (
"blazing/cool"
"blazing/cool/coolconfig"
)
const TableNameServerList = "server_list"
// 服务器设置天气地图|地图是否显示其他人,设置异色概率|ip
// ServerList mapped from table <server_list>
type ServerList struct {
*cool.Model
coolconfig.ServerList
//isonline
IsOnline uint8 `gorm:"column:isonline;default:0;comment:'是否在线'" json:"isonline"`
}
// TableName ServerList's table name
func (*ServerList) TableName() string {
return TableNameServerList
}
// GroupName ServerList's table group
func (*ServerList) GroupName() string {
return "default"
}
// NewServerList create a new ServerList
func NewServerList() *ServerList {
return &ServerList{
Model: cool.NewModel(),
}
}
// init 创建表
func init() {
cool.CreateTable(&ServerList{})
}
package model
import (
"blazing/cool"
"blazing/cool/coolconfig"
)
const TableNameServerList = "server_list"
// 服务器设置天气地图|地图是否显示其他人,设置异色概率|ip
// ServerList mapped from table <server_list>
type ServerList struct {
*cool.Model
coolconfig.ServerList
ServerShow *ServerShow `orm:"with:server_id=online_id" json:"server_show,omitempty"`
// isonline
IsOnline uint8 `gorm:"column:isonline;default:0;comment:'是否在线'" json:"isonline"`
}
// TableName ServerList's table name
func (*ServerList) TableName() string {
return TableNameServerList
}
// GroupName ServerList's table group
func (*ServerList) GroupName() string {
return "default"
}
// NewServerList create a new ServerList
func NewServerList() *ServerList {
return &ServerList{
Model: cool.NewModel(),
}
}
// init 创建表
func init() {
cool.CreateTable(&ServerList{})
}

View File

@@ -0,0 +1,39 @@
package model
import (
"blazing/cool"
"time"
)
const TableNameServerShow = "server_show"
// ServerShow 绑定服务器展示信息(冠名、属主、到期时间)。
type ServerShow struct {
*cool.Model
ServerID uint32 `gorm:"column:server_id;comment:'服务器ID';uniqueIndex" json:"server_id"`
Name string `gorm:"comment:'服务器展示名'" json:"name"`
Owner uint32 `gorm:"comment:'服务器属主'" json:"owner"`
ExpireTime time.Time `gorm:"column:expire_time;default:0;comment:'展示到期时间'" json:"expire_time"`
}
// TableName ServerShow's table name
func (*ServerShow) TableName() string {
return TableNameServerShow
}
// GroupName ServerShow's table group
func (*ServerShow) GroupName() string {
return "default"
}
// NewServerShow create a new ServerShow
func NewServerShow() *ServerShow {
return &ServerShow{
Model: cool.NewModel(),
}
}
// init 创建表
func init() {
cool.CreateTable(&ServerShow{})
}

View File

@@ -12,6 +12,7 @@ import (
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
"github.com/google/uuid"
)
@@ -165,7 +166,6 @@ type ServerNamingCDKResult struct {
ServerName string
OwnerID uint32
ServerExpireTime time.Time
CDKExpireTime time.Time
}
// UseServerNamingCDK 使用服务器冠名类型CDK并原子化更新服务器归属和到期时间。
@@ -175,7 +175,7 @@ func (s *CdkService) UseServerNamingCDK(ctx context.Context, code string, ownerI
}
now := time.Now()
serverService := NewServerService()
var updated model.ServerList
var updated model.ServerShow
err := g.DB(s.Model.GroupName()).Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
var cfg model.CDKConfig
@@ -196,13 +196,13 @@ func (s *CdkService) UseServerNamingCDK(ctx context.Context, code string, ownerI
}
var server model.ServerList
if err := tx.Model(model.NewServerList()).Where("online_id", serverID).Scan(&server); err != nil {
if err := tx.Model(model.NewServerList()).With(model.ServerShow{}).Where("online_id", serverID).Scan(&server); err != nil {
return err
}
if server.OnlineID == 0 {
return gerror.New("服务器不存在")
}
if server.Owner != ownerID && !serverService.CanUseDonationName(server, now) {
if !serverService.CanUseDonationName(server, ownerID, now) {
return gerror.New("服务器不可冠名")
}
@@ -215,23 +215,40 @@ func (s *CdkService) UseServerNamingCDK(ctx context.Context, code string, ownerI
return gerror.New("cdk已被使用")
}
updated = server
var currentShow model.ServerShow
if server.ServerShow != nil {
currentShow = *server.ServerShow
}
updated = currentShow
updated.ServerID = serverID
updated.Name = serverName
updated.Owner = ownerID
if server.Owner != ownerID {
updated.CDKExpireTime = now.AddDate(0, 1, 0)
if currentShow.ServerID == 0 || !serverService.isActiveServerShow(&currentShow, now) || currentShow.Owner != ownerID {
updated.ExpireTime = now.AddDate(0, 1, 0)
} else {
baseTime := server.CDKExpireTime
baseTime := currentShow.ExpireTime
if baseTime.IsZero() {
baseTime = now
}
updated.CDKExpireTime = baseTime.AddDate(0, 1, 0)
updated.ExpireTime = baseTime.AddDate(0, 1, 0)
}
_, err = tx.Model(model.NewServerList()).Where("online_id", serverID).Data(g.Map{
"name": updated.Name,
"owner": updated.Owner,
"cdk_expire_time": updated.CDKExpireTime,
if currentShow.ServerID == 0 {
_, err = tx.Model(model.NewServerShow()).Data(g.Map{
"server_id": updated.ServerID,
"name": updated.Name,
"owner": updated.Owner,
"expire_time": updated.ExpireTime,
}).Insert()
return err
}
_, err = tx.Model(model.NewServerShow()).Where("server_id", serverID).Data(g.Map{
"name": updated.Name,
"owner": updated.Owner,
"expire_time": updated.ExpireTime,
}).Update()
return err
})
@@ -241,12 +258,12 @@ func (s *CdkService) UseServerNamingCDK(ctx context.Context, code string, ownerI
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.NewServerShow().GroupName()).GetCore().ClearCache(context.TODO(), model.NewServerShow().TableName())
return &ServerNamingCDKResult{
ServerID: updated.OnlineID,
ServerID: updated.ServerID,
ServerName: updated.Name,
OwnerID: updated.Owner,
ServerExpireTime: updated.ExpireTime,
CDKExpireTime: updated.CDKExpireTime,
}, nil
}
@@ -263,6 +280,18 @@ func (s *CdkService) BatchGenerate(ctx context.Context, count int) (interface{},
delete(requestData, "cdk_code")
delete(requestData, "id")
cdkType := gconv.Uint32(requestData["type"])
if cdkType != CDKTypeReward && cdkType != CDKTypeServerNaming {
return nil, gerror.New("CDK类型非法")
}
requestData["type"] = cdkType
if cdkType == CDKTypeServerNaming {
requestData["exchange_remain_count"] = int64(1)
requestData["item_reward_ids"] = []uint32{}
requestData["elf_reward_ids"] = []uint32{}
requestData["title_reward_ids"] = uint32(0)
}
codes, err := s.generateAvailableCodes(count)
if err != nil {
return nil, err

View File

@@ -8,6 +8,7 @@ import (
"sort"
"time"
"github.com/gogf/gf/v2/container/gmap"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
@@ -21,45 +22,65 @@ type ServerService struct {
bucket string
}
type ServerShowInfo struct {
OnlineID uint32 `json:"online_id"`
Name string `json:"name"`
IP string `json:"ip"`
Port uint32 `json:"port"`
IsVip uint32 `json:"is_vip"`
IsDebug uint8 `json:"is_debug"`
IsOpen uint8 `json:"is_open"`
Owner uint32 `json:"owner"`
ExpireTime time.Time `json:"expire_time"`
ServerShow *model.ServerShow `json:"servershow,omitempty"`
}
func NewServerService() *ServerService {
cf := &ServerService{
Service: &cool.Service{
Model: model.NewServerList(),
PageQueryOp: &cool.QueryOp{
ModifyResult: func(ctx g.Ctx, data interface{}) interface{} {
var rr []g.MapStrAny
r, _ := gconv.Map(data)["list"].(gdb.Result)
for i := 0; i < len(r); i++ {
t, ok := cool.GetClient(gconv.Uint32(r[i].Map()["online_id"]), gconv.Uint32(r[i].Map()["port"]))
// tt.Friends = v.Friends
subm := r[i].GMap()
if ok {
err := t.KickPerson(0) //实现指定服务器踢人
if err == nil {
r, _ := utils.TcpPing(fmt.Sprintf("%s:%d", r[i].Map()["ip"], r[i].Map()["port"]))
subm.Set("isonline", r)
} else {
subm.Set("isonline", 0)
}
} else {
subm.Set("isonline", 0)
}
rr = append(rr, subm.MapStrAny())
}
data.(map[string]interface{})["list"] = rr
return data
},
},
},
}
cf.PageQueryOp = &cool.QueryOp{
ModifyResult: func(ctx g.Ctx, data interface{}) interface{} {
var rr []g.MapStrAny
r, _ := gconv.Map(data)["list"].(gdb.Result)
now := time.Now()
serverIDs := make([]uint32, 0, len(r))
for i := 0; i < len(r); i++ {
serverID := gconv.Uint32(r[i].Map()["online_id"])
if serverID == 0 {
continue
}
serverIDs = append(serverIDs, serverID)
}
showMap := cf.getActiveServerShowMap(serverIDs, now)
for i := 0; i < len(r); i++ {
t, ok := cool.GetClient(gconv.Uint32(r[i].Map()["online_id"]), gconv.Uint32(r[i].Map()["port"]))
subm := r[i].GMap()
cf.applyServerShowMap(subm, gconv.Uint32(r[i].Map()["online_id"]), showMap)
if ok {
err := t.KickPerson(0) //实现指定服务器踢人
if err == nil {
r, _ := utils.TcpPing(fmt.Sprintf("%s:%d", r[i].Map()["ip"], r[i].Map()["port"]))
subm.Set("isonline", r)
} else {
subm.Set("isonline", 0)
}
} else {
subm.Set("isonline", 0)
}
rr = append(rr, subm.MapStrAny())
}
data.(map[string]interface{})["list"] = rr
return data
},
}
cfg := storage.Config{
Zone: &storage.ZoneHuadong,
UseHTTPS: true,
@@ -67,107 +88,106 @@ func NewServerService() *ServerService {
}
mac := qbox.NewMac("DzMpomnPxqBHkIcvxTbC-hl_8LjVB0LXZuhCky_u", "bhoxrpG1s7MBmSS2I1k5t9zMpuiderpBDZoIPQKU")
cf.bucket = "blazingt"
cf.manager = storage.NewBucketManager(mac, &cfg)
return cf
}
func (s *ServerService) GetPort(DepartmentID uint) gdb.List {
var res gdb.Result
m := cool.DBM(s.Model).Where("is_open", 1).Fields("ip", "port", "online_id", "is_vip", "name")
if DepartmentID != 1 {
res, _ = m.All()
} else {
res, _ = m.Where("is_debug", 0).All()
func (s *ServerService) GetPort(DepartmentID uint) []ServerShowInfo {
servers := s.GetServer()
items := make([]ServerShowInfo, 0, len(servers))
for _, server := range servers {
if server.IsOpen != 1 {
continue
}
if DepartmentID == 1 && server.IsDebug != 0 {
continue
}
items = append(items, ServerShowInfo{
OnlineID: server.OnlineID,
Name: server.Name,
IP: server.IP,
Port: server.Port,
IsVip: server.IsVip,
IsDebug: server.IsDebug,
IsOpen: server.IsOpen,
Owner: server.Owner,
ExpireTime: server.ExpireTime,
ServerShow: server.ServerShow,
})
}
return res.List()
return items
}
func (s *ServerService) GetServer() []model.ServerList {
var item []model.ServerList
cool.DBM(s.Model).Scan(&item)
dbm_nocache_noenable(s.Model).With(model.ServerShow{}).Scan(&item)
s.applyServerShowList(item, time.Now())
return item
}
func (s *ServerService) StartUPdate(OnlineID uint16, isinstall int) model.ServerList {
m := cool.DBM(s.Model).Where("online_id", OnlineID)
var tttt model.ServerList
m.Scan(&tttt)
if isinstall == 1 {
tttt.IsOpen = uint8(0)
m.Save(tttt)
}
// s.CleanCache()
return tttt
}
func (s *ServerService) SetServerID(OnlineID uint32, Port uint32) error {
m := cool.DBM(s.Model).Where("online_id", OnlineID)
var tttt model.ServerList
m.Scan(&tttt)
tttt.Port = Port
tttt.OnlineID = OnlineID
tttt.IsOpen = 1
m.Save(tttt)
// s.CleanCache()
return nil
}
func (s *ServerService) GetServerID(OnlineID uint32) model.ServerList {
var tttt model.ServerList
cool.DBM(s.Model).Where("online_id", OnlineID).Scan(&tttt)
dbm_nocache_noenable(s.Model).With(model.ServerShow{}).Where("online_id", OnlineID).Scan(&tttt)
s.applyServerShow(&tttt, time.Now())
return tttt
}
// GetDonationAvailableServerIDs 返回当前可被冠名占用的服务器ID列表。
func (s *ServerService) GetDonationAvailableServerIDs() []uint32 {
servers := s.GetServer()
now := time.Now()
builder := dbm_nocache_noenable(s.Model).Builder().Where("owner", 0).WhereOr("cdk_expire_time <= ?", now)
var rows []struct {
OnlineID uint32 `json:"online_id"`
}
dbm_nocache_noenable(s.Model).Fields("online_id").Where(builder).OrderAsc("online_id").Scan(&rows)
ids := make([]uint32, 0, len(rows))
for _, row := range rows {
if row.OnlineID == 0 {
ids := make([]uint32, 0, len(servers))
for _, server := range servers {
if server.OnlineID == 0 {
continue
}
ids = append(ids, row.OnlineID)
if s.isActiveServerShow(server.ServerShow, now) {
continue
}
ids = append(ids, server.OnlineID)
}
sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] })
return ids
}
// CanUseDonationName 校验目标服务器在当前时间点是否允许被冠名。
func (s *ServerService) CanUseDonationName(server model.ServerList, now time.Time) bool {
func (s *ServerService) CanUseDonationName(server model.ServerList, ownerID uint32, now time.Time) bool {
if server.OnlineID == 0 {
return false
}
if server.Owner == 0 {
if !s.isActiveServerShow(server.ServerShow, now) {
return true
}
return !server.CDKExpireTime.After(now)
return server.ServerShow.Owner == ownerID
}
// 保存版本号
func (s *ServerService) SetServerScreen(id uint32, name string) {
cool.DBM(s.Model).Where("online_id", id).Data("old_screen", name).Update()
}
func (s *ServerService) GetFile() string {
var files []File
prefix := "logic"
@@ -178,7 +198,6 @@ func (s *ServerService) GetFile() string {
if err != nil {
return ""
}
// 添加文件到结果列表
for _, entry := range entries {
files = append(files, File{
Name: entry.Key,
@@ -187,22 +206,19 @@ func (s *ServerService) GetFile() string {
Time: entry.PutTime,
})
}
// 如果没有更多文件,结束循环
if !hasNext {
break
}
// 更新标记,继续下一页
marker = nextMarker
}
sort.Slice(files, func(i, j int) bool {
return files[i].Time > files[j].Time
})
if len(files) == 0 {
return ""
}
return files[0].Name
}
type File struct {
@@ -213,3 +229,74 @@ type File struct {
Modified string `json:"modified"`
Time int64 `json:"time"`
}
func (s *ServerService) isActiveServerShow(show *model.ServerShow, now time.Time) bool {
if show == nil {
return false
}
if show.ServerID == 0 || show.Owner == 0 {
return false
}
if show.ExpireTime.IsZero() {
return false
}
return show.ExpireTime.After(now)
}
func (s *ServerService) applyServerShowList(servers []model.ServerList, now time.Time) {
for i := range servers {
s.applyServerShow(&servers[i], now)
}
}
func (s *ServerService) applyServerShow(server *model.ServerList, now time.Time) {
if server == nil {
return
}
server.Owner = 0
server.ExpireTime = time.Time{}
if !s.isActiveServerShow(server.ServerShow, now) {
return
}
if server.ServerShow.Name != "" {
server.Name = server.ServerShow.Name
}
server.Owner = server.ServerShow.Owner
server.ExpireTime = server.ServerShow.ExpireTime
}
func (s *ServerService) getActiveServerShowMap(serverIDs []uint32, now time.Time) map[uint32]*model.ServerShow {
showMap := make(map[uint32]*model.ServerShow, len(serverIDs))
if len(serverIDs) == 0 {
return showMap
}
var shows []model.ServerShow
dbm_nocache_noenable(model.NewServerShow()).WhereIn("server_id", serverIDs).Scan(&shows)
for i := range shows {
show := &shows[i]
if !s.isActiveServerShow(show, now) {
continue
}
showMap[show.ServerID] = show
}
return showMap
}
func (s *ServerService) applyServerShowMap(serverMap *gmap.StrAnyMap, serverID uint32, showMap map[uint32]*model.ServerShow) {
if serverMap == nil {
return
}
serverMap.Set("owner", uint32(0))
serverMap.Set("expire_time", time.Time{})
show, ok := showMap[serverID]
if !ok {
return
}
if show.Name != "" {
serverMap.Set("name", show.Name)
}
serverMap.Set("owner", show.Owner)
serverMap.Set("expire_time", show.ExpireTime)
serverMap.Set("servershow", show)
return
}