forked from zmb3/spotify
-
Notifications
You must be signed in to change notification settings - Fork 0
/
album.go
210 lines (186 loc) · 6.54 KB
/
album.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
package spotify
import (
"context"
"errors"
"fmt"
"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 artist’s
// 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 endpoint 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"`
}
// ReleaseDateTime converts the album's ReleaseDate to a time.TimeValue.
// All of the fields in the result may not be valid. For example, if
// ReleaseDatePrecision is "month", then only the month and year
// (but not the day) of the result are valid.
func (s *SimpleAlbum) ReleaseDateTime() time.Time {
if s.ReleaseDatePrecision == "day" {
result, _ := time.Parse(DateLayout, s.ReleaseDate)
return result
}
if s.ReleaseDatePrecision == "month" {
ym := strings.Split(s.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(s.ReleaseDate)
return time.Date(year, 1, 1, 0, 0, 0, 0, time.UTC)
}
// 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
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 popularity of the album's individual tracks.
Popularity Numeric `json:"popularity"`
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"`
}
// GetAlbum gets Spotify catalog information for a single album, given its Spotify ID.
// Supported options: Market
func (c *Client) GetAlbum(ctx context.Context, id ID, opts ...RequestOption) (*FullAlbum, error) {
spotifyURL := fmt.Sprintf("%salbums/%s", c.baseURL, id)
if params := processOptions(opts...).urlParams.Encode(); params != "" {
spotifyURL += "?" + params
}
var a FullAlbum
err := c.get(ctx, 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.
//
// Doc API: https://developer.spotify.com/documentation/web-api/reference/albums/get-several-albums/
//
// Supported options: Market
func (c *Client) GetAlbums(ctx context.Context, ids []ID, opts ...RequestOption) ([]*FullAlbum, error) {
if len(ids) > 20 {
return nil, errors.New("spotify: exceeded maximum number of albums")
}
params := processOptions(opts...).urlParams
params.Set("ids", strings.Join(toStringSlice(ids), ","))
spotifyURL := fmt.Sprintf("%salbums?%s", c.baseURL, params.Encode())
var a struct {
Albums []*FullAlbum `json:"albums"`
}
err := c.get(ctx, 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
AlbumTypeAppearsOn
AlbumTypeCompilation
)
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&AlbumTypeAppearsOn != 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.
//
// Supported Options: Market, Limit, Offset
func (c *Client) GetAlbumTracks(ctx context.Context, id ID, opts ...RequestOption) (*SimpleTrackPage, error) {
spotifyURL := fmt.Sprintf("%salbums/%s/tracks", c.baseURL, id)
if params := processOptions(opts...).urlParams.Encode(); params != "" {
spotifyURL += "?" + params
}
var result SimpleTrackPage
err := c.get(ctx, spotifyURL, &result)
if err != nil {
return nil, err
}
return &result, nil
}