Skip to content

Commit

Permalink
fix disney plus and optimize some requests
Browse files Browse the repository at this point in the history
  • Loading branch information
Ziedelth committed Dec 11, 2024
1 parent c022d48 commit 8bc5b6b
Show file tree
Hide file tree
Showing 16 changed files with 5,520 additions and 55 deletions.
4 changes: 1 addition & 3 deletions src/main/kotlin/fr/shikkanime/Application.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import fr.shikkanime.services.AnimeService
import fr.shikkanime.services.EpisodeMappingService
import fr.shikkanime.services.ImageService
import fr.shikkanime.services.MemberService
import fr.shikkanime.services.caches.AnimeCacheService
import fr.shikkanime.utils.Constant
import fr.shikkanime.utils.JobManager
import fr.shikkanime.utils.LoggerFactory
Expand Down Expand Up @@ -72,7 +71,6 @@ fun main(args: Array<String>) {

private fun updateAndDeleteData() {
val animeService = Constant.injector.getInstance(AnimeService::class.java)
val animeCacheService = Constant.injector.getInstance(AnimeCacheService::class.java)
val episodeMappingService = Constant.injector.getInstance(EpisodeMappingService::class.java)
val seasonRegex = " Saison (\\d)| ([MDCLXVI]+$)".toRegex()

Expand Down Expand Up @@ -104,7 +102,7 @@ private fun updateAndDeleteData() {
anime.slug = slug
logger.info("Updating slug for anime ${anime.name} to $slug")

animeCacheService.findBySlug(anime.countryCode!!, slug)?.let { existing ->
animeService.findBySlug(anime.countryCode!!, slug)?.let { existing ->
logger.warning("Slug $slug already exists, merging ${anime.name} with ${existing.name}")
animeService.merge(anime, existing)
return@forEach
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ class AnimeController : HasPageableRoute() {
private fun animeDetails(
@PathParam("uuid") uuid: UUID,
): Response {
return Response.ok(AbstractConverter.convert(animeCacheService.find(uuid) ?: return Response.notFound(), AnimeDto::class.java))
return Response.ok(AbstractConverter.convert(animeService.find(uuid) ?: return Response.notFound(), AnimeDto::class.java))
}

@Path("/{uuid}")
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package fr.shikkanime.controllers.site

import com.google.inject.Inject
import fr.shikkanime.converters.AbstractConverter
import fr.shikkanime.dtos.animes.AnimeDto
import fr.shikkanime.entities.SortParameter
import fr.shikkanime.entities.enums.*
Expand Down Expand Up @@ -123,7 +122,7 @@ class SiteController {
}

private fun getAnimeDetail(slug: String, season: Int? = null, page: Int? = null): Response {
val dto = AbstractConverter.convert(animeCacheService.findBySlug(CountryCode.FR, slug) ?: return Response.notFound(), AnimeDto::class.java)
val dto = animeCacheService.findBySlug(CountryCode.FR, slug) ?: return Response.notFound()
val seasonDto = dto.seasons?.firstOrNull { it.number == (season ?: it.number) } ?: return Response.notFound()
val limit = configCacheService.getValueAsInt(ConfigPropertyKey.ANIME_EPISODES_SIZE_LIMIT, 24)
val findAllBy = episodeMappingCacheService.findAllBy(
Expand Down Expand Up @@ -186,8 +185,7 @@ class SiteController {
@PathParam("season") season: Int,
@PathParam("episodeSlug") episodeSlug: String
): Response {
val dto = AbstractConverter.convert(animeCacheService.findBySlug(CountryCode.FR, slug) ?: return Response.notFound(), AnimeDto::class.java)

val dto = animeCacheService.findBySlug(CountryCode.FR, slug) ?: return Response.notFound()
if (dto.seasons.isNullOrEmpty()) return Response.notFound()
if (dto.seasons!!.none { it.number == season }) return Response.redirect("/animes/$slug/season-${dto.seasons!!.last().number}/$episodeSlug")

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ class AnimeToAnimeDtoConverter : AbstractConverter<Anime, AnimeDto>() {
image = from.image!!,
banner = from.banner!!,
description = from.description,
simulcasts = convert(
simulcasts = if (Hibernate.isInitialized(from.simulcasts)) convert(
from.simulcasts.sortBySeasonAndYear(),
SimulcastDto::class.java
)!!,
)!! else null,
audioLocales = audioLocales.takeIf { it.isNotEmpty() },
langTypes = audioLocales.map { LangType.fromAudioLocale(from.countryCode, it) }.distinct().sorted().takeIf { it.isNotEmpty() }?.toSet(),
seasons = seasons.map { (season, lastReleaseDateTime) -> SeasonDto(season, lastReleaseDateTime.withUTCString()) }.takeIf { it.isNotEmpty() }?.toSet(),
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/fr/shikkanime/dtos/animes/AnimeDto.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ data class AnimeDto(
val image: String,
val banner: String,
val description: String?,
val simulcasts: Set<SimulcastDto>,
val simulcasts: Set<SimulcastDto>?,
var audioLocales: Set<String>? = null,
var langTypes: Set<LangType>? = null,
var seasons: Set<SeasonDto>? = null,
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/fr/shikkanime/entities/Anime.kt
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class Anime(
var banner: String? = null,
@Column(nullable = true, columnDefinition = "VARCHAR(2000)")
var description: String? = null,
@ManyToMany(fetch = FetchType.EAGER)
@ManyToMany(fetch = FetchType.LAZY)
@JoinTable(
name = "anime_simulcast",
joinColumns = [JoinColumn(name = "anime_uuid")],
Expand Down
29 changes: 19 additions & 10 deletions src/main/kotlin/fr/shikkanime/jobs/FetchEpisodesJob.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,24 @@ class FetchEpisodesJob : AbstractJob {
@Inject
private lateinit var configCacheService: ConfigCacheService

fun addHashCaches(
it: AbstractPlatform<*, *, *>,
variants: List<EpisodeVariant>
) {
if (it.getPlatform() == Platform.DISN) {
val episodeVariants = variants.filter { variant -> variant.platform == it.getPlatform() }

it.hashCache.addAll(episodeVariants.map { variant ->
".{2}-.{4}-(.*)-.{2}-.{2}".toRegex().find(variant.identifier!!)!!.groupValues[1]
})

it.hashCache.addAll(episodeVariants.map { variant ->
EncryptionManager.toSHA512("${variant.mapping!!.anime!!.name}-${variant.mapping!!.season}-${variant.mapping!!.number}")
.substring(0..<8)
})
}
}

override fun run() {
if (isRunning) {
if (++lock > maxLock) {
Expand All @@ -56,16 +74,7 @@ class FetchEpisodesJob : AbstractJob {
if (!isInitialized) {
identifiers.addAll(episodeVariantCacheService.findAllIdentifiers())
val variants = episodeVariantCacheService.findAll()

Constant.abstractPlatforms.forEach {
it.hashCache.addAll(
variants.filter { variant -> variant.platform == it.getPlatform() }
.map { variant ->
".{2}-.{4}-(.*)-.{2}-.{2}".toRegex().find(variant.identifier!!)!!.groupValues[1]
}
)
}

Constant.abstractPlatforms.forEach { addHashCaches(it, variants) }
variants.forEach { typeIdentifiers.add(getTypeIdentifier(it)) }
isInitialized = true
}
Expand Down
51 changes: 40 additions & 11 deletions src/main/kotlin/fr/shikkanime/platforms/DisneyPlusPlatform.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,10 @@ import fr.shikkanime.entities.enums.Platform
import fr.shikkanime.exceptions.AnimeException
import fr.shikkanime.platforms.configuration.DisneyPlusConfiguration
import fr.shikkanime.services.caches.ConfigCacheService
import fr.shikkanime.utils.MapCache
import fr.shikkanime.utils.*
import fr.shikkanime.utils.ObjectParser.getAsInt
import fr.shikkanime.utils.ObjectParser.getAsLong
import fr.shikkanime.utils.ObjectParser.getAsString
import fr.shikkanime.utils.isEqualOrAfter
import fr.shikkanime.utils.normalize
import fr.shikkanime.utils.withUTC
import fr.shikkanime.wrappers.DisneyPlusWrapper
import kotlinx.coroutines.runBlocking
import java.io.File
Expand Down Expand Up @@ -63,6 +60,29 @@ class DisneyPlusPlatform :
return animeDetails to episodes
}

private fun getFileApiContent(
bypassFileContent: File,
simulcast: DisneyPlusConfiguration.DisneyPlusSimulcast
): Pair<JsonObject, List<JsonObject>> {
val (animeDetails, seasons) = DisneyPlusWrapper.parseAnimeJson(bypassFileContent.readText())

val episodes = seasons.flatMap { season ->
val seasonEpisodes = mutableListOf<JsonObject>()

DisneyPlusWrapper.parseSeasonJson(
File(
ClassLoader.getSystemClassLoader()
.getResource("disney_plus/${simulcast.name}/episodes-$season.json")?.file
?: throw Exception("File not found")
).readText(), seasonEpisodes
)

seasonEpisodes
}

return animeDetails to episodes
}

override fun fetchEpisodes(zonedDateTime: ZonedDateTime, bypassFileContent: File?): List<Episode> {
val list = mutableListOf<Episode>()

Expand All @@ -71,12 +91,19 @@ class DisneyPlusPlatform :
it.releaseDay == zonedDateTime.dayOfWeek.value && zonedDateTime.toLocalTime()
.isEqualOrAfter(LocalTime.parse(it.releaseTime))
}.forEach { simulcast ->
val (animeDetails, episodes) = getApiContent(
CountryCodeDisneyPlusSimulcastKeyCache(
countryCode,
val (animeDetails, episodes) = if (bypassFileContent != null && bypassFileContent.exists()) {
getFileApiContent(
bypassFileContent,
simulcast
), zonedDateTime
)
)
} else {
getApiContent(
CountryCodeDisneyPlusSimulcastKeyCache(
countryCode,
simulcast
), zonedDateTime
)
}

episodes.forEach {
try {
Expand Down Expand Up @@ -137,11 +164,13 @@ class DisneyPlusPlatform :
zonedDateTime.withUTC().format(DateTimeFormatter.ISO_LOCAL_DATE) + "T${simulcast.releaseTime}Z"
val releaseDateTime = ZonedDateTime.parse(releaseDateTimeUTC)

if (hashCache.contains(oldId) || hashCache.contains(id)) {
val computedId = EncryptionManager.toSHA512("$animeName-$season-$number").substring(0..<8)

if (hashCache.contains(oldId) || hashCache.contains(id) || hashCache.contains(computedId)) {
throw AnimeException("Episode already exists")
}

hashCache.addAll(mutableListOf(oldId, id))
hashCache.addAll(mutableListOf(oldId, id, computedId))

return Episode(
countryCode = countryCode,
Expand Down
20 changes: 19 additions & 1 deletion src/main/kotlin/fr/shikkanime/repositories/AnimeRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ class AnimeRepository : AbstractRepository<Anime>() {
cb: CriteriaBuilder,
root: Root<Anime>,
searchTypes: Array<LangType>?
): MutableList<Predicate> {
): List<Predicate> {
val orPredicate = mutableListOf<Predicate>()

countryCode?.let { cc ->
Expand Down Expand Up @@ -209,6 +209,24 @@ class AnimeRepository : AbstractRepository<Anime>() {
}
}

override fun find(uuid: UUID): Anime? {
return database.entityManager.use {
val cb = it.criteriaBuilder
val query = cb.createQuery(getEntityClass())
val root = query.from(getEntityClass())

query.where(cb.equal(root[Anime_.uuid], uuid))

createReadOnlyQuery(it, query)
.resultList
.firstOrNull()
?.apply {
Hibernate.initialize(simulcasts)
Hibernate.initialize(platformIds)
}
}
}

fun findBySlug(countryCode: CountryCode, slug: String): Anime? {
return database.entityManager.use {
val cb = it.criteriaBuilder
Expand Down
2 changes: 1 addition & 1 deletion src/main/kotlin/fr/shikkanime/services/AnimeService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -430,7 +430,7 @@ class AnimeService : AbstractService<Anime, AnimeRepository>() {
private fun updateAnimeSimulcast(animeDto: AnimeDto, anime: Anime) {
anime.simulcasts.clear()

animeDto.simulcasts.forEach { simulcastDto ->
animeDto.simulcasts?.forEach { simulcastDto ->
val simulcast = simulcastService.find(simulcastDto.uuid!!) ?: return@forEach

if (anime.simulcasts.none { it.uuid == simulcast.uuid }) {
Expand Down
17 changes: 14 additions & 3 deletions src/main/kotlin/fr/shikkanime/services/caches/AnimeCacheService.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package fr.shikkanime.services.caches

import com.google.inject.Inject
import fr.shikkanime.caches.CountryCodeIdKeyCache
import fr.shikkanime.caches.CountryCodeLocalDateKeyCache
import fr.shikkanime.caches.CountryCodeNamePaginationKeyCache
import fr.shikkanime.caches.CountryCodeUUIDSortPaginationKeyCache
import fr.shikkanime.converters.AbstractConverter
import fr.shikkanime.dtos.animes.AnimeDto
import fr.shikkanime.dtos.PageableDto
import fr.shikkanime.dtos.enums.Status
Expand Down Expand Up @@ -69,7 +71,7 @@ class AnimeCacheService : AbstractCacheService {
}
}

private val findAllByCountryCodeCache = MapCache<CountryCode, List<Anime>>(
val findAllByCountryCodeCache = MapCache(
"AnimeCacheService.findAllByCountryCodeCache",
classes = listOf(Anime::class.java, EpisodeMapping::class.java),
fn = { CountryCode.entries },
Expand Down Expand Up @@ -143,6 +145,15 @@ class AnimeCacheService : AbstractCacheService {
}
}

private val findBySlugCache = MapCache<CountryCodeIdKeyCache, AnimeDto?>(
"AnimeCacheService.findBySlugCache",
classes = listOf(Anime::class.java),
) {
animeService.findBySlug(it.countryCode, it.id)?.let { anime ->
AbstractConverter.convert(anime, AnimeDto::class.java)
}
}

fun findAllBy(
countryCode: CountryCode?,
uuid: UUID?,
Expand All @@ -158,9 +169,9 @@ class AnimeCacheService : AbstractCacheService {

fun findAll() = CountryCode.entries.flatMap { findAllByCountryCodeCache[it]!! }

fun find(uuid: UUID?) = findAll().find { it.uuid == uuid }
fun find(uuid: UUID?) = findAll().firstOrNull { it.uuid == uuid }

fun findBySlug(countryCode: CountryCode, slug: String) = findAllByCountryCodeCache[countryCode]!!.find { it.slug == slug }
fun findBySlug(countryCode: CountryCode, slug: String) = findBySlugCache[CountryCodeIdKeyCache(countryCode, slug)]

fun getWeeklyAnimes(countryCode: CountryCode, memberUuid: UUID?, startOfWeekDay: LocalDate) =
weeklyMemberCache[CountryCodeLocalDateKeyCache(memberUuid, countryCode, startOfWeekDay)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import fr.shikkanime.entities.EpisodeVariant
import fr.shikkanime.entities.SortParameter
import fr.shikkanime.entities.enums.CountryCode
import fr.shikkanime.entities.enums.EpisodeType
import fr.shikkanime.services.AnimeService
import fr.shikkanime.services.EpisodeMappingService
import fr.shikkanime.utils.MapCache
import java.util.UUID
Expand All @@ -25,17 +24,14 @@ class EpisodeMappingCacheService : AbstractCacheService {

@Inject
private lateinit var episodeMappingService: EpisodeMappingService

@Inject
private lateinit var animeService: AnimeService

@Inject
private lateinit var episodeVariantCacheService: EpisodeVariantCacheService

@Inject
private lateinit var animeCacheService: AnimeCacheService

private val findAllCache = MapCache<String, List<EpisodeMapping>>(
private val findAllCache = MapCache(
"EpisodeMappingCacheService.findAllCache",
classes = listOf(EpisodeMapping::class.java),
fn = { listOf(DEFAULT_ALL_KEY) },
Expand All @@ -53,12 +49,13 @@ class EpisodeMappingCacheService : AbstractCacheService {
classes = listOf(
EpisodeMapping::class.java,
EpisodeVariant::class.java
)
),
requiredCaches = { listOf(animeCacheService.findAllByCountryCodeCache) }
) {
PageableDto.fromPageable(
episodeMappingService.findAllBy(
it.countryCode,
animeService.find(it.uuid),
animeCacheService.find(it.uuid),
it.season,
it.sort,
it.page,
Expand All @@ -69,7 +66,7 @@ class EpisodeMappingCacheService : AbstractCacheService {
)
}

private val findAllSeoCache = MapCache<String, List<EpisodeMappingSeoDto>>(
private val findAllSeoCache = MapCache(
"EpisodeMappingCacheService.findAllSeoCache",
classes = listOf(EpisodeMapping::class.java),
fn = { listOf(DEFAULT_ALL_KEY) },
Expand Down
Loading

0 comments on commit 8bc5b6b

Please sign in to comment.