fix(pt/goanimes): Fix http 502 + add more extractors (#2611)
This commit is contained in:
parent
34b01b16f4
commit
82c0ff0c47
@ -1,4 +1,5 @@
|
|||||||
dependencies {
|
dependencies {
|
||||||
implementation(project(":lib-playlist-utils"))
|
implementation(project(":lib-playlist-utils"))
|
||||||
|
implementation(project(":lib-blogger-extractor"))
|
||||||
implementation("dev.datlag.jsunpacker:jsunpacker:1.0.1")
|
implementation("dev.datlag.jsunpacker:jsunpacker:1.0.1")
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import eu.kanade.tachiyomi.animeextension.pt.goanimes.extractors.LinkfunBypasser
|
|||||||
import eu.kanade.tachiyomi.animeextension.pt.goanimes.extractors.PlaylistExtractor
|
import eu.kanade.tachiyomi.animeextension.pt.goanimes.extractors.PlaylistExtractor
|
||||||
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
import eu.kanade.tachiyomi.animesource.model.SEpisode
|
||||||
import eu.kanade.tachiyomi.animesource.model.Video
|
import eu.kanade.tachiyomi.animesource.model.Video
|
||||||
|
import eu.kanade.tachiyomi.lib.bloggerextractor.BloggerExtractor
|
||||||
import eu.kanade.tachiyomi.multisrc.dooplay.DooPlay
|
import eu.kanade.tachiyomi.multisrc.dooplay.DooPlay
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
@ -69,22 +70,46 @@ class GoAnimes : DooPlay(
|
|||||||
override val prefQualityEntries = prefQualityValues
|
override val prefQualityEntries = prefQualityValues
|
||||||
|
|
||||||
private val goanimesExtractor by lazy { GoAnimesExtractor(client, headers) }
|
private val goanimesExtractor by lazy { GoAnimesExtractor(client, headers) }
|
||||||
|
private val bloggerExtractor by lazy { BloggerExtractor(client) }
|
||||||
private val linkfunBypasser by lazy { LinkfunBypasser(client) }
|
private val linkfunBypasser by lazy { LinkfunBypasser(client) }
|
||||||
|
|
||||||
override fun videoListParse(response: Response): List<Video> {
|
override fun videoListParse(response: Response): List<Video> {
|
||||||
val document = response.use { it.asJsoup() }
|
val document = response.use { it.asJsoup() }
|
||||||
val players = document.select("ul#playeroptionsul li")
|
val players = document.select("ul#playeroptionsul li")
|
||||||
return players.parallelMap {
|
return players.parallelCatchingFlatMap(::getPlayerVideos)
|
||||||
runCatching {
|
|
||||||
getPlayerVideos(it)
|
|
||||||
}.getOrElse { emptyList() }
|
|
||||||
}.flatten().ifEmpty { throw Exception("Nenhum vídeo encontrado.") }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getPlayerVideos(player: Element): List<Video> {
|
private fun getPlayerVideos(player: Element): List<Video> {
|
||||||
val url = getPlayerUrl(player)
|
val url = getPlayerUrl(player)
|
||||||
return when {
|
return when {
|
||||||
"player5.goanimes.net" in url -> goanimesExtractor.videosFromUrl(url)
|
"player5.goanimes.net" in url -> goanimesExtractor.videosFromUrl(url)
|
||||||
|
"https://gojopoolt" in url -> {
|
||||||
|
val headers = headers.newBuilder()
|
||||||
|
.set("referer", url)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
val script = client.newCall(GET(url, headers)).execute()
|
||||||
|
.use { it.body.string() }
|
||||||
|
.let { JsDecoder.decodeScript(it, false) }
|
||||||
|
|
||||||
|
script.substringAfter("sources: [")
|
||||||
|
.substringBefore(']')
|
||||||
|
.split('{')
|
||||||
|
.drop(1)
|
||||||
|
.mapNotNull {
|
||||||
|
val videoUrl = it.substringAfter("file: ")
|
||||||
|
.substringBefore(", ")
|
||||||
|
.trim('"', '\'', ' ')
|
||||||
|
.ifBlank { return@mapNotNull null }
|
||||||
|
|
||||||
|
val resolution = it.substringAfter("label: ", "")
|
||||||
|
.substringAfter('"')
|
||||||
|
.substringBefore('"')
|
||||||
|
.ifBlank { "Default" }
|
||||||
|
|
||||||
|
Video(videoUrl, "Gojopoolt - $resolution", videoUrl, headers)
|
||||||
|
}
|
||||||
|
}
|
||||||
listOf("/bloggerjwplayer", "/m3u8", "/multivideo").any { it in url } -> {
|
listOf("/bloggerjwplayer", "/m3u8", "/multivideo").any { it in url } -> {
|
||||||
val script = client.newCall(GET(url)).execute()
|
val script = client.newCall(GET(url)).execute()
|
||||||
.use { it.body.string() }
|
.use { it.body.string() }
|
||||||
@ -102,6 +127,7 @@ class GoAnimes : DooPlay(
|
|||||||
else -> emptyList<Video>()
|
else -> emptyList<Video>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"www.blogger.com" in url -> bloggerExtractor.videosFromUrl(url, headers)
|
||||||
else -> emptyList<Video>()
|
else -> emptyList<Video>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,8 +157,12 @@ class GoAnimes : DooPlay(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ============================= Utilities ==============================
|
// ============================= Utilities ==============================
|
||||||
private inline fun <A, B> Iterable<A>.parallelMap(crossinline f: suspend (A) -> B): List<B> =
|
private inline fun <A, B> Iterable<A>.parallelCatchingFlatMap(crossinline f: suspend (A) -> Iterable<B>): List<B> =
|
||||||
runBlocking {
|
runBlocking {
|
||||||
map { async(Dispatchers.Default) { f(it) } }.awaitAll()
|
map {
|
||||||
|
async(Dispatchers.Default) {
|
||||||
|
runCatching { f(it) }.getOrElse { emptyList() }
|
||||||
|
}
|
||||||
|
}.awaitAll().flatten()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package eu.kanade.tachiyomi.animeextension.pt.goanimes.extractors
|
package eu.kanade.tachiyomi.animeextension.pt.goanimes.extractors
|
||||||
|
|
||||||
|
import android.util.Base64
|
||||||
import dev.datlag.jsunpacker.JsUnpacker
|
import dev.datlag.jsunpacker.JsUnpacker
|
||||||
import eu.kanade.tachiyomi.animesource.model.Video
|
import eu.kanade.tachiyomi.animesource.model.Video
|
||||||
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
|
import eu.kanade.tachiyomi.lib.playlistutils.PlaylistUtils
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import okhttp3.Headers
|
import okhttp3.Headers
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
|
||||||
class GoAnimesExtractor(private val client: OkHttpClient, private val headers: Headers) {
|
class GoAnimesExtractor(private val client: OkHttpClient, private val headers: Headers) {
|
||||||
@ -32,7 +34,16 @@ class GoAnimesExtractor(private val client: OkHttpClient, private val headers: H
|
|||||||
.substringBefore("'", "")
|
.substringBefore("'", "")
|
||||||
.takeIf(String::isNotEmpty)
|
.takeIf(String::isNotEmpty)
|
||||||
?: return emptyList()
|
?: return emptyList()
|
||||||
playlistUtils.extractFromHls(playlistUrl, url, videoNameGen = { "$PLAYER_NAME - $it" })
|
|
||||||
|
val fixedUrl = if (playlistUrl.contains("/aHR0")) {
|
||||||
|
val encoded = playlistUrl.substringAfterLast("/").substringBefore(".")
|
||||||
|
String(Base64.decode(encoded, Base64.DEFAULT))
|
||||||
|
} else {
|
||||||
|
playlistUrl
|
||||||
|
}
|
||||||
|
|
||||||
|
val referer = url.toHttpUrl().queryParameter("url") ?: url
|
||||||
|
playlistUtils.extractFromHls(fixedUrl, referer, videoNameGen = { "$PLAYER_NAME - $it" })
|
||||||
}
|
}
|
||||||
else -> emptyList()
|
else -> emptyList()
|
||||||
}
|
}
|
||||||
|
@ -25,10 +25,14 @@ object JsDecoder {
|
|||||||
}.joinToString("")
|
}.joinToString("")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun decodeScript(html: String): String {
|
fun decodeScript(html: String, isB64: Boolean = true): String {
|
||||||
val script = html.substringAfter(";base64,")
|
val script = if (isB64) {
|
||||||
|
html.substringAfter(";base64,")
|
||||||
.substringBefore('"')
|
.substringBefore('"')
|
||||||
.let { String(Base64.decode(it, Base64.DEFAULT)) }
|
.let { String(Base64.decode(it, Base64.DEFAULT)) }
|
||||||
|
} else {
|
||||||
|
html
|
||||||
|
}
|
||||||
|
|
||||||
val regex = """\}\("(\w+)",.*?"(\w+)",(\d+),(\d+),.*?\)""".toRegex()
|
val regex = """\}\("(\w+)",.*?"(\w+)",(\d+),(\d+),.*?\)""".toRegex()
|
||||||
return regex.find(script)
|
return regex.find(script)
|
||||||
|
@ -19,7 +19,7 @@ class DooPlayGenerator : ThemeSourceGenerator {
|
|||||||
SingleLang("Animes House", "https://animeshouse.net", "pt-BR", isNsfw = false, overrideVersionCode = 8),
|
SingleLang("Animes House", "https://animeshouse.net", "pt-BR", isNsfw = false, overrideVersionCode = 8),
|
||||||
SingleLang("Cinemathek", "https://cinemathek.net", "de", isNsfw = true, overrideVersionCode = 17),
|
SingleLang("Cinemathek", "https://cinemathek.net", "de", isNsfw = true, overrideVersionCode = 17),
|
||||||
SingleLang("DonghuaX", "https://donghuax.com", "pt-BR", isNsfw = false, overrideVersionCode = 1),
|
SingleLang("DonghuaX", "https://donghuax.com", "pt-BR", isNsfw = false, overrideVersionCode = 1),
|
||||||
SingleLang("GoAnimes", "https://goanimes.net", "pt-BR", isNsfw = true, overrideVersionCode = 5),
|
SingleLang("GoAnimes", "https://goanimes.net", "pt-BR", isNsfw = true, overrideVersionCode = 6),
|
||||||
SingleLang("JetAnime", "https://ssl.jetanimes.com", "fr", isNsfw = false, overrideVersionCode = 2),
|
SingleLang("JetAnime", "https://ssl.jetanimes.com", "fr", isNsfw = false, overrideVersionCode = 2),
|
||||||
SingleLang("Kinoking", "https://kinoking.cc", "de", isNsfw = false, overrideVersionCode = 19),
|
SingleLang("Kinoking", "https://kinoking.cc", "de", isNsfw = false, overrideVersionCode = 19),
|
||||||
SingleLang("Multimovies", "https://multimovies.live", "en", isNsfw = false, overrideVersionCode = 13),
|
SingleLang("Multimovies", "https://multimovies.live", "en", isNsfw = false, overrideVersionCode = 13),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user