mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
7294b21a9e
5 changed files with 60 additions and 28 deletions
|
@ -6,6 +6,7 @@ import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||||
import com.lagradost.cloudstream3.utils.*
|
import com.lagradost.cloudstream3.utils.*
|
||||||
import org.jsoup.Jsoup
|
import org.jsoup.Jsoup
|
||||||
|
import org.jsoup.nodes.Document
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import javax.crypto.Cipher
|
import javax.crypto.Cipher
|
||||||
|
@ -34,7 +35,7 @@ class GogoanimeProvider : MainAPI() {
|
||||||
* */
|
* */
|
||||||
private fun getKey(id: String): String? {
|
private fun getKey(id: String): String? {
|
||||||
return normalSafeApiCall {
|
return normalSafeApiCall {
|
||||||
id.map {
|
id.map {
|
||||||
it.code.toString(16)
|
it.code.toString(16)
|
||||||
}.joinToString("").substring(0, 32)
|
}.joinToString("").substring(0, 32)
|
||||||
}
|
}
|
||||||
|
@ -77,6 +78,7 @@ class GogoanimeProvider : MainAPI() {
|
||||||
* @param secretKey secret key for decryption 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 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 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(
|
suspend fun extractVidstream(
|
||||||
iframeUrl: String,
|
iframeUrl: String,
|
||||||
|
@ -86,7 +88,8 @@ class GogoanimeProvider : MainAPI() {
|
||||||
secretKey: String?,
|
secretKey: String?,
|
||||||
secretDecryptKey: String?,
|
secretDecryptKey: String?,
|
||||||
// This could be removed, but i prefer it verbose
|
// This could be removed, but i prefer it verbose
|
||||||
isUsingAdaptiveKeys: Boolean
|
isUsingAdaptiveKeys: Boolean,
|
||||||
|
isUsingAdaptiveData: Boolean
|
||||||
) = safeApiCall {
|
) = safeApiCall {
|
||||||
// https://github.com/saikou-app/saikou/blob/3e756bd8e876ad7a9318b17110526880525a5cd3/app/src/main/java/ani/saikou/anime/source/extractors/GogoCDN.kt
|
// 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
|
// No Licence on the following code
|
||||||
|
@ -98,8 +101,10 @@ class GogoanimeProvider : MainAPI() {
|
||||||
|
|
||||||
val id = Regex("id=([^&]+)").find(iframeUrl)!!.value.removePrefix("id=")
|
val id = Regex("id=([^&]+)").find(iframeUrl)!!.value.removePrefix("id=")
|
||||||
|
|
||||||
|
var document: Document? = null
|
||||||
val foundIv =
|
val foundIv =
|
||||||
iv ?: app.get(iframeUrl).document.select("""div.wrapper[class*=container]""")
|
iv ?: app.get(iframeUrl).document.also { document = it }
|
||||||
|
.select("""div.wrapper[class*=container]""")
|
||||||
.attr("class").split("-").lastOrNull() ?: return@safeApiCall
|
.attr("class").split("-").lastOrNull() ?: return@safeApiCall
|
||||||
val foundKey = secretKey ?: getKey(base64Decode(id) + foundIv) ?: return@safeApiCall
|
val foundKey = secretKey ?: getKey(base64Decode(id) + foundIv) ?: return@safeApiCall
|
||||||
val foundDecryptKey = secretDecryptKey ?: foundKey
|
val foundDecryptKey = secretDecryptKey ?: foundKey
|
||||||
|
@ -108,9 +113,19 @@ class GogoanimeProvider : MainAPI() {
|
||||||
val mainUrl = "https://" + uri.host
|
val mainUrl = "https://" + uri.host
|
||||||
|
|
||||||
val encryptedId = cryptoHandler(id, foundIv, foundKey)
|
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 =
|
val jsonResponse =
|
||||||
app.get(
|
app.get(
|
||||||
"$mainUrl/encrypt-ajax.php?id=$encryptedId&alias=$id",
|
"$mainUrl/encrypt-ajax.php?$encryptRequestData",
|
||||||
headers = mapOf("X-Requested-With" to "XMLHttpRequest")
|
headers = mapOf("X-Requested-With" to "XMLHttpRequest")
|
||||||
)
|
)
|
||||||
val dataencrypted =
|
val dataencrypted =
|
||||||
|
@ -129,7 +144,7 @@ class GogoanimeProvider : MainAPI() {
|
||||||
source.file,
|
source.file,
|
||||||
mainUrl,
|
mainUrl,
|
||||||
headers = mapOf("Referer" to "https://gogoplay4.com")
|
headers = mapOf("Referer" to "https://gogoplay4.com")
|
||||||
).forEach (sourceCallback)
|
).forEach(sourceCallback)
|
||||||
}
|
}
|
||||||
source.file.contains("vidstreaming") -> {
|
source.file.contains("vidstreaming") -> {
|
||||||
sourceCallback.invoke(
|
sourceCallback.invoke(
|
||||||
|
@ -382,9 +397,9 @@ class GogoanimeProvider : MainAPI() {
|
||||||
loadExtractor(data, streamingResponse.url, callback)
|
loadExtractor(data, streamingResponse.url, callback)
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
val iv = "4968442212618524"
|
val iv = "3134003223491201"
|
||||||
val secretKey = "34541577475429958244002440089157"
|
val secretKey = "37911490979715163134003223491201"
|
||||||
val secretDecryptKey = "20945647121183498244002440089157"
|
val secretDecryptKey = "54674138327930866480207815084989"
|
||||||
extractVidstream(
|
extractVidstream(
|
||||||
iframe,
|
iframe,
|
||||||
this.name,
|
this.name,
|
||||||
|
@ -392,7 +407,8 @@ class GogoanimeProvider : MainAPI() {
|
||||||
iv,
|
iv,
|
||||||
secretKey,
|
secretKey,
|
||||||
secretDecryptKey,
|
secretDecryptKey,
|
||||||
false
|
isUsingAdaptiveKeys = false,
|
||||||
|
isUsingAdaptiveData = true
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
package com.lagradost.cloudstream3.extractors
|
package com.lagradost.cloudstream3.extractors
|
||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty
|
import com.fasterxml.jackson.annotation.JsonProperty
|
||||||
import com.fasterxml.jackson.module.kotlin.readValue
|
|
||||||
import com.lagradost.cloudstream3.apmap
|
import com.lagradost.cloudstream3.apmap
|
||||||
import com.lagradost.cloudstream3.app
|
import com.lagradost.cloudstream3.app
|
||||||
import com.lagradost.cloudstream3.mapper
|
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorApi
|
import com.lagradost.cloudstream3.utils.ExtractorApi
|
||||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||||
import com.lagradost.cloudstream3.utils.M3u8Helper.Companion.generateM3u8
|
import com.lagradost.cloudstream3.utils.M3u8Helper.Companion.generateM3u8
|
||||||
|
@ -48,7 +46,7 @@ class VizcloudDigital : WcoStream() {
|
||||||
}
|
}
|
||||||
|
|
||||||
open class WcoStream : ExtractorApi() {
|
open class WcoStream : ExtractorApi() {
|
||||||
override var name = "VidStream" //Cause works for animekisa and wco
|
override var name = "VidStream" // Cause works for animekisa and wco
|
||||||
override var mainUrl = "https://vidstream.pro"
|
override var mainUrl = "https://vidstream.pro"
|
||||||
override val requiresReferer = false
|
override val requiresReferer = false
|
||||||
|
|
||||||
|
@ -65,8 +63,6 @@ open class WcoStream : ExtractorApi() {
|
||||||
val apiLink = "$baseUrl/info/$Id?domain=wcostream.cc&skey=$skey"
|
val apiLink = "$baseUrl/info/$Id?domain=wcostream.cc&skey=$skey"
|
||||||
val referrer = "$baseUrl/e/$Id?domain=wcostream.cc"
|
val referrer = "$baseUrl/e/$Id?domain=wcostream.cc"
|
||||||
|
|
||||||
val response = app.get(apiLink, headers = mapOf("Referer" to referrer)).text
|
|
||||||
|
|
||||||
data class Sources(
|
data class Sources(
|
||||||
@JsonProperty("file") val file: String,
|
@JsonProperty("file") val file: String,
|
||||||
@JsonProperty("label") val label: String?
|
@JsonProperty("label") val label: String?
|
||||||
|
@ -81,14 +77,14 @@ open class WcoStream : ExtractorApi() {
|
||||||
@JsonProperty("media") val media: Media
|
@JsonProperty("media") val media: Media
|
||||||
)
|
)
|
||||||
|
|
||||||
val mapped = response.let { mapper.readValue<WcoResponse>(it) }
|
val mapped = app.get(apiLink, headers = mapOf("Referer" to referrer)).mapped<WcoResponse>()
|
||||||
val sources = mutableListOf<ExtractorLink>()
|
val sources = mutableListOf<ExtractorLink>()
|
||||||
|
|
||||||
if (mapped.success) {
|
if (mapped.success) {
|
||||||
mapped.media.sources.forEach {
|
mapped.media.sources.forEach {
|
||||||
if (mainUrl == "https://vizcloud2.ru" || mainUrl == "https://vizcloud.online") {
|
if (mainUrl == "https://vizcloud2.ru" || mainUrl == "https://vizcloud.online") {
|
||||||
if (it.file.contains("vizcloud2.ru") || it.file.contains("vizcloud.online")) {
|
if (it.file.contains("vizcloud2.ru") || it.file.contains("vizcloud.online")) {
|
||||||
//Had to do this thing 'cause "list.m3u8#.mp4" gives 404 error so no quality is added
|
// Had to do this thing 'cause "list.m3u8#.mp4" gives 404 error so no quality is added
|
||||||
val link1080 = it.file.replace("list.m3u8#.mp4", "H4/v.m3u8")
|
val link1080 = it.file.replace("list.m3u8#.mp4", "H4/v.m3u8")
|
||||||
val link720 = it.file.replace("list.m3u8#.mp4", "H3/v.m3u8")
|
val link720 = it.file.replace("list.m3u8#.mp4", "H3/v.m3u8")
|
||||||
val link480 = it.file.replace("list.m3u8#.mp4", "H2/v.m3u8")
|
val link480 = it.file.replace("list.m3u8#.mp4", "H2/v.m3u8")
|
||||||
|
@ -123,17 +119,26 @@ open class WcoStream : ExtractorApi() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (
|
||||||
if (mainUrl == "https://vidstream.pro" || mainUrl == "https://vidstreamz.online" || mainUrl == "https://vizcloud2.online"
|
arrayOf(
|
||||||
|| mainUrl == "https://vizcloud.xyz" || mainUrl == "https://vizcloud.live" || mainUrl == "https://vizcloud.info"
|
"https://vidstream.pro",
|
||||||
|| mainUrl == "https://mwvn.vizcloud.info" || mainUrl == "https://vizcloud.digital"
|
"https://vidstreamz.online",
|
||||||
|
"https://vizcloud2.online",
|
||||||
|
"https://vizcloud.xyz",
|
||||||
|
"https://vizcloud.live",
|
||||||
|
"https://vizcloud.info",
|
||||||
|
"https://mwvn.vizcloud.info",
|
||||||
|
"https://vizcloud.digital"
|
||||||
|
).contains(mainUrl)
|
||||||
) {
|
) {
|
||||||
if (it.file.contains("m3u8")) {
|
if (it.file.contains("m3u8")) {
|
||||||
generateM3u8(
|
sources.addAll(
|
||||||
name,
|
generateM3u8(
|
||||||
it.file.replace("#.mp4", ""),
|
name,
|
||||||
url,
|
it.file.replace("#.mp4", ""),
|
||||||
headers = mapOf("Referer" to url)
|
url,
|
||||||
|
headers = mapOf("Referer" to url)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
sources.add(
|
sources.add(
|
||||||
|
|
|
@ -199,7 +199,10 @@ class DramaSeeProvider : 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(url, this.name, callback, iv, secretKey, secretKey, false)
|
extractVidstream(url, this.name, callback, iv, secretKey, secretKey,
|
||||||
|
isUsingAdaptiveKeys = false,
|
||||||
|
isUsingAdaptiveData = false
|
||||||
|
)
|
||||||
AsianEmbedHelper.getUrls(url, callback)
|
AsianEmbedHelper.getUrls(url, callback)
|
||||||
}
|
}
|
||||||
url.startsWith("https://embedsito.com") -> {
|
url.startsWith("https://embedsito.com") -> {
|
||||||
|
|
|
@ -69,6 +69,11 @@ open class VidstreamProviderTemplate : MainAPI() {
|
||||||
open val secretDecryptKey: String? = null
|
open val secretDecryptKey: String? = null
|
||||||
/** Generated the key from IV and ID */
|
/** Generated the key from IV and ID */
|
||||||
open val isUsingAdaptiveKeys: Boolean = false
|
open val isUsingAdaptiveKeys: Boolean = false
|
||||||
|
/**
|
||||||
|
* Generate data for the encrypt-ajax automatically (only on supported sites)
|
||||||
|
* See $("script[data-name='episode']")[0].dataset.value
|
||||||
|
* */
|
||||||
|
open val isUsingAdaptiveData: Boolean = false
|
||||||
|
|
||||||
|
|
||||||
// // mainUrl is good to have as a holder for the url to make future changes easier.
|
// // mainUrl is good to have as a holder for the url to make future changes easier.
|
||||||
|
@ -255,7 +260,7 @@ open class VidstreamProviderTemplate : MainAPI() {
|
||||||
val iframeLink =
|
val iframeLink =
|
||||||
Jsoup.parse(app.get(data).text).selectFirst("iframe")?.attr("src") ?: return false
|
Jsoup.parse(app.get(data).text).selectFirst("iframe")?.attr("src") ?: return false
|
||||||
|
|
||||||
extractVidstream(iframeLink, this.name, callback, iv, secretKey, secretDecryptKey, isUsingAdaptiveKeys)
|
extractVidstream(iframeLink, this.name, callback, iv, secretKey, secretDecryptKey, isUsingAdaptiveKeys, isUsingAdaptiveData)
|
||||||
// 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)
|
||||||
|
|
|
@ -216,7 +216,10 @@ 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(url, this.name, callback, iv, secretKey, secretKey, false)
|
extractVidstream(url, this.name, callback, iv, secretKey, secretKey,
|
||||||
|
isUsingAdaptiveKeys = false,
|
||||||
|
isUsingAdaptiveData = false
|
||||||
|
)
|
||||||
AsianEmbedHelper.getUrls(url, callback)
|
AsianEmbedHelper.getUrls(url, callback)
|
||||||
}
|
}
|
||||||
url.startsWith("https://embedsito.com") -> {
|
url.startsWith("https://embedsito.com") -> {
|
||||||
|
|
Loading…
Reference in a new issue