863 lines
26 KiB
Go
863 lines
26 KiB
Go
package baishun
|
|
|
|
import (
|
|
"chatapp3-golang/internal/model"
|
|
"chatapp3-golang/internal/utils"
|
|
"context"
|
|
"fmt"
|
|
"net/http"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
)
|
|
|
|
const adminTimeLayout = "2006-01-02 15:04:05"
|
|
const baishunRoomCategory = "CHAT_ROOM"
|
|
|
|
type adminGameRow struct {
|
|
ID int64
|
|
SysOrigin string
|
|
Profile string
|
|
InternalGameID string
|
|
Name string
|
|
Category string
|
|
GameCode string
|
|
Cover string
|
|
Amounts string
|
|
Showcase bool
|
|
Sort int64
|
|
Height float64
|
|
Width float64
|
|
FullScreen bool
|
|
ClientOrigin string
|
|
Regions string
|
|
GameModeRaw string
|
|
CreateTime time.Time
|
|
UpdateTime time.Time
|
|
VendorGameID string
|
|
LaunchMode string
|
|
ExtPackageVersion string
|
|
ExtPreviewURL string
|
|
PackageURL string
|
|
ExtOrientation *int
|
|
ExtSafeHeight int
|
|
ExtGSP string
|
|
CurrencyIcon string
|
|
ExtExtraJSON string
|
|
CatalogStatus string
|
|
CatalogPreviewURL string
|
|
CatalogDownloadURL string
|
|
CatalogPackage string
|
|
CatalogOrientation *int
|
|
CatalogSafeHeight int
|
|
CatalogGameModeJSON string
|
|
}
|
|
|
|
// PageAdminGames 返回后台百顺游戏管理分页数据。
|
|
func (s *BaishunService) PageAdminGames(
|
|
ctx context.Context,
|
|
sysOrigin string,
|
|
profile string,
|
|
keyword string,
|
|
showcase *bool,
|
|
cursor int,
|
|
limit int,
|
|
) (*AdminBaishunGamePageResponse, error) {
|
|
sysOrigin = normalizeAdminSysOrigin(sysOrigin)
|
|
profile, err := s.requestProfile(ctx, sysOrigin, profile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
cursor = normalizePageCursor(cursor)
|
|
limit = normalizePageLimit(limit)
|
|
|
|
countQuery := s.buildAdminGameQuery(ctx, sysOrigin, profile, keyword, showcase)
|
|
|
|
var total int64
|
|
if err := countQuery.Count(&total).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var rows []adminGameRow
|
|
listQuery := s.buildAdminGameQuery(ctx, sysOrigin, profile, keyword, showcase)
|
|
if err := listQuery.
|
|
Select(`
|
|
cfg.id AS id,
|
|
cfg.sys_origin AS sys_origin,
|
|
ext.profile AS profile,
|
|
cfg.game_id AS internal_game_id,
|
|
cfg.name AS name,
|
|
cfg.category AS category,
|
|
cfg.game_code AS game_code,
|
|
cfg.cover AS cover,
|
|
cfg.amounts AS amounts,
|
|
cfg.is_showcase AS showcase,
|
|
cfg.sort AS sort,
|
|
cfg.height AS height,
|
|
cfg.width AS width,
|
|
cfg.full_screen AS full_screen,
|
|
cfg.client_origin AS client_origin,
|
|
cfg.regions AS regions,
|
|
cfg.game_mode AS game_mode_raw,
|
|
cfg.create_time AS create_time,
|
|
cfg.update_time AS update_time,
|
|
ext.vendor_game_id AS vendor_game_id,
|
|
ext.launch_mode AS launch_mode,
|
|
ext.package_version AS ext_package_version,
|
|
ext.preview_url AS ext_preview_url,
|
|
ext.package_url AS package_url,
|
|
ext.orientation AS ext_orientation,
|
|
ext.safe_height AS ext_safe_height,
|
|
ext.gsp AS ext_gsp,
|
|
ext.currency_icon AS currency_icon,
|
|
ext.extra_json AS ext_extra_json,
|
|
cat.status AS catalog_status,
|
|
cat.preview_url AS catalog_preview_url,
|
|
cat.download_url AS catalog_download_url,
|
|
cat.package_version AS catalog_package,
|
|
cat.orientation AS catalog_orientation,
|
|
cat.safe_height AS catalog_safe_height,
|
|
cat.game_mode_json AS catalog_game_mode_json
|
|
`).
|
|
Order("cfg.is_showcase DESC").
|
|
Order("cfg.sort DESC").
|
|
Order("cfg.update_time DESC").
|
|
Limit(limit).
|
|
Offset((cursor - 1) * limit).
|
|
Scan(&rows).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
items := make([]AdminBaishunGameItem, 0, len(rows))
|
|
for _, row := range rows {
|
|
items = append(items, row.toAdminItem())
|
|
}
|
|
|
|
return &AdminBaishunGamePageResponse{
|
|
Cursor: cursor,
|
|
Limit: limit,
|
|
Records: items,
|
|
Total: total,
|
|
}, nil
|
|
}
|
|
|
|
// SaveAdminGame 保存后台百顺游戏配置。
|
|
func (s *BaishunService) SaveAdminGame(ctx context.Context, req SaveAdminBaishunGameRequest) (*AdminBaishunGameItem, error) {
|
|
sysOrigin := normalizeAdminSysOrigin(req.SysOrigin)
|
|
profile, err := s.requestProfile(ctx, sysOrigin, req.Profile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
runtimeCfg, err := s.resolveRuntimeConfigForProfile(ctx, sysOrigin, profile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
catalog, err := s.findCatalogForAdmin(ctx, sysOrigin, profile, req.VendorGameID, req.GameID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if req.VendorGameID <= 0 {
|
|
req.VendorGameID = catalog.VendorGameID
|
|
}
|
|
if req.VendorGameID <= 0 {
|
|
return nil, NewAppError(http.StatusBadRequest, "vendor_game_id_required", "vendorGameId is required")
|
|
}
|
|
|
|
gameID := strings.TrimSpace(req.GameID)
|
|
if gameID == "" {
|
|
gameID = defaultIfBlank(catalog.InternalGameID, fmt.Sprintf("bs_%d", req.VendorGameID))
|
|
}
|
|
if gameID == "" {
|
|
return nil, NewAppError(http.StatusBadRequest, "game_id_required", "gameId is required")
|
|
}
|
|
|
|
name := defaultIfBlank(strings.TrimSpace(req.Name), defaultIfBlank(catalog.Name, gameID))
|
|
if name == "" {
|
|
return nil, NewAppError(http.StatusBadRequest, "name_required", "name is required")
|
|
}
|
|
category := defaultIfBlank(strings.TrimSpace(req.Category), baishunRoomCategory)
|
|
cover := defaultIfBlank(strings.TrimSpace(req.Cover), defaultIfBlank(catalog.Cover, catalog.PreviewURL))
|
|
clientOrigin := defaultIfBlank(strings.TrimSpace(req.ClientOrigin), "COMMON")
|
|
gameCode := defaultIfBlank(strings.TrimSpace(req.GameCode), strconv.Itoa(req.VendorGameID))
|
|
launchMode := defaultIfBlank(strings.TrimSpace(req.LaunchMode), baishunLaunchModeRemote)
|
|
packageVersion := defaultIfBlank(strings.TrimSpace(req.PackageVersion), catalog.PackageVersion)
|
|
previewURL := defaultIfBlank(strings.TrimSpace(req.PreviewURL), catalog.PreviewURL)
|
|
packageURL := defaultIfBlank(strings.TrimSpace(req.PackageURL), catalog.DownloadURL)
|
|
gsp := defaultIfBlank(strings.TrimSpace(req.GSP), defaultAdminGSP(catalog.GSP, runtimeCfg.gsp()))
|
|
safeHeight := req.SafeHeight
|
|
if safeHeight <= 0 {
|
|
safeHeight = catalog.SafeHeight
|
|
}
|
|
orientation := req.Orientation
|
|
if orientation == nil && catalog.Orientation != nil {
|
|
value := *catalog.Orientation
|
|
orientation = &value
|
|
}
|
|
gameMode := baishunFixedGameMode
|
|
|
|
tx := s.repo.DB.WithContext(ctx).Begin()
|
|
if tx.Error != nil {
|
|
return nil, tx.Error
|
|
}
|
|
defer func() {
|
|
if r := recover(); r != nil {
|
|
tx.Rollback()
|
|
panic(r)
|
|
}
|
|
}()
|
|
|
|
cfg, err := s.findAdminConfigForSave(tx, sysOrigin, profile, req.ID, gameID, req.VendorGameID)
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return nil, err
|
|
}
|
|
showcase := resolveAdminShowcase(req.Showcase, cfg.Showcase, cfg.ID == 0)
|
|
|
|
cfgValues := map[string]any{
|
|
"sys_origin": sysOrigin,
|
|
"game_origin": baishunVendorType,
|
|
"game_id": gameID,
|
|
"name": name,
|
|
"category": category,
|
|
"game_code": gameCode,
|
|
"cover": cover,
|
|
"amounts": strings.TrimSpace(req.Amounts),
|
|
"is_showcase": showcase,
|
|
"sort": req.Sort,
|
|
"height": req.Height,
|
|
"width": req.Width,
|
|
"full_screen": req.FullScreen,
|
|
"client_origin": clientOrigin,
|
|
"regions": strings.TrimSpace(req.Regions),
|
|
"game_mode": formatAdminGameModeRaw(gameMode),
|
|
}
|
|
|
|
if cfg.ID == 0 {
|
|
nextID, idErr := utils.NextID()
|
|
if idErr != nil {
|
|
tx.Rollback()
|
|
return nil, idErr
|
|
}
|
|
cfg = model.SysGameListConfig{
|
|
ID: nextID,
|
|
SysOrigin: sysOrigin,
|
|
GameOrigin: baishunVendorType,
|
|
GameID: gameID,
|
|
Name: name,
|
|
Category: category,
|
|
GameCode: gameCode,
|
|
Cover: cover,
|
|
Amounts: strings.TrimSpace(req.Amounts),
|
|
Showcase: showcase,
|
|
Sort: req.Sort,
|
|
Height: req.Height,
|
|
Width: req.Width,
|
|
FullScreen: req.FullScreen,
|
|
ClientOrigin: clientOrigin,
|
|
Regions: strings.TrimSpace(req.Regions),
|
|
GameMode: formatAdminGameModeRaw(gameMode),
|
|
}
|
|
if err := tx.Create(&cfg).Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, err
|
|
}
|
|
} else {
|
|
if err := tx.Model(&model.SysGameListConfig{}).
|
|
Where("id = ?", cfg.ID).
|
|
Updates(cfgValues).Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
var ext model.SysGameListVendorExt
|
|
err = tx.Where("game_list_config_id = ? AND vendor_type = ? AND profile = ?", cfg.ID, baishunVendorType, profile).First(&ext).Error
|
|
if err != nil && err != gorm.ErrRecordNotFound {
|
|
tx.Rollback()
|
|
return nil, err
|
|
}
|
|
|
|
now := time.Now()
|
|
extraJSON := updateExtExtraJSONWithGameType(ext.ExtraJSON, req.LaunchParams, baishunVendorType, ext.ID != 0)
|
|
if ext.ID == 0 {
|
|
nextID, idErr := utils.NextID()
|
|
if idErr != nil {
|
|
tx.Rollback()
|
|
return nil, idErr
|
|
}
|
|
ext = model.SysGameListVendorExt{
|
|
ID: nextID,
|
|
GameListConfigID: cfg.ID,
|
|
SysOrigin: sysOrigin,
|
|
Profile: profile,
|
|
VendorType: baishunVendorType,
|
|
VendorGameID: strconv.Itoa(req.VendorGameID),
|
|
LaunchMode: launchMode,
|
|
PackageVersion: packageVersion,
|
|
PackageURL: packageURL,
|
|
PreviewURL: previewURL,
|
|
Orientation: orientation,
|
|
SafeHeight: safeHeight,
|
|
GSP: gsp,
|
|
CurrencyIcon: strings.TrimSpace(req.CurrencyIcon),
|
|
ExtraJSON: extraJSON,
|
|
Enabled: true,
|
|
CreateTime: now,
|
|
UpdateTime: now,
|
|
}
|
|
if err := tx.Create(&ext).Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, err
|
|
}
|
|
} else {
|
|
if err := tx.Model(&model.SysGameListVendorExt{}).
|
|
Where("id = ?", ext.ID).
|
|
Updates(map[string]any{
|
|
"sys_origin": sysOrigin,
|
|
"profile": profile,
|
|
"vendor_game_id": strconv.Itoa(req.VendorGameID),
|
|
"launch_mode": launchMode,
|
|
"package_version": packageVersion,
|
|
"package_url": packageURL,
|
|
"preview_url": previewURL,
|
|
"orientation": orientation,
|
|
"safe_height": safeHeight,
|
|
"gsp": gsp,
|
|
"currency_icon": strings.TrimSpace(req.CurrencyIcon),
|
|
"extra_json": extraJSON,
|
|
"enabled": true,
|
|
"bridge_schema_version": defaultIfBlank(ext.BridgeSchemaVersion, "1.0"),
|
|
"update_time": now,
|
|
}).Error; err != nil {
|
|
tx.Rollback()
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
if err := tx.Commit().Error; err != nil {
|
|
return nil, err
|
|
}
|
|
s.clearJavaGameListCache(ctx)
|
|
return s.getAdminGame(ctx, sysOrigin, profile, cfg.ID)
|
|
}
|
|
|
|
// DeleteAdminGame 删除后台百顺游戏配置,不影响目录表。
|
|
func (s *BaishunService) DeleteAdminGame(ctx context.Context, sysOrigin string, profile string, id int64) error {
|
|
if id <= 0 {
|
|
return NewAppError(http.StatusBadRequest, "id_required", "id is required")
|
|
}
|
|
sysOrigin = normalizeAdminSysOrigin(sysOrigin)
|
|
profile, err := s.requestProfile(ctx, sysOrigin, profile)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
tx := s.repo.DB.WithContext(ctx).Begin()
|
|
if tx.Error != nil {
|
|
return tx.Error
|
|
}
|
|
if err := tx.Where("game_list_config_id = ? AND vendor_type = ? AND profile = ?", id, baishunVendorType, profile).
|
|
Delete(&model.SysGameListVendorExt{}).Error; err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
var remaining int64
|
|
if err := tx.Model(&model.SysGameListVendorExt{}).
|
|
Where("game_list_config_id = ? AND vendor_type = ?", id, baishunVendorType).
|
|
Count(&remaining).Error; err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
if remaining == 0 {
|
|
if err := tx.Where("id = ? AND sys_origin = ? AND game_origin = ?", id, sysOrigin, baishunVendorType).
|
|
Delete(&model.SysGameListConfig{}).Error; err != nil {
|
|
tx.Rollback()
|
|
return err
|
|
}
|
|
}
|
|
if err := tx.Commit().Error; err != nil {
|
|
return err
|
|
}
|
|
s.clearJavaGameListCache(ctx)
|
|
return nil
|
|
}
|
|
|
|
// ImportCatalogGames 把本地目录中尚未进入后台列表的百顺游戏补齐成可配置记录。
|
|
func (s *BaishunService) ImportCatalogGames(ctx context.Context, sysOrigin string, profile string, vendorGameIDs []int, defaultShowcase ...bool) (*ImportCatalogResponse, error) {
|
|
sysOrigin = normalizeAdminSysOrigin(sysOrigin)
|
|
profile, err := s.requestProfile(ctx, sysOrigin, profile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
tx := s.repo.DB.WithContext(ctx).Begin()
|
|
if tx.Error != nil {
|
|
return nil, tx.Error
|
|
}
|
|
resp, err := s.importCatalogGamesTx(tx, sysOrigin, profile, buildVendorGameIDFilter(vendorGameIDs), resolveImportDefaultShowcase(defaultShowcase...))
|
|
if err != nil {
|
|
tx.Rollback()
|
|
return nil, err
|
|
}
|
|
if err := tx.Commit().Error; err != nil {
|
|
return nil, err
|
|
}
|
|
s.clearJavaGameListCache(ctx)
|
|
return resp, nil
|
|
}
|
|
|
|
// SyncAdminGames 先同步百顺平台目录,再把缺失配置导入后台列表。
|
|
func (s *BaishunService) SyncAdminGames(ctx context.Context, req SyncCatalogRequest) (*SyncAdminCatalogResponse, error) {
|
|
syncResp, err := s.SyncCatalog(ctx, req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
importResp, err := s.ImportCatalogGames(ctx, req.SysOrigin, req.Profile, req.VendorGameIDs, resolveBoolPtrDefault(req.DefaultShowcase, true))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &SyncAdminCatalogResponse{
|
|
Inserted: syncResp.Inserted,
|
|
Updated: syncResp.Updated,
|
|
Skipped: syncResp.Skipped,
|
|
Existing: importResp.Existing,
|
|
Imported: importResp.Imported,
|
|
}, nil
|
|
}
|
|
|
|
func (s *BaishunService) buildAdminGameQuery(ctx context.Context, sysOrigin, profile, keyword string, showcase *bool) *gorm.DB {
|
|
query := s.repo.DB.WithContext(ctx).
|
|
Table("sys_game_list_config AS cfg").
|
|
Joins("JOIN sys_game_list_vendor_ext ext ON ext.game_list_config_id = cfg.id AND ext.vendor_type = ? AND ext.profile = ?", baishunVendorType, profile).
|
|
Joins(`
|
|
LEFT JOIN baishun_game_catalog cat
|
|
ON cat.sys_origin = cfg.sys_origin
|
|
AND cat.profile = ext.profile
|
|
AND (
|
|
CAST(cat.vendor_game_id AS CHAR) = ext.vendor_game_id
|
|
OR cat.internal_game_id = cfg.game_id
|
|
)
|
|
`).
|
|
Where("cfg.sys_origin = ? AND cfg.game_origin = ?", sysOrigin, baishunVendorType)
|
|
if showcase != nil {
|
|
query = query.Where("cfg.is_showcase = ?", *showcase)
|
|
}
|
|
keyword = strings.TrimSpace(keyword)
|
|
if keyword != "" {
|
|
like := "%" + keyword + "%"
|
|
query = query.Where(`
|
|
cfg.name LIKE ?
|
|
OR cfg.game_id LIKE ?
|
|
OR cfg.game_code LIKE ?
|
|
OR ext.vendor_game_id LIKE ?
|
|
`, like, like, like, like)
|
|
}
|
|
return query
|
|
}
|
|
|
|
func (s *BaishunService) getAdminGame(ctx context.Context, sysOrigin string, profile string, id int64) (*AdminBaishunGameItem, error) {
|
|
var rows []adminGameRow
|
|
err := s.buildAdminGameQuery(ctx, sysOrigin, profile, "", nil).
|
|
Where("cfg.id = ?", id).
|
|
Select(`
|
|
cfg.id AS id,
|
|
cfg.sys_origin AS sys_origin,
|
|
ext.profile AS profile,
|
|
cfg.game_id AS internal_game_id,
|
|
cfg.name AS name,
|
|
cfg.category AS category,
|
|
cfg.game_code AS game_code,
|
|
cfg.cover AS cover,
|
|
cfg.amounts AS amounts,
|
|
cfg.is_showcase AS showcase,
|
|
cfg.sort AS sort,
|
|
cfg.height AS height,
|
|
cfg.width AS width,
|
|
cfg.full_screen AS full_screen,
|
|
cfg.client_origin AS client_origin,
|
|
cfg.regions AS regions,
|
|
cfg.game_mode AS game_mode_raw,
|
|
cfg.create_time AS create_time,
|
|
cfg.update_time AS update_time,
|
|
ext.vendor_game_id AS vendor_game_id,
|
|
ext.launch_mode AS launch_mode,
|
|
ext.package_version AS ext_package_version,
|
|
ext.preview_url AS ext_preview_url,
|
|
ext.package_url AS package_url,
|
|
ext.orientation AS ext_orientation,
|
|
ext.safe_height AS ext_safe_height,
|
|
ext.gsp AS ext_gsp,
|
|
ext.currency_icon AS currency_icon,
|
|
ext.extra_json AS ext_extra_json,
|
|
cat.status AS catalog_status,
|
|
cat.preview_url AS catalog_preview_url,
|
|
cat.download_url AS catalog_download_url,
|
|
cat.package_version AS catalog_package,
|
|
cat.orientation AS catalog_orientation,
|
|
cat.safe_height AS catalog_safe_height,
|
|
cat.game_mode_json AS catalog_game_mode_json
|
|
`).
|
|
Limit(1).
|
|
Scan(&rows).Error
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if len(rows) == 1 {
|
|
item := rows[0].toAdminItem()
|
|
return &item, nil
|
|
}
|
|
return nil, NewAppError(http.StatusNotFound, "game_not_found", "admin baishun game not found")
|
|
}
|
|
|
|
func (s *BaishunService) findCatalogForAdmin(ctx context.Context, sysOrigin string, profile string, vendorGameID int, gameID string) (model.BaishunGameCatalog, error) {
|
|
query := s.repo.DB.WithContext(ctx).Where("sys_origin = ? AND profile = ?", sysOrigin, profile)
|
|
switch {
|
|
case vendorGameID > 0:
|
|
query = query.Where("vendor_game_id = ?", vendorGameID)
|
|
case strings.TrimSpace(gameID) != "":
|
|
query = query.Where("internal_game_id = ?", strings.TrimSpace(gameID))
|
|
default:
|
|
return model.BaishunGameCatalog{}, nil
|
|
}
|
|
|
|
var catalog model.BaishunGameCatalog
|
|
if err := query.First(&catalog).Error; err != nil {
|
|
if err == gorm.ErrRecordNotFound {
|
|
return model.BaishunGameCatalog{}, nil
|
|
}
|
|
return model.BaishunGameCatalog{}, err
|
|
}
|
|
return catalog, nil
|
|
}
|
|
|
|
func (s *BaishunService) findAdminConfigForSave(tx *gorm.DB, sysOrigin string, profile string, id int64, gameID string, vendorGameID int) (model.SysGameListConfig, error) {
|
|
var cfg model.SysGameListConfig
|
|
if id > 0 {
|
|
err := tx.Where("id = ? AND sys_origin = ? AND game_origin = ?", id, sysOrigin, baishunVendorType).First(&cfg).Error
|
|
if err == gorm.ErrRecordNotFound {
|
|
return model.SysGameListConfig{}, NewAppError(http.StatusNotFound, "game_not_found", "admin baishun game not found")
|
|
}
|
|
if err == nil {
|
|
var extCount int64
|
|
err = tx.Model(&model.SysGameListVendorExt{}).
|
|
Where("game_list_config_id = ? AND vendor_type = ? AND profile = ?", cfg.ID, baishunVendorType, profile).
|
|
Count(&extCount).Error
|
|
if err != nil {
|
|
return model.SysGameListConfig{}, err
|
|
}
|
|
if extCount == 0 {
|
|
return model.SysGameListConfig{}, NewAppError(http.StatusNotFound, "game_not_found", "admin baishun game not found")
|
|
}
|
|
}
|
|
return cfg, err
|
|
}
|
|
|
|
if vendorGameID > 0 {
|
|
var ext model.SysGameListVendorExt
|
|
err := tx.Where("sys_origin = ? AND profile = ? AND vendor_type = ? AND vendor_game_id = ?", sysOrigin, profile, baishunVendorType, strconv.Itoa(vendorGameID)).First(&ext).Error
|
|
if err != nil && err != gorm.ErrRecordNotFound {
|
|
return model.SysGameListConfig{}, err
|
|
}
|
|
if ext.GameListConfigID > 0 {
|
|
err = tx.Where("id = ? AND sys_origin = ? AND game_origin = ?", ext.GameListConfigID, sysOrigin, baishunVendorType).First(&cfg).Error
|
|
if err == nil {
|
|
return cfg, nil
|
|
}
|
|
if err != gorm.ErrRecordNotFound {
|
|
return model.SysGameListConfig{}, err
|
|
}
|
|
}
|
|
}
|
|
|
|
if strings.TrimSpace(gameID) == "" {
|
|
return model.SysGameListConfig{}, nil
|
|
}
|
|
err := tx.Table("sys_game_list_config AS cfg").
|
|
Joins("JOIN sys_game_list_vendor_ext ext ON ext.game_list_config_id = cfg.id AND ext.vendor_type = ? AND ext.profile = ?", baishunVendorType, profile).
|
|
Where("cfg.sys_origin = ? AND cfg.game_origin = ? AND cfg.game_id = ?", sysOrigin, baishunVendorType, strings.TrimSpace(gameID)).
|
|
Select("cfg.*").
|
|
Limit(1).
|
|
Scan(&cfg).Error
|
|
if err != nil {
|
|
return model.SysGameListConfig{}, err
|
|
}
|
|
if cfg.ID == 0 {
|
|
return model.SysGameListConfig{}, nil
|
|
}
|
|
return cfg, nil
|
|
}
|
|
|
|
func (s *BaishunService) importCatalogGamesTx(tx *gorm.DB, sysOrigin string, profile string, filter map[int]struct{}, defaultShowcase bool) (*ImportCatalogResponse, error) {
|
|
ctx := tx.Statement.Context
|
|
if ctx == nil {
|
|
ctx = context.Background()
|
|
}
|
|
runtimeCfg, err := s.resolveRuntimeConfigForProfile(ctx, sysOrigin, profile)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
query := tx.Where("sys_origin = ? AND profile = ? AND status = ?", sysOrigin, profile, baishunCatalogEnabled)
|
|
if len(filter) > 0 {
|
|
ids := make([]int, 0, len(filter))
|
|
for id := range filter {
|
|
ids = append(ids, id)
|
|
}
|
|
query = query.Where("vendor_game_id IN ?", ids)
|
|
}
|
|
|
|
var catalogs []model.BaishunGameCatalog
|
|
if err := query.Order("vendor_game_id ASC").Find(&catalogs).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
resp := &ImportCatalogResponse{}
|
|
for _, catalog := range catalogs {
|
|
vendorGameID := strconv.Itoa(catalog.VendorGameID)
|
|
now := time.Now()
|
|
|
|
var ext model.SysGameListVendorExt
|
|
err := tx.Where("sys_origin = ? AND profile = ? AND vendor_type = ? AND vendor_game_id = ?", sysOrigin, profile, baishunVendorType, vendorGameID).First(&ext).Error
|
|
if err != nil && err != gorm.ErrRecordNotFound {
|
|
return nil, err
|
|
}
|
|
if err == nil && ext.GameListConfigID > 0 {
|
|
var cfg model.SysGameListConfig
|
|
cfgErr := tx.Where("id = ? AND sys_origin = ? AND game_origin = ?", ext.GameListConfigID, sysOrigin, baishunVendorType).First(&cfg).Error
|
|
if cfgErr == nil {
|
|
resp.Existing++
|
|
continue
|
|
}
|
|
if cfgErr != gorm.ErrRecordNotFound {
|
|
return nil, cfgErr
|
|
}
|
|
}
|
|
|
|
nextCfgID, idErr := utils.NextID()
|
|
if idErr != nil {
|
|
return nil, idErr
|
|
}
|
|
cfg := model.SysGameListConfig{
|
|
ID: nextCfgID,
|
|
SysOrigin: sysOrigin,
|
|
GameOrigin: baishunVendorType,
|
|
GameID: defaultIfBlank(catalog.InternalGameID, fmt.Sprintf("bs_%d", catalog.VendorGameID)),
|
|
Name: catalog.Name,
|
|
Category: baishunRoomCategory,
|
|
GameCode: vendorGameID,
|
|
Cover: defaultIfBlank(catalog.Cover, catalog.PreviewURL),
|
|
Showcase: defaultShowcase,
|
|
Sort: int64(catalog.VendorGameID),
|
|
FullScreen: true,
|
|
ClientOrigin: "COMMON",
|
|
GameMode: formatAdminGameModeRaw(baishunFixedGameMode),
|
|
}
|
|
if err := tx.Create(&cfg).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
nextID, idErr := utils.NextID()
|
|
if idErr != nil {
|
|
return nil, idErr
|
|
}
|
|
extraJSON := updateExtExtraJSONWithGameType(ext.ExtraJSON, nil, baishunVendorType, ext.ID != 0)
|
|
extValues := map[string]any{
|
|
"game_list_config_id": cfg.ID,
|
|
"sys_origin": sysOrigin,
|
|
"profile": profile,
|
|
"vendor_type": baishunVendorType,
|
|
"vendor_game_id": vendorGameID,
|
|
"launch_mode": baishunLaunchModeRemote,
|
|
"package_version": catalog.PackageVersion,
|
|
"package_url": catalog.DownloadURL,
|
|
"preview_url": catalog.PreviewURL,
|
|
"orientation": catalog.Orientation,
|
|
"safe_height": catalog.SafeHeight,
|
|
"gsp": defaultAdminGSP(catalog.GSP, runtimeCfg.gsp()),
|
|
"bridge_schema_version": "1.0",
|
|
"extra_json": extraJSON,
|
|
"enabled": true,
|
|
"update_time": now,
|
|
}
|
|
if ext.ID > 0 {
|
|
if err := tx.Model(&model.SysGameListVendorExt{}).
|
|
Where("id = ?", ext.ID).
|
|
Updates(extValues).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
newExt := model.SysGameListVendorExt{
|
|
ID: nextID,
|
|
GameListConfigID: cfg.ID,
|
|
SysOrigin: sysOrigin,
|
|
Profile: profile,
|
|
VendorType: baishunVendorType,
|
|
VendorGameID: vendorGameID,
|
|
LaunchMode: baishunLaunchModeRemote,
|
|
PackageVersion: catalog.PackageVersion,
|
|
PackageURL: catalog.DownloadURL,
|
|
PreviewURL: catalog.PreviewURL,
|
|
Orientation: catalog.Orientation,
|
|
SafeHeight: catalog.SafeHeight,
|
|
GSP: defaultAdminGSP(catalog.GSP, runtimeCfg.gsp()),
|
|
BridgeSchemaVersion: "1.0",
|
|
ExtraJSON: extraJSON,
|
|
Enabled: true,
|
|
CreateTime: now,
|
|
UpdateTime: now,
|
|
}
|
|
if err := tx.Create(&newExt).Error; err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
resp.Imported++
|
|
}
|
|
return resp, nil
|
|
}
|
|
|
|
func resolveImportDefaultShowcase(values ...bool) bool {
|
|
if len(values) == 0 {
|
|
return true
|
|
}
|
|
return values[0]
|
|
}
|
|
|
|
func resolveBoolPtrDefault(value *bool, fallback bool) bool {
|
|
if value == nil {
|
|
return fallback
|
|
}
|
|
return *value
|
|
}
|
|
|
|
func (r adminGameRow) toAdminItem() AdminBaishunGameItem {
|
|
return AdminBaishunGameItem{
|
|
ID: r.ID,
|
|
SysOrigin: r.SysOrigin,
|
|
Profile: normalizeBaishunProfile(r.Profile),
|
|
GameID: r.InternalGameID,
|
|
GameType: gameTypeFromExtraJSON(r.ExtExtraJSON, baishunVendorType),
|
|
VendorGameID: parseAdminVendorGameID(r.VendorGameID, r.InternalGameID),
|
|
Name: r.Name,
|
|
Category: r.Category,
|
|
GameCode: r.GameCode,
|
|
Cover: r.Cover,
|
|
Amounts: r.Amounts,
|
|
Showcase: r.Showcase,
|
|
Sort: r.Sort,
|
|
Height: r.Height,
|
|
Width: r.Width,
|
|
FullScreen: r.FullScreen,
|
|
ClientOrigin: r.ClientOrigin,
|
|
Regions: r.Regions,
|
|
GameMode: baishunFixedGameMode,
|
|
LaunchMode: defaultIfBlank(r.LaunchMode, baishunLaunchModeRemote),
|
|
PackageVersion: defaultIfBlank(r.ExtPackageVersion, r.CatalogPackage),
|
|
PreviewURL: defaultIfBlank(r.ExtPreviewURL, r.CatalogPreviewURL),
|
|
PackageURL: defaultIfBlank(r.PackageURL, r.CatalogDownloadURL),
|
|
Orientation: chooseAdminOrientation(r.ExtOrientation, r.CatalogOrientation),
|
|
SafeHeight: chooseAdminSafeHeight(r.ExtSafeHeight, r.CatalogSafeHeight),
|
|
GSP: r.ExtGSP,
|
|
CurrencyIcon: r.CurrencyIcon,
|
|
CatalogStatus: r.CatalogStatus,
|
|
LaunchParams: launchParamsWithGameType(r.ExtExtraJSON, baishunVendorType),
|
|
CreateTime: formatAdminTime(r.CreateTime),
|
|
UpdateTime: formatAdminTime(r.UpdateTime),
|
|
}
|
|
}
|
|
|
|
func normalizeAdminSysOrigin(sysOrigin string) string {
|
|
sysOrigin = strings.ToUpper(strings.TrimSpace(sysOrigin))
|
|
if sysOrigin == "" {
|
|
return "LIKEI"
|
|
}
|
|
return sysOrigin
|
|
}
|
|
|
|
func normalizePageCursor(cursor int) int {
|
|
if cursor <= 0 {
|
|
return 1
|
|
}
|
|
return cursor
|
|
}
|
|
|
|
func normalizePageLimit(limit int) int {
|
|
if limit <= 0 {
|
|
return 20
|
|
}
|
|
if limit > 200 {
|
|
return 200
|
|
}
|
|
return limit
|
|
}
|
|
|
|
func resolveAdminShowcase(showcase *bool, current bool, isCreate bool) bool {
|
|
if showcase != nil {
|
|
return *showcase
|
|
}
|
|
if isCreate {
|
|
return true
|
|
}
|
|
return current
|
|
}
|
|
|
|
func defaultAdminGSP(catalogGSP string, fallback int) string {
|
|
if strings.TrimSpace(catalogGSP) != "" {
|
|
return strings.TrimSpace(catalogGSP)
|
|
}
|
|
if fallback > 0 {
|
|
return strconv.Itoa(fallback)
|
|
}
|
|
return "101"
|
|
}
|
|
|
|
func formatAdminGameModeRaw(gameMode int) string {
|
|
return fmt.Sprintf("[%d]", baishunFixedGameMode)
|
|
}
|
|
|
|
func parseAdminVendorGameID(raw string, gameID string) int {
|
|
if parsed, err := strconv.Atoi(strings.TrimSpace(raw)); err == nil {
|
|
return parsed
|
|
}
|
|
if strings.HasPrefix(strings.TrimSpace(gameID), "bs_") {
|
|
if parsed, err := strconv.Atoi(strings.TrimPrefix(strings.TrimSpace(gameID), "bs_")); err == nil {
|
|
return parsed
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func chooseAdminOrientation(extOrientation, catalogOrientation *int) int {
|
|
if extOrientation != nil {
|
|
return *extOrientation
|
|
}
|
|
if catalogOrientation != nil {
|
|
return *catalogOrientation
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func chooseAdminSafeHeight(extSafeHeight, catalogSafeHeight int) int {
|
|
if extSafeHeight > 0 {
|
|
return extSafeHeight
|
|
}
|
|
return catalogSafeHeight
|
|
}
|
|
|
|
func formatAdminTime(value time.Time) string {
|
|
if value.IsZero() {
|
|
return ""
|
|
}
|
|
return value.Format(adminTimeLayout)
|
|
}
|
|
|
|
func buildVendorGameIDFilter(vendorGameIDs []int) map[int]struct{} {
|
|
filter := make(map[int]struct{}, len(vendorGameIDs))
|
|
for _, id := range vendorGameIDs {
|
|
if id > 0 {
|
|
filter[id] = struct{}{}
|
|
}
|
|
}
|
|
return filter
|
|
}
|