search.go 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. package wikidata
  2. import (
  3. "notabug.org/apiote/amuse/network"
  4. "encoding/json"
  5. "math"
  6. "net/http"
  7. "net/url"
  8. "strconv"
  9. "strings"
  10. "notabug.org/apiote/gott"
  11. )
  12. type SearchResults struct {
  13. Results []struct {
  14. Id string
  15. Type string
  16. Uri string
  17. Label string
  18. Description string
  19. Image []string
  20. ImagePath string
  21. }
  22. }
  23. type WikidataQuery struct {
  24. query string
  25. language string
  26. page int64
  27. }
  28. func createSearchQuery(args ...interface{}) (interface{}, error) {
  29. query := args[0].(*WikidataQuery)
  30. result := args[1].(*network.Result)
  31. client := &http.Client{}
  32. url := "https://inventaire.io/api/search?types=works|series&lang=" + query.language + "&search=" + url.QueryEscape(query.query) + "&limit=" + strconv.FormatInt(8*(query.page+1), 10)
  33. request, err := http.NewRequest("GET", url, nil)
  34. result.Client = client
  35. result.Request = request
  36. return gott.Tuple(args), err
  37. }
  38. func unmarshalSearchResults(args ...interface{}) (interface{}, error) {
  39. query := args[0].(*WikidataQuery)
  40. result := args[1].(*network.Result)
  41. results := &SearchResults{}
  42. err := json.Unmarshal(result.Body, results)
  43. fisrtOnPage := int(query.page * 8)
  44. if len(results.Results) > fisrtOnPage {
  45. firstOnNext := math.Min(float64(query.page+1)*8, float64(len(results.Results)))
  46. results.Results = results.Results[fisrtOnPage:int(firstOnNext)]
  47. }
  48. result.Result = results
  49. return gott.Tuple(args), err
  50. }
  51. func parseImageUri(args ...interface{}) interface{} {
  52. results := args[1].(*network.Result).Result.(*SearchResults)
  53. for i, result := range results.Results {
  54. if len(result.Image) > 0 {
  55. if strings.Index(result.Image[0], ".") != -1 {
  56. result.ImagePath = "https://commons.wikimedia.org/wiki/Special:FilePath/" + result.Image[0] + "?width=154"
  57. } else {
  58. result.ImagePath = "https://inventaire.io/img/entities/154x154/" + result.Image[0]
  59. }
  60. results.Results[i] = result
  61. }
  62. }
  63. return gott.Tuple(args)
  64. }
  65. func Search(query, language string, page int64) (*SearchResults, error) {
  66. results, err := gott.
  67. NewResult(gott.Tuple{&WikidataQuery{query, language, page}, &network.Result{}}).
  68. Bind(createSearchQuery).
  69. Bind(network.DoRequest).
  70. Bind(network.HandleRequestError).
  71. Bind(network.ReadResponse).
  72. Bind(unmarshalSearchResults).
  73. Map(parseImageUri).
  74. Finish()
  75. if err != nil {
  76. if _, ok := err.(network.HttpError); ok {
  77. return &SearchResults{}, nil
  78. }
  79. return &SearchResults{}, err
  80. } else {
  81. return results.(gott.Tuple)[1].(*network.Result).Result.(*SearchResults), nil
  82. }
  83. }