sub2api/backend/internal/service/windsurf_token_provider.go
win 9156585a23 chore: gofmt/goimports 后处理
合并上游后统一运行 gofmt/goimports,消除排序差异与空行不一致。
2026-04-24 11:52:53 +08:00

115 lines
3.0 KiB
Go

package service
import (
"context"
"fmt"
"time"
"github.com/Wei-Shaw/sub2api/internal/config"
"github.com/Wei-Shaw/sub2api/internal/domain"
"github.com/Wei-Shaw/sub2api/internal/pkg/windsurf"
)
type WindsurfTokenProvider struct {
cfg config.WindsurfConfig
accountRepo AccountRepository
proxyRepo ProxyRepository
authClient *windsurf.AuthClient
}
func NewWindsurfTokenProvider(
cfg config.WindsurfConfig,
accountRepo AccountRepository,
proxyRepo ProxyRepository,
authClient *windsurf.AuthClient,
) *WindsurfTokenProvider {
return &WindsurfTokenProvider{
cfg: cfg,
accountRepo: accountRepo,
proxyRepo: proxyRepo,
authClient: authClient,
}
}
type WindsurfToken struct {
APIKey string
ProxyURL string
AccountID int64
Tier string
LSBinding WindsurfLSBinding
}
func (p *WindsurfTokenProvider) GetToken(ctx context.Context, accountID int64) (*WindsurfToken, error) {
account, err := p.accountRepo.GetByID(ctx, accountID)
if err != nil {
return nil, fmt.Errorf("get account: %w", err)
}
if account.Platform != domain.PlatformWindsurf {
return nil, fmt.Errorf("account %d is not a windsurf account", accountID)
}
creds := LoadWindsurfCredentials(account.Credentials)
if creds.APIKey == "" {
return nil, fmt.Errorf("account %d has no api_key", accountID)
}
proxyURL := ""
if account.ProxyID != nil {
proxy, err := p.proxyRepo.GetByID(ctx, *account.ProxyID)
if err == nil {
proxyURL = proxy.URL()
}
}
if creds.NeedsRefresh(p.cfg.Refresh.RefreshBeforeExpiry) {
if refreshErr := p.refreshInline(ctx, account, &creds, proxyURL); refreshErr != nil {
if !creds.IsExpired() {
extra := LoadWindsurfExtra(account.Extra)
return &WindsurfToken{
APIKey: creds.APIKey,
ProxyURL: proxyURL,
AccountID: accountID,
Tier: creds.Tier,
LSBinding: extra.LSBinding,
}, nil
}
return nil, fmt.Errorf("token expired and refresh failed: %w", refreshErr)
}
}
extra := LoadWindsurfExtra(account.Extra)
return &WindsurfToken{
APIKey: creds.APIKey,
ProxyURL: proxyURL,
AccountID: accountID,
Tier: creds.Tier,
LSBinding: extra.LSBinding,
}, nil
}
func (p *WindsurfTokenProvider) refreshInline(ctx context.Context, account *Account, creds *WindsurfCredentials, proxyURL string) error {
if creds.AuthMethod != "firebase" || creds.RefreshToken == "" {
return fmt.Errorf("cannot refresh: auth_method=%s", creds.AuthMethod)
}
result, err := p.authClient.RefreshFirebaseToken(ctx, creds.RefreshToken, proxyURL)
if err != nil {
return err
}
creds.IDToken = result.IDToken
creds.RefreshToken = result.RefreshToken
creds.ExpiresAt = time.Now().Add(time.Duration(result.ExpiresIn) * time.Second).Format(time.RFC3339)
creds.LastRefreshAt = time.Now().Format(time.RFC3339)
regResult, err := p.authClient.ReRegisterWithCodeium(ctx, result.IDToken, proxyURL)
if err == nil {
creds.APIKey = regResult.APIKey
creds.LastReregisterAt = time.Now().Format(time.RFC3339)
}
account.Credentials = StoreWindsurfCredentials(*creds)
return p.accountRepo.Update(ctx, account)
}