Skip to content

Commit 52dba8e

Browse files
committed
add new builders when directly using tokens
1 parent b0d44bf commit 52dba8e

20 files changed

+286
-238
lines changed

src/commonMain/kotlin/com.adamratzman.spotify/Builder.kt

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ fun getSpotifyAuthorizationUrl(vararg scopes: SpotifyScope, clientId: String, re
5959
*
6060
* @return [SpotifyImplicitGrantApi] that can immediately begin making calls
6161
*/
62-
fun spotifyImplicitGrantApi(clientId: String, redirectUri: String, token: Token, options: SpotifyApiOptions = SpotifyApiOptionsBuilder().build()) =
62+
fun spotifyImplicitGrantApi(clientId: String?, redirectUri: String?, token: Token, options: SpotifyApiOptions = SpotifyApiOptionsBuilder().build()) =
6363
SpotifyImplicitGrantApi(
6464
clientId,
6565
null,
@@ -118,6 +118,26 @@ fun spotifyAppApi(clientId: String, clientSecret: String, block: SpotifyAppApiBu
118118
}
119119
}
120120

121+
/**
122+
* Instantiate a new [SpotifyAppApiBuilder] using a [Token]
123+
*
124+
* @param clientId Spotify [client id](https://developer.spotify.com/documentation/general/guides/app-settings/)
125+
* @param clientSecret Spotify [client secret](https://developer.spotify.com/documentation/general/guides/app-settings/)
126+
* @param apiToken The access token that will be associated with the built API instance
127+
*
128+
* @return Configurable [SpotifyAppApiBuilder] that, when built, creates a new [SpotifyAppApi]
129+
*/
130+
fun spotifyAppApi(clientId: String?, clientSecret: String?, apiToken: Token) =
131+
SpotifyAppApiBuilder().apply {
132+
credentials {
133+
this.clientId = clientId
134+
this.clientSecret = clientSecret
135+
}
136+
authentication {
137+
token = apiToken
138+
}
139+
}
140+
121141
/**
122142
* Instantiate a new [SpotifyAppApiBuilder] by providing a builder initialization [block].
123143
*
@@ -169,6 +189,34 @@ fun spotifyClientApi(
169189
}
170190
}
171191

192+
/**
193+
* Instantiate a new [SpotifyClientApiBuilder] using a [Token]
194+
*
195+
*
196+
* @param clientId Spotify [client id](https://developer.spotify.com/documentation/general/guides/app-settings/)
197+
* @param clientSecret Spotify [client secret](https://developer.spotify.com/documentation/general/guides/app-settings/)
198+
* @param redirectUri Spotify [redirect uri](https://developer.spotify.com/documentation/general/guides/app-settings/)
199+
* @param apiToken The access token that will be associated with the built API instance
200+
*
201+
* @return Configurable [SpotifyClientApiBuilder] that, when built, creates a new [SpotifyClientApi]
202+
*/
203+
fun spotifyClientApi(
204+
clientId: String?,
205+
clientSecret: String?,
206+
redirectUri: String?,
207+
apiToken: Token
208+
) = SpotifyClientApiBuilder().apply {
209+
credentials {
210+
this.clientId = clientId
211+
this.clientSecret = clientSecret
212+
this.redirectUri = redirectUri
213+
}
214+
215+
authentication {
216+
token = apiToken
217+
}
218+
}
219+
172220
/**
173221
* Instantiate a new [SpotifyClientApiBuilder] using a Spotify [clientId], [clientSecret], and [redirectUri],
174222
* with an existing [SpotifyUserAuthorization] and with the ability to configure the api settings by providing a
@@ -792,7 +840,7 @@ class SpotifyApiOptionsBuilder(
792840
var allowBulkRequests: Boolean = true,
793841
var requestTimeoutMillis: Long? = null,
794842
var json: Json = nonstrictJson,
795-
var refreshTokenProducer: (suspend (SpotifyApi<*,*>) -> Token)? = null
843+
var refreshTokenProducer: (suspend (SpotifyApi<*, *>) -> Token)? = null
796844
) {
797845
fun build() =
798846
if (enableAllOptions)
@@ -842,7 +890,7 @@ class SpotifyApiOptionsBuilder(
842890
*
843891
*/
844892

845-
data class SpotifyApiOptions (
893+
data class SpotifyApiOptions(
846894
var useCache: Boolean,
847895
var cacheLimit: Int?,
848896
var automaticRefresh: Boolean,
@@ -853,7 +901,7 @@ data class SpotifyApiOptions (
853901
var allowBulkRequests: Boolean,
854902
var requestTimeoutMillis: Long?,
855903
var json: Json,
856-
var refreshTokenProducer: (suspend (SpotifyApi<*,*>) -> Token)?
904+
var refreshTokenProducer: (suspend (SpotifyApi<*, *>) -> Token)?
857905
)
858906

859907
@Deprecated("Name has been replaced by `options`", ReplaceWith("SpotifyApiOptions"))

src/commonMain/kotlin/com.adamratzman.spotify/SpotifyApi.kt

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ internal const val base = "https://api.spotify.com/v1"
6464
* @property logger The Spotify event logger
6565
* @property requestTimeoutMillis The maximum time, in milliseconds, before terminating an http request
6666
* @property allowBulkRequests Allow splitting too-large requests into smaller, allowable api requests
67+
* @property refreshTokenProducer Pluggable producer that refreshes and replaces the current [token].
6768
*
6869
*/
6970
sealed class SpotifyApi<T : SpotifyApi<T, B>, B : ISpotifyApiBuilder<T, B>>(
@@ -80,7 +81,7 @@ sealed class SpotifyApi<T : SpotifyApi<T, B>, B : ISpotifyApiBuilder<T, B>>(
8081
var allowBulkRequests: Boolean,
8182
var requestTimeoutMillis: Long?,
8283
var json: Json,
83-
var refreshTokenProducer: suspend (SpotifyApi<*,*>) -> Token
84+
var refreshTokenProducer: suspend (SpotifyApi<*, *>) -> Token
8485
) {
8586
var useCache = useCache
8687
set(value) {
@@ -391,7 +392,7 @@ class SpotifyAppApi internal constructor(
391392
}
392393

393394
companion object {
394-
private val defaultAppApiTokenRefreshProducer: suspend (SpotifyApi<*,*>) -> Token = { api ->
395+
private val defaultAppApiTokenRefreshProducer: suspend (SpotifyApi<*, *>) -> Token = { api ->
395396
require(api.clientId != null && api.clientSecret != null) { "Either the client id or the client secret is not set" }
396397

397398
getCredentialedToken(api.clientId, api.clientSecret, api, api.json)
@@ -609,7 +610,7 @@ open class SpotifyClientApi internal constructor(
609610
scopes.all { token.scopes?.contains(it) == true }
610611

611612
companion object {
612-
private val defaultClientApiTokenRefreshProducer: suspend (SpotifyApi<*,*>) -> Token = { api ->
613+
private val defaultClientApiTokenRefreshProducer: suspend (SpotifyApi<*, *>) -> Token = { api ->
613614
require(api.clientId != null && api.clientSecret != null) { "Either the client id or the client secret is not set" }
614615

615616
val currentToken = api.token
@@ -686,7 +687,7 @@ typealias SpotifyClientAPI = SpotifyClientApi
686687
@Deprecated("API name has been updated for kotlin convention consistency", ReplaceWith("SpotifyAppApi"))
687688
typealias SpotifyAppAPI = SpotifyAppApi
688689

689-
typealias GenericSpotifyApi = SpotifyApi<*, *>
690+
typealias GenericSpotifyApi = SpotifyApi<*, *>
690691

691692
/**
692693
*

src/commonMain/kotlin/com.adamratzman.spotify/endpoints/client/ClientFollowingApi.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,8 @@ class ClientFollowingApi(api: GenericSpotifyApi) : FollowingApi(api) {
151151
* with full [Artist] objects
152152
*/
153153
fun getFollowedArtists(
154-
limit: Int? = api.defaultLimit,
155-
after: String? = null
154+
limit: Int? = api.defaultLimit,
155+
after: String? = null
156156
): SpotifyRestActionPaging<Artist, CursorBasedPagingObject<Artist>> {
157157
return toActionPaging {
158158
get(

src/commonMain/kotlin/com.adamratzman.spotify/endpoints/client/ClientLibraryApi.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ class ClientLibraryApi(api: GenericSpotifyApi) : SpotifyEndpoint(api) {
4444
* @return [PagingObject] of [SavedTrack] ordered by position in library
4545
*/
4646
fun getSavedTracks(
47-
limit: Int? = api.defaultLimit,
48-
offset: Int? = null,
49-
market: Market? = null
47+
limit: Int? = api.defaultLimit,
48+
offset: Int? = null,
49+
market: Market? = null
5050
): SpotifyRestActionPaging<SavedTrack, PagingObject<SavedTrack>> {
5151
return toActionPaging {
5252
get(
@@ -71,9 +71,9 @@ class ClientLibraryApi(api: GenericSpotifyApi) : SpotifyEndpoint(api) {
7171
* @return Paging Object of [SavedAlbum] ordered by position in library
7272
*/
7373
fun getSavedAlbums(
74-
limit: Int? = api.defaultLimit,
75-
offset: Int? = null,
76-
market: Market? = null
74+
limit: Int? = api.defaultLimit,
75+
offset: Int? = null,
76+
market: Market? = null
7777
): SpotifyRestActionPaging<SavedAlbum, PagingObject<SavedAlbum>> {
7878
return toActionPaging {
7979
get(

src/commonMain/kotlin/com.adamratzman.spotify/endpoints/client/ClientPersonalizationApi.kt

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,9 @@ class ClientPersonalizationApi(api: GenericSpotifyApi) : SpotifyEndpoint(api) {
6868
* @return [PagingObject] of full [Artist] objects sorted by affinity
6969
*/
7070
fun getTopArtists(
71-
limit: Int? = api.defaultLimit,
72-
offset: Int? = null,
73-
timeRange: TimeRange? = null
71+
limit: Int? = api.defaultLimit,
72+
offset: Int? = null,
73+
timeRange: TimeRange? = null
7474
): SpotifyRestActionPaging<Artist, PagingObject<Artist>> {
7575
return toActionPaging {
7676
get(
@@ -102,9 +102,9 @@ class ClientPersonalizationApi(api: GenericSpotifyApi) : SpotifyEndpoint(api) {
102102
* @return [PagingObject] of full [Track] objects sorted by affinity
103103
*/
104104
fun getTopTracks(
105-
limit: Int? = api.defaultLimit,
106-
offset: Int? = null,
107-
timeRange: TimeRange? = null
105+
limit: Int? = api.defaultLimit,
106+
offset: Int? = null,
107+
timeRange: TimeRange? = null
108108
): SpotifyRestActionPaging<Track, PagingObject<Track>> {
109109
return toActionPaging {
110110
get(

src/commonMain/kotlin/com.adamratzman.spotify/endpoints/client/ClientPlayerApi.kt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,9 +80,9 @@ class ClientPlayerApi(api: GenericSpotifyApi) : SpotifyEndpoint(api) {
8080
*
8181
*/
8282
fun getRecentlyPlayed(
83-
limit: Int? = api.defaultLimit,
84-
before: String? = null,
85-
after: String? = null
83+
limit: Int? = api.defaultLimit,
84+
before: String? = null,
85+
after: String? = null
8686
): SpotifyRestActionPaging<PlayHistory, CursorBasedPagingObject<PlayHistory>> {
8787
return toActionPaging {
8888
get(
@@ -256,11 +256,11 @@ class ClientPlayerApi(api: GenericSpotifyApi) : SpotifyEndpoint(api) {
256256
* @throws BadRequestException if more than one type of play type is specified or the offset is illegal.
257257
*/
258258
fun startPlayback(
259-
collection: CollectionUri? = null,
260-
offsetNum: Int? = null,
261-
offsetPlayable: PlayableUri? = null,
262-
deviceId: String? = null,
263-
tracksToPlay: List<PlayableUri> = emptyList()
259+
collection: CollectionUri? = null,
260+
offsetNum: Int? = null,
261+
offsetPlayable: PlayableUri? = null,
262+
deviceId: String? = null,
263+
tracksToPlay: List<PlayableUri> = emptyList()
264264
): SpotifyRestAction<Unit> {
265265
return toAction {
266266
val url = EndpointBuilder("/me/player/play").with("device_id", deviceId).toString()

src/commonMain/kotlin/com.adamratzman.spotify/endpoints/client/ClientPlaylistApi.kt

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,11 @@ class ClientPlaylistApi(api: GenericSpotifyApi) : PlaylistApi(api) {
6464
* @return The created [Playlist] object with no tracks
6565
*/
6666
fun createClientPlaylist(
67-
name: String,
68-
description: String? = null,
69-
public: Boolean? = null,
70-
collaborative: Boolean? = null,
71-
user: String = (api as SpotifyClientApi).userId
67+
name: String,
68+
description: String? = null,
69+
public: Boolean? = null,
70+
collaborative: Boolean? = null,
71+
user: String = (api as SpotifyClientApi).userId
7272
): SpotifyRestAction<Playlist> {
7373
if (name.isEmpty()) throw BadRequestException(ErrorObject(400, "Name cannot be empty"))
7474
return toAction {
@@ -154,11 +154,11 @@ class ClientPlaylistApi(api: GenericSpotifyApi) : PlaylistApi(api) {
154154
* @throws BadRequestException if the playlist is not found or parameters exceed the max length
155155
*/
156156
fun changeClientPlaylistDetails(
157-
playlist: String,
158-
name: String? = null,
159-
public: Boolean? = null,
160-
collaborative: Boolean? = null,
161-
description: String? = null
157+
playlist: String,
158+
name: String? = null,
159+
public: Boolean? = null,
160+
collaborative: Boolean? = null,
161+
description: String? = null
162162
): SpotifyRestAction<Unit> {
163163
val body = jsonMap()
164164
if (name != null) body += json { "name" to name }
@@ -189,8 +189,8 @@ class ClientPlaylistApi(api: GenericSpotifyApi) : PlaylistApi(api) {
189189
* @throws BadRequestException if the filters provided are illegal
190190
*/
191191
fun getClientPlaylists(
192-
limit: Int? = api.defaultLimit,
193-
offset: Int? = null
192+
limit: Int? = api.defaultLimit,
193+
offset: Int? = null
194194
): SpotifyRestActionPaging<SimplePlaylist, PagingObject<SimplePlaylist>> {
195195
require(!(limit != null && limit !in 1..50)) { "Limit must be between 1 and 50. Provided $limit" }
196196
require(!(offset != null && offset !in 0..100000)) { "Offset must be between 0 and 100,000. Provided $limit" }
@@ -256,11 +256,11 @@ class ClientPlaylistApi(api: GenericSpotifyApi) : PlaylistApi(api) {
256256
* @throws BadRequestException if the playlist is not found or illegal filters are applied
257257
*/
258258
fun reorderClientPlaylistTracks(
259-
playlist: String,
260-
reorderRangeStart: Int,
261-
reorderRangeLength: Int? = null,
262-
insertionPoint: Int,
263-
snapshotId: String? = null
259+
playlist: String,
260+
reorderRangeStart: Int,
261+
reorderRangeLength: Int? = null,
262+
insertionPoint: Int,
263+
snapshotId: String? = null
264264
): SpotifyRestAction<PlaylistSnapshot> {
265265
return toAction {
266266
val body = jsonMap()
@@ -351,12 +351,12 @@ class ClientPlaylistApi(api: GenericSpotifyApi) : PlaylistApi(api) {
351351
* @throws BadRequestException if invalid data is provided
352352
*/
353353
fun uploadClientPlaylistCover(
354-
playlist: String,
355-
imagePath: String? = null,
356-
imageFile: File? = null,
357-
image: BufferedImage? = null,
358-
imageData: String? = null,
359-
imageUrl: String? = null
354+
playlist: String,
355+
imagePath: String? = null,
356+
imageFile: File? = null,
357+
image: BufferedImage? = null,
358+
imageData: String? = null,
359+
imageUrl: String? = null
360360
): SpotifyRestAction<Unit> {
361361
return toAction {
362362
val data = imageData ?: when {
@@ -388,10 +388,10 @@ class ClientPlaylistApi(api: GenericSpotifyApi) : PlaylistApi(api) {
388388
* @param snapshotId The playlist snapshot against which to apply this action. **recommended to have**
389389
*/
390390
fun removeTrackFromClientPlaylist(
391-
playlist: String,
392-
track: String,
393-
positions: SpotifyTrackPositions,
394-
snapshotId: String? = null
391+
playlist: String,
392+
track: String,
393+
positions: SpotifyTrackPositions,
394+
snapshotId: String? = null
395395
) = removeTracksFromClientPlaylist(playlist, track to positions, snapshotId = snapshotId)
396396

397397
/**
@@ -407,9 +407,9 @@ class ClientPlaylistApi(api: GenericSpotifyApi) : PlaylistApi(api) {
407407
* @param snapshotId The playlist snapshot against which to apply this action. **recommended to have**
408408
*/
409409
fun removeTrackFromClientPlaylist(
410-
playlist: String,
411-
track: String,
412-
snapshotId: String? = null
410+
playlist: String,
411+
track: String,
412+
snapshotId: String? = null
413413
) = removeTracksFromClientPlaylist(playlist, track, snapshotId = snapshotId)
414414

415415
/**
@@ -425,9 +425,9 @@ class ClientPlaylistApi(api: GenericSpotifyApi) : PlaylistApi(api) {
425425
* @param snapshotId The playlist snapshot against which to apply this action. **recommended to have**
426426
*/
427427
fun removeTracksFromClientPlaylist(
428-
playlist: String,
429-
vararg tracks: String,
430-
snapshotId: String? = null
428+
playlist: String,
429+
vararg tracks: String,
430+
snapshotId: String? = null
431431
) = removePlaylistTracksImpl(playlist, tracks.map { it to null }.toTypedArray(), snapshotId)
432432

433433
/**
@@ -443,15 +443,15 @@ class ClientPlaylistApi(api: GenericSpotifyApi) : PlaylistApi(api) {
443443
* @param snapshotId The playlist snapshot against which to apply this action. **recommended to have**
444444
*/
445445
fun removeTracksFromClientPlaylist(
446-
playlist: String,
447-
vararg tracks: Pair<String, SpotifyTrackPositions>,
448-
snapshotId: String? = null
446+
playlist: String,
447+
vararg tracks: Pair<String, SpotifyTrackPositions>,
448+
snapshotId: String? = null
449449
) = removePlaylistTracksImpl(playlist, tracks.toList().toTypedArray(), snapshotId)
450450

451451
private fun removePlaylistTracksImpl(
452-
playlist: String,
453-
tracks: Array<Pair<String, SpotifyTrackPositions?>>,
454-
snapshotId: String?
452+
playlist: String,
453+
tracks: Array<Pair<String, SpotifyTrackPositions?>>,
454+
snapshotId: String?
455455
): SpotifyRestAction<PlaylistSnapshot> {
456456
checkBulkRequesting(100, tracks.size)
457457
if (snapshotId != null && tracks.size > 100) throw BadRequestException("You cannot provide both the snapshot id and attempt bulk requesting")

0 commit comments

Comments
 (0)