Refactor season endpoint and include tags endpoint

v5 v5.7.0
Jéluchu 1 month ago
parent 03842ab1f9
commit b0fd2e84ad

@ -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")
)

@ -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"

@ -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")
)

@ -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,
)

@ -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) {

@ -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 skipCount = (page - 1) * size
if (page < 1 || size < 1) call.badRequestError(ErrorMessages.InvalidSizeAndPage.message)
val station = parseSeasons(call.request.queryParameters["season"] ?: SeasonCalendar.currentSeason.name)
?: SeasonCalendar.currentSeason
val query = directory.find(
Filters.and(
Filters.eq("season.year", year),
Filters.eq("season.station", station)
Filters.eq("season.station", station),
Filters.ne("type", "MUSIC"),
Filters.ne("type", "PV"),
)
)
.toList()
.map { documentToSeasonEntity(it) }
.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(
"\$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"))
)

@ -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<Document> = 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))
}
}
Loading…
Cancel
Save