Skip to content

Commit

Permalink
fix: Replace getRecommendations with getTopItems
Browse files Browse the repository at this point in the history
getRecommendations endpoint is deprecated. Replace it with
getTopItems
https://developer.spotify.com/documentation/web-api/reference/get-recommendations
  • Loading branch information
PolinaPolupan committed Dec 18, 2024
1 parent 0c14db2 commit 25a2b79
Show file tree
Hide file tree
Showing 11 changed files with 1,668 additions and 28 deletions.
13 changes: 1 addition & 12 deletions .idea/deploymentTargetSelector.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import android.text.TextUtils
import android.util.Base64
import android.util.Log
import com.example.mymusic.core.common.ApplicationScope
import com.example.mymusic.core.common.Constants
import com.example.mymusic.core.common.IoDispatcher
import com.example.mymusic.core.datastore.MyMusicPreferencesDataSource
import dagger.hilt.android.internal.Contexts
Expand Down Expand Up @@ -54,10 +55,10 @@ class AuthorizationManager @Inject constructor(

private fun initAuthServiceConfig() {
_authServiceConfig = AuthorizationServiceConfiguration(
Uri.parse(com.example.mymusic.core.common.Constants.URL_AUTHORIZATION),
Uri.parse(com.example.mymusic.core.common.Constants.URL_TOKEN_EXCHANGE),
Uri.parse(Constants.URL_AUTHORIZATION),
Uri.parse(Constants.URL_TOKEN_EXCHANGE),
null,
Uri.parse(com.example.mymusic.core.common.Constants.URL_AUTH_REDIRECT))
Uri.parse(Constants.URL_AUTH_REDIRECT))
}

private fun initAuthService() {
Expand Down Expand Up @@ -102,28 +103,29 @@ class AuthorizationManager @Inject constructor(
val encoding = Base64.URL_SAFE or Base64.NO_PADDING or Base64.NO_WRAP
val codeVerifier = Base64.encodeToString(bytes, encoding)

val digest = MessageDigest.getInstance(com.example.mymusic.core.common.Constants.MESSAGE_DIGEST_ALGORITHM)
val digest = MessageDigest.getInstance(Constants.MESSAGE_DIGEST_ALGORITHM)
val hash = digest.digest(codeVerifier.toByteArray())
val codeChallenge = Base64.encodeToString(hash, encoding)

val builder = AuthorizationRequest.Builder(
_authServiceConfig,
com.example.mymusic.core.common.Constants.CLIENT_ID,
Constants.CLIENT_ID,
ResponseTypeValues.CODE,
Uri.parse(com.example.mymusic.core.common.Constants.URL_AUTH_REDIRECT))
Uri.parse(Constants.URL_AUTH_REDIRECT))
.setCodeVerifier(codeVerifier,
codeChallenge,
com.example.mymusic.core.common.Constants.CODE_VERIFIER_CHALLENGE_METHOD)
Constants.CODE_VERIFIER_CHALLENGE_METHOD)

builder.setScopes(
com.example.mymusic.core.common.Constants.SCOPE_STREAMING,
com.example.mymusic.core.common.Constants.SCOPE_EMAIL,
com.example.mymusic.core.common.Constants.SCOPE_APP_REMOTE_CONTROL,
com.example.mymusic.core.common.Constants.SCOPE_USER_MODIFY_PLAYBACK_STATE,
com.example.mymusic.core.common.Constants.SCOPE_USER_READ_PRIVATE,
com.example.mymusic.core.common.Constants.SCOPE_USER_READ_RECENTLY_PLAYED,
com.example.mymusic.core.common.Constants.SCOPE_USER_LIBRARY_READ,
com.example.mymusic.core.common.Constants.SCOPE_PLAYLIST_READ_PRIVATE
Constants.SCOPE_STREAMING,
Constants.SCOPE_EMAIL,
Constants.SCOPE_APP_REMOTE_CONTROL,
Constants.SCOPE_USER_MODIFY_PLAYBACK_STATE,
Constants.SCOPE_USER_READ_PRIVATE,
Constants.SCOPE_USER_READ_RECENTLY_PLAYED,
Constants.SCOPE_USER_LIBRARY_READ,
Constants.SCOPE_PLAYLIST_READ_PRIVATE,
Constants.SCOPE_USER_TOP_READ
)

val request = builder.build()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class Constants {
const val SCOPE_USER_READ_CURRENTLY_PLAYING = "user-read-currently-playing"
const val SCOPE_APP_REMOTE_CONTROL = "app-remote-control"
const val SCOPE_STREAMING = "streaming"
const val SCOPE_USER_TOP_READ = "user-top-read"
const val SCOPE_PLAYLIST_READ_PRIVATE = "playlist-read-private"
const val SCOPE_PLAYLIST_MODIFY_PRIVATE = "playlist-modify-private"
const val SCOPE_PLAYLIST_MODIFY_PUBLIC = "playlist-modify-public"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,10 @@ class OfflineFirstMusicRepository @Inject constructor(
override suspend fun refresh() {
withContext(dispatcher) {

val remoteMusic = getRecommendations()
// Get recommendations endpoint is deprecated
//val remoteMusic = getRecommendations()

val remoteMusic = networkDataSource.getTopItems("tracks")

if (remoteMusic.isNotEmpty()) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -448,3 +448,5 @@ class MusicDaoTest {
primaryColor = null
)
}


Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,19 @@ import com.example.mymusic.core.network.model.RecentlyPlayedTracksResponse
import com.example.mymusic.core.network.model.SavedAlbumsResponse
import com.example.mymusic.core.network.model.SavedPlaylistResponse
import com.example.mymusic.core.network.model.SpotifyTrack
import com.example.mymusic.core.network.model.UsersTopItemsResponse
import com.haroldadmin.cnradapter.NetworkResponse
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Query

interface MyMusicAPIService {

@GET("https://api.spotify.com/v1/me/top/{type}")
suspend fun getTopItems(
@Path("type") type: String
): NetworkResponse<UsersTopItemsResponse, ErrorResponse>

@GET("https://api.spotify.com/v1/recommendations?limit=10&seed_genres=pop")
suspend fun getRecommendations(): NetworkResponse<RecommendationsResponse, ErrorResponse>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import com.example.mymusic.core.network.model.SpotifySimplifiedTrack
import com.example.mymusic.core.network.model.SpotifyTrack

interface MyMusicNetworkDataSource {
suspend fun getTopItems(type: String): List<SpotifyTrack>

suspend fun getRecommendations(): List<SpotifyTrack>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,19 @@ import com.example.mymusic.core.network.model.SavedAlbumsResponse
import com.example.mymusic.core.network.model.SavedPlaylistResponse
import com.example.mymusic.core.network.model.SpotifySimplifiedTrack
import com.example.mymusic.core.network.model.SpotifyTrack
import com.example.mymusic.core.network.model.UsersTopItemsResponse
import com.haroldadmin.cnradapter.NetworkResponse
import javax.inject.Inject

class RetrofitNetworkDataSource @Inject constructor(
private val apiService: MyMusicAPIService
): MyMusicNetworkDataSource {
override suspend fun getTopItems(type: String): List<SpotifyTrack> {
val response = apiService.getTopItems(type)
val data = (response as? NetworkResponse.Success<UsersTopItemsResponse, ErrorResponse>?)?.body?.items ?: emptyList()

return processResponse(response, data, emptyList())
}

override suspend fun getRecommendations(): List<SpotifyTrack> {
val response = apiService.getRecommendations()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import com.example.mymusic.core.network.model.SavedAlbumsResponse
import com.example.mymusic.core.network.model.SavedPlaylistResponse
import com.example.mymusic.core.network.model.SpotifySimplifiedTrack
import com.example.mymusic.core.network.model.SpotifyTrack
import com.example.mymusic.core.network.model.UsersTopItemsResponse
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.withContext
Expand All @@ -26,6 +27,14 @@ class FakeNetworkDataSource @Inject constructor(
@IoDispatcher val dispatcher: CoroutineDispatcher,
@ApplicationContext val context: Context
) : MyMusicNetworkDataSource {
override suspend fun getTopItems(type: String): List<SpotifyTrack> =
withContext(dispatcher) {
val inputStream = context.resources.openRawResource(R.raw.top_items)
.bufferedReader().use { it.readText() }

val response = Json.decodeFromString<UsersTopItemsResponse>(inputStream)
response.items
}

override suspend fun getRecommendations(): List<SpotifyTrack> =
withContext(dispatcher) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.example.mymusic.core.network.model

import kotlinx.serialization.Serializable

@Serializable
data class UsersTopItemsResponse(
val href: String,
val limit: Int,
val next: String?,
val offset: Int,
val previous: String?,
val total: String,
val items: List<SpotifyTrack> // OneOf issue https://developer.spotify.com/documentation/web-api/reference/get-users-top-artists-and-tracks
)
Loading

0 comments on commit 25a2b79

Please sign in to comment.