/sources/duckduckgo/duckduckgo.go

https://github.com/shivylp/radium · Go · 73 lines · 54 code · 15 blank · 4 comment · 11 complexity · 7e3ef5705d2db331b690f227a948a514 MD5 · raw file

  1. package duckduckgo
  2. import (
  3. "context"
  4. "encoding/json"
  5. "net/http"
  6. "net/url"
  7. "github.com/spy16/radium"
  8. )
  9. const ddgURL = "https://api.duckduckgo.com"
  10. // New initializes a duckduckgo based radium source implementation.
  11. func New() *DuckDuckGo {
  12. return &DuckDuckGo{}
  13. }
  14. // DuckDuckGo implements radium.Source interface using DuckDuckGo search
  15. // engine project.
  16. type DuckDuckGo struct {
  17. }
  18. // Search makes request to duckduckgo instant answers API to fetch the abstract.
  19. func (ddg DuckDuckGo) Search(ctx context.Context, query radium.Query) ([]radium.Article, error) {
  20. req, err := makeDDGRequest(ctx, query)
  21. if err != nil {
  22. return nil, err
  23. }
  24. cl := http.Client{}
  25. resp, err := cl.Do(req)
  26. if err != nil {
  27. return nil, err
  28. }
  29. defer resp.Body.Close()
  30. ires := instantResult{}
  31. if err := json.NewDecoder(resp.Body).Decode(&ires); err != nil {
  32. return nil, err
  33. }
  34. result := radium.Article{}
  35. result.Title = query.Text
  36. result.Content = ires.Abstract
  37. return []radium.Article{result}, nil
  38. }
  39. func makeDDGRequest(ctx context.Context, query radium.Query) (*http.Request, error) {
  40. pu, err := url.Parse(ddgURL)
  41. if err != nil {
  42. return nil, err
  43. }
  44. params := pu.Query()
  45. params.Set("q", query.Text)
  46. params.Set("format", "json")
  47. pu.RawQuery = params.Encode()
  48. req, err := http.NewRequest(http.MethodGet, pu.String(), nil)
  49. if err != nil {
  50. return nil, err
  51. }
  52. req.WithContext(ctx)
  53. return req, nil
  54. }
  55. type instantResult struct {
  56. Abstract string `json:"AbstractText"`
  57. AbstractURL string `json:"AbstractURL"`
  58. }