AllAnime fix for time-tagged shows

This commit is contained in:
no-commit 2023-03-03 14:30:21 +01:00
parent 13a55de223
commit 17ac5f1736
2 changed files with 61 additions and 36 deletions

View File

@ -1,5 +1,5 @@
// use an integer for version numbers // use an integer for version numbers
version = 6 version = 7
cloudstream { cloudstream {

View File

@ -7,6 +7,7 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.mvvm.safeApiCall import com.lagradost.cloudstream3.mvvm.safeApiCall
import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.parseJson
import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.AppUtils.toJson
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
import com.lagradost.cloudstream3.utils.Coroutines.mainWork import com.lagradost.cloudstream3.utils.Coroutines.mainWork
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.M3u8Helper import com.lagradost.cloudstream3.utils.M3u8Helper
@ -45,6 +46,22 @@ class AllAnimeProvider : MainAPI() {
@JsonProperty("__typename") val _typename: String @JsonProperty("__typename") val _typename: String
) )
data class CharacterImage(
@JsonProperty("large") val large: String?,
@JsonProperty("medium") val medium: String?
)
data class CharacterName(
@JsonProperty("full") val full: String?,
@JsonProperty("native") val native: String?
)
data class Characters(
@JsonProperty("image") val image: CharacterImage?,
@JsonProperty("role") val role: String?,
@JsonProperty("name") val name: CharacterName?,
)
private data class Edges( private data class Edges(
@JsonProperty("_id") val Id: String?, @JsonProperty("_id") val Id: String?,
@JsonProperty("name") val name: String, @JsonProperty("name") val name: String,
@ -60,6 +77,7 @@ class AllAnimeProvider : MainAPI() {
@JsonProperty("studios") val studios: List<String>?, @JsonProperty("studios") val studios: List<String>?,
@JsonProperty("genres") val genres: List<String>?, @JsonProperty("genres") val genres: List<String>?,
@JsonProperty("averageScore") val averageScore: Int?, @JsonProperty("averageScore") val averageScore: Int?,
@JsonProperty("characters") val characters: List<Characters>?,
@JsonProperty("description") val description: String?, @JsonProperty("description") val description: String?,
@JsonProperty("status") val status: String?, @JsonProperty("status") val status: String?,
@JsonProperty("banner") val banner: String?, @JsonProperty("banner") val banner: String?,
@ -182,11 +200,11 @@ class AllAnimeProvider : MainAPI() {
override suspend fun search(query: String): List<SearchResponse> { override suspend fun search(query: String): List<SearchResponse> {
val link = val link =
"""$mainUrl/allanimeapi?variables={"search":{"allowAdult":false,"allowUnknown":false,"query":"$query"},"limit":26,"page":1,"translationType":"sub","countryOrigin":"ALL"}&extensions={"persistedQuery":{"version":1,"sha256Hash":"9c7a8bc1e095a34f2972699e8105f7aaf9082c6e1ccd56eab99c2f1a971152c6"}}""" """$mainUrl/allanimeapi?variables={"search":{"allowAdult":false,"allowUnknown":false,"query":"$query"},"limit":26,"page":1,"translationType":"sub","countryOrigin":"ALL"}&extensions={"persistedQuery":{"version":1,"sha256Hash":"9c7a8bc1e095a34f2972699e8105f7aaf9082c6e1ccd56eab99c2f1a971152c6"}}"""
var res = app.get(link).text val res = app.get(link).text.takeUnless { it.contains("PERSISTED_QUERY_NOT_FOUND") }
if (res.contains("PERSISTED_QUERY_NOT_FOUND")) { // Retries
res = app.get(link).text ?: app.get(link).text.takeUnless { it.contains("PERSISTED_QUERY_NOT_FOUND") }
if (res.contains("PERSISTED_QUERY_NOT_FOUND")) return emptyList() ?: return emptyList()
}
val response = parseJson<AllAnimeQuery>(res) val response = parseJson<AllAnimeQuery>(res)
val results = response.data.shows.edges.filter { val results = response.data.shows.edges.filter {
@ -211,17 +229,19 @@ class AllAnimeProvider : MainAPI() {
@JsonProperty("raw") val raw: List<String> @JsonProperty("raw") val raw: List<String>
) )
override suspend fun load(url: String): LoadResponse? { /**
val (rhino, scope) = mainWork { * @return the show info, or the redirect url if the url is outdated
val rhino = Context.enter() **/
rhino.optimizationLevel = -1 private suspend fun getShow(url: String, rhino: Context): String? {
val scope: Scriptable = rhino.initSafeStandardObjects() // Fix old bookmarks.
rhino to scope val fixedUrl = url.replace("https://allanime.site", mainUrl)
} val html = app.get(fixedUrl).text
val html = app.get(url).text
val soup = Jsoup.parse(html) val soup = Jsoup.parse(html)
val scope = mainWork {
rhino.initSafeStandardObjects() as Scriptable
}
val script = soup.select("script").firstOrNull { val script = soup.select("script").firstOrNull {
it.html().contains("window.__NUXT__") it.html().contains("window.__NUXT__")
} ?: return null } ?: return null
@ -229,15 +249,30 @@ class AllAnimeProvider : MainAPI() {
val js = """ val js = """
const window = {} const window = {}
${script.html()} ${script.html()}
const returnValue = JSON.stringify(window.__NUXT__.fetch[0].show) const returnValue = JSON.stringify(window.__NUXT__.fetch[0].show) || window.__NUXT__.fetch[0].errorQueryString
""".trimIndent() """.trimIndent()
val jsEval = mainWork { return mainWork {
rhino.evaluateString(scope, js, "JavaScript", 1, null) rhino.evaluateString(scope, js, "JavaScript", 1, null)
scope.get("returnValue", scope) ?: return@mainWork null scope.get("returnValue", scope) ?: return@mainWork null
} ?: return null } as? String
}
val showData = parseJson<Edges>(jsEval as String) override suspend fun load(url: String): LoadResponse? {
val rhino = mainWork {
Context.enter().apply {
this.optimizationLevel = -1
}
}
val show = getShow(url, rhino) ?: return null
// Try parsing the maybe show string
val showData = tryParseJson<Edges>(show)
// Use the redirect url if the url is outdated
?: getShow(
fixUrl(show),
rhino
)?.let { parseJson<Edges>(it) } ?: return null
val title = showData.name val title = showData.name
val description = showData.description val description = showData.description
@ -258,16 +293,16 @@ class AllAnimeProvider : MainAPI() {
}) else null) }) else null)
} }
val characters = soup.select("div.character > div.card-character-box").mapNotNull { val characters = showData.characters?.map {
val img = it?.selectFirst("img")?.attr("src") ?: return@mapNotNull null val role = when (it.role) {
val name = it.selectFirst("div > a")?.ownText() ?: return@mapNotNull null
val role = when (it.selectFirst("div > .text-secondary")?.text()?.trim()) {
"Main" -> ActorRole.Main "Main" -> ActorRole.Main
"Supporting" -> ActorRole.Supporting "Supporting" -> ActorRole.Supporting
"Background" -> ActorRole.Background "Background" -> ActorRole.Background
else -> null else -> null
} }
Pair(Actor(name, img), role) val name = it.name?.full ?: it.name?.native ?: ""
val image = it.image?.large ?: it.image?.medium
Pair(Actor(name, image), role)
} }
// bruh, they use graphql and bruh it is fucked // bruh, they use graphql and bruh it is fucked
@ -325,14 +360,6 @@ class AllAnimeProvider : MainAPI() {
return false return false
} }
private fun String.sanitize(): String {
var out = this
listOf(Pair("\\u002F", "/")).forEach {
out = out.replace(it.first, it.second)
}
return out
}
private data class Links( private data class Links(
@JsonProperty("link") val link: String, @JsonProperty("link") val link: String,
@JsonProperty("hls") val hls: Boolean?, @JsonProperty("hls") val hls: Boolean?,
@ -374,10 +401,8 @@ class AllAnimeProvider : MainAPI() {
callback: (ExtractorLink) -> Unit callback: (ExtractorLink) -> Unit
): Boolean { ): Boolean {
val loadData = parseJson<AllAnimeLoadData>(data) val loadData = parseJson<AllAnimeLoadData>(data)
var apiEndPoint = val apiEndPoint =
parseJson<ApiEndPoint>(app.get("$mainUrl/getVersion").text).episodeIframeHead parseJson<ApiEndPoint>(app.get("$mainUrl/getVersion").text).episodeIframeHead.removeSuffix("/")
if (apiEndPoint.endsWith("/")) apiEndPoint =
apiEndPoint.slice(0 until apiEndPoint.length - 1)
val apiUrl = val apiUrl =
"""$apiUrl/allanimeapi?variables={"showId":"${loadData.hash}","translationType":"${loadData.dubStatus}","episodeString":"${loadData.episode}"}&extensions={"persistedQuery":{"version":1,"sha256Hash":"1f0a5d6c9ce6cd3127ee4efd304349345b0737fbf5ec33a60bbc3d18e3bb7c61"}}""" """$apiUrl/allanimeapi?variables={"showId":"${loadData.hash}","translationType":"${loadData.dubStatus}","episodeString":"${loadData.episode}"}&extensions={"persistedQuery":{"version":1,"sha256Hash":"1f0a5d6c9ce6cd3127ee4efd304349345b0737fbf5ec33a60bbc3d18e3bb7c61"}}"""