Skip to content

Commit b0c751f

Browse files
committed
fix #20 & refractor asserts into assertTrue
1 parent 8818354 commit b0c751f

File tree

14 files changed

+152
-77
lines changed

14 files changed

+152
-77
lines changed

src/main/kotlin/com/adamratzman/spotify/endpoints/client/ClientFollowingAPI.kt

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package com.adamratzman.spotify.endpoints.client
22

33
import com.adamratzman.spotify.endpoints.public.FollowingAPI
44
import com.adamratzman.spotify.main.SpotifyAPI
5+
import com.adamratzman.spotify.main.SpotifyClientAPI
56
import com.adamratzman.spotify.main.SpotifyRestAction
67
import com.adamratzman.spotify.utils.*
78
import java.util.function.Supplier
@@ -23,6 +24,20 @@ class ClientFollowingAPI(api: SpotifyAPI) : FollowingAPI(api) {
2324
})
2425
}
2526

27+
/**
28+
* Check to see if the logged-in Spotify user is following the specified playlist.
29+
*
30+
* @param playlistOwner Spotify ID of the creator of the playlist
31+
* @param playlistId Spotify playlist ID
32+
*
33+
* @return booleans representing whether the user follows the playlist. User IDs **not** found will return false
34+
*
35+
* @throws [BadRequestException] if the playlist is not found
36+
*/
37+
fun isFollowingPlaylist(playlistOwner: String, playlistId: String): SpotifyRestAction<Boolean> {
38+
return toAction(Supplier { isFollowingPlaylist(playlistOwner, playlistId, (api as SpotifyClientAPI).userId).complete() })
39+
}
40+
2641
/**
2742
* Check to see if the current user is following one or more other Spotify users.
2843
*
@@ -138,9 +153,9 @@ class ClientFollowingAPI(api: SpotifyAPI) : FollowingAPI(api) {
138153
*
139154
* @throws BadRequestException if the playlist is not found
140155
*/
141-
fun followPlaylist(ownerId: String, playlistId: String, followPublicly: Boolean = true): SpotifyRestAction<Unit> {
156+
fun followPlaylist(playlistId: String, followPublicly: Boolean = true): SpotifyRestAction<Unit> {
142157
return toAction(Supplier {
143-
put(EndpointBuilder("/users/$ownerId/playlists/$playlistId/followers").toString(), "{\"public\": $followPublicly}")
158+
put(EndpointBuilder("/playlists/$playlistId/followers").toString(), "{\"public\": $followPublicly}")
144159
Unit
145160
})
146161

@@ -210,9 +225,9 @@ class ClientFollowingAPI(api: SpotifyAPI) : FollowingAPI(api) {
210225
*
211226
* @throws BadRequestException if the playlist is not found
212227
*/
213-
fun unfollowPlaylist(ownerId: String, playlistId: String): SpotifyRestAction<Unit> {
228+
fun unfollowPlaylist(playlistId: String): SpotifyRestAction<Unit> {
214229
return toAction(Supplier {
215-
delete(EndpointBuilder("/users/$ownerId/playlists/$playlistId/followers").toString())
230+
delete(EndpointBuilder("/playlists/$playlistId/followers").toString())
216231
Unit
217232
})
218233
}

src/main/kotlin/com/adamratzman/spotify/endpoints/client/ClientPlaylistAPI.kt

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,11 @@ class ClientPlaylistAPI(api: SpotifyAPI) : PlaylistsAPI(api) {
5959
*
6060
* @throws BadRequestException if any invalid track ids is provided or the playlist is not found
6161
*/
62-
fun addTracksToPlaylist(playlistId: String, vararg ids: String, position: Int? = null, userId: String = (api as SpotifyClientAPI).userId): SpotifyRestAction<Unit> {
62+
fun addTracksToPlaylist(playlistId: String, vararg ids: String, position: Int? = null): SpotifyRestAction<Unit> {
6363
val json = JSONObject().put("uris", ids.map { "spotify:track:${it.encode()}" })
6464
if (position != null) json.put("position", position)
6565
return toAction(Supplier {
66-
post(EndpointBuilder("/users/${userId.encode()}/playlists/${playlistId.encode()}/tracks").toString(), json.toString())
66+
post(EndpointBuilder("/playlists/${playlistId.encode()}/tracks").toString(), json.toString())
6767
Unit
6868
})
6969
}
@@ -81,15 +81,15 @@ class ClientPlaylistAPI(api: SpotifyAPI) : PlaylistsAPI(api) {
8181
* @throws BadRequestException if the playlist is not found or parameters exceed the max length
8282
*/
8383
fun changePlaylistDescription(playlistId: String, name: String? = null, public: Boolean? = null, collaborative: Boolean? = null,
84-
description: String? = null, userId: String = (api as SpotifyClientAPI).userId): SpotifyRestAction<Unit> {
84+
description: String? = null): SpotifyRestAction<Unit> {
8585
val json = JSONObject()
8686
if (name != null) json.put("name", name)
8787
if (public != null) json.put("public", public)
8888
if (collaborative != null) json.put("collaborative", collaborative)
8989
if (description != null) json.put("description", description)
9090
if (json.length() == 0) throw IllegalArgumentException("At least one option must not be null")
9191
return toAction(Supplier {
92-
put(EndpointBuilder("/users/${userId.encode()}/playlists/${playlistId.encode()}").toString(), json.toString())
92+
put(EndpointBuilder("/playlists/${playlistId.encode()}").toString(), json.toString())
9393
Unit
9494
})
9595
}
@@ -133,9 +133,9 @@ class ClientPlaylistAPI(api: SpotifyAPI) : PlaylistsAPI(api) {
133133
* @param id playlist id
134134
* @param ownerId the owner of this playlist. Ignore if it's the authenticated user
135135
*/
136-
fun deletePlaylist(id: String, ownerId: String? = null): SpotifyRestAction<Unit> {
136+
fun deletePlaylist(id: String): SpotifyRestAction<Unit> {
137137
api as SpotifyClientAPI
138-
return api.following.unfollowPlaylist(ownerId ?: api.userId, id)
138+
return api.following.unfollowPlaylist(id)
139139
}
140140

141141
/**
@@ -157,14 +157,14 @@ class ClientPlaylistAPI(api: SpotifyAPI) : PlaylistsAPI(api) {
157157
* @throws BadRequestException if the playlist is not found or illegal filters are applied
158158
*/
159159
fun reorderTracks(playlistId: String, reorderRangeStart: Int, reorderRangeLength: Int? = null, insertionPoint: Int,
160-
snapshotId: String? = null, userId: String = (api as SpotifyClientAPI).userId): SpotifyRestAction<Snapshot> {
160+
snapshotId: String? = null): SpotifyRestAction<Snapshot> {
161161
return toAction(Supplier {
162162
val json = JSONObject()
163163
json.put("range_start", reorderRangeStart)
164164
json.put("insert_before", insertionPoint)
165165
if (reorderRangeLength != null) json.put("range_length", reorderRangeLength)
166166
if (snapshotId != null) json.put("snapshot_id", snapshotId)
167-
put(EndpointBuilder("/users/${userId.encode()}/playlists/${playlistId.encode()}/tracks").toString(), json.toString())
167+
put(EndpointBuilder("/playlists/${playlistId.encode()}/tracks").toString(), json.toString())
168168
.toObject<Snapshot>(api)
169169
})
170170
}
@@ -179,11 +179,11 @@ class ClientPlaylistAPI(api: SpotifyAPI) : PlaylistsAPI(api) {
179179
*
180180
* @throws BadRequestException if playlist is not found or illegal tracks are provided
181181
*/
182-
fun setPlaylistTracks(playlistId: String, vararg trackIds: String, userId: String = (api as SpotifyClientAPI).userId): SpotifyRestAction<Unit> {
182+
fun setPlaylistTracks(playlistId: String, vararg trackIds: String): SpotifyRestAction<Unit> {
183183
return toAction(Supplier {
184184
val json = JSONObject()
185185
json.put("uris", trackIds.map { "spotify:track:${it.encode()}" })
186-
put(EndpointBuilder("/users/${userId.encode()}/playlists/${playlistId.encode()}/tracks").toString(),
186+
put(EndpointBuilder("/playlists/${playlistId.encode()}/tracks").toString(),
187187
json.toString())
188188
Unit
189189
})
@@ -194,8 +194,8 @@ class ClientPlaylistAPI(api: SpotifyAPI) : PlaylistsAPI(api) {
194194
* @param userId The user’s Spotify user ID.
195195
* @param playlistId The Spotify ID for the playlist.
196196
*/
197-
fun removeAllPlaylistTracks(playlistId: String, userId: String = (api as SpotifyClientAPI).userId): SpotifyRestAction<Unit> {
198-
return setPlaylistTracks(playlistId, userId = userId)
197+
fun removeAllPlaylistTracks(playlistId: String): SpotifyRestAction<Unit> {
198+
return setPlaylistTracks(playlistId)
199199
}
200200

201201
/**
@@ -216,7 +216,7 @@ class ClientPlaylistAPI(api: SpotifyAPI) : PlaylistsAPI(api) {
216216
*/
217217
fun uploadPlaylistCover(playlistId: String, imagePath: String? = null,
218218
imageFile: File? = null, image: BufferedImage? = null, imageData: String? = null,
219-
imageUrl: String? = null, userId: String = (api as SpotifyClientAPI).userId): SpotifyRestAction<Unit> {
219+
imageUrl: String? = null): SpotifyRestAction<Unit> {
220220
return toAction(Supplier {
221221
val data = imageData ?: when {
222222
image != null -> encode(image)
@@ -225,7 +225,7 @@ class ClientPlaylistAPI(api: SpotifyAPI) : PlaylistsAPI(api) {
225225
imagePath != null -> encode(ImageIO.read(URL("file:///$imagePath")))
226226
else -> throw IllegalArgumentException("No cover image was specified")
227227
}
228-
put(EndpointBuilder("/users/${userId.encode()}/playlists/${playlistId.encode()}/images").toString(),
228+
put(EndpointBuilder("/playlists/${playlistId.encode()}/images").toString(),
229229
data, contentType = "image/jpeg")
230230
Unit
231231
})

src/main/kotlin/com/adamratzman/spotify/endpoints/public/FollowingAPI.kt

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,25 @@ open class FollowingAPI(api: SpotifyAPI) : SpotifyEndpoint(api) {
2020
*
2121
* @throws [BadRequestException] if the playlist is not found
2222
*/
23-
fun doUsersFollowPlaylist(playlistOwner: String, playlistId: String, vararg userIds: String): SpotifyRestAction<List<Boolean>> {
23+
fun areFollowingPlaylist(playlistOwner: String, playlistId: String, vararg userIds: String): SpotifyRestAction<List<Boolean>> {
2424
return toAction(Supplier {
2525
get(EndpointBuilder("/users/${playlistOwner.encode()}/playlists/${playlistId.encode()}/followers/contains")
26-
.with("ids", userIds.joinToString(",") {it.encode()}).toString()).toObject<List<Boolean>>(api)
26+
.with("ids", userIds.joinToString(",") { it.encode() }).toString()).toObject<List<Boolean>>(api)
2727
})
2828
}
29+
30+
/**
31+
* Check to see if a specific Spotify user is following the specified playlist.
32+
*
33+
* @param playlistOwner Spotify ID of the creator of the playlist
34+
* @param playlistId Spotify playlist ID
35+
* @param userId Spotify user id
36+
*
37+
* @return booleans representing whether the user follows the playlist. User IDs **not** found will return false
38+
*
39+
* @throws [BadRequestException] if the playlist is not found
40+
*/
41+
fun isFollowingPlaylist(playlistOwner: String, playlistId: String, userId: String): SpotifyRestAction<Boolean> {
42+
return toAction(Supplier { areFollowingPlaylist(playlistOwner, playlistId, userIds = *arrayOf(userId)).complete()[0] })
43+
}
2944
}

src/main/kotlin/com/adamratzman/spotify/endpoints/public/PlaylistsAPI.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ open class PlaylistsAPI(api: SpotifyAPI) : SpotifyEndpoint(api) {
3737
*
3838
* @throws BadRequestException if the playlist is not found
3939
*/
40-
fun getPlaylist(userId: String, playlistId: String, market: Market? = null): SpotifyRestAction<Playlist?> {
40+
fun getPlaylist(playlistId: String, market: Market? = null): SpotifyRestAction<Playlist?> {
4141
return toAction(Supplier {
4242
catch {
43-
get(EndpointBuilder("/users/${userId.encode()}/playlists/${playlistId.encode()}")
43+
get(EndpointBuilder("/playlists/${playlistId.encode()}")
4444
.with("market", market?.code).toString()).toObject<Playlist>(api)
4545
}
4646
})
@@ -57,9 +57,9 @@ open class PlaylistsAPI(api: SpotifyAPI) : SpotifyEndpoint(api) {
5757
*
5858
* @throws BadRequestException if the playlist cannot be found
5959
*/
60-
fun getPlaylistTracks(userId: String, playlistId: String, limit: Int? = null, offset: Int? = null, market: Market? = null): SpotifyRestAction<LinkedResult<PlaylistTrack>> {
60+
fun getPlaylistTracks(playlistId: String, limit: Int? = null, offset: Int? = null, market: Market? = null): SpotifyRestAction<LinkedResult<PlaylistTrack>> {
6161
return toAction(Supplier {
62-
get(EndpointBuilder("/users/${userId.encode()}/playlists/${playlistId.encode()}/tracks").with("limit", limit)
62+
get(EndpointBuilder("/playlists/${playlistId.encode()}/tracks").with("limit", limit)
6363
.with("offset", offset).with("market", market?.code).toString()).toLinkedResult<PlaylistTrack>(api)
6464
})
6565

@@ -72,9 +72,9 @@ open class PlaylistsAPI(api: SpotifyAPI) : SpotifyEndpoint(api) {
7272
*
7373
* @throws BadRequestException if the playlist cannot be found
7474
*/
75-
fun getPlaylistCovers(userId: String, playlistId: String): SpotifyRestAction<List<SpotifyImage>> {
75+
fun getPlaylistCovers(playlistId: String): SpotifyRestAction<List<SpotifyImage>> {
7676
return toAction(Supplier {
77-
get(EndpointBuilder("/users/${userId.encode()}/playlists/${playlistId.encode()}/images").toString()).toObject<List<SpotifyImage>>(api)
77+
get(EndpointBuilder("/playlists/${playlistId.encode()}/images").toString()).toObject<List<SpotifyImage>>(api)
7878
})
7979
}
8080
}

src/main/kotlin/com/adamratzman/spotify/utils/Endpoints.kt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.adamratzman.spotify.main.SpotifyAPI
44
import com.adamratzman.spotify.main.SpotifyClientAPI
55
import com.adamratzman.spotify.main.SpotifyRestAction
66
import com.adamratzman.spotify.main.base
7+
import com.google.gson.JsonParseException
78
import org.json.JSONObject
89
import org.jsoup.Connection
910
import org.jsoup.Jsoup
@@ -45,7 +46,14 @@ abstract class SpotifyEndpoint(val api: SpotifyAPI) {
4546
}
4647
connection = connection.header("Authorization", "Bearer ${api.token.access_token}")
4748
val document = connection.method(method).ignoreHttpErrors(true).execute()
48-
if (document.statusCode() / 200 != 1 /* Check if status is 2xx */) throw BadRequestException(api.gson.fromJson(document.body(), ErrorResponse::class.java).error)
49+
if (document.statusCode() / 200 != 1 /* Check if status is 2xx */) {
50+
val message = try {
51+
api.gson.fromJson(document.body(), ErrorResponse::class.java).error
52+
} catch (e: JsonParseException) {
53+
ErrorObject(400, "malformed request (likely spaces)")
54+
}
55+
throw BadRequestException(message)
56+
}
4957
else if (document.statusCode() == 202 && retry202) return execute(url, body, method, false)
5058
return document.body()
5159
}

src/main/kotlin/com/adamratzman/spotify/utils/ResultObjects.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ data class Album(val album_type: String, val artists: List<SimpleArtist>, val av
8181
data class SimplePlaylist(val collaborative: Boolean, val external_urls: HashMap<String, String>, val href: String, val id: String,
8282
val images: List<SpotifyImage>, val name: String, val owner: SpotifyPublicUser, val public: Boolean?,
8383
val snapshot_id: String, val tracks: PlaylistTrackInfo, val type: String, val uri: String) : Linkable() {
84-
fun toFullPlaylist(market: Market? = null): SpotifyRestAction<Playlist?> = api.playlists.getPlaylist(owner.id, id, market)
84+
fun toFullPlaylist(market: Market? = null): SpotifyRestAction<Playlist?> = api.playlists.getPlaylist(id, market)
8585
}
8686

8787
/**

src/test/kotlin/com/adamratzman/spotify/private/ClientFollowingAPITest.kt

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,64 @@ class ClientFollowingAPITest : Spek({
1919
api.following.unfollowArtist(testArtistId).complete()
2020
}
2121

22-
assert(!api.following.isFollowingArtist(testArtistId).complete())
22+
assertTrue(!api.following.isFollowingArtist(testArtistId).complete())
2323

2424
val beforeFollowing = api.following.getFollowedArtists().complete().getAllItems<Artist>().complete()
2525

2626
assertNull(beforeFollowing.find { it.id == testArtistId })
2727

28+
api.following.followArtist(testArtistId).complete()
2829
api.following.followArtist(testArtistId).complete()
2930

30-
assert(api.following.isFollowingArtist(testArtistId).complete())
31+
assertTrue(api.following.isFollowingArtist(testArtistId).complete())
3132

3233
assertEquals(1, api.following.getFollowedArtists().complete().getAllItems<Artist>().complete().size - beforeFollowing.size)
3334

35+
api.following.unfollowArtist(testArtistId).complete()
3436
api.following.unfollowArtist(testArtistId).complete()
3537

36-
assert(beforeFollowing.size == api.following.getFollowedArtists().complete().getAllItems<Artist>().complete().size)
38+
assertTrue(beforeFollowing.size == api.following.getFollowedArtists().complete().getAllItems<Artist>().complete().size)
3739

38-
assert(!api.following.isFollowingArtist(testArtistId).complete())
40+
assertTrue(!api.following.isFollowingArtist(testArtistId).complete())
3941

4042
assertThrows<BadRequestException> { api.following.isFollowingArtist("no u").complete() }
4143
assertThrows<BadRequestException> { api.following.followArtist("no u").complete() }
42-
assertThrows<BadRequestException> { api.following.followArtists(testArtistId,"no u").complete() }
44+
assertThrows<BadRequestException> { api.following.followArtists(testArtistId, "no u").complete() }
4345
assertThrows<BadRequestException> { api.following.unfollowArtist("no u").complete() }
4446
}
47+
48+
it("follow/unfollow users") {
49+
val testUserId = "adamratzman"
50+
51+
if (api.following.isFollowingUser(testUserId).complete()) {
52+
api.following.unfollowUser(testUserId).complete()
53+
}
54+
55+
api.following.followUser(testUserId).complete()
56+
57+
assertTrue(api.following.isFollowingUser(testUserId).complete())
58+
59+
api.following.unfollowUser(testUserId).complete()
60+
61+
assertFalse(api.following.isFollowingUser(testUserId).complete())
62+
}
63+
64+
it("follow/unfollow playlists") {
65+
val playlistId = "37i9dQZF1DXcBWIGoYBM5M"
66+
val playlistOwnerId = "spotify"
67+
if (api.following.isFollowingPlaylist(playlistOwnerId, playlistId).complete()) {
68+
api.following.unfollowPlaylist(playlistId).complete()
69+
}
70+
71+
assertFalse(api.following.isFollowingPlaylist(playlistOwnerId, playlistId).complete())
72+
73+
api.following.followPlaylist(playlistId).complete()
74+
75+
assertTrue(api.following.isFollowingPlaylist(playlistOwnerId, playlistId).complete())
76+
77+
assertThrows<BadRequestException> { api.following.isFollowingPlaylist(" no u", "no u").complete() }
78+
assertThrows<BadRequestException> { api.following.unfollowPlaylist("no-u").complete() }
79+
assertThrows<BadRequestException> { api.following.followPlaylist("nou").complete() }
80+
}
4581
}
4682
})

src/test/kotlin/com/adamratzman/spotify/private/ClientPersonalizationAPITest.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,21 @@ package com.adamratzman.spotify.private
33
import com.adamratzman.spotify.api
44
import com.adamratzman.spotify.endpoints.client.ClientPersonalizationAPI
55
import com.adamratzman.spotify.main.SpotifyClientAPI
6+
import org.junit.jupiter.api.Assertions.assertTrue
67
import org.spekframework.spek2.Spek
78
import org.spekframework.spek2.style.specification.describe
89

910
class ClientPersonalizationAPITest:Spek({
1011
describe("personalization endpoints") {
1112
it("top artists") {
1213
if (api !is SpotifyClientAPI) return@it
13-
assert(api.personalization.getTopArtists(5, timeRange = ClientPersonalizationAPI.TimeRange.MEDIUM_TERM)
14+
assertTrue(api.personalization.getTopArtists(5, timeRange = ClientPersonalizationAPI.TimeRange.MEDIUM_TERM)
1415
.complete().items.isNotEmpty())
1516
}
1617

1718
it("top tracks") {
1819
(api as? SpotifyClientAPI) ?: return@it
19-
assert(api.personalization.getTopTracks(5).complete().items.isNotEmpty())
20+
assertTrue(api.personalization.getTopTracks(5).complete().items.isNotEmpty())
2021
}
2122
}
2223
})

0 commit comments

Comments
 (0)