mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	Fixed Bflix Vidstream and the Vidstream provider
This commit is contained in:
		
							parent
							
								
									30fddb0360
								
							
						
					
					
						commit
						f27e25b15b
					
				
					 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.utils.*
 | 
			
		||||
import org.jsoup.Jsoup
 | 
			
		||||
import org.jsoup.nodes.Document
 | 
			
		||||
import java.net.URI
 | 
			
		||||
import java.util.*
 | 
			
		||||
import javax.crypto.Cipher
 | 
			
		||||
| 
						 | 
				
			
			@ -34,7 +35,7 @@ class GogoanimeProvider : MainAPI() {
 | 
			
		|||
         * */
 | 
			
		||||
        private fun getKey(id: String): String? {
 | 
			
		||||
            return normalSafeApiCall {
 | 
			
		||||
                 id.map {
 | 
			
		||||
                id.map {
 | 
			
		||||
                    it.code.toString(16)
 | 
			
		||||
                }.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 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,
 | 
			
		||||
| 
						 | 
				
			
			@ -86,7 +88,8 @@ class GogoanimeProvider : MainAPI() {
 | 
			
		|||
            secretKey: String?,
 | 
			
		||||
            secretDecryptKey: String?,
 | 
			
		||||
            // This could be removed, but i prefer it verbose
 | 
			
		||||
            isUsingAdaptiveKeys: Boolean
 | 
			
		||||
            isUsingAdaptiveKeys: Boolean,
 | 
			
		||||
            isUsingAdaptiveData: Boolean
 | 
			
		||||
        ) = 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
 | 
			
		||||
| 
						 | 
				
			
			@ -98,8 +101,10 @@ class GogoanimeProvider : MainAPI() {
 | 
			
		|||
 | 
			
		||||
            val id = Regex("id=([^&]+)").find(iframeUrl)!!.value.removePrefix("id=")
 | 
			
		||||
 | 
			
		||||
            var document: Document? = null
 | 
			
		||||
            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
 | 
			
		||||
            val foundKey = secretKey ?: getKey(base64Decode(id) + foundIv) ?: return@safeApiCall
 | 
			
		||||
            val foundDecryptKey = secretDecryptKey ?: foundKey
 | 
			
		||||
| 
						 | 
				
			
			@ -108,9 +113,19 @@ class GogoanimeProvider : MainAPI() {
 | 
			
		|||
            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?id=$encryptedId&alias=$id",
 | 
			
		||||
                    "$mainUrl/encrypt-ajax.php?$encryptRequestData",
 | 
			
		||||
                    headers = mapOf("X-Requested-With" to "XMLHttpRequest")
 | 
			
		||||
                )
 | 
			
		||||
            val dataencrypted =
 | 
			
		||||
| 
						 | 
				
			
			@ -129,7 +144,7 @@ class GogoanimeProvider : MainAPI() {
 | 
			
		|||
                            source.file,
 | 
			
		||||
                            mainUrl,
 | 
			
		||||
                            headers = mapOf("Referer" to "https://gogoplay4.com")
 | 
			
		||||
                        ).forEach (sourceCallback)
 | 
			
		||||
                        ).forEach(sourceCallback)
 | 
			
		||||
                    }
 | 
			
		||||
                    source.file.contains("vidstreaming") -> {
 | 
			
		||||
                        sourceCallback.invoke(
 | 
			
		||||
| 
						 | 
				
			
			@ -382,9 +397,9 @@ class GogoanimeProvider : MainAPI() {
 | 
			
		|||
                            loadExtractor(data, streamingResponse.url, callback)
 | 
			
		||||
                        }
 | 
			
		||||
                }, {
 | 
			
		||||
                    val iv = "4968442212618524"
 | 
			
		||||
                    val secretKey = "34541577475429958244002440089157"
 | 
			
		||||
                    val secretDecryptKey = "20945647121183498244002440089157"
 | 
			
		||||
                    val iv = "3134003223491201"
 | 
			
		||||
                    val secretKey = "37911490979715163134003223491201"
 | 
			
		||||
                    val secretDecryptKey = "54674138327930866480207815084989"
 | 
			
		||||
                    extractVidstream(
 | 
			
		||||
                        iframe,
 | 
			
		||||
                        this.name,
 | 
			
		||||
| 
						 | 
				
			
			@ -392,7 +407,8 @@ class GogoanimeProvider : MainAPI() {
 | 
			
		|||
                        iv,
 | 
			
		||||
                        secretKey,
 | 
			
		||||
                        secretDecryptKey,
 | 
			
		||||
                        false
 | 
			
		||||
                        isUsingAdaptiveKeys = false,
 | 
			
		||||
                        isUsingAdaptiveData = true
 | 
			
		||||
                    )
 | 
			
		||||
                })
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,10 +1,8 @@
 | 
			
		|||
package com.lagradost.cloudstream3.extractors
 | 
			
		||||
 | 
			
		||||
import com.fasterxml.jackson.annotation.JsonProperty
 | 
			
		||||
import com.fasterxml.jackson.module.kotlin.readValue
 | 
			
		||||
import com.lagradost.cloudstream3.apmap
 | 
			
		||||
import com.lagradost.cloudstream3.app
 | 
			
		||||
import com.lagradost.cloudstream3.mapper
 | 
			
		||||
import com.lagradost.cloudstream3.utils.ExtractorApi
 | 
			
		||||
import com.lagradost.cloudstream3.utils.ExtractorLink
 | 
			
		||||
import com.lagradost.cloudstream3.utils.M3u8Helper.Companion.generateM3u8
 | 
			
		||||
| 
						 | 
				
			
			@ -48,7 +46,7 @@ class VizcloudDigital : WcoStream() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
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 val requiresReferer = false
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -65,8 +63,6 @@ open class WcoStream : ExtractorApi() {
 | 
			
		|||
        val apiLink = "$baseUrl/info/$Id?domain=wcostream.cc&skey=$skey"
 | 
			
		||||
        val referrer = "$baseUrl/e/$Id?domain=wcostream.cc"
 | 
			
		||||
 | 
			
		||||
        val response = app.get(apiLink, headers = mapOf("Referer" to referrer)).text
 | 
			
		||||
 | 
			
		||||
        data class Sources(
 | 
			
		||||
            @JsonProperty("file") val file: String,
 | 
			
		||||
            @JsonProperty("label") val label: String?
 | 
			
		||||
| 
						 | 
				
			
			@ -81,14 +77,14 @@ open class WcoStream : ExtractorApi() {
 | 
			
		|||
            @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>()
 | 
			
		||||
 | 
			
		||||
        if (mapped.success) {
 | 
			
		||||
            mapped.media.sources.forEach {
 | 
			
		||||
                if (mainUrl == "https://vizcloud2.ru" || mainUrl == "https://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 link720 = it.file.replace("list.m3u8#.mp4", "H3/v.m3u8")
 | 
			
		||||
                        val link480 = it.file.replace("list.m3u8#.mp4", "H2/v.m3u8")
 | 
			
		||||
| 
						 | 
				
			
			@ -123,17 +119,26 @@ open class WcoStream : ExtractorApi() {
 | 
			
		|||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                if (mainUrl == "https://vidstream.pro" || mainUrl == "https://vidstreamz.online" || mainUrl == "https://vizcloud2.online"
 | 
			
		||||
                    || mainUrl == "https://vizcloud.xyz" || mainUrl == "https://vizcloud.live" || mainUrl == "https://vizcloud.info"
 | 
			
		||||
                    || mainUrl == "https://mwvn.vizcloud.info" || mainUrl == "https://vizcloud.digital"
 | 
			
		||||
                } else if (
 | 
			
		||||
                    arrayOf(
 | 
			
		||||
                        "https://vidstream.pro",
 | 
			
		||||
                        "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")) {
 | 
			
		||||
                        generateM3u8(
 | 
			
		||||
                            name,
 | 
			
		||||
                            it.file.replace("#.mp4", ""),
 | 
			
		||||
                            url,
 | 
			
		||||
                            headers = mapOf("Referer" to url)
 | 
			
		||||
                        sources.addAll(
 | 
			
		||||
                            generateM3u8(
 | 
			
		||||
                                name,
 | 
			
		||||
                                it.file.replace("#.mp4", ""),
 | 
			
		||||
                                url,
 | 
			
		||||
                                headers = mapOf("Referer" to url)
 | 
			
		||||
                            )
 | 
			
		||||
                        )
 | 
			
		||||
                    } else {
 | 
			
		||||
                        sources.add(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -199,7 +199,10 @@ class DramaSeeProvider : MainAPI() {
 | 
			
		|||
                    url.startsWith("https://asianembed.io") || url.startsWith("https://asianload.io") -> {
 | 
			
		||||
                        val iv = "9262859232435825"
 | 
			
		||||
                        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)
 | 
			
		||||
                    }
 | 
			
		||||
                    url.startsWith("https://embedsito.com") -> {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,6 +69,11 @@ open class VidstreamProviderTemplate : MainAPI() {
 | 
			
		|||
    open val secretDecryptKey: String? = null
 | 
			
		||||
    /** Generated the key from IV and ID */
 | 
			
		||||
    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.
 | 
			
		||||
| 
						 | 
				
			
			@ -255,7 +260,7 @@ open class VidstreamProviderTemplate : MainAPI() {
 | 
			
		|||
        val iframeLink =
 | 
			
		||||
            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.
 | 
			
		||||
        // 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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -216,7 +216,10 @@ class WatchAsianProvider : MainAPI() {
 | 
			
		|||
                url.startsWith("https://asianembed.io") || url.startsWith("https://asianload.io") -> {
 | 
			
		||||
                    val iv = "9262859232435825"
 | 
			
		||||
                    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)
 | 
			
		||||
                }
 | 
			
		||||
                url.startsWith("https://embedsito.com") -> {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue