diff --git a/src/main/kotlin/com/jeluchu/core/models/animeflv/lastepisodes/EpisodeEntity.kt b/src/main/kotlin/com/jeluchu/core/models/animeflv/lastepisodes/EpisodeEntity.kt deleted file mode 100644 index 87aa89b..0000000 --- a/src/main/kotlin/com/jeluchu/core/models/animeflv/lastepisodes/EpisodeEntity.kt +++ /dev/null @@ -1,10 +0,0 @@ -package com.jeluchu.core.models.animeflv.lastepisodes - -import kotlinx.serialization.Serializable - -@Serializable -data class EpisodeEntity( - var number: Int, - var image: String, - var title: String -) diff --git a/src/main/kotlin/com/jeluchu/core/models/animeflv/lastepisodes/LastEpisodeData.kt b/src/main/kotlin/com/jeluchu/core/models/animeflv/lastepisodes/LastEpisodeData.kt deleted file mode 100644 index b05086b..0000000 --- a/src/main/kotlin/com/jeluchu/core/models/animeflv/lastepisodes/LastEpisodeData.kt +++ /dev/null @@ -1,19 +0,0 @@ -package com.jeluchu.core.models.animeflv.lastepisodes - -import kotlinx.serialization.Serializable - -@Serializable -data class LastEpisodeData( - val cover: String?, - val number: Int?, - val title: String?, - val url: String? -) { - companion object { - fun LastEpisodeData.toEpisodeEntity() = EpisodeEntity( - number = number ?: 0, - image = cover.orEmpty(), - title = title.orEmpty() - ) - } -} \ No newline at end of file diff --git a/src/main/kotlin/com/jeluchu/core/models/animeflv/lastepisodes/LastEpisodes.kt b/src/main/kotlin/com/jeluchu/core/models/animeflv/lastepisodes/LastEpisodes.kt deleted file mode 100644 index 6f24861..0000000 --- a/src/main/kotlin/com/jeluchu/core/models/animeflv/lastepisodes/LastEpisodes.kt +++ /dev/null @@ -1,9 +0,0 @@ -package com.jeluchu.core.models.animeflv.lastepisodes - -import kotlinx.serialization.Serializable - -@Serializable -data class LastEpisodes( - val data: List?, - val success: Boolean? -) \ 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 7cacb7b..8d95353 100644 --- a/src/main/kotlin/com/jeluchu/features/anime/mappers/AnimeMappers.kt +++ b/src/main/kotlin/com/jeluchu/features/anime/mappers/AnimeMappers.kt @@ -1,9 +1,8 @@ package com.jeluchu.features.anime.mappers import com.jeluchu.core.extensions.* -import com.jeluchu.core.models.animeflv.lastepisodes.EpisodeEntity +import com.jeluchu.features.anime.models.lastepisodes.LastEpisodeData import com.jeluchu.features.anime.models.anime.* -import com.jeluchu.features.anime.models.directory.AnimeDirectoryEntity import com.jeluchu.features.anime.models.directory.AnimeTypeEntity import com.jeluchu.features.rankings.models.AnimeTopEntity import com.jeluchu.features.rankings.models.CharacterTopEntity @@ -233,6 +232,16 @@ fun documentToAnimeTopEntity(doc: Document) = AnimeTopEntity( page = doc.getIntSafe("page"), ) +fun documentToAnimeLastEpisodeEntity(doc: Document) = LastEpisodeData( + malId = doc.getIntSafe("malId"), + title = doc.getStringSafe("title"), + image = doc.getStringSafe("image"), + day = doc.getStringSafe("day"), + time = doc.getStringSafe("time"), + score = doc.getStringSafe("score"), + timezone = doc.getStringSafe("timezone") +) + fun documentToMangaTopEntity(doc: Document) = MangaTopEntity( malId = doc.getIntSafe("malId"), rank = doc.getIntSafe("rank"), @@ -288,10 +297,4 @@ fun documentToAnimeDirectoryEntity(doc: Document) = AnimeTypeEntity( title = doc.getStringSafe("title"), image = doc.getStringSafe("image"), episodes = doc.getListSafe("episodes").size -) - -fun documentToLastEpisodesEntity(doc: Document) = EpisodeEntity( - number = doc.getIntSafe("number"), - title = doc.getStringSafe("title"), - image = doc.getStringSafe("image") ) \ No newline at end of file diff --git a/src/main/kotlin/com/jeluchu/features/anime/models/lastepisodes/LastEpisodeData.kt b/src/main/kotlin/com/jeluchu/features/anime/models/lastepisodes/LastEpisodeData.kt new file mode 100644 index 0000000..f4b25fa --- /dev/null +++ b/src/main/kotlin/com/jeluchu/features/anime/models/lastepisodes/LastEpisodeData.kt @@ -0,0 +1,27 @@ +package com.jeluchu.features.anime.models.lastepisodes + +import com.jeluchu.core.models.jikan.anime.AnimeData +import kotlinx.serialization.Serializable + +@Serializable +data class LastEpisodeData( + val malId: Int = 0, + val title: String?, + val score: String?, + val image: String?, + val day: String?, + val time: String?, + val timezone: String?, +) { + companion object { + fun AnimeData.toLastEpisodeData() = LastEpisodeData( + malId = malId ?: 0, + day = broadcast?.day.orEmpty(), + time = broadcast?.time.orEmpty(), + score = score?.toString().orEmpty(), + image = images?.webp?.large.orEmpty(), + timezone = broadcast?.timezone.orEmpty(), + title = titles?.first()?.title.orEmpty() + ) + } +} \ 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 80672f7..971d2ba 100644 --- a/src/main/kotlin/com/jeluchu/features/anime/services/AnimeService.kt +++ b/src/main/kotlin/com/jeluchu/features/anime/services/AnimeService.kt @@ -1,8 +1,6 @@ package com.jeluchu.features.anime.services import com.jeluchu.core.connection.RestClient -import com.jeluchu.core.enums.AnimeTypes -import com.jeluchu.core.enums.Day import com.jeluchu.core.enums.TimeUnit import com.jeluchu.core.enums.parseAnimeType import com.jeluchu.core.extensions.needsUpdate @@ -10,26 +8,31 @@ import com.jeluchu.core.extensions.update import com.jeluchu.core.messages.ErrorMessages import com.jeluchu.core.models.ErrorResponse import com.jeluchu.core.models.PaginationResponse -import com.jeluchu.core.models.animeflv.lastepisodes.LastEpisodeData.Companion.toEpisodeEntity -import com.jeluchu.core.models.animeflv.lastepisodes.LastEpisodes -import com.jeluchu.core.models.jikan.anime.AnimeData.Companion.toDayEntity +import com.jeluchu.features.anime.models.lastepisodes.LastEpisodeData +import com.jeluchu.features.anime.models.lastepisodes.LastEpisodeData.Companion.toLastEpisodeData +import com.jeluchu.core.models.jikan.search.AnimeSearch import com.jeluchu.core.utils.BaseUrls import com.jeluchu.core.utils.Collections -import com.jeluchu.core.utils.Endpoints import com.jeluchu.core.utils.TimerKey -import com.jeluchu.features.anime.mappers.* -import com.jeluchu.features.schedule.models.ScheduleEntity +import com.jeluchu.core.utils.parseDataToDocuments +import com.jeluchu.features.anime.mappers.documentToAnimeLastEpisodeEntity +import com.jeluchu.features.anime.mappers.documentToAnimeTypeEntity +import com.jeluchu.features.anime.mappers.documentToMoreInfoEntity import com.mongodb.client.MongoDatabase -import com.mongodb.client.model.Filters +import com.mongodb.client.model.Filters.eq import io.ktor.http.* import io.ktor.server.response.* import io.ktor.server.routing.* +import kotlinx.coroutines.delay import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json import org.bson.Document +import java.time.LocalDate +import java.time.format.TextStyle +import java.util.* class AnimeService( - database: MongoDatabase + private val database: MongoDatabase ) { private val timers = database.getCollection(Collections.TIMERS) private val directoryCollection = database.getCollection(Collections.ANIME_DETAILS) @@ -61,7 +64,7 @@ class AnimeService( call.respond(HttpStatusCode.OK, Json.encodeToString(response)) } else { val animes = directoryCollection - .find(Filters.eq("type", type.uppercase())) + .find(eq("type", type.uppercase())) .skip(skipCount) .limit(size) .toList() @@ -82,7 +85,7 @@ class AnimeService( suspend fun getAnimeByMalId(call: RoutingCall) = try { val id = call.parameters["id"]?.toInt() ?: throw IllegalArgumentException(ErrorMessages.InvalidMalId.message) - directoryCollection.find(Filters.eq("malId", id)).firstOrNull()?.let { anime -> + directoryCollection.find(eq("malId", id)).firstOrNull()?.let { anime -> val info = documentToMoreInfoEntity(anime) call.respond(HttpStatusCode.OK, Json.encodeToString(info)) } ?: call.respond(HttpStatusCode.NotFound, ErrorResponse(ErrorMessages.AnimeNotFound.message)) @@ -91,36 +94,61 @@ class AnimeService( } suspend fun getLastEpisodes(call: RoutingCall) = try { + val dayOfWeek = LocalDate.now() + .dayOfWeek + .getDisplayName(TextStyle.FULL, Locale.ENGLISH) + .plus("s") + + val timerKey = TimerKey.LAST_EPISODES + val collection = database.getCollection(timerKey) + val needsUpdate = timers.needsUpdate( - amount = 3, + amount = 6, + key = timerKey, unit = TimeUnit.HOUR, - key = TimerKey.LAST_EPISODES ) if (needsUpdate) { - lastEpisodesCollection.deleteMany(Document()) + collection.deleteMany(Document()) + + val response = RestClient.request( + BaseUrls.JIKAN + "anime?status=airing&type=tv", + AnimeSearch.serializer() + ) + + val animes = mutableListOf() + val totalPage = response.pagination?.lastPage ?: 0 + response.data?.map { it.toLastEpisodeData() }.orEmpty().let { animes.addAll(it) } + + for (page in 2..totalPage) { + val responsePage = RestClient.request( + BaseUrls.JIKAN + "anime?status=airing&type=tv&page=$page", + AnimeSearch.serializer() + ).data?.map { it.toLastEpisodeData() }.orEmpty() + + animes.addAll(responsePage) + delay(1000) + } - val episodes = getLastedEpisodes().data?.map { it.toEpisodeEntity() }.orEmpty() - val documents = episodes.map { anime -> Document.parse(Json.encodeToString(anime)) } - if (documents.isNotEmpty()) lastEpisodesCollection.insertMany(documents) - timers.update(TimerKey.LAST_EPISODES) + val documentsToInsert = parseDataToDocuments(animes, LastEpisodeData.serializer()) + if (documentsToInsert.isNotEmpty()) collection.insertMany(documentsToInsert) + timers.update(timerKey) - call.respond(HttpStatusCode.OK, Json.encodeToString(episodes)) + val queryDb = collection + .find(eq("day", dayOfWeek)) + .toList() + + val elements = queryDb.map { documentToAnimeLastEpisodeEntity(it) } + call.respond(HttpStatusCode.OK, Json.encodeToString(elements)) } else { - val elements = lastEpisodesCollection.find().toList() - call.respond(HttpStatusCode.OK, elements.documentToLastEpisodesEntity()) + val elements = collection + .find(eq("day", dayOfWeek)) + .toList() + .map { documentToAnimeLastEpisodeEntity(it) } + + call.respond(HttpStatusCode.OK, Json.encodeToString(elements)) } } catch (ex: Exception) { call.respond(HttpStatusCode.Unauthorized, ErrorResponse(ErrorMessages.UnauthorizedMongo.message)) } - - private suspend fun getLastedEpisodes() = RestClient.requestWithDelay( - url = BaseUrls.ANIME_FLV + Endpoints.LAST_EPISODES, - deserializer = LastEpisodes.serializer() - ) - - private fun List.documentToLastEpisodesEntity(): String { - val directory = map { documentToLastEpisodesEntity(it) } - return Json.encodeToString(directory) - } } \ No newline at end of file