diff --git a/.golangci.yml b/.golangci.yml index af35675..e681f63 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -96,7 +96,7 @@ linters-settings: gomnd: ignored-files: - - "examples/*.go" + - examples/album/main.go varnamelen: ignore-names: @@ -106,7 +106,11 @@ linters-settings: issues: exclude-rules: - - path: _test.go + - path: (.+)_test\.go linters: - cyclop - funlen + - path: examples/(.+)/main.go + linters: + - funlen + - gomnd diff --git a/README.md b/README.md index 4510028..4e7d765 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ An unofficial Go library for interacting with the TIDAL API. ![GitHub Tag](https://img.shields.io/github/v/tag/tomjowitt/gotidal) ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/tomjowitt/gotidal/test.yml?label=tests) ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/tomjowitt/gotidal/lint.yml?label=lint) +![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/tomjowitt/gotidal) ## Guidelines diff --git a/album.go b/album.go index 6dbf74c..e981c80 100644 --- a/album.go +++ b/album.go @@ -96,17 +96,6 @@ func (c *Client) GetSingleAlbum(ctx context.Context, id string) (*Album, error) return &result, nil } -// itemsParams defines the request parameters used by the album items API endpoint. -type itemsParams struct { - // Pagination offset (in number of items). - // Example: 0 - Offset int `json:"offset"` - - // Page size. - // Example: 10 - Limit int `json:"limit"` -} - type trackResults struct { Data []Track `json:"data"` MetaData ItemMetaData `json:"metadata"` @@ -120,13 +109,14 @@ const paginationLimit = 100 // one round-trip. If the metadata reports a higher total then we make susequent API calls until all the tracks are // returned. // -// This endpoint also supports videos but it was hard to find any examples of this. +// This endpoint also supports videos but it was hard to find any examples of this, so for the moment this is tracks +// only. func (c *Client) GetAlbumTracks(ctx context.Context, id string) ([]Track, error) { if id == "" { return nil, ErrMissingRequiredParameters } - params := itemsParams{ + params := PaginationParams{ Limit: paginationLimit, Offset: 0, } @@ -200,15 +190,48 @@ func (c *Client) GetMultipleAlbums(ctx context.Context, ids []string) ([]Album, response, err := c.request(ctx, http.MethodGet, "/albums/byIds", params) if err != nil { - return nil, fmt.Errorf("failed to connect to the albums endpoint: %w", err) + return nil, fmt.Errorf("failed to connect to the multiple albums endpoint: %w", err) } var results albumResults err = json.Unmarshal(response, &results) if err != nil { - return nil, fmt.Errorf("failed to unmarshal the albums response body: %w", err) + return nil, fmt.Errorf("failed to unmarshal the multiple albums response body: %w", err) } return results.Data, nil } + +type similarAlbum struct { + Resource struct { + ID string `json:"id"` + } +} + +type similarAlbumResults struct { + Data []similarAlbum `json:"data"` + MetaData ItemMetaData `json:"metadata"` +} + +// GetSimilarAlbums returns a slice of album IDs that can be used as a parameter in the GetMultipleAlbums function. +func (c *Client) GetSimilarAlbums(ctx context.Context, id string, params PaginationParams) ([]string, error) { + response, err := c.request(ctx, http.MethodGet, concat("/albums/", id, "/similar"), params) + if err != nil { + return nil, fmt.Errorf("failed to connect to the similar albums endpoint: %w", err) + } + + var results similarAlbumResults + + err = json.Unmarshal(response, &results) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal the similar albums response body: %w", err) + } + + var albumIDs []string + for _, albumID := range results.Data { + albumIDs = append(albumIDs, albumID.Resource.ID) + } + + return albumIDs, nil +} diff --git a/client.go b/client.go index cb8f292..403b4a3 100644 --- a/client.go +++ b/client.go @@ -24,10 +24,12 @@ const ( var ErrUnexpectedResponseCode = errors.New("returned an unexpected status code") +// HTTPClient provides an interface to make HTTP requests. type HTTPClient interface { Do(req *http.Request) (*http.Response, error) } +// Client defines the parameters needed to create a TIDAL API client. type Client struct { httpClient HTTPClient ContentType string @@ -36,6 +38,12 @@ type Client struct { CountryCode string } +// PaginationParams defines the limit and offset for pagination functions. +type PaginationParams struct { + Limit int + Offset int +} + // NewClient returns an API client based on a users credentials and location. func NewClient(clientID string, clientSecret string, countryCode string) (*Client, error) { ctx := context.Background() diff --git a/examples/album/main.go b/examples/album/main.go index d7dc606..dab183d 100644 --- a/examples/album/main.go +++ b/examples/album/main.go @@ -68,4 +68,22 @@ func main() { for _, item := range items { log.Printf("#%d (Vol #%d) - %s - %s", item.TrackNumber, item.VolumeNumber, item.Title, item.Album.Title) } + + log.Println("-------------------------------------------------") + log.Println("Similar Albums to 'New York Dolls - s/t'") + log.Println("-------------------------------------------------") + + similarIDs, err := client.GetSimilarAlbums(ctx, "3992356", gotidal.PaginationParams{Limit: 10}) + if err != nil { + log.Fatal(err) + } + + similarAlbums, err := client.GetMultipleAlbums(ctx, similarIDs) + if err != nil { + log.Fatal(err) + } + + for _, item := range similarAlbums { + log.Printf("%s - %s", item.Title, item.Artists[0].Name) + } } diff --git a/testdata/similar-albums.json b/testdata/similar-albums.json new file mode 100644 index 0000000..5c9aebb --- /dev/null +++ b/testdata/similar-albums.json @@ -0,0 +1,57 @@ +{ + "data": [ + { + "resource": { + "id": "51462398" + } + }, + { + "resource": { + "id": "7915601" + } + }, + { + "resource": { + "id": "217162" + } + }, + { + "resource": { + "id": "1653024" + } + }, + { + "resource": { + "id": "14057908" + } + }, + { + "resource": { + "id": "9373" + } + }, + { + "resource": { + "id": "477295" + } + }, + { + "resource": { + "id": "51462439" + } + }, + { + "resource": { + "id": "7915627" + } + }, + { + "resource": { + "id": "49794441" + } + } + ], + "metadata": { + "total": 96 + } +}