yumi-golang/internal/service/baishun/provider_config.go
2026-04-24 13:04:06 +08:00

321 lines
9.7 KiB
Go

package baishun
import (
"chatapp3-golang/internal/model"
"chatapp3-golang/internal/utils"
"context"
"net/http"
"strings"
"time"
"gorm.io/gorm"
"gorm.io/gorm/clause"
)
type baishunRuntimeConfig struct {
SysOrigin string
Profile string
PlatformBaseURL string
AppID int64
AppName string
AppChannel string
AppKey string
GSP int
LaunchCodeTTLSeconds int
SSTokenTTLSeconds int
}
func (c baishunRuntimeConfig) appChannel() string {
return defaultIfBlank(strings.TrimSpace(c.AppChannel), "skychat")
}
func (c baishunRuntimeConfig) gsp() int {
if c.GSP > 0 {
return c.GSP
}
return 101
}
func (c baishunRuntimeConfig) launchCodeTTLSeconds() int {
if c.LaunchCodeTTLSeconds > 0 {
return c.LaunchCodeTTLSeconds
}
return 300
}
func (c baishunRuntimeConfig) ssTokenTTLSeconds() int {
if c.SSTokenTTLSeconds > 0 {
return c.SSTokenTTLSeconds
}
return 86400
}
func (s *BaishunService) defaultRuntimeConfig(sysOrigin string) baishunRuntimeConfig {
return baishunRuntimeConfig{
SysOrigin: normalizeAdminSysOrigin(sysOrigin),
Profile: baishunProfileProd,
PlatformBaseURL: strings.TrimSpace(s.cfg.Baishun.PlatformBaseURL),
AppID: s.cfg.Baishun.AppID,
AppName: strings.TrimSpace(s.cfg.Baishun.AppName),
AppChannel: strings.TrimSpace(s.cfg.Baishun.AppChannel),
AppKey: strings.TrimSpace(s.cfg.Baishun.AppKey),
GSP: s.cfg.Baishun.GSP,
LaunchCodeTTLSeconds: s.cfg.Baishun.LaunchCodeTTLSeconds,
SSTokenTTLSeconds: s.cfg.Baishun.SSTokenTTLSeconds,
}
}
func applyProviderRow(base baishunRuntimeConfig, row model.BaishunProviderConfig) baishunRuntimeConfig {
base.SysOrigin = normalizeAdminSysOrigin(defaultIfBlank(row.SysOrigin, base.SysOrigin))
base.Profile = normalizeBaishunProfile(defaultIfBlank(row.Profile, base.Profile))
if strings.TrimSpace(row.PlatformBaseURL) != "" {
base.PlatformBaseURL = strings.TrimSpace(row.PlatformBaseURL)
}
if row.AppID > 0 {
base.AppID = row.AppID
}
if strings.TrimSpace(row.AppName) != "" {
base.AppName = strings.TrimSpace(row.AppName)
}
if strings.TrimSpace(row.AppChannel) != "" {
base.AppChannel = strings.TrimSpace(row.AppChannel)
}
if strings.TrimSpace(row.AppKey) != "" {
base.AppKey = strings.TrimSpace(row.AppKey)
}
if row.GSP > 0 {
base.GSP = row.GSP
}
if row.LaunchCodeTTLSeconds > 0 {
base.LaunchCodeTTLSeconds = row.LaunchCodeTTLSeconds
}
if row.SSTokenTTLSeconds > 0 {
base.SSTokenTTLSeconds = row.SSTokenTTLSeconds
}
return base
}
func (s *BaishunService) resolveRuntimeConfig(ctx context.Context, sysOrigin string) (baishunRuntimeConfig, error) {
sysOrigin = normalizeAdminSysOrigin(sysOrigin)
profile, err := s.activeProfile(ctx, sysOrigin)
if err != nil {
return baishunRuntimeConfig{}, err
}
return s.resolveRuntimeConfigForProfile(ctx, sysOrigin, profile)
}
func (s *BaishunService) resolveRuntimeConfigForProfile(ctx context.Context, sysOrigin string, profile string) (baishunRuntimeConfig, error) {
sysOrigin = normalizeAdminSysOrigin(sysOrigin)
profile, err := validateBaishunProfile(profile)
if err != nil {
return baishunRuntimeConfig{}, err
}
base := s.defaultRuntimeConfig(sysOrigin)
base.Profile = profile
var row model.BaishunProviderConfig
err = s.repo.DB.WithContext(ctx).
Where("sys_origin = ? AND profile = ?", sysOrigin, profile).
Limit(1).
First(&row).Error
if err == nil {
return applyProviderRow(base, row), nil
}
if err == gorm.ErrRecordNotFound {
return base, nil
}
return baishunRuntimeConfig{}, err
}
func (s *BaishunService) resolveRuntimeConfigByApp(ctx context.Context, appID int64, appChannel string) (baishunRuntimeConfig, error) {
base := s.defaultRuntimeConfig("LIKEI")
appChannel = strings.TrimSpace(appChannel)
queries := make([]func(*gorm.DB) *gorm.DB, 0, 3)
if appID > 0 && appChannel != "" {
queries = append(queries, func(db *gorm.DB) *gorm.DB {
return db.Where("app_id = ? AND app_channel = ?", appID, appChannel)
})
}
if appID > 0 {
queries = append(queries, func(db *gorm.DB) *gorm.DB {
return db.Where("app_id = ?", appID)
})
}
if appChannel != "" {
queries = append(queries, func(db *gorm.DB) *gorm.DB {
return db.Where("app_channel = ?", appChannel)
})
}
for _, build := range queries {
var row model.BaishunProviderConfig
err := build(s.repo.DB.WithContext(ctx)).
Order("active DESC").
Order("update_time DESC").
Limit(1).
First(&row).Error
if err == nil {
return applyProviderRow(s.defaultRuntimeConfig(row.SysOrigin), row), nil
}
if err != gorm.ErrRecordNotFound {
return baishunRuntimeConfig{}, err
}
}
return base, nil
}
func (s *BaishunService) GetProviderConfig(ctx context.Context, sysOrigin string, profile string) (*BaishunProviderConfigItem, error) {
sysOrigin = normalizeAdminSysOrigin(sysOrigin)
activeProfile, err := s.activeProfile(ctx, sysOrigin)
if err != nil {
return nil, err
}
profile, err = s.requestProfile(ctx, sysOrigin, profile)
if err != nil {
return nil, err
}
runtimeCfg, err := s.resolveRuntimeConfigForProfile(ctx, sysOrigin, profile)
if err != nil {
return nil, err
}
var row model.BaishunProviderConfig
_ = s.repo.DB.WithContext(ctx).
Where("sys_origin = ? AND profile = ?", sysOrigin, profile).
Limit(1).
First(&row).Error
return &BaishunProviderConfigItem{
ID: row.ID,
SysOrigin: runtimeCfg.SysOrigin,
Profile: runtimeCfg.Profile,
ActiveProfile: activeProfile,
Active: runtimeCfg.Profile == activeProfile,
PlatformBaseURL: runtimeCfg.PlatformBaseURL,
AppID: runtimeCfg.AppID,
AppName: runtimeCfg.AppName,
AppChannel: runtimeCfg.appChannel(),
AppKey: runtimeCfg.AppKey,
GSP: runtimeCfg.gsp(),
LaunchCodeTTLSeconds: runtimeCfg.launchCodeTTLSeconds(),
SSTokenTTLSeconds: runtimeCfg.ssTokenTTLSeconds(),
UpdateTime: formatAdminTime(row.UpdateTime),
}, nil
}
func (s *BaishunService) SaveProviderConfig(ctx context.Context, req SaveBaishunProviderConfigRequest) (*BaishunProviderConfigItem, error) {
sysOrigin := normalizeAdminSysOrigin(req.SysOrigin)
profile, err := validateBaishunProfile(req.Profile)
if err != nil {
return nil, err
}
platformBaseURL := strings.TrimSpace(req.PlatformBaseURL)
appChannel := strings.TrimSpace(req.AppChannel)
appKey := strings.TrimSpace(req.AppKey)
switch {
case platformBaseURL == "":
return nil, NewAppError(http.StatusBadRequest, "platform_base_url_required", "platformBaseUrl is required")
case req.AppID <= 0:
return nil, NewAppError(http.StatusBadRequest, "app_id_required", "appId is required")
case appChannel == "":
return nil, NewAppError(http.StatusBadRequest, "app_channel_required", "appChannel is required")
case appKey == "":
return nil, NewAppError(http.StatusBadRequest, "app_key_required", "appKey is required")
}
id, err := utils.NextID()
if err != nil {
return nil, err
}
now := time.Now()
row := model.BaishunProviderConfig{
ID: id,
SysOrigin: sysOrigin,
Profile: profile,
PlatformBaseURL: platformBaseURL,
AppID: req.AppID,
AppName: strings.TrimSpace(req.AppName),
AppChannel: appChannel,
AppKey: appKey,
GSP: req.GSP,
LaunchCodeTTLSeconds: req.LaunchCodeTTLSeconds,
SSTokenTTLSeconds: req.SSTokenTTLSeconds,
CreateTime: now,
UpdateTime: now,
}
if row.GSP <= 0 {
row.GSP = 101
}
if row.LaunchCodeTTLSeconds <= 0 {
row.LaunchCodeTTLSeconds = 300
}
if row.SSTokenTTLSeconds <= 0 {
row.SSTokenTTLSeconds = 86400
}
var activeCount int64
if err := s.repo.DB.WithContext(ctx).
Model(&model.BaishunProviderConfig{}).
Where("sys_origin = ? AND active = ?", sysOrigin, true).
Count(&activeCount).Error; err != nil {
return nil, err
}
row.Active = activeCount == 0
if err := s.repo.DB.WithContext(ctx).Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "sys_origin"}, {Name: "profile"}},
DoUpdates: clause.AssignmentColumns([]string{
"platform_base_url", "app_id", "app_name", "app_channel", "app_key",
"gsp", "launch_code_ttl_seconds", "ss_token_ttl_seconds", "update_time",
}),
}).Create(&row).Error; err != nil {
return nil, err
}
if row.Active {
s.clearJavaGameListCache(ctx)
}
return s.GetProviderConfig(ctx, sysOrigin, profile)
}
func (s *BaishunService) ActivateProviderProfile(ctx context.Context, req ActivateBaishunProviderProfileRequest) (*BaishunProviderConfigItem, error) {
sysOrigin := normalizeAdminSysOrigin(req.SysOrigin)
profile, err := validateBaishunProfile(req.Profile)
if err != nil {
return nil, err
}
var row model.BaishunProviderConfig
if err := s.repo.DB.WithContext(ctx).
Where("sys_origin = ? AND profile = ?", sysOrigin, profile).
Limit(1).
First(&row).Error; err != nil {
if err == gorm.ErrRecordNotFound {
return nil, NewAppError(http.StatusBadRequest, "profile_config_missing", "profile config is missing")
}
return nil, err
}
now := time.Now()
if err := s.repo.DB.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
if err := tx.Model(&model.BaishunProviderConfig{}).
Where("sys_origin = ?", sysOrigin).
Updates(map[string]any{
"active": false,
"update_time": now,
}).Error; err != nil {
return err
}
return tx.Model(&model.BaishunProviderConfig{}).
Where("sys_origin = ? AND profile = ?", sysOrigin, profile).
Updates(map[string]any{
"active": true,
"update_time": now,
}).Error
}); err != nil {
return nil, err
}
s.clearJavaGameListCache(ctx)
return s.GetProviderConfig(ctx, sysOrigin, profile)
}