package placement import "strings" // SearchSourceMode mirrors the legacy Next.js search source options per Threads account. type SearchSourceMode string const ( SearchSourceMixed SearchSourceMode = "mixed" SearchSourceThreads SearchSourceMode = "threads" SearchSourceBrave SearchSourceMode = "brave" SearchSourceCrawler SearchSourceMode = "crawler" SearchSourceThreadsBrave SearchSourceMode = "threads_brave" SearchSourceThreadsCrawler SearchSourceMode = "threads_crawler" SearchSourceBraveCrawler SearchSourceMode = "brave_crawler" ) const DefaultSearchSourceMode = SearchSourceMixed func ParseSearchSourceMode(raw string) SearchSourceMode { switch SearchSourceMode(strings.TrimSpace(raw)) { case SearchSourceMixed, SearchSourceThreads, SearchSourceBrave, SearchSourceCrawler, SearchSourceThreadsBrave, SearchSourceThreadsCrawler, SearchSourceBraveCrawler: return SearchSourceMode(strings.TrimSpace(raw)) default: return DefaultSearchSourceMode } } func ModeAllowsThreadsAPI(mode SearchSourceMode) bool { switch mode { case SearchSourceMixed, SearchSourceThreads, SearchSourceThreadsBrave, SearchSourceThreadsCrawler: return true default: return false } } func ModeAllowsBrave(mode SearchSourceMode) bool { switch mode { case SearchSourceMixed, SearchSourceBrave, SearchSourceThreadsBrave, SearchSourceBraveCrawler: return true default: return false } } func ModeAllowsCrawler(mode SearchSourceMode) bool { switch mode { case SearchSourceMixed, SearchSourceCrawler, SearchSourceThreadsCrawler, SearchSourceBraveCrawler: return true default: return false } } // MemberNeedsWebSearchKey reports whether placement scan should require a web search API key. func MemberNeedsWebSearchKey(ctx MemberContext) bool { if !ctx.AllowsBrave || ctx.DevMode { return false } switch ctx.SearchSourceMode { case SearchSourceBrave, SearchSourceThreadsBrave: return true case SearchSourceThreads: return false default: return ctx.AllowsBrave } } // MemberNeedsBraveKey is deprecated; use MemberNeedsWebSearchKey. func MemberNeedsBraveKey(ctx MemberContext) bool { return MemberNeedsWebSearchKey(ctx) } // WithoutCrawler returns a mode that never uses Playwright, for formal API-only routing. func WithoutCrawler(mode SearchSourceMode) SearchSourceMode { switch mode { case SearchSourceMixed, SearchSourceThreadsCrawler, SearchSourceBraveCrawler: return SearchSourceThreadsBrave case SearchSourceCrawler: return SearchSourceThreads default: return mode } }