Improve pagination and include seasonal endpoint for directory

This commit is contained in:
Jéluchu 2025-01-13 20:04:31 +01:00
parent df6baa761b
commit 78f0af195a
7 changed files with 79 additions and 31 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -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<Document>.documentAnimeTypeMapper(): String {
val directory = map { documentToAnimeTypeEntity(it) }
return Json.encodeToString(directory)
}
}
}

View File

@ -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<Document>.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))
}
}
}