Skip to content

Commit 0874ac5

Browse files
committed
document SpotifyAPI methods
1 parent 780566d commit 0874ac5

File tree

8 files changed

+290
-16
lines changed

8 files changed

+290
-16
lines changed

src/main/kotlin/com/adamratzman/spotify/endpoints/pub/browse/BrowseAPI.kt

Lines changed: 137 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,39 +2,124 @@ package com.adamratzman.spotify.endpoints.pub.browse
22

33
import com.adamratzman.spotify.main.SpotifyAPI
44
import com.adamratzman.spotify.utils.*
5+
import org.json.JSONObject
6+
import java.sql.Timestamp
57
import java.util.function.Supplier
68
import java.util.stream.Collectors
79

810
/**
911
* Endpoints for getting playlists and new album releases featured on Spotify’s Browse tab.
1012
*/
1113
class BrowseAPI(api: SpotifyAPI) : SpotifyEndpoint(api) {
14+
/**
15+
* Get available genre seeds for recommendations
16+
*
17+
* @return List of genre ids
18+
*/
19+
fun getAvailableGenreSeeds(): SpotifyRestAction<List<String>> {
20+
return toAction(Supplier {
21+
JSONObject(get("https://api.spotify.com/v1/recommendations/available-genre-seeds")).getJSONArray("genres").map { it.toString() }
22+
})
23+
}
24+
25+
/**
26+
* Get a list of new album releases featured in Spotify (shown, for example, on a Spotify player’s “Browse” tab).
27+
*
28+
* @param limit The number of album objects to return. Default: 20. Minimum: 1. Maximum: 50.
29+
* @param offset The index of the first album to return. Default: 0 (i.e., the first album). Use with limit to get the next set of albums.
30+
* @param market Provide this parameter if you want the list of returned items to be relevant to a particular country.
31+
* If omitted, the returned items will be relevant to all countries.
32+
*
33+
* @throws BadRequestException if filter parameters are illegal
34+
*/
1235
fun getNewReleases(limit: Int = 20, offset: Int = 0, market: Market? = null): SpotifyRestAction<PagingObject<Album>> {
1336
return toAction(Supplier {
1437
get("https://api.spotify.com/v1/browse/new-releases?limit=$limit&offset=$offset${if (market != null) "&market=${market.code}" else ""}")
1538
.toPagingObject<Album>("albums", api)
1639
})
1740
}
1841

19-
fun getFeaturedPlaylists(limit: Int = 20, offset: Int = 0, locale: String? = null, market: Market? = null): SpotifyRestAction<FeaturedPlaylists> {
42+
/**
43+
* Get a list of Spotify featured playlists (shown, for example, on a Spotify player’s ‘Browse’ tab).
44+
*
45+
* @param limit The number of album objects to return. Default: 20. Minimum: 1. Maximum: 50.
46+
* @param offset The index of the first album to return. Default: 0 (i.e., the first album). Use with limit to get the next set of albums.
47+
* @param locale The desired language, consisting of a lowercase ISO 639-1 language code and an uppercase ISO 3166-1 alpha-2 country code, joined by an underscore. For example: es_MX, meaning “Spanish (Mexico)”.
48+
* Provide this parameter if you want the results returned in a particular language (where available).
49+
* Note that, if locale is not supplied, or if the specified language is not available,
50+
* all strings will be returned in the Spotify default language (American English. The locale parameter, combined with the country parameter, may give odd results if not carefully matched.
51+
* For example country=SE&locale=de_DE will return a list of categories relevant to Sweden but as German language strings.
52+
* @param market Provide this parameter if you want the list of returned items to be relevant to a particular country.
53+
* If omitted, the returned items will be relevant to all countries.
54+
* @param timestamp Use this parameter to specify the user’s local time to get results tailored for that specific
55+
* date and time in the day. If not provided, the response defaults to the current UTC time.
56+
*
57+
* @throws BadRequestException if filter parameters are illegal or [locale] does not exist
58+
*/
59+
fun getFeaturedPlaylists(limit: Int = 20, offset: Int = 0, locale: String? = null, market: Market? = null, timestamp: Timestamp? = null): SpotifyRestAction<FeaturedPlaylists> {
2060
return toAction(Supplier {
21-
get("https://api.spotify.com/v1/browse/featured-playlists?limit=$limit&offset=$offset${if (locale != null) "&locale=$locale" else ""}${if (market != null) "&market=${market.code}" else ""}").toObject<FeaturedPlaylists>(api)
61+
timestamp?.let { timestamp.time = 1000 * (Math.floor(timestamp.time / 1000.0).toLong()) }
62+
get("https://api.spotify.com/v1/browse/featured-playlists?limit=$limit&offset=$offset" +
63+
"${if (locale != null) "&locale=$locale" else ""}${if (market != null) "&market=${market.code}" else ""}${if (timestamp != null) "&timestamp=$timestamp" else ""}")
64+
.toObject<FeaturedPlaylists>(api)
2265
})
2366
}
2467

68+
/**
69+
* Get a list of categories used to tag items in Spotify (on, for example, the Spotify player’s “Browse” tab).
70+
*
71+
* @param limit The number of album objects to return. Default: 20. Minimum: 1. Maximum: 50.
72+
* @param offset The index of the first album to return. Default: 0 (i.e., the first album). Use with limit to get the next set of albums.
73+
* @param locale The desired language, consisting of a lowercase ISO 639-1 language code and an uppercase ISO 3166-1 alpha-2 country code, joined by an underscore. For example: es_MX, meaning “Spanish (Mexico)”.
74+
* Provide this parameter if you want the results returned in a particular language (where available).
75+
* Note that, if locale is not supplied, or if the specified language is not available,
76+
* all strings will be returned in the Spotify default language (American English. The locale parameter, combined with the country parameter, may give odd results if not carefully matched.
77+
* For example country=SE&locale=de_DE will return a list of categories relevant to Sweden but as German language strings.
78+
* @param market Provide this parameter if you want the list of returned items to be relevant to a particular country.
79+
* If omitted, the returned items will be relevant to all countries.
80+
*/
2581
fun getCategoryList(limit: Int = 20, offset: Int = 0, locale: String? = null, market: Market? = null): SpotifyRestAction<PagingObject<SpotifyCategory>> {
2682
return toAction(Supplier {
2783
get("https://api.spotify.com/v1/browse/categories?limit=$limit&offset=$offset${if (locale != null) "&locale=$locale" else ""}${if (market != null) "&market=${market.code}" else ""}")
2884
.toPagingObject<SpotifyCategory>("categories", api)
2985
})
3086
}
3187

32-
fun getCategory(categoryId: String, market: Market? = null): SpotifyRestAction<SpotifyCategory> {
88+
/**
89+
* Get a single category used to tag items in Spotify (on, for example, the Spotify player’s “Browse” tab).
90+
*
91+
* @param locale The desired language, consisting of a lowercase ISO 639-1 language code and an uppercase ISO 3166-1 alpha-2 country code, joined by an underscore. For example: es_MX, meaning “Spanish (Mexico)”.
92+
* Provide this parameter if you want the results returned in a particular language (where available).
93+
* Note that, if locale is not supplied, or if the specified language is not available,
94+
* all strings will be returned in the Spotify default language (American English. The locale parameter, combined with the country parameter, may give odd results if not carefully matched.
95+
* For example country=SE&locale=de_DE will return a list of categories relevant to Sweden but as German language strings.
96+
* @param market Provide this parameter if you want the list of returned items to be relevant to a particular country.
97+
* If omitted, the returned items will be relevant to all countries.
98+
*
99+
* @throws BadRequestException if [categoryId] is not found or [locale] does not exist on Spotify
100+
*/
101+
fun getCategory(categoryId: String, market: Market? = null, locale: String? = null): SpotifyRestAction<SpotifyCategory> {
33102
return toAction(Supplier {
34-
get("https://api.spotify.com/v1/browse/categories/${categoryId.encode()}${if (market != null) "?market=${market.code}" else ""}").toObject<SpotifyCategory>(api)
103+
val params = when {
104+
market != null && locale == null -> "?market=${market.code}"
105+
market == null && locale != null -> "?locale=$locale"
106+
market != null && locale != null -> "?market=${market.code}&locale=$locale"
107+
else -> null
108+
}
109+
get("https://api.spotify.com/v1/browse/categories/${categoryId.encode()}" + params).toObject<SpotifyCategory>(api)
35110
})
36111
}
37112

113+
/**
114+
* Get a list of Spotify playlists tagged with a particular category.
115+
*
116+
* @param market Provide this parameter if you want the list of returned items to be relevant to a particular country.
117+
* If omitted, the returned items will be relevant to all countries.
118+
* @param limit The number of album objects to return. Default: 20. Minimum: 1. Maximum: 50.
119+
* @param offset The index of the first album to return. Default: 0 (i.e., the first album). Use with limit to get the next set of albums.
120+
*
121+
* @throws BadRequestException if [categoryId] is not found or filters are illegal
122+
*/
38123
fun getPlaylistsForCategory(categoryId: String, market: Market? = null, limit: Int = 20, offset: Int = 0): SpotifyRestAction<PagingObject<SimplePlaylist>> {
39124
return toAction(Supplier {
40125
get("https://api.spotify.com/v1/browse/categories/${categoryId.encode()}/playlists?limit=$limit&offset=$offset${if (market != null) "&market=${market.code}" else ""}")
@@ -43,19 +128,60 @@ class BrowseAPI(api: SpotifyAPI) : SpotifyEndpoint(api) {
43128
}
44129

45130
/**
131+
* Create a playlist-style listening experience based on seed artists, tracks and genres.
132+
* Recommendations are generated based on the available information for a given seed entity and matched against similar
133+
* artists and tracks. If there is sufficient information about the provided seeds, a list of tracks will be returned
134+
* together with pool size details. For artists and tracks that are very new or obscure there might not be enough data
135+
* to generate a list of tracks.
136+
*
137+
* Tuneable track attribute descriptions and ranges are described [here](https://hastebin.com/olojoxonul.vbs)
46138
* @param seedArtists A possibly null provided list of <b>Artist IDs</b> to be used to generate recommendations
47139
* @param seedGenres A possibly null provided list of <b>Genre IDs</b> to be used to generate recommendations
48140
* @param seedTracks A possibly null provided list of <b>Track IDs</b> to be used to generate recommendations
49-
* @param targets A provided HashMap of attributes you'd like to weight. <b>See https://developer.spotify.com/web-api/complete-recommendations/ and scroll down to "<b>Tuneable Track attributes</b>" for a full list of optional attributes like "speechiness"
141+
* @param limit The number of album objects to return. Default: 20. Minimum: 1. Maximum: 50.
142+
* @param market Provide this parameter if you want the list of returned items to be relevant to a particular country.
143+
* If omitted, the returned items will be relevant to all countries.
144+
* @param targetAttributes For each of the tunable track attributes a target value may be provided.
145+
* Tracks with the attribute values nearest to the target values will be preferred.
146+
* @param minAttributes For each tunable track attribute, a hard floor on the selected track attribute’s value can be provided.
147+
* @param maxAttributes For each tunable track attribute, a hard ceiling on the selected track attribute’s value can be provided.
148+
* For example, setting max instrumentalness equal to 0.35 would filter out most tracks that are likely to be instrumental.
149+
*
150+
* @return [RecommendationResponse] with [RecommendationSeed]s used and [SimpleTrack]s found
151+
*
152+
* @throws BadRequestException if any filter is applied illegally
50153
*/
51-
fun getRecommendations(seedArtists: List<String>? = null, seedGenres: List<String>? = null, seedTracks: List<String>? = null, targets: HashMap<String, Number> = hashMapOf(), limit: Int = 20): SpotifyRestAction<RecommendationResponse> {
52-
val url = StringBuilder("https://api.spotify.com/v1/recommendations?limit=$limit")
53-
if (seedArtists != null) url.append("&seed_artists=${seedArtists.map { it.encode() }.stream().collect(Collectors.joining(","))}")
54-
if (seedGenres != null) url.append("&seed_genres=${seedGenres.map { it.encode() }.stream().collect(Collectors.joining(","))}")
55-
if (seedTracks != null) url.append("&seed_tracks=${seedTracks.map { it.encode() }.stream().collect(Collectors.joining(","))}")
56-
if (targets.size > 0) targets.forEach { url.append("&target_${it.key.encode()}=${it.value}") }
154+
fun getRecommendations(seedArtists: List<String>? = null, seedGenres: List<String>? = null, seedTracks: List<String>? = null, limit: Int = 20,
155+
market: Market? = null, targetAttributes: HashMap<TuneableTrackAttribute, Number> = hashMapOf(),
156+
minAttributes: HashMap<TuneableTrackAttribute, Number>, maxAttributes: HashMap<TuneableTrackAttribute, Number>)
157+
: SpotifyRestAction<RecommendationResponse> {
57158
return toAction(Supplier {
159+
val url = StringBuilder("https://api.spotify.com/v1/recommendations?limit=$limit")
160+
if (market != null) url.append("&market=${market.code}")
161+
if (seedArtists != null) url.append("&seed_artists=${seedArtists.map { it.encode() }.stream().collect(Collectors.joining(","))}")
162+
if (seedGenres != null) url.append("&seed_genres=${seedGenres.map { it.encode() }.stream().collect(Collectors.joining(","))}")
163+
if (seedTracks != null) url.append("&seed_tracks=${seedTracks.map { it.encode() }.stream().collect(Collectors.joining(","))}")
164+
if (targetAttributes.isNotEmpty()) targetAttributes.forEach { url.append("&target_${it.key.attribute}=${it.value}") }
165+
if (minAttributes.isNotEmpty()) minAttributes.forEach { url.append("&min_${it.key.attribute}=${it.value}") }
166+
if (maxAttributes.isNotEmpty()) maxAttributes.forEach { url.append("&max_${it.key.attribute}=${it.value}") }
58167
get(url.toString()).toObject<RecommendationResponse>(api)
59168
})
60169
}
170+
}
171+
172+
enum class TuneableTrackAttribute(val attribute: String) {
173+
ACOUSTICNESS("acousticness"),
174+
DANCEABILITY("danceability"),
175+
DURATION_IN_MILLISECONDS("duration_ms"),
176+
ENERGY("energy"),
177+
INSTRUMENTALNESS("instrumentalness"),
178+
KEY("key"),
179+
LIVENESS("liveness"),
180+
LOUDNESS("loudness"),
181+
MODE("mode"),
182+
POPULARITY("popularity"),
183+
SPEECHINESS("speechiness"),
184+
TEMPO("tempo"),
185+
TIME_SIGNATURE("time_signature"),
186+
VALENCE("valence")
61187
}

src/main/kotlin/com/adamratzman/spotify/endpoints/pub/follow/PublicFollowingAPI.kt

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,25 @@ package com.adamratzman.spotify.endpoints.pub.follow
33
import com.adamratzman.spotify.main.SpotifyAPI
44
import com.adamratzman.spotify.utils.SpotifyEndpoint
55
import com.adamratzman.spotify.utils.SpotifyRestAction
6-
import com.adamratzman.spotify.utils.toObject
76
import com.adamratzman.spotify.utils.encode
7+
import com.adamratzman.spotify.utils.toObject
88
import java.util.function.Supplier
99

1010
/**
1111
* This endpoint allow you check the playlists that a Spotify user follows.
1212
*/
1313
class PublicFollowingAPI(api: SpotifyAPI) : SpotifyEndpoint(api) {
14+
/**
15+
* Check to see if one or more Spotify users are following a specified playlist.
16+
*
17+
* @param playlistOwner Spotify ID of the creator of the playlist
18+
* @param playlistId Spotify playlist ID
19+
* @param userIds users to check
20+
*
21+
* @return List of Booleans representing whether the user follows the playlist. User IDs **not** found will return false
22+
*
23+
* @throws [BadRequestException] if the playlist is not found
24+
*/
1425
fun doUsersFollowPlaylist(playlistOwner: String, playlistId: String, vararg userIds: String): SpotifyRestAction<List<Boolean>> {
1526
return toAction(Supplier {
1627
get("https://api.spotify.com/v1/users/${playlistOwner.encode()}/playlists/${playlistId.encode()}/followers/contains?ids=${userIds.map { it.encode() }.joinToString(",")}").toObject<List<Boolean>>(api)

src/main/kotlin/com/adamratzman/spotify/endpoints/pub/playlists/PlaylistsAPI.kt

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,49 @@ import java.util.function.Supplier
88
* Endpoints for retrieving information about a user’s playlists
99
*/
1010
class PlaylistsAPI(api: SpotifyAPI) : SpotifyEndpoint(api) {
11+
/**
12+
* Get a list of the playlists owned or followed by a Spotify user.
13+
*
14+
* @param userId The user’s Spotify user ID.
15+
* @param limit The number of album objects to return. Default: 20. Minimum: 1. Maximum: 50.
16+
* @param offset The index of the first album to return. Default: 0 (i.e., the first album). Use with limit to get the next set of albums.
17+
*
18+
* @return [PagingObject] of [SimplePlaylist]s. This does not have the detail of full [Playlist] objects.
19+
*
20+
* @throws BadRequestException if the [userId] cannot be found
21+
*/
1122
fun getPlaylists(userId: String, limit: Int = 20, offset: Int = 0): SpotifyRestAction<PagingObject<SimplePlaylist>> {
1223
return toAction(Supplier {
1324
get("https://api.spotify.com/v1/users/${userId.encode()}/playlists?limit=$limit&offset=$offset").toPagingObject<SimplePlaylist>(api = api)
1425
})
1526
}
1627

28+
/**
29+
* Get a playlist owned by a Spotify user.
30+
*
31+
* @param userId The user’s Spotify user ID.
32+
* @param playlistId The Spotify ID for the playlist.
33+
* @param market Provide this parameter if you want to apply [Track Relinking](https://github.com/adamint/spotify-web-api-kotlin/blob/master/README.md#track-relinking)
34+
*
35+
* @throws BadRequestException if the playlist is not found
36+
*/
1737
fun getPlaylist(userId: String, playlistId: String, market: Market? = null): SpotifyRestAction<Playlist> {
1838
return toAction(Supplier {
1939
get("https://api.spotify.com/v1/users/${userId.encode()}/playlists/${playlistId.encode()}${if (market != null) "?market=${market.code}" else ""}").toObject<Playlist>(api)
2040
})
2141
}
2242

43+
/**
44+
* Get full details of the tracks of a playlist owned by a Spotify user.
45+
*
46+
* @param userId The user’s Spotify user ID.
47+
* @param playlistId The Spotify ID for the playlist.
48+
* @param market Provide this parameter if you want to apply [Track Relinking](https://github.com/adamint/spotify-web-api-kotlin/blob/master/README.md#track-relinking)
49+
* @param limit The number of album objects to return. Default: 20. Minimum: 1. Maximum: 50.
50+
* @param offset The index of the first album to return. Default: 0 (i.e., the first album). Use with limit to get the next set of albums.
51+
*
52+
* @throws BadRequestException if the playlist cannot be found
53+
*/
2354
fun getPlaylistTracks(userId: String, playlistId: String, limit: Int = 20, offset: Int = 0, market: Market? = null): SpotifyRestAction<LinkedResult<PlaylistTrack>> {
2455
return toAction(Supplier {
2556
get("https://api.spotify.com/v1/users/${userId.encode()}/playlists/${playlistId.encode()}/tracks?limit=$limit&offset=$offset${if (market != null) "&market=${market.code}" else ""}")
@@ -28,6 +59,13 @@ class PlaylistsAPI(api: SpotifyAPI) : SpotifyEndpoint(api) {
2859

2960
}
3061

62+
/**
63+
* Get the current image associated with a specific playlist.
64+
* @param userId The user’s Spotify user ID.
65+
* @param playlistId The Spotify ID for the playlist.
66+
*
67+
* @throws BadRequestException if the playlist cannot be found
68+
*/
3169
fun getPlaylistCovers(userId: String, playlistId: String): SpotifyRestAction<List<SpotifyImage>> {
3270
return toAction(Supplier {
3371
get("https://api.spotify.com/v1/users/${userId.encode()}/playlists/${playlistId.encode()}/images").toObject<List<SpotifyImage>>(api)

0 commit comments

Comments
 (0)