Spanish extension fixes

Closes #134
This commit is contained in:
imper1aldev 2024-08-13 23:07:29 -06:00
parent c6456c8ff4
commit 593a7634d9
8 changed files with 54 additions and 92 deletions

View file

@ -34,7 +34,7 @@ class DoodExtractor(private val client: OkHttpClient) {
), ),
).execute().body.string() ).execute().body.string()
val videoUrl = "$videoUrlStart$randomString?token=$token&expiry=$expiry" val videoUrl = "$videoUrlStart$randomString?token=$token&expiry=$expiry"
Video(newUrl, newQuality, videoUrl, headers = doodHeaders(doodHost), subtitleTracks = externalSubs) Video(videoUrl, newQuality, videoUrl, headers = doodHeaders(doodHost), subtitleTracks = externalSubs)
}.getOrNull() }.getOrNull()
} }

View file

@ -1,7 +1,7 @@
ext { ext {
extName = 'Cuevana' extName = 'Cuevana'
extClass = '.CuevanaFactory' extClass = '.CuevanaFactory'
extVersionCode = 31 extVersionCode = 32
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View file

@ -6,6 +6,7 @@ import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.es.cuevana.models.AnimeEpisodesList import eu.kanade.tachiyomi.animeextension.es.cuevana.models.AnimeEpisodesList
import eu.kanade.tachiyomi.animeextension.es.cuevana.models.PopularAnimeList import eu.kanade.tachiyomi.animeextension.es.cuevana.models.PopularAnimeList
import eu.kanade.tachiyomi.animeextension.es.cuevana.models.Server
import eu.kanade.tachiyomi.animeextension.es.cuevana.models.Videos import eu.kanade.tachiyomi.animeextension.es.cuevana.models.Videos
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilter import eu.kanade.tachiyomi.animesource.model.AnimeFilter
@ -24,10 +25,7 @@ import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
import eu.kanade.tachiyomi.lib.youruploadextractor.YourUploadExtractor import eu.kanade.tachiyomi.lib.youruploadextractor.YourUploadExtractor
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import eu.kanade.tachiyomi.util.parallelMapBlocking
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
@ -35,6 +33,7 @@ import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.ArrayList
class CuevanaEu(override val name: String, override val baseUrl: String) : ConfigurableAnimeSource, ParsedAnimeHttpSource() { class CuevanaEu(override val name: String, override val baseUrl: String) : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
@ -151,28 +150,28 @@ class CuevanaEu(override val name: String, override val baseUrl: String) : Confi
private fun serverIterator(videos: Videos?): MutableList<Video> { private fun serverIterator(videos: Videos?): MutableList<Video> {
val videoList = mutableListOf<Video>() val videoList = mutableListOf<Video>()
videos?.latino?.parallelMapBlocking { videos?.latino?.forEach {
try { try {
val body = client.newCall(GET(it.result!!)).execute().asJsoup() val body = client.newCall(GET(it.result!!)).execute().asJsoup()
val url = body.selectFirst("script:containsData(var message)")?.data()?.substringAfter("var url = '")?.substringBefore("'") ?: "" val url = body.selectFirst("script:containsData(var message)")?.data()?.substringAfter("var url = '")?.substringBefore("'") ?: ""
loadExtractor(url, "[LAT]").let { videoList.addAll(it) } loadExtractor(url, "[LAT]").let { videoList.addAll(it) }
} catch (_: Exception) { } } catch (_: Exception) { }
} }
videos?.spanish?.map { videos?.spanish?.forEach {
try { try {
val body = client.newCall(GET(it.result!!)).execute().asJsoup() val body = client.newCall(GET(it.result!!)).execute().asJsoup()
val url = body.selectFirst("script:containsData(var message)")?.data()?.substringAfter("var url = '")?.substringBefore("'") ?: "" val url = body.selectFirst("script:containsData(var message)")?.data()?.substringAfter("var url = '")?.substringBefore("'") ?: ""
loadExtractor(url, "[CAST]").let { videoList.addAll(it) } loadExtractor(url, "[CAST]").let { videoList.addAll(it) }
} catch (_: Exception) { } } catch (_: Exception) { }
} }
videos?.english?.map { videos?.english?.forEach {
try { try {
val body = client.newCall(GET(it.result!!)).execute().asJsoup() val body = client.newCall(GET(it.result!!)).execute().asJsoup()
val url = body.selectFirst("script:containsData(var message)")?.data()?.substringAfter("var url = '")?.substringBefore("'") ?: "" val url = body.selectFirst("script:containsData(var message)")?.data()?.substringAfter("var url = '")?.substringBefore("'") ?: ""
loadExtractor(url, "[ENG]").let { videoList.addAll(it) } loadExtractor(url, "[ENG]").let { videoList.addAll(it) }
} catch (_: Exception) { } } catch (_: Exception) { }
} }
videos?.japanese?.map { videos?.japanese?.forEach {
val body = client.newCall(GET(it.result!!)).execute().asJsoup() val body = client.newCall(GET(it.result!!)).execute().asJsoup()
val url = body.selectFirst("script:containsData(var message)")?.data()?.substringAfter("var url = '")?.substringBefore("'") ?: "" val url = body.selectFirst("script:containsData(var message)")?.data()?.substringAfter("var url = '")?.substringBefore("'") ?: ""
loadExtractor(url, "[JAP]").let { videoList.addAll(it) } loadExtractor(url, "[JAP]").let { videoList.addAll(it) }
@ -183,31 +182,6 @@ class CuevanaEu(override val name: String, override val baseUrl: String) : Confi
private fun loadExtractor(url: String, prefix: String = ""): List<Video> { private fun loadExtractor(url: String, prefix: String = ""): List<Video> {
val videoList = mutableListOf<Video>() val videoList = mutableListOf<Video>()
val embedUrl = url.lowercase() val embedUrl = url.lowercase()
if (embedUrl.contains("tomatomatela")) {
try {
val mainUrl = url.substringBefore("/embed.html#").substringAfter("https://")
val headers = headers.newBuilder()
.set("authority", mainUrl)
.set("accept", "application/json, text/javascript, */*; q=0.01")
.set("accept-language", "es-MX,es-419;q=0.9,es;q=0.8,en;q=0.7")
.set("sec-ch-ua", "\"Chromium\";v=\"106\", \"Google Chrome\";v=\"106\", \"Not;A=Brand\";v=\"99\"")
.set("sec-ch-ua-mobile", "?0")
.set("sec-ch-ua-platform", "Windows")
.set("sec-fetch-dest", "empty")
.set("sec-fetch-mode", "cors")
.set("sec-fetch-site", "same-origin")
.set("x-requested-with", "XMLHttpRequest")
.build()
val token = url.substringAfter("/embed.html#")
val urlRequest = "https://$mainUrl/details.php?v=$token"
val response = client.newCall(GET(urlRequest, headers = headers)).execute().asJsoup()
val bodyText = response.select("body").text()
val json = json.decodeFromString<JsonObject>(bodyText)
val status = json["status"]!!.jsonPrimitive!!.content
val file = json["file"]!!.jsonPrimitive!!.content
if (status == "200") { videoList.add(Video(file, "$prefix Tomatomatela", file, headers = null)) }
} catch (_: Exception) { }
}
if (embedUrl.contains("yourupload")) { if (embedUrl.contains("yourupload")) {
val videos = YourUploadExtractor(client).videoFromUrl(url, headers = headers) val videos = YourUploadExtractor(client).videoFromUrl(url, headers = headers)
videoList.addAll(videos) videoList.addAll(videos)

View file

@ -1,7 +1,7 @@
ext { ext {
extName = 'MetroSeries' extName = 'MetroSeries'
extClass = '.MetroSeries' extClass = '.MetroSeries'
extVersionCode = 9 extVersionCode = 10
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View file

@ -129,7 +129,7 @@ class MetroSeries : ConfigurableAnimeSource, AnimeHttpSource() {
return episodes return episodes
} }
private fun getDetailSeason(element: org.jsoup.nodes.Element, objectNumber: String, referer: String): IntRange { private fun getDetailSeason(element: Element, objectNumber: String, referer: String): IntRange {
try { try {
val post = element.attr("data-post") val post = element.attr("data-post")
val season = element.attr("data-season") val season = element.attr("data-season")
@ -189,6 +189,16 @@ class MetroSeries : ConfigurableAnimeSource, AnimeHttpSource() {
val videoList = mutableListOf<Video>() val videoList = mutableListOf<Video>()
val termId = document.select("#option-players").attr("data-term") val termId = document.select("#option-players").attr("data-term")
document.select(".player-options-list li a").forEach { document.select(".player-options-list li a").forEach {
val prefix = runCatching {
val lang = it.select(".option").text().lowercase()
when {
lang.contains("latino") -> "[LAT]"
lang.contains("castellano") -> "[CAST]"
lang.contains("sub") -> "[SUB]"
else -> ""
}
}.getOrDefault("")
val ide = it.attr("data-opt") val ide = it.attr("data-opt")
val formBody = FormBody.Builder() val formBody = FormBody.Builder()
.add("action", "action_player_series") .add("action", "action_player_series")
@ -217,29 +227,29 @@ class MetroSeries : ConfigurableAnimeSource, AnimeHttpSource() {
val key = src.split("/").last() val key = src.split("/").last()
src = "https://fastream.to/embed-$key.html" src = "https://fastream.to/embed-$key.html"
} }
FastreamExtractor(client, headers).videosFromUrl(src, needsSleep = false).also(videoList::addAll) FastreamExtractor(client, headers).videosFromUrl(src, needsSleep = false, prefix = "$prefix Fastream:").also(videoList::addAll)
} }
if (src.contains("upstream")) { if (src.contains("upstream")) {
UpstreamExtractor(client).videosFromUrl(src).let { videoList.addAll(it) } UpstreamExtractor(client).videosFromUrl(src, prefix = "$prefix ").let { videoList.addAll(it) }
} }
if (src.contains("yourupload")) { if (src.contains("yourupload")) {
YourUploadExtractor(client).videoFromUrl(src, headers).let { videoList.addAll(it) } YourUploadExtractor(client).videoFromUrl(src, headers, prefix = "$prefix ").let { videoList.addAll(it) }
} }
if (src.contains("voe")) { if (src.contains("voe")) {
VoeExtractor(client).videosFromUrl(src).also(videoList::addAll) VoeExtractor(client).videosFromUrl(src, prefix = "$prefix ").also(videoList::addAll)
} }
if (src.contains("wishembed") || src.contains("streamwish") || src.contains("wish")) { if (src.contains("wishembed") || src.contains("streamwish") || src.contains("wish")) {
StreamWishExtractor(client, headers).videosFromUrl(src) { "StreamWish:$it" }.also(videoList::addAll) StreamWishExtractor(client, headers).videosFromUrl(src) { "$prefix StreamWish:$it" }.also(videoList::addAll)
} }
if (src.contains("mp4upload")) { if (src.contains("mp4upload")) {
Mp4uploadExtractor(client).videosFromUrl(src, headers).let { videoList.addAll(it) } Mp4uploadExtractor(client).videosFromUrl(src, headers, prefix = "$prefix ").let { videoList.addAll(it) }
} }
if (src.contains("burst")) { if (src.contains("burst")) {
BurstCloudExtractor(client).videoFromUrl(src, headers = headers).let { videoList.addAll(it) } BurstCloudExtractor(client).videoFromUrl(src, headers = headers, prefix = "$prefix ").let { videoList.addAll(it) }
} }
if (src.contains("filemoon") || src.contains("moonplayer")) { if (src.contains("filemoon") || src.contains("moonplayer")) {
FilemoonExtractor(client).videosFromUrl(src, headers = headers, prefix = "Filemoon:").let { videoList.addAll(it) } FilemoonExtractor(client).videosFromUrl(src, headers = headers, prefix = "$prefix Filemoon:").let { videoList.addAll(it) }
} }
} catch (_: Exception) {} } catch (_: Exception) {}
} }

View file

@ -1,7 +1,7 @@
ext { ext {
extName = 'Pelisplushd' extName = 'Pelisplushd'
extClass = '.PelisplushdFactory' extClass = '.PelisplushdFactory'
extVersionCode = 55 extVersionCode = 56
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View file

@ -28,7 +28,6 @@ import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
import eu.kanade.tachiyomi.lib.youruploadextractor.YourUploadExtractor import eu.kanade.tachiyomi.lib.youruploadextractor.YourUploadExtractor
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
@ -59,6 +58,9 @@ open class Pelisplushd(override val name: String, override val baseUrl: String)
"Upload", "BurstCloud", "Upstream", "StreamTape", "Amazon", "Upload", "BurstCloud", "Upstream", "StreamTape", "Amazon",
"Fastream", "Filemoon", "StreamWish", "Okru", "Streamlare", "Fastream", "Filemoon", "StreamWish", "Okru", "Streamlare",
) )
private val REGEX_LINK = "https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)".toRegex()
private val REGEX_VIDEO_OPTS = "'(https?://[^']*)'".toRegex()
} }
override fun popularAnimeSelector(): String = "div.Posters a.Posters-link" override fun popularAnimeSelector(): String = "div.Posters a.Posters-link"
@ -105,20 +107,23 @@ open class Pelisplushd(override val name: String, override val baseUrl: String)
override fun videoListParse(response: Response): List<Video> { override fun videoListParse(response: Response): List<Video> {
val document = response.asJsoup() val document = response.asJsoup()
val videoList = mutableListOf<Video>() val videoList = mutableListOf<Video>()
val data = document.selectFirst("script:containsData(video[1] = )")?.data() ?: return emptyList()
val data = document.selectFirst("script:containsData(video[1] = )")?.data() REGEX_VIDEO_OPTS.findAll(data).map { it.groupValues[1] }.forEach { opt ->
val apiUrl = data?.substringAfter("video[1] = '", "")?.substringBefore("';", "") val apiResponse = client.newCall(GET(opt)).execute()
val alternativeServers = document.select("ul.TbVideoNv.nav.nav-tabs li:not(:first-child)")
if (!apiUrl.isNullOrEmpty()) {
val apiResponse = client.newCall(GET(apiUrl)).execute()
val docResponse = apiResponse.asJsoup() val docResponse = apiResponse.asJsoup()
if (apiResponse.isSuccessful) { if (apiResponse.isSuccessful) {
val regIsUrl = "https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)".toRegex() val encryptedList = if (docResponse.select("iframe").any()) {
val encryptedList = docResponse.select("#PlayerDisplay div[class*=\"OptionsLangDisp\"] div[class*=\"ODDIV\"] div[class*=\"OD\"] li") listOf(docResponse.select("iframe").attr("src"))
} else {
docResponse.select("#PlayerDisplay div[class*=\"OptionsLangDisp\"] div[class*=\"ODDIV\"] div[class*=\"OD\"] li")
.map { it.attr("onclick") }
}
encryptedList.flatMap { encryptedList.flatMap {
runCatching { runCatching {
val url = it.attr("onclick") val url = it.substringAfter("go_to_player('")
.substringAfter("go_to_player('")
.substringAfter("go_to_playerVast('") .substringAfter("go_to_playerVast('")
.substringBefore("?cover_url=") .substringBefore("?cover_url=")
.substringBefore("')") .substringBefore("')")
@ -128,7 +133,7 @@ open class Pelisplushd(override val name: String, override val baseUrl: String)
.substringBefore("?thumb=") .substringBefore("?thumb=")
.substringBefore("#poster=") .substringBefore("#poster=")
val realUrl = if (!regIsUrl.containsMatchIn(url)) { val realUrl = if (!REGEX_LINK.containsMatchIn(url)) {
String(Base64.decode(url, Base64.DEFAULT)) String(Base64.decode(url, Base64.DEFAULT))
} else if (url.contains("?data=")) { } else if (url.contains("?data=")) {
val apiPageSoup = client.newCall(GET(url)).execute().asJsoup() val apiPageSoup = client.newCall(GET(url)).execute().asJsoup()
@ -142,27 +147,6 @@ open class Pelisplushd(override val name: String, override val baseUrl: String)
}.also(videoList::addAll) }.also(videoList::addAll)
} }
} }
// verifier for old series
if (!apiUrl.isNullOrEmpty() && !apiUrl.contains("/video/") || alternativeServers.any()) {
document.select("ul.TbVideoNv.nav.nav-tabs li").parallelCatchingFlatMapBlocking { id ->
val serverName = id.select("a").text().lowercase()
val serverId = id.attr("data-id")
var serverUrl = data?.substringAfter("video[$serverId] = '", "")?.substringBefore("';", "")
if (serverUrl != null && serverUrl.contains("api.mycdn.moe")) {
val urlId = serverUrl.substringAfter("id=")
serverUrl = when (serverName) {
"sbfast" -> { "https://sbfull.com/e/$urlId" }
"plusto" -> { "https://owodeuwu.xyz/v/$urlId" }
"doodstream" -> { "https://dood.to/e/$urlId" }
"upload", "uqload" -> { "https://uqload.com/embed-$urlId.html" }
else -> ""
}
}
serverVideoResolver(serverUrl ?: "")
}.also(videoList::addAll)
}
return videoList return videoList
} }
@ -206,8 +190,8 @@ open class Pelisplushd(override val name: String, override val baseUrl: String)
StreamWishExtractor(client, docHeaders).videosFromUrl(url, videoNameGen = { "StreamWish:$it" }) StreamWishExtractor(client, docHeaders).videosFromUrl(url, videoNameGen = { "StreamWish:$it" })
} }
embedUrl.contains("doodstream") || embedUrl.contains("dood.") || embedUrl.contains("ds2play") || embedUrl.contains("doods.") -> { embedUrl.contains("doodstream") || embedUrl.contains("dood.") || embedUrl.contains("ds2play") || embedUrl.contains("doods.") -> {
val url2 = url.replace("https://doodstream.com/e/", "https://dood.to/e/") val url2 = url.replace("https://doodstream.com/e/", "https://d0000d.com/e/")
listOf(DoodExtractor(client).videoFromUrl(url2, "DoodStream", false)!!) listOf(DoodExtractor(client).videoFromUrl(url2, "DoodStream")!!)
} }
embedUrl.contains("streamlare") -> StreamlareExtractor(client).videosFromUrl(url) embedUrl.contains("streamlare") -> StreamlareExtractor(client).videosFromUrl(url)
embedUrl.contains("yourupload") || embedUrl.contains("upload") -> YourUploadExtractor(client).videoFromUrl(url, headers = headers) embedUrl.contains("yourupload") || embedUrl.contains("upload") -> YourUploadExtractor(client).videoFromUrl(url, headers = headers)

View file

@ -83,26 +83,20 @@ class Pelisplusto(override val name: String, override val baseUrl: String) : Pel
val episode = SEpisode.create().apply { val episode = SEpisode.create().apply {
episode_number = 1F episode_number = 1F
name = "PELÍCULA" name = "PELÍCULA"
setUrlWithoutDomain(response.request.url.toString()) setUrlWithoutDomain(jsoup.location())
} }
episodes.add(episode) episodes.add(episode)
} else { } else {
var jsonscript = "" val jsonStrData = jsoup.selectFirst("script:containsData(const seasonUrl =)")?.data() ?: return emptyList()
jsoup.select("script[type=text/javascript]").mapNotNull { script -> val jsonParse = json.decodeFromString<JsonObject>(jsonStrData.substringAfter("seasonsJson = ").substringBefore(";"))
val ssRegex = Regex("(?i)seasons")
val ss = if (script.data().contains(ssRegex)) script.data() else ""
val swaa = ss.substringAfter("seasonsJson = ").substringBefore(";")
jsonscript = swaa
}
val jsonParse = json.decodeFromString<JsonObject>(jsonscript)
var index = 0 var index = 0
jsonParse.entries.map { jsonParse.entries.map {
it.value.jsonArray.reversed().map { element -> it.value.jsonArray.reversed().map { element ->
index += 1 index += 1
val jsonElement = element!!.jsonObject val jsonElement = element.jsonObject
val season = jsonElement["season"]!!.jsonPrimitive!!.content val season = jsonElement["season"]!!.jsonPrimitive.content
val title = jsonElement["title"]!!.jsonPrimitive!!.content val title = jsonElement["title"]!!.jsonPrimitive.content
val ep = jsonElement["episode"]!!.jsonPrimitive!!.content val ep = jsonElement["episode"]!!.jsonPrimitive.content
val episode = SEpisode.create().apply { val episode = SEpisode.create().apply {
episode_number = index.toFloat() episode_number = index.toFloat()
name = "T$season - E$ep - $title" name = "T$season - E$ep - $title"