diff --git a/src/main/kotlin/com/jeluchu/core/models/SimpleAnimeEntity.kt b/src/main/kotlin/com/jeluchu/core/models/SimpleAnimeEntity.kt new file mode 100644 index 0000000..57add03 --- /dev/null +++ b/src/main/kotlin/com/jeluchu/core/models/SimpleAnimeEntity.kt @@ -0,0 +1,27 @@ +package com.jeluchu.core.models + +import com.jeluchu.core.extensions.getDocumentSafe +import com.jeluchu.core.extensions.getIntSafe +import com.jeluchu.core.extensions.getStringSafe +import com.jeluchu.features.anime.mappers.documentToMultipleLanguageLists +import com.jeluchu.features.anime.models.anime.MultipleLanguageLists +import com.jeluchu.features.anime.models.tags.TagsAnimeEntity +import kotlinx.serialization.Serializable +import org.bson.Document + +@Serializable +data class SimpleAnimeEntity( + val malId: Int, + val type: String, + val title: String, + val image: String, + val score: String +) + +fun documentToSimpleAnimeEntity(doc: Document) = SimpleAnimeEntity( + malId = doc.getIntSafe("malId"), + title = doc.getStringSafe("title"), + type = doc.getStringSafe("type"), + score = doc.getStringSafe("score"), + image = doc.getStringSafe("poster") +) \ No newline at end of file diff --git a/src/main/kotlin/com/jeluchu/core/utils/Constants.kt b/src/main/kotlin/com/jeluchu/core/utils/Constants.kt index 89e997d..f9884a2 100644 --- a/src/main/kotlin/com/jeluchu/core/utils/Constants.kt +++ b/src/main/kotlin/com/jeluchu/core/utils/Constants.kt @@ -52,6 +52,7 @@ object Routes { const val ES = "/es" const val EN = "/en" const val TOP = "/top" + const val TAGS = "/tags" const val NEWS = "/news" const val ANIME = "/anime" const val MANGA = "/manga" diff --git a/src/main/kotlin/com/jeluchu/features/anime/mappers/SeasonMappers.kt b/src/main/kotlin/com/jeluchu/features/anime/mappers/SeasonMappers.kt deleted file mode 100644 index b595081..0000000 --- a/src/main/kotlin/com/jeluchu/features/anime/mappers/SeasonMappers.kt +++ /dev/null @@ -1,13 +0,0 @@ -package com.jeluchu.features.anime.mappers - -import com.jeluchu.core.extensions.getIntSafe -import com.jeluchu.core.extensions.getStringSafe -import com.jeluchu.features.anime.models.seasons.SeasonAnimeEntity -import org.bson.Document - -fun documentToSeasonEntity(doc: Document) = SeasonAnimeEntity( - score = doc.getStringSafe("score"), - malId = doc.getIntSafe("malId"), - image = doc.getStringSafe("poster"), - title = doc.getStringSafe("title") -) \ No newline at end of file diff --git a/src/main/kotlin/com/jeluchu/features/anime/models/seasons/SeasonAnimeEntity.kt b/src/main/kotlin/com/jeluchu/features/anime/models/seasons/SeasonAnimeEntity.kt deleted file mode 100644 index 534c45d..0000000 --- a/src/main/kotlin/com/jeluchu/features/anime/models/seasons/SeasonAnimeEntity.kt +++ /dev/null @@ -1,11 +0,0 @@ -package com.jeluchu.features.anime.models.seasons - -import kotlinx.serialization.Serializable - -@Serializable -data class SeasonAnimeEntity( - val malId: Int, - val title: String, - val image: String, - val score: String, -) \ No newline at end of file diff --git a/src/main/kotlin/com/jeluchu/features/anime/routes/AnimeRoutes.kt b/src/main/kotlin/com/jeluchu/features/anime/routes/AnimeRoutes.kt index 58898f3..9f411ff 100644 --- a/src/main/kotlin/com/jeluchu/features/anime/routes/AnimeRoutes.kt +++ b/src/main/kotlin/com/jeluchu/features/anime/routes/AnimeRoutes.kt @@ -5,17 +5,20 @@ import com.jeluchu.core.utils.Routes import com.jeluchu.features.anime.services.AnimeService import com.jeluchu.features.anime.services.DirectoryService import com.jeluchu.features.anime.services.SeasonService +import com.jeluchu.features.anime.services.TagsService import com.mongodb.client.MongoDatabase import io.ktor.server.routing.* fun Route.animeEndpoints( mongoDatabase: MongoDatabase, service: AnimeService = AnimeService(mongoDatabase), + tagsService: TagsService = TagsService(mongoDatabase), seasonService: SeasonService = SeasonService(mongoDatabase), directoryService: DirectoryService = DirectoryService(mongoDatabase), ) = route(Routes.ANIME) { getToJson { service.getAnimeByType(call) } getToJson(Routes.ID) { service.getAnimeByMalId(call) } + getToJson(Routes.TAGS) { tagsService.getAnimeByAnyTag(call) } getToJson(Routes.LAST_EPISODES) { service.getLastEpisodes(call) } route(Routes.SEASON) { diff --git a/src/main/kotlin/com/jeluchu/features/anime/services/SeasonService.kt b/src/main/kotlin/com/jeluchu/features/anime/services/SeasonService.kt index 73df943..348696a 100644 --- a/src/main/kotlin/com/jeluchu/features/anime/services/SeasonService.kt +++ b/src/main/kotlin/com/jeluchu/features/anime/services/SeasonService.kt @@ -1,15 +1,9 @@ package com.jeluchu.features.anime.services -import com.jeluchu.core.enums.TimeUnit import com.jeluchu.core.enums.parseSeasons -import com.jeluchu.core.extensions.badRequestError -import com.jeluchu.core.extensions.getIntSafeQueryParam -import com.jeluchu.core.extensions.needsUpdate -import com.jeluchu.core.extensions.update -import com.jeluchu.core.messages.ErrorMessages -import com.jeluchu.core.utils.* -import com.jeluchu.features.anime.mappers.documentToAnimeDirectoryEntity -import com.jeluchu.features.anime.mappers.documentToSeasonEntity +import com.jeluchu.core.models.documentToSimpleAnimeEntity +import com.jeluchu.core.utils.Collections +import com.jeluchu.core.utils.SeasonCalendar import com.jeluchu.features.anime.models.seasons.YearSeasons import com.mongodb.client.MongoCollection import com.mongodb.client.MongoDatabase @@ -31,21 +25,19 @@ class SeasonService( ) { suspend fun getAnimeBySeason(call: RoutingCall) { val year = call.request.queryParameters["year"]?.toInt() ?: SeasonCalendar.currentYear - val station = parseSeasons(call.request.queryParameters["season"] ?: SeasonCalendar.currentSeason.name) ?: SeasonCalendar.currentSeason - val page = call.getIntSafeQueryParam("page", 1) - val size = call.getIntSafeQueryParam("size", 10) + val station = parseSeasons(call.request.queryParameters["season"] ?: SeasonCalendar.currentSeason.name) + ?: SeasonCalendar.currentSeason - val skipCount = (page - 1) * size - if (page < 1 || size < 1) call.badRequestError(ErrorMessages.InvalidSizeAndPage.message) - - val query = directory.find( - Filters.and( - Filters.eq("season.year", year), - Filters.eq("season.station", station) - ) - ) - .toList() - .map { documentToSeasonEntity(it) } + val query = directory.find( + Filters.and( + Filters.eq("season.year", year), + Filters.eq("season.station", station), + Filters.ne("type", "MUSIC"), + Filters.ne("type", "PV"), + ) + ) + .toList() + .map { documentToSimpleAnimeEntity(it) } call.respond(HttpStatusCode.OK, Json.encodeToString(query)) } @@ -56,18 +48,18 @@ class SeasonService( val pipeline = listOf( Aggregates.match( - Document("\$and", listOf( - Document("season.year", Document("\$gt", 0)), - Document("season.year", Document("\$lte", currentYear)), - Document("season.station", Document("\$in", validSeasons)) - )) + Document( + "\$and", listOf( + Document("season.year", Document("\$gt", 0)), + Document("season.year", Document("\$lte", currentYear)), + Document("season.station", Document("\$in", validSeasons)) + ) + ) ), - Aggregates.group( "\$season.year", Accumulators.addToSet("seasons", "\$season.station") ), - Aggregates.project( Document().apply { put("year", "\$_id") @@ -75,7 +67,6 @@ class SeasonService( put("_id", 0) } ), - Aggregates.sort(Sorts.descending("year")) ) diff --git a/src/main/kotlin/com/jeluchu/features/anime/services/TagsService.kt b/src/main/kotlin/com/jeluchu/features/anime/services/TagsService.kt new file mode 100644 index 0000000..cb19b74 --- /dev/null +++ b/src/main/kotlin/com/jeluchu/features/anime/services/TagsService.kt @@ -0,0 +1,44 @@ +package com.jeluchu.features.anime.services + +import com.jeluchu.core.models.documentToSimpleAnimeEntity +import com.jeluchu.core.utils.Collections +import com.mongodb.client.MongoCollection +import com.mongodb.client.MongoDatabase +import com.mongodb.client.model.Filters +import io.ktor.http.* +import io.ktor.server.response.* +import io.ktor.server.routing.* +import kotlinx.serialization.encodeToString +import kotlinx.serialization.json.Json +import org.bson.Document + +class TagsService( + private val database: MongoDatabase, + private val directory: MongoCollection = database.getCollection(Collections.ANIME_DIRECTORY) +) { + suspend fun getAnimeByAnyTag(call: RoutingCall) { + val tagsParam = call.request.queryParameters["tags"].orEmpty() + + val tags = if (tagsParam.isNotEmpty()) { + tagsParam.split(",").map { it.trim() } + } else emptyList() + + if (tags.isEmpty()) { + call.respond(HttpStatusCode.BadRequest, "No tags provided") + return + } + + val query = directory.find( + Filters.or( + Filters.`in`("tags.es", tags), + Filters.`in`("tags.en", tags), + Filters.ne("type", "MUSIC"), + Filters.ne("type", "PV"), + ) + ) + .toList() + .map { documentToSimpleAnimeEntity(it) } + + call.respond(HttpStatusCode.OK, Json.encodeToString(query)) + } +} \ No newline at end of file