fix(es/pelisplushd): Fixes to all sources (#1988)

This commit is contained in:
imper1aldev
2023-07-31 02:41:06 -06:00
committed by GitHub
parent 7609b54cdc
commit bf7115a533
8 changed files with 210 additions and 23 deletions

View File

@ -5,7 +5,7 @@ ext {
extName = 'Pelisplushd'
pkgNameSuffix = 'es.pelisplushd'
extClass = '.PelisplushdFactory'
extVersionCode = 38
extVersionCode = 39
libVersion = '13'
}
@ -18,6 +18,7 @@ dependencies {
implementation(project(':lib-dood-extractor'))
implementation(project(':lib-voe-extractor'))
implementation(project(':lib-okru-extractor'))
implementation "dev.datlag.jsunpacker:jsunpacker:1.0.1"
}
apply from: "$rootDir/common.gradle"

View File

@ -5,6 +5,7 @@ import android.content.SharedPreferences
import android.util.Base64
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.es.pelisplushd.extractors.StreamWishExtractor
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
@ -13,6 +14,7 @@ import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.lib.doodextractor.DoodExtractor
import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
import eu.kanade.tachiyomi.lib.streamlareextractor.StreamlareExtractor
import eu.kanade.tachiyomi.lib.streamsbextractor.StreamSBExtractor
import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
@ -92,31 +94,30 @@ open class Pelisplushd(override val name: String, override val baseUrl: String)
val apiUrl = data.substringAfter("video[1] = '", "").substringBefore("';", "")
val alternativeServers = document.select("ul.TbVideoNv.nav.nav-tabs li:not(:first-child)")
if (apiUrl.isNotEmpty()) {
val domainRegex = Regex("^(?:https?:\\/\\/)?(?:[^@\\/\\n]+@)?(?:www\\.)?([^:\\/?\\n]+)")
val domainUrl = domainRegex.findAll(apiUrl).firstOrNull()?.value
// val domainRegex = Regex("^(?:https?:\\/\\/)?(?:[^@\\/\\n]+@)?(?:www\\.)?([^:\\/?\\n]+)")
// val domainUrl = domainRegex.findAll(apiUrl).firstOrNull()?.value
val apiResponse = client.newCall(GET(apiUrl)).execute().asJsoup()
val encryptedList = apiResponse!!.select("#PlayerDisplay div[class*=\"OptionsLangDisp\"] div[class*=\"ODDIV\"] div[class*=\"OD\"] li[data-r]")
val decryptedList = apiResponse!!.select("#PlayerDisplay div[class*=\"OptionsLangDisp\"] div[class*=\"ODDIV\"] div[class*=\"OD\"] li:not([data-r])")
val encryptedList = apiResponse!!.select("#PlayerDisplay div[class*=\"OptionsLangDisp\"] div[class*=\"ODDIV\"] div[class*=\"OD\"] li")
val regIsUrl = "https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)".toRegex()
encryptedList.forEach {
val url = String(Base64.decode(it.attr("data-r"), Base64.DEFAULT))
val server = it.select("span").text()
serverVideoResolver(url, server)?.forEach { video -> videoList.add(video) }
}
decryptedList.forEach {
val server = it.select("span").text()
val url = it.attr("onclick")
var url = it.attr("onclick")
.substringAfter("go_to_player('")
.substringBefore("?cover_url=")
.substringBefore("')")
.substringBefore("',")
.substringBefore("?poster")
.substringBefore("#poster=")
val regIsUrl = "https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)".toRegex()
if (regIsUrl.containsMatchIn(url)) {
if (!regIsUrl.containsMatchIn(url)) {
url = String(Base64.decode(url, Base64.DEFAULT))
}
if (!url.contains("?data=")) {
serverVideoResolver(url, server)?.forEach { video -> videoList.add(video) }
} else {
val apiPageSoup = client.newCall(GET("$domainUrl/player/?id=$url")).execute().asJsoup()
val apiPageSoup = client.newCall(GET(url)).execute().asJsoup()
val realUrl = apiPageSoup.selectFirst("iframe")?.attr("src")
if (realUrl != null) {
serverVideoResolver(realUrl, server)?.forEach { video -> videoList.add(video) }
@ -195,6 +196,13 @@ open class Pelisplushd(override val name: String, override val baseUrl: String)
DoodExtractor(client).videoFromUrl(url2, "DoodStream", false)?.let { videoList.add(it) }
} else if (server.lowercase() == "upload") {
return YourUploadExtractor(client).videoFromUrl(url, headers = headers)
} else if (server.lowercase().contains("streamwish")) {
val docHeaders = headers.newBuilder()
.add("Referer", "$baseUrl/")
.build()
StreamWishExtractor(client, docHeaders).videosFromUrl(url, "StreamWish ")
} else if (server.contains("filemoon") || server.contains("moonplayer")) {
FilemoonExtractor(client).videosFromUrl(url, headers = headers).also(videoList::addAll)
}
} catch (_: Exception) {}
return videoList

View File

@ -2,6 +2,9 @@ package eu.kanade.tachiyomi.animeextension.es.pelisplushd
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.es.pelisplushd.extractors.StreamHideExtractor
import eu.kanade.tachiyomi.animeextension.es.pelisplushd.extractors.StreamWishExtractor
import eu.kanade.tachiyomi.animeextension.es.pelisplushd.extractors.UqloadExtractor
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
import eu.kanade.tachiyomi.animesource.model.SAnime
@ -16,7 +19,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 kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonPrimitive
@ -190,6 +192,18 @@ class Pelisplusph(override val name: String, override val baseUrl: String) : Pel
if (embedUrl.contains("streamlare")) {
videoList.addAll(StreamlareExtractor(client).videosFromUrl(url))
}
if (embedUrl.contains("streamwish")) {
val docHeaders = headers.newBuilder()
.add("Referer", "$baseUrl/")
.build()
StreamWishExtractor(client, docHeaders).videosFromUrl(url, "StreamWish ")
}
if (embedUrl.contains("ahvsh") || embedUrl.contains("streamhide")) {
StreamHideExtractor(client).videosFromUrl(url, "StreamHide")
}
if (embedUrl.contains("uqload")) {
UqloadExtractor(client).videosFromUrl(url, headers)
}
return videoList
}

View File

@ -1,7 +1,12 @@
package eu.kanade.tachiyomi.animeextension.es.pelisplushd
import android.util.Base64
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.es.pelisplushd.extractors.StreamHideExtractor
import eu.kanade.tachiyomi.animeextension.es.pelisplushd.extractors.StreamWishExtractor
import eu.kanade.tachiyomi.animeextension.es.pelisplushd.extractors.UqloadExtractor
import eu.kanade.tachiyomi.animeextension.es.pelisplushd.extractors.VudeoExtractor
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
import eu.kanade.tachiyomi.animesource.model.SAnime
@ -105,16 +110,35 @@ class Pelisplusto(override val name: String, override val baseUrl: String) : Pel
}
}
private fun fetchUrls(text: String?): List<String> {
if (text.isNullOrEmpty()) return listOf()
val linkRegex = "(http|ftp|https):\\/\\/([\\w_-]+(?:(?:\\.[\\w_-]+)+))([\\w.,@?^=%&:\\/~+#-]*[\\w@?^=%&\\/~+#-])".toRegex()
return linkRegex.findAll(text).map { it.value.trim().removeSurrounding("\"") }.toList()
}
override fun videoListParse(response: Response): List<Video> {
val document = response.asJsoup()
val videoList = mutableListOf<Video>()
document.select(".bg-tabs li").map { it ->
val link = it.attr("data-server")
.replace("https://sblanh.com", "https://watchsb.com")
.replace(Regex("([a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)=https:\\/\\/ww3.pelisplus.to.*"), "")
document.select(".bg-tabs ul li").map { it ->
val url = String(Base64.decode(it.attr("data-server"), Base64.DEFAULT))
if (url.contains("/player/")) {
try {
val script = client.newCall(GET(url)).execute().asJsoup().selectFirst("script:containsData(window.onload)")!!.data()
fetchUrls(script).map {
val link = it.replace("https://sblanh.com", "https://lvturbo.com")
.replace(Regex("([a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)=https:\\/\\/ww3.pelisplus.to.*"), "")
loadExtractor(link).let { videos ->
videoList.addAll(videos)
}
}
} catch (_: Exception) {}
} else {
val link = url.replace("https://sblanh.com", "https://lvturbo.com")
.replace(Regex("([a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)=https:\\/\\/ww3.pelisplus.to.*"), "")
loadExtractor(link).let { videos ->
videoList.addAll(videos)
loadExtractor(link).let { videos ->
videoList.addAll(videos)
}
}
}
return videoList
@ -146,7 +170,7 @@ class Pelisplusto(override val name: String, override val baseUrl: String) : Pel
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 (e: Exception) { }
} catch (_: Exception) { }
}
if (embedUrl.contains("yourupload")) {
val videos = YourUploadExtractor(client).videoFromUrl(url, headers = headers)
@ -185,6 +209,21 @@ class Pelisplusto(override val name: String, override val baseUrl: String) : Pel
if (embedUrl.contains("streamlare")) {
videoList.addAll(StreamlareExtractor(client).videosFromUrl(url))
}
if (embedUrl.contains("uqload")) {
UqloadExtractor(client).videosFromUrl(url, headers)
}
if (embedUrl.contains("streamwish")) {
val docHeaders = headers.newBuilder()
.add("Referer", "$baseUrl/")
.build()
StreamWishExtractor(client, docHeaders).videosFromUrl(url, "StreamWish ")
}
if (embedUrl.contains("ahvsh") || embedUrl.contains("streamhide")) {
StreamHideExtractor(client).videosFromUrl(url, "StreamHide")
}
if (embedUrl.contains("vudeo")) {
VudeoExtractor(client).videosFromUrl(url)
}
return videoList
}

View File

@ -0,0 +1,34 @@
package eu.kanade.tachiyomi.animeextension.es.pelisplushd.extractors
import eu.kanade.tachiyomi.animesource.model.Track
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import okhttp3.OkHttpClient
class StreamHideExtractor(private val client: OkHttpClient) {
// from nineanime / ask4movie FilemoonExtractor
private val subtitleRegex = Regex("""#EXT-X-MEDIA:TYPE=SUBTITLES.*?NAME="(.*?)".*?URI="(.*?)"""")
fun videosFromUrl(url: String, name: String): List<Video> {
val page = client.newCall(GET(url)).execute().body.string()
val unpacked = JsUnpacker(page).unpack() ?: return emptyList()
val playlistUrl = unpacked.substringAfter("sources:")
.substringAfter("file:\"") // StreamHide
.substringAfter("src:\"") // StreamVid
.substringBefore('"')
val playlistData = client.newCall(GET(playlistUrl)).execute().body.string()
val subs = subtitleRegex.findAll(playlistData).map {
val urlPart = it.groupValues[2]
val subUrl = when {
!urlPart.startsWith("https:") ->
playlistUrl.substringBeforeLast("/") + "/$urlPart"
else -> urlPart
}
Track(subUrl, it.groupValues[1])
}.toList()
// The playlist usually only have one video quality.
return listOf(Video(playlistUrl, name, playlistUrl, subtitleTracks = subs))
}
}

View File

@ -0,0 +1,45 @@
package eu.kanade.tachiyomi.animeextension.es.pelisplushd.extractors
import dev.datlag.jsunpacker.JsUnpacker
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
class StreamWishExtractor(private val client: OkHttpClient, private val headers: Headers) {
fun videosFromUrl(url: String, prefix: String): List<Video> {
val videoList = mutableListOf<Video>()
val doc = client.newCall(GET(url, headers = headers)).execute().asJsoup()
val jsEval = doc.selectFirst("script:containsData(m3u8)")?.data() ?: "UwU"
val masterUrl = JsUnpacker.unpackAndCombine(jsEval)
?.substringAfter("source")
?.substringAfter("file:\"")
?.substringBefore("\"")
?: return emptyList()
val playlistHeaders = headers.newBuilder()
.add("Accept", "*/*")
.add("Host", masterUrl.toHttpUrl().host)
.add("Origin", "https://${url.toHttpUrl().host}")
.set("Referer", "https://${url.toHttpUrl().host}/")
.build()
val masterBase = "https://${masterUrl.toHttpUrl().host}${masterUrl.toHttpUrl().encodedPath}"
.substringBeforeLast("/") + "/"
val masterPlaylist = client.newCall(
GET(masterUrl, headers = playlistHeaders),
).execute().body.string()
val separator = "#EXT-X-STREAM-INF:"
masterPlaylist.substringAfter(separator).split(separator).forEach {
val quality = prefix + it.substringAfter("RESOLUTION=").substringAfter("x").substringBefore(",") + "p "
val videoUrl = masterBase + it.substringAfter("\n").substringBefore("\n")
videoList.add(Video(videoUrl, quality, videoUrl, headers = playlistHeaders))
}
return videoList
}
}

View File

@ -0,0 +1,26 @@
package eu.kanade.tachiyomi.animeextension.es.pelisplushd.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
class UqloadExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String, headers: Headers, quality: String = "Uqload"): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
val check = document.selectFirst("script:containsData(sources)")!!.data()
val videoUrl = check.substringAfter("sources: [\"").substringBefore("\"")
val videoHeaders = headers.newBuilder()
.add("Accept", "video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5")
.add("Host", videoUrl.toHttpUrl().host)
.add("Referer", "https://uqload.co/")
.build()
return if (check.contains("sources")) {
listOf(Video(url, quality, videoUrl, headers = videoHeaders))
} else {
emptyList()
}
}
}

View File

@ -0,0 +1,20 @@
package eu.kanade.tachiyomi.animeextension.es.pelisplushd.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.OkHttpClient
class VudeoExtractor(private val client: OkHttpClient) {
fun videosFromUrl(url: String): List<Video> {
val document = client.newCall(GET(url)).execute().asJsoup()
val videoList = mutableListOf<Video>()
document.select("script:containsData(sources: [)").forEach { script ->
val videoUrl = script.data().substringAfter("sources: [").substringBefore("]").replace("\"", "").split(",")
videoUrl.forEach {
videoList.add(Video(it, "Vudeo", it, headers = Headers.headersOf("referer", "https://vudeo.net/")))
}
}
return videoList
}
}