mirror of
https://github.com/recloudstream/cloudstream-extensions.git
synced 2024-08-15 03:03:54 +00:00
Fixed almost all providers
This commit is contained in:
parent
5c5a8d142f
commit
51101ae3b3
30 changed files with 565 additions and 52 deletions
|
@ -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
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
dependencies {
|
||||
implementation(project(mapOf("path" to ":VidstreamProviderTemplate")))
|
||||
}
|
||||
// use an integer for version numbers
|
||||
version = 1
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
dependencies {
|
||||
implementation(project(mapOf("path" to ":WatchAsianProvider")))
|
||||
}
|
||||
// use an integer for version numbers
|
||||
version = 1
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
dependencies {
|
||||
implementation(project(mapOf("path" to ":WatchAsianProvider")))
|
||||
}
|
||||
// use an integer for version numbers
|
||||
version = 1
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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:
|
||||
|
|
|
@ -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<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 {
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
dependencies {
|
||||
implementation(project(mapOf("path" to ":SflixProvider")))
|
||||
}
|
||||
// use an integer for version numbers
|
||||
version = 1
|
||||
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
dependencies {
|
||||
implementation(project(mapOf("path" to ":SflixProvider")))
|
||||
}
|
||||
// use an integer for version numbers
|
||||
version = 1
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
dependencies {
|
||||
implementation(project(mapOf("path" to ":VidstreamProviderTemplate")))
|
||||
}
|
||||
// use an integer for version numbers
|
||||
version = 1
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
dependencies {
|
||||
implementation(project(mapOf("path" to ":VidstreamProviderTemplate")))
|
||||
}
|
||||
// use an integer for version numbers
|
||||
version = 1
|
||||
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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")
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in a new issue