1
0
mirror of https://github.com/taigrr/wtf synced 2025-01-18 04:03:14 -08:00
2019-07-15 09:06:49 -07:00

221 lines
7.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package spotify
import (
"errors"
"fmt"
"net/url"
"strconv"
"strings"
"time"
)
// SimpleAlbum contains basic data about an album.
type SimpleAlbum struct {
// The name of the album.
Name string `json:"name"`
// A slice of SimpleArtists
Artists []SimpleArtist `json:"artists"`
// The field is present when getting an artists
// albums. Possible values are “album”, “single”,
// “compilation”, “appears_on”. Compare to album_type
// this field represents relationship between the artist
// and the album.
AlbumGroup string `json:"album_group"`
// The type of the album: one of "album",
// "single", or "compilation".
AlbumType string `json:"album_type"`
// The SpotifyID for the album.
ID ID `json:"id"`
// The SpotifyURI for the album.
URI URI `json:"uri"`
// The markets in which the album is available,
// identified using ISO 3166-1 alpha-2 country
// codes. Note that al album is considered
// available in a market when at least 1 of its
// tracks is available in that market.
AvailableMarkets []string `json:"available_markets"`
// A link to the Web API enpoint providing full
// details of the album.
Endpoint string `json:"href"`
// The cover art for the album in various sizes,
// widest first.
Images []Image `json:"images"`
// Known external URLs for this album.
ExternalURLs map[string]string `json:"external_urls"`
// The date the album was first released. For example, "1981-12-15".
// Depending on the ReleaseDatePrecision, it might be shown as
// "1981" or "1981-12". You can use ReleaseDateTime to convert this
// to a time.Time value.
ReleaseDate string `json:"release_date"`
// The precision with which ReleaseDate value is known: "year", "month", or "day"
ReleaseDatePrecision string `json:"release_date_precision"`
}
// Copyright contains the copyright statement associated with an album.
type Copyright struct {
// The copyright text for the album.
Text string `json:"text"`
// The type of copyright.
Type string `json:"type"`
}
// FullAlbum provides extra album data in addition to the data provided by SimpleAlbum.
type FullAlbum struct {
SimpleAlbum
Artists []SimpleArtist `json:"artists"`
Copyrights []Copyright `json:"copyrights"`
Genres []string `json:"genres"`
// The popularity of the album, represented as an integer between 0 and 100,
// with 100 being the most popular. Popularity of an album is calculated
// from the popularify of the album's individual tracks.
Popularity int `json:"popularity"`
// The date the album was first released. For example, "1981-12-15".
// Depending on the ReleaseDatePrecision, it might be shown as
// "1981" or "1981-12". You can use ReleaseDateTime to convert this
// to a time.Time value.
ReleaseDate string `json:"release_date"`
// The precision with which ReleaseDate value is known: "year", "month", or "day"
ReleaseDatePrecision string `json:"release_date_precision"`
Tracks SimpleTrackPage `json:"tracks"`
ExternalIDs map[string]string `json:"external_ids"`
}
// SavedAlbum provides info about an album saved to an user's account.
type SavedAlbum struct {
// The date and time the track was saved, represented as an ISO
// 8601 UTC timestamp with a zero offset (YYYY-MM-DDTHH:MM:SSZ).
// You can use the TimestampLayout constant to convert this to
// a time.Time value.
AddedAt string `json:"added_at"`
FullAlbum `json:"album"`
}
// ReleaseDateTime converts the album's ReleaseDate to a time.TimeValue.
// All of the fields in the result may not be valid. For example, if
// f.ReleaseDatePrecision is "month", then only the month and year
// (but not the day) of the result are valid.
func (f *FullAlbum) ReleaseDateTime() time.Time {
if f.ReleaseDatePrecision == "day" {
result, _ := time.Parse(DateLayout, f.ReleaseDate)
return result
}
if f.ReleaseDatePrecision == "month" {
ym := strings.Split(f.ReleaseDate, "-")
year, _ := strconv.Atoi(ym[0])
month, _ := strconv.Atoi(ym[1])
return time.Date(year, time.Month(month), 1, 0, 0, 0, 0, time.UTC)
}
year, _ := strconv.Atoi(f.ReleaseDate)
return time.Date(year, 1, 1, 0, 0, 0, 0, time.UTC)
}
// GetAlbum gets Spotify catalog information for a single album, given its Spotify ID.
func (c *Client) GetAlbum(id ID) (*FullAlbum, error) {
spotifyURL := fmt.Sprintf("%salbums/%s", c.baseURL, id)
var a FullAlbum
err := c.get(spotifyURL, &a)
if err != nil {
return nil, err
}
return &a, nil
}
func toStringSlice(ids []ID) []string {
result := make([]string, len(ids))
for i, str := range ids {
result[i] = str.String()
}
return result
}
// GetAlbums gets Spotify Catalog information for multiple albums, given their
// Spotify IDs. It supports up to 20 IDs in a single call. Albums are returned
// in the order requested. If an album is not found, that position in the
// result slice will be nil.
func (c *Client) GetAlbums(ids ...ID) ([]*FullAlbum, error) {
if len(ids) > 20 {
return nil, errors.New("spotify: exceeded maximum number of albums")
}
spotifyURL := fmt.Sprintf("%salbums?ids=%s", c.baseURL, strings.Join(toStringSlice(ids), ","))
var a struct {
Albums []*FullAlbum `json:"albums"`
}
err := c.get(spotifyURL, &a)
if err != nil {
return nil, err
}
return a.Albums, nil
}
// AlbumType represents the type of an album. It can be used to filter
// results when searching for albums.
type AlbumType int
// AlbumType values that can be used to filter which types of albums are
// searched for. These are flags that can be bitwise OR'd together
// to search for multiple types of albums simultaneously.
const (
AlbumTypeAlbum AlbumType = 1 << iota
AlbumTypeSingle = 1 << iota
AlbummTypeAppearsOn = 1 << iota
AlbumTypeCompilation = 1 << iota
)
func (at AlbumType) encode() string {
types := []string{}
if at&AlbumTypeAlbum != 0 {
types = append(types, "album")
}
if at&AlbumTypeSingle != 0 {
types = append(types, "single")
}
if at&AlbummTypeAppearsOn != 0 {
types = append(types, "appears_on")
}
if at&AlbumTypeCompilation != 0 {
types = append(types, "compilation")
}
return strings.Join(types, ",")
}
// GetAlbumTracks gets the tracks for a particular album.
// If you only care about the tracks, this call is more efficient
// than GetAlbum.
func (c *Client) GetAlbumTracks(id ID) (*SimpleTrackPage, error) {
return c.GetAlbumTracksOpt(id, -1, -1)
}
// GetAlbumTracksOpt behaves like GetAlbumTracks, with the exception that it
// allows you to specify extra parameters that limit the number of results returned.
// The maximum number of results to return is specified by limit.
// The offset argument can be used to specify the index of the first track to return.
// It can be used along with limit to reqeust the next set of results.
func (c *Client) GetAlbumTracksOpt(id ID, limit, offset int) (*SimpleTrackPage, error) {
spotifyURL := fmt.Sprintf("%salbums/%s/tracks", c.baseURL, id)
v := url.Values{}
if limit != -1 {
v.Set("limit", strconv.Itoa(limit))
}
if offset != -1 {
v.Set("offset", strconv.Itoa(offset))
}
optional := v.Encode()
if optional != "" {
spotifyURL = spotifyURL + "?" + optional
}
var result SimpleTrackPage
err := c.get(spotifyURL, &result)
if err != nil {
return nil, err
}
return &result, nil
}