diff --git a/src/main/kotlin/com/jeluchu/core/models/PaginacionResponse.kt b/src/main/kotlin/com/jeluchu/core/models/PaginationResponse.kt similarity index 100% rename from src/main/kotlin/com/jeluchu/core/models/PaginacionResponse.kt rename to src/main/kotlin/com/jeluchu/core/models/PaginationResponse.kt diff --git a/src/main/kotlin/com/jeluchu/core/utils/Constants.kt b/src/main/kotlin/com/jeluchu/core/utils/Constants.kt index ab7e2ad..d63e250 100644 --- a/src/main/kotlin/com/jeluchu/core/utils/Constants.kt +++ b/src/main/kotlin/com/jeluchu/core/utils/Constants.kt @@ -6,14 +6,10 @@ object BaseUrls { } object Endpoints { - const val FULL = "full" - const val ANIME = "anime/" const val SCHEDULES = "schedules" const val TOP_ANIME = "top/anime" const val TOP_MANGA = "top/manga" const val TOP_PEOPLE = "top/people" - const val STATISTICS = "statistics" - const val CHARACTERS = "characters" const val TOP_CHARACTER = "top/characters" const val LAST_EPISODES = "list/latest-episodes" } @@ -22,22 +18,19 @@ object Routes { const val TOP = "/top" const val ANIME = "/anime" const val MANGA = "/manga" - const val PAGE = "/{page}" const val PEOPLE = "/people" const val SCHEDULE = "/schedule" const val DIRECTORY = "/directory" const val CHARACTER = "/characters" const val LAST_EPISODES = "/lastEpisodes" const val ID = "/{id}" - const val ANIME_TYPE = "/{type}" + const val TYPE = "/{type}" + const val SEASON = "/{year}/{season}" const val DAY = "/{day}" - const val TOP_CHARACTER = "/top/character" - const val RANKINGS = "/{type}/{filter}/{page}" } object TimerKey { const val KEY = "key" - const val RANKING = "ranking" const val SCHEDULE = "schedule" const val LAST_UPDATED = "lastUpdated" const val ANIME_TYPE = "anime_" @@ -47,12 +40,10 @@ object TimerKey { object Collections { const val TIMERS = "timers" const val SCHEDULES = "schedule" - const val ANIME_TYPE = "anime_" const val ANIME_DETAILS = "anime_details" const val LAST_EPISODES = "last_episodes" const val ANIME_RANKING = "anime_ranking" const val MANGA_RANKING = "manga_ranking" const val PEOPLE_RANKING = "people_ranking" - const val ANIME_DIRECTORY = "anime_directory" const val CHARACTER_RANKING = "character_ranking" } \ No newline at end of file diff --git a/src/main/kotlin/com/jeluchu/features/anime/mappers/AnimeMappers.kt b/src/main/kotlin/com/jeluchu/features/anime/mappers/AnimeMappers.kt index 61dfd99..d0046ba 100644 --- a/src/main/kotlin/com/jeluchu/features/anime/mappers/AnimeMappers.kt +++ b/src/main/kotlin/com/jeluchu/features/anime/mappers/AnimeMappers.kt @@ -287,6 +287,8 @@ fun documentToCharacterTopEntity(doc: Document) = CharacterTopEntity( fun documentToAnimeTypeEntity(doc: Document) = AnimeTypeEntity( score = doc.getString("score"), malId = doc.getIntSafe("malId"), + year = doc.getIntSafe("year"), + season = doc.getStringSafe("season"), type = doc.getStringSafe("type"), title = doc.getStringSafe("title"), image = doc.getStringSafe("poster"), diff --git a/src/main/kotlin/com/jeluchu/features/anime/models/directory/AnimeTypeEntity.kt b/src/main/kotlin/com/jeluchu/features/anime/models/directory/AnimeTypeEntity.kt index dbb15c2..19ede49 100644 --- a/src/main/kotlin/com/jeluchu/features/anime/models/directory/AnimeTypeEntity.kt +++ b/src/main/kotlin/com/jeluchu/features/anime/models/directory/AnimeTypeEntity.kt @@ -7,6 +7,8 @@ data class AnimeTypeEntity( val malId: Int? = 0, val type: String? = "", val episodes: Int? = 0, + val year: Int? = 0, + val season: String? = "", val title: String? = "", val image: String? = "", val score: String? = "" 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 d2af6fb..a2793e1 100644 --- a/src/main/kotlin/com/jeluchu/features/anime/routes/AnimeRoutes.kt +++ b/src/main/kotlin/com/jeluchu/features/anime/routes/AnimeRoutes.kt @@ -19,6 +19,7 @@ fun Route.animeEndpoints( route(Routes.DIRECTORY) { getToJson { service.getDirectory(call) } - getToJson(Routes.ANIME_TYPE) { directoryService.getAnimeByType(call) } + getToJson(Routes.TYPE) { directoryService.getAnimeByType(call) } + getToJson(Routes.SEASON) { directoryService.getAnimeBySeason(call) } } } \ No newline at end of file diff --git a/src/main/kotlin/com/jeluchu/features/anime/services/AnimeService.kt b/src/main/kotlin/com/jeluchu/features/anime/services/AnimeService.kt index 38101af..80672f7 100644 --- a/src/main/kotlin/com/jeluchu/features/anime/services/AnimeService.kt +++ b/src/main/kotlin/com/jeluchu/features/anime/services/AnimeService.kt @@ -50,7 +50,7 @@ class AnimeService( .limit(size) .toList() - val elements = animes.map { documentToAnimeDirectoryEntity(it) } + val elements = animes.map { documentToAnimeTypeEntity(it) } val response = PaginationResponse( page = page, @@ -123,10 +123,4 @@ class AnimeService( val directory = map { documentToLastEpisodesEntity(it) } return Json.encodeToString(directory) } - - private fun List.documentAnimeTypeMapper(): String { - val directory = map { documentToAnimeTypeEntity(it) } - return Json.encodeToString(directory) - } -} - +} \ No newline at end of file diff --git a/src/main/kotlin/com/jeluchu/features/anime/services/DirectoryService.kt b/src/main/kotlin/com/jeluchu/features/anime/services/DirectoryService.kt index 72f50cf..e5bc006 100644 --- a/src/main/kotlin/com/jeluchu/features/anime/services/DirectoryService.kt +++ b/src/main/kotlin/com/jeluchu/features/anime/services/DirectoryService.kt @@ -38,7 +38,9 @@ class DirectoryService( ErrorResponse(ErrorMessages.InvalidAnimeType.message) ) - val timerKey = "${TimerKey.ANIME_TYPE}${param.lowercase()}" + val timerKey = "${TimerKey.ANIME_TYPE}${param.lowercase()}_$page" + val collection = database.getCollection(timerKey) + val needsUpdate = timers.needsUpdate( amount = 30, key = timerKey, @@ -46,7 +48,6 @@ class DirectoryService( ) if (needsUpdate) { - val collection = database.getCollection(timerKey) collection.deleteMany(Document()) val animes = directory @@ -62,31 +63,88 @@ class DirectoryService( val response = PaginationResponse( page = page, - size = size, data = animeTypes, - totalItems = directory.countDocuments().toInt() + size = animeTypes.size ) call.respond(HttpStatusCode.OK, Json.encodeToString(response)) } else { - val elements = directory.find() + val elements = collection + .find() .skip(skipCount) .limit(size) .toList() + val responseItems = elements.map { documentToAnimeTypeEntity(it) } val response = PaginationResponse( page = page, - size = size, - totalItems = directory.countDocuments().toInt(), - data = elements.map { documentToAnimeTypeEntity(it) } + data = responseItems, + size = responseItems.size ) call.respond(HttpStatusCode.OK, Json.encodeToString(response)) } } - private fun List.documentAnimeTypeMapper(): String { - val directory = map { documentToAnimeTypeEntity(it) } - return Json.encodeToString(directory) + suspend fun getAnimeBySeason(call: RoutingCall) { + val page = call.request.queryParameters["page"]?.toIntOrNull() ?: 1 + val size = call.request.queryParameters["size"]?.toIntOrNull() ?: 10 + val year = call.parameters["year"]?.toIntOrNull() ?: throw IllegalArgumentException(ErrorMessages.NotFound.message) + val season = call.parameters["season"] ?: throw IllegalArgumentException(ErrorMessages.NotFound.message) + + if (page < 1 || size < 1) call.respond(HttpStatusCode.BadRequest, ErrorMessages.InvalidSizeAndPage.message) + val skipCount = (page - 1) * size + + val timerKey = "${TimerKey.ANIME_TYPE}${year}_${season}_$page" + val collection = database.getCollection(timerKey) + + val needsUpdate = timers.needsUpdate( + amount = 30, + key = timerKey, + unit = TimeUnit.DAY, + ) + + if (needsUpdate) { + collection.deleteMany(Document()) + + val animes = directory + .find( + Filters.and( + Filters.eq("year", year), + Filters.eq("season", season) + ) + ) + .skip(skipCount) + .limit(size) + .toList() + + val animeTypes = animes.map { documentToAnimeTypeEntity(it) } + val documents = animeTypes.map { anime -> Document.parse(Json.encodeToString(anime)) } + if (documents.isNotEmpty()) collection.insertMany(documents) + timers.update(timerKey) + + val response = PaginationResponse( + page = page, + data = animeTypes, + size = animeTypes.size + ) + + call.respond(HttpStatusCode.OK, Json.encodeToString(response)) + } else { + val elements = collection + .find() + .skip(skipCount) + .limit(size) + .toList() + + val responseItems = elements.map { documentToAnimeTypeEntity(it) } + val response = PaginationResponse( + page = page, + data = responseItems, + size = responseItems.size + ) + + call.respond(HttpStatusCode.OK, Json.encodeToString(response)) + } } } \ No newline at end of file