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 | ||||||
|  | @ -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,18 +119,27 @@ 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")) { | ||||||
|  |                         sources.addAll( | ||||||
|                             generateM3u8( |                             generateM3u8( | ||||||
|                                 name, |                                 name, | ||||||
|                                 it.file.replace("#.mp4", ""), |                                 it.file.replace("#.mp4", ""), | ||||||
|                                 url, |                                 url, | ||||||
|                                 headers = mapOf("Referer" to url) |                                 headers = mapOf("Referer" to url) | ||||||
|                             ) |                             ) | ||||||
|  |                         ) | ||||||
|                     } else { |                     } else { | ||||||
|                         sources.add( |                         sources.add( | ||||||
|                             ExtractorLink( |                             ExtractorLink( | ||||||
|  |  | ||||||
|  | @ -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…
	
	Add table
		Add a link
		
	
		Reference in a new issue