mirror of
https://github.com/tapframe/NuvioStreaming.git
synced 2026-08-06 19:38:58 +00:00
Merge pull request #1420 from Laskco/skip-intro-merge-providers
fix(player): merge skip-intro providers instead of first-match-wins
This commit is contained in:
commit
ade6935330
1 changed files with 60 additions and 65 deletions
|
|
@ -25,30 +25,14 @@ object SkipIntroRepository {
|
|||
val cacheKey = "$imdbId:$season:$episode"
|
||||
cache[cacheKey]?.let { return it }
|
||||
|
||||
if (introDbConfigured) {
|
||||
val result = fetchFromIntroDb(imdbId, season, episode)
|
||||
if (result.isNotEmpty()) return result.also { cache[cacheKey] = it }
|
||||
}
|
||||
|
||||
val introDb = if (introDbConfigured) fetchFromIntroDb(imdbId, season, episode) else emptyList()
|
||||
val entries = resolveImdbEntries(imdbId)
|
||||
val animeSkip = fetchAnimeSkipForEntries(entries, season, episode)
|
||||
val malId = entries.getOrNull(season - 1)?.myanimelist?.toString()
|
||||
?: entries.firstOrNull()?.myanimelist?.toString()
|
||||
if (malId != null) {
|
||||
val result = fetchFromAniSkip(malId, episode)
|
||||
if (result.isNotEmpty()) return result.also { cache[cacheKey] = it }
|
||||
}
|
||||
val aniSkip = if (malId != null) fetchFromAniSkip(malId, episode) else emptyList()
|
||||
|
||||
val seasonAnilistId = entries.getOrNull(season - 1)?.anilist?.toString()
|
||||
val fallbackAnilistId = entries.firstOrNull()?.anilist?.toString()
|
||||
for ((anilistId, seasonFilter) in listOfNotNull(
|
||||
seasonAnilistId?.let { it to null },
|
||||
if (fallbackAnilistId != null && fallbackAnilistId != seasonAnilistId) fallbackAnilistId to season else null
|
||||
)) {
|
||||
val result = fetchFromAnimeSkip(anilistId, episode, season = seasonFilter)
|
||||
if (result.isNotEmpty()) return result.also { cache[cacheKey] = it }
|
||||
}
|
||||
|
||||
return emptyList<SkipInterval>().also { cache[cacheKey] = it }
|
||||
return mergeByPriority(introDb, animeSkip, aniSkip).also { cache[cacheKey] = it }
|
||||
}
|
||||
|
||||
suspend fun getSkipIntervalsForMal(
|
||||
|
|
@ -62,41 +46,27 @@ object SkipIntroRepository {
|
|||
val cacheKey = "mal:$malId:$episode"
|
||||
cache[cacheKey]?.let { return it }
|
||||
|
||||
val aniSkipResult = fetchFromAniSkip(malId, episode)
|
||||
if (aniSkipResult.isNotEmpty()) return aniSkipResult.also { cache[cacheKey] = it }
|
||||
val aniSkip = fetchFromAniSkip(malId, episode)
|
||||
|
||||
val imdbId = try {
|
||||
SkipIntroApi.resolveMalToImdb(malId)?.imdb
|
||||
} catch (_: Exception) { null }
|
||||
|
||||
var introDb = emptyList<SkipInterval>()
|
||||
var animeSkip = emptyList<SkipInterval>()
|
||||
if (imdbId != null) {
|
||||
val entries = resolveImdbEntries(imdbId)
|
||||
val season = entries.indexOfFirst { it.myanimelist == malId.toIntOrNull() } + 1
|
||||
|
||||
if (introDbConfigured) {
|
||||
val result = fetchFromIntroDb(imdbId, season, episode)
|
||||
if (result.isNotEmpty()) return result.also { cache[cacheKey] = it }
|
||||
}
|
||||
val seasonAnilistId = entries.getOrNull(season - 1)?.anilist?.toString()
|
||||
val fallbackAnilistId = entries.firstOrNull()?.anilist?.toString()
|
||||
for ((anilistId, seasonFilter) in listOfNotNull(
|
||||
seasonAnilistId?.let { it to null },
|
||||
if (fallbackAnilistId != null && fallbackAnilistId != seasonAnilistId) fallbackAnilistId to season else null
|
||||
)) {
|
||||
val result = fetchFromAnimeSkip(anilistId, episode, season = seasonFilter)
|
||||
if (result.isNotEmpty()) return result.also { cache[cacheKey] = it }
|
||||
}
|
||||
if (introDbConfigured) introDb = fetchFromIntroDb(imdbId, season, episode)
|
||||
animeSkip = fetchAnimeSkipForEntries(entries, season, episode)
|
||||
} else {
|
||||
val anilistId = try {
|
||||
SkipIntroApi.resolveMalToAnilist(malId)?.anilist?.toString()
|
||||
} catch (_: Exception) { null }
|
||||
if (anilistId != null) {
|
||||
val result = fetchFromAnimeSkip(anilistId, episode, season = null)
|
||||
if (result.isNotEmpty()) return result.also { cache[cacheKey] = it }
|
||||
}
|
||||
if (anilistId != null) animeSkip = fetchFromAnimeSkip(anilistId, episode, season = null)
|
||||
}
|
||||
|
||||
return emptyList<SkipInterval>().also { cache[cacheKey] = it }
|
||||
return mergeByPriority(introDb, animeSkip, aniSkip).also { cache[cacheKey] = it }
|
||||
}
|
||||
|
||||
suspend fun getSkipIntervalsForKitsu(
|
||||
|
|
@ -113,44 +83,69 @@ object SkipIntroRepository {
|
|||
val malId = try {
|
||||
SkipIntroApi.resolveKitsuToMal(kitsuId)?.myanimelist?.toString()
|
||||
} catch (_: Exception) { null }
|
||||
|
||||
if (malId != null) {
|
||||
val result = fetchFromAniSkip(malId, episode)
|
||||
if (result.isNotEmpty()) return result.also { cache[cacheKey] = it }
|
||||
}
|
||||
val aniSkip = if (malId != null) fetchFromAniSkip(malId, episode) else emptyList()
|
||||
|
||||
val imdbId = try {
|
||||
SkipIntroApi.resolveKitsuToImdb(kitsuId)?.imdb
|
||||
} catch (_: Exception) { null }
|
||||
|
||||
var introDb = emptyList<SkipInterval>()
|
||||
var animeSkip = emptyList<SkipInterval>()
|
||||
if (imdbId != null) {
|
||||
val entries = resolveImdbEntries(imdbId)
|
||||
val season = entries.indexOfFirst { it.kitsu == kitsuId.toIntOrNull() } + 1
|
||||
|
||||
if (introDbConfigured) {
|
||||
val result = fetchFromIntroDb(imdbId, season, episode)
|
||||
if (result.isNotEmpty()) return result.also { cache[cacheKey] = it }
|
||||
}
|
||||
val seasonAnilistId = entries.getOrNull(season - 1)?.anilist?.toString()
|
||||
val fallbackAnilistId = entries.firstOrNull()?.anilist?.toString()
|
||||
for ((anilistId, seasonFilter) in listOfNotNull(
|
||||
seasonAnilistId?.let { it to null },
|
||||
if (fallbackAnilistId != null && fallbackAnilistId != seasonAnilistId) fallbackAnilistId to season else null
|
||||
)) {
|
||||
val result = fetchFromAnimeSkip(anilistId, episode, season = seasonFilter)
|
||||
if (result.isNotEmpty()) return result.also { cache[cacheKey] = it }
|
||||
}
|
||||
if (introDbConfigured) introDb = fetchFromIntroDb(imdbId, season, episode)
|
||||
animeSkip = fetchAnimeSkipForEntries(entries, season, episode)
|
||||
} else {
|
||||
val anilistId = try {
|
||||
SkipIntroApi.resolveKitsuToAnilist(kitsuId)?.anilist?.toString()
|
||||
} catch (_: Exception) { null }
|
||||
if (anilistId != null) {
|
||||
val result = fetchFromAnimeSkip(anilistId, episode, season = null)
|
||||
if (result.isNotEmpty()) return result.also { cache[cacheKey] = it }
|
||||
}
|
||||
if (anilistId != null) animeSkip = fetchFromAnimeSkip(anilistId, episode, season = null)
|
||||
}
|
||||
|
||||
return emptyList<SkipInterval>().also { cache[cacheKey] = it }
|
||||
return mergeByPriority(introDb, animeSkip, aniSkip).also { cache[cacheKey] = it }
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge provider results into one best-of: fill each segment category (opening / ending /
|
||||
* recap) from the highest-priority provider that has it. Arguments MUST be passed in priority
|
||||
* order (IntroDB has the broadest coverage, then Anime-Skip, then AniSkip), so a partial
|
||||
* result from one provider never shadows a complete segment from another.
|
||||
*/
|
||||
private fun mergeByPriority(vararg providerResults: List<SkipInterval>): List<SkipInterval> {
|
||||
val chosen = LinkedHashMap<String, SkipInterval>()
|
||||
for (result in providerResults) {
|
||||
for (interval in result) {
|
||||
val category = segmentCategory(interval.type) ?: continue
|
||||
if (category !in chosen) chosen[category] = interval
|
||||
}
|
||||
}
|
||||
return chosen.values.toList()
|
||||
}
|
||||
|
||||
private fun segmentCategory(type: String): String? = when (type.lowercase()) {
|
||||
"intro", "op", "mixed-op" -> "opening"
|
||||
"outro", "ed", "mixed-ed", "credits", "ending" -> "ending"
|
||||
"recap" -> "recap"
|
||||
else -> null
|
||||
}
|
||||
|
||||
// AnimeSkip: season-specific AniList ID first, then season-1 as a season-filtered fallback.
|
||||
private suspend fun fetchAnimeSkipForEntries(
|
||||
entries: List<ArmEntry>,
|
||||
season: Int,
|
||||
episode: Int
|
||||
): List<SkipInterval> {
|
||||
val seasonAnilistId = entries.getOrNull(season - 1)?.anilist?.toString()
|
||||
val fallbackAnilistId = entries.firstOrNull()?.anilist?.toString()
|
||||
for ((anilistId, seasonFilter) in listOfNotNull(
|
||||
seasonAnilistId?.let { it to null },
|
||||
if (fallbackAnilistId != null && fallbackAnilistId != seasonAnilistId) fallbackAnilistId to season else null
|
||||
)) {
|
||||
val result = fetchFromAnimeSkip(anilistId, episode, season = seasonFilter)
|
||||
if (result.isNotEmpty()) return result
|
||||
}
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
private suspend fun fetchFromIntroDb(imdbId: String, season: Int, episode: Int): List<SkipInterval> {
|
||||
|
|
|
|||
Loading…
Reference in a new issue