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) }