Use Jikan to show last episodes with time and malId

v5 v5.3.3
Jéluchu 7 months ago
parent 1433bca666
commit 3760530255

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

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

@ -1,9 +0,0 @@
package com.jeluchu.core.models.animeflv.lastepisodes
import kotlinx.serialization.Serializable
@Serializable
data class LastEpisodes(
val data: List<LastEpisodeData>?,
val success: Boolean?
)

@ -1,9 +1,8 @@
package com.jeluchu.features.anime.mappers package com.jeluchu.features.anime.mappers
import com.jeluchu.core.extensions.* 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.anime.*
import com.jeluchu.features.anime.models.directory.AnimeDirectoryEntity
import com.jeluchu.features.anime.models.directory.AnimeTypeEntity import com.jeluchu.features.anime.models.directory.AnimeTypeEntity
import com.jeluchu.features.rankings.models.AnimeTopEntity import com.jeluchu.features.rankings.models.AnimeTopEntity
import com.jeluchu.features.rankings.models.CharacterTopEntity import com.jeluchu.features.rankings.models.CharacterTopEntity
@ -233,6 +232,16 @@ fun documentToAnimeTopEntity(doc: Document) = AnimeTopEntity(
page = doc.getIntSafe("page"), 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( fun documentToMangaTopEntity(doc: Document) = MangaTopEntity(
malId = doc.getIntSafe("malId"), malId = doc.getIntSafe("malId"),
rank = doc.getIntSafe("rank"), rank = doc.getIntSafe("rank"),
@ -288,10 +297,4 @@ fun documentToAnimeDirectoryEntity(doc: Document) = AnimeTypeEntity(
title = doc.getStringSafe("title"), title = doc.getStringSafe("title"),
image = doc.getStringSafe("image"), image = doc.getStringSafe("image"),
episodes = doc.getListSafe<Document>("episodes").size episodes = doc.getListSafe<Document>("episodes").size
)
fun documentToLastEpisodesEntity(doc: Document) = EpisodeEntity(
number = doc.getIntSafe("number"),
title = doc.getStringSafe("title"),
image = doc.getStringSafe("image")
) )

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

@ -1,8 +1,6 @@
package com.jeluchu.features.anime.services package com.jeluchu.features.anime.services
import com.jeluchu.core.connection.RestClient 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.TimeUnit
import com.jeluchu.core.enums.parseAnimeType import com.jeluchu.core.enums.parseAnimeType
import com.jeluchu.core.extensions.needsUpdate 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.messages.ErrorMessages
import com.jeluchu.core.models.ErrorResponse import com.jeluchu.core.models.ErrorResponse
import com.jeluchu.core.models.PaginationResponse import com.jeluchu.core.models.PaginationResponse
import com.jeluchu.core.models.animeflv.lastepisodes.LastEpisodeData.Companion.toEpisodeEntity import com.jeluchu.features.anime.models.lastepisodes.LastEpisodeData
import com.jeluchu.core.models.animeflv.lastepisodes.LastEpisodes import com.jeluchu.features.anime.models.lastepisodes.LastEpisodeData.Companion.toLastEpisodeData
import com.jeluchu.core.models.jikan.anime.AnimeData.Companion.toDayEntity import com.jeluchu.core.models.jikan.search.AnimeSearch
import com.jeluchu.core.utils.BaseUrls import com.jeluchu.core.utils.BaseUrls
import com.jeluchu.core.utils.Collections import com.jeluchu.core.utils.Collections
import com.jeluchu.core.utils.Endpoints
import com.jeluchu.core.utils.TimerKey import com.jeluchu.core.utils.TimerKey
import com.jeluchu.features.anime.mappers.* import com.jeluchu.core.utils.parseDataToDocuments
import com.jeluchu.features.schedule.models.ScheduleEntity 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.MongoDatabase
import com.mongodb.client.model.Filters import com.mongodb.client.model.Filters.eq
import io.ktor.http.* import io.ktor.http.*
import io.ktor.server.response.* import io.ktor.server.response.*
import io.ktor.server.routing.* import io.ktor.server.routing.*
import kotlinx.coroutines.delay
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import org.bson.Document import org.bson.Document
import java.time.LocalDate
import java.time.format.TextStyle
import java.util.*
class AnimeService( class AnimeService(
database: MongoDatabase private val database: MongoDatabase
) { ) {
private val timers = database.getCollection(Collections.TIMERS) private val timers = database.getCollection(Collections.TIMERS)
private val directoryCollection = database.getCollection(Collections.ANIME_DETAILS) private val directoryCollection = database.getCollection(Collections.ANIME_DETAILS)
@ -61,7 +64,7 @@ class AnimeService(
call.respond(HttpStatusCode.OK, Json.encodeToString(response)) call.respond(HttpStatusCode.OK, Json.encodeToString(response))
} else { } else {
val animes = directoryCollection val animes = directoryCollection
.find(Filters.eq("type", type.uppercase())) .find(eq("type", type.uppercase()))
.skip(skipCount) .skip(skipCount)
.limit(size) .limit(size)
.toList() .toList()
@ -82,7 +85,7 @@ class AnimeService(
suspend fun getAnimeByMalId(call: RoutingCall) = try { suspend fun getAnimeByMalId(call: RoutingCall) = try {
val id = call.parameters["id"]?.toInt() ?: throw IllegalArgumentException(ErrorMessages.InvalidMalId.message) 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) val info = documentToMoreInfoEntity(anime)
call.respond(HttpStatusCode.OK, Json.encodeToString(info)) call.respond(HttpStatusCode.OK, Json.encodeToString(info))
} ?: call.respond(HttpStatusCode.NotFound, ErrorResponse(ErrorMessages.AnimeNotFound.message)) } ?: call.respond(HttpStatusCode.NotFound, ErrorResponse(ErrorMessages.AnimeNotFound.message))
@ -91,36 +94,61 @@ class AnimeService(
} }
suspend fun getLastEpisodes(call: RoutingCall) = try { 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( val needsUpdate = timers.needsUpdate(
amount = 3, amount = 6,
key = timerKey,
unit = TimeUnit.HOUR, unit = TimeUnit.HOUR,
key = TimerKey.LAST_EPISODES
) )
if (needsUpdate) { if (needsUpdate) {
lastEpisodesCollection.deleteMany(Document()) collection.deleteMany(Document())
val response = RestClient.request(
BaseUrls.JIKAN + "anime?status=airing&type=tv",
AnimeSearch.serializer()
)
val animes = mutableListOf<LastEpisodeData>()
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 documentsToInsert = parseDataToDocuments(animes, LastEpisodeData.serializer())
val documents = episodes.map { anime -> Document.parse(Json.encodeToString(anime)) } if (documentsToInsert.isNotEmpty()) collection.insertMany(documentsToInsert)
if (documents.isNotEmpty()) lastEpisodesCollection.insertMany(documents) timers.update(timerKey)
timers.update(TimerKey.LAST_EPISODES)
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 { } else {
val elements = lastEpisodesCollection.find().toList() val elements = collection
call.respond(HttpStatusCode.OK, elements.documentToLastEpisodesEntity()) .find(eq("day", dayOfWeek))
.toList()
.map { documentToAnimeLastEpisodeEntity(it) }
call.respond(HttpStatusCode.OK, Json.encodeToString(elements))
} }
} catch (ex: Exception) { } catch (ex: Exception) {
call.respond(HttpStatusCode.Unauthorized, ErrorResponse(ErrorMessages.UnauthorizedMongo.message)) 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<Document>.documentToLastEpisodesEntity(): String {
val directory = map { documentToLastEpisodesEntity(it) }
return Json.encodeToString(directory)
}
} }
Loading…
Cancel
Save