Renamed the Go module to align with the updated repository path for better clarity and organization. This ensures consistency across the project and prevents potential import conflicts.
		
			
				
	
	
		
			83 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			83 lines
		
	
	
		
			1.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package search
 | |
| 
 | |
| import (
 | |
| 	"context"
 | |
| 	"fmt"
 | |
| 	"time"
 | |
| 
 | |
| 	"gitea.stevedudenhoeffer.com/steve/answer/pkg/cache"
 | |
| 	"gitea.stevedudenhoeffer.com/steve/go-extractor"
 | |
| 	"gitea.stevedudenhoeffer.com/steve/go-extractor/sites/duckduckgo"
 | |
| )
 | |
| 
 | |
| type duckDuckGo struct {
 | |
| 	Cache   cache.Cache
 | |
| 	Browser extractor.Browser
 | |
| }
 | |
| 
 | |
| func NewDuckDuckGo(c cache.Cache) (Search, error) {
 | |
| 	timeout := 60 * time.Second
 | |
| 	browser, err := extractor.NewPlayWrightBrowser(extractor.PlayWrightBrowserOptions{Timeout: &timeout})
 | |
| 
 | |
| 	if err != nil {
 | |
| 		return nil, fmt.Errorf("failed to create browser: %w", err)
 | |
| 	}
 | |
| 
 | |
| 	return duckDuckGo{
 | |
| 		Cache:   c,
 | |
| 		Browser: browser,
 | |
| 	}, nil
 | |
| }
 | |
| 
 | |
| var _ Search = duckDuckGo{}
 | |
| 
 | |
| func (d duckDuckGo) Search(ctx context.Context, search string) ([]Result, error) {
 | |
| 	var res []Result
 | |
| 
 | |
| 	key := "duckduckgo:" + search
 | |
| 
 | |
| 	err := d.Cache.GetJSON(key, &res)
 | |
| 
 | |
| 	if err == nil {
 | |
| 		return res, nil
 | |
| 	}
 | |
| 
 | |
| 	results, err := d.searchDuckDuckGo(ctx, search)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	for _, r := range results {
 | |
| 		res = append(res, Result{
 | |
| 			Title:       r.Title,
 | |
| 			URL:         r.URL,
 | |
| 			Description: r.Description,
 | |
| 		})
 | |
| 	}
 | |
| 
 | |
| 	_ = d.Cache.SetJSON(key, res)
 | |
| 
 | |
| 	return res, nil
 | |
| }
 | |
| 
 | |
| func (d duckDuckGo) searchDuckDuckGo(ctx context.Context, search string) ([]Result, error) {
 | |
| 	cfg := duckduckgo.DefaultConfig
 | |
| 
 | |
| 	r, err := cfg.Search(ctx, d.Browser, search)
 | |
| 	if err != nil {
 | |
| 		return nil, err
 | |
| 	}
 | |
| 
 | |
| 	res := make([]Result, len(r))
 | |
| 
 | |
| 	for i, v := range r {
 | |
| 		res[i] = Result{
 | |
| 			URL:         v.URL,
 | |
| 			Title:       v.Title,
 | |
| 			Description: v.Description,
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	return res, nil
 | |
| }
 |