diff --git a/DopeboxProvider/build.gradle.kts b/DopeboxProvider/build.gradle.kts index 704695e..9d974c3 100644 --- a/DopeboxProvider/build.gradle.kts +++ b/DopeboxProvider/build.gradle.kts @@ -1,5 +1,6 @@ dependencies { -// implementation(project(mapOf("path" to ":SflixProvider"))) +implementation(project(mapOf("path" to ":SflixProvider"))) + // implementation(project(mapOf("path" to ":SflixProvider"))) } // use an integer for version numbers version = 1 diff --git a/DramaSeeProvider/build.gradle.kts b/DramaSeeProvider/build.gradle.kts index e7d2158..df3927d 100644 --- a/DramaSeeProvider/build.gradle.kts +++ b/DramaSeeProvider/build.gradle.kts @@ -1,3 +1,6 @@ +dependencies { + implementation(project(mapOf("path" to ":VidstreamProviderTemplate"))) +} // use an integer for version numbers version = 1 diff --git a/DramaSeeProvider/src/main/kotlin/com/lagradost/DramaSeeProvider.kt b/DramaSeeProvider/src/main/kotlin/com/lagradost/DramaSeeProvider.kt index 22ccc56..ae31a24 100644 --- a/DramaSeeProvider/src/main/kotlin/com/lagradost/DramaSeeProvider.kt +++ b/DramaSeeProvider/src/main/kotlin/com/lagradost/DramaSeeProvider.kt @@ -1,7 +1,8 @@ package com.lagradost import com.lagradost.cloudstream3.* -import com.lagradost.cloudstream3.animeproviders.GogoanimeProvider.Companion.extractVidstream +import com.lagradost.cloudstream3.extractors.Vidstream +//import com.lagradost.cloudstream3.animeproviders.GogoanimeProvider.Companion.extractVidstream import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.loadExtractor @@ -200,7 +201,7 @@ class DramaSeeProvider : MainAPI() { val iv = "9262859232435825" val secretKey = "93422192433952489752342908585752" val secretDecryptKey = "93422192433952489752342908585752" - extractVidstream( + Vidstream.extractVidstream( iframe.url, this.name, callback, diff --git a/KdramaHoodProvider/build.gradle.kts b/KdramaHoodProvider/build.gradle.kts index e7d2158..91a4840 100644 --- a/KdramaHoodProvider/build.gradle.kts +++ b/KdramaHoodProvider/build.gradle.kts @@ -1,3 +1,7 @@ +dependencies { + implementation(project(mapOf("path" to ":WatchAsianProvider"))) + implementation(project(mapOf("path" to ":WatchAsianProvider"))) +} // use an integer for version numbers version = 1 diff --git a/KdramaHoodProvider/src/main/kotlin/com/lagradost/KdramaHoodProvider.kt b/KdramaHoodProvider/src/main/kotlin/com/lagradost/KdramaHoodProvider.kt index 055c7ea..6c04a36 100644 --- a/KdramaHoodProvider/src/main/kotlin/com/lagradost/KdramaHoodProvider.kt +++ b/KdramaHoodProvider/src/main/kotlin/com/lagradost/KdramaHoodProvider.kt @@ -2,8 +2,6 @@ package com.lagradost import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* -import com.lagradost.cloudstream3.extractors.XStreamCdn -import com.lagradost.cloudstream3.extractors.helper.AsianEmbedHelper import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.toJson diff --git a/OpenVidsProvider/build.gradle.kts b/OpenVidsProvider/build.gradle.kts index e7d2158..c5b221c 100644 --- a/OpenVidsProvider/build.gradle.kts +++ b/OpenVidsProvider/build.gradle.kts @@ -1,3 +1,7 @@ +dependencies { + implementation(project(mapOf("path" to ":VidstreamProviderTemplate"))) + implementation(project(mapOf("path" to ":VidEmbedProvider"))) +} // use an integer for version numbers version = 1 diff --git a/OpenVidsProvider/src/main/kotlin/com/lagradost/OpenVidsProvider.kt b/OpenVidsProvider/src/main/kotlin/com/lagradost/OpenVidsProvider.kt index c036340..5496cb4 100644 --- a/OpenVidsProvider/src/main/kotlin/com/lagradost/OpenVidsProvider.kt +++ b/OpenVidsProvider/src/main/kotlin/com/lagradost/OpenVidsProvider.kt @@ -2,7 +2,7 @@ package com.lagradost import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* -import com.lagradost.cloudstream3.animeproviders.GogoanimeProvider.Companion.extractVidstream +import com.lagradost.cloudstream3.extractors.Vidstream import com.lagradost.cloudstream3.metaproviders.TmdbLink import com.lagradost.cloudstream3.metaproviders.TmdbProvider import com.lagradost.cloudstream3.utils.AppUtils.parseJson @@ -115,7 +115,7 @@ class OpenVidsProvider:TmdbProvider() { listservers.apmap { links -> if (links.contains("membed")) { val membed = VidEmbedProvider() - extractVidstream( + Vidstream.extractVidstream( links, this.name, callback, diff --git a/PinoyMoviePediaProvider/build.gradle.kts b/PinoyMoviePediaProvider/build.gradle.kts index e7d2158..871010c 100644 --- a/PinoyMoviePediaProvider/build.gradle.kts +++ b/PinoyMoviePediaProvider/build.gradle.kts @@ -1,3 +1,6 @@ +dependencies { + implementation(project(mapOf("path" to ":WatchAsianProvider"))) +} // use an integer for version numbers version = 1 diff --git a/PinoyMoviePediaProvider/src/main/kotlin/com/lagradost/PinoyMoviePediaProvider.kt b/PinoyMoviePediaProvider/src/main/kotlin/com/lagradost/PinoyMoviePediaProvider.kt index 9636dd4..9a23a32 100644 --- a/PinoyMoviePediaProvider/src/main/kotlin/com/lagradost/PinoyMoviePediaProvider.kt +++ b/PinoyMoviePediaProvider/src/main/kotlin/com/lagradost/PinoyMoviePediaProvider.kt @@ -1,7 +1,7 @@ package com.lagradost import com.lagradost.cloudstream3.* -import com.lagradost.cloudstream3.extractors.FEmbed +//import com.lagradost.cloudstream3.extractors.FEmbed import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.ExtractorLink diff --git a/PinoyMoviesEsProvider/build.gradle.kts b/PinoyMoviesEsProvider/build.gradle.kts index e7d2158..871010c 100644 --- a/PinoyMoviesEsProvider/build.gradle.kts +++ b/PinoyMoviesEsProvider/build.gradle.kts @@ -1,3 +1,6 @@ +dependencies { + implementation(project(mapOf("path" to ":WatchAsianProvider"))) +} // use an integer for version numbers version = 1 diff --git a/PinoyMoviesEsProvider/src/main/kotlin/com/lagradost/PinoyMoviesEsProvider.kt b/PinoyMoviesEsProvider/src/main/kotlin/com/lagradost/PinoyMoviesEsProvider.kt index 5fb5500..9c13f59 100644 --- a/PinoyMoviesEsProvider/src/main/kotlin/com/lagradost/PinoyMoviesEsProvider.kt +++ b/PinoyMoviesEsProvider/src/main/kotlin/com/lagradost/PinoyMoviesEsProvider.kt @@ -2,8 +2,8 @@ package com.lagradost import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* -import com.lagradost.cloudstream3.extractors.FEmbed -import com.lagradost.cloudstream3.extractors.helper.VstreamhubHelper +//import com.lagradost.cloudstream3.extractors.FEmbed +//import com.lagradost.cloudstream3.extractors.helper.VstreamhubHelper import com.lagradost.cloudstream3.network.DdosGuardKiller import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson diff --git a/PinoyMoviesEsProvider/src/main/kotlin/com/lagradost/VstreamhubHelper.kt b/PinoyMoviesEsProvider/src/main/kotlin/com/lagradost/VstreamhubHelper.kt new file mode 100644 index 0000000..e9cf8a5 --- /dev/null +++ b/PinoyMoviesEsProvider/src/main/kotlin/com/lagradost/VstreamhubHelper.kt @@ -0,0 +1,58 @@ +package com.lagradost + +import com.lagradost.cloudstream3.SubtitleFile +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.Qualities +import com.lagradost.cloudstream3.utils.loadExtractor + +class VstreamhubHelper { + companion object { + private val baseUrl: String = "https://vstreamhub.com" + private val baseName: String = "Vstreamhub" + + suspend fun getUrls( + url: String, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + if (url.startsWith(baseUrl)) { + // Fetch links + val doc = app.get(url).document.select("script") + doc?.forEach { + val innerText = it?.toString() + if (!innerText.isNullOrEmpty()) { + if (innerText.contains("file:")) { + val startString = "file: " + val aa = innerText.substring(innerText.indexOf(startString)) + val linkUrl = + aa.substring(startString.length + 1, aa.indexOf("\",")).trim() + //Log.i(baseName, "Result => (linkUrl) ${linkUrl}") + val exlink = ExtractorLink( + name = "$baseName m3u8", + source = baseName, + url = linkUrl, + quality = Qualities.Unknown.value, + referer = url, + isM3u8 = true + ) + callback.invoke(exlink) + } + if (innerText.contains("playerInstance")) { + val aa = + innerText.substring(innerText.indexOf("playerInstance.addButton")) + val startString = "window.open([" + val bb = aa.substring(aa.indexOf(startString)) + val datavid = bb.substring(startString.length, bb.indexOf("]")) + .removeSurrounding("\"") + if (datavid.isNotBlank()) { + loadExtractor(datavid, url, subtitleCallback, callback) + //Log.i(baseName, "Result => (datavid) ${datavid}") + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/README.md b/README.md index abe2c40..fcd6e95 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,11 @@ **⚠️ This is currently under development, dont use it yet if you're not comfortable with constantly merging new changes** -# `Cloudstream3 Plugin Repo Template` +# Cloudstream 3 Movies Repository -Template for a [Cloudstream3](https://github.com/recloudstream) plugin repo +Not all extractors are included, only those need to compile. We need to use loadExtractor in the future. -**⚠️ Make sure you check "Include all branches" when using this template** - - ## Getting started with writing your first plugin -This template includes 1 example plugin. - 1. Open the root build.gradle.kts, read the comments and replace all the placeholders 2. Familiarize yourself with the project structure. Most files are commented 3. Build or deploy your first plugin using: diff --git a/SflixProvider/src/main/kotlin/com/lagradost/SflixProvider.kt b/SflixProvider/src/main/kotlin/com/lagradost/SflixProvider.kt index b9b35b6..3b9bcc7 100644 --- a/SflixProvider/src/main/kotlin/com/lagradost/SflixProvider.kt +++ b/SflixProvider/src/main/kotlin/com/lagradost/SflixProvider.kt @@ -8,9 +8,7 @@ import com.lagradost.cloudstream3.APIHolder.unixTimeMS import com.lagradost.cloudstream3.LoadResponse.Companion.addActors import com.lagradost.cloudstream3.LoadResponse.Companion.addDuration import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer -import com.lagradost.cloudstream3.animeproviders.ZoroProvider -import com.lagradost.cloudstream3.mvvm.normalSafeApiCall -import com.lagradost.cloudstream3.mvvm.safeApiCall +//import com.lagradost.cloudstream3.animeproviders.ZoroProvider import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson @@ -678,19 +676,19 @@ open class SflixProvider : MainAPI() { var sid: String? = null if (useSidAuthentication && extractorData != null) { - negotiateNewSid(extractorData)?.also { + negotiateNewSid(extractorData)?.also { pollingData -> app.post( - "$extractorData&t=${generateTimeStamp()}&sid=${it.sid}", + "$extractorData&t=${generateTimeStamp()}&sid=${pollingData.sid}", requestBody = "40".toRequestBody(), timeout = 60 ) val text = app.get( - "$extractorData&t=${generateTimeStamp()}&sid=${it.sid}", + "$extractorData&t=${generateTimeStamp()}&sid=${pollingData.sid}", timeout = 60 ).text.replaceBefore("{", "") sid = parseJson(text).sid - ioSafe { app.get("$extractorData&t=${generateTimeStamp()}&sid=${it.sid}") } + ioSafe { app.get("$extractorData&t=${generateTimeStamp()}&sid=${pollingData.sid}") } } } @@ -738,7 +736,7 @@ open class SflixProvider : MainAPI() { ) ?.forEach { // Sets Zoro SID used for video loading - (this as? ZoroProvider)?.sid?.set(it.url.hashCode(), sid) +// (this as? ZoroProvider)?.sid?.set(it.url.hashCode(), sid) callback(it) } } diff --git a/SolarmovieProvider/build.gradle.kts b/SolarmovieProvider/build.gradle.kts index e7d2158..ce4f6b5 100644 --- a/SolarmovieProvider/build.gradle.kts +++ b/SolarmovieProvider/build.gradle.kts @@ -1,3 +1,6 @@ +dependencies { + implementation(project(mapOf("path" to ":SflixProvider"))) +} // use an integer for version numbers version = 1 diff --git a/TwoEmbedProvider/build.gradle.kts b/TwoEmbedProvider/build.gradle.kts index e7d2158..ce4f6b5 100644 --- a/TwoEmbedProvider/build.gradle.kts +++ b/TwoEmbedProvider/build.gradle.kts @@ -1,3 +1,6 @@ +dependencies { + implementation(project(mapOf("path" to ":SflixProvider"))) +} // use an integer for version numbers version = 1 diff --git a/TwoEmbedProvider/src/main/kotlin/com/lagradost/TwoEmbedProvider.kt b/TwoEmbedProvider/src/main/kotlin/com/lagradost/TwoEmbedProvider.kt index b5cd390..a97887d 100644 --- a/TwoEmbedProvider/src/main/kotlin/com/lagradost/TwoEmbedProvider.kt +++ b/TwoEmbedProvider/src/main/kotlin/com/lagradost/TwoEmbedProvider.kt @@ -2,6 +2,8 @@ package com.lagradost import android.util.Log import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.SflixProvider.Companion.extractRabbitStream +import com.lagradost.SflixProvider.Companion.runSflixExtractorVerifierJob import com.lagradost.cloudstream3.APIHolder.getCaptchaToken import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.TvType @@ -9,8 +11,6 @@ import com.lagradost.cloudstream3.apmap import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.metaproviders.TmdbLink import com.lagradost.cloudstream3.metaproviders.TmdbProvider -import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.extractRabbitStream -import com.lagradost.cloudstream3.movieproviders.SflixProvider.Companion.runSflixExtractorVerifierJob import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.loadExtractor diff --git a/VidEmbedProvider/build.gradle.kts b/VidEmbedProvider/build.gradle.kts index e7d2158..df3927d 100644 --- a/VidEmbedProvider/build.gradle.kts +++ b/VidEmbedProvider/build.gradle.kts @@ -1,3 +1,6 @@ +dependencies { + implementation(project(mapOf("path" to ":VidstreamProviderTemplate"))) +} // use an integer for version numbers version = 1 diff --git a/VidSrcProvider/src/main/kotlin/com/lagradost/VidSrcProvider.kt b/VidSrcProvider/src/main/kotlin/com/lagradost/VidSrcProvider.kt index efa78e0..012cae9 100644 --- a/VidSrcProvider/src/main/kotlin/com/lagradost/VidSrcProvider.kt +++ b/VidSrcProvider/src/main/kotlin/com/lagradost/VidSrcProvider.kt @@ -2,11 +2,12 @@ package com.lagradost import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.TvType -import com.lagradost.cloudstream3.extractors.VidSrcExtractor +//import com.lagradost.cloudstream3.extractors.VidSrcExtractor import com.lagradost.cloudstream3.metaproviders.TmdbLink import com.lagradost.cloudstream3.metaproviders.TmdbProvider import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.loadExtractor class VidSrcProvider : TmdbProvider() { override val apiName = "VidSrc" @@ -19,9 +20,9 @@ class VidSrcProvider : TmdbProvider() { TvType.TvSeries, ) - companion object { - val extractor = VidSrcExtractor() - } +// companion object { +// val extractor = VidSrcExtractor() +// } override suspend fun loadLinks( data: String, @@ -44,7 +45,8 @@ class VidSrcProvider : TmdbProvider() { "$mainUrl/embed/$suffix" } - extractor.getSafeUrl(embedUrl, null, subtitleCallback, callback) + loadExtractor(embedUrl, null, subtitleCallback, callback) +// extractor.getSafeUrl(embedUrl, null, subtitleCallback, callback) return true } diff --git a/VidstreamProviderTemplate/src/main/kotlin/com/lagradost/MultiQuality.kt b/VidstreamProviderTemplate/src/main/kotlin/com/lagradost/MultiQuality.kt new file mode 100644 index 0000000..2f77415 --- /dev/null +++ b/VidstreamProviderTemplate/src/main/kotlin/com/lagradost/MultiQuality.kt @@ -0,0 +1,59 @@ +package com.lagradost + +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.getQualityFromName +import java.net.URI + +class MultiQuality : ExtractorApi() { + override var name = "MultiQuality" + override var mainUrl = "https://gogo-play.net" + 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( + ExtractorLink( + name, + name = name, + urlRegex.find(this.url)!!.groupValues[1] + match.groupValues[0], + url, + getQualityFromName(match.groupValues[1]), + isM3u8 = true + ) + ) + } + + } + } else if (extractedUrl.endsWith(".mp4")) { + extractedLinksList.add( + ExtractorLink( + name, + "$name ${sourceMatch.groupValues[2]}", + extractedUrl, + url.replace(" ", "%20"), + Qualities.Unknown.value, + ) + ) + } + } + return extractedLinksList + } + } +} \ No newline at end of file diff --git a/VidstreamProviderTemplate/src/main/kotlin/com/lagradost/Vidstream.kt b/VidstreamProviderTemplate/src/main/kotlin/com/lagradost/Vidstream.kt new file mode 100644 index 0000000..e14fd52 --- /dev/null +++ b/VidstreamProviderTemplate/src/main/kotlin/com/lagradost/Vidstream.kt @@ -0,0 +1,235 @@ +package com.lagradost.cloudstream3.extractors + +import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.MultiQuality +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.AcraApplication.Companion.getKey +import com.lagradost.cloudstream3.mvvm.safeApiCall +import com.lagradost.cloudstream3.utils.* +import org.jsoup.Jsoup +import org.jsoup.nodes.Document +import java.net.URI +import javax.crypto.Cipher +import javax.crypto.spec.IvParameterSpec +import javax.crypto.spec.SecretKeySpec + +/** + * 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" + + companion object { + data class GogoSources( + @JsonProperty("source") val source: List?, + @JsonProperty("sourceBk") val sourceBk: List?, + //val track: List, + //val advertising: List, + //val linkiframe: String + ) + + data class GogoSource( + @JsonProperty("file") val file: String, + @JsonProperty("label") val label: String?, + @JsonProperty("type") val type: String?, + @JsonProperty("default") val default: String? = null + ) + + // https://github.com/saikou-app/saikou/blob/3e756bd8e876ad7a9318b17110526880525a5cd3/app/src/main/java/ani/saikou/anime/source/extractors/GogoCDN.kt#L60 + // No Licence on the function + private fun cryptoHandler( + string: String, + iv: String, + secretKeyString: String, + encrypt: Boolean = true + ): String { + //println("IV: $iv, Key: $secretKeyString, encrypt: $encrypt, Message: $string") + val ivParameterSpec = IvParameterSpec(iv.toByteArray()) + val secretKey = SecretKeySpec(secretKeyString.toByteArray(), "AES") + val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") + return if (!encrypt) { + cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec) + String(cipher.doFinal(base64DecodeArray(string))) + } else { + cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec) + base64Encode(cipher.doFinal(string.toByteArray())) + } + } + + /** + * @param iframeUrl something like https://gogoplay4.com/streaming.php?id=XXXXXX + * @param mainApiName used for ExtractorLink names and source + * @param iv secret iv from site, required non-null if isUsingAdaptiveKeys is off + * @param secretKey secret key for decryption from site, required non-null if isUsingAdaptiveKeys is off + * @param secretDecryptKey secret key to decrypt the response json, required non-null if isUsingAdaptiveKeys is off + * @param isUsingAdaptiveKeys generates keys from IV and ID, see getKey() + * @param isUsingAdaptiveData generate encrypt-ajax data based on $("script[data-name='episode']")[0].dataset.value + * */ + suspend fun extractVidstream( + iframeUrl: String, + mainApiName: String, + callback: (ExtractorLink) -> Unit, + iv: String?, + secretKey: String?, + secretDecryptKey: String?, + // This could be removed, but i prefer it verbose + isUsingAdaptiveKeys: Boolean, + isUsingAdaptiveData: Boolean, + // If you don't want to re-fetch the document + iframeDocument: Document? = null + ) = safeApiCall { + // https://github.com/saikou-app/saikou/blob/3e756bd8e876ad7a9318b17110526880525a5cd3/app/src/main/java/ani/saikou/anime/source/extractors/GogoCDN.kt + // No Licence on the following code + // Also modified of https://github.com/jmir1/aniyomi-extensions/blob/master/src/en/gogoanime/src/eu/kanade/tachiyomi/animeextension/en/gogoanime/extractors/GogoCdnExtractor.kt + // License on the code above https://github.com/jmir1/aniyomi-extensions/blob/master/LICENSE + + if ((iv == null || secretKey == null || secretDecryptKey == null) && !isUsingAdaptiveKeys) + return@safeApiCall + + val id = Regex("id=([^&]+)").find(iframeUrl)!!.value.removePrefix("id=") + + var document: Document? = iframeDocument + val foundIv = + iv ?: (document ?: app.get(iframeUrl).document.also { document = it }) + .select("""div.wrapper[class*=container]""") + .attr("class").split("-").lastOrNull() ?: return@safeApiCall + val foundKey = secretKey ?: getKey(base64Decode(id) + foundIv) ?: return@safeApiCall + val foundDecryptKey = secretDecryptKey ?: foundKey + + val uri = URI(iframeUrl) + val mainUrl = "https://" + uri.host + + val encryptedId = cryptoHandler(id, foundIv, foundKey) + val encryptRequestData = if (isUsingAdaptiveData) { + // Only fetch the document if necessary + val realDocument = document ?: app.get(iframeUrl).document + val dataEncrypted = + realDocument.select("script[data-name='episode']").attr("data-value") + val headers = cryptoHandler(dataEncrypted, foundIv, foundKey, false) + "id=$encryptedId&alias=$id&" + headers.substringAfter("&") + } else { + "id=$encryptedId&alias=$id" + } + + val jsonResponse = + app.get( + "$mainUrl/encrypt-ajax.php?$encryptRequestData", + headers = mapOf("X-Requested-With" to "XMLHttpRequest") + ) + val dataencrypted = + jsonResponse.text.substringAfter("{\"data\":\"").substringBefore("\"}") + val datadecrypted = cryptoHandler(dataencrypted, foundIv, foundDecryptKey, false) + val sources = AppUtils.parseJson(datadecrypted) + + fun invokeGogoSource( + source: GogoSource, + sourceCallback: (ExtractorLink) -> Unit + ) { + sourceCallback.invoke( + ExtractorLink( + mainApiName, + mainApiName, + source.file, + mainUrl, + getQualityFromName(source.label), + isM3u8 = source.type == "hls" || source.label?.contains( + "auto", + ignoreCase = true + ) == true + ) + ) + } + + sources.source?.forEach { + invokeGogoSource(it, callback) + } + sources.sourceBk?.forEach { + invokeGogoSource(it, callback) + } + } + } + + + 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) + argamap( + { + normalApis.apmap { 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")?.apmap { element -> + val href = element.attr("href") ?: return@apmap + val qual = if (element.text() + .contains("HDP") + ) "1080" else qualityRegex.find(element.text())?.destructured?.component1() + .toString() + + if (!loadExtractor(href, link, subtitleCallback, callback)) { + callback.invoke( + ExtractorLink( + this.name, + name = this.name, + href, + page.url, + getQualityFromName(qual), + element.attr("href").contains(".m3u8") + ) + ) + } + } + }, { + 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 }.apmap { api -> + if (link.startsWith(api.mainUrl)) { + api.getSafeUrl(link, extractorUrl, subtitleCallback, callback) + } + } + } + } + } + ) + return true + } +} \ No newline at end of file diff --git a/VidstreamProviderTemplate/src/main/kotlin/com/lagradost/VidstreamProviderTemplate.kt b/VidstreamProviderTemplate/src/main/kotlin/com/lagradost/VidstreamProviderTemplate.kt index 247f794..751783d 100644 --- a/VidstreamProviderTemplate/src/main/kotlin/com/lagradost/VidstreamProviderTemplate.kt +++ b/VidstreamProviderTemplate/src/main/kotlin/com/lagradost/VidstreamProviderTemplate.kt @@ -1,6 +1,7 @@ package com.lagradost import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.extractors.Vidstream //import com.lagradost.cloudstream3.animeproviders.GogoanimeProvider.Companion.extractVidstream //import com.lagradost.cloudstream3.extractors.Vidstream import com.lagradost.cloudstream3.utils.ExtractorLink @@ -274,12 +275,12 @@ open class VidstreamProviderTemplate : MainAPI() { // ) // In this case the video player is a vidstream clone and can be handled by the vidstream extractor. // This case is a both unorthodox and you normally do not call extractors as they detect the url returned and does the rest. -// val vidstreamObject = Vidstream(vidstreamExtractorUrl ?: mainUrl) + val vidstreamObject = Vidstream(vidstreamExtractorUrl ?: mainUrl) // https://vidembed.cc/streaming.php?id=MzUwNTY2&... -> MzUwNTY2 val id = Regex("""id=([^&]*)""").find(iframeLink)?.groupValues?.get(1) if (id != null) { -// vidstreamObject.getUrl(id, isCasting, subtitleCallback, callback) + vidstreamObject.getUrl(id, isCasting, subtitleCallback, callback) } val html = app.get(fixUrl(iframeLink)).text diff --git a/VidstreamProviderTemplate/src/main/kotlin/com/lagradost/VidstreamProviderTemplatePlugin.kt b/VidstreamProviderTemplate/src/main/kotlin/com/lagradost/VidstreamProviderTemplatePlugin.kt index 6b26b67..2e789e4 100644 --- a/VidstreamProviderTemplate/src/main/kotlin/com/lagradost/VidstreamProviderTemplatePlugin.kt +++ b/VidstreamProviderTemplate/src/main/kotlin/com/lagradost/VidstreamProviderTemplatePlugin.kt @@ -4,11 +4,13 @@ package com.lagradost import com.lagradost.cloudstream3.plugins.CloudstreamPlugin import com.lagradost.cloudstream3.plugins.Plugin import android.content.Context +import com.lagradost.cloudstream3.extractors.Vidstream @CloudstreamPlugin class VidstreamProviderTemplatePlugin: Plugin() { override fun load(context: Context) { // All providers should be added in this manner. Please don't edit the providers list directly. + registerExtractorAPI(MultiQuality()) registerMainAPI(VidstreamProviderTemplate()) } } \ No newline at end of file diff --git a/WatchAsianProvider/build.gradle.kts b/WatchAsianProvider/build.gradle.kts index e7d2158..df3927d 100644 --- a/WatchAsianProvider/build.gradle.kts +++ b/WatchAsianProvider/build.gradle.kts @@ -1,3 +1,6 @@ +dependencies { + implementation(project(mapOf("path" to ":VidstreamProviderTemplate"))) +} // use an integer for version numbers version = 1 diff --git a/WatchAsianProvider/src/main/kotlin/com/lagradost/AsianEmbedHelper.kt b/WatchAsianProvider/src/main/kotlin/com/lagradost/AsianEmbedHelper.kt new file mode 100644 index 0000000..f6b71a1 --- /dev/null +++ b/WatchAsianProvider/src/main/kotlin/com/lagradost/AsianEmbedHelper.kt @@ -0,0 +1,32 @@ +package com.lagradost + +import android.util.Log +import com.lagradost.cloudstream3.SubtitleFile +import com.lagradost.cloudstream3.apmap +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.loadExtractor + +class AsianEmbedHelper { + companion object { + suspend fun getUrls( + url: String, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + // Fetch links + val doc = app.get(url).document + val links = doc.select("div#list-server-more > ul > li.linkserver") + if (!links.isNullOrEmpty()) { + links.apmap { + val datavid = it.attr("data-video") ?: "" + //Log.i("AsianEmbed", "Result => (datavid) ${datavid}") + if (datavid.isNotBlank()) { + val res = loadExtractor(datavid, url, subtitleCallback, callback) + Log.i("AsianEmbed", "Result => ($res) (datavid) $datavid") + } + } + } + } + } +} \ No newline at end of file diff --git a/WatchAsianProvider/src/main/kotlin/com/lagradost/WatchAsianProvider.kt b/WatchAsianProvider/src/main/kotlin/com/lagradost/WatchAsianProvider.kt index 3b59dea..84fd13a 100644 --- a/WatchAsianProvider/src/main/kotlin/com/lagradost/WatchAsianProvider.kt +++ b/WatchAsianProvider/src/main/kotlin/com/lagradost/WatchAsianProvider.kt @@ -1,9 +1,10 @@ package com.lagradost import com.lagradost.cloudstream3.* -import com.lagradost.cloudstream3.animeproviders.GogoanimeProvider.Companion.extractVidstream -import com.lagradost.cloudstream3.extractors.XStreamCdn -import com.lagradost.cloudstream3.extractors.helper.AsianEmbedHelper +import com.lagradost.cloudstream3.extractors.Vidstream +//import com.lagradost.cloudstream3.animeproviders.GogoanimeProvider.Companion.extractVidstream +//import com.lagradost.cloudstream3.extractors.XStreamCdn +//import com.lagradost.cloudstream3.extractors.helper.AsianEmbedHelper import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.ExtractorLink @@ -216,7 +217,7 @@ class WatchAsianProvider : MainAPI() { url.startsWith("https://asianembed.io") || url.startsWith("https://asianload.io") -> { val iv = "9262859232435825" val secretKey = "93422192433952489752342908585752" - extractVidstream( + Vidstream.extractVidstream( url, this.name, callback, iv, secretKey, secretKey, isUsingAdaptiveKeys = false, isUsingAdaptiveData = false diff --git a/WatchAsianProvider/src/main/kotlin/com/lagradost/WatchAsianProviderPlugin.kt b/WatchAsianProvider/src/main/kotlin/com/lagradost/WatchAsianProviderPlugin.kt index 376c416..948a677 100644 --- a/WatchAsianProvider/src/main/kotlin/com/lagradost/WatchAsianProviderPlugin.kt +++ b/WatchAsianProvider/src/main/kotlin/com/lagradost/WatchAsianProviderPlugin.kt @@ -10,5 +10,12 @@ class WatchAsianProviderPlugin: Plugin() { override fun load(context: Context) { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(WatchAsianProvider()) + registerExtractorAPI(XStreamCdn()) + registerExtractorAPI(LayarKaca()) + registerExtractorAPI(DBfilm()) + registerExtractorAPI(Luxubu()) + registerExtractorAPI(FEmbed()) + registerExtractorAPI(Fplayer()) + registerExtractorAPI(FeHD()) } } \ No newline at end of file diff --git a/WatchAsianProvider/src/main/kotlin/com/lagradost/XStreamCdn.kt b/WatchAsianProvider/src/main/kotlin/com/lagradost/XStreamCdn.kt new file mode 100644 index 0000000..f6de868 --- /dev/null +++ b/WatchAsianProvider/src/main/kotlin/com/lagradost/XStreamCdn.kt @@ -0,0 +1,93 @@ +package com.lagradost + +import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.utils.AppUtils +import com.lagradost.cloudstream3.utils.ExtractorApi +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.getQualityFromName + +class LayarKaca: XStreamCdn() { + override val name: String = "LayarKaca-xxi" + override val mainUrl: String = "https://layarkacaxxi.icu" +} + +class DBfilm: XStreamCdn() { + override val name: String = "DBfilm" + override val mainUrl: String = "https://dbfilm.bar" +} + +class Luxubu : XStreamCdn(){ + override val name: String = "FE" + override val mainUrl: String = "https://www.luxubu.review" +} + +class FEmbed: XStreamCdn() { + override val name: String = "FEmbed" + override val mainUrl: String = "https://www.fembed.com" +} + +class Fplayer: XStreamCdn() { + override val name: String = "Fplayer" + override val mainUrl: String = "https://fplayer.info" +} + +class FeHD: XStreamCdn() { + override val name: String = "FeHD" + override val mainUrl: String = "https://fembed-hd.com" + override var domainUrl: String = "fembed-hd.com" +} + +open class XStreamCdn : ExtractorApi() { + override val name: String = "XStreamCdn" + override val mainUrl: String = "https://embedsito.com" + override val requiresReferer = false + open var domainUrl: String = "embedsito.com" + + private data class ResponseData( + @JsonProperty("file") val file: String, + @JsonProperty("label") val label: String, + //val type: String // Mp4 + ) + + private data class ResponseJson( + @JsonProperty("success") val success: Boolean, + @JsonProperty("data") val data: List? + ) + + override fun getExtractorUrl(id: String): String { + return "$domainUrl/api/source/$id" + } + + override suspend fun getUrl(url: String, referer: String?): List { + val headers = mapOf( + "Referer" to url, + "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; rv:78.0) Gecko/20100101 Firefox/78.0", + ) + val id = url.trimEnd('/').split("/").last() + val newUrl = "https://${domainUrl}/api/source/${id}" + val extractedLinksList: MutableList = mutableListOf() + with(app.post(newUrl, headers = headers)) { + if (this.code != 200) return listOf() + val text = this.text + if (text.isEmpty()) return listOf() + if (text == """{"success":false,"data":"Video not found or has been removed"}""") return listOf() + AppUtils.parseJson(text)?.let { + if (it.success && it.data != null) { + it.data.forEach { data -> + extractedLinksList.add( + ExtractorLink( + name, + name = name, + data.file, + url, + getQualityFromName(data.label), + ) + ) + } + } + } + } + return extractedLinksList + } +} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 393a90a..8228533 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -80,6 +80,7 @@ subprojects { implementation("com.github.Blatzar:NiceHttp:0.3.2") // http library implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.1") implementation("org.jsoup:jsoup:1.13.1") // html parser + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4") // html parser //run JS implementation("org.mozilla:rhino:1.7.14") diff --git a/settings.gradle.kts b/settings.gradle.kts index e7988ca..a736e6c 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -12,13 +12,13 @@ include( "AsiaFlixProvider", "DoramasYTProvider", // "SflixProProvider", -// "PinoyMoviePediaProvider", + "PinoyMoviePediaProvider", "SeriesflixProvider", "TrailersTwoProvider", -// "PinoyMoviesEsProvider", + "PinoyMoviesEsProvider", "KisskhProvider", -// "DramaSeeProvider", -// "VidstreamProviderTemplate", + "DramaSeeProvider", + "VidstreamProviderTemplate", "RebahinProvider", "AllMoviesForYouProvider", "UakinoProvider", @@ -26,41 +26,41 @@ include( "FaselHDProvider", "MeloMovieProvider", "PelisplusProvider", -// "AsianLoadProvider", + "AsianLoadProvider", "YomoviesProvider", "AkwamProvider", -// "VidEmbedProvider", + "VidEmbedProvider", "IdlixProvider", "NginxProvider", "SoaptwoDayProvider", "PinoyHDXyzProvider", "AltadefinizioneProvider", "PelisflixProvider", -// "SflixProvider", + "SflixProvider", "ElifilmsProvider", -// "VidSrcProvider", + "VidSrcProvider", "EgyBestProvider", -// "WatchAsianProvider", + "WatchAsianProvider", "VfSerieProvider", "LayarKacaProvider", "EntrepeliculasyseriesProvider", "TantiFilmProvider", -// "TwoEmbedProvider", + "TwoEmbedProvider", "SuperStream", "FilmpertuttiProvider", "FrenchStreamProvider", -// "KdramaHoodProvider", + "KdramaHoodProvider", "MyCimaProvider", "IlGenioDelloStreamingProvider", "EstrenosDoramasProvider", // "HDTodayProvider", -// "DopeboxProvider", + "DopeboxProvider", "DubokuProvider", "HDMProvider", "PhimmoichillProvider", "PelisplusProviderTemplate", "OlgplyProvider", -// "SolarmovieProvider", + "SolarmovieProvider", "PeliSmartProvider", "VfFilmProvider", "IHaveNoTvProvider", @@ -70,7 +70,7 @@ include( "HDrezkaProvider", "PelisplusHDProvider", "MultiplexProvider", -// "OpenVidsProvider", + "OpenVidsProvider", //"BflixProvider", // "FmoviesToProvider", "TheFlixToProvider",