u
This commit is contained in:
		
							
								
								
									
										109
									
								
								endpoint/search.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								endpoint/search.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,109 @@ | ||||
| package endpoint | ||||
|  | ||||
| import ( | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"net/http" | ||||
| 	"net/url" | ||||
| 	"strings" | ||||
| 	"time" | ||||
|  | ||||
| 	pb "github.com/bestnite/go-igdb/proto" | ||||
|  | ||||
| 	"github.com/PuerkitoBio/goquery" | ||||
| 	"github.com/bestnite/go-flaresolverr" | ||||
| 	"google.golang.org/protobuf/proto" | ||||
| ) | ||||
|  | ||||
| var webSearchCFCookies struct { | ||||
| 	cookies []*http.Cookie | ||||
| 	expires time.Time | ||||
| } | ||||
|  | ||||
| type Search struct { | ||||
| 	BaseEndpoint | ||||
| 	flaresolverr *flaresolverr.Flaresolverr | ||||
| } | ||||
|  | ||||
| func (a *Search) Search(query string) ([]*pb.Search, error) { | ||||
| 	resp, err := a.request("https://api.igdb.com/v4/search.pb", query) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("failed to request: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	data := pb.SearchResult{} | ||||
| 	if err = proto.Unmarshal(resp.Body(), &data); err != nil { | ||||
| 		return nil, fmt.Errorf("failed to unmarshal: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	if len(data.Searches) == 0 { | ||||
| 		return nil, fmt.Errorf("no results: %s", query) | ||||
| 	} | ||||
|  | ||||
| 	return data.Searches, nil | ||||
| } | ||||
|  | ||||
| func (a *Search) getFlaresolverr() (*flaresolverr.Flaresolverr, error) { | ||||
| 	if a.flaresolverr == nil { | ||||
| 		return nil, fmt.Errorf("flaresolverr is not initialized") | ||||
| 	} | ||||
| 	return a.flaresolverr, nil | ||||
| } | ||||
|  | ||||
| func (a *Search) WebSearchGameIDs(name string) ([]uint64, error) { | ||||
| 	params := url.Values{} | ||||
| 	params.Add("q", name) | ||||
| 	params.Add("utf8", "✓") | ||||
| 	Url := fmt.Sprintf("%s?%s", "https://www.igdb.com/search", params.Encode()) | ||||
|  | ||||
| 	f, err := a.getFlaresolverr() | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("failed to get flaresolverr: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	var respBody io.Reader | ||||
| 	if webSearchCFCookies.cookies == nil || time.Now().After(webSearchCFCookies.expires) { | ||||
| 		resp, err := f.GetV1(Url, nil) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("failed to web search: %s: %w", name, err) | ||||
| 		} | ||||
| 		webSearchCFCookies.cookies = resp.Solution.Cookies | ||||
| 		webSearchCFCookies.expires = time.Now().Add(3 * time.Hour) | ||||
| 		respBody = strings.NewReader(resp.Solution.Response) | ||||
| 	} else if time.Now().Before(webSearchCFCookies.expires) { | ||||
| 		resp, err := f.SimulateGet(Url, &flaresolverr.SimulateOptions{ | ||||
| 			HttpCookies: webSearchCFCookies.cookies, | ||||
| 		}) | ||||
| 		if err != nil { | ||||
| 			return nil, fmt.Errorf("failed to search IGDB ID: %s: %w", name, err) | ||||
| 		} | ||||
| 		respBody = strings.NewReader(resp.Body) | ||||
| 	} | ||||
|  | ||||
| 	doc, err := goquery.NewDocumentFromReader(respBody) | ||||
| 	if err != nil { | ||||
| 		return nil, fmt.Errorf("failed to parse IGDB web search response: %w", err) | ||||
| 	} | ||||
| 	selection := doc.Find("script[data-component-name='GameEntries']") | ||||
| 	if selection.Length() == 0 { | ||||
| 		return nil, fmt.Errorf("no search results found for: %s", name) | ||||
| 	} | ||||
| 	innerJson := selection.First().Text() | ||||
| 	data := struct { | ||||
| 		Games []struct { | ||||
| 			Id   uint64 `json:"id"` | ||||
| 			Name string `json:"name"` | ||||
| 		} `json:"games"` | ||||
| 	}{} | ||||
| 	if err := json.Unmarshal([]byte(innerJson), &data); err != nil { | ||||
| 		return nil, fmt.Errorf("failed to unmarshal IGDB web search response: %w", err) | ||||
| 	} | ||||
|  | ||||
| 	ids := make([]uint64, len(data.Games)) | ||||
| 	for i, game := range data.Games { | ||||
| 		ids[i] = game.Id | ||||
| 	} | ||||
|  | ||||
| 	return ids, nil | ||||
| } | ||||
		Reference in New Issue
	
	Block a user