Fixed almost all providers

This commit is contained in:
Blatzar 2022-08-10 04:08:53 +02:00
parent 5c5a8d142f
commit 51101ae3b3
30 changed files with 565 additions and 52 deletions

View file

@ -1,4 +1,5 @@
dependencies { 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 // use an integer for version numbers

View file

@ -1,3 +1,6 @@
dependencies {
implementation(project(mapOf("path" to ":VidstreamProviderTemplate")))
}
// use an integer for version numbers // use an integer for version numbers
version = 1 version = 1

View file

@ -1,7 +1,8 @@
package com.lagradost package com.lagradost
import com.lagradost.cloudstream3.* 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.ExtractorLink
import com.lagradost.cloudstream3.utils.loadExtractor import com.lagradost.cloudstream3.utils.loadExtractor
@ -200,7 +201,7 @@ class DramaSeeProvider : MainAPI() {
val iv = "9262859232435825" val iv = "9262859232435825"
val secretKey = "93422192433952489752342908585752" val secretKey = "93422192433952489752342908585752"
val secretDecryptKey = "93422192433952489752342908585752" val secretDecryptKey = "93422192433952489752342908585752"
extractVidstream( Vidstream.extractVidstream(
iframe.url, iframe.url,
this.name, this.name,
callback, callback,

View file

@ -1,3 +1,7 @@
dependencies {
implementation(project(mapOf("path" to ":WatchAsianProvider")))
implementation(project(mapOf("path" to ":WatchAsianProvider")))
}
// use an integer for version numbers // use an integer for version numbers
version = 1 version = 1

View file

@ -2,8 +2,6 @@ package com.lagradost
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.* 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.mvvm.logError
import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.parseJson
import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.AppUtils.toJson

View file

@ -1,3 +1,7 @@
dependencies {
implementation(project(mapOf("path" to ":VidstreamProviderTemplate")))
implementation(project(mapOf("path" to ":VidEmbedProvider")))
}
// use an integer for version numbers // use an integer for version numbers
version = 1 version = 1

View file

@ -2,7 +2,7 @@ package com.lagradost
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.* 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.TmdbLink
import com.lagradost.cloudstream3.metaproviders.TmdbProvider import com.lagradost.cloudstream3.metaproviders.TmdbProvider
import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.parseJson
@ -115,7 +115,7 @@ class OpenVidsProvider:TmdbProvider() {
listservers.apmap { links -> listservers.apmap { links ->
if (links.contains("membed")) { if (links.contains("membed")) {
val membed = VidEmbedProvider() val membed = VidEmbedProvider()
extractVidstream( Vidstream.extractVidstream(
links, links,
this.name, this.name,
callback, callback,

View file

@ -1,3 +1,6 @@
dependencies {
implementation(project(mapOf("path" to ":WatchAsianProvider")))
}
// use an integer for version numbers // use an integer for version numbers
version = 1 version = 1

View file

@ -1,7 +1,7 @@
package com.lagradost package com.lagradost
import com.lagradost.cloudstream3.* 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.toJson
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink

View file

@ -1,3 +1,6 @@
dependencies {
implementation(project(mapOf("path" to ":WatchAsianProvider")))
}
// use an integer for version numbers // use an integer for version numbers
version = 1 version = 1

View file

@ -2,8 +2,8 @@ package com.lagradost
import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.annotation.JsonProperty
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.extractors.FEmbed //import com.lagradost.cloudstream3.extractors.FEmbed
import com.lagradost.cloudstream3.extractors.helper.VstreamhubHelper //import com.lagradost.cloudstream3.extractors.helper.VstreamhubHelper
import com.lagradost.cloudstream3.network.DdosGuardKiller import com.lagradost.cloudstream3.network.DdosGuardKiller
import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.AppUtils.toJson
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson

View file

@ -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}")
}
}
}
}
}
}
}
}

View file

@ -1,16 +1,11 @@
**⚠️ This is currently under development, dont use it yet if you're not comfortable with constantly merging new changes** **⚠️ 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
**⚠️ Make sure you check "Include all branches" when using this template**
Not all extractors are included, only those need to compile. We need to use loadExtractor in the future.
## Getting started with writing your first plugin ## 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 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 2. Familiarize yourself with the project structure. Most files are commented
3. Build or deploy your first plugin using: 3. Build or deploy your first plugin using:

View file

@ -8,9 +8,7 @@ import com.lagradost.cloudstream3.APIHolder.unixTimeMS
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
import com.lagradost.cloudstream3.LoadResponse.Companion.addDuration import com.lagradost.cloudstream3.LoadResponse.Companion.addDuration
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
import com.lagradost.cloudstream3.animeproviders.ZoroProvider //import com.lagradost.cloudstream3.animeproviders.ZoroProvider
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
import com.lagradost.cloudstream3.mvvm.safeApiCall
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.parseJson
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
@ -678,19 +676,19 @@ open class SflixProvider : MainAPI() {
var sid: String? = null var sid: String? = null
if (useSidAuthentication && extractorData != null) { if (useSidAuthentication && extractorData != null) {
negotiateNewSid(extractorData)?.also { negotiateNewSid(extractorData)?.also { pollingData ->
app.post( app.post(
"$extractorData&t=${generateTimeStamp()}&sid=${it.sid}", "$extractorData&t=${generateTimeStamp()}&sid=${pollingData.sid}",
requestBody = "40".toRequestBody(), requestBody = "40".toRequestBody(),
timeout = 60 timeout = 60
) )
val text = app.get( val text = app.get(
"$extractorData&t=${generateTimeStamp()}&sid=${it.sid}", "$extractorData&t=${generateTimeStamp()}&sid=${pollingData.sid}",
timeout = 60 timeout = 60
).text.replaceBefore("{", "") ).text.replaceBefore("{", "")
sid = parseJson<PollingData>(text).sid sid = parseJson<PollingData>(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 { ?.forEach {
// Sets Zoro SID used for video loading // 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) callback(it)
} }
} }

View file

@ -1,3 +1,6 @@
dependencies {
implementation(project(mapOf("path" to ":SflixProvider")))
}
// use an integer for version numbers // use an integer for version numbers
version = 1 version = 1

View file

@ -1,3 +1,6 @@
dependencies {
implementation(project(mapOf("path" to ":SflixProvider")))
}
// use an integer for version numbers // use an integer for version numbers
version = 1 version = 1

View file

@ -2,6 +2,8 @@ package com.lagradost
import android.util.Log import android.util.Log
import com.fasterxml.jackson.annotation.JsonProperty 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.APIHolder.getCaptchaToken
import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.SubtitleFile
import com.lagradost.cloudstream3.TvType import com.lagradost.cloudstream3.TvType
@ -9,8 +11,6 @@ import com.lagradost.cloudstream3.apmap
import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.app
import com.lagradost.cloudstream3.metaproviders.TmdbLink import com.lagradost.cloudstream3.metaproviders.TmdbLink
import com.lagradost.cloudstream3.metaproviders.TmdbProvider 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.AppUtils.parseJson
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.loadExtractor import com.lagradost.cloudstream3.utils.loadExtractor

View file

@ -1,3 +1,6 @@
dependencies {
implementation(project(mapOf("path" to ":VidstreamProviderTemplate")))
}
// use an integer for version numbers // use an integer for version numbers
version = 1 version = 1

View file

@ -2,11 +2,12 @@ package com.lagradost
import com.lagradost.cloudstream3.SubtitleFile import com.lagradost.cloudstream3.SubtitleFile
import com.lagradost.cloudstream3.TvType 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.TmdbLink
import com.lagradost.cloudstream3.metaproviders.TmdbProvider import com.lagradost.cloudstream3.metaproviders.TmdbProvider
import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.parseJson
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
import com.lagradost.cloudstream3.utils.loadExtractor
class VidSrcProvider : TmdbProvider() { class VidSrcProvider : TmdbProvider() {
override val apiName = "VidSrc" override val apiName = "VidSrc"
@ -19,9 +20,9 @@ class VidSrcProvider : TmdbProvider() {
TvType.TvSeries, TvType.TvSeries,
) )
companion object { // companion object {
val extractor = VidSrcExtractor() // val extractor = VidSrcExtractor()
} // }
override suspend fun loadLinks( override suspend fun loadLinks(
data: String, data: String,
@ -44,7 +45,8 @@ class VidSrcProvider : TmdbProvider() {
"$mainUrl/embed/$suffix" "$mainUrl/embed/$suffix"
} }
extractor.getSafeUrl(embedUrl, null, subtitleCallback, callback) loadExtractor(embedUrl, null, subtitleCallback, callback)
// extractor.getSafeUrl(embedUrl, null, subtitleCallback, callback)
return true return true
} }

View file

@ -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<ExtractorLink> {
val extractedLinksList: MutableList<ExtractorLink> = 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
}
}
}

View file

@ -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<GogoSource>?,
@JsonProperty("sourceBk") val sourceBk: List<GogoSource>?,
//val track: List<Any?>,
//val advertising: List<Any?>,
//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<GogoSources>(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<ExtractorLink> = 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
}
}

View file

@ -1,6 +1,7 @@
package com.lagradost package com.lagradost
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.extractors.Vidstream
//import com.lagradost.cloudstream3.animeproviders.GogoanimeProvider.Companion.extractVidstream //import com.lagradost.cloudstream3.animeproviders.GogoanimeProvider.Companion.extractVidstream
//import com.lagradost.cloudstream3.extractors.Vidstream //import com.lagradost.cloudstream3.extractors.Vidstream
import com.lagradost.cloudstream3.utils.ExtractorLink 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. // 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. // 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 // https://vidembed.cc/streaming.php?id=MzUwNTY2&... -> MzUwNTY2
val id = Regex("""id=([^&]*)""").find(iframeLink)?.groupValues?.get(1) val id = Regex("""id=([^&]*)""").find(iframeLink)?.groupValues?.get(1)
if (id != null) { if (id != null) {
// vidstreamObject.getUrl(id, isCasting, subtitleCallback, callback) vidstreamObject.getUrl(id, isCasting, subtitleCallback, callback)
} }
val html = app.get(fixUrl(iframeLink)).text val html = app.get(fixUrl(iframeLink)).text

View file

@ -4,11 +4,13 @@ package com.lagradost
import com.lagradost.cloudstream3.plugins.CloudstreamPlugin import com.lagradost.cloudstream3.plugins.CloudstreamPlugin
import com.lagradost.cloudstream3.plugins.Plugin import com.lagradost.cloudstream3.plugins.Plugin
import android.content.Context import android.content.Context
import com.lagradost.cloudstream3.extractors.Vidstream
@CloudstreamPlugin @CloudstreamPlugin
class VidstreamProviderTemplatePlugin: Plugin() { class VidstreamProviderTemplatePlugin: Plugin() {
override fun load(context: Context) { override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly. // All providers should be added in this manner. Please don't edit the providers list directly.
registerExtractorAPI(MultiQuality())
registerMainAPI(VidstreamProviderTemplate()) registerMainAPI(VidstreamProviderTemplate())
} }
} }

View file

@ -1,3 +1,6 @@
dependencies {
implementation(project(mapOf("path" to ":VidstreamProviderTemplate")))
}
// use an integer for version numbers // use an integer for version numbers
version = 1 version = 1

View file

@ -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")
}
}
}
}
}
}

View file

@ -1,9 +1,10 @@
package com.lagradost package com.lagradost
import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.*
import com.lagradost.cloudstream3.animeproviders.GogoanimeProvider.Companion.extractVidstream import com.lagradost.cloudstream3.extractors.Vidstream
import com.lagradost.cloudstream3.extractors.XStreamCdn //import com.lagradost.cloudstream3.animeproviders.GogoanimeProvider.Companion.extractVidstream
import com.lagradost.cloudstream3.extractors.helper.AsianEmbedHelper //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.parseJson
import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.AppUtils.toJson
import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.ExtractorLink
@ -216,7 +217,7 @@ class WatchAsianProvider : MainAPI() {
url.startsWith("https://asianembed.io") || url.startsWith("https://asianload.io") -> { url.startsWith("https://asianembed.io") || url.startsWith("https://asianload.io") -> {
val iv = "9262859232435825" val iv = "9262859232435825"
val secretKey = "93422192433952489752342908585752" val secretKey = "93422192433952489752342908585752"
extractVidstream( Vidstream.extractVidstream(
url, this.name, callback, iv, secretKey, secretKey, url, this.name, callback, iv, secretKey, secretKey,
isUsingAdaptiveKeys = false, isUsingAdaptiveKeys = false,
isUsingAdaptiveData = false isUsingAdaptiveData = false

View file

@ -10,5 +10,12 @@ class WatchAsianProviderPlugin: Plugin() {
override fun load(context: Context) { override fun load(context: Context) {
// All providers should be added in this manner. Please don't edit the providers list directly. // All providers should be added in this manner. Please don't edit the providers list directly.
registerMainAPI(WatchAsianProvider()) registerMainAPI(WatchAsianProvider())
registerExtractorAPI(XStreamCdn())
registerExtractorAPI(LayarKaca())
registerExtractorAPI(DBfilm())
registerExtractorAPI(Luxubu())
registerExtractorAPI(FEmbed())
registerExtractorAPI(Fplayer())
registerExtractorAPI(FeHD())
} }
} }

View file

@ -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<ResponseData>?
)
override fun getExtractorUrl(id: String): String {
return "$domainUrl/api/source/$id"
}
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> {
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<ExtractorLink> = 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<ResponseJson?>(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
}
}

View file

@ -80,6 +80,7 @@ subprojects {
implementation("com.github.Blatzar:NiceHttp:0.3.2") // http library implementation("com.github.Blatzar:NiceHttp:0.3.2") // http library
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.1") implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.13.1")
implementation("org.jsoup:jsoup:1.13.1") // html parser implementation("org.jsoup:jsoup:1.13.1") // html parser
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4") // html parser
//run JS //run JS
implementation("org.mozilla:rhino:1.7.14") implementation("org.mozilla:rhino:1.7.14")

View file

@ -12,13 +12,13 @@ include(
"AsiaFlixProvider", "AsiaFlixProvider",
"DoramasYTProvider", "DoramasYTProvider",
// "SflixProProvider", // "SflixProProvider",
// "PinoyMoviePediaProvider", "PinoyMoviePediaProvider",
"SeriesflixProvider", "SeriesflixProvider",
"TrailersTwoProvider", "TrailersTwoProvider",
// "PinoyMoviesEsProvider", "PinoyMoviesEsProvider",
"KisskhProvider", "KisskhProvider",
// "DramaSeeProvider", "DramaSeeProvider",
// "VidstreamProviderTemplate", "VidstreamProviderTemplate",
"RebahinProvider", "RebahinProvider",
"AllMoviesForYouProvider", "AllMoviesForYouProvider",
"UakinoProvider", "UakinoProvider",
@ -26,41 +26,41 @@ include(
"FaselHDProvider", "FaselHDProvider",
"MeloMovieProvider", "MeloMovieProvider",
"PelisplusProvider", "PelisplusProvider",
// "AsianLoadProvider", "AsianLoadProvider",
"YomoviesProvider", "YomoviesProvider",
"AkwamProvider", "AkwamProvider",
// "VidEmbedProvider", "VidEmbedProvider",
"IdlixProvider", "IdlixProvider",
"NginxProvider", "NginxProvider",
"SoaptwoDayProvider", "SoaptwoDayProvider",
"PinoyHDXyzProvider", "PinoyHDXyzProvider",
"AltadefinizioneProvider", "AltadefinizioneProvider",
"PelisflixProvider", "PelisflixProvider",
// "SflixProvider", "SflixProvider",
"ElifilmsProvider", "ElifilmsProvider",
// "VidSrcProvider", "VidSrcProvider",
"EgyBestProvider", "EgyBestProvider",
// "WatchAsianProvider", "WatchAsianProvider",
"VfSerieProvider", "VfSerieProvider",
"LayarKacaProvider", "LayarKacaProvider",
"EntrepeliculasyseriesProvider", "EntrepeliculasyseriesProvider",
"TantiFilmProvider", "TantiFilmProvider",
// "TwoEmbedProvider", "TwoEmbedProvider",
"SuperStream", "SuperStream",
"FilmpertuttiProvider", "FilmpertuttiProvider",
"FrenchStreamProvider", "FrenchStreamProvider",
// "KdramaHoodProvider", "KdramaHoodProvider",
"MyCimaProvider", "MyCimaProvider",
"IlGenioDelloStreamingProvider", "IlGenioDelloStreamingProvider",
"EstrenosDoramasProvider", "EstrenosDoramasProvider",
// "HDTodayProvider", // "HDTodayProvider",
// "DopeboxProvider", "DopeboxProvider",
"DubokuProvider", "DubokuProvider",
"HDMProvider", "HDMProvider",
"PhimmoichillProvider", "PhimmoichillProvider",
"PelisplusProviderTemplate", "PelisplusProviderTemplate",
"OlgplyProvider", "OlgplyProvider",
// "SolarmovieProvider", "SolarmovieProvider",
"PeliSmartProvider", "PeliSmartProvider",
"VfFilmProvider", "VfFilmProvider",
"IHaveNoTvProvider", "IHaveNoTvProvider",
@ -70,7 +70,7 @@ include(
"HDrezkaProvider", "HDrezkaProvider",
"PelisplusHDProvider", "PelisplusHDProvider",
"MultiplexProvider", "MultiplexProvider",
// "OpenVidsProvider", "OpenVidsProvider",
//"BflixProvider", //"BflixProvider",
// "FmoviesToProvider", // "FmoviesToProvider",
"TheFlixToProvider", "TheFlixToProvider",