mb.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. package mb
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "net/http"
  6. "sort"
  7. "time"
  8. )
  9. const (
  10. apiURI = "https://musicbrainz.org/ws/2"
  11. artistSearchEndpoint = "artist?query"
  12. )
  13. //MB holds the http client and the search results
  14. type MB struct {
  15. Client http.Client
  16. artist artistSearch
  17. }
  18. //NewMusicBrainzSearch returns a new Search object
  19. func NewMusicBrainzSearch() MB {
  20. var mbSearch MB
  21. timeout := time.Duration(10 * time.Second)
  22. mbSearch.Client = http.Client{Timeout: timeout}
  23. return mbSearch
  24. }
  25. //GetArtistName get the artist with the highest score on the search
  26. func (m MB) GetArtistName() (string, error) {
  27. if len(m.artist.Artists) == 0 {
  28. return "", fmt.Errorf("could not find any artist")
  29. }
  30. return m.artist.Artists[0].Name, nil
  31. }
  32. //SearchForArtist return a list of artists using `query` as parameter if none found returns error
  33. func (m *MB) SearchForArtist(query string) error {
  34. uri := fmt.Sprintf("%s/%s=%s", apiURI, artistSearchEndpoint, query)
  35. req, err := http.NewRequest(
  36. "GET",
  37. uri,
  38. nil)
  39. req.Header.Set(
  40. "User-Agent",
  41. "Go Application Development: Create spotify playlist based on artist")
  42. req.Header.Set("Content-Type", "application/json")
  43. req.Header.Set("Accept", "application/json")
  44. if err != nil {
  45. fmt.Printf("error creating request\n%v", err)
  46. return err
  47. }
  48. resp, err := m.Client.Do(req)
  49. if err != nil {
  50. fmt.Printf("error opening request\n%v", err)
  51. return err
  52. }
  53. defer resp.Body.Close()
  54. if err != nil {
  55. fmt.Printf("could not read body\n%v", err)
  56. return err
  57. }
  58. err = json.NewDecoder(resp.Body).Decode(&m.artist)
  59. if err != nil {
  60. fmt.Printf("could not decode body\n%v", err)
  61. return err
  62. }
  63. if m.artist.Count == 0 {
  64. return fmt.Errorf("cound not found artist: %s", query)
  65. }
  66. return nil
  67. }
  68. //GetArtistTags returns the tags in order of relevance of the current artist
  69. func (m MB) GetArtistTags() []Tags {
  70. var t []Tags
  71. for _, elem := range m.artist.Artists[0].Tags {
  72. if int(elem.Count) > 0 {
  73. t = append(t, elem)
  74. }
  75. }
  76. sort.Sort(ByInverseCount(t))
  77. return t
  78. }
  79. type artistSearch struct {
  80. Created time.Time `json:"created"`
  81. Count int `json:"count"`
  82. Offset int `json:"offset"`
  83. Artists []artists `json:"artists"`
  84. }
  85. type area struct {
  86. ID string `json:"id"`
  87. Type string `json:"type"`
  88. TypeID string `json:"type-id"`
  89. Name string `json:"name"`
  90. SortName string `json:"sort-name"`
  91. LifeSpan struct {
  92. Ended interface{} `json:"ended"`
  93. } `json:"life-span"`
  94. }
  95. type alias struct {
  96. SortName string `json:"sort-name"`
  97. TypeID string `json:"type-id,omitempty"`
  98. Name string `json:"name"`
  99. Locale interface{} `json:"locale"`
  100. Type string `json:"type"`
  101. Primary interface{} `json:"primary"`
  102. BeginDate interface{} `json:"begin-date"`
  103. EndDate interface{} `json:"end-date"`
  104. }
  105. type artists struct {
  106. ID string `json:"id"`
  107. Type string `json:"type,omitempty"`
  108. TypeID string `json:"type-id,omitempty"`
  109. Score int `json:"score"`
  110. Name string `json:"name"`
  111. SortName string `json:"sort-name"`
  112. Country string `json:"country,omitempty"`
  113. Area area `json:"area,omitempty"`
  114. BeginArea struct {
  115. ID string `json:"id"`
  116. Type string `json:"type"`
  117. TypeID string `json:"type-id"`
  118. Name string `json:"name"`
  119. SortName string `json:"sort-name"`
  120. LifeSpan struct {
  121. Ended interface{} `json:"ended"`
  122. } `json:"life-span"`
  123. } `json:"begin-area,omitempty"`
  124. Isnis []string `json:"isnis,omitempty"`
  125. LifeSpan struct {
  126. Begin string `json:"begin"`
  127. Ended interface{} `json:"ended"`
  128. } `json:"life-span,omitempty"`
  129. Aliases []alias `json:"aliases,omitempty"`
  130. Tags []Tags `json:"tags,omitempty"`
  131. Disambiguation string `json:"disambiguation,omitempty"`
  132. }
  133. //Tags represent Artist tags (eg. Rock, Punk, Late 2000s)
  134. type Tags struct {
  135. Count int `json:"count"`
  136. Name string `json:"name"`
  137. }
  138. //ByInverseCount return the tags in relevance order
  139. type ByInverseCount []Tags
  140. func (t ByInverseCount) Len() int { return len(t) }
  141. func (t ByInverseCount) Less(i, j int) bool { return t[i].Count >= t[j].Count }
  142. func (t ByInverseCount) Swap(i, j int) { t[i], t[j] = t[j], t[i] }