package job import ( "context" "fmt" "strings" libthreads "haixun-backend/internal/library/threadsapi" jobdom "haixun-backend/internal/model/job/domain/usecase" threadsaccountdomain "haixun-backend/internal/model/threads_account/domain/usecase" ) type RefreshThreadsTokenDeps struct { Jobs jobdom.UseCase ThreadsAccount threadsaccountdomain.UseCase } func RegisterRefreshThreadsTokenHandler(runner *Runner, deps RefreshThreadsTokenDeps) { if runner == nil { return } runner.RegisterStepHandler("refresh", func(ctx context.Context, step StepContext) error { return runRefreshThreadsToken(ctx, step, deps) }) } func runRefreshThreadsToken(ctx context.Context, step StepContext, deps RefreshThreadsTokenDeps) error { payload := step.Run.Payload tenantID, ownerUID := runActorFromPayload(payload, step.Run) accountID := strings.TrimSpace(stringField(payload, "account_id")) if tenantID == "" || ownerUID == "" || accountID == "" { return fmt.Errorf("refresh-threads-token payload missing tenant_id, owner_uid, or account_id") } cred, err := deps.ThreadsAccount.ResolveMemberThreadsPublishCredential(ctx, tenantID, ownerUID) if err != nil { return fmt.Errorf("resolve publish credential: %w", err) } if cred == nil || cred.AccessToken == "" { return fmt.Errorf("no access token found for account %s", accountID) } result, err := libthreads.RefreshAccessToken(ctx, cred.AccessToken) if err != nil { return fmt.Errorf("refresh token: %w", err) } expiresAt := libthreads.NsFromNow(result.ExpiresIn) if _, err := deps.ThreadsAccount.SaveAPIAccessToken(ctx, accountID, result.AccessToken, expiresAt); err != nil { return fmt.Errorf("save refreshed token: %w", err) } _, err = deps.Jobs.CompleteRun(ctx, jobdom.CompleteRunRequest{ JobID: step.JobID, WorkerID: step.WorkerID, Result: map[string]any{ "account_id": accountID, "expires_at": expiresAt, "token_short": result.AccessToken[:min(len(result.AccessToken), 8)] + "...", }, }) return err }