diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/AsianLoad.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/AsianLoad.kt deleted file mode 100644 index 70e869f552a..00000000000 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/AsianLoad.kt +++ /dev/null @@ -1,50 +0,0 @@ -package com.lagradost.cloudstream3.extractors - -import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.utils.ExtractorApi -import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.M3u8Helper -import com.lagradost.cloudstream3.utils.newExtractorLink - -class Vidnest : AsianLoad() { - override var name = "Vidnest" - override var mainUrl = "https://vidnest.io" -} - -open class AsianLoad : ExtractorApi() { - override var name = "AsianLoad" - override var mainUrl = "https://asianhdplay.pro" - override val requiresReferer = true - - private val sourceRegex = Regex("""sources:[\W\w]*?file:\s*?["'](.*?)["']""") - override suspend fun getUrl(url: String, referer: String?): List { - val extractedLinksList: MutableList = mutableListOf() - with(app.get(url, referer = referer)) { - sourceRegex.findAll(this.text).forEach { sourceMatch -> - val extractedUrl = sourceMatch.groupValues[1] - // Trusting this isn't mp4, may fuck up stuff - if (extractedUrl.contains(".m3u8")) { - M3u8Helper.generateM3u8( - name, - extractedUrl, - url, - headers = mapOf("referer" to this.url) - ).forEach { link -> - extractedLinksList.add(link) - } - } else if (extractedUrl.contains(".mp4")) { - extractedLinksList.add( - newExtractorLink( - source = name, - name = name, - url = extractedUrl, - ) { - this.referer = url.replace(" ", "%20") - } - ) - } - } - return extractedLinksList - } - } -} diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Bigwarp.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Bigwarp.kt deleted file mode 100644 index 50a68c62f27..00000000000 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Bigwarp.kt +++ /dev/null @@ -1,51 +0,0 @@ -package com.lagradost.cloudstream3.extractors - -import com.lagradost.cloudstream3.SubtitleFile -import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.utils.ExtractorApi -import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.Qualities -import com.lagradost.cloudstream3.utils.newExtractorLink - -open class BigwarpIO : ExtractorApi() { - override var name = "Bigwarp" - override var mainUrl = "https://bigwarp.io" - override val requiresReferer = false - - private val sourceRegex = Regex("""file:\s*['"](.*?)['"],label:\s*['"](.*?)['"]""") - private val qualityRegex = Regex("""\d+x(\d+) .*""") - - override suspend fun getUrl( - url: String, - referer: String?, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ) { - val resp = app.get(url).text - - for (sourceMatch in sourceRegex.findAll(resp)) { - val label = sourceMatch.groupValues[2] - - callback.invoke( - newExtractorLink( - name, - "$name ${label.split(" ", limit = 2).getOrNull(1)}", - sourceMatch.groupValues[1], // streams are usually in mp4 format - ) { - this.referer = url - this.quality = - qualityRegex.find(label)?.groupValues?.getOrNull(1)?.toIntOrNull() - ?: Qualities.Unknown.value - } - ) - } - } -} - -class BgwpCC : BigwarpIO() { - override var mainUrl = "https://bgwp.cc" -} - -class BigwarpArt : BigwarpIO() { - override var mainUrl = "https://bigwarp.art" -} diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Fastream.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Fastream.kt index e8f8c49aca0..94ddaf61e0e 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Fastream.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Fastream.kt @@ -1,54 +1,44 @@ package com.lagradost.cloudstream3.extractors +import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.amap import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.extractors.helper.JwPlayerHelper import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.M3u8Helper.Companion.generateM3u8 import com.lagradost.cloudstream3.utils.getAndUnpack -import org.jsoup.nodes.Document +import com.lagradost.cloudstream3.utils.getPacked -open class Fastream: ExtractorApi() { +open class Fastream : ExtractorApi() { override var mainUrl = "https://fastream.to" override var name = "Fastream" override val requiresReferer = false - suspend fun getstream( - response: Document, - sources: ArrayList): Boolean{ - response.select("script").amap { script -> - if (script.data().contains(Regex("eval\\(function\\(p,a,c,k,e,[rd]"))) { - val unpacked = getAndUnpack(script.data()) - //val m3u8regex = Regex("((https:|http:)\\/\\/.*\\.m3u8)") - val newm3u8link = unpacked.substringAfter("file:\"").substringBefore("\"") - //val m3u8link = m3u8regex.find(unpacked)?.value ?: return@forEach - generateM3u8( - name, - newm3u8link, - mainUrl - ).forEach { link -> - sources.add(link) - } - } - } - return true - } - override suspend fun getUrl(url: String, referer: String?): List { - val sources = ArrayList() + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { val idregex = Regex("emb.html\\?(.*)=") - if (url.contains(Regex("(emb.html.*fastream)"))) { + val response = if (url.contains(Regex("(emb.html.*fastream)"))) { val id = idregex.find(url)?.destructured?.component1() ?: "" - val response = app.post("https://fastream.to/dl", allowRedirects = false, + app.post( + "$mainUrl/dl", allowRedirects = false, data = mapOf( "op" to "embed", "file_code" to id, "auto" to "1" ) ).document - getstream(response, sources) + } else { + app.get(url, referer = url).document + } + response.select("script").amap { script -> + if (getPacked(script.data()) != null) { + val unPacked = getAndUnpack(script.data()) + JwPlayerHelper.extractStreamLinks(unPacked, name, mainUrl, callback, subtitleCallback) + } } - val response = app.get(url, referer = url).document - getstream(response, sources) - return sources } } \ No newline at end of file diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Filegram.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Filegram.kt index 7baa62710ba..7756f729087 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Filegram.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Filegram.kt @@ -3,10 +3,9 @@ package com.lagradost.cloudstream3.extractors import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.USER_AGENT import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.extractors.helper.JwPlayerHelper import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.M3u8Helper -import com.lagradost.cloudstream3.utils.fixUrl import com.lagradost.cloudstream3.utils.getAndUnpack import org.jsoup.nodes.Element @@ -35,15 +34,8 @@ open class Filegram : ExtractorApi() { val doc = app.get(getEmbedUrl(url), referer = referer).document val unpackedJs = unpackJs(doc).toString() - val videoUrl = Regex("""file:\s*"([^"]+\.m3u8[^"]*)"""").find(unpackedJs)?.groupValues?.get(1) - if (videoUrl != null) { - M3u8Helper.generateM3u8( - this.name, - fixUrl(videoUrl), - "$mainUrl/", - headers = header - ).forEach(callback) - } + + JwPlayerHelper.extractStreamLinks(unpackedJs, name, mainUrl, callback, subtitleCallback, headers = header) } private fun unpackJs(script: Element): String? { diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Filemoon.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Filemoon.kt index 6c10a92d935..ad4def1defc 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Filemoon.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Filemoon.kt @@ -3,6 +3,7 @@ package com.lagradost.cloudstream3.extractors import com.lagradost.api.Log import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.extractors.helper.JwPlayerHelper import com.lagradost.cloudstream3.network.WebViewResolver import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorLink @@ -54,18 +55,16 @@ open class FilemoonV2 : ExtractorApi() { ?.data().orEmpty() val unpackedScript = JsUnpacker(fallbackScriptData).unpack() - val videoUrl = unpackedScript?.let { - Regex("""sources:\[\{file:"(.*?)"""").find(it)?.groupValues?.get(1) - } + val linkFound = JwPlayerHelper.extractStreamLinks( + unpackedScript.orEmpty(), + name, + mainUrl, + callback, + subtitleCallback, + defaultHeaders + ) - if (!videoUrl.isNullOrEmpty()) { - M3u8Helper.generateM3u8( - name, - videoUrl, - mainUrl, - headers = defaultHeaders - ).forEach(callback) - } else { + if (!linkFound) { Log.d("FilemoonV2", "No iframe and no video URL found in script fallback.") } return @@ -81,18 +80,15 @@ open class FilemoonV2 : ExtractorApi() { val unpackedScript = JsUnpacker(iframeScriptData).unpack() - val videoUrl = unpackedScript?.let { - Regex("""sources:\[\{file:"(.*?)"""").find(it)?.groupValues?.get(1) - } + val linkFound = JwPlayerHelper.extractStreamLinks( + unpackedScript.orEmpty(), + name, + mainUrl, + callback, + subtitleCallback + ) - if (!videoUrl.isNullOrEmpty()) { - M3u8Helper.generateM3u8( - name, - videoUrl, - mainUrl, - headers = defaultHeaders - ).forEach(callback) - } else { + if (!linkFound) { // Last-resort fallback using WebView interception val resolver = WebViewResolver( interceptUrl = Regex("""(m3u8|master\.txt)"""), diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Filesim.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Filesim.kt index 4c5352dd92a..ff6b4f299e5 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Filesim.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Filesim.kt @@ -4,6 +4,7 @@ import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.utils.* import com.lagradost.api.Log +import com.lagradost.cloudstream3.extractors.helper.JwPlayerHelper import com.lagradost.cloudstream3.network.WebViewResolver @@ -76,17 +77,9 @@ open class Filesim : ExtractorApi() { pageResponse.document.selectFirst("script:containsData(sources:)")?.data() } - val m3u8Url = scriptData?.let { - Regex("""file:\s*"(.*?m3u8.*?)"""").find(it)?.groupValues?.getOrNull(1) - } + val linkFound = JwPlayerHelper.extractStreamLinks(scriptData.orEmpty(), name, mainUrl, callback, subtitleCallback) - if (!m3u8Url.isNullOrEmpty()) { - M3u8Helper.generateM3u8( - name, - m3u8Url, - mainUrl - ).forEach(callback) - } else { + if (!linkFound) { // Fallback using WebViewResolver val resolver = WebViewResolver( interceptUrl = Regex("""(m3u8|master\.txt)"""), diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/GamoVideo.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/GamoVideo.kt index 7e00dbf9596..85212e6bb5b 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/GamoVideo.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/GamoVideo.kt @@ -1,7 +1,10 @@ package com.lagradost.cloudstream3.extractors +import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.utils.* +import com.lagradost.cloudstream3.extractors.helper.JwPlayerHelper +import com.lagradost.cloudstream3.utils.ExtractorApi +import com.lagradost.cloudstream3.utils.ExtractorLink open class GamoVideo : ExtractorApi() { @@ -11,21 +14,13 @@ open class GamoVideo : ExtractorApi() { override suspend fun getUrl( url: String, - referer: String? - ): List? { - return app.get(url, referer = referer).document.select("script") - .firstOrNull { it.html().contains("sources:") }!!.html().substringAfter("file: \"") - .substringBefore("\",").let { - listOf( - newExtractorLink( - name, - name, - it, - ) { - this.referer = url - this.quality = Qualities.Unknown.value - } - ) - } + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + app.get(url, referer = referer).document.select("script") + .firstOrNull { JwPlayerHelper.canParseJwScript(it.data()) }!!.let { + JwPlayerHelper.extractStreamLinks(it.data(), name, mainUrl, callback, subtitleCallback) + } } } diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Hxfile.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Hxfile.kt index 8a56783b1f6..8f8a0c0cec2 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Hxfile.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Hxfile.kt @@ -1,9 +1,9 @@ package com.lagradost.cloudstream3.extractors -import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.extractors.helper.JwPlayerHelper import com.lagradost.cloudstream3.utils.* -import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson class Neonime7n : Hxfile() { override val name = "Neonime7n" @@ -39,64 +39,22 @@ open class Hxfile : ExtractorApi() { override val requiresReferer = false open val redirect = true - override suspend fun getUrl(url: String, referer: String?): List? { - val sources = mutableListOf() + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { val document = app.get(url, allowRedirects = redirect, referer = referer).document with(document) { this.select("script").map { script -> - if (script.data().contains("eval(function(p,a,c,k,e,d)")) { - val data = - getAndUnpack(script.data()).substringAfter("sources:[").substringBefore("]") - tryParseJson>("[$data]")?.map { - sources.add( - newExtractorLink( - name, - name, - it.file, - ) { - this.referer = mainUrl - this.quality = when { - url.contains("hxfile.co") -> getQualityFromName( - Regex("\\d\\.(.*?).mp4").find( - document.select("title").text() - )?.groupValues?.get(1).toString() - ) - else -> getQualityFromName(it.label) - } - } - ) - } - } else if (script.data().contains("\"sources\":[")) { - val data = script.data().substringAfter("\"sources\":[").substringBefore("]") - tryParseJson>("[$data]")?.map { - sources.add( - newExtractorLink( - name, - name, - it.file, - ) { - this.referer = mainUrl - this.quality = when { - it.label?.contains("HD") == true -> Qualities.P720.value - it.label?.contains("SD") == true -> Qualities.P480.value - else -> getQualityFromName(it.label) - } - } - ) - } - } - else { - null + if (getPacked(script.data()) != null) { + val data = getAndUnpack(script.data()) + JwPlayerHelper.extractStreamLinks(data, name, mainUrl, callback, subtitleCallback) + } else if (JwPlayerHelper.canParseJwScript(script.data())) { + JwPlayerHelper.extractStreamLinks(script.data(), name, mainUrl, callback, subtitleCallback) } } } - return sources } - - private data class ResponseSource( - @JsonProperty("file") val file: String, - @JsonProperty("type") val type: String?, - @JsonProperty("label") val label: String? - ) - } diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/JWPlayer.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/JWPlayer.kt index e744fdb3977..090b4d50fd1 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/JWPlayer.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/JWPlayer.kt @@ -1,13 +1,10 @@ package com.lagradost.cloudstream3.extractors -import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson +import com.lagradost.cloudstream3.extractors.helper.JwPlayerHelper import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.Qualities -import com.lagradost.cloudstream3.utils.getQualityFromName -import com.lagradost.cloudstream3.utils.newExtractorLink class Meownime : JWPlayer() { override val name = "Meownime" @@ -34,50 +31,36 @@ class DesuOdvip : JWPlayer() { override val mainUrl = "https://desustream.me/odvip/" } +class Vidnest : JWPlayer() { + override var name = "Vidnest" + override var mainUrl = "https://vidnest.io" +} + +open class BigwarpIO : JWPlayer() { + override var name = "Bigwarp" + override var mainUrl = "https://bigwarp.io" +} + +class BgwpCC : BigwarpIO() { + override var mainUrl = "https://bgwp.cc" +} + +class BigwarpArt : BigwarpIO() { + override var mainUrl = "https://bigwarp.art" +} + open class JWPlayer : ExtractorApi() { override val name = "JWPlayer" override val mainUrl = "https://www.jwplayer.com" override val requiresReferer = false - override suspend fun getUrl(url: String, referer: String?): List? { - val sources = mutableListOf() - with(app.get(url).document) { - val data = this.select("script").mapNotNull { script -> - if (script.data().contains("sources: [")) { - script.data().substringAfter("sources: [") - .substringBefore("],").replace("'", "\"") - } else if (script.data().contains("otakudesu('")) { - script.data().substringAfter("otakudesu('") - .substringBefore("');") - } else { - null - } - } - - tryParseJson>("$data")?.map { - sources.add( - newExtractorLink( - name, - name, - it.file, - ) { - this.referer = url - this.quality = getQualityFromName( - Regex("(\\d{3,4}p)").find(it.file)?.groupValues?.get( - 1 - ) - ) - } - ) - } - } - return sources + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val script = app.get(url).document.selectFirst("script:containsData(sources:)") ?: return + JwPlayerHelper.extractStreamLinks(script.data(), name, mainUrl, callback, subtitleCallback) } - - private data class ResponseSource( - @JsonProperty("file") val file: String, - @JsonProperty("type") val type: String?, - @JsonProperty("label") val label: String? - ) - } \ No newline at end of file diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Jeniusplay.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Jeniusplay.kt index f64863a9f3a..896228b5110 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Jeniusplay.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Jeniusplay.kt @@ -3,9 +3,12 @@ package com.lagradost.cloudstream3.extractors import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.newSubtitleFile -import com.lagradost.cloudstream3.utils.* -import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson +import com.lagradost.cloudstream3.extractors.helper.JwPlayerHelper +import com.lagradost.cloudstream3.utils.ExtractorApi +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.M3u8Helper +import com.lagradost.cloudstream3.utils.getAndUnpack +import com.lagradost.cloudstream3.utils.getPacked open class Jeniusplay : ExtractorApi() { override val name = "Jeniusplay" @@ -34,40 +37,17 @@ open class Jeniusplay : ExtractorApi() { url, ).forEach(callback) - document.select("script").map { script -> - if (script.data().contains("eval(function(p,a,c,k,e,d)")) { - val subData = - getAndUnpack(script.data()).substringAfter("\"tracks\":[").substringBefore("],") - tryParseJson>("[$subData]")?.map { subtitle -> - subtitleCallback.invoke( - newSubtitleFile( - getLanguage(subtitle.label ?: ""), - subtitle.file - ) - ) - } + if (getPacked(script.data()) != null) { + val unpacked = getAndUnpack(script.data()) + JwPlayerHelper.extractStreamLinks(unpacked, name, mainUrl, callback, subtitleCallback) } } } - private fun getLanguage(str: String): String { - return when { - str.contains("indonesia", true) || str - .contains("bahasa", true) -> "Indonesian" - else -> str - } - } - data class ResponseSource( @JsonProperty("hls") val hls: Boolean, @JsonProperty("videoSource") val videoSource: String, @JsonProperty("securedLink") val securedLink: String?, ) - - data class Tracks( - @JsonProperty("kind") val kind: String?, - @JsonProperty("file") val file: String, - @JsonProperty("label") val label: String?, - ) } \ No newline at end of file diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/LuluStream.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/LuluStream.kt index c130ca2de92..519741b8da6 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/LuluStream.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/LuluStream.kt @@ -1,12 +1,10 @@ package com.lagradost.cloudstream3.extractors import com.lagradost.cloudstream3.SubtitleFile +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.extractors.helper.JwPlayerHelper import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.utils.INFER_TYPE -import com.lagradost.cloudstream3.utils.Qualities -import com.lagradost.cloudstream3.utils.newExtractorLink class Lulustream1 : LuluStream() { override val name = "Lulustream" @@ -42,18 +40,7 @@ open class LuluStream : ExtractorApi() { ).document post.selectFirst("script:containsData(vplayer)")?.data() ?.let { script -> - Regex("file:\"(.*)\"").find(script)?.groupValues?.get(1)?.let { link -> - callback( - newExtractorLink( - name, - name, - link, - ) { - this.referer = mainUrl - this.quality = Qualities.P1080.value - } - ) - } + JwPlayerHelper.extractStreamLinks(script, name, mainUrl, callback, subtitleCallback) } } } \ No newline at end of file diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Minoplres.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Minoplres.kt deleted file mode 100644 index 702501a1e0c..00000000000 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Minoplres.kt +++ /dev/null @@ -1,38 +0,0 @@ -package com.lagradost.cloudstream3.extractors - -import com.fasterxml.jackson.annotation.JsonProperty -import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson -import com.lagradost.cloudstream3.utils.ExtractorApi -import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.M3u8Helper - -open class Minoplres : ExtractorApi() { - - override val name = "Minoplres" // formerly SpeedoStream - override val requiresReferer = true - override val mainUrl = "https://minoplres.xyz" // formerly speedostream.bond - private val hostUrl = "https://minoplres.xyz" - - override suspend fun getUrl(url: String, referer: String?): List { - val sources = mutableListOf() - app.get(url, referer = referer).document.select("script").map { script -> - if (script.data().contains("jwplayer(\"vplayer\").setup(")) { - val data = script.data().substringAfter("sources: [") - .substringBefore("],").replace("file", "\"file\"").trim() - tryParseJson(data)?.let { - M3u8Helper.generateM3u8( - name, - it.file, - "$hostUrl/", - ).forEach { m3uData -> sources.add(m3uData) } - } - } - } - return sources - } - - private data class File( - @JsonProperty("file") val file: String, - ) -} diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/MultiQuality.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/MultiQuality.kt deleted file mode 100644 index 802d9ea3af6..00000000000 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/MultiQuality.kt +++ /dev/null @@ -1,63 +0,0 @@ -package com.lagradost.cloudstream3.extractors - -import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.utils.ExtractorApi -import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.ExtractorLinkType -import com.lagradost.cloudstream3.utils.Qualities -import com.lagradost.cloudstream3.utils.getQualityFromName -import com.lagradost.cloudstream3.utils.newExtractorLink -import java.net.URI - -open class MultiQuality : ExtractorApi() { - override var name = "MultiQuality" - override var mainUrl = "https://anihdplay.com" - private val sourceRegex = Regex("""file:\s*['"](.*?)['"],label:\s*['"](.*?)['"]""") - private val m3u8Regex = Regex(""".*?(\d*).m3u8""") - private val urlRegex = Regex("""(.*?)([^/]+$)""") - override val requiresReferer = false - - override fun getExtractorUrl(id: String): String { - return "$mainUrl/loadserver.php?id=$id" - } - - override suspend fun getUrl(url: String, referer: String?): List { - val extractedLinksList: MutableList = mutableListOf() - with(app.get(url)) { - sourceRegex.findAll(this.text).forEach { sourceMatch -> - val extractedUrl = sourceMatch.groupValues[1] - // Trusting this isn't mp4, may fuck up stuff - if (URI(extractedUrl).path.endsWith(".m3u8")) { - with(app.get(extractedUrl)) { - m3u8Regex.findAll(this.text).forEach { match -> - extractedLinksList.add( - newExtractorLink( - source = name, - name = name, - url = urlRegex.find(this.url)!!.groupValues[1] + match.groupValues[0], - type = ExtractorLinkType.M3U8 - ) { - this.referer = url - this.quality = getQualityFromName(match.groupValues[1]) - } - ) - } - - } - } else if (extractedUrl.endsWith(".mp4")) { - extractedLinksList.add( - newExtractorLink( - name, - "$name ${sourceMatch.groupValues[2]}", - extractedUrl, - ) { - this.referer = url.replace(" ", "%20") - this.quality = Qualities.Unknown.value - } - ) - } - } - return extractedLinksList - } - } -} diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Pelisplus.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Pelisplus.kt deleted file mode 100644 index e2588feb63f..00000000000 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Pelisplus.kt +++ /dev/null @@ -1,101 +0,0 @@ -package com.lagradost.cloudstream3.extractors - -import com.lagradost.cloudstream3.SubtitleFile -import com.lagradost.cloudstream3.amap -import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.mvvm.safeAsync -import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.INFER_TYPE -import com.lagradost.cloudstream3.utils.extractorApis -import com.lagradost.cloudstream3.utils.getQualityFromName -import com.lagradost.cloudstream3.utils.loadExtractor -import com.lagradost.cloudstream3.utils.newExtractorLink -import org.jsoup.Jsoup - -/** - * overrideMainUrl is necessary for for other vidstream clones like vidembed.cc - * If they diverge it'd be better to make them separate. - * */ -open class Pelisplus(val mainUrl: String) { - val name: String = "Vidstream" - - private fun getExtractorUrl(id: String): String { - return "$mainUrl/play?id=$id" - } - - private fun getDownloadUrl(id: String): String { - return "$mainUrl/download?id=$id" - } - - private val normalApis = arrayListOf(MultiQuality()) - - // https://gogo-stream.com/streaming.php?id=MTE3NDg5 - suspend fun getUrl( - id: String, - isCasting: Boolean = false, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit - ): Boolean { - try { - normalApis.amap { api -> - val url = api.getExtractorUrl(id) - api.getSafeUrl(url, subtitleCallback = subtitleCallback, callback = callback) - } - val extractorUrl = getExtractorUrl(id) - - /** Stolen from GogoanimeProvider.kt extractor */ - safeAsync { - val link = getDownloadUrl(id) - println("Generated vidstream download link: $link") - val page = app.get(link, referer = extractorUrl) - - val pageDoc = Jsoup.parse(page.text) - val qualityRegex = Regex("(\\d+)P") - - //a[download] - pageDoc.select(".dowload > a").amap { element -> - val href = element.attr("href") - val qual = if (element.text() - .contains("HDP") - ) "1080" else qualityRegex.find(element.text())?.destructured?.component1() - .toString() - - if (!loadExtractor(href, link, subtitleCallback, callback)) { - callback.invoke( - newExtractorLink( - this.name, - name = this.name, - href - ) { - this.referer = page.url - this.quality = getQualityFromName(qual) - } - ) - } - } - } - - with(app.get(extractorUrl)) { - val document = Jsoup.parse(this.text) - val primaryLinks = document.select("ul.list-server-items > li.linkserver") - //val extractedLinksList: MutableList = mutableListOf() - - // All vidstream links passed to extractors - primaryLinks.distinctBy { it.attr("data-video") }.forEach { element -> - val link = element.attr("data-video") - //val name = element.text() - - // Matches vidstream links with extractors - extractorApis.filter { !it.requiresReferer || !isCasting }.amap { api -> - if (link.startsWith(api.mainUrl)) { - api.getSafeUrl(link, extractorUrl, subtitleCallback, callback) - } - } - } - return true - } - } catch (e: Exception) { - return false - } - } -} diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/StreamWishExtractor.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/StreamWishExtractor.kt index 8f4aceead3f..596aa7462b8 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/StreamWishExtractor.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/StreamWishExtractor.kt @@ -4,6 +4,7 @@ import com.lagradost.api.Log import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.USER_AGENT import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.extractors.helper.JwPlayerHelper import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.M3u8Helper @@ -12,7 +13,6 @@ import com.lagradost.cloudstream3.utils.getPacked import com.lagradost.cloudstream3.network.WebViewResolver - class Mwish : StreamWishExtractor() { override val name = "Mwish" override val mainUrl = "https://mwish.pro" @@ -170,18 +170,9 @@ open class StreamWishExtractor : ExtractorApi() { else -> pageResponse.document.selectFirst("script:containsData(sources:)")?.data() } - val directStreamUrl = playerScriptData?.let { - Regex("""file:\s*"(.*?m3u8.*?)"""").find(it)?.groupValues?.getOrNull(1) - } + val linkFound = JwPlayerHelper.extractStreamLinks(playerScriptData.orEmpty(), name, mainUrl, callback, subtitleCallback, headers) - if (!directStreamUrl.isNullOrEmpty()) { - M3u8Helper.generateM3u8( - name, - directStreamUrl, - mainUrl, - headers = headers - ).forEach(callback) - } else { + if (!linkFound) { val webViewM3u8Resolver = WebViewResolver( interceptUrl = Regex("""txt|m3u8"""), additionalUrls = listOf(Regex("""txt|m3u8""")), diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/StreamoUpload.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/StreamoUpload.kt index 7fafe05bec7..b7f618e9553 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/StreamoUpload.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/StreamoUpload.kt @@ -1,42 +1,30 @@ package com.lagradost.cloudstream3.extractors -import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson +import com.lagradost.cloudstream3.extractors.helper.JwPlayerHelper import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.getAndUnpack -import com.lagradost.cloudstream3.utils.Qualities -import com.lagradost.cloudstream3.utils.M3u8Helper +import com.lagradost.cloudstream3.utils.getPacked open class StreamoUpload : ExtractorApi() { override val name = "StreamoUpload" override val mainUrl = "https://streamoupload.xyz" override val requiresReferer = true - override suspend fun getUrl(url: String, referer: String?): List { - val sources = mutableListOf() + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { val response = app.get(url, referer = referer) - val scriptElements = response.document.select("script").map { script -> - if (script.data().contains("eval(function(p,a,c,k,e,d)")) { + response.document.select("script").map { script -> + if (getPacked(script.data()) != null) { val data = getAndUnpack(script.data()) - .substringAfter("sources:[") - .substringBefore("],") - .replace("file", "\"file\"") - .trim() - tryParseJson(data)?.let { - M3u8Helper.generateM3u8( - name, - it.file, - "$mainUrl/", - ).forEach { m3uData -> sources.add(m3uData) } - } + JwPlayerHelper.extractStreamLinks(data, name, mainUrl, callback, subtitleCallback) } } - return sources } - - private data class File( - @JsonProperty("file") val file: String, - ) } diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Supervideo.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Supervideo.kt index e70cae6bdf8..5e47dd2decf 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Supervideo.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Supervideo.kt @@ -1,42 +1,27 @@ package com.lagradost.cloudstream3.extractors -import com.fasterxml.jackson.annotation.JsonProperty -import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.utils.* -import com.lagradost.cloudstream3.utils.AppUtils.parseJson - -data class Files( - @JsonProperty("file") val id: String, - @JsonProperty("label") val label: String? = null, -) +import com.lagradost.cloudstream3.extractors.helper.JwPlayerHelper +import com.lagradost.cloudstream3.utils.ExtractorApi +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.JsUnpacker open class Supervideo : ExtractorApi() { override var name = "Supervideo" override var mainUrl = "https://supervideo.cc" override val requiresReferer = false - override suspend fun getUrl(url: String, referer: String?): List? { - val extractedLinksList: MutableList = mutableListOf() + + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { val response = app.get(url).text val jstounpack = Regex("eval((.|\\n)*?)").find(response)?.groups?.get(1)?.value - val unpacjed = JsUnpacker(jstounpack).unpack() - val extractedUrl = - unpacjed?.let { Regex("""sources:((.|\n)*?)image""").find(it) }?.groups?.get(1)?.value.toString() - .replace("file", """"file"""").replace("label", """"label"""") - .substringBeforeLast(",") - val parsedlinks = parseJson>(extractedUrl) - parsedlinks.forEach { data -> - if (data.label.isNullOrBlank()) { // mp4 links (with labels) are slow. Use only m3u8 link. - M3u8Helper.generateM3u8( - name, - data.id, - url, - headers = mapOf("referer" to url) - ).forEach { link -> - extractedLinksList.add(link) - } - } - } - return extractedLinksList + val unpacked = JsUnpacker(jstounpack).unpack() + + JwPlayerHelper.extractStreamLinks(unpacked.orEmpty(), name, mainUrl, callback, subtitleCallback) } } \ No newline at end of file diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Up4Stream.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Up4Stream.kt index 91150992b3a..b72213e66ea 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Up4Stream.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Up4Stream.kt @@ -1,13 +1,13 @@ package com.lagradost.cloudstream3.extractors import com.lagradost.api.Log +import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.extractors.helper.JwPlayerHelper import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.JsUnpacker -import com.lagradost.cloudstream3.utils.Qualities import com.lagradost.cloudstream3.utils.fixUrl -import com.lagradost.cloudstream3.utils.newExtractorLink import kotlinx.coroutines.delay class Up4FunTop : Up4Stream() { @@ -19,12 +19,17 @@ open class Up4Stream : ExtractorApi() { override var mainUrl = "https://up4stream.com" override val requiresReferer = true - override suspend fun getUrl(url: String, referer: String?): List? { + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { val movieId = url.substringAfterLast("/").substringBefore(".html") // redirect from "wait 5 seconds" page to actual movie page val redirectResponse = app.get(url, cookies = mapOf("id" to movieId)) - val redirectForm = redirectResponse.document.selectFirst("form[method=POST]") ?: return null + val redirectForm = redirectResponse.document.selectFirst("form[method=POST]") ?: return val redirectUrl = fixUrl(redirectForm.attr("action")) val redirectParams = redirectForm.select("input[type=hidden]").associate { input -> input.attr("name") to input.attr("value") @@ -42,19 +47,7 @@ open class Up4Stream : ExtractorApi() { } JsUnpacker(extractedpack).unpack()?.let { unPacked -> - Regex("sources:\\[\\{file:\"(.*?)\"").find(unPacked)?.groupValues?.get(1)?.let { link -> - return listOf( - newExtractorLink( - this.name, - this.name, - link, - ) { - this.referer = referer.orEmpty() - this.quality = Qualities.Unknown.value - } - ) - } + JwPlayerHelper.extractStreamLinks(unPacked, name, mainUrl, callback, subtitleCallback) } - return null } } \ No newline at end of file diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/VidHidePro.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/VidHidePro.kt index 5a3bba08e8c..d39a595779a 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/VidHidePro.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/VidHidePro.kt @@ -3,8 +3,11 @@ package com.lagradost.cloudstream3.extractors import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.USER_AGENT import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.utils.* -import com.lagradost.cloudstream3.utils.M3u8Helper.Companion.generateM3u8 +import com.lagradost.cloudstream3.extractors.helper.JwPlayerHelper +import com.lagradost.cloudstream3.utils.ExtractorApi +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.getAndUnpack +import com.lagradost.cloudstream3.utils.getPacked class VidHidePro1 : VidHidePro() { override var mainUrl = "https://filelions.live" @@ -71,24 +74,12 @@ open class VidHidePro : ExtractorApi() { val response = app.get(getEmbedUrl(url), referer = referer) val script = if (!getPacked(response.text).isNullOrEmpty()) { - var result = getAndUnpack(response.text) - if(result.contains("var links")){ - result = result.substringAfter("var links") - } - result + getAndUnpack(response.text) } else { response.document.selectFirst("script:containsData(sources:)")?.data() } ?: return - // m3u8 urls could be prefixed by 'file:', 'hls2:' or 'hls4:', so we just match ':' - Regex(":\\s*\"(.*?m3u8.*?)\"").findAll(script).forEach { m3u8Match -> - generateM3u8( - name, - fixUrl(m3u8Match.groupValues[1]), - referer = "$mainUrl/", - headers = headers - ).forEach(callback) - } + JwPlayerHelper.extractStreamLinks(script, name, mainUrl, callback, subtitleCallback, headers) } private fun getEmbedUrl(url: String): String { diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Vidmoly.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Vidmoly.kt index f966a2f5d01..3949c045cef 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Vidmoly.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Vidmoly.kt @@ -1,12 +1,11 @@ package com.lagradost.cloudstream3.extractors -import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.USER_AGENT import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.newSubtitleFile -import com.lagradost.cloudstream3.utils.* -import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson +import com.lagradost.cloudstream3.extractors.helper.JwPlayerHelper +import com.lagradost.cloudstream3.utils.ExtractorApi +import com.lagradost.cloudstream3.utils.ExtractorLink import kotlinx.coroutines.delay class Vidmolyme : Vidmoly() { @@ -48,39 +47,7 @@ open class Vidmoly : ExtractorApi() { if(script.isNullOrEmpty()) delay(500) } - val videoData = script?.substringAfter("sources: [") - ?.substringBefore("],")?.addMarks("file") - val subData = script?.substringAfter("tracks: [")?.substringBefore("]")?.addMarks("file") - ?.addMarks("label")?.addMarks("kind") - - tryParseJson(videoData)?.file?.let { m3uLink -> - M3u8Helper.generateM3u8( - name, - m3uLink, - "$mainUrl/" - ).forEach(callback) - } - - tryParseJson>("[${subData}]") - ?.filter { it.kind == "captions" }?.map { - subtitleCallback.invoke( - newSubtitleFile( - it.label.toString(), - fixUrl(it.file.toString()) - ) - ) - } + JwPlayerHelper.extractStreamLinks(script.orEmpty(), name, mainUrl, callback, subtitleCallback) } - - private data class Source( - @JsonProperty("file") val file: String? = null, - ) - - private data class SubSource( - @JsonProperty("file") val file: String? = null, - @JsonProperty("label") val label: String? = null, - @JsonProperty("kind") val kind: String? = null, - ) - } diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Vidstream.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Vidstream.kt deleted file mode 100644 index ab228ee3c27..00000000000 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Vidstream.kt +++ /dev/null @@ -1,104 +0,0 @@ -package com.lagradost.cloudstream3.extractors - -import com.lagradost.cloudstream3.SubtitleFile -import com.lagradost.cloudstream3.amap -import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.runAllAsync -import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.INFER_TYPE -import com.lagradost.cloudstream3.utils.extractorApis -import com.lagradost.cloudstream3.utils.getQualityFromName -import com.lagradost.cloudstream3.utils.loadExtractor -import com.lagradost.cloudstream3.utils.newExtractorLink -import org.jsoup.Jsoup - -/** - * overrideMainUrl is necessary for for other vidstream clones like vidembed.cc - * If they diverge it'd be better to make them separate. - * */ -class Vidstream(val mainUrl: String) { - val name: String = "Vidstream" - - private fun getExtractorUrl(id: String): String { - return "$mainUrl/streaming.php?id=$id" - } - - private fun getDownloadUrl(id: String): String { - return "$mainUrl/download?id=$id" - } - - private val normalApis = arrayListOf(MultiQuality()) - - // https://gogo-stream.com/streaming.php?id=MTE3NDg5 - suspend fun getUrl( - id: String, - isCasting: Boolean = false, - subtitleCallback: (SubtitleFile) -> Unit, - callback: (ExtractorLink) -> Unit, - ): Boolean { - val extractorUrl = getExtractorUrl(id) - runAllAsync( - { - normalApis.amap { api -> - val url = api.getExtractorUrl(id) - api.getSafeUrl( - url, - callback = callback, - subtitleCallback = subtitleCallback - ) - } - }, { - /** Stolen from GogoanimeProvider.kt extractor */ - val link = getDownloadUrl(id) - println("Generated vidstream download link: $link") - val page = app.get(link, referer = extractorUrl) - - val pageDoc = Jsoup.parse(page.text) - val qualityRegex = Regex("(\\d+)P") - - //a[download] - pageDoc.select(".dowload > a").amap { element -> - val href = element.attr("href") - val qual = if (element.text() - .contains("HDP") - ) "1080" else qualityRegex.find(element.text())?.destructured?.component1() - .toString() - - if (!loadExtractor(href, link, subtitleCallback, callback)) { - callback.invoke( - newExtractorLink( - this.name, - name = this.name, - href, - type = INFER_TYPE - ) { - this.referer = page.url - this.quality = getQualityFromName(qual) - } - ) - } - } - }, { - with(app.get(extractorUrl)) { - val document = Jsoup.parse(this.text) - val primaryLinks = document.select("ul.list-server-items > li.linkserver") - //val extractedLinksList: MutableList = mutableListOf() - - // All vidstream links passed to extractors - primaryLinks.distinctBy { it.attr("data-video") }.forEach { element -> - val link = element.attr("data-video") - //val name = element.text() - - // Matches vidstream links with extractors - extractorApis.filter { !it.requiresReferer || !isCasting }.amap { api -> - if (link.startsWith(api.mainUrl)) { - api.getSafeUrl(link, extractorUrl, subtitleCallback, callback) - } - } - } - } - } - ) - return true - } -} \ No newline at end of file diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Vtbe.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Vtbe.kt index 37b8ecb239e..2fdd7082a34 100644 --- a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Vtbe.kt +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Vtbe.kt @@ -1,15 +1,11 @@ package com.lagradost.cloudstream3.extractors -import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.utils.* -import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson -import com.lagradost.cloudstream3.utils.JsUnpacker +import com.lagradost.cloudstream3.extractors.helper.JwPlayerHelper import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.Qualities -import com.lagradost.cloudstream3.utils.getQualityFromName -import java.net.URI +import com.lagradost.cloudstream3.utils.JsUnpacker open class Vtbe : ExtractorApi() { @@ -17,23 +13,16 @@ open class Vtbe : ExtractorApi() { override var mainUrl = "https://vtbe.to" override val requiresReferer = true - override suspend fun getUrl(url: String, referer: String?): List? { + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { val response = app.get(url,referer=mainUrl).document - val extractedpack =response.selectFirst("script:containsData(function(p,a,c,k,e,d))")?.data().toString() + val extractedpack = response.selectFirst("script:containsData(function(p,a,c,k,e,d))")?.data().toString() JsUnpacker(extractedpack).unpack()?.let { unPacked -> - Regex("sources:\\[\\{file:\"(.*?)\"").find(unPacked)?.groupValues?.get(1)?.let { link -> - return listOf( - newExtractorLink( - this.name, - this.name, - link, - ) { - this.referer = referer ?: "" - this.quality = Qualities.Unknown.value - } - ) - } + JwPlayerHelper.extractStreamLinks(unPacked, name, mainUrl, callback, subtitleCallback) } - return null } } diff --git a/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/helper/JWPlayerHelper.kt b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/helper/JWPlayerHelper.kt new file mode 100644 index 00000000000..23f9a7ca832 --- /dev/null +++ b/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/helper/JWPlayerHelper.kt @@ -0,0 +1,153 @@ +package com.lagradost.cloudstream3.extractors.helper + +import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.api.Log +import com.lagradost.cloudstream3.SubtitleFile +import com.lagradost.cloudstream3.newSubtitleFile +import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.M3u8Helper +import com.lagradost.cloudstream3.utils.newExtractorLink +import kotlin.collections.orEmpty + +object JwPlayerHelper { + private val sourceRegex = Regex(""""?sources"?:\s*(\[.*?\])""") + private val tracksRegex = Regex(""""?tracks"?:\s*(\[.*?\])""") + private val m3u8Regex = Regex("""[:=]\s*\"([^\"\s]+(\.m3u8|master\.txt)[^\"\s]*)""") + + /** + * Get stream links the "sources" attribute inside a JWPlayer script, e.g. + * + * ```js + *