Fix(en/Aniplay): Fixes and Improvements (#382)

* en/AniPlay: fixed warnings

* en/AniPlay: updated wrong url

* en/AniPlay: better list parsing

* en/AniPlay: added invalid index safeguard to video server and type name

* en/AniPlay: better server names in source list

* en/AniPlay: made some Episode class members nullable

* en/AniPlay: added Timed out message

* en/AniPlay: performance improvement

* en/AniPlay: removed confusing server names

* en/AniPlay: fixed small warning

* en/AniPlay: updated versionCode
This commit is contained in:
Josef František Straka 2024-11-22 02:21:13 +01:00 committed by GitHub
parent 5a9383dffb
commit 6dd53f4aa6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 44 additions and 18 deletions

View file

@ -2,7 +2,7 @@ ext {
extName = 'AniPlay' extName = 'AniPlay'
extClass = '.AniPlay' extClass = '.AniPlay'
themePkg = 'anilist' themePkg = 'anilist'
overrideVersionCode = 4 overrideVersionCode = 5
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View file

@ -17,7 +17,8 @@ import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
import eu.kanade.tachiyomi.multisrc.anilist.AniListAnimeHttpSource import eu.kanade.tachiyomi.multisrc.anilist.AniListAnimeHttpSource
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.util.parallelFlatMapBlocking import eu.kanade.tachiyomi.util.parallelFlatMap
import eu.kanade.tachiyomi.util.parallelMap
import eu.kanade.tachiyomi.util.parseAs import eu.kanade.tachiyomi.util.parseAs
import kotlinx.serialization.SerializationException import kotlinx.serialization.SerializationException
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
@ -32,6 +33,7 @@ import java.io.IOException
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Locale import java.util.Locale
@Suppress("unused")
class AniPlay : AniListAnimeHttpSource(), ConfigurableAnimeSource { class AniPlay : AniListAnimeHttpSource(), ConfigurableAnimeSource {
override val name = "AniPlay" override val name = "AniPlay"
override val lang = "en" override val lang = "en"
@ -68,7 +70,7 @@ class AniPlay : AniListAnimeHttpSource(), ConfigurableAnimeSource {
} }
} }
val baseHost: String get() = "${preferences.getString(PREF_DOMAIN_KEY, PREF_DOMAIN_DEFAULT)}" private val baseHost: String get() = "${preferences.getString(PREF_DOMAIN_KEY, PREF_DOMAIN_DEFAULT)}"
/* ====================================== Episode List ====================================== */ /* ====================================== Episode List ====================================== */
@ -131,7 +133,7 @@ class AniPlay : AniListAnimeHttpSource(), ConfigurableAnimeSource {
source = provider.providerId, source = provider.providerId,
episodeId = episode.id, episodeId = episode.id,
episodeNum = episode.number, episodeNum = episode.number,
hasDub = episode.hasDub, hasDub = episode.hasDub ?: false,
) )
episodeExtras[episodeNumber] = existingEpisodeExtras + listOf(episodeExtra) episodeExtras[episodeNumber] = existingEpisodeExtras + listOf(episodeExtra)
} }
@ -160,7 +162,7 @@ class AniPlay : AniListAnimeHttpSource(), ConfigurableAnimeSource {
else -> "" else -> ""
} }
val filler = when { val filler = when {
episode.isFiller && isMarkFiller -> " • Filler Episode" episode.isFiller == true && isMarkFiller -> " • Filler Episode"
else -> "" else -> ""
} }
val scanlator = "Sub$dub$filler" val scanlator = "Sub$dub$filler"
@ -206,11 +208,14 @@ class AniPlay : AniListAnimeHttpSource(), ConfigurableAnimeSource {
.add("Next-Action", getHeaderValue(baseHost, NEXT_ACTION_SOURCES_LIST)) .add("Next-Action", getHeaderValue(baseHost, NEXT_ACTION_SOURCES_LIST))
.build() .build()
val episodeDataList = extras.parallelFlatMapBlocking { extra -> var timeouts = 0
var maxTimeout = 0
val episodeDataList = extras.parallelFlatMap { extra ->
val languages = mutableListOf("sub").apply { val languages = mutableListOf("sub").apply {
if (extra.hasDub) add("dub") if (extra.hasDub) add("dub")
} }
languages.map { language -> languages.parallelMap { language ->
maxTimeout += 1
val epNum = if (extra.episodeNum == extra.episodeNum.toInt().toFloat()) { val epNum = if (extra.episodeNum == extra.episodeNum.toInt().toFloat()) {
extra.episodeNum.toInt().toString() // If it has no fractional part, convert it to an integer extra.episodeNum.toInt().toString() // If it has no fractional part, convert it to an integer
} else { } else {
@ -221,12 +226,11 @@ class AniPlay : AniListAnimeHttpSource(), ConfigurableAnimeSource {
.toRequestBody("application/json".toMediaType()) .toRequestBody("application/json".toMediaType())
val params = mapOf( val params = mapOf(
"id" to animeId,
"host" to extra.source, "host" to extra.source,
"ep" to epNum, "ep" to epNum,
"type" to language, "type" to language,
) )
val builder = Uri.parse("$baseUrl/anime/watch").buildUpon() val builder = Uri.parse("$baseUrl/anime/watch/$animeId").buildUpon()
params.map { (k, v) -> builder.appendQueryParameter(k, v); } params.map { (k, v) -> builder.appendQueryParameter(k, v); }
val url = builder.build().toString() val url = builder.build().toString()
try { try {
@ -234,8 +238,7 @@ class AniPlay : AniListAnimeHttpSource(), ConfigurableAnimeSource {
val response = client.newCall(request).execute() val response = client.newCall(request).execute()
val responseString = response.body.string() val responseString = response.body.string()
val sourcesString = responseString.split("1:").last() val sourcesString = extractSourcesList(responseString) ?: return@parallelMap null
if (sourcesString.startsWith("null")) return@map null
val data = sourcesString.parseAs<VideoSourceResponse>() val data = sourcesString.parseAs<VideoSourceResponse>()
EpisodeData( EpisodeData(
@ -243,16 +246,25 @@ class AniPlay : AniListAnimeHttpSource(), ConfigurableAnimeSource {
language = language, language = language,
response = data, response = data,
) )
} catch (e: java.net.SocketTimeoutException) {
timeouts += 1
null
} catch (e: IOException) { } catch (e: IOException) {
Log.w("AniPlay", "VideoList $url IOException", e) Log.w("AniPlay", "VideoList $url IOException", e)
timeouts = -999
null // Return null to be filtered out null // Return null to be filtered out
} catch (e: Exception) { } catch (e: Exception) {
Log.w("AniPlay", "VideoList $url Exception", e) Log.w("AniPlay", "VideoList $url Exception", e)
timeouts = -999
null // Return null to be filtered out null // Return null to be filtered out
} }
}.filterNotNull() // Filter out null values due to errors }.filterNotNull() // Filter out null values due to errors
} }
if (maxTimeout == timeouts && timeouts != 0) {
throw Exception("Timed out")
}
val videos = episodeDataList.flatMap { episodeData -> val videos = episodeDataList.flatMap { episodeData ->
val defaultSource = episodeData.response.sources?.firstOrNull { val defaultSource = episodeData.response.sources?.firstOrNull {
it.quality in listOf("default", "auto") it.quality in listOf("default", "auto")
@ -294,7 +306,15 @@ class AniPlay : AniListAnimeHttpSource(), ConfigurableAnimeSource {
} }
private fun extractEpisodeList(input: String): String? { private fun extractEpisodeList(input: String): String? {
val startMarker = "1:[" return extractList(input, '[', ']')
}
private fun extractSourcesList(input: String): String? {
return extractList(input, '{', '}')
}
private fun extractList(input: String, bracket1: Char, bracket2: Char): String? {
val startMarker = "1:$bracket1"
val list1Index = input.indexOf(startMarker) val list1Index = input.indexOf(startMarker)
if (list1Index == -1) return null if (list1Index == -1) return null
@ -304,8 +324,8 @@ class AniPlay : AniListAnimeHttpSource(), ConfigurableAnimeSource {
while (endIndex < input.length && bracketCount > 0) { while (endIndex < input.length && bracketCount > 0) {
when (input[endIndex]) { when (input[endIndex]) {
'[' -> bracketCount++ bracket1 -> bracketCount++
']' -> bracketCount-- bracket2 -> bracketCount--
} }
endIndex++ endIndex++
} }
@ -419,11 +439,17 @@ class AniPlay : AniListAnimeHttpSource(), ConfigurableAnimeSource {
} }
private fun getServerName(value: String): String { private fun getServerName(value: String): String {
val index = PREF_SERVER_ENTRY_VALUES.indexOf(value) val index = PREF_SERVER_ENTRY_VALUES.indexOf(value)
if (index == -1) {
return "Other"
}
return PREF_SERVER_ENTRIES[index] return PREF_SERVER_ENTRIES[index]
} }
private fun getTypeName(value: String): String { private fun getTypeName(value: String): String {
val index = PREF_TYPE_ENTRY_VALUES.indexOf(value) val index = PREF_TYPE_ENTRY_VALUES.indexOf(value)
if (index == -1) {
return "Other"
}
return PREF_TYPE_ENTRIES[index] return PREF_TYPE_ENTRIES[index]
} }
@ -445,7 +471,7 @@ class AniPlay : AniListAnimeHttpSource(), ConfigurableAnimeSource {
private const val PREF_DOMAIN_DEFAULT = "aniplaynow.live" private const val PREF_DOMAIN_DEFAULT = "aniplaynow.live"
private const val PREF_SERVER_KEY = "server" private const val PREF_SERVER_KEY = "server"
private val PREF_SERVER_ENTRIES = arrayOf("Kuro (Gogoanime)", "Yuki (HiAnime)", "Yuno (Yugenanime)") private val PREF_SERVER_ENTRIES = arrayOf("Kuro", "Yuki", "Yuno")
private val PREF_SERVER_ENTRY_VALUES = arrayOf("kuro", "yuki", "yuno") private val PREF_SERVER_ENTRY_VALUES = arrayOf("kuro", "yuki", "yuno")
private const val PREF_SERVER_DEFAULT = "kuro" private const val PREF_SERVER_DEFAULT = "kuro"

View file

@ -13,9 +13,9 @@ data class EpisodeListResponse(
data class Episode( data class Episode(
val id: String, val id: String,
val number: Float, val number: Float,
val title: String, val title: String?,
val hasDub: Boolean, val hasDub: Boolean?,
val isFiller: Boolean, val isFiller: Boolean?,
val img: String?, val img: String?,
val description: String?, val description: String?,
val createdAt: String?, val createdAt: String?,