mirror of https://github.com/aruppi/aruppi-api
Improve pagination and include seasonal endpoint for directory
This commit is contained in:
parent
df6baa761b
commit
78f0af195a
|
@ -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"
|
||||
}
|
|
@ -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"),
|
||||
|
|
|
@ -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? = ""
|
||||
|
|
|
@ -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) }
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue