package placement import ( "context" "strings" libthreads "haixun-backend/internal/library/threadsapi" ) type ReplyMediaResolveInput struct { AccessToken string StorageState string ExternalID string Permalink string HintText string } // ResolveReplyMediaWithFallback resolves a Threads reply target id via API and permalink scraping. func ResolveReplyMediaWithFallback(ctx context.Context, in ReplyMediaResolveInput) (string, error) { return resolveReplyMedia(ctx, in, false) } // ResolveReplyMediaForPublish prefers fast permalink scraping, then API lookup. func ResolveReplyMediaForPublish(ctx context.Context, in ReplyMediaResolveInput) (string, error) { return resolveReplyMedia(ctx, in, true) } func resolveReplyMedia(ctx context.Context, in ReplyMediaResolveInput, publishFastPath bool) (string, error) { if libthreads.IsNumericMediaID(in.ExternalID) { return strings.TrimSpace(in.ExternalID), nil } permalink := strings.TrimSpace(in.Permalink) if publishFastPath && permalink != "" { if scraped, sErr := RunResolveMediaFromPermalink(ctx, permalink, in.StorageState); sErr == nil && libthreads.IsNumericMediaID(scraped) { return scraped, nil } } client := libthreads.NewClient(in.AccessToken) id, err := client.ResolveReplyMedia(ctx, libthreads.ResolveReplyMediaInput{ ExternalID: in.ExternalID, Permalink: in.Permalink, HintText: in.HintText, }) if err == nil && libthreads.IsNumericMediaID(id) { return id, nil } if !publishFastPath && permalink != "" { if scraped, sErr := RunResolveMediaFromPermalink(ctx, permalink, in.StorageState); sErr == nil && libthreads.IsNumericMediaID(scraped) { return scraped, nil } } return "", err }