Improve pagination and include seasonal endpoint for directory

v5 v5.3.1
Jéluchu 7 months ago
parent df6baa761b
commit 78f0af195a

@ -6,14 +6,10 @@ object BaseUrls {
} }
object Endpoints { object Endpoints {
const val FULL = "full"
const val ANIME = "anime/"
const val SCHEDULES = "schedules" const val SCHEDULES = "schedules"
const val TOP_ANIME = "top/anime" const val TOP_ANIME = "top/anime"
const val TOP_MANGA = "top/manga" const val TOP_MANGA = "top/manga"
const val TOP_PEOPLE = "top/people" const val TOP_PEOPLE = "top/people"
const val STATISTICS = "statistics"
const val CHARACTERS = "characters"
const val TOP_CHARACTER = "top/characters" const val TOP_CHARACTER = "top/characters"
const val LAST_EPISODES = "list/latest-episodes" const val LAST_EPISODES = "list/latest-episodes"
} }
@ -22,22 +18,19 @@ object Routes {
const val TOP = "/top" const val TOP = "/top"
const val ANIME = "/anime" const val ANIME = "/anime"
const val MANGA = "/manga" const val MANGA = "/manga"
const val PAGE = "/{page}"
const val PEOPLE = "/people" const val PEOPLE = "/people"
const val SCHEDULE = "/schedule" const val SCHEDULE = "/schedule"
const val DIRECTORY = "/directory" const val DIRECTORY = "/directory"
const val CHARACTER = "/characters" const val CHARACTER = "/characters"
const val LAST_EPISODES = "/lastEpisodes" const val LAST_EPISODES = "/lastEpisodes"
const val ID = "/{id}" const val ID = "/{id}"
const val ANIME_TYPE = "/{type}" const val TYPE = "/{type}"
const val SEASON = "/{year}/{season}"
const val DAY = "/{day}" const val DAY = "/{day}"
const val TOP_CHARACTER = "/top/character"
const val RANKINGS = "/{type}/{filter}/{page}"
} }
object TimerKey { object TimerKey {
const val KEY = "key" const val KEY = "key"
const val RANKING = "ranking"
const val SCHEDULE = "schedule" const val SCHEDULE = "schedule"
const val LAST_UPDATED = "lastUpdated" const val LAST_UPDATED = "lastUpdated"
const val ANIME_TYPE = "anime_" const val ANIME_TYPE = "anime_"
@ -47,12 +40,10 @@ object TimerKey {
object Collections { object Collections {
const val TIMERS = "timers" const val TIMERS = "timers"
const val SCHEDULES = "schedule" const val SCHEDULES = "schedule"
const val ANIME_TYPE = "anime_"
const val ANIME_DETAILS = "anime_details" const val ANIME_DETAILS = "anime_details"
const val LAST_EPISODES = "last_episodes" const val LAST_EPISODES = "last_episodes"
const val ANIME_RANKING = "anime_ranking" const val ANIME_RANKING = "anime_ranking"
const val MANGA_RANKING = "manga_ranking" const val MANGA_RANKING = "manga_ranking"
const val PEOPLE_RANKING = "people_ranking" const val PEOPLE_RANKING = "people_ranking"
const val ANIME_DIRECTORY = "anime_directory"
const val CHARACTER_RANKING = "character_ranking" const val CHARACTER_RANKING = "character_ranking"
} }

@ -287,6 +287,8 @@ fun documentToCharacterTopEntity(doc: Document) = CharacterTopEntity(
fun documentToAnimeTypeEntity(doc: Document) = AnimeTypeEntity( fun documentToAnimeTypeEntity(doc: Document) = AnimeTypeEntity(
score = doc.getString("score"), score = doc.getString("score"),
malId = doc.getIntSafe("malId"), malId = doc.getIntSafe("malId"),
year = doc.getIntSafe("year"),
season = doc.getStringSafe("season"),
type = doc.getStringSafe("type"), type = doc.getStringSafe("type"),
title = doc.getStringSafe("title"), title = doc.getStringSafe("title"),
image = doc.getStringSafe("poster"), image = doc.getStringSafe("poster"),

@ -7,6 +7,8 @@ data class AnimeTypeEntity(
val malId: Int? = 0, val malId: Int? = 0,
val type: String? = "", val type: String? = "",
val episodes: Int? = 0, val episodes: Int? = 0,
val year: Int? = 0,
val season: String? = "",
val title: String? = "", val title: String? = "",
val image: String? = "", val image: String? = "",
val score: String? = "" val score: String? = ""

@ -19,6 +19,7 @@ fun Route.animeEndpoints(
route(Routes.DIRECTORY) { route(Routes.DIRECTORY) {
getToJson { service.getDirectory(call) } getToJson { service.getDirectory(call) }
getToJson(Routes.ANIME_TYPE) { directoryService.getAnimeByType(call) } getToJson(Routes.TYPE) { directoryService.getAnimeByType(call) }
getToJson(Routes.SEASON) { directoryService.getAnimeBySeason(call) }
} }
} }

@ -50,7 +50,7 @@ class AnimeService(
.limit(size) .limit(size)
.toList() .toList()
val elements = animes.map { documentToAnimeDirectoryEntity(it) } val elements = animes.map { documentToAnimeTypeEntity(it) }
val response = PaginationResponse( val response = PaginationResponse(
page = page, page = page,
@ -123,10 +123,4 @@ class AnimeService(
val directory = map { documentToLastEpisodesEntity(it) } val directory = map { documentToLastEpisodesEntity(it) }
return Json.encodeToString(directory) return Json.encodeToString(directory)
} }
private fun List<Document>.documentAnimeTypeMapper(): String {
val directory = map { documentToAnimeTypeEntity(it) }
return Json.encodeToString(directory)
} }
}

@ -38,7 +38,9 @@ class DirectoryService(
ErrorResponse(ErrorMessages.InvalidAnimeType.message) 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( val needsUpdate = timers.needsUpdate(
amount = 30, amount = 30,
key = timerKey, key = timerKey,
@ -46,7 +48,6 @@ class DirectoryService(
) )
if (needsUpdate) { if (needsUpdate) {
val collection = database.getCollection(timerKey)
collection.deleteMany(Document()) collection.deleteMany(Document())
val animes = directory val animes = directory
@ -62,31 +63,88 @@ class DirectoryService(
val response = PaginationResponse( val response = PaginationResponse(
page = page, page = page,
size = size,
data = animeTypes, data = animeTypes,
totalItems = directory.countDocuments().toInt() size = animeTypes.size
) )
call.respond(HttpStatusCode.OK, Json.encodeToString(response)) call.respond(HttpStatusCode.OK, Json.encodeToString(response))
} else { } else {
val elements = directory.find() val elements = collection
.find()
.skip(skipCount) .skip(skipCount)
.limit(size) .limit(size)
.toList() .toList()
val responseItems = elements.map { documentToAnimeTypeEntity(it) }
val response = PaginationResponse( val response = PaginationResponse(
page = page, page = page,
size = size, data = responseItems,
totalItems = directory.countDocuments().toInt(), size = responseItems.size
data = elements.map { documentToAnimeTypeEntity(it) }
) )
call.respond(HttpStatusCode.OK, Json.encodeToString(response)) call.respond(HttpStatusCode.OK, Json.encodeToString(response))
} }
} }
private fun List<Document>.documentAnimeTypeMapper(): String { suspend fun getAnimeBySeason(call: RoutingCall) {
val directory = map { documentToAnimeTypeEntity(it) } val page = call.request.queryParameters["page"]?.toIntOrNull() ?: 1
return Json.encodeToString(directory) 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))
}
} }
} }
Loading…
Cancel
Save