From 22d9b2bc1511e63906001d96e7d856217b79732f Mon Sep 17 00:00:00 2001 From: Jonathan Hall Date: Tue, 12 Nov 2024 21:33:54 -0600 Subject: [PATCH] Misc GoDoc updates --- album.go | 59 +++++++++------- artist.go | 8 ++- audio_analysis.go | 12 ++-- audio_features.go | 10 ++- category.go | 7 +- countries.go | 4 +- cursor.go | 2 +- library.go | 12 ++-- page.go | 26 +++---- player.go | 93 ++++++++++++------------- playlist.go | 164 ++++++++++++++++++++++++++------------------ recommendation.go | 31 +++++---- request_options.go | 32 +++++---- search.go | 23 ++++--- show.go | 53 ++++++++------ track.go | 57 ++++++++------- track_attributes.go | 114 +++++++++++++++--------------- user.go | 119 ++++++++++++++++++++------------ 18 files changed, 475 insertions(+), 351 deletions(-) diff --git a/album.go b/album.go index d624155..e30d0be 100644 --- a/album.go +++ b/album.go @@ -13,7 +13,7 @@ import ( type SimpleAlbum struct { // The name of the album. Name string `json:"name"` - // A slice of SimpleArtists + // A slice of [SimpleArtist]. Artists []SimpleArtist `json:"artists"` // The field is present when getting an artist’s // albums. Possible values are “album”, “single”, @@ -24,15 +24,20 @@ type SimpleAlbum struct { // The type of the album: one of "album", // "single", or "compilation". AlbumType string `json:"album_type"` - // The SpotifyID for the album. + // The [Spotify ID] for the album. + // + // [Spotify ID]: https://developer.spotify.com/documentation/web-api/concepts/spotify-uris-ids ID ID `json:"id"` - // The SpotifyURI for the album. + // The [Spotify URI] for the album. + // + // [Spotify URI]: https://developer.spotify.com/documentation/web-api/concepts/spotify-uris-ids 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. + // The markets in which the album is available, identified using + // [ISO 3166-1 alpha-2] country codes. Note that an album is considered + // available in a market when at least 1 of its tracks is available in that + // market. + // + // [ISO 3166-1 alpha-2]: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 AvailableMarkets []string `json:"available_markets"` // A link to the Web API endpoint providing full // details of the album. @@ -44,8 +49,8 @@ type SimpleAlbum struct { 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. + // "1981" or "1981-12". You can use [SimpleAlbum.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"` @@ -53,9 +58,9 @@ type SimpleAlbum struct { TotalTracks Numeric `json:"total_tracks"` } -// ReleaseDateTime converts the album's ReleaseDate to a time.TimeValue. +// ReleaseDateTime converts [SimpleAlbum.ReleaseDate] to a [time.Time]. // All of the fields in the result may not be valid. For example, if -// ReleaseDatePrecision is "month", then only the month and year +// [SimpleAlbum.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" { @@ -80,7 +85,7 @@ type Copyright struct { Type string `json:"type"` } -// FullAlbum provides extra album data in addition to the data provided by SimpleAlbum. +// FullAlbum provides extra album data in addition to the data provided by [SimpleAlbum]. type FullAlbum struct { SimpleAlbum Copyrights []Copyright `json:"copyrights"` @@ -93,18 +98,19 @@ type FullAlbum struct { ExternalIDs map[string]string `json:"external_ids"` } -// SavedAlbum provides info about an album saved to an user's account. +// SavedAlbum provides info about an album saved to a 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. + // You can use [TimestampLayout] 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 +// GetAlbum gets Spotify catalog information for a single album, given its +// [Spotify ID]. Supported options: [Market]. +// +// [Spotify ID]: https://developer.spotify.com/documentation/web-api/concepts/spotify-uris-ids func (c *Client) GetAlbum(ctx context.Context, id ID, opts ...RequestOption) (*FullAlbum, error) { spotifyURL := fmt.Sprintf("%salbums/%s", c.baseURL, id) @@ -130,14 +136,15 @@ func toStringSlice(ids []ID) []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 +// GetAlbums gets Spotify Catalog information for [multiple albums], given their +// [Spotify ID]s. 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]. // -// Supported options: Market +// [multiple albums]: https://developer.spotify.com/documentation/web-api/reference/get-multiple-albums +// [Spotify ID]: https://developer.spotify.com/documentation/web-api/concepts/spotify-uris-ids 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") @@ -190,11 +197,13 @@ func (at AlbumType) encode() string { return strings.Join(types, ",") } -// GetAlbumTracks gets the tracks for a particular album. +// GetAlbumTracks gets the [tracks] for a particular album. // If you only care about the tracks, this call is more efficient -// than GetAlbum. +// than [GetAlbum]. +// +// Supported Options: [Market], [Limit], [Offset]. // -// Supported Options: Market, Limit, Offset +// [tracks]: https://developer.spotify.com/documentation/web-api/reference/get-an-albums-tracks func (c *Client) GetAlbumTracks(ctx context.Context, id ID, opts ...RequestOption) (*SimpleTrackPage, error) { spotifyURL := fmt.Sprintf("%salbums/%s/tracks", c.baseURL, id) diff --git a/artist.go b/artist.go index 5eceff7..6b733b8 100644 --- a/artist.go +++ b/artist.go @@ -17,7 +17,7 @@ type SimpleArtist struct { ExternalURLs map[string]string `json:"external_urls"` } -// FullArtist provides extra artist data in addition to what is provided by SimpleArtist. +// FullArtist provides extra artist data in addition to what is provided by [SimpleArtist]. type FullArtist struct { SimpleArtist // The popularity of the artist, expressed as an integer between 0 and 100. @@ -66,7 +66,9 @@ func (c *Client) GetArtists(ctx context.Context, ids ...ID) ([]*FullArtist, erro // GetArtistsTopTracks gets Spotify catalog information about an artist's top // tracks in a particular country. It returns a maximum of 10 tracks. The -// country is specified as an ISO 3166-1 alpha-2 country code. +// country is specified as an [ISO 3166-1 alpha-2] country code. +// +// [ISO 3166-1 alpha-2]: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 func (c *Client) GetArtistsTopTracks(ctx context.Context, artistID ID, country string) ([]FullTrack, error) { spotifyURL := fmt.Sprintf("%sartists/%s/top-tracks?country=%s", c.baseURL, artistID, country) @@ -108,7 +110,7 @@ func (c *Client) GetRelatedArtists(ctx context.Context, id ID) ([]FullArtist, er // If the Market is not specified, Spotify will likely return a lot // of duplicates (one for each market in which the album is available // -// Supported options: Market +// Supported options: [Market]. func (c *Client) GetArtistAlbums(ctx context.Context, artistID ID, ts []AlbumType, opts ...RequestOption) (*SimpleAlbumPage, error) { spotifyURL := fmt.Sprintf("%sartists/%s/albums", c.baseURL, artistID) // add optional query string if options were specified diff --git a/audio_analysis.go b/audio_analysis.go index ffe13e3..e490a4c 100644 --- a/audio_analysis.go +++ b/audio_analysis.go @@ -5,9 +5,11 @@ import ( "fmt" ) -// AudioAnalysis contains a detailed audio analysis for a single track -// identified by its unique Spotify ID. See: -// https://developer.spotify.com/web-api/get-audio-analysis/ +// AudioAnalysis contains a [detailed audio analysis] for a single track +// identified by its unique [Spotify ID]. +// +// [detailed audio analysis]: https://developer.spotify.com/documentation/web-api/reference/get-audio-analysis +// [Spotify ID]: https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids type AudioAnalysis struct { Bars []Marker `json:"bars"` Beats []Marker `json:"beats"` @@ -95,8 +97,10 @@ type AnalysisTrack struct { RhythmVersion float64 `json:"rhythm_version"` } -// GetAudioAnalysis queries the Spotify web API for an audio analysis of a +// GetAudioAnalysis queries the Spotify web API for an [audio analysis] of a // single track. +// +// [audio analysis]: https://developer.spotify.com/documentation/web-api/reference/get-audio-analysis func (c *Client) GetAudioAnalysis(ctx context.Context, id ID) (*AudioAnalysis, error) { url := fmt.Sprintf("%saudio-analysis/%s", c.baseURL, id) diff --git a/audio_features.go b/audio_features.go index df13802..32b0db3 100644 --- a/audio_features.go +++ b/audio_features.go @@ -37,8 +37,10 @@ type AudioFeatures struct { // intended to represent instrumental tracks, but confidence is higher as the // value approaches 1.0. Instrumentalness float32 `json:"instrumentalness"` - // The key the track is in. Integers map to pitches using standard Pitch Class notation - // (https://en.wikipedia.org/wiki/Pitch_class). + // The key the track is in. Integers map to pitches using standard + // [Pitch Class] notation. + // + // [Pitch Class]: https://en.wikipedia.org/wiki/Pitch_class Key Numeric `json:"key"` // Detects the presence of an audience in the recording. Higher liveness // values represent an increased probability that the track was performed live. @@ -73,7 +75,9 @@ type AudioFeatures struct { Valence float32 `json:"valence"` } -// Key represents a pitch using Pitch Class notation. +// Key represents a pitch using [Pitch Class] notation. +// +// [Pitch Class]: https://en.wikipedia.org/wiki/Pitch_class type Key int const ( diff --git a/category.go b/category.go index 38bdce1..e7bfd89 100644 --- a/category.go +++ b/category.go @@ -21,7 +21,7 @@ type Category struct { // GetCategory gets a single category used to tag items in Spotify. // -// Supported options: Country, Locale +// Supported options: [Country], [Locale]. func (c *Client) GetCategory(ctx context.Context, id string, opts ...RequestOption) (Category, error) { cat := Category{} spotifyURL := fmt.Sprintf("%sbrowse/categories/%s", c.baseURL, id) @@ -38,7 +38,8 @@ func (c *Client) GetCategory(ctx context.Context, id string, opts ...RequestOpti } // GetCategoryPlaylists gets a list of Spotify playlists tagged with a particular category. -// Supported options: Country, Limit, Offset +// +// Supported options: [Country], [Limit], [Offset]. func (c *Client) GetCategoryPlaylists(ctx context.Context, catID string, opts ...RequestOption) (*SimplePlaylistPage, error) { spotifyURL := fmt.Sprintf("%sbrowse/categories/%s/playlists", c.baseURL, catID) if params := processOptions(opts...).urlParams.Encode(); params != "" { @@ -59,7 +60,7 @@ func (c *Client) GetCategoryPlaylists(ctx context.Context, catID string, opts .. // GetCategories gets a list of categories used to tag items in Spotify // -// Supported options: Country, Locale, Limit, Offset +// Supported options: [Country], [Locale], [Limit], [Offset]. func (c *Client) GetCategories(ctx context.Context, opts ...RequestOption) (*CategoryPage, error) { spotifyURL := c.baseURL + "browse/categories" if query := processOptions(opts...).urlParams.Encode(); query != "" { diff --git a/countries.go b/countries.go index a8f3f4c..17de059 100644 --- a/countries.go +++ b/countries.go @@ -1,8 +1,8 @@ package spotify -// ISO 3166-1 alpha 2 country codes. +// [ISO 3166-1 alpha-2] country codes. // -// see: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 +// [ISO 3166-1 alpha-2]: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 const ( CountryArgentina = "AR" CountryAustralia = "AU" diff --git a/cursor.go b/cursor.go index 0d08ddc..672cc54 100644 --- a/cursor.go +++ b/cursor.go @@ -30,7 +30,7 @@ type cursorPage struct { } // FullArtistCursorPage is a cursor-based paging object containing -// a set of FullArtist objects. +// a set of [FullArtist] objects. type FullArtistCursorPage struct { cursorPage Artists []FullArtist `json:"items"` diff --git a/library.go b/library.go index 1b7d740..f58508e 100644 --- a/library.go +++ b/library.go @@ -37,31 +37,31 @@ func (c *Client) libraryContains(ctx context.Context, typ string, ids ...ID) ([] } // AddTracksToLibrary saves one or more tracks to the current user's -// "Your Music" library. This call requires the ScopeUserLibraryModify scope. +// "Your Music" library. This call requires the [ScopeUserLibraryModify] scope. // A track can only be saved once; duplicate IDs are ignored. func (c *Client) AddTracksToLibrary(ctx context.Context, ids ...ID) error { return c.modifyLibrary(ctx, "tracks", true, ids...) } // RemoveTracksFromLibrary removes one or more tracks from the current user's -// "Your Music" library. This call requires the ScopeUserModifyLibrary scope. +// "Your Music" library. This call requires the [ScopeUserModifyLibrary] scope. // Trying to remove a track when you do not have the user's authorization -// results in a `spotify.Error` with the status code set to http.StatusUnauthorized. +// results in an [Error] with the status code set to [net/http.StatusUnauthorized]. func (c *Client) RemoveTracksFromLibrary(ctx context.Context, ids ...ID) error { return c.modifyLibrary(ctx, "tracks", false, ids...) } // AddAlbumsToLibrary saves one or more albums to the current user's -// "Your Albums" library. This call requires the ScopeUserLibraryModify scope. +// "Your Albums" library. This call requires the [ScopeUserLibraryModify] scope. // A track can only be saved once; duplicate IDs are ignored. func (c *Client) AddAlbumsToLibrary(ctx context.Context, ids ...ID) error { return c.modifyLibrary(ctx, "albums", true, ids...) } // RemoveAlbumsFromLibrary removes one or more albums from the current user's -// "Your Albums" library. This call requires the ScopeUserModifyLibrary scope. +// "Your Albums" library. This call requires the [ScopeUserModifyLibrary] scope. // Trying to remove a track when you do not have the user's authorization -// results in a `spotify.Error` with the status code set to http.StatusUnauthorized. +// results in an [Error] with the status code set to [net/http.StatusUnauthorized]. func (c *Client) RemoveAlbumsFromLibrary(ctx context.Context, ids ...ID) error { return c.modifyLibrary(ctx, "albums", false, ids...) } diff --git a/page.go b/page.go index 1e3ded2..e8b6475 100644 --- a/page.go +++ b/page.go @@ -35,49 +35,49 @@ type basePage struct { Previous string `json:"previous"` } -// FullArtistPage contains FullArtists returned by the Web API. +// FullArtistPage contains [FullArtists] returned by the Web API. type FullArtistPage struct { basePage Artists []FullArtist `json:"items"` } -// SimpleAlbumPage contains SimpleAlbums returned by the Web API. +// SimpleAlbumPage contains [SimpleAlbums] returned by the Web API. type SimpleAlbumPage struct { basePage Albums []SimpleAlbum `json:"items"` } -// SavedAlbumPage contains SavedAlbums returned by the Web API. +// SavedAlbumPage contains [SavedAlbums] returned by the Web API. type SavedAlbumPage struct { basePage Albums []SavedAlbum `json:"items"` } -// SavedShowPage contains SavedShows returned by the Web API +// SavedShowPage contains [SavedShows] returned by the Web API type SavedShowPage struct { basePage Shows []SavedShow `json:"items"` } -// SimplePlaylistPage contains SimplePlaylists returned by the Web API. +// SimplePlaylistPage contains [SimplePlaylists] returned by the Web API. type SimplePlaylistPage struct { basePage Playlists []SimplePlaylist `json:"items"` } -// SimpleTrackPage contains SimpleTracks returned by the Web API. +// SimpleTrackPage contains [SimpleTracks] returned by the Web API. type SimpleTrackPage struct { basePage Tracks []SimpleTrack `json:"items"` } -// FullTrackPage contains FullTracks returned by the Web API. +// FullTrackPage contains [FullTracks] returned by the Web API. type FullTrackPage struct { basePage Tracks []FullTrack `json:"items"` } -// SavedTrackPage contains SavedTracks return by the Web API. +// SavedTrackPage contains [SavedTracks] return by the Web API. type SavedTrackPage struct { basePage Tracks []SavedTrack `json:"items"` @@ -89,19 +89,19 @@ type PlaylistTrackPage struct { Tracks []PlaylistTrack `json:"items"` } -// CategoryPage contains Category objects returned by the Web API. +// CategoryPage contains [Category] objects returned by the Web API. type CategoryPage struct { basePage Categories []Category `json:"items"` } -// SimpleEpisodePage contains EpisodePage returned by the Web API. +// SimpleEpisodePage contains [EpisodePage] returned by the Web API. type SimpleEpisodePage struct { basePage Episodes []EpisodePage `json:"items"` } -// SimpleShowPage contains ShowPage returned by the Web API. +// SimpleShowPage contains [ShowPage] returned by the Web API. type SimpleShowPage struct { basePage Shows []FullShow `json:"items"` @@ -114,7 +114,7 @@ type pageable interface{ canPage() } func (b *basePage) canPage() {} // NextPage fetches the next page of items and writes them into p. -// It returns ErrNoMorePages if p already contains the last page. +// It returns [ErrNoMorePages] if p already contains the last page. func (c *Client) NextPage(ctx context.Context, p pageable) error { if p == nil || reflect.ValueOf(p).IsNil() { return fmt.Errorf("spotify: p must be a non-nil pointer to a page") @@ -138,7 +138,7 @@ func (c *Client) NextPage(ctx context.Context, p pageable) error { } // PreviousPage fetches the previous page of items and writes them into p. -// It returns ErrNoMorePages if p already contains the last page. +// It returns [ErrNoMorePages] if p already contains the last page. func (c *Client) PreviousPage(ctx context.Context, p pageable) error { if p == nil || reflect.ValueOf(p).IsNil() { return fmt.Errorf("spotify: p must be a non-nil pointer to a page") diff --git a/player.go b/player.go index 34f11fc..4b0008e 100755 --- a/player.go +++ b/player.go @@ -10,7 +10,7 @@ import ( "time" ) -// PlayerDevice contains information about a device that a user can play music on +// PlayerDevice contains information about a device that a user can play music on. type PlayerDevice struct { // ID of the device. This may be empty. ID ID `json:"id"` @@ -38,7 +38,7 @@ type PlayerState struct { RepeatState string `json:"repeat_state"` } -// PlaybackContext is the playback context +// PlaybackContext is the playback context. type PlaybackContext struct { // ExternalURLs of the context, or null if not available. ExternalURLs map[string]string `json:"external_urls"` @@ -50,7 +50,7 @@ type PlaybackContext struct { URI URI `json:"uri"` } -// CurrentlyPlaying contains the information about currently playing items +// CurrentlyPlaying contains the information about currently playing items. type CurrentlyPlaying struct { // Timestamp when data was fetched Timestamp int64 `json:"timestamp"` @@ -79,7 +79,7 @@ type RecentlyPlayedResult struct { Items []RecentlyPlayedItem `json:"items"` } -// PlaybackOffset can be specified either by track URI OR Position. If the +// PlaybackOffset can be specified either by track URI or Position. If the // Position field is set to a non-nil pointer, it will be taken into // consideration when specifying the playback offset. If the Position field is // set to a nil pointer, it will be ignored and only the URI will be used to @@ -100,7 +100,7 @@ type PlayOptions struct { // PlaybackContext Spotify URI of the context to play. // Valid contexts are albums, artists & playlists. PlaybackContext *URI `json:"context_uri,omitempty"` - // URIs Array of the Spotify track URIs to play + // URIs Array of the Spotify track URIs to play. URIs []URI `json:"uris,omitempty"` // PlaybackOffset Indicates from where in the context playback should start. // Only available when context corresponds to an album or playlist @@ -114,9 +114,10 @@ type PlayOptions struct { } // RecentlyPlayedOptions describes options for the recently-played request. All -// fields are optional. Only one of `AfterEpochMs` and `BeforeEpochMs` may be -// given. Note that it seems as if Spotify only remembers the fifty most-recent -// tracks as of right now. +// fields are optional. Only one of AfterEpochMs and BeforeEpochMs may be +// given. +// +// Note: it seems as if Spotify only remembers the fifty most-recent tracks. type RecentlyPlayedOptions struct { // Limit is the maximum number of items to return. Must be no greater than // fifty. @@ -138,7 +139,7 @@ type Queue struct { // PlayerDevices information about available devices for the current user. // -// Requires the ScopeUserReadPlaybackState scope in order to read information +// Requires the [ScopeUserReadPlaybackState] scope in order to read information func (c *Client) PlayerDevices(ctx context.Context) ([]PlayerDevice, error) { var result struct { PlayerDevices []PlayerDevice `json:"devices"` @@ -153,9 +154,9 @@ func (c *Client) PlayerDevices(ctx context.Context) ([]PlayerDevice, error) { } // PlayerState gets information about the playing state for the current user -// Requires the ScopeUserReadPlaybackState scope in order to read information +// Requires the [ScopeUserReadPlaybackState] scope in order to read information // -// Supported options: Market +// Supported options: [Market]. func (c *Client) PlayerState(ctx context.Context, opts ...RequestOption) (*PlayerState, error) { spotifyURL := c.baseURL + "me/player" if params := processOptions(opts...).urlParams.Encode(); params != "" { @@ -175,10 +176,10 @@ func (c *Client) PlayerState(ctx context.Context, opts ...RequestOption) (*Playe // PlayerCurrentlyPlaying gets information about the currently playing status // for the current user. // -// Requires the ScopeUserReadCurrentlyPlaying scope or the ScopeUserReadPlaybackState -// scope in order to read information +// Requires the [ScopeUserReadCurrentlyPlaying] scope or the [ScopeUserReadPlaybackState] +// scope in order to read information. // -// Supported options: Market +// Supported options: [Market]. func (c *Client) PlayerCurrentlyPlaying(ctx context.Context, opts ...RequestOption) (*CurrentlyPlaying, error) { spotifyURL := c.baseURL + "me/player/currently-playing" @@ -201,12 +202,12 @@ func (c *Client) PlayerCurrentlyPlaying(ctx context.Context, opts ...RequestOpti } // PlayerRecentlyPlayed gets a list of recently-played tracks for the current -// user. This call requires ScopeUserReadRecentlyPlayed. +// user. This call requires [ScopeUserReadRecentlyPlayed]. func (c *Client) PlayerRecentlyPlayed(ctx context.Context) ([]RecentlyPlayedItem, error) { return c.PlayerRecentlyPlayedOpt(ctx, nil) } -// PlayerRecentlyPlayedOpt is like PlayerRecentlyPlayed, but it accepts +// PlayerRecentlyPlayedOpt is like [PlayerRecentlyPlayed], but it accepts // additional options for sorting and filtering the results. func (c *Client) PlayerRecentlyPlayedOpt(ctx context.Context, opt *RecentlyPlayedOptions) ([]RecentlyPlayedItem, error) { spotifyURL := c.baseURL + "me/player/recently-played" @@ -243,7 +244,7 @@ func (c *Client) PlayerRecentlyPlayedOpt(ctx context.Context, opt *RecentlyPlaye // paused on the new device you should send a pause command to the currently // active device before transferring to the new device_id. // -// Requires the ScopeUserModifyPlaybackState in order to modify the player state +// Requires the [ScopeUserModifyPlaybackState] in order to modify the player state. func (c *Client) TransferPlayback(ctx context.Context, deviceID ID, play bool) error { reqData := struct { DeviceID []ID `json:"device_ids"` @@ -274,12 +275,12 @@ func (c *Client) TransferPlayback(ctx context.Context, deviceID ID, play bool) e } // Play Start a new context or resume current playback on the user's active -// device. This call requires ScopeUserModifyPlaybackState in order to modify the player state. +// device. This call requires [ScopeUserModifyPlaybackState] in order to modify the player state. func (c *Client) Play(ctx context.Context) error { return c.PlayOpt(ctx, nil) } -// PlayOpt is like Play but with more options +// PlayOpt is like [Play] but with more options. func (c *Client) PlayOpt(ctx context.Context, opt *PlayOptions) error { spotifyURL := c.baseURL + "me/player/play" buf := new(bytes.Buffer) @@ -314,14 +315,14 @@ func (c *Client) PlayOpt(ctx context.Context, opt *PlayOptions) error { // Pause Playback on the user's currently active device. // -// Requires the ScopeUserModifyPlaybackState in order to modify the player state +// Requires the [ScopeUserModifyPlaybackState] in order to modify the player state. func (c *Client) Pause(ctx context.Context) error { return c.PauseOpt(ctx, nil) } -// PauseOpt is like Pause but with more options +// PauseOpt is like [Pause] but with more options. // -// Only expects PlayOptions.DeviceID, all other options will be ignored +// Only expects [PlayOptions.DeviceID], all other options will be ignored. func (c *Client) PauseOpt(ctx context.Context, opt *PlayOptions) error { spotifyURL := c.baseURL + "me/player/pause" @@ -349,7 +350,7 @@ func (c *Client) PauseOpt(ctx context.Context, opt *PlayOptions) error { } // GetQueue gets the user's queue on the user's currently -// active device. This call requires ScopeUserReadPlaybackState +// active device. This call requires [ScopeUserReadPlaybackState] func (c *Client) GetQueue(ctx context.Context) (*Queue, error) { spotifyURL := c.baseURL + "me/player/queue" v := url.Values{} @@ -368,15 +369,15 @@ func (c *Client) GetQueue(ctx context.Context) (*Queue, error) { } // QueueSong adds a song to the user's queue on the user's currently -// active device. This call requires ScopeUserModifyPlaybackState -// in order to modify the player state +// active device. This call requires [ScopeUserModifyPlaybackState] +// to modify the player state func (c *Client) QueueSong(ctx context.Context, trackID ID) error { return c.QueueSongOpt(ctx, trackID, nil) } -// QueueSongOpt is like QueueSong but with more options +// QueueSongOpt is like [QueueSong] but with more options. // -// Only expects PlayOptions.DeviceID, all other options will be ignored +// Only expects [PlayOptions.DeviceID], all other options will be ignored. func (c *Client) QueueSongOpt(ctx context.Context, trackID ID, opt *PlayOptions) error { uri := "spotify:track:" + trackID spotifyURL := c.baseURL + "me/player/queue" @@ -406,15 +407,15 @@ func (c *Client) QueueSongOpt(ctx context.Context, trackID ID, opt *PlayOptions) } // Next skips to the next track in the user's queue in the user's -// currently active device. This call requires ScopeUserModifyPlaybackState -// in order to modify the player state +// currently active device. This call requires [ScopeUserModifyPlaybackState] +// in order to modify the player state. func (c *Client) Next(ctx context.Context) error { return c.NextOpt(ctx, nil) } -// NextOpt is like Next but with more options +// NextOpt is like Next but with more options. // -// Only expects PlayOptions.DeviceID, all other options will be ignored +// Only expects [PlayOptions.DeviceID], all other options will be ignored. func (c *Client) NextOpt(ctx context.Context, opt *PlayOptions) error { spotifyURL := c.baseURL + "me/player/next" @@ -441,16 +442,16 @@ func (c *Client) NextOpt(ctx context.Context, opt *PlayOptions) error { return nil } -// Previous skips to the Previous track in the user's queue in the user's -// currently active device. This call requires ScopeUserModifyPlaybackState +// Previous skips to the previous track in the user's queue on the user's +// currently active device. This call requires [ScopeUserModifyPlaybackState] // in order to modify the player state func (c *Client) Previous(ctx context.Context) error { return c.PreviousOpt(ctx, nil) } -// PreviousOpt is like Previous but with more options +// PreviousOpt is like [Previous] but with more options. // -// Only expects PlayOptions.DeviceID, all other options will be ignored +// Only expects [PlayOptions.DeviceID], all other options will be ignored. func (c *Client) PreviousOpt(ctx context.Context, opt *PlayOptions) error { spotifyURL := c.baseURL + "me/player/previous" @@ -483,14 +484,14 @@ func (c *Client) PreviousOpt(ctx context.Context, opt *PlayOptions) error { // Passing in a position that is greater than the length of the track // will cause the player to start playing the next song. // -// Requires the ScopeUserModifyPlaybackState in order to modify the player state +// Requires the [ScopeUserModifyPlaybackState] in order to modify the player state. func (c *Client) Seek(ctx context.Context, position int) error { return c.SeekOpt(ctx, position, nil) } -// SeekOpt is like Seek but with more options +// SeekOpt is like [Seek] but with more options. // -// Only expects PlayOptions.DeviceID, all other options will be ignored +// Only expects [PlayOptions.DeviceID], all other options will be ignored. func (c *Client) SeekOpt(ctx context.Context, position int, opt *PlayOptions) error { return c.playerFuncWithOpt( ctx, @@ -511,9 +512,9 @@ func (c *Client) Repeat(ctx context.Context, state string) error { return c.RepeatOpt(ctx, state, nil) } -// RepeatOpt is like Repeat but with more options +// RepeatOpt is like [Repeat] but with more options. // -// Only expects PlayOptions.DeviceID, all other options will be ignored. +// Only expects [PlayOptions.DeviceID], all other options will be ignored. func (c *Client) RepeatOpt(ctx context.Context, state string, opt *PlayOptions) error { return c.playerFuncWithOpt( ctx, @@ -529,14 +530,14 @@ func (c *Client) RepeatOpt(ctx context.Context, state string, opt *PlayOptions) // // Percent is must be a value from 0 to 100 inclusive. // -// Requires the ScopeUserModifyPlaybackState in order to modify the player state +// Requires the [ScopeUserModifyPlaybackState] in order to modify the player state. func (c *Client) Volume(ctx context.Context, percent int) error { return c.VolumeOpt(ctx, percent, nil) } -// VolumeOpt is like Volume but with more options +// VolumeOpt is like [Volume] but with more options. // -// Only expects PlayOptions.DeviceID, all other options will be ignored +// Only expects [PlayOptions.DeviceID], all other options will be ignored. func (c *Client) VolumeOpt(ctx context.Context, percent int, opt *PlayOptions) error { return c.playerFuncWithOpt( ctx, @@ -550,14 +551,14 @@ func (c *Client) VolumeOpt(ctx context.Context, percent int, opt *PlayOptions) e // Shuffle switches shuffle on or off for user's playback. // -// Requires the ScopeUserModifyPlaybackState in order to modify the player state +// Requires the [ScopeUserModifyPlaybackState] in order to modify the player state. func (c *Client) Shuffle(ctx context.Context, shuffle bool) error { return c.ShuffleOpt(ctx, shuffle, nil) } -// ShuffleOpt is like Shuffle but with more options +// ShuffleOpt is like [Shuffle] but with more options. // -// Only expects PlayOptions.DeviceID, all other options will be ignored +// Only expects [PlayOptions.DeviceID], all other options will be ignored. func (c *Client) ShuffleOpt(ctx context.Context, shuffle bool, opt *PlayOptions) error { return c.playerFuncWithOpt( ctx, diff --git a/playlist.go b/playlist.go index 80c59bf..2e8a4c6 100644 --- a/playlist.go +++ b/playlist.go @@ -48,7 +48,7 @@ type SimplePlaylist struct { URI URI `json:"uri"` } -// FullPlaylist provides extra playlist data in addition to the data provided by SimplePlaylist. +// FullPlaylist provides extra playlist data in addition to the data provided by [SimplePlaylist]. type FullPlaylist struct { SimplePlaylist // Information about the followers of this playlist. @@ -56,8 +56,11 @@ type FullPlaylist struct { Tracks PlaylistTrackPage `json:"tracks"` } -// FeaturedPlaylistsOpt gets a list of playlists featured by Spotify. -// Supported options: Locale, Country, Timestamp, Limit, Offset +// FeaturedPlaylists gets a [list of playlists featured by Spotify]. +// +// Supported options: [Locale], [Country], [Timestamp], [Limit], [Offset]. +// +// [list of playlists featured by Spotify]: https://developer.spotify.com/documentation/web-api/reference/get-featured-playlists func (c *Client) FeaturedPlaylists(ctx context.Context, opts ...RequestOption) (message string, playlists *SimplePlaylistPage, e error) { spotifyURL := c.baseURL + "browse/featured-playlists" if params := processOptions(opts...).urlParams.Encode(); params != "" { @@ -77,14 +80,16 @@ func (c *Client) FeaturedPlaylists(ctx context.Context, opts ...RequestOption) ( return result.Message, &result.Playlists, nil } -// FollowPlaylist adds the current user as a follower of the specified +// FollowPlaylist [adds the current user as a follower] of the specified // playlist. Any playlist can be followed, regardless of its private/public // status, as long as you know the playlist ID. // // If the public argument is true, then the playlist will be included in the // user's public playlists. To be able to follow playlists privately, the user -// must have granted the ScopePlaylistModifyPrivate scope. The -// ScopePlaylistModifyPublic scope is required to follow playlists publicly. +// must have granted the [ScopePlaylistModifyPrivate] scope. The +// [ScopePlaylistModifyPublic] scope is required to follow playlists publicly. +// +// [adds the current user as a follower]: https://developer.spotify.com/documentation/web-api/reference/follow-playlist func (c *Client) FollowPlaylist(ctx context.Context, playlist ID, public bool) error { spotifyURL := buildFollowURI(c.baseURL, playlist) body := strings.NewReader(strconv.FormatBool(public)) @@ -100,9 +105,11 @@ func (c *Client) FollowPlaylist(ctx context.Context, playlist ID, public bool) e return nil } -// UnfollowPlaylist removes the current user as a follower of a playlist. -// Unfollowing a publicly followed playlist requires ScopePlaylistModifyPublic. -// Unfolowing a privately followed playlist requies ScopePlaylistModifyPrivate. +// UnfollowPlaylist [removes the current user as a follower of a playlist]. +// Unfollowing a publicly followed playlist requires [ScopePlaylistModifyPublic]. +// Unfolowing a privately followed playlist requies [ScopePlaylistModifyPrivate]. +// +// [removes the current user as a follower of a playlist]: https://developer.spotify.com/documentation/web-api/reference/unfollow-playlist func (c *Client) UnfollowPlaylist(ctx context.Context, playlist ID) error { spotifyURL := buildFollowURI(c.baseURL, playlist) req, err := http.NewRequestWithContext(ctx, "DELETE", spotifyURL, nil) @@ -121,17 +128,19 @@ func buildFollowURI(url string, playlist ID) string { url, string(playlist)) } -// GetPlaylistsForUser gets a list of the playlists owned or followed by a +// GetPlaylistsForUser [gets a list of the playlists] owned or followed by a // particular Spotify user. // // Private playlists and collaborative playlists are only retrievable for the // current user. In order to read private playlists, the user must have granted -// the ScopePlaylistReadPrivate scope. Note that this scope alone will not +// the [ScopePlaylistReadPrivate] scope. Note that this scope alone will not // return collaborative playlists, even though they are always private. In // order to read collaborative playlists, the user must have granted the -// ScopePlaylistReadCollaborative scope. +// [ScopePlaylistReadCollaborative] scope. +// +// Supported options: [Limit], [Offset]. // -// Supported options: Limit, Offset +// [gets a list of the playlists]: https://developer.spotify.com/documentation/web-api/reference/get-list-users-playlists func (c *Client) GetPlaylistsForUser(ctx context.Context, userID string, opts ...RequestOption) (*SimplePlaylistPage, error) { spotifyURL := c.baseURL + "users/" + userID + "/playlists" if params := processOptions(opts...).urlParams.Encode(); params != "" { @@ -148,8 +157,11 @@ func (c *Client) GetPlaylistsForUser(ctx context.Context, userID string, opts .. return &result, err } -// GetPlaylist fetches a playlist from spotify. -// Supported options: Fields +// GetPlaylist [fetches a playlist] from spotify. +// +// Supported options: [Fields]. +// +// [fetches a playlist]: https://developer.spotify.com/documentation/web-api/reference/get-playlist func (c *Client) GetPlaylist(ctx context.Context, playlistID ID, opts ...RequestOption) (*FullPlaylist, error) { spotifyURL := fmt.Sprintf("%splaylists/%s", c.baseURL, playlistID) if params := processOptions(opts...).urlParams.Encode(); params != "" { @@ -166,12 +178,12 @@ func (c *Client) GetPlaylist(ctx context.Context, playlistID ID, opts ...Request return &playlist, err } -// GetPlaylistTracks gets full details of the tracks in a playlist, given the +// GetPlaylistTracks [gets full details of the tracks in a playlist], given the // playlist's Spotify ID. // -// Supported options: Limit, Offset, Market, Fields +// Supported options: [Limit], [Offset], [Market], [Fields]. // -// Deprecated: the Spotify api is moving towards supporting both tracks and episodes. Use GetPlaylistItems which +// Deprecated: the Spotify api is moving towards supporting both tracks and episodes. Use [GetPlaylistItems] which // supports these. func (c *Client) GetPlaylistTracks( ctx context.Context, @@ -196,8 +208,8 @@ func (c *Client) GetPlaylistTracks( // PlaylistItem contains info about an item in a playlist. type PlaylistItem struct { // The date and time the track was added to the playlist. - // You can use the TimestampLayout constant to convert - // this field to a time.Time value. + // You can use [TimestampLayout] to convert + // this field to a [time.Time]. // Warning: very old playlists may not populate this value. AddedAt string `json:"added_at"` // The Spotify user who added the track to the playlist. @@ -259,10 +271,13 @@ type PlaylistItemPage struct { Items []PlaylistItem `json:"items"` } -// GetPlaylistItems gets full details of the items in a playlist, given the -// playlist's Spotify ID. +// GetPlaylistItems [gets full details of the items in a playlist], given the +// playlist's [Spotify ID]. // -// Supported options: Limit, Offset, Market, Fields +// Supported options: [Limit], [Offset], [Market], [Fields]. +// +// [gets full details of the items in a playlist]: https://developer.spotify.com/documentation/web-api/reference/get-playlists-tracks +// [Spotify ID]: https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids func (c *Client) GetPlaylistItems(ctx context.Context, playlistID ID, opts ...RequestOption) (*PlaylistItemPage, error) { spotifyURL := fmt.Sprintf("%splaylists/%s/tracks", c.baseURL, playlistID) @@ -283,15 +298,17 @@ func (c *Client) GetPlaylistItems(ctx context.Context, playlistID ID, opts ...Re return &result, err } -// CreatePlaylistForUser creates a playlist for a Spotify user. +// CreatePlaylistForUser [creates a playlist] for a Spotify user. // The playlist will be empty until you add tracks to it. // The playlistName does not need to be unique - a user can have // several playlists with the same name. // -// Creating a public playlist for a user requires ScopePlaylistModifyPublic; -// creating a private playlist requires ScopePlaylistModifyPrivate. +// Creating a public playlist for a user requires [ScopePlaylistModifyPublic]; +// creating a private playlist requires [ScopePlaylistModifyPrivate]. // // On success, the newly created playlist is returned. +// +// [creates a playlist]: https://developer.spotify.com/documentation/web-api/reference/create-playlist func (c *Client) CreatePlaylistForUser(ctx context.Context, userID, playlistName, description string, public bool, collaborative bool) (*FullPlaylist, error) { spotifyURL := fmt.Sprintf("%susers/%s/playlists", c.baseURL, userID) body := struct { @@ -324,41 +341,47 @@ func (c *Client) CreatePlaylistForUser(ctx context.Context, userID, playlistName return &p, err } -// ChangePlaylistName changes the name of a playlist. This call requires that the -// user has authorized the ScopePlaylistModifyPublic or ScopePlaylistModifyPrivate +// ChangePlaylistName [changes the name of a playlist]. This call requires that the +// user has authorized the [ScopePlaylistModifyPublic] or [ScopePlaylistModifyPrivate] // scopes (depending on whether the playlist is public or private). // The current user must own the playlist in order to modify it. +// +// [changes the name of a playlist]: https://developer.spotify.com/documentation/web-api/reference/change-playlist-details func (c *Client) ChangePlaylistName(ctx context.Context, playlistID ID, newName string) error { return c.modifyPlaylist(ctx, playlistID, newName, "", nil) } -// ChangePlaylistAccess modifies the public/private status of a playlist. This call -// requires that the user has authorized the ScopePlaylistModifyPublic or -// ScopePlaylistModifyPrivate scopes (depending on whether the playlist is -// currently public or private). The current user must own the playlist in order to modify it. +// ChangePlaylistAccess [modifies the public/private status of a playlist]. This call +// requires that the user has authorized the [ScopePlaylistModifyPublic] or +// [ScopePlaylistModifyPrivate] scopes (depending on whether the playlist is +// currently public or private). The current user must own the playlist to modify it. +// +// [modifies the public/private status of a playlist]: https://developer.spotify.com/documentation/web-api/reference/change-playlist-details func (c *Client) ChangePlaylistAccess(ctx context.Context, playlistID ID, public bool) error { return c.modifyPlaylist(ctx, playlistID, "", "", &public) } -// ChangePlaylistDescription modifies the description of a playlist. This call -// requires that the user has authorized the ScopePlaylistModifyPublic or -// ScopePlaylistModifyPrivate scopes (depending on whether the playlist is -// currently public or private). The current user must own the playlist in order to modify it. +// ChangePlaylistDescription [modifies the description of a playlist]. This call +// requires that the user has authorized the [ScopePlaylistModifyPublic] or +// [ScopePlaylistModifyPrivate] scopes (depending on whether the playlist is +// currently public or private). The current user must own the playlist to modify it. +// +// [modifies the description of a playlist]: https://developer.spotify.com/documentation/web-api/reference/change-playlist-details func (c *Client) ChangePlaylistDescription(ctx context.Context, playlistID ID, newDescription string) error { return c.modifyPlaylist(ctx, playlistID, "", newDescription, nil) } -// ChangePlaylistNameAndAccess combines ChangePlaylistName and ChangePlaylistAccess into -// a single Web API call. It requires that the user has authorized the ScopePlaylistModifyPublic -// or ScopePlaylistModifyPrivate scopes (depending on whether the playlist is currently -// public or private). The current user must own the playlist in order to modify it. +// ChangePlaylistNameAndAccess combines [ChangePlaylistName] and [ChangePlaylistAccess] into +// a single Web API call. It requires that the user has authorized the [ScopePlaylistModifyPublic] +// or [ScopePlaylistModifyPrivate] scopes (depending on whether the playlist is currently +// public or private). The current user must own the playlist to modify it. func (c *Client) ChangePlaylistNameAndAccess(ctx context.Context, playlistID ID, newName string, public bool) error { return c.modifyPlaylist(ctx, playlistID, newName, "", &public) } -// ChangePlaylistNameAccessAndDescription combines ChangePlaylistName, ChangePlaylistAccess, and -// ChangePlaylistDescription into a single Web API call. It requires that the user has authorized -// the ScopePlaylistModifyPublic or ScopePlaylistModifyPrivate scopes (depending on whether the +// ChangePlaylistNameAccessAndDescription combines [ChangePlaylistName], [ChangePlaylistAccess], and +// [ChangePlaylistDescription] into a single Web API call. It requires that the user has authorized +// the [ScopePlaylistModifyPublic] or [ScopePlaylistModifyPrivate] scopes (depending on whether the // playlist is currently public or private). The current user must own the playlist in order to modify it. func (c *Client) ChangePlaylistNameAccessAndDescription(ctx context.Context, playlistID ID, newName, newDescription string, public bool) error { return c.modifyPlaylist(ctx, playlistID, newName, newDescription, &public) @@ -391,11 +414,13 @@ func (c *Client) modifyPlaylist(ctx context.Context, playlistID ID, newName, new return nil } -// AddTracksToPlaylist adds one or more tracks to a user's playlist. -// This call requires ScopePlaylistModifyPublic or ScopePlaylistModifyPrivate. +// AddTracksToPlaylist [adds one or more tracks to a user's playlist]. +// This call requires [ScopePlaylistModifyPublic] or [ScopePlaylistModifyPrivate]. // A maximum of 100 tracks can be added per call. It returns a snapshot ID that // can be used to identify this version (the new version) of the playlist in // future requests. +// +// [adds one or more tracks to a user's playlist]: https://developer.spotify.com/documentation/web-api/reference/add-tracks-to-playlist func (c *Client) AddTracksToPlaylist(ctx context.Context, playlistID ID, trackIDs ...ID) (snapshotID string, err error) { uris := make([]string, len(trackIDs)) for i, id := range trackIDs { @@ -428,13 +453,15 @@ func (c *Client) AddTracksToPlaylist(ctx context.Context, playlistID ID, trackID return result.SnapshotID, nil } -// RemoveTracksFromPlaylist removes one or more tracks from a user's playlist. -// This call requires that the user has authorized the ScopePlaylistModifyPublic -// or ScopePlaylistModifyPrivate scopes. +// RemoveTracksFromPlaylist [removes one or more tracks from a user's playlist]. +// This call requires that the user has authorized the [ScopePlaylistModifyPublic] +// or [ScopePlaylistModifyPrivate] scopes. // // If the track(s) occur multiple times in the specified playlist, then all occurrences // of the track will be removed. If successful, the snapshot ID returned can be used to // identify the playlist version in future requests. +// +// [removes one or more tracks from a user's playlist]: https://developer.spotify.com/documentation/web-api/reference/remove-tracks-playlist func (c *Client) RemoveTracksFromPlaylist(ctx context.Context, playlistID ID, trackIDs ...ID) (newSnapshotID string, err error) { tracks := make([]struct { URI string `json:"uri"` @@ -454,7 +481,7 @@ type TrackToRemove struct { Positions []int `json:"positions"` } -// NewTrackToRemove creates a new TrackToRemove object with the specified +// NewTrackToRemove returns a [TrackToRemove] with the specified // track ID and playlist locations. func NewTrackToRemove(trackID string, positions []int) TrackToRemove { return TrackToRemove{ @@ -463,7 +490,7 @@ func NewTrackToRemove(trackID string, positions []int) TrackToRemove { } } -// RemoveTracksFromPlaylistOpt is like RemoveTracksFromPlaylist, but it supports +// RemoveTracksFromPlaylistOpt is like [RemoveTracksFromPlaylist], but it supports // optional parameters that offer more fine-grained control. Instead of deleting // all occurrences of a track, this function takes an index with each track URI // that indicates the position of the track in the playlist. @@ -520,16 +547,18 @@ func (c *Client) removeTracksFromPlaylist( return result.SnapshotID, err } -// ReplacePlaylistTracks replaces all of the tracks in a playlist, overwriting its +// ReplacePlaylistTracks [replaces all of the tracks in a playlist], overwriting its // existing tracks This can be useful for replacing or reordering tracks, or for // clearing a playlist. // // Modifying a public playlist requires that the user has authorized the -// ScopePlaylistModifyPublic scope. Modifying a private playlist requires the -// ScopePlaylistModifyPrivate scope. +// [ScopePlaylistModifyPublic] scope. Modifying a private playlist requires the +// [ScopePlaylistModifyPrivate] scope. // -// A maximum of 100 tracks is permitted in this call. Additional tracks must be -// added via AddTracksToPlaylist. +// A maximum of 100 tracks are permitted in this call. Additional tracks must be +// added via [AddTracksToPlaylist]. +// +// [replaces all of the tracks in a playlist]: https://developer.spotify.com/documentation/web-api/reference/reorder-or-replace-playlists-tracks func (c *Client) ReplacePlaylistTracks(ctx context.Context, playlistID ID, trackIDs ...ID) error { trackURIs := make([]string, len(trackIDs)) for i, u := range trackIDs { @@ -549,16 +578,18 @@ func (c *Client) ReplacePlaylistTracks(ctx context.Context, playlistID ID, track return nil } -// ReplacePlaylistItems replaces all the items in a playlist, overwriting its +// ReplacePlaylistItems [replaces all the items in a playlist], overwriting its // existing tracks This can be useful for replacing or reordering tracks, or for // clearing a playlist. // // Modifying a public playlist requires that the user has authorized the -// ScopePlaylistModifyPublic scope. Modifying a private playlist requires the -// ScopePlaylistModifyPrivate scope. +// [ScopePlaylistModifyPublic] scope. Modifying a private playlist requires the +// [ScopePlaylistModifyPrivate] scope. // // A maximum of 100 tracks is permited in this call. Additional tracks must be // added via AddTracksToPlaylist. +// +// [replaces all the items in a playlist]: https://developer.spotify.com/documentation/web-api/reference/reorder-or-replace-playlists-tracks func (c *Client) ReplacePlaylistItems(ctx context.Context, playlistID ID, items ...URI) (string, error) { m := make(map[string]interface{}) m["uris"] = items @@ -587,12 +618,14 @@ func (c *Client) ReplacePlaylistItems(ctx context.Context, playlistID ID, items return result.SnapshotID, nil } -// UserFollowsPlaylist checks if one or more (up to 5) Spotify users are following +// UserFollowsPlaylist [checks if one or more (up to 5) users are following] // a Spotify playlist, given the playlist's owner and ID. // // Checking if a user follows a playlist publicly doesn't require any scopes. // Checking if the user is privately following a playlist is only possible for the -// current user when that user has granted access to the ScopePlaylistReadPrivate scope. +// current user when that user has granted access to the [ScopePlaylistReadPrivate] scope. +// +// [checks if one or more (up to 5) users are following]: https://developer.spotify.com/documentation/web-api/reference/check-if-user-follows-playlist func (c *Client) UserFollowsPlaylist(ctx context.Context, playlistID ID, userIDs ...string) ([]bool, error) { spotifyURL := fmt.Sprintf("%splaylists/%s/followers/contains?ids=%s", c.baseURL, playlistID, strings.Join(userIDs, ",")) @@ -635,15 +668,15 @@ type PlaylistReorderOptions struct { } // ReorderPlaylistTracks reorders a track or group of tracks in a playlist. It -// returns a snapshot ID that can be used to identify the [newly modified] playlist +// returns a snapshot ID that can be used to identify the (newly modified) playlist // version in future requests. // -// See the docs for PlaylistReorderOptions for information on how the reordering +// See the docs for [PlaylistReorderOptions] for information on how the reordering // works. // -// Reordering tracks in the current user's public playlist requires ScopePlaylistModifyPublic. +// Reordering tracks in the current user's public playlist requires [ScopePlaylistModifyPublic]. // Reordering tracks in the user's private playlists (including collaborative playlists) requires -// ScopePlaylistModifyPrivate. +// [ScopePlaylistModifyPrivate]. func (c *Client) ReorderPlaylistTracks(ctx context.Context, playlistID ID, opt PlaylistReorderOptions) (snapshotID string, err error) { spotifyURL := fmt.Sprintf("%splaylists/%s/tracks", c.baseURL, playlistID) j, err := json.Marshal(opt) @@ -669,7 +702,8 @@ func (c *Client) ReorderPlaylistTracks(ctx context.Context, playlistID ID, opt P // SetPlaylistImage replaces the image used to represent a playlist. // This action can only be performed by the owner of the playlist, -// and requires ScopeImageUpload as well as ScopeModifyPlaylist{Public|Private}.. +// and requires [ScopeImageUpload] as well as [ScopeModifyPlaylistPublic] or +// [ScopeModifyPlaylistPrivate]. func (c *Client) SetPlaylistImage(ctx context.Context, playlistID ID, img io.Reader) error { spotifyURL := fmt.Sprintf("%splaylists/%s/images", c.baseURL, playlistID) // data flow: diff --git a/recommendation.go b/recommendation.go index f881c45..3eff7b1 100644 --- a/recommendation.go +++ b/recommendation.go @@ -16,19 +16,19 @@ type Seeds struct { Genres []string } -// count returns the total number of seeds contained in s +// count returns the total number of seeds contained in s. func (s Seeds) count() int { return len(s.Artists) + len(s.Tracks) + len(s.Genres) } -// Recommendations contains a list of recommended tracks based on seeds +// Recommendations contains a list of recommended tracks based on seeds. type Recommendations struct { Seeds []RecommendationSeed `json:"seeds"` Tracks []SimpleTrack `json:"tracks"` } // RecommendationSeed represents a recommendation seed after -// being processed by the Spotify API +// being processed by the Spotify API. type RecommendationSeed struct { AfterFilteringSize Numeric `json:"afterFilteringSize"` AfterRelinkingSize Numeric `json:"afterRelinkingSize"` @@ -38,7 +38,7 @@ type RecommendationSeed struct { Type string `json:"type"` } -// MaxNumberOfSeeds allowed by Spotify for a recommendation request +// MaxNumberOfSeeds allowed by Spotify for a recommendation request. const MaxNumberOfSeeds = 5 // setSeedValues sets url values into v for each seed in seeds @@ -67,14 +67,17 @@ func setTrackAttributesValues(trackAttributes *TrackAttributes, values url.Value } } -// GetRecommendations returns a list of recommended tracks based on the given seeds. -// Recommendations are generated based on the available information for a given seed entity -// and matched against similar artists and tracks. If there is sufficient information -// about the provided seeds, a list of tracks will be returned together with pool size details. -// For artists and tracks that are very new or obscure -// there might not be enough data to generate a list of tracks. +// GetRecommendations returns a [list of recommended tracks] based on the given +// seeds. Recommendations are generated based on the available information for a +// given seed entity and matched against similar artists and tracks. If there is +// sufficient information about the provided seeds, a list of tracks will be +// returned together with pool size details. For artists and tracks that are +// very new or obscure there might not be enough data to generate a list of +// tracks. // -// Supported options: Limit, Country +// Supported options: [Limit], [Country]. +// +// [list of recommended tracks]: https://developer.spotify.com/documentation/web-api/reference/get-recommendations func (c *Client) GetRecommendations(ctx context.Context, seeds Seeds, trackAttributes *TrackAttributes, opts ...RequestOption) (*Recommendations, error) { v := processOptions(opts...).urlParams @@ -99,8 +102,10 @@ func (c *Client) GetRecommendations(ctx context.Context, seeds Seeds, trackAttri return &recommendations, err } -// GetAvailableGenreSeeds retrieves a list of available genres seed parameter values for -// recommendations. +// GetAvailableGenreSeeds retrieves a [list of available genres] seed parameter +// values for recommendations. +// +// [list of available genres]: https://developer.spotify.com/documentation/web-api/reference/get-recommendation-genres func (c *Client) GetAvailableGenreSeeds(ctx context.Context) ([]string, error) { spotifyURL := c.baseURL + "recommendations/available-genre-seeds" diff --git a/request_options.go b/request_options.go index d973f15..5e84008 100644 --- a/request_options.go +++ b/request_options.go @@ -12,14 +12,14 @@ type requestOptions struct { urlParams url.Values } -// Limit sets the number of entries that a request should return +// Limit sets the number of entries that a request should return. func Limit(amount int) RequestOption { return func(o *requestOptions) { o.urlParams.Set("limit", strconv.Itoa(amount)) } } -// Market enables track re-linking +// Market enables track re-linking. func Market(code string) RequestOption { return func(o *requestOptions) { o.urlParams.Set("market", code) @@ -46,7 +46,7 @@ func Locale(code string) RequestOption { } } -// Offset sets the index of the first entry to return +// Offset sets the index of the first entry to return. func Offset(amount int) RequestOption { return func(o *requestOptions) { o.urlParams.Set("offset", strconv.Itoa(amount)) @@ -54,7 +54,7 @@ func Offset(amount int) RequestOption { } // Timestamp in ISO 8601 format (yyyy-MM-ddTHH:mm:ss). -// use this parameter to specify the user's local time to +// Use this parameter to specify the user's local time to // get results tailored for that specific date and time // in the day. If not provided, the response defaults to // the current UTC time. @@ -72,20 +72,24 @@ func After(after string) RequestOption { } // Fields is a comma-separated list of the fields to return. -// See the JSON tags on the FullPlaylist struct for valid field options. +// See the JSON tags on [FullPlaylist] for valid field options. // For example, to get just the playlist's description and URI: -// fields = "description,uri" +// +// fields = "description,uri" // // A dot separator can be used to specify non-reoccurring fields, while // parentheses can be used to specify reoccurring fields within objects. // For example, to get just the added date and the user ID of the adder: -// fields = "tracks.items(added_at,added_by.id)" +// +// fields = "tracks.items(added_at,added_by.id)" // // Use multiple parentheses to drill down into nested objects, for example: -// fields = "tracks.items(track(name,href,album(name,href)))" +// +// fields = "tracks.items(track(name,href,album(name,href)))" // // Fields can be excluded by prefixing them with an exclamation mark, for example; -// fields = "tracks.items(track(name,href,album(!name,href)))" +// +// fields = "tracks.items(track(name,href,album(!name,href)))" func Fields(fields string) RequestOption { return func(o *requestOptions) { o.urlParams.Set("fields", fields) @@ -103,8 +107,9 @@ const ( ShortTermRange Range = "short_term" ) -// Timerange sets the time period that spoty will use when returning information. Use LongTermRange, MediumTermRange -// and ShortTermRange to set the appropriate period. +// Timerange sets the time period that Spotify will use when returning +// information. Use [LongTermRange], [MediumTermRange] and [ShortTermRange] to +// set the appropriate period. func Timerange(timerange Range) RequestOption { return func(o *requestOptions) { o.urlParams.Set("time_range", string(timerange)) @@ -118,8 +123,9 @@ const ( TrackAdditionalType = "track" ) -// AdditionalTypes is a list of item types that your client supports besides the default track type. -// Valid types are: EpisodeAdditionalType and TrackAdditionalType. +// AdditionalTypes is a list of item types that your client supports besides +// the default track type. Valid types are: [EpisodeAdditionalType] and +// [TrackAdditionalType]. func AdditionalTypes(types ...AdditionalType) RequestOption { strTypes := make([]string, len(types)) for i, t := range types { diff --git a/search.go b/search.go index aabd8a3..21ead18 100644 --- a/search.go +++ b/search.go @@ -15,11 +15,12 @@ const ( MarketFromToken = "from_token" ) -// SearchType represents the type of a query used in the Search function. +// SearchType represents the type of a query used by [Search]. type SearchType int -// Search type values that can be passed to the Search function. These are flags -// that can be bitwise OR'd together to search for multiple types of content simultaneously. +// Search type values that can be passed to [Search]. These are flags +// that can be bitwise OR'd together to search for multiple types of content +// simultaneously. const ( SearchTypeAlbum SearchType = 1 << iota SearchTypeArtist = 1 << iota @@ -52,7 +53,7 @@ func (st SearchType) encode() string { return strings.Join(types, ",") } -// SearchResult contains the results of a call to Search. +// SearchResult contains the results of a call to [Search]. // Fields that weren't searched for will be nil pointers. type SearchResult struct { Artists *FullArtistPage `json:"artists"` @@ -63,19 +64,19 @@ type SearchResult struct { Episodes *SimpleEpisodePage `json:"episodes"` } -// Search gets Spotify catalog information about artists, albums, tracks, +// Search gets [Spotify catalog information] about artists, albums, tracks, // or playlists that match a keyword string. t is a mask containing one or more // search types. For example, `Search(query, SearchTypeArtist|SearchTypeAlbum)` // will search for artists or albums matching the specified keywords. // -// Matching +// # Matching // // Matching of search keywords is NOT case sensitive. Keywords are matched in // any order unless surrounded by double quotes. Searching for playlists will // return results where the query keyword(s) match any part of the playlist's // name or description. Only popular public playlists are returned. // -// Operators +// # Operators // // The operator NOT can be used to exclude results. For example, // query = "roadhouse NOT blues" returns items that match "roadhouse" but excludes @@ -85,14 +86,14 @@ type SearchResult struct { // // Operators should be specified in uppercase. // -// Wildcards +// # Wildcards // // The asterisk (*) character can, with some limitations, be used as a wildcard // (maximum of 2 per query). It will match a variable number of non-white-space // characters. It cannot be used in a quoted phrase, in a field filter, or as // the first character of a keyword string. // -// Field filters +// # Field filters // // By default, results are returned when a match is found in any field of the // target object type. Searches can be made more specific by specifying an album, @@ -118,7 +119,9 @@ type SearchResult struct { // If the client has a valid access token, then the results will only include // content playable in the user's country. // -// Limit, Market and Offset request options are supported +// Supported options: [Limit], [Market], [Offset]. +// +// [Spotify catalog information]: https://developer.spotify.com/documentation/web-api/reference/search func (c *Client) Search(ctx context.Context, query string, t SearchType, opts ...RequestOption) (*SearchResult, error) { v := processOptions(opts...).urlParams v.Set("q", query) diff --git a/show.go b/show.go index fb4a3f6..f7d8999 100644 --- a/show.go +++ b/show.go @@ -9,10 +9,9 @@ import ( ) type SavedShow struct { - // The date and time the show 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. + // The date and time the show was saved, represented as an ISO 8601 UTC + // timestamp with a zero offset (YYYY-MM-DDTHH:MM:SSZ). You can use + // [TimestampLayout] to convert this to a [time.Time]. AddedAt string `json:"added_at"` FullShow `json:"show"` } @@ -28,7 +27,9 @@ type FullShow struct { // SimpleShow contains basic data about a show. type SimpleShow struct { // A list of the countries in which the show can be played, - // identified by their ISO 3166-1 alpha-2 code. + // identified by their [ISO 3166-1 alpha-2] code. + // + // [ISO 3166-1 alpha-2]: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 AvailableMarkets []string `json:"available_markets"` // The copyright statements of the show. @@ -60,7 +61,9 @@ type SimpleShow struct { IsExternallyHosted *bool `json:"is_externally_hosted"` // A list of the languages used in the show, identified by - // their ISO 639 code. + // their [ISO 639] code. + // + // [ISO 639]: https://en.wikipedia.org/wiki/ISO_639 Languages []string `json:"languages"` // The media type of the show. @@ -99,7 +102,9 @@ type EpisodePage struct { // A link to the Web API endpoint providing full details of the episode. Href string `json:"href"` - // The Spotify ID for the episode. + // The [Spotify ID] for the episode. + // + // [Spotify ID]: https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids ID ID `json:"id"` // The cover art for the episode in various sizes, widest first. @@ -112,7 +117,9 @@ type EpisodePage struct { // Otherwise false. IsPlayable bool `json:"is_playable"` - // A list of the languages used in the episode, identified by their ISO 639 code. + // A list of the languages used in the episode, identified by their [ISO 639] code. + // + // [ISO 639]: https://en.wikipedia.org/wiki/ISO_639 Languages []string `json:"languages"` // The name of the episode. @@ -150,9 +157,9 @@ type ResumePointObject struct { ResumePositionMs Numeric `json:"resume_position_ms"` } -// ReleaseDateTime converts the show's ReleaseDate to a time.TimeValue. +// ReleaseDateTime converts [EpisodePage.ReleaseDate] to a [time.Time]. // All of the fields in the result may not be valid. For example, if -// ReleaseDatePrecision is "month", then only the month and year +// [EpisodePage.ReleaseDatePrecision] is "month", then only the month and year // (but not the day) of the result are valid. func (e *EpisodePage) ReleaseDateTime() time.Time { if e.ReleaseDatePrecision == "day" { @@ -169,9 +176,11 @@ func (e *EpisodePage) ReleaseDateTime() time.Time { return time.Date(year, 1, 1, 0, 0, 0, 0, time.UTC) } -// GetShow retrieves information about a specific show. -// API reference: https://developer.spotify.com/documentation/web-api/reference/#endpoint-get-a-show -// Supported options: Market +// GetShow retrieves information about a [specific show]. +// +// Supported options: [Market]. +// +// [specific show]: https://developer.spotify.com/documentation/web-api/reference/get-a-show func (c *Client) GetShow(ctx context.Context, id ID, opts ...RequestOption) (*FullShow, error) { spotifyURL := c.baseURL + "shows/" + string(id) if params := processOptions(opts...).urlParams.Encode(); params != "" { @@ -188,9 +197,11 @@ func (c *Client) GetShow(ctx context.Context, id ID, opts ...RequestOption) (*Fu return &result, nil } -// GetShowEpisodes retrieves paginated episode information about a specific show. -// API reference: https://developer.spotify.com/documentation/web-api/reference/#endpoint-get-a-shows-episodes -// Supported options: Market, Limit, Offset +// GetShowEpisodes retrieves paginated [episode information] about a specific show. +// +// Supported options: [Market], [Limit], [Offset]. +// +// [episode information]: https://developer.spotify.com/documentation/web-api/reference/get-a-shows-episodes func (c *Client) GetShowEpisodes(ctx context.Context, id string, opts ...RequestOption) (*SimpleEpisodePage, error) { spotifyURL := c.baseURL + "shows/" + id + "/episodes" if params := processOptions(opts...).urlParams.Encode(); params != "" { @@ -207,8 +218,9 @@ func (c *Client) GetShowEpisodes(ctx context.Context, id string, opts ...Request return &result, nil } -// SaveShowsForCurrentUser saves one or more shows to current Spotify user's library. -// API reference: https://developer.spotify.com/documentation/web-api/reference/#/operations/save-shows-user +// SaveShowsForCurrentUser [saves one or more shows] to current Spotify user's library. +// +// [saves one or more shows]: https://developer.spotify.com/documentation/web-api/reference/save-shows-user func (c *Client) SaveShowsForCurrentUser(ctx context.Context, ids []ID) error { spotifyURL := c.baseURL + "me/shows?ids=" + strings.Join(toStringSlice(ids), ",") req, err := http.NewRequestWithContext(ctx, http.MethodPut, spotifyURL, nil) @@ -219,8 +231,9 @@ func (c *Client) SaveShowsForCurrentUser(ctx context.Context, ids []ID) error { return c.execute(req, nil, http.StatusOK) } -// GetEpisode gets an episode from a show. -// API reference: https://developer.spotify.com/documentation/web-api/reference/get-an-episode +// GetEpisode gets an [episode] from a show. +// +// [episode]: https://developer.spotify.com/documentation/web-api/reference/get-an-episode func (c *Client) GetEpisode(ctx context.Context, id string, opts ...RequestOption) (*EpisodePage, error) { spotifyURL := c.baseURL + "episodes/" + id if params := processOptions(opts...).urlParams.Encode(); params != "" { diff --git a/track.go b/track.go index 306e779..24172cf 100644 --- a/track.go +++ b/track.go @@ -19,7 +19,9 @@ type SimpleTrack struct { Album SimpleAlbum `json:"album"` Artists []SimpleArtist `json:"artists"` // A list of the countries in which the track can be played, - // identified by their ISO 3166-1 alpha-2 codes. + // identified by their [ISO 3166-1 alpha-2] codes. + // + // [ISO 3166-1 alpha=2]: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 AvailableMarkets []string `json:"available_markets"` // The disc number (usually 1 unless the album consists of more than one disc). DiscNumber Numeric `json:"disc_number"` @@ -51,8 +53,9 @@ func (st SimpleTrack) String() string { return fmt.Sprintf("TRACK<[%s] [%s]>", st.ID, st.Name) } -// LinkedFromInfo -// See: https://developer.spotify.com/documentation/general/guides/track-relinking-guide/ +// LinkedFromInfo is included in a track response when [Track Relinking] is applied. +// +// [Track Relinking]: https://developer.spotify.com/documentation/general/guides/track-relinking-guide/ type LinkedFromInfo struct { // ExternalURLs are the known external APIs for this track or album ExternalURLs map[string]string `json:"external_urls"` @@ -66,11 +69,13 @@ type LinkedFromInfo struct { // Type of the link: album of the track Type string `json:"type"` - // URI is the Spotify URI of the track/album + // URI is the [Spotify URI] of the track/album. + // + // [Spotify URI]: https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids URI string `json:"uri"` } -// FullTrack provides extra track data in addition to what is provided by SimpleTrack. +// FullTrack provides extra track data in addition to what is provided by [SimpleTrack]. type FullTrack struct { SimpleTrack // Popularity of the track. The value will be between 0 and 100, @@ -78,21 +83,25 @@ type FullTrack struct { // both total plays and most recent plays. Popularity Numeric `json:"popularity"` - // IsPlayable defines if the track is playable. It's reported when the "market" parameter is passed to the tracks - // listing API. - // See: https://developer.spotify.com/documentation/general/guides/track-relinking-guide/ + // IsPlayable is included when [Track Relinking] is applied, and reports if + // the track is playable. It's reported when the "market" parameter is + // passed to the tracks listing API. + // + // [Track Relinking]: https://developer.spotify.com/documentation/general/guides/track-relinking-guide/ IsPlayable *bool `json:"is_playable"` - // LinkedFrom points to the linked track. It's reported when the "market" parameter is passed to the tracks listing - // API. + // LinkedFromInfo is included in a track response when [Track Relinking] is + // applied, and points to the linked track. It's reported when the "market" + // parameter is passed to the tracks listing API. + // + // [Track Relinking]: https://developer.spotify.com/documentation/general/guides/track-relinking-guide/ LinkedFrom *LinkedFromInfo `json:"linked_from"` } // PlaylistTrack contains info about a track in a playlist. type PlaylistTrack struct { - // The date and time the track was added to the playlist. - // You can use the TimestampLayout constant to convert - // this field to a time.Time value. + // The date and time the track was added to the playlist. You can use + // [TimestampLayout] to convert this field to a [time.Time]. // Warning: very old playlists may not populate this value. AddedAt string `json:"added_at"` // The Spotify user who added the track to the playlist. @@ -106,25 +115,25 @@ type PlaylistTrack struct { // SavedTrack provides info about a track saved to a user's account. type SavedTrack 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. + // 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 + // [TimestampLayout] to convert this to a [time.Time]. AddedAt string `json:"added_at"` FullTrack `json:"track"` } -// TimeDuration returns the track's duration as a time.Duration value. +// TimeDuration returns the track's duration as a [time.Duration] value. func (t *SimpleTrack) TimeDuration() time.Duration { return time.Duration(t.Duration) * time.Millisecond } // GetTrack gets Spotify catalog information for -// a single track identified by its unique Spotify ID. +// a [single track] identified by its unique [Spotify ID]. // -// API Doc: https://developer.spotify.com/documentation/web-api/reference/tracks/get-track/ +// Supported options: [Market]. // -// Supported options: Market +// [single track]: https://developer.spotify.com/documentation/web-api/reference/get-track +// [Spotify ID]: https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids func (c *Client) GetTrack(ctx context.Context, id ID, opts ...RequestOption) (*FullTrack, error) { spotifyURL := c.baseURL + "tracks/" + string(id) @@ -142,15 +151,15 @@ func (c *Client) GetTrack(ctx context.Context, id ID, opts ...RequestOption) (*F return &t, nil } -// GetTracks gets Spotify catalog information for multiple tracks based on their +// GetTracks gets Spotify catalog information for [multiple tracks] based on their // Spotify IDs. It supports up to 50 tracks in a single call. Tracks are // returned in the order requested. If a track is not found, that position in the // result will be nil. Duplicate ids in the query will result in duplicate // tracks in the result. // -// API Doc: https://developer.spotify.com/documentation/web-api/reference/tracks/get-several-tracks/ +// Supported options: [Market]. // -// Supported options: Market +// [multiple tracks]: https://developer.spotify.com/documentation/web-api/reference/get-several-tracks func (c *Client) GetTracks(ctx context.Context, ids []ID, opts ...RequestOption) ([]*FullTrack, error) { if len(ids) > 50 { return nil, errors.New("spotify: FindTracks supports up to 50 tracks") diff --git a/track_attributes.go b/track_attributes.go index 1154b9a..a6a36e2 100644 --- a/track_attributes.go +++ b/track_attributes.go @@ -2,25 +2,32 @@ package spotify // TrackAttributes contains various tuneable parameters that can be used for recommendations. // For each of the tuneable track attributes, target, min and max values may be provided. +// // Target: -// Tracks with the attribute values nearest to the target values will be preferred. -// For example, you might request TargetEnergy=0.6 and TargetDanceability=0.8. -// All target values will be weighed equally in ranking results. +// +// Tracks with the attribute values nearest to the target values will be preferred. +// For example, you might request TargetEnergy=0.6 and TargetDanceability=0.8. +// All target values will be weighed equally in ranking results. +// // Max: -// A hard ceiling on the selected track attribute’s value can be provided. -// For example, MaxInstrumentalness=0.35 would filter out most tracks -// that are likely to be instrumental. +// +// A hard ceiling on the selected track attribute’s value can be provided. +// For example, MaxInstrumentalness=0.35 would filter out most tracks +// that are likely to be instrumental. +// // Min: -// A hard floor on the selected track attribute’s value can be provided. -// For example, min_tempo=140 would restrict results to only those tracks -// with a tempo of greater than 140 beats per minute. +// +// A hard floor on the selected track attribute’s value can be provided. +// For example, min_tempo=140 would restrict results to only those tracks +// with a tempo of greater than 140 beats per minute. type TrackAttributes struct { intAttributes map[string]int floatAttributes map[string]float64 } -// NewTrackAttributes returns a new TrackAttributes instance with no attributes set. +// NewTrackAttributes returns a new [TrackAttributes] instance with no attributes set. // Attributes can then be chained following a builder pattern: +// // ta := NewTrackAttributes(). // MaxAcousticness(0.15). // TargetPopularity(90) @@ -31,7 +38,7 @@ func NewTrackAttributes() *TrackAttributes { } } -// MaxAcousticness sets the maximum acousticness +// MaxAcousticness sets the maximum acousticness. // Acousticness is a confidence measure from 0.0 to 1.0 of whether // the track is acoustic. A value of 1.0 represents high confidence // that the track is acoustic. @@ -40,7 +47,7 @@ func (ta *TrackAttributes) MaxAcousticness(acousticness float64) *TrackAttribute return ta } -// MinAcousticness sets the minimum acousticness +// MinAcousticness sets the minimum acousticness. // Acousticness is a confidence measure from 0.0 to 1.0 of whether // the track is acoustic. A value of 1.0 represents high confidence // that the track is acoustic. @@ -49,7 +56,7 @@ func (ta *TrackAttributes) MinAcousticness(acousticness float64) *TrackAttribute return ta } -// TargetAcousticness sets the target acousticness +// TargetAcousticness sets the target acousticness. // Acousticness is a confidence measure from 0.0 to 1.0 of whether // the track is acoustic. A value of 1.0 represents high confidence // that the track is acoustic. @@ -58,7 +65,7 @@ func (ta *TrackAttributes) TargetAcousticness(acousticness float64) *TrackAttrib return ta } -// MaxDanceability sets the maximum danceability +// MaxDanceability sets the maximum danceability. // Danceability describes how suitable a track is for dancing based on // a combination of musical elements including tempo, rhythm stability, // beat strength, and overall regularity. @@ -68,7 +75,7 @@ func (ta *TrackAttributes) MaxDanceability(danceability float64) *TrackAttribute return ta } -// MinDanceability sets the minimum danceability +// MinDanceability sets the minimum danceability. // Danceability describes how suitable a track is for dancing based on // a combination of musical elements including tempo, rhythm stability, // beat strength, and overall regularity. @@ -78,7 +85,7 @@ func (ta *TrackAttributes) MinDanceability(danceability float64) *TrackAttribute return ta } -// TargetDanceability sets the target danceability +// TargetDanceability sets the target danceability. // Danceability describes how suitable a track is for dancing based on // a combination of musical elements including tempo, rhythm stability, // beat strength, and overall regularity. @@ -88,25 +95,25 @@ func (ta *TrackAttributes) TargetDanceability(danceability float64) *TrackAttrib return ta } -// MaxDuration sets the maximum length of the track in milliseconds +// MaxDuration sets the maximum length of the track in milliseconds. func (ta *TrackAttributes) MaxDuration(duration int) *TrackAttributes { ta.intAttributes["max_duration_ms"] = duration return ta } -// MinDuration sets the minimum length of the track in milliseconds +// MinDuration sets the minimum length of the track in milliseconds. func (ta *TrackAttributes) MinDuration(duration int) *TrackAttributes { ta.intAttributes["min_duration_ms"] = duration return ta } -// TargetDuration sets the target length of the track in milliseconds +// TargetDuration sets the target length of the track in milliseconds. func (ta *TrackAttributes) TargetDuration(duration int) *TrackAttributes { ta.intAttributes["target_duration_ms"] = duration return ta } -// MaxEnergy sets the maximum energy +// MaxEnergy sets the maximum energy. // Energy is a measure from 0.0 to 1.0 and represents a perceptual measure // of intensity and activity. Typically, energetic tracks feel fast, loud, // and noisy. @@ -115,7 +122,7 @@ func (ta *TrackAttributes) MaxEnergy(energy float64) *TrackAttributes { return ta } -// MinEnergy sets the minimum energy +// MinEnergy sets the minimum energy. // Energy is a measure from 0.0 to 1.0 and represents a perceptual measure // of intensity and activity. Typically, energetic tracks feel fast, loud, // and noisy. @@ -124,7 +131,7 @@ func (ta *TrackAttributes) MinEnergy(energy float64) *TrackAttributes { return ta } -// TargetEnergy sets the target energy +// TargetEnergy sets the target energy. // Energy is a measure from 0.0 to 1.0 and represents a perceptual measure // of intensity and activity. Typically, energetic tracks feel fast, loud, // and noisy. @@ -133,7 +140,7 @@ func (ta *TrackAttributes) TargetEnergy(energy float64) *TrackAttributes { return ta } -// MaxInstrumentalness sets the maximum instrumentalness +// MaxInstrumentalness sets the maximum instrumentalness. // Instrumentalness predicts whether a track contains no vocals. // "Ooh" and "aah" sounds are treated as instrumental in this context. // Rap or spoken word tracks are clearly "vocal". @@ -144,10 +151,9 @@ func (ta *TrackAttributes) TargetEnergy(energy float64) *TrackAttributes { func (ta *TrackAttributes) MaxInstrumentalness(instrumentalness float64) *TrackAttributes { ta.floatAttributes["max_instrumentalness"] = instrumentalness return ta - } -// MinInstrumentalness sets the minimum instrumentalness +// MinInstrumentalness sets the minimum instrumentalness. // Instrumentalness predicts whether a track contains no vocals. // "Ooh" and "aah" sounds are treated as instrumental in this context. // Rap or spoken word tracks are clearly "vocal". @@ -158,10 +164,9 @@ func (ta *TrackAttributes) MaxInstrumentalness(instrumentalness float64) *TrackA func (ta *TrackAttributes) MinInstrumentalness(instrumentalness float64) *TrackAttributes { ta.floatAttributes["min_instrumentalness"] = instrumentalness return ta - } -// TargetInstrumentalness sets the target instrumentalness +// TargetInstrumentalness sets the target instrumentalness. // Instrumentalness predicts whether a track contains no vocals. // "Ooh" and "aah" sounds are treated as instrumental in this context. // Rap or spoken word tracks are clearly "vocal". @@ -172,34 +177,36 @@ func (ta *TrackAttributes) MinInstrumentalness(instrumentalness float64) *TrackA func (ta *TrackAttributes) TargetInstrumentalness(instrumentalness float64) *TrackAttributes { ta.floatAttributes["target_instrumentalness"] = instrumentalness return ta - } -// MaxKey sets the maximum key -// Integers map to pitches using standard Pitch Class notation -// (https://en.wikipedia.org/wiki/Pitch_class). +// MaxKey sets the maximum key. +// Integers map to pitches using standard [Pitch Class] notation +// +// [Pitch Class]: https://en.wikipedia.org/wiki/Pitch_class func (ta *TrackAttributes) MaxKey(key int) *TrackAttributes { ta.intAttributes["max_key"] = key return ta } -// MinKey sets the minimum key -// Integers map to pitches using standard Pitch Class notation -// (https://en.wikipedia.org/wiki/Pitch_class). +// MinKey sets the minimum key. +// Integers map to pitches using standard [Pitch Class] notation +// +// [Pitch Class]: https://en.wikipedia.org/wiki/Pitch_class func (ta *TrackAttributes) MinKey(key int) *TrackAttributes { ta.intAttributes["min_key"] = key return ta } -// TargetKey sets the target key -// Integers map to pitches using standard Pitch Class notation -// (https://en.wikipedia.org/wiki/Pitch_class). +// TargetKey sets the target key. +// Integers map to pitches using standard [Pitch Class] notation. +// +// [Pitch Class]: https://en.wikipedia.org/wiki/Pitch_class func (ta *TrackAttributes) TargetKey(key int) *TrackAttributes { ta.intAttributes["target_key"] = key return ta } -// MaxLiveness sets the maximum liveness +// MaxLiveness sets the maximum liveness. // Detects the presence of an audience in the recording. Higher liveness // values represent an increased probability that the track was performed live. // A value above 0.8 provides strong likelihood that the track is live. @@ -208,7 +215,7 @@ func (ta *TrackAttributes) MaxLiveness(liveness float64) *TrackAttributes { return ta } -// MinLiveness sets the minimum liveness +// MinLiveness sets the minimum liveness. // Detects the presence of an audience in the recording. Higher liveness // values represent an increased probability that the track was performed live. // A value above 0.8 provides strong likelihood that the track is live. @@ -217,7 +224,7 @@ func (ta *TrackAttributes) MinLiveness(liveness float64) *TrackAttributes { return ta } -// TargetLiveness sets the target liveness +// TargetLiveness sets the target liveness. // Detects the presence of an audience in the recording. Higher liveness // values represent an increased probability that the track was performed live. // A value above 0.8 provides strong likelihood that the track is live. @@ -226,7 +233,7 @@ func (ta *TrackAttributes) TargetLiveness(liveness float64) *TrackAttributes { return ta } -// MaxLoudness sets the maximum loudness in decibels (dB) +// MaxLoudness sets the maximum loudness in decibels (dB). // Loudness values are averaged across the entire track and are // useful for comparing the relative loudness of tracks. // Typical values range between -60 and 0 dB. @@ -235,7 +242,7 @@ func (ta *TrackAttributes) MaxLoudness(loudness float64) *TrackAttributes { return ta } -// MinLoudness sets the minimum loudness in decibels (dB) +// MinLoudness sets the minimum loudness in decibels (dB). // Loudness values are averaged across the entire track and are // useful for comparing the relative loudness of tracks. // Typical values range between -60 and 0 dB. @@ -244,7 +251,7 @@ func (ta *TrackAttributes) MinLoudness(loudness float64) *TrackAttributes { return ta } -// TargetLoudness sets the target loudness in decibels (dB) +// TargetLoudness sets the target loudness in decibels (dB). // Loudness values are averaged across the entire track and are // useful for comparing the relative loudness of tracks. // Typical values range between -60 and 0 dB. @@ -253,21 +260,21 @@ func (ta *TrackAttributes) TargetLoudness(loudness float64) *TrackAttributes { return ta } -// MaxMode sets the maximum mode +// MaxMode sets the maximum mode. // Mode indicates the modality (major or minor) of a track. func (ta *TrackAttributes) MaxMode(mode int) *TrackAttributes { ta.intAttributes["max_mode"] = mode return ta } -// MinMode sets the minimum mode +// MinMode sets the minimum mode. // Mode indicates the modality (major or minor) of a track. func (ta *TrackAttributes) MinMode(mode int) *TrackAttributes { ta.intAttributes["min_mode"] = mode return ta } -// TargetMode sets the target mode +// TargetMode sets the target mode. // Mode indicates the modality (major or minor) of a track. func (ta *TrackAttributes) TargetMode(mode int) *TrackAttributes { ta.intAttributes["target_mode"] = mode @@ -327,7 +334,6 @@ func (ta *TrackAttributes) TargetPopularity(popularity int) *TrackAttributes { func (ta *TrackAttributes) MaxSpeechiness(speechiness float64) *TrackAttributes { ta.floatAttributes["max_speechiness"] = speechiness return ta - } // MinSpeechiness sets the minimum speechiness. @@ -341,7 +347,6 @@ func (ta *TrackAttributes) MaxSpeechiness(speechiness float64) *TrackAttributes func (ta *TrackAttributes) MinSpeechiness(speechiness float64) *TrackAttributes { ta.floatAttributes["min_speechiness"] = speechiness return ta - } // TargetSpeechiness sets the target speechiness. @@ -373,10 +378,9 @@ func (ta *TrackAttributes) MinTempo(tempo float64) *TrackAttributes { func (ta *TrackAttributes) TargetTempo(tempo float64) *TrackAttributes { ta.floatAttributes["target_tempo"] = tempo return ta - } -// MaxTimeSignature sets the maximum time signature +// MaxTimeSignature sets the maximum time signature. // The time signature (meter) is a notational convention to // specify how many beats are in each bar (or measure). func (ta *TrackAttributes) MaxTimeSignature(timeSignature int) *TrackAttributes { @@ -384,7 +388,7 @@ func (ta *TrackAttributes) MaxTimeSignature(timeSignature int) *TrackAttributes return ta } -// MinTimeSignature sets the minimum time signature +// MinTimeSignature sets the minimum time signature. // The time signature (meter) is a notational convention to // specify how many beats are in each bar (or measure). func (ta *TrackAttributes) MinTimeSignature(timeSignature int) *TrackAttributes { @@ -392,7 +396,7 @@ func (ta *TrackAttributes) MinTimeSignature(timeSignature int) *TrackAttributes return ta } -// TargetTimeSignature sets the target time signature +// TargetTimeSignature sets the target time signature. // The time signature (meter) is a notational convention to // specify how many beats are in each bar (or measure). func (ta *TrackAttributes) TargetTimeSignature(timeSignature int) *TrackAttributes { @@ -402,7 +406,7 @@ func (ta *TrackAttributes) TargetTimeSignature(timeSignature int) *TrackAttribut // MaxValence sets the maximum valence. // Valence is a measure from 0.0 to 1.0 describing the musical positiveness -/// conveyed by a track. +// conveyed by a track. // Tracks with high valence sound more positive (e.g. happy, cheerful, euphoric), // while tracks with low valence sound more negative (e.g. sad, depressed, angry). func (ta *TrackAttributes) MaxValence(valence float64) *TrackAttributes { @@ -412,7 +416,7 @@ func (ta *TrackAttributes) MaxValence(valence float64) *TrackAttributes { // MinValence sets the minimum valence. // Valence is a measure from 0.0 to 1.0 describing the musical positiveness -/// conveyed by a track. +// / conveyed by a track. // Tracks with high valence sound more positive (e.g. happy, cheerful, euphoric), // while tracks with low valence sound more negative (e.g. sad, depressed, angry). func (ta *TrackAttributes) MinValence(valence float64) *TrackAttributes { @@ -422,7 +426,7 @@ func (ta *TrackAttributes) MinValence(valence float64) *TrackAttributes { // TargetValence sets the target valence. // Valence is a measure from 0.0 to 1.0 describing the musical positiveness -/// conveyed by a track. +// / conveyed by a track. // Tracks with high valence sound more positive (e.g. happy, cheerful, euphoric), // while tracks with low valence sound more negative (e.g. sad, depressed, angry). func (ta *TrackAttributes) TargetValence(valence float64) *TrackAttributes { diff --git a/user.go b/user.go index f9bc545..3b9f44d 100644 --- a/user.go +++ b/user.go @@ -34,28 +34,32 @@ type User struct { type PrivateUser struct { User // The country of the user, as set in the user's account profile. - // An ISO 3166-1 alpha-2 country code. This field is only available when the - // current user has granted access to the ScopeUserReadPrivate scope. + // An [ISO 3166-1 alpha-2] country code. This field is only available when + // the current user has granted access to the [ScopeUserReadPrivate] scope. + // + // [ISO 3166-1 alpha-2]: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 Country string `json:"country"` // The user's email address, as entered by the user when creating their account. // Note: this email is UNVERIFIED - there is no proof that it actually // belongs to the user. This field is only available when the current user - // has granted access to the ScopeUserReadEmail scope. + // has granted access to the [ScopeUserReadEmail] scope. Email string `json:"email"` // The user's Spotify subscription level: "premium", "free", etc. // The subscription level "open" can be considered the same as "free". // This field is only available when the current user has granted access to - // the ScopeUserReadPrivate scope. + // the [ScopeUserReadPrivate] scope. Product string `json:"product"` // The user's date of birth, in the format 'YYYY-MM-DD'. You can use - // the DateLayout constant to convert this to a time.Time value. - // This field is only available when the current user has granted - // access to the ScopeUserReadBirthdate scope. + // [DateLayout] to convert this to a [time.Time] value. This field is only + // available when the current user has granted access to the + // [ScopeUserReadBirthdate] scope. Birthdate string `json:"birthdate"` } -// GetUsersPublicProfile gets public profile information about a +// GetUsersPublicProfile gets [public profile] information about a // Spotify User. It does not require authentication. +// +// [public profile]: https://developer.spotify.com/documentation/web-api/reference/get-users-profile func (c *Client) GetUsersPublicProfile(ctx context.Context, userID ID) (*User, error) { spotifyURL := c.baseURL + "users/" + string(userID) @@ -70,17 +74,19 @@ func (c *Client) GetUsersPublicProfile(ctx context.Context, userID ID) (*User, e } // CurrentUser gets detailed profile information about the -// current user. +// [current user]. // // Reading the user's email address requires that the application -// has the ScopeUserReadEmail scope. Reading the country, display +// has the [ScopeUserReadEmail] scope. Reading the country, display // name, profile images, and product subscription level requires -// that the application has the ScopeUserReadPrivate scope. +// that the application has the [ScopeUserReadPrivate] scope. // // Warning: The email address in the response will be the address // that was entered when the user created their spotify account. // This email address is unverified - do not assume that Spotify has // checked that the email address actually belongs to the user. +// +// [current user]: https://developer.spotify.com/documentation/web-api/reference/get-current-users-profile func (c *Client) CurrentUser(ctx context.Context) (*PrivateUser, error) { var result PrivateUser @@ -92,12 +98,12 @@ func (c *Client) CurrentUser(ctx context.Context) (*PrivateUser, error) { return &result, nil } -// CurrentUsersShows gets a list of shows saved in the current +// CurrentUsersShows gets a [list of shows] saved in the current // Spotify user's "Your Music" library. // -// API Doc: https://developer.spotify.com/documentation/web-api/reference-beta/#endpoint-get-users-saved-shows +// Supported options: [Limit], [Offset]. // -// Supported options: Limit, Offset +// [list of shows]: https://developer.spotify.com/documentation/web-api/reference/get-users-saved-shows func (c *Client) CurrentUsersShows(ctx context.Context, opts ...RequestOption) (*SavedShowPage, error) { spotifyURL := c.baseURL + "me/shows" if params := processOptions(opts...).urlParams.Encode(); params != "" { @@ -114,12 +120,12 @@ func (c *Client) CurrentUsersShows(ctx context.Context, opts ...RequestOption) ( return &result, nil } -// CurrentUsersTracks gets a list of songs saved in the current +// CurrentUsersTracks gets a [list of songs] saved in the current // Spotify user's "Your Music" library. // -// API Doc: https://developer.spotify.com/documentation/web-api/reference-beta/#endpoint-get-users-saved-tracks +// Supported options: [Limit], [Country], [Offset]. // -// Supported options: Limit, Country, Offset +// [list of songs]: https://developer.spotify.com/documentation/web-api/reference/get-users-saved-tracks func (c *Client) CurrentUsersTracks(ctx context.Context, opts ...RequestOption) (*SavedTrackPage, error) { spotifyURL := c.baseURL + "me/tracks" if params := processOptions(opts...).urlParams.Encode(); params != "" { @@ -136,51 +142,63 @@ func (c *Client) CurrentUsersTracks(ctx context.Context, opts ...RequestOption) return &result, nil } -// FollowUser adds the current user as a follower of one or more -// spotify users, identified by their Spotify IDs. +// FollowUser [adds the current user as a follower] of one or more +// spotify users, identified by their [Spotify ID]s. // // Modifying the lists of artists or users the current user follows -// requires that the application has the ScopeUserFollowModify scope. +// requires that the application has the [ScopeUserFollowModify] scope. +// +// [adds the current user as a follower]: https://developer.spotify.com/documentation/web-api/reference/follow-artists-users +// [Spotify ID]: https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids func (c *Client) FollowUser(ctx context.Context, ids ...ID) error { return c.modifyFollowers(ctx, "user", true, ids...) } -// FollowArtist adds the current user as a follower of one or more -// spotify artists, identified by their Spotify IDs. +// FollowArtist [adds the current user as a follower] of one or more +// spotify artists, identified by their [Spotify ID]s. // // Modifying the lists of artists or users the current user follows -// requires that the application has the ScopeUserFollowModify scope. +// requires that the application has the [ScopeUserFollowModify] scope. +// +// [adds the current user as a follower]: https://developer.spotify.com/documentation/web-api/reference/follow-artists-users +// [Spotify ID]: https://developer.spotify.com/documentation/web-api/#spotify-uris-and-ids func (c *Client) FollowArtist(ctx context.Context, ids ...ID) error { return c.modifyFollowers(ctx, "artist", true, ids...) } -// UnfollowUser removes the current user as a follower of one or more +// UnfollowUser [removes the current user as a follower] of one or more // Spotify users. // // Modifying the lists of artists or users the current user follows -// requires that the application has the ScopeUserFollowModify scope. +// requires that the application has the [ScopeUserFollowModify] scope. +// +// [removes the current user as a follower]: https://developer.spotify.com/documentation/web-api/reference/unfollow-artists-users func (c *Client) UnfollowUser(ctx context.Context, ids ...ID) error { return c.modifyFollowers(ctx, "user", false, ids...) } -// UnfollowArtist removes the current user as a follower of one or more +// UnfollowArtist [removes the current user as a follower] of one or more // Spotify artists. // // Modifying the lists of artists or users the current user follows -// requires that the application has the ScopeUserFollowModify scope. +// requires that the application has the [ScopeUserFollowModify] scope. +// +// [removes the current user as a follower]: https://developer.spotify.com/documentation/web-api/reference/unfollow-artists-users func (c *Client) UnfollowArtist(ctx context.Context, ids ...ID) error { return c.modifyFollowers(ctx, "artist", false, ids...) } -// CurrentUserFollows checks to see if the current user is following +// CurrentUserFollows [checks to see if the current user is following] // one or more artists or other Spotify Users. This call requires -// ScopeUserFollowRead. +// [ScopeUserFollowRead]. // // The t argument indicates the type of the IDs, and must be either // "user" or "artist". // // The result is returned as a slice of bool values in the same order // in which the IDs were specified. +// +// [checks to see if the current user is following]: https://developer.spotify.com/documentation/web-api/reference/check-current-user-follows func (c *Client) CurrentUserFollows(ctx context.Context, t string, ids ...ID) ([]bool, error) { if l := len(ids); l == 0 || l > 50 { return nil, errors.New("spotify: UserFollows supports 1 to 50 IDs") @@ -224,9 +242,12 @@ func (c *Client) modifyFollowers(ctx context.Context, usertype string, follow bo return nil } -// CurrentUsersFollowedArtists gets the current user's followed artists. -// This call requires that the user has granted the ScopeUserFollowRead scope. -// Supported options: Limit, After +// CurrentUsersFollowedArtists gets the [current user's followed artists]. +// This call requires that the user has granted the [ScopeUserFollowRead] scope. +// +// Supported options: [Limit], [After]. +// +// [current user's followed artists]: https://developer.spotify.com/documentation/web-api/reference/get-followed func (c *Client) CurrentUsersFollowedArtists(ctx context.Context, opts ...RequestOption) (*FullArtistCursorPage, error) { spotifyURL := c.baseURL + "me/following" v := processOptions(opts...).urlParams @@ -247,10 +268,12 @@ func (c *Client) CurrentUsersFollowedArtists(ctx context.Context, opts ...Reques return &result.A, nil } -// CurrentUsersAlbums gets a list of albums saved in the current +// CurrentUsersAlbums gets a [list of albums] saved in the current // Spotify user's "Your Music" library. // -// Supported options: Market, Limit, Offset +// Supported options: [Market], [Limit], [Offset]. +// +// [list of albums]: https://developer.spotify.com/documentation/web-api/reference/get-users-saved-albums func (c *Client) CurrentUsersAlbums(ctx context.Context, opts ...RequestOption) (*SavedAlbumPage, error) { spotifyURL := c.baseURL + "me/albums" if params := processOptions(opts...).urlParams.Encode(); params != "" { @@ -267,15 +290,17 @@ func (c *Client) CurrentUsersAlbums(ctx context.Context, opts ...RequestOption) return &result, nil } -// CurrentUsersPlaylists gets a list of the playlists owned or followed by +// CurrentUsersPlaylists gets a [list of the playlists] owned or followed by // the current spotify user. // -// Private playlists require the ScopePlaylistReadPrivate scope. Note that +// Private playlists require the [ScopePlaylistReadPrivate] scope. Note that // this scope alone will not return collaborative playlists, even though // they are always private. In order to retrieve collaborative playlists -// the user must authorize the ScopePlaylistReadCollaborative scope. +// the user must authorize the [ScopePlaylistReadCollaborative] scope. // -// Supported options: Limit, Offset +// Supported options: [Limit], [Offset]. +// +// [list of the playlists]: https://developer.spotify.com/documentation/web-api/reference/get-a-list-of-current-users-playlists func (c *Client) CurrentUsersPlaylists(ctx context.Context, opts ...RequestOption) (*SimplePlaylistPage, error) { spotifyURL := c.baseURL + "me/playlists" if params := processOptions(opts...).urlParams.Encode(); params != "" { @@ -292,10 +317,12 @@ func (c *Client) CurrentUsersPlaylists(ctx context.Context, opts ...RequestOptio return &result, nil } -// CurrentUsersTopArtists fetches a list of the user's top artists over the specified Timerange. -// The default is medium term. +// CurrentUsersTopArtists fetches a list of the [user's top artists] over the specified [Timerange]. +// The default is [MediumTermRange]. +// +// Supported options: [Limit], [Timerange] // -// Supported options: Limit, Timerange +// [user's top artists]: https://developer.spotify.com/documentation/web-api/reference/get-users-top-artists-and-tracks func (c *Client) CurrentUsersTopArtists(ctx context.Context, opts ...RequestOption) (*FullArtistPage, error) { spotifyURL := c.baseURL + "me/top/artists" if params := processOptions(opts...).urlParams.Encode(); params != "" { @@ -312,11 +339,13 @@ func (c *Client) CurrentUsersTopArtists(ctx context.Context, opts ...RequestOpti return &result, nil } -// CurrentUsersTopTracks fetches the user's top tracks over the specified Timerange -// sensible defaults. The default limit is 20 and the default timerange -// is medium_term. This call requires ScopeUserTopRead. +// CurrentUsersTopTracks fetches the [user's top tracks] over the specified +// [Timerange]. The default limit is 20 and the default timerange is +// [MediumTermRange]. This call requires [ScopeUserTopRead]. +// +// Supported options: [Limit], [Timerange], [Offset]. // -// Supported options: Limit, Timerange, Offset +// [user's top tracks]: https://developer.spotify.com/documentation/web-api/reference/get-users-top-artists-and-tracks func (c *Client) CurrentUsersTopTracks(ctx context.Context, opts ...RequestOption) (*FullTrackPage, error) { spotifyURL := c.baseURL + "me/top/tracks" if params := processOptions(opts...).urlParams.Encode(); params != "" {