feat(Sora): 完成Sora网关接入与媒体能力

新增 Sora 网关路由、账号调度与同步服务\n补充媒体代理与签名 URL、模型列表动态拉取\n完善计费配置、前端支持与相关测试
This commit is contained in:
yangjianbo
2026-01-31 20:22:22 +08:00
parent 99dc3b59bc
commit 618a614cbf
67 changed files with 4840 additions and 202 deletions

View File

@@ -86,6 +86,7 @@ type OpenAITokenRefresher struct {
openaiOAuthService *OpenAIOAuthService
accountRepo AccountRepository
soraAccountRepo SoraAccountRepository // Sora 扩展表仓储,用于双表同步
soraSyncService *Sora2APISyncService // Sora2API 同步服务
}
// NewOpenAITokenRefresher 创建 OpenAI token刷新器
@@ -103,17 +104,22 @@ func (r *OpenAITokenRefresher) SetSoraAccountRepo(repo SoraAccountRepository) {
r.soraAccountRepo = repo
}
// SetSoraSyncService 设置 Sora2API 同步服务
func (r *OpenAITokenRefresher) SetSoraSyncService(svc *Sora2APISyncService) {
r.soraSyncService = svc
}
// CanRefresh 检查是否能处理此账号
// 只处理 openai 平台的 oauth 类型账号
func (r *OpenAITokenRefresher) CanRefresh(account *Account) bool {
return account.Platform == PlatformOpenAI &&
return (account.Platform == PlatformOpenAI || account.Platform == PlatformSora) &&
account.Type == AccountTypeOAuth
}
// NeedsRefresh 检查token是否需要刷新
// 基于 expires_at 字段判断是否在刷新窗口内
func (r *OpenAITokenRefresher) NeedsRefresh(account *Account, refreshWindow time.Duration) bool {
expiresAt := account.GetOpenAITokenExpiresAt()
expiresAt := account.GetCredentialAsTime("expires_at")
if expiresAt == nil {
return false
}
@@ -145,6 +151,17 @@ func (r *OpenAITokenRefresher) Refresh(ctx context.Context, account *Account) (m
go r.syncLinkedSoraAccounts(context.Background(), account.ID, newCredentials)
}
// 如果是 Sora 平台账号,同步到 sora2api不阻塞主流程
if account.Platform == PlatformSora && r.soraSyncService != nil {
syncAccount := *account
syncAccount.Credentials = newCredentials
go func() {
if err := r.soraSyncService.SyncAccount(context.Background(), &syncAccount); err != nil {
log.Printf("[TokenSync] 同步 Sora2API 失败: account_id=%d err=%v", syncAccount.ID, err)
}
}()
}
return newCredentials, nil
}
@@ -201,6 +218,13 @@ func (r *OpenAITokenRefresher) syncLinkedSoraAccounts(ctx context.Context, opena
}
}
// 2.3 同步到 sora2api如果配置
if r.soraSyncService != nil {
if err := r.soraSyncService.SyncAccount(ctx, &soraAccount); err != nil {
log.Printf("[TokenSync] 同步 sora2api 失败: account_id=%d err=%v", soraAccount.ID, err)
}
}
log.Printf("[TokenSync] 成功同步 Sora 账号 token: sora_account_id=%d openai_account_id=%d dual_table=%v",
soraAccount.ID, openaiAccountID, r.soraAccountRepo != nil)
}