From 71cb4abae9c49333b5000f6a2544cf33317a16df Mon Sep 17 00:00:00 2001 From: william Date: Tue, 24 Jan 2023 22:39:09 -0500 Subject: [PATCH] Things --- .../dev/fyloz/musicplayer/core/Application.kt | 19 +++---- .../fyloz/musicplayer/core/CollectionUtils.kt | 5 ++ .../core/data/RepositoryInjection.kt | 4 +- .../musicplayer/core/data/SongRepository.kt | 5 -- .../musicplayer/core/data/TrackRepository.kt | 7 +++ .../core/data/memory/BaseMemoryRepository.kt | 2 +- .../core/data/memory/SongMemoryRepository.kt | 8 --- .../core/data/memory/TrackMemoryRepository.kt | 13 +++++ .../musicplayer/core/factory/SongFactory.kt | 10 ---- .../core/factory/SongFactoryProxy.kt | 29 ----------- .../musicplayer/core/factory/TrackFactory.kt | 10 ++++ .../core/factory/TrackFactoryProxy.kt | 27 ++++++++++ .../fyloz/musicplayer/core/http/SongRoutes.kt | 32 ------------ .../musicplayer/core/http/TrackRoutes.kt | 49 +++++++++++++++++++ ...teSongRequest.kt => ImportTrackRequest.kt} | 2 +- .../fyloz/musicplayer/core/logic/SongLogic.kt | 31 ------------ .../musicplayer/core/logic/TrackLogic.kt | 39 +++++++++++++++ .../musicplayer/core/model/SearchResult.kt | 13 +++-- .../dev/fyloz/musicplayer/core/model/Song.kt | 18 ------- .../dev/fyloz/musicplayer/core/model/Track.kt | 38 ++++++++++++++ .../dev/fyloz/musicplayer/modules/Module.kt | 10 ++-- .../modules/spotify/SpotifyApiProvider.kt | 4 +- .../modules/spotify/SpotifyInjection.kt | 2 +- .../modules/spotify/SpotifyModule.kt | 5 +- .../modules/spotify/SpotifySong.kt | 12 ----- .../modules/spotify/SpotifySongFactory.kt | 23 --------- .../modules/spotify/SpotifyTrack.kt | 16 ++++++ .../modules/spotify/SpotifyTrackFactory.kt | 37 ++++++++++++++ 28 files changed, 274 insertions(+), 196 deletions(-) create mode 100644 src/main/kotlin/dev/fyloz/musicplayer/core/CollectionUtils.kt delete mode 100644 src/main/kotlin/dev/fyloz/musicplayer/core/data/SongRepository.kt create mode 100644 src/main/kotlin/dev/fyloz/musicplayer/core/data/TrackRepository.kt delete mode 100644 src/main/kotlin/dev/fyloz/musicplayer/core/data/memory/SongMemoryRepository.kt create mode 100644 src/main/kotlin/dev/fyloz/musicplayer/core/data/memory/TrackMemoryRepository.kt delete mode 100644 src/main/kotlin/dev/fyloz/musicplayer/core/factory/SongFactory.kt delete mode 100644 src/main/kotlin/dev/fyloz/musicplayer/core/factory/SongFactoryProxy.kt create mode 100644 src/main/kotlin/dev/fyloz/musicplayer/core/factory/TrackFactory.kt create mode 100644 src/main/kotlin/dev/fyloz/musicplayer/core/factory/TrackFactoryProxy.kt delete mode 100644 src/main/kotlin/dev/fyloz/musicplayer/core/http/SongRoutes.kt create mode 100644 src/main/kotlin/dev/fyloz/musicplayer/core/http/TrackRoutes.kt rename src/main/kotlin/dev/fyloz/musicplayer/core/http/requests/{CreateSongRequest.kt => ImportTrackRequest.kt} (60%) delete mode 100644 src/main/kotlin/dev/fyloz/musicplayer/core/logic/SongLogic.kt create mode 100644 src/main/kotlin/dev/fyloz/musicplayer/core/logic/TrackLogic.kt delete mode 100644 src/main/kotlin/dev/fyloz/musicplayer/core/model/Song.kt create mode 100644 src/main/kotlin/dev/fyloz/musicplayer/core/model/Track.kt delete mode 100644 src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifySong.kt delete mode 100644 src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifySongFactory.kt create mode 100644 src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyTrack.kt create mode 100644 src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyTrackFactory.kt diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/Application.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/Application.kt index df8be0f..d64206e 100644 --- a/src/main/kotlin/dev/fyloz/musicplayer/core/Application.kt +++ b/src/main/kotlin/dev/fyloz/musicplayer/core/Application.kt @@ -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 } } diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/CollectionUtils.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/CollectionUtils.kt new file mode 100644 index 0000000..1d77a40 --- /dev/null +++ b/src/main/kotlin/dev/fyloz/musicplayer/core/CollectionUtils.kt @@ -0,0 +1,5 @@ +package dev.fyloz.musicplayer.core + +fun MutableMap.removeIf(predicate: (V) -> Boolean) { + this.filterValues(predicate).map { it.key }.forEach(this::remove) +} diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/data/RepositoryInjection.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/data/RepositoryInjection.kt index 614704c..50ae9e2 100644 --- a/src/main/kotlin/dev/fyloz/musicplayer/core/data/RepositoryInjection.kt +++ b/src/main/kotlin/dev/fyloz/musicplayer/core/data/RepositoryInjection.kt @@ -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 { SongMemoryRepository() } + single { TrackMemoryRepository() } } } diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/data/SongRepository.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/data/SongRepository.kt deleted file mode 100644 index 1267585..0000000 --- a/src/main/kotlin/dev/fyloz/musicplayer/core/data/SongRepository.kt +++ /dev/null @@ -1,5 +0,0 @@ -package dev.fyloz.musicplayer.core.data - -import dev.fyloz.musicplayer.core.model.Song - -interface SongRepository : Repository diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/data/TrackRepository.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/data/TrackRepository.kt new file mode 100644 index 0000000..37c5de0 --- /dev/null +++ b/src/main/kotlin/dev/fyloz/musicplayer/core/data/TrackRepository.kt @@ -0,0 +1,7 @@ +package dev.fyloz.musicplayer.core.data + +import dev.fyloz.musicplayer.core.model.Track + +interface TrackRepository : Repository { + fun deleteByTrackId(trackId: String, source: String) +} diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/data/memory/BaseMemoryRepository.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/data/memory/BaseMemoryRepository.kt index f28cbc7..4f447fd 100644 --- a/src/main/kotlin/dev/fyloz/musicplayer/core/data/memory/BaseMemoryRepository.kt +++ b/src/main/kotlin/dev/fyloz/musicplayer/core/data/memory/BaseMemoryRepository.kt @@ -3,7 +3,7 @@ package dev.fyloz.musicplayer.core.data.memory import dev.fyloz.musicplayer.core.data.Repository abstract class BaseMemoryRepository : Repository { - private val memoryCache = mutableMapOf() + protected val memoryCache = mutableMapOf() override fun findAll() = memoryCache.values override fun findById(id: String) = memoryCache[id] diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/data/memory/SongMemoryRepository.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/data/memory/SongMemoryRepository.kt deleted file mode 100644 index 5005182..0000000 --- a/src/main/kotlin/dev/fyloz/musicplayer/core/data/memory/SongMemoryRepository.kt +++ /dev/null @@ -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(), SongRepository { - override fun getId(t: Song) = t.id -} diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/data/memory/TrackMemoryRepository.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/data/memory/TrackMemoryRepository.kt new file mode 100644 index 0000000..bc1ea91 --- /dev/null +++ b/src/main/kotlin/dev/fyloz/musicplayer/core/data/memory/TrackMemoryRepository.kt @@ -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(), TrackRepository { + override fun deleteByTrackId(trackId: String, source: String) { + memoryCache.removeIf { it.source == source && it.trackId == trackId } + } + + override fun getId(t: Track) = t.id +} diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/factory/SongFactory.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/factory/SongFactory.kt deleted file mode 100644 index a1c0391..0000000 --- a/src/main/kotlin/dev/fyloz/musicplayer/core/factory/SongFactory.kt +++ /dev/null @@ -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 - suspend fun create(id: String, songId: String, auth: AuthorizationData): Song -} diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/factory/SongFactoryProxy.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/factory/SongFactoryProxy.kt deleted file mode 100644 index 9d0b304..0000000 --- a/src/main/kotlin/dev/fyloz/musicplayer/core/factory/SongFactoryProxy.kt +++ /dev/null @@ -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() - - fun registerFactory(type: String, factory: SongFactory) { - factories[type] = factory; - } - - suspend fun search(query: String, auth: AuthorizationData): SearchResult { - val results = mutableMapOf>() - 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]!!; -} diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/factory/TrackFactory.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/factory/TrackFactory.kt new file mode 100644 index 0000000..f766275 --- /dev/null +++ b/src/main/kotlin/dev/fyloz/musicplayer/core/factory/TrackFactory.kt @@ -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 + suspend fun create(id: String, trackId: String, auth: AuthorizationData): Track +} diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/factory/TrackFactoryProxy.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/factory/TrackFactoryProxy.kt new file mode 100644 index 0000000..5b14d1d --- /dev/null +++ b/src/main/kotlin/dev/fyloz/musicplayer/core/factory/TrackFactoryProxy.kt @@ -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() + + fun registerFactory(source: String, factory: TrackFactory) { + factories[source] = factory; + } + + suspend fun search(query: String, auth: AuthorizationData): SearchResult { + val results = mutableMapOf>() + 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]!!; +} diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/http/SongRoutes.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/http/SongRoutes.kt deleted file mode 100644 index ca63724..0000000 --- a/src/main/kotlin/dev/fyloz/musicplayer/core/http/SongRoutes.kt +++ /dev/null @@ -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() - - 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() - val song = logic.save(request.type, request.songId, call.getAuthorizationData()) - call.respond(song) - } - } -} diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/http/TrackRoutes.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/http/TrackRoutes.kt new file mode 100644 index 0000000..66b4cc8 --- /dev/null +++ b/src/main/kotlin/dev/fyloz/musicplayer/core/http/TrackRoutes.kt @@ -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() + + 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() + 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) + } + } + } +} diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/http/requests/CreateSongRequest.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/http/requests/ImportTrackRequest.kt similarity index 60% rename from src/main/kotlin/dev/fyloz/musicplayer/core/http/requests/CreateSongRequest.kt rename to src/main/kotlin/dev/fyloz/musicplayer/core/http/requests/ImportTrackRequest.kt index c065b8d..5a4f700 100644 --- a/src/main/kotlin/dev/fyloz/musicplayer/core/http/requests/CreateSongRequest.kt +++ b/src/main/kotlin/dev/fyloz/musicplayer/core/http/requests/ImportTrackRequest.kt @@ -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) diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/logic/SongLogic.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/logic/SongLogic.kt deleted file mode 100644 index 8f1bb50..0000000 --- a/src/main/kotlin/dev/fyloz/musicplayer/core/logic/SongLogic.kt +++ /dev/null @@ -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() - private val songFactory by inject() - - 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() -} diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/logic/TrackLogic.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/logic/TrackLogic.kt new file mode 100644 index 0000000..47e8e14 --- /dev/null +++ b/src/main/kotlin/dev/fyloz/musicplayer/core/logic/TrackLogic.kt @@ -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() + private val trackFactory by inject() + + 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() +} diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/model/SearchResult.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/model/SearchResult.kt index c620318..6570a62 100644 --- a/src/main/kotlin/dev/fyloz/musicplayer/core/model/SearchResult.kt +++ b/src/main/kotlin/dev/fyloz/musicplayer/core/model/SearchResult.kt @@ -2,11 +2,14 @@ package dev.fyloz.musicplayer.core.model import kotlinx.serialization.Serializable -typealias SearchResult = Map> +typealias SearchResult = Map> @Serializable -data class SearchResultItem( - val songId: String, +data class ExternalTrack( + val trackId: String, val name: String, - val authors: Collection -) \ No newline at end of file + val albumName: String, + val authors: Collection, + val thumbnailUrl: String, + val previewUrl: String +) diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/model/Song.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/model/Song.kt deleted file mode 100644 index 0fcfded..0000000 --- a/src/main/kotlin/dev/fyloz/musicplayer/core/model/Song.kt +++ /dev/null @@ -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 -} diff --git a/src/main/kotlin/dev/fyloz/musicplayer/core/model/Track.kt b/src/main/kotlin/dev/fyloz/musicplayer/core/model/Track.kt new file mode 100644 index 0000000..1fe1200 --- /dev/null +++ b/src/main/kotlin/dev/fyloz/musicplayer/core/model/Track.kt @@ -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 + + /** 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 +) diff --git a/src/main/kotlin/dev/fyloz/musicplayer/modules/Module.kt b/src/main/kotlin/dev/fyloz/musicplayer/modules/Module.kt index 2d911e4..769a7bb 100644 --- a/src/main/kotlin/dev/fyloz/musicplayer/modules/Module.kt +++ b/src/main/kotlin/dev/fyloz/musicplayer/modules/Module.kt @@ -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.registerFactory(moduleName, getSongFactory()) + val trackFactoryProxy by inject() + 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 } diff --git a/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyApiProvider.kt b/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyApiProvider.kt index 52acfaf..38e63d1 100644 --- a/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyApiProvider.kt +++ b/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyApiProvider.kt @@ -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) } diff --git a/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyInjection.kt b/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyInjection.kt index 9090eb8..eba679a 100644 --- a/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyInjection.kt +++ b/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyInjection.kt @@ -4,6 +4,6 @@ import org.koin.dsl.module object SpotifyInjection { val koinBeans = module { - single { SpotifySongFactory() } + single { SpotifyTrackFactory() } } } diff --git a/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyModule.kt b/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyModule.kt index 8b8f1d7..628df60 100644 --- a/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyModule.kt +++ b/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyModule.kt @@ -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" diff --git a/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifySong.kt b/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifySong.kt deleted file mode 100644 index 5846d07..0000000 --- a/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifySong.kt +++ /dev/null @@ -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 -) : Song() diff --git a/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifySongFactory.kt b/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifySongFactory.kt deleted file mode 100644 index 59036f0..0000000 --- a/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifySongFactory.kt +++ /dev/null @@ -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 { - 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(SpotifyModule.moduleName).accessToken -} diff --git a/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyTrack.kt b/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyTrack.kt new file mode 100644 index 0000000..2f60d82 --- /dev/null +++ b/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyTrack.kt @@ -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, + override val imagesUrls: TrackImagesUrls +) : Track() { + override val source = SpotifyModule.moduleName +} diff --git a/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyTrackFactory.kt b/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyTrackFactory.kt new file mode 100644 index 0000000..3addf56 --- /dev/null +++ b/src/main/kotlin/dev/fyloz/musicplayer/modules/spotify/SpotifyTrackFactory.kt @@ -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 { + 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(SpotifyModule.moduleName).accessToken +}