package gamemanagement import ( "strings" "time" "hyapp-admin-server/internal/appctx" "hyapp-admin-server/internal/middleware" gamev1 "hyapp.local/api/proto/game/v1" "github.com/gin-gonic/gin" ) type platformRequest struct { PlatformCode string `json:"platformCode"` PlatformName string `json:"platformName"` Status string `json:"status"` APIBaseURL string `json:"apiBaseUrl"` // AdapterType 只允许服务端白名单中的值,避免后台误填导致回调走错协议。 AdapterType string `json:"adapterType"` // CallbackSecret 只有提交非空时才覆盖旧密钥,编辑其它字段时前端传空即可。 CallbackSecret string `json:"callbackSecret"` CallbackIPWhitelist []string `json:"callbackIpWhitelist"` // AdapterConfigJSON 是厂商扩展配置,保持 JSON 字符串透传给 game-service。 AdapterConfigJSON string `json:"adapterConfigJson"` SortOrder int32 `json:"sortOrder"` } type catalogRequest struct { GameID string `json:"gameId"` PlatformCode string `json:"platformCode"` ProviderGameID string `json:"providerGameId"` GameName string `json:"gameName"` Category string `json:"category"` IconURL string `json:"iconUrl"` CoverURL string `json:"coverUrl"` LaunchMode string `json:"launchMode"` Orientation string `json:"orientation"` SafeHeight int32 `json:"safeHeight"` MinCoin int64 `json:"minCoin"` Status string `json:"status"` SortOrder int32 `json:"sortOrder"` Tags []string `json:"tags"` } type statusRequest struct { Status string `json:"status"` } type diceConfigRequest struct { Status string `json:"status"` StakeOptions []diceStakeReq `json:"stakeOptions"` FeeBPS int32 `json:"feeBps"` PoolBPS int32 `json:"poolBps"` MinPlayers int32 `json:"minPlayers"` MaxPlayers int32 `json:"maxPlayers"` RobotEnabled bool `json:"robotEnabled"` RobotMatchWaitMS int64 `json:"robotMatchWaitMs"` } type diceStakeReq struct { StakeCoin int64 `json:"stakeCoin"` Enabled bool `json:"enabled"` SortOrder int32 `json:"sortOrder"` } type dicePoolAdjustRequest struct { AmountCoin int64 `json:"amountCoin"` Direction string `json:"direction"` Reason string `json:"reason"` } type diceGenerateRobotsRequest struct { Count int32 `json:"count"` NicknamePrefix string `json:"nicknamePrefix"` NicknameLanguage string `json:"nicknameLanguage"` AvatarURLs []string `json:"avatarUrls"` Country string `json:"country"` Gender string `json:"gender"` } type diceRobotStatusRequest struct { Status string `json:"status"` } func (r platformRequest) toProto(platformCode string) *gamev1.GamePlatform { if platformCode == "" { platformCode = r.PlatformCode } return &gamev1.GamePlatform{ PlatformCode: strings.TrimSpace(platformCode), PlatformName: strings.TrimSpace(r.PlatformName), Status: strings.TrimSpace(r.Status), ApiBaseUrl: strings.TrimSpace(r.APIBaseURL), AdapterType: strings.TrimSpace(r.AdapterType), CallbackSecret: strings.TrimSpace(r.CallbackSecret), CallbackIpWhitelist: compactTags(r.CallbackIPWhitelist), AdapterConfigJson: strings.TrimSpace(r.AdapterConfigJSON), SortOrder: r.SortOrder, } } func (r catalogRequest) toProto(gameID string) *gamev1.GameCatalogItem { if gameID == "" { gameID = r.GameID } return &gamev1.GameCatalogItem{ GameId: strings.TrimSpace(gameID), PlatformCode: strings.TrimSpace(r.PlatformCode), ProviderGameId: strings.TrimSpace(r.ProviderGameID), GameName: strings.TrimSpace(r.GameName), Category: strings.TrimSpace(r.Category), IconUrl: strings.TrimSpace(r.IconURL), CoverUrl: strings.TrimSpace(r.CoverURL), LaunchMode: strings.TrimSpace(r.LaunchMode), Orientation: strings.TrimSpace(r.Orientation), SafeHeight: r.SafeHeight, MinCoin: r.MinCoin, Status: strings.TrimSpace(r.Status), SortOrder: r.SortOrder, Tags: compactTags(r.Tags), } } func (r diceConfigRequest) toProto(gameID string) *gamev1.DiceConfig { options := make([]*gamev1.DiceStakeOption, 0, len(r.StakeOptions)) for _, option := range r.StakeOptions { options = append(options, &gamev1.DiceStakeOption{ StakeCoin: option.StakeCoin, Enabled: option.Enabled, SortOrder: option.SortOrder, }) } return &gamev1.DiceConfig{ GameId: strings.TrimSpace(gameID), Status: strings.TrimSpace(r.Status), StakeOptions: options, FeeBps: r.FeeBPS, PoolBps: r.PoolBPS, MinPlayers: r.MinPlayers, MaxPlayers: r.MaxPlayers, RobotEnabled: r.RobotEnabled, RobotMatchWaitMs: r.RobotMatchWaitMS, } } func compactTags(tags []string) []string { out := make([]string, 0, len(tags)) seen := make(map[string]struct{}, len(tags)) for _, tag := range tags { value := strings.TrimSpace(tag) if value == "" { continue } if _, ok := seen[value]; ok { continue } seen[value] = struct{}{} out = append(out, value) } return out } func requestMeta(c *gin.Context) *gamev1.RequestMeta { return &gamev1.RequestMeta{ RequestId: middleware.CurrentRequestID(c), Caller: "admin-server", ActorUserId: int64(middleware.CurrentUserID(c)), SentAtMs: time.Now().UnixMilli(), AppCode: appctx.FromContext(c.Request.Context()), } }