Things
This commit is contained in:
parent
a73ba4cd77
commit
71cb4abae9
|
@ -2,10 +2,10 @@ package dev.fyloz.musicplayer.core
|
|||
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import dev.fyloz.musicplayer.core.data.RepositoryInjection
|
||||
import dev.fyloz.musicplayer.core.factory.SongFactoryProxy
|
||||
import dev.fyloz.musicplayer.core.factory.TrackFactoryProxy
|
||||
import dev.fyloz.musicplayer.core.http.auth.AuthorizationData
|
||||
import dev.fyloz.musicplayer.core.http.configureSongRoutes
|
||||
import dev.fyloz.musicplayer.core.logic.SongLogic
|
||||
import dev.fyloz.musicplayer.core.http.configureTrackRoutes
|
||||
import dev.fyloz.musicplayer.core.logic.TrackLogic
|
||||
import dev.fyloz.musicplayer.modules.Module
|
||||
import io.ktor.client.*
|
||||
import io.ktor.http.*
|
||||
|
@ -51,8 +51,8 @@ fun Application.module() {
|
|||
RepositoryInjection.koinBeans,
|
||||
|
||||
module {
|
||||
single { SongFactoryProxy() }
|
||||
single { SongLogic() }
|
||||
single { TrackFactoryProxy() }
|
||||
single { TrackLogic() }
|
||||
single {
|
||||
HttpClient {
|
||||
install(io.ktor.client.plugins.contentnegotiation.ContentNegotiation) {
|
||||
|
@ -80,18 +80,19 @@ fun Application.module() {
|
|||
registeredModules.values.forEach { it.configureRoutes(this) }
|
||||
|
||||
route("/api/v1") {
|
||||
configureSongRoutes()
|
||||
configureTrackRoutes()
|
||||
}
|
||||
}
|
||||
|
||||
install(CORS) {
|
||||
allowMethod(HttpMethod.Options)
|
||||
allowMethod(HttpMethod.Post)
|
||||
allowMethod(HttpMethod.Put)
|
||||
allowMethod(HttpMethod.Delete)
|
||||
allowMethod(HttpMethod.Patch)
|
||||
allowHeader(HttpHeaders.Authorization)
|
||||
allowHeader("MyCustomHeader")
|
||||
allowHeader(HttpHeaders.AccessControlAllowOrigin)
|
||||
allowHeader(HttpHeaders.ContentType)
|
||||
anyHost() // @TODO: Don't do this in production if possible. Try to limit it.
|
||||
allowCredentials = true
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package dev.fyloz.musicplayer.core
|
||||
|
||||
fun <K, V> MutableMap<K, V>.removeIf(predicate: (V) -> Boolean) {
|
||||
this.filterValues(predicate).map { it.key }.forEach(this::remove)
|
||||
}
|
|
@ -1,10 +1,10 @@
|
|||
package dev.fyloz.musicplayer.core.data
|
||||
|
||||
import dev.fyloz.musicplayer.core.data.memory.SongMemoryRepository
|
||||
import dev.fyloz.musicplayer.core.data.memory.TrackMemoryRepository
|
||||
import org.koin.dsl.module
|
||||
|
||||
object RepositoryInjection {
|
||||
val koinBeans = module {
|
||||
single<SongRepository> { SongMemoryRepository() }
|
||||
single<TrackRepository> { TrackMemoryRepository() }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
package dev.fyloz.musicplayer.core.data
|
||||
|
||||
import dev.fyloz.musicplayer.core.model.Song
|
||||
|
||||
interface SongRepository : Repository<Song>
|
|
@ -0,0 +1,7 @@
|
|||
package dev.fyloz.musicplayer.core.data
|
||||
|
||||
import dev.fyloz.musicplayer.core.model.Track
|
||||
|
||||
interface TrackRepository : Repository<Track> {
|
||||
fun deleteByTrackId(trackId: String, source: String)
|
||||
}
|
|
@ -3,7 +3,7 @@ package dev.fyloz.musicplayer.core.data.memory
|
|||
import dev.fyloz.musicplayer.core.data.Repository
|
||||
|
||||
abstract class BaseMemoryRepository<T> : Repository<T> {
|
||||
private val memoryCache = mutableMapOf<String, T>()
|
||||
protected val memoryCache = mutableMapOf<String, T>()
|
||||
|
||||
override fun findAll() = memoryCache.values
|
||||
override fun findById(id: String) = memoryCache[id]
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
package dev.fyloz.musicplayer.core.data.memory
|
||||
|
||||
import dev.fyloz.musicplayer.core.data.SongRepository
|
||||
import dev.fyloz.musicplayer.core.model.Song
|
||||
|
||||
class SongMemoryRepository : BaseMemoryRepository<Song>(), SongRepository {
|
||||
override fun getId(t: Song) = t.id
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package dev.fyloz.musicplayer.core.data.memory
|
||||
|
||||
import dev.fyloz.musicplayer.core.data.TrackRepository
|
||||
import dev.fyloz.musicplayer.core.model.Track
|
||||
import dev.fyloz.musicplayer.core.removeIf
|
||||
|
||||
class TrackMemoryRepository : BaseMemoryRepository<Track>(), TrackRepository {
|
||||
override fun deleteByTrackId(trackId: String, source: String) {
|
||||
memoryCache.removeIf { it.source == source && it.trackId == trackId }
|
||||
}
|
||||
|
||||
override fun getId(t: Track) = t.id
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package dev.fyloz.musicplayer.core.factory
|
||||
|
||||
import dev.fyloz.musicplayer.core.http.auth.AuthorizationData
|
||||
import dev.fyloz.musicplayer.core.model.SearchResultItem
|
||||
import dev.fyloz.musicplayer.core.model.Song
|
||||
|
||||
interface SongFactory {
|
||||
suspend fun search(query: String, auth: AuthorizationData): Collection<SearchResultItem>
|
||||
suspend fun create(id: String, songId: String, auth: AuthorizationData): Song
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package dev.fyloz.musicplayer.core.factory
|
||||
|
||||
import dev.fyloz.musicplayer.core.http.auth.AuthorizationData
|
||||
import dev.fyloz.musicplayer.core.model.SearchResult
|
||||
import dev.fyloz.musicplayer.core.model.SearchResultItem
|
||||
import dev.fyloz.musicplayer.core.model.Song
|
||||
|
||||
typealias STR = String
|
||||
|
||||
class SongFactoryProxy {
|
||||
private val factories = mutableMapOf<String, SongFactory>()
|
||||
|
||||
fun registerFactory(type: String, factory: SongFactory) {
|
||||
factories[type] = factory;
|
||||
}
|
||||
|
||||
suspend fun search(query: String, auth: AuthorizationData): SearchResult {
|
||||
val results = mutableMapOf<String, Collection<SearchResultItem>>()
|
||||
factories.forEach { (type, factory) ->
|
||||
results[type] = factory.search(query, auth)
|
||||
}
|
||||
return results.toMap()
|
||||
}
|
||||
|
||||
suspend fun create(type: String, id: String, songId: String, auth: AuthorizationData): Song =
|
||||
getFactory(type).create(id, songId, auth)
|
||||
|
||||
private fun getFactory(type: String) = factories[type]!!;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package dev.fyloz.musicplayer.core.factory
|
||||
|
||||
import dev.fyloz.musicplayer.core.http.auth.AuthorizationData
|
||||
import dev.fyloz.musicplayer.core.model.ExternalTrack
|
||||
import dev.fyloz.musicplayer.core.model.Track
|
||||
|
||||
interface TrackFactory {
|
||||
suspend fun search(query: String, auth: AuthorizationData): Collection<ExternalTrack>
|
||||
suspend fun create(id: String, trackId: String, auth: AuthorizationData): Track
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package dev.fyloz.musicplayer.core.factory
|
||||
|
||||
import dev.fyloz.musicplayer.core.http.auth.AuthorizationData
|
||||
import dev.fyloz.musicplayer.core.model.SearchResult
|
||||
import dev.fyloz.musicplayer.core.model.ExternalTrack
|
||||
import dev.fyloz.musicplayer.core.model.Track
|
||||
|
||||
class TrackFactoryProxy {
|
||||
private val factories = mutableMapOf<String, TrackFactory>()
|
||||
|
||||
fun registerFactory(source: String, factory: TrackFactory) {
|
||||
factories[source] = factory;
|
||||
}
|
||||
|
||||
suspend fun search(query: String, auth: AuthorizationData): SearchResult {
|
||||
val results = mutableMapOf<String, Collection<ExternalTrack>>()
|
||||
factories.forEach { (source, factory) ->
|
||||
results[source] = factory.search(query, auth)
|
||||
}
|
||||
return results.toMap()
|
||||
}
|
||||
|
||||
suspend fun create(source: String, id: String, trackId: String, auth: AuthorizationData): Track =
|
||||
getFactory(source).create(id, trackId, auth)
|
||||
|
||||
private fun getFactory(source: String) = factories[source]!!;
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
package dev.fyloz.musicplayer.core.http
|
||||
|
||||
import dev.fyloz.musicplayer.core.getAuthorizationData
|
||||
import dev.fyloz.musicplayer.core.http.requests.CreateSongRequest
|
||||
import dev.fyloz.musicplayer.core.logic.SongLogic
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
import org.koin.ktor.ext.inject
|
||||
|
||||
fun Route.configureSongRoutes() {
|
||||
val logic by inject<SongLogic>()
|
||||
|
||||
route("/song") {
|
||||
get("/") {
|
||||
call.respond(logic.getAll().toList())
|
||||
}
|
||||
|
||||
get("/search") {
|
||||
val query = call.request.queryParameters["q"]!!
|
||||
val songs = logic.search(query, call.getAuthorizationData())
|
||||
call.respond(songs)
|
||||
}
|
||||
|
||||
post {
|
||||
val request = call.receive<CreateSongRequest>()
|
||||
val song = logic.save(request.type, request.songId, call.getAuthorizationData())
|
||||
call.respond(song)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package dev.fyloz.musicplayer.core.http
|
||||
|
||||
import dev.fyloz.musicplayer.core.getAuthorizationData
|
||||
import dev.fyloz.musicplayer.core.http.requests.ImportTrackRequest
|
||||
import dev.fyloz.musicplayer.core.logic.TrackLogic
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
import org.koin.ktor.ext.inject
|
||||
|
||||
fun Route.configureTrackRoutes() {
|
||||
val logic by inject<TrackLogic>()
|
||||
|
||||
route("/tracks") {
|
||||
get("/") {
|
||||
call.respond(logic.getAll().toList())
|
||||
}
|
||||
|
||||
get("/trackIds/") {
|
||||
call.respond(logic.getAllTrackIdsBySource())
|
||||
}
|
||||
|
||||
get("/search") {
|
||||
val query = call.request.queryParameters["q"]!!
|
||||
val tracks = logic.search(query, call.getAuthorizationData())
|
||||
call.respond(tracks)
|
||||
}
|
||||
|
||||
post("/") {
|
||||
val request = call.receive<ImportTrackRequest>()
|
||||
val track = logic.save(request.source, request.trackId, call.getAuthorizationData())
|
||||
call.respond(HttpStatusCode.Created, track)
|
||||
}
|
||||
|
||||
delete("/trackId/{source}/{trackId}") {
|
||||
val source = call.parameters["source"]
|
||||
val trackId = call.parameters["trackId"]
|
||||
|
||||
if (source != null && trackId != null) {
|
||||
logic.deleteByTrackId(trackId, source)
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.BadRequest)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,4 +3,4 @@ package dev.fyloz.musicplayer.core.http.requests
|
|||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class CreateSongRequest(val type: String, val songId: String)
|
||||
data class ImportTrackRequest(val source: String, val trackId: String)
|
|
@ -1,31 +0,0 @@
|
|||
package dev.fyloz.musicplayer.core.logic
|
||||
|
||||
import dev.fyloz.musicplayer.core.data.SongRepository
|
||||
import dev.fyloz.musicplayer.core.factory.SongFactoryProxy
|
||||
import dev.fyloz.musicplayer.core.http.auth.AuthorizationData
|
||||
import dev.fyloz.musicplayer.core.model.SearchResult
|
||||
import dev.fyloz.musicplayer.core.model.Song
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import java.util.UUID
|
||||
|
||||
class SongLogic : KoinComponent {
|
||||
private val repository by inject<SongRepository>()
|
||||
private val songFactory by inject<SongFactoryProxy>()
|
||||
|
||||
fun getAll() = repository.findAll()
|
||||
fun getById(id: String) = repository.findById(id)
|
||||
|
||||
suspend fun search(query: String, auth: AuthorizationData): SearchResult {
|
||||
return songFactory.search(query, auth)
|
||||
}
|
||||
|
||||
suspend fun save(type: String, songId: String, auth: AuthorizationData): Song {
|
||||
val id = generateId()
|
||||
val song = songFactory.create(type, id, songId, auth)
|
||||
repository.save(song)
|
||||
return song
|
||||
}
|
||||
|
||||
private fun generateId() = UUID.randomUUID().toString()
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package dev.fyloz.musicplayer.core.logic
|
||||
|
||||
import dev.fyloz.musicplayer.core.data.TrackRepository
|
||||
import dev.fyloz.musicplayer.core.factory.TrackFactoryProxy
|
||||
import dev.fyloz.musicplayer.core.http.auth.AuthorizationData
|
||||
import dev.fyloz.musicplayer.core.model.SearchResult
|
||||
import dev.fyloz.musicplayer.core.model.Track
|
||||
import org.koin.core.component.KoinComponent
|
||||
import org.koin.core.component.inject
|
||||
import java.util.UUID
|
||||
|
||||
class TrackLogic : KoinComponent {
|
||||
private val repository by inject<TrackRepository>()
|
||||
private val trackFactory by inject<TrackFactoryProxy>()
|
||||
|
||||
fun getAll() = repository.findAll()
|
||||
fun getAllTrackIdsBySource() = getAll()
|
||||
.groupBy { it.source }
|
||||
.mapValues { it.value.map { track -> track.trackId } }
|
||||
|
||||
fun getById(id: String) = repository.findById(id)
|
||||
|
||||
suspend fun search(query: String, auth: AuthorizationData): SearchResult {
|
||||
return trackFactory.search(query, auth)
|
||||
}
|
||||
|
||||
suspend fun save(source: String, trackId: String, auth: AuthorizationData): Track {
|
||||
val id = generateId()
|
||||
val track = trackFactory.create(source, id, trackId, auth)
|
||||
repository.save(track)
|
||||
return track
|
||||
}
|
||||
|
||||
fun deleteByTrackId(trackId: String, source: String) {
|
||||
repository.deleteByTrackId(trackId, source)
|
||||
}
|
||||
|
||||
private fun generateId() = UUID.randomUUID().toString()
|
||||
}
|
|
@ -2,11 +2,14 @@ package dev.fyloz.musicplayer.core.model
|
|||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
typealias SearchResult = Map<String, Collection<SearchResultItem>>
|
||||
typealias SearchResult = Map<String, Collection<ExternalTrack>>
|
||||
|
||||
@Serializable
|
||||
data class SearchResultItem(
|
||||
val songId: String,
|
||||
data class ExternalTrack(
|
||||
val trackId: String,
|
||||
val name: String,
|
||||
val authors: Collection<String>
|
||||
val albumName: String,
|
||||
val authors: Collection<String>,
|
||||
val thumbnailUrl: String,
|
||||
val previewUrl: String
|
||||
)
|
|
@ -1,18 +0,0 @@
|
|||
package dev.fyloz.musicplayer.core.model
|
||||
|
||||
/**
|
||||
* A generic song.
|
||||
*/
|
||||
abstract class Song {
|
||||
/** The id of the song in the local system. **/
|
||||
abstract val id: String
|
||||
|
||||
/** The id of the song in the remote service. **/
|
||||
abstract val songId: String
|
||||
|
||||
/** The name of the song. **/
|
||||
abstract val name: String
|
||||
|
||||
/** The name of the authors of the song. **/
|
||||
abstract val authors: Collection<String>
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package dev.fyloz.musicplayer.core.model
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* A generic track.
|
||||
*/
|
||||
abstract class Track {
|
||||
/** The id of the track in the local system. **/
|
||||
abstract val id: String
|
||||
|
||||
/** The id of the track in the remote service. **/
|
||||
abstract val trackId: String
|
||||
|
||||
/** The name of the track. **/
|
||||
abstract val name: String
|
||||
|
||||
/** The name of the authors of the track. **/
|
||||
abstract val authors: Collection<String>
|
||||
|
||||
/** The name of the source module of the track. **/
|
||||
abstract val source: String
|
||||
|
||||
/** The URLs to the track images. **/
|
||||
abstract val imagesUrls: TrackImagesUrls
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class TrackImagesUrls(
|
||||
/** The URL of the track icon. **/
|
||||
val icon: String,
|
||||
|
||||
/** The URL of the track thumbnail. **/
|
||||
val thumbnail: String,
|
||||
|
||||
/** The URL of the track's full resolution image. **/
|
||||
val fullRes: String
|
||||
)
|
|
@ -1,8 +1,8 @@
|
|||
package dev.fyloz.musicplayer.modules
|
||||
|
||||
import dev.fyloz.musicplayer.core.KoinModule
|
||||
import dev.fyloz.musicplayer.core.factory.SongFactory
|
||||
import dev.fyloz.musicplayer.core.factory.SongFactoryProxy
|
||||
import dev.fyloz.musicplayer.core.factory.TrackFactory
|
||||
import dev.fyloz.musicplayer.core.factory.TrackFactoryProxy
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.config.*
|
||||
import io.ktor.server.routing.*
|
||||
|
@ -14,8 +14,8 @@ abstract class Module(private val moduleName: String) {
|
|||
|
||||
open fun configure(app: Application) {
|
||||
with(app) {
|
||||
val songFactoryProxy by inject<SongFactoryProxy>()
|
||||
songFactoryProxy.registerFactory(moduleName, getSongFactory())
|
||||
val trackFactoryProxy by inject<TrackFactoryProxy>()
|
||||
trackFactoryProxy.registerFactory(moduleName, getTrackFactory())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -39,5 +39,5 @@ abstract class Module(private val moduleName: String) {
|
|||
protected open fun Route.configureModuleRoutes() {
|
||||
}
|
||||
|
||||
protected abstract fun getSongFactory(): SongFactory
|
||||
protected abstract fun getTrackFactory(): TrackFactory
|
||||
}
|
||||
|
|
|
@ -16,6 +16,6 @@ class SpotifyApiProvider : HttpProvider("https://api.spotify.com/v1") {
|
|||
}
|
||||
}.tracks.items
|
||||
|
||||
suspend fun getSongById(songId: String, accessToken: String): Track =
|
||||
get("tracks/$songId", accessToken)
|
||||
suspend fun getTrackById(trackId: String, accessToken: String): Track =
|
||||
get("tracks/$trackId", accessToken)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,6 @@ import org.koin.dsl.module
|
|||
|
||||
object SpotifyInjection {
|
||||
val koinBeans = module {
|
||||
single<SpotifySongFactory> { SpotifySongFactory() }
|
||||
single<SpotifyTrackFactory> { SpotifyTrackFactory() }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,7 +47,8 @@ class SpotifyModule : Module(moduleName) {
|
|||
}
|
||||
|
||||
override fun getAuthorizationData(call: ApplicationCall) = SpotifyAuthorizationData(
|
||||
call.request.cookies["Spotify-Access-Token"]!!
|
||||
// call.request.cookies["Spotify-Access-Token"]!!
|
||||
"BQA5jMFjiPuGgPJ8ogizGh3lR82HIGnkGAZQWFcUSOzIeoGonRleiJ1VUueUlfRpBPBjczBzNZY3EWEHC8kU21SzSyz__DPcZouA2Geyy1obEmbTar8OhQn640JU8VoszpsDFoZTyEAQATbKHVlq6n7Vb51S_nqFHcYww_rUfwObuVRumydpU8rHqWqr"
|
||||
)
|
||||
|
||||
override fun Route.configureModuleRoutes() {
|
||||
|
@ -67,7 +68,7 @@ class SpotifyModule : Module(moduleName) {
|
|||
}
|
||||
}
|
||||
|
||||
override fun getSongFactory() = SpotifySongFactory()
|
||||
override fun getTrackFactory() = SpotifyTrackFactory()
|
||||
|
||||
companion object {
|
||||
const val moduleName = "spotify"
|
||||
|
|
|
@ -1,12 +0,0 @@
|
|||
package dev.fyloz.musicplayer.modules.spotify
|
||||
|
||||
import dev.fyloz.musicplayer.core.model.Song
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class SpotifySong(
|
||||
override val id: String,
|
||||
override val songId: String,
|
||||
override val name: String,
|
||||
override val authors: Collection<String>
|
||||
) : Song()
|
|
@ -1,23 +0,0 @@
|
|||
package dev.fyloz.musicplayer.modules.spotify
|
||||
|
||||
import dev.fyloz.musicplayer.core.factory.SongFactory
|
||||
import dev.fyloz.musicplayer.core.http.auth.AuthorizationData
|
||||
import dev.fyloz.musicplayer.core.model.SearchResultItem
|
||||
import dev.fyloz.musicplayer.core.model.Song
|
||||
|
||||
class SpotifySongFactory : SongFactory {
|
||||
private val apiProvider = SpotifyApiProvider()
|
||||
|
||||
override suspend fun search(query: String, auth: AuthorizationData): Collection<SearchResultItem> {
|
||||
val apiSongs = apiProvider.search(query, "track", auth.accessToken)
|
||||
return apiSongs.map { SearchResultItem(it.id, it.name, it.artists.map { a -> a.name }) }
|
||||
}
|
||||
|
||||
override suspend fun create(id: String, songId: String, auth: AuthorizationData): Song {
|
||||
val spotifyApiSong = apiProvider.getSongById(songId, auth.accessToken);
|
||||
return SpotifySong(id, songId, spotifyApiSong.name, spotifyApiSong.artists.map { it.name })
|
||||
}
|
||||
|
||||
private val AuthorizationData.accessToken
|
||||
get() = getModuleData<SpotifyAuthorizationData>(SpotifyModule.moduleName).accessToken
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package dev.fyloz.musicplayer.modules.spotify
|
||||
|
||||
import dev.fyloz.musicplayer.core.model.Track
|
||||
import dev.fyloz.musicplayer.core.model.TrackImagesUrls
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class SpotifyTrack(
|
||||
override val id: String,
|
||||
override val trackId: String,
|
||||
override val name: String,
|
||||
override val authors: Collection<String>,
|
||||
override val imagesUrls: TrackImagesUrls
|
||||
) : Track() {
|
||||
override val source = SpotifyModule.moduleName
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
package dev.fyloz.musicplayer.modules.spotify
|
||||
|
||||
import dev.fyloz.musicplayer.core.factory.TrackFactory
|
||||
import dev.fyloz.musicplayer.core.http.auth.AuthorizationData
|
||||
import dev.fyloz.musicplayer.core.model.ExternalTrack
|
||||
import dev.fyloz.musicplayer.core.model.Track
|
||||
import dev.fyloz.musicplayer.core.model.TrackImagesUrls
|
||||
|
||||
class SpotifyTrackFactory : TrackFactory {
|
||||
private val apiProvider = SpotifyApiProvider()
|
||||
|
||||
override suspend fun search(query: String, auth: AuthorizationData): Collection<ExternalTrack> {
|
||||
val tracks = apiProvider.search(query, "track", auth.accessToken)
|
||||
|
||||
return tracks.map {
|
||||
val artists = it.artists.map { artist -> artist.name }
|
||||
val thumbnailUrl = it.album.images.first { image -> image.width == 300 }.url
|
||||
|
||||
ExternalTrack(it.id, it.name, it.album.name, artists, thumbnailUrl, it.previewUrl)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun create(id: String, trackId: String, auth: AuthorizationData): Track {
|
||||
val spotifyApiTrack = apiProvider.getTrackById(trackId, auth.accessToken)
|
||||
val artists = spotifyApiTrack.artists.map { it.name }
|
||||
val imagesUrls = TrackImagesUrls(
|
||||
spotifyApiTrack.album.images.first { it.width == 64 }.url,
|
||||
spotifyApiTrack.album.images.first { it.width == 300 }.url,
|
||||
spotifyApiTrack.album.images.first { it.width == 640 }.url
|
||||
)
|
||||
|
||||
return SpotifyTrack(id, trackId, spotifyApiTrack.name, artists, imagesUrls)
|
||||
}
|
||||
|
||||
private val AuthorizationData.accessToken
|
||||
get() = getModuleData<SpotifyAuthorizationData>(SpotifyModule.moduleName).accessToken
|
||||
}
|
Loading…
Reference in New Issue