730 lines
20 KiB
Go
730 lines
20 KiB
Go
package musicbrainz_org
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"git.gammaspectra.live/S.O.N.G/METANOIA/metadata"
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
var baseURL = "https://musicbrainz.org/"
|
|
var baseAPIURL = "https://musicbrainz.org/ws/2/"
|
|
var baseCoverAPIURL = "https://coverartarchive.org/"
|
|
|
|
type Source struct {
|
|
client *metadata.CachingClient
|
|
}
|
|
|
|
func NewSource() *Source {
|
|
s := &Source{}
|
|
s.client = metadata.NewCachingClient(s.GetURL(), time.Second)
|
|
return s
|
|
}
|
|
|
|
func (s *Source) GetName() string {
|
|
return "MusicBrainz"
|
|
}
|
|
|
|
func (s *Source) GetURL() string {
|
|
return baseURL
|
|
}
|
|
|
|
func (s *Source) GetLicense() metadata.License {
|
|
return metadata.License{
|
|
//Most core data is CC0
|
|
Code: metadata.CC_BY_NC_SA_30,
|
|
URL: baseURL + "doc/About/Data_License",
|
|
Attribution: fmt.Sprintf("%s (%s)", s.GetName(), s.GetURL()),
|
|
}
|
|
}
|
|
|
|
func (s *Source) FindByTOC(toc metadata.TOC) []*metadata.Album {
|
|
return s.FindByDiscIDTOC(toc.GetDiscID(), toc)
|
|
}
|
|
|
|
func (s *Source) FindByDiscID(discId metadata.DiscID) []*metadata.Album {
|
|
return s.FindByDiscIDTOC(discId, metadata.TOC{})
|
|
}
|
|
func (s *Source) FindByDiscIDTOC(discId metadata.DiscID, toc metadata.TOC) (albums []*metadata.Album) {
|
|
|
|
uri, _ := url.Parse(baseAPIURL)
|
|
uri.Path += "discid/" + string(discId)
|
|
|
|
query := uri.Query()
|
|
if len(toc) > 0 {
|
|
query.Add("toc", fmt.Sprintf("1 %s", toc.MusicBrainzString()))
|
|
}
|
|
query.Add("fmt", "json")
|
|
query.Add("cdstubs", "no")
|
|
query.Add("media-format", "all")
|
|
|
|
uri.RawQuery = query.Encode()
|
|
response, err := s.client.Request(&http.Request{
|
|
Method: "GET",
|
|
URL: uri,
|
|
}, time.Hour*24*14)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
body, err := ioutil.ReadAll(response.Body)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
type SearchResult struct {
|
|
Sectors int `json:"sectors"`
|
|
Id string `json:"id"`
|
|
Offsets []int `json:"offsets"`
|
|
OffsetCount int `json:"offset-count"`
|
|
Releases []struct {
|
|
Id string `json:"id"`
|
|
Title string `json:"title"`
|
|
Date string `json:"date"`
|
|
Country string `json:"country"`
|
|
Media []mediaEntry `json:"media"`
|
|
} `json:"releases"`
|
|
}
|
|
|
|
result := &SearchResult{}
|
|
|
|
err = json.Unmarshal(body, result)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
for _, r := range result.Releases {
|
|
album := s.GetRelease(r.Id)
|
|
if album != nil {
|
|
albums = append(albums, album)
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s *Source) FindByAlbumNames(names []metadata.Name) []*metadata.Album {
|
|
query := ""
|
|
for _, v := range names {
|
|
if len(query) == 0 {
|
|
query += fmt.Sprintf("release:(%q) OR releaseaccent:(%q)", v.Name, v.Name)
|
|
} else {
|
|
query += fmt.Sprintf("OR release:(%q) OR releaseaccent:(%q)", v.Name, v.Name)
|
|
}
|
|
}
|
|
|
|
return s.FindQueryArguments(query)
|
|
}
|
|
|
|
func (s *Source) FindByCatalogNumber(catalog metadata.CatalogNumber) []*metadata.Album {
|
|
|
|
query := fmt.Sprintf("catno:(%q)", string(catalog))
|
|
|
|
if strings.Index(string(catalog), "-") != -1 {
|
|
query += fmt.Sprintf("OR catno:(%q)", strings.Replace(string(catalog), "-", "", -1))
|
|
}
|
|
|
|
return s.FindQueryArguments(query)
|
|
|
|
}
|
|
|
|
type tagEntry struct {
|
|
Count int `json:"count"`
|
|
Name string `json:"name"`
|
|
}
|
|
type ratingEntry struct {
|
|
VotesCount int `json:"votes-count"`
|
|
Value *float64 `json:"value"`
|
|
}
|
|
type workEntry struct {
|
|
Id string `json:"id"`
|
|
Rating ratingEntry `json:"rating"`
|
|
Language string `json:"language"`
|
|
Title string `json:"title"`
|
|
Disambiguation string `json:"disambiguation"`
|
|
Languages []string `json:"languages"`
|
|
Attributes []string `json:"attributes"`
|
|
Relations []relationEntry `json:"relations"`
|
|
}
|
|
type urlEntry struct {
|
|
Id string `json:"id"`
|
|
Resource string `json:"resource"`
|
|
}
|
|
type eventEntry struct {
|
|
Id string `json:"id"`
|
|
Type string `json:"type"`
|
|
Name string `json:"name"`
|
|
Disambiguation string `json:"disambiguation"`
|
|
}
|
|
type artistEntry struct {
|
|
Id string `json:"id"`
|
|
Name string `json:"name"`
|
|
SortName string `json:"sort-name"`
|
|
Disambiguation string `json:"disambiguation"`
|
|
Type string `json:"type"`
|
|
Rating ratingEntry `json:"rating"`
|
|
Aliases []aliasEntry `json:"aliases"`
|
|
}
|
|
type artistCreditEntry struct {
|
|
Name string `json:"name"`
|
|
Artist artistEntry `json:"artist"`
|
|
JoinPhrase string `json:"joinphrase"`
|
|
}
|
|
type relationEntry struct {
|
|
Id string `json:"id"`
|
|
Attributes []string `json:"attributes"`
|
|
TargetCredit string `json:"target-credit"`
|
|
Direction string `json:"direction"`
|
|
TargetType string `json:"target-type"`
|
|
SourceCredit string `json:"source-credit"`
|
|
Type string `json:"type"`
|
|
Artist *artistEntry `json:"artist"`
|
|
Work *workEntry `json:"work"`
|
|
Event *eventEntry `json:"event"`
|
|
Recording *recordingEntry `json:"recording"`
|
|
Url *urlEntry `json:"url"`
|
|
}
|
|
|
|
type recordingEntry struct {
|
|
Id string `json:"id"`
|
|
Video bool `json:"video"`
|
|
Title string `json:"title"`
|
|
Length int `json:"length"`
|
|
FirstReleaseDate string `json:"first-release-date"`
|
|
Rating ratingEntry `json:"rating"`
|
|
Relations []relationEntry `json:"relations"`
|
|
ISRCS []string `json:"isrcs"`
|
|
ArtistCredit []artistCreditEntry `json:"artist-credit"`
|
|
//TODO Aliases
|
|
}
|
|
|
|
type trackEntry struct {
|
|
Id string `json:"id"`
|
|
Title string `json:"title"`
|
|
Length int `json:"length"`
|
|
Position int `json:"position"`
|
|
Number string `json:"number"`
|
|
Recording recordingEntry `json:"recording"`
|
|
}
|
|
|
|
type discEntry struct {
|
|
OffsetCount int `json:"offset-count"`
|
|
Offsets []int `json:"offsets"`
|
|
Id string `json:"id"`
|
|
Sectors int `json:"sectors"`
|
|
}
|
|
|
|
type mediaEntry struct {
|
|
TrackOffset int `json:"track-offset"`
|
|
Position int `json:"position"`
|
|
Format string `json:"format"`
|
|
Tracks []trackEntry `json:"tracks"`
|
|
Discs []discEntry `json:"discs"`
|
|
TrackCount int `json:"track-count"`
|
|
Title string `json:"title"`
|
|
}
|
|
|
|
type aliasEntry struct {
|
|
Type string `json:"type"`
|
|
Name string `json:"name"`
|
|
SortName string `json:"sort-name"`
|
|
}
|
|
|
|
type labelEntry struct {
|
|
Id string `json:"id"`
|
|
Tags []tagEntry `json:"tags"`
|
|
Disambiguation string `json:"disambiguation"`
|
|
Name string `json:"name"`
|
|
ShortName string `json:"short-name"`
|
|
//TODO Aliases
|
|
//TODO genres
|
|
Type string `json:"type"`
|
|
}
|
|
|
|
func (s *Source) GetReleaseCoverArt(releaseId string) (urls []metadata.Name) {
|
|
uri, _ := url.Parse(baseCoverAPIURL)
|
|
uri.Path += "release/" + releaseId
|
|
|
|
response, err := s.client.Request(&http.Request{
|
|
Method: "GET",
|
|
URL: uri,
|
|
}, time.Hour*24*60)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
body, err := ioutil.ReadAll(response.Body)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
result := &struct {
|
|
Release string `json:"release"`
|
|
Images []struct {
|
|
Approved bool `json:"approved"`
|
|
Back bool `json:"back"`
|
|
Comment string `json:"comment"`
|
|
Edit int `json:"edit"`
|
|
Front bool `json:"front"`
|
|
Id int `json:"id"`
|
|
Image string `json:"image"`
|
|
Thumbnails map[string]string `json:"thumbnails"`
|
|
Types []string `json:"types"`
|
|
} `json:"images"`
|
|
}{}
|
|
|
|
err = json.Unmarshal(body, result)
|
|
if err == nil {
|
|
for _, image := range result.Images {
|
|
//fix http -> https
|
|
imageUrl := strings.Replace(image.Image, "http://", "https://", 1)
|
|
name := metadata.Name{
|
|
Kind: "",
|
|
Name: imageUrl,
|
|
}
|
|
if len(image.Types) == 0 {
|
|
name.Kind = "unknown"
|
|
} else {
|
|
for _, priority := range []string{
|
|
"Other",
|
|
"Booklet",
|
|
"Tray",
|
|
"Spine",
|
|
"Obi",
|
|
"Track",
|
|
"Liner",
|
|
"Sticker",
|
|
"Medium",
|
|
"Poster",
|
|
"Matrix/Runout",
|
|
"Front",
|
|
"Back",
|
|
"Watermark",
|
|
"Raw/Unedited",
|
|
} {
|
|
for _, t := range image.Types {
|
|
if t == priority {
|
|
if len(name.Kind) == 0 {
|
|
name.Kind += strings.ToLower(t)
|
|
} else {
|
|
name.Kind += ", " + strings.ToLower(t)
|
|
}
|
|
break
|
|
}
|
|
}
|
|
}
|
|
}
|
|
urls = append(urls, name)
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s *Source) GetRelease(releaseId string) *metadata.Album {
|
|
uri, _ := url.Parse(baseAPIURL)
|
|
uri.Path += "release/" + releaseId
|
|
|
|
query := uri.Query()
|
|
query.Add("fmt", "json")
|
|
query.Add("inc", strings.Join([]string{
|
|
"aliases",
|
|
"artist-credits",
|
|
"artist-rels",
|
|
"artists",
|
|
"discids",
|
|
"event-rels",
|
|
"genres",
|
|
"isrcs",
|
|
"labels",
|
|
"media",
|
|
"ratings",
|
|
"recording-level-rels",
|
|
"recording-rels",
|
|
"recordings",
|
|
"release-rels",
|
|
"series-rels",
|
|
"tags",
|
|
"url-rels",
|
|
"work-level-rels",
|
|
"work-rels",
|
|
}, "+"))
|
|
|
|
uri.RawQuery = query.Encode()
|
|
response, err := s.client.Request(&http.Request{
|
|
Method: "GET",
|
|
URL: uri,
|
|
}, time.Hour*24*60)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
defer response.Body.Close()
|
|
body, err := ioutil.ReadAll(response.Body)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
release := &struct {
|
|
ArtistCredit []artistCreditEntry `json:"artist-credit"`
|
|
Country string `json:"country"`
|
|
Disambiguation string `json:"disambiguation"`
|
|
LabelInfo []struct {
|
|
CatalogNumber string `json:"catalog-number"`
|
|
Label labelEntry `json:"label"`
|
|
} `json:"label-info"`
|
|
Relations []relationEntry `json:"relations"`
|
|
Tags []tagEntry `json:"tags"`
|
|
CoverArtArchive struct {
|
|
Count int `json:"count"`
|
|
Front bool `json:"front"`
|
|
Darkened bool `json:"darkened"`
|
|
Back bool `json:"back"`
|
|
Artwork bool `json:"artwork"`
|
|
} `json:"cover-art-archive"`
|
|
Date string `json:"date"`
|
|
Media []mediaEntry `json:"media"`
|
|
Title string `json:"title"`
|
|
Aliases []aliasEntry `json:"aliases"`
|
|
Status string `json:"status"`
|
|
Id string `json:"id"`
|
|
Barcode string `json:"barcode"`
|
|
ASIN string `json:"asin"`
|
|
}{}
|
|
|
|
err = json.Unmarshal(body, release)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
album := &metadata.Album{
|
|
License: s.GetLicense(),
|
|
SourceUniqueIdentifier: baseURL + "release/" + release.Id,
|
|
Name: []metadata.Name{
|
|
{Kind: "original", Name: release.Title},
|
|
},
|
|
Identifiers: []metadata.Name{
|
|
{
|
|
Kind: "url",
|
|
Name: baseURL + "release/" + release.Id,
|
|
},
|
|
},
|
|
}
|
|
|
|
for _, n := range release.Aliases {
|
|
if n.Type == "Release name" {
|
|
album.Name = append(album.Name, metadata.Name{Kind: "original", Name: n.Name})
|
|
if n.SortName != n.Name {
|
|
album.Name = append(album.Name, metadata.Name{Kind: "sort", Name: n.SortName})
|
|
}
|
|
}
|
|
}
|
|
|
|
if release.CoverArtArchive.Count > 0 {
|
|
album.Art = s.GetReleaseCoverArt(release.Id)
|
|
}
|
|
|
|
album.ReleaseDate, _ = time.ParseInLocation("2006-01-02", release.Date, time.UTC)
|
|
|
|
for _, l := range release.LabelInfo {
|
|
album.Identifiers = append(album.Identifiers, metadata.Name{
|
|
Kind: "catalog",
|
|
Name: l.CatalogNumber,
|
|
})
|
|
}
|
|
|
|
if len(release.Barcode) > 0 {
|
|
album.Identifiers = append(album.Identifiers, metadata.Name{
|
|
Kind: "barcode",
|
|
Name: release.Barcode,
|
|
})
|
|
}
|
|
|
|
if len(release.ASIN) > 0 {
|
|
album.Identifiers = append(album.Identifiers, metadata.Name{
|
|
Kind: "asin",
|
|
Name: release.ASIN,
|
|
})
|
|
}
|
|
|
|
for _, t := range release.Tags {
|
|
album.Tags = append(album.Tags, metadata.Name{
|
|
Kind: "genre",
|
|
Name: t.Name,
|
|
})
|
|
}
|
|
|
|
for _, relation := range release.Relations {
|
|
if relation.Direction == "backward" {
|
|
if relation.Artist != nil {
|
|
role := metadata.Role{
|
|
Kind: relation.Type, //TODO: normalize
|
|
}
|
|
|
|
if relation.Artist.Type == "Group" {
|
|
role.Group = relation.Artist.Name
|
|
}
|
|
|
|
role.Name = []metadata.Name{{Kind: "original", Name: relation.Artist.Name}}
|
|
if relation.Artist.SortName != relation.Artist.Name {
|
|
role.Name = append(role.Name, metadata.Name{Kind: "sort", Name: relation.Artist.SortName})
|
|
}
|
|
if len(relation.Artist.Disambiguation) > 0 {
|
|
role.Name = append(role.Name, metadata.Name{Kind: "disambiguation", Name: relation.Artist.Disambiguation})
|
|
}
|
|
for _, n := range relation.Artist.Aliases {
|
|
role.Name = append(role.Name, metadata.Name{Kind: "original", Name: n.Name})
|
|
if n.SortName != n.Name {
|
|
role.Name = append(role.Name, metadata.Name{Kind: "sort", Name: n.SortName})
|
|
}
|
|
}
|
|
role.Name = append(role.Name, metadata.Name{Kind: "url", Name: baseURL + "artist/" + relation.Artist.Id})
|
|
|
|
album.Roles = append(album.Roles, role)
|
|
} else if relation.Event != nil && relation.Type == "available at" {
|
|
album.Links = append(album.Links, metadata.Link{
|
|
Kind: "release",
|
|
Name: []metadata.Name{
|
|
{Kind: "name", Name: relation.Event.Name},
|
|
{Kind: "url", Name: baseURL + "event/" + relation.Event.Id},
|
|
},
|
|
})
|
|
}
|
|
} else if relation.Direction == "forward" {
|
|
if relation.Url != nil {
|
|
album.Links = append(album.Links, metadata.Link{
|
|
Kind: relation.Type,
|
|
Name: []metadata.Name{{Kind: "url", Name: relation.Url.Resource}},
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
for _, media := range release.Media {
|
|
disc := metadata.Disc{}
|
|
|
|
if len(media.Title) > 0 {
|
|
disc.Name = append(disc.Name, metadata.Name{Kind: "original", Name: media.Title})
|
|
}
|
|
|
|
if len(media.Discs) > 0 {
|
|
d := media.Discs[0]
|
|
|
|
if len(d.Offsets) > 0 {
|
|
toc := append(metadata.TOC{d.Sectors}, d.Offsets...)
|
|
|
|
disc.Identifiers = append(disc.Identifiers, metadata.Name{
|
|
Kind: "toc",
|
|
Name: toc.String(),
|
|
})
|
|
|
|
disc.Identifiers = append(disc.Identifiers, metadata.Name{
|
|
Kind: "cddb1",
|
|
Name: toc.GetCDDB1().String(),
|
|
})
|
|
|
|
disc.Identifiers = append(disc.Identifiers, metadata.Name{
|
|
Kind: "tocid",
|
|
Name: string(toc.GetTocID()),
|
|
})
|
|
}
|
|
|
|
if len(d.Id) > 0 {
|
|
disc.Identifiers = append(disc.Identifiers, metadata.Name{
|
|
Kind: "discid",
|
|
Name: d.Id,
|
|
})
|
|
}
|
|
}
|
|
|
|
for _, t := range media.Tracks {
|
|
track := metadata.Track{
|
|
Name: metadata.NameSlice{
|
|
{Kind: "original", Name: t.Title},
|
|
},
|
|
Identifiers: metadata.NameSlice{
|
|
{Kind: "url", Name: baseURL + "track/" + t.Id},
|
|
{Kind: "url", Name: baseURL + "recording/" + t.Recording.Id},
|
|
},
|
|
Duration: time.Millisecond * time.Duration(t.Length),
|
|
}
|
|
|
|
for _, isrc := range t.Recording.ISRCS {
|
|
track.Identifiers = append(track.Identifiers, metadata.Name{
|
|
Kind: "isrc",
|
|
Name: isrc,
|
|
})
|
|
}
|
|
|
|
for _, relation := range t.Recording.Relations {
|
|
if relation.Direction == "backward" {
|
|
if relation.Artist != nil {
|
|
role := metadata.Role{
|
|
Kind: relation.Type, //TODO: normalize
|
|
}
|
|
|
|
if relation.Artist.Type == "Group" {
|
|
role.Group = relation.Artist.Name
|
|
}
|
|
|
|
if len(relation.Attributes) > 0 {
|
|
role.Kind += "; " + strings.Join(relation.Attributes, ", ")
|
|
}
|
|
|
|
role.Name = []metadata.Name{{Kind: "original", Name: relation.Artist.Name}}
|
|
if relation.Artist.SortName != relation.Artist.Name {
|
|
role.Name = append(role.Name, metadata.Name{Kind: "sort", Name: relation.Artist.SortName})
|
|
}
|
|
if len(relation.Artist.Disambiguation) > 0 {
|
|
role.Name = append(role.Name, metadata.Name{Kind: "disambiguation", Name: relation.Artist.Disambiguation})
|
|
}
|
|
for _, n := range relation.Artist.Aliases {
|
|
role.Name = append(role.Name, metadata.Name{Kind: "original", Name: n.Name})
|
|
if n.SortName != n.Name {
|
|
role.Name = append(role.Name, metadata.Name{Kind: "sort", Name: n.SortName})
|
|
}
|
|
}
|
|
role.Name = append(role.Name, metadata.Name{Kind: "url", Name: baseURL + "artist/" + relation.Artist.Id})
|
|
|
|
track.Roles = append(track.Roles, role)
|
|
}
|
|
} else if relation.Direction == "forward" {
|
|
if relation.Work != nil && relation.Type == "performance" {
|
|
link := metadata.Link{
|
|
Kind: "work",
|
|
Name: []metadata.Name{
|
|
{Kind: "original", Name: relation.Work.Title},
|
|
{Kind: "url", Name: baseURL + "work/" + relation.Work.Id},
|
|
},
|
|
}
|
|
if len(relation.Work.Disambiguation) > 0 {
|
|
link.Name = append(link.Name, metadata.Name{Kind: "disambiguation", Name: relation.Work.Disambiguation})
|
|
}
|
|
track.Links = append(track.Links, link)
|
|
|
|
for _, r2 := range relation.Work.Relations {
|
|
if r2.Direction == "backward" {
|
|
if r2.Artist != nil {
|
|
role := metadata.Role{
|
|
Kind: r2.Type, //TODO: normalize
|
|
}
|
|
|
|
if r2.Artist.Type == "Group" {
|
|
role.Group = r2.Artist.Name
|
|
}
|
|
|
|
role.Name = []metadata.Name{{Kind: "original", Name: r2.Artist.Name}}
|
|
if r2.Artist.SortName != r2.Artist.Name {
|
|
role.Name = append(role.Name, metadata.Name{Kind: "sort", Name: r2.Artist.SortName})
|
|
}
|
|
if len(r2.Artist.Disambiguation) > 0 {
|
|
role.Name = append(role.Name, metadata.Name{Kind: "disambiguation", Name: r2.Artist.Disambiguation})
|
|
}
|
|
for _, n := range r2.Artist.Aliases {
|
|
role.Name = append(role.Name, metadata.Name{Kind: "original", Name: n.Name})
|
|
if n.SortName != n.Name {
|
|
role.Name = append(role.Name, metadata.Name{Kind: "sort", Name: n.SortName})
|
|
}
|
|
}
|
|
role.Name = append(role.Name, metadata.Name{Kind: "url", Name: baseURL + "artist/" + r2.Artist.Id})
|
|
|
|
track.Roles = append(track.Roles, role)
|
|
}
|
|
}
|
|
}
|
|
|
|
} else if relation.Recording != nil && relation.Type == "remix" {
|
|
track.Links = append(track.Links, metadata.Link{
|
|
Kind: "original",
|
|
Name: []metadata.Name{
|
|
{Kind: "original", Name: relation.Recording.Title},
|
|
{Kind: "url", Name: baseURL + "recording/" + relation.Recording.Id},
|
|
},
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
disc.Tracks = append(disc.Tracks, track)
|
|
}
|
|
|
|
album.Discs = append(album.Discs, disc)
|
|
|
|
}
|
|
|
|
return album
|
|
}
|
|
|
|
func (s *Source) FindQueryArguments(queryArgs string) (albums []*metadata.Album) {
|
|
|
|
uri, _ := url.Parse(baseAPIURL)
|
|
uri.Path += "release/"
|
|
|
|
query := uri.Query()
|
|
query.Add("query", queryArgs)
|
|
query.Add("fmt", "json")
|
|
|
|
uri.RawQuery = query.Encode()
|
|
response, err := s.client.Request(&http.Request{
|
|
Method: "GET",
|
|
URL: uri,
|
|
}, time.Hour*24*14)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
body, err := ioutil.ReadAll(response.Body)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
type SearchResult struct {
|
|
Count int `json:"count"`
|
|
Releases []struct {
|
|
Id string `json:"id"`
|
|
Score int `json:"score"`
|
|
Count int `json:"count"`
|
|
Title string `json:"title"`
|
|
Date string `json:"date"`
|
|
Country string `json:"country"`
|
|
LabelInfo []struct {
|
|
CatalogNumber string `json:"catalog-number"`
|
|
Label struct {
|
|
Id string `json:"id"`
|
|
Name string `json:"name"`
|
|
} `json:"label"`
|
|
} `json:"label-info"`
|
|
TrackCount int `json:"track-count"`
|
|
Media []struct {
|
|
Format string `json:"format"`
|
|
DiscCount int `json:"disc-count"`
|
|
TrackCount int `json:"track-count"`
|
|
} `json:"media"`
|
|
} `json:"releases"`
|
|
}
|
|
|
|
result := &SearchResult{}
|
|
|
|
err = json.Unmarshal(body, result)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
for _, r := range result.Releases {
|
|
album := s.GetRelease(r.Id)
|
|
if album != nil {
|
|
albums = append(albums, album)
|
|
}
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func (s *Source) Test() {
|
|
album := s.FindByTOC(metadata.NewTOCFromString("267453 150 24647 71194 95579 139576 174573 199089 244305"))
|
|
//album := s.GetRelease("9ca2748b-88fd-44a7-bc5c-036574148571")
|
|
|
|
log.Print(album)
|
|
}
|