diff --git a/lib/dood-extractor/src/main/java/eu/kanade/tachiyomi/lib/doodextractor/DoodExtractor.kt b/lib/dood-extractor/src/main/java/eu/kanade/tachiyomi/lib/doodextractor/DoodExtractor.kt index 86ca8280..2d2c460c 100644 --- a/lib/dood-extractor/src/main/java/eu/kanade/tachiyomi/lib/doodextractor/DoodExtractor.kt +++ b/lib/dood-extractor/src/main/java/eu/kanade/tachiyomi/lib/doodextractor/DoodExtractor.kt @@ -34,7 +34,7 @@ class DoodExtractor(private val client: OkHttpClient) { ), ).execute().body.string() 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() } diff --git a/src/es/cuevana/build.gradle b/src/es/cuevana/build.gradle index 59228a93..caa81a5b 100644 --- a/src/es/cuevana/build.gradle +++ b/src/es/cuevana/build.gradle @@ -1,7 +1,7 @@ ext { extName = 'Cuevana' extClass = '.CuevanaFactory' - extVersionCode = 31 + extVersionCode = 32 } apply from: "$rootDir/common.gradle" diff --git a/src/es/cuevana/src/eu/kanade/tachiyomi/animeextension/es/cuevana/CuevanaEu.kt b/src/es/cuevana/src/eu/kanade/tachiyomi/animeextension/es/cuevana/CuevanaEu.kt index bbd3b01c..1fb5b789 100644 --- a/src/es/cuevana/src/eu/kanade/tachiyomi/animeextension/es/cuevana/CuevanaEu.kt +++ b/src/es/cuevana/src/eu/kanade/tachiyomi/animeextension/es/cuevana/CuevanaEu.kt @@ -6,6 +6,7 @@ import androidx.preference.ListPreference import androidx.preference.PreferenceScreen 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.Server import eu.kanade.tachiyomi.animeextension.es.cuevana.models.Videos import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource 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.network.GET import eu.kanade.tachiyomi.util.asJsoup -import eu.kanade.tachiyomi.util.parallelMapBlocking import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.jsonPrimitive import okhttp3.Request import okhttp3.Response import org.jsoup.nodes.Document @@ -35,6 +33,7 @@ import org.jsoup.nodes.Element import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import java.text.SimpleDateFormat +import java.util.ArrayList 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> { val videoList = mutableListOf<Video>() - videos?.latino?.parallelMapBlocking { + videos?.latino?.forEach { try { val body = client.newCall(GET(it.result!!)).execute().asJsoup() val url = body.selectFirst("script:containsData(var message)")?.data()?.substringAfter("var url = '")?.substringBefore("'") ?: "" loadExtractor(url, "[LAT]").let { videoList.addAll(it) } } catch (_: Exception) { } } - videos?.spanish?.map { + videos?.spanish?.forEach { try { val body = client.newCall(GET(it.result!!)).execute().asJsoup() val url = body.selectFirst("script:containsData(var message)")?.data()?.substringAfter("var url = '")?.substringBefore("'") ?: "" loadExtractor(url, "[CAST]").let { videoList.addAll(it) } } catch (_: Exception) { } } - videos?.english?.map { + videos?.english?.forEach { try { val body = client.newCall(GET(it.result!!)).execute().asJsoup() val url = body.selectFirst("script:containsData(var message)")?.data()?.substringAfter("var url = '")?.substringBefore("'") ?: "" loadExtractor(url, "[ENG]").let { videoList.addAll(it) } } catch (_: Exception) { } } - videos?.japanese?.map { + videos?.japanese?.forEach { val body = client.newCall(GET(it.result!!)).execute().asJsoup() val url = body.selectFirst("script:containsData(var message)")?.data()?.substringAfter("var url = '")?.substringBefore("'") ?: "" 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> { val videoList = mutableListOf<Video>() 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")) { val videos = YourUploadExtractor(client).videoFromUrl(url, headers = headers) videoList.addAll(videos) diff --git a/src/es/metroseries/build.gradle b/src/es/metroseries/build.gradle index 44556510..affe0d95 100644 --- a/src/es/metroseries/build.gradle +++ b/src/es/metroseries/build.gradle @@ -1,7 +1,7 @@ ext { extName = 'MetroSeries' extClass = '.MetroSeries' - extVersionCode = 9 + extVersionCode = 10 } apply from: "$rootDir/common.gradle" diff --git a/src/es/metroseries/src/eu/kanade/tachiyomi/animeextension/es/metroseries/MetroSeries.kt b/src/es/metroseries/src/eu/kanade/tachiyomi/animeextension/es/metroseries/MetroSeries.kt index cffb3e52..910404a4 100644 --- a/src/es/metroseries/src/eu/kanade/tachiyomi/animeextension/es/metroseries/MetroSeries.kt +++ b/src/es/metroseries/src/eu/kanade/tachiyomi/animeextension/es/metroseries/MetroSeries.kt @@ -129,7 +129,7 @@ class MetroSeries : ConfigurableAnimeSource, AnimeHttpSource() { 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 { val post = element.attr("data-post") val season = element.attr("data-season") @@ -189,6 +189,16 @@ class MetroSeries : ConfigurableAnimeSource, AnimeHttpSource() { val videoList = mutableListOf<Video>() val termId = document.select("#option-players").attr("data-term") 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 formBody = FormBody.Builder() .add("action", "action_player_series") @@ -217,29 +227,29 @@ class MetroSeries : ConfigurableAnimeSource, AnimeHttpSource() { val key = src.split("/").last() 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")) { - UpstreamExtractor(client).videosFromUrl(src).let { videoList.addAll(it) } + UpstreamExtractor(client).videosFromUrl(src, prefix = "$prefix ").let { videoList.addAll(it) } } 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")) { - 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")) { - 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")) { - Mp4uploadExtractor(client).videosFromUrl(src, headers).let { videoList.addAll(it) } + Mp4uploadExtractor(client).videosFromUrl(src, headers, prefix = "$prefix ").let { videoList.addAll(it) } } 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")) { - 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) {} } diff --git a/src/es/pelisplushd/build.gradle b/src/es/pelisplushd/build.gradle index 46735d89..04f52e34 100644 --- a/src/es/pelisplushd/build.gradle +++ b/src/es/pelisplushd/build.gradle @@ -1,7 +1,7 @@ ext { extName = 'Pelisplushd' extClass = '.PelisplushdFactory' - extVersionCode = 55 + extVersionCode = 56 } apply from: "$rootDir/common.gradle" diff --git a/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplushd.kt b/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplushd.kt index 1b42837c..d4af36af 100644 --- a/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplushd.kt +++ b/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplushd.kt @@ -28,7 +28,6 @@ import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor import eu.kanade.tachiyomi.lib.youruploadextractor.YourUploadExtractor import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.util.asJsoup -import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.Request import okhttp3.Response @@ -59,6 +58,9 @@ open class Pelisplushd(override val name: String, override val baseUrl: String) "Upload", "BurstCloud", "Upstream", "StreamTape", "Amazon", "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" @@ -105,20 +107,23 @@ open class Pelisplushd(override val name: String, override val baseUrl: String) override fun videoListParse(response: Response): List<Video> { val document = response.asJsoup() val videoList = mutableListOf<Video>() + val data = document.selectFirst("script:containsData(video[1] = )")?.data() ?: return emptyList() - val data = document.selectFirst("script:containsData(video[1] = )")?.data() - val apiUrl = data?.substringAfter("video[1] = '", "")?.substringBefore("';", "") - val alternativeServers = document.select("ul.TbVideoNv.nav.nav-tabs li:not(:first-child)") - if (!apiUrl.isNullOrEmpty()) { - val apiResponse = client.newCall(GET(apiUrl)).execute() + REGEX_VIDEO_OPTS.findAll(data).map { it.groupValues[1] }.forEach { opt -> + val apiResponse = client.newCall(GET(opt)).execute() val docResponse = apiResponse.asJsoup() + 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 = docResponse.select("#PlayerDisplay div[class*=\"OptionsLangDisp\"] div[class*=\"ODDIV\"] div[class*=\"OD\"] li") + val encryptedList = if (docResponse.select("iframe").any()) { + 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 { runCatching { - val url = it.attr("onclick") - .substringAfter("go_to_player('") + val url = it.substringAfter("go_to_player('") .substringAfter("go_to_playerVast('") .substringBefore("?cover_url=") .substringBefore("')") @@ -128,7 +133,7 @@ open class Pelisplushd(override val name: String, override val baseUrl: String) .substringBefore("?thumb=") .substringBefore("#poster=") - val realUrl = if (!regIsUrl.containsMatchIn(url)) { + val realUrl = if (!REGEX_LINK.containsMatchIn(url)) { String(Base64.decode(url, Base64.DEFAULT)) } else if (url.contains("?data=")) { 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) } } - - // 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 } @@ -206,8 +190,8 @@ open class Pelisplushd(override val name: String, override val baseUrl: String) StreamWishExtractor(client, docHeaders).videosFromUrl(url, videoNameGen = { "StreamWish:$it" }) } embedUrl.contains("doodstream") || embedUrl.contains("dood.") || embedUrl.contains("ds2play") || embedUrl.contains("doods.") -> { - val url2 = url.replace("https://doodstream.com/e/", "https://dood.to/e/") - listOf(DoodExtractor(client).videoFromUrl(url2, "DoodStream", false)!!) + val url2 = url.replace("https://doodstream.com/e/", "https://d0000d.com/e/") + listOf(DoodExtractor(client).videoFromUrl(url2, "DoodStream")!!) } embedUrl.contains("streamlare") -> StreamlareExtractor(client).videosFromUrl(url) embedUrl.contains("yourupload") || embedUrl.contains("upload") -> YourUploadExtractor(client).videoFromUrl(url, headers = headers) diff --git a/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplusto.kt b/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplusto.kt index fbb6655e..199d779e 100644 --- a/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplusto.kt +++ b/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplusto.kt @@ -83,26 +83,20 @@ class Pelisplusto(override val name: String, override val baseUrl: String) : Pel val episode = SEpisode.create().apply { episode_number = 1F name = "PELĂCULA" - setUrlWithoutDomain(response.request.url.toString()) + setUrlWithoutDomain(jsoup.location()) } episodes.add(episode) } else { - var jsonscript = "" - jsoup.select("script[type=text/javascript]").mapNotNull { script -> - 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) + val jsonStrData = jsoup.selectFirst("script:containsData(const seasonUrl =)")?.data() ?: return emptyList() + val jsonParse = json.decodeFromString<JsonObject>(jsonStrData.substringAfter("seasonsJson = ").substringBefore(";")) var index = 0 jsonParse.entries.map { it.value.jsonArray.reversed().map { element -> index += 1 - val jsonElement = element!!.jsonObject - val season = jsonElement["season"]!!.jsonPrimitive!!.content - val title = jsonElement["title"]!!.jsonPrimitive!!.content - val ep = jsonElement["episode"]!!.jsonPrimitive!!.content + val jsonElement = element.jsonObject + val season = jsonElement["season"]!!.jsonPrimitive.content + val title = jsonElement["title"]!!.jsonPrimitive.content + val ep = jsonElement["episode"]!!.jsonPrimitive.content val episode = SEpisode.create().apply { episode_number = index.toFloat() name = "T$season - E$ep - $title"