package main import ( "encoding/json" "fmt" "net/http" "net/url" "time" ) type LibreXResult struct { Title string `json:"title"` URL string `json:"url"` Description string `json:"description"` } type LibreXResponse []LibreXResult func PerformLibreXTextSearch(query, safe, lang string, page int) ([]TextSearchResult, time.Duration, error) { startTime := time.Now() // LibreX uses offset instead of page (starting at 0) pageOffset := (page - 1) * 10 // Generate User-Agent userAgent, err := GetUserAgent("librex-text-search") if err != nil { return nil, 0, err } var allResults []TextSearchResult for _, domain := range config.LibreXInstances { searchURL := fmt.Sprintf("https://%s/api.php?q=%s&p=%d&t=0", domain, url.QueryEscape(query), pageOffset, ) req, err := http.NewRequest("GET", searchURL, nil) if err != nil { printWarn("failed to create request for domain %s: %v", domain, err) continue } req.Header.Set("User-Agent", userAgent) resp, err := DoMetaProxyRequest(req) if err != nil { return nil, 0, fmt.Errorf("failed to do meta-request: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { printWarn("unexpected status code from %s: %d", domain, resp.StatusCode) continue } var librexResp LibreXResponse if err := json.NewDecoder(resp.Body).Decode(&librexResp); err != nil { printWarn("error decoding response from %s: %v", domain, err) continue } // Accumulate results from this instance for _, item := range librexResp { allResults = append(allResults, TextSearchResult{ URL: item.URL, Header: item.Title, Description: item.Description, Source: "LibreX", }) } } duration := time.Since(startTime) if len(allResults) == 0 { return nil, duration, fmt.Errorf("no results found from any LibreX instance") } return allResults, duration, nil }