AnimesHouse: Fix NPE and video extractor operation (#864)

* AnimesHouse: Fix NPE when fetching anime details

* AnimesHouse: Remove useless parameter on EdifierExtractor

* AnimesHouse: Bump version

* AnimesHouse: Add bypasser to redplay video protector

* AnimesHouse: Ignore errors when fetching videos
This commit is contained in:
Claudemirovsky
2022-09-14 10:19:13 -03:00
committed by GitHub
parent 7dcba7c84e
commit 4a40e39bc9
4 changed files with 70 additions and 6 deletions

View File

@ -5,7 +5,7 @@ ext {
extName = 'Animes House'
pkgNameSuffix = 'pt.animeshouse'
extClass = '.AnimesHouse'
extVersionCode = 1
extVersionCode = 2
libVersion = '13'
}

View File

@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.animeextension.pt.animeshouse.extractors.GenericExtra
import eu.kanade.tachiyomi.animeextension.pt.animeshouse.extractors.JsUnpacker
import eu.kanade.tachiyomi.animeextension.pt.animeshouse.extractors.McpExtractor
import eu.kanade.tachiyomi.animeextension.pt.animeshouse.extractors.MpFourDooExtractor
import eu.kanade.tachiyomi.animeextension.pt.animeshouse.extractors.RedplayBypasser
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
import eu.kanade.tachiyomi.animesource.model.AnimesPage
@ -119,7 +120,11 @@ class AnimesHouse : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
.execute()
.asJsoup()
val iframe = doc.selectFirst("iframe")
return iframe.attr("src")
return iframe.attr("src").let {
if (it.startsWith("/redplay"))
RedplayBypasser(client, headers).fromUrl(baseUrl + it)
else it
}
}
override fun videoListParse(response: Response): List<Video> {
@ -128,7 +133,9 @@ class AnimesHouse : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val videoList = mutableListOf<Video>()
players.forEach { player ->
val url = getPlayerUrl(player)
videoList.addAll(getPlayerVideos(url))
val videos = runCatching { getPlayerVideos(url) }
.getOrNull() ?: emptyList<Video>()
videoList.addAll(videos)
}
return videoList
}
@ -143,7 +150,7 @@ class AnimesHouse : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
"embed.php?" in url ->
EmbedExtractor(headers).getVideoList(url, iframeBody)
"edifier" in url ->
EdifierExtractor(client, headers).getVideoList(url, iframeBody)
EdifierExtractor(client, headers).getVideoList(url)
"mp4doo" in url ->
MpFourDooExtractor(headers).getVideoList(unpackedBody)
"clp-new" in url || "gcloud" in url ->
@ -241,7 +248,7 @@ class AnimesHouse : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
anime.genre = sheader.select("div.data > div.sgeneros > a")
.joinToString(", ") { it.text() }
val info = doc.selectFirst("div#info")
var description = info.selectFirst("p").text() + "\n"
var description = info.selectFirst("p")?.let { it.text() + "\n" } ?: ""
info.getInfo("Título")?.let { description += "$it" }
info.getInfo("Ano")?.let { description += "$it" }
info.getInfo("Temporadas")?.let { description += "$it" }

View File

@ -13,7 +13,7 @@ class EdifierExtractor(
private val REGEX_EDIFIER = Regex(""""file":"(.*?)","label":"(\S+?)"""")
private val PLAYER_NAME = "EDIFIER"
fun getVideoList(url: String, iframeBody: String): List<Video> {
fun getVideoList(url: String): List<Video> {
val apiUrl = url.replace("/v/", "/api/source/")
val req = client.newCall(POST(apiUrl)).execute()
val body = req.body?.string().orEmpty()

View File

@ -0,0 +1,57 @@
package eu.kanade.tachiyomi.animeextension.pt.animeshouse.extractors
import android.util.Base64
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.FormBody
import okhttp3.Headers
import okhttp3.OkHttpClient
class RedplayBypasser(
private val client: OkHttpClient,
private val headers: Headers
) {
fun fromUrl(url: String): String {
val firstDoc = client.newCall(GET(url, headers)).execute().asJsoup()
val next = firstDoc.selectFirst("a").attr("href")
var nextPage = client.newCall(GET(next, headers)).execute()
var iframeUrl = ""
var formUrl = next
while (iframeUrl == "") {
val nextDoc = nextPage.asJsoup(decodeAtob(nextPage.body!!.string()))
val iframe = nextDoc.selectFirst("iframe")
if (iframe != null)
iframeUrl = iframe.attr("src")
else {
val newHeaders = headers.newBuilder()
.set("Referer", formUrl)
.build()
val formBody = FormBody.Builder()
formUrl = nextDoc.selectFirst("form").attr("action")
nextDoc.select("input[name]").forEach {
formBody.add(it.attr("name"), it.attr("value"))
}
nextPage = client.newCall(POST(formUrl, newHeaders, formBody.build()))
.execute()
}
}
return iframeUrl
}
private fun decodeAtob(html: String): String {
val atobContent = html.substringAfter("atob(\"").substringBefore("\"));")
val hexAtob = atobContent.replace("\\x", "").decodeHex()
val decoded = Base64.decode(hexAtob, Base64.DEFAULT)
return String(decoded)
}
// Stolen from AnimixPlay(EN) / GogoCdnExtractor
private fun String.decodeHex(): ByteArray {
check(length % 2 == 0) { "Must have an even length" }
return chunked(2)
.map { it.toInt(16).toByte() }
.toByteArray()
}
}