haixunMaster/haixun-backend/internal/library/placement/discover_route.go

114 lines
3.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package placement
import (
"context"
"fmt"
)
// ShouldTryCrawlerFirst reports whether discover should attempt Playwright before Threads API
// to minimize official API calls when a browser session is available.
func ShouldTryCrawlerFirst(m MemberContext) bool {
if !m.AllowsCrawler || !m.BrowserConnected || m.CrawlerBlocked() {
return false
}
switch m.SearchSourceMode {
case SearchSourceCrawler, SearchSourceThreadsCrawler, SearchSourceBraveCrawler:
return true
case SearchSourceMixed, SearchSourceThreadsBrave:
return true
default:
return false
}
}
// CrawlerBlocked returns true when the mode is API-only or web-search-only.
func (m MemberContext) CrawlerBlocked() bool {
switch m.SearchSourceMode {
case SearchSourceThreads, SearchSourceBrave:
return true
default:
return false
}
}
// CrawlerFallbackAllowed returns true when crawler may be used after API/web search fails.
func (m MemberContext) CrawlerFallbackAllowed() bool {
if !m.AllowsCrawler || !m.BrowserConnected {
return false
}
switch m.SearchSourceMode {
case SearchSourceThreadsCrawler, SearchSourceBraveCrawler, SearchSourceMixed:
return true
default:
return false
}
}
// HasDiscoverPath reports whether at least one discover backend is configured and connected.
func (m MemberContext) HasDiscoverPath() bool {
if m.AllowsCrawler && m.BrowserConnected {
return true
}
if m.AllowsThreadsAPI && m.ApiConnected {
return true
}
if m.AllowsBrave && m.WebSearchAPIKey() != "" {
return true
}
return false
}
// DiscoverPathLabel summarizes the active routing for job progress UI.
func (m MemberContext) DiscoverPathLabel() string {
if ShouldTryCrawlerFirst(m) {
if m.AllowsThreadsAPI && m.ApiConnected {
return "爬蟲優先(不足再 API"
}
return "爬蟲"
}
if m.SearchSourceMode == SearchSourceCrawler {
return "爬蟲"
}
if m.AllowsThreadsAPI && m.ApiConnected {
return "Threads API"
}
if m.AllowsBrave {
return m.WebSearchProviderLabel()
}
return string(m.SearchSourceMode)
}
func discoverMissingPathError(m MemberContext) error {
switch m.SearchSourceMode {
case SearchSourceCrawler:
return fmt.Errorf("請先同步 Chrome Session 以使用爬蟲搜尋")
case SearchSourceThreadsCrawler, SearchSourceBraveCrawler:
if !m.BrowserConnected && !m.ApiConnected && m.WebSearchAPIKey() == "" {
return fmt.Errorf("請同步 Chrome Session 或完成 Threads API / Web Search 連線")
}
if !m.BrowserConnected {
return fmt.Errorf("爬蟲優先模式建議先同步 Chrome Session亦可改用僅 Threads API")
}
return fmt.Errorf("請完成 Threads API 或 Web Search 連線作為備援")
case SearchSourceThreads, SearchSourceThreadsBrave:
return fmt.Errorf("請先完成 Threads API 連線")
case SearchSourceBrave:
return fmt.Errorf("請在設定頁設定 %s Search API key", m.WebSearchProviderLabel())
case SearchSourceMixed:
return fmt.Errorf("請同步 Chrome Session、完成 Threads API 或設定 Web Search API key 至少一項")
default:
return fmt.Errorf("目前搜尋來源模式無可用管道:%s", m.SearchSourceMode)
}
}
func runCrawlerDiscover(ctx context.Context, req DiscoverRequest) ([]DiscoverPost, error) {
if req.Crawler == nil {
return nil, fmt.Errorf("crawler search not configured")
}
keyword := CrawlerKeywordFromQuery(req.Query, req.Keyword)
if keyword == "" {
return nil, fmt.Errorf("crawler keyword is empty")
}
return req.Crawler(ctx, req.Member, keyword, req.Limit)
}