forked from recloudstream/cloudstream
		
	fixes on mcloud/vidstream/bflix/9anime (#1091)
* fixes * minor thing * minor thing
This commit is contained in:
		
							parent
							
								
									bf4bd7f5e2
								
							
						
					
					
						commit
						4fa60e6b5e
					
				
					 6 changed files with 111 additions and 43 deletions
				
			
		|  | @ -64,7 +64,7 @@ class NineAnimeProvider : MainAPI() { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     //Credits to https://github.com/jmir1 |     //Credits to https://github.com/jmir1 | ||||||
|     private val key = "0wMrYU+ixjJ4QdzgfN2HlyIVAt3sBOZnCT9Lm7uFDovkb/EaKpRWhqXS5168ePcG" |     private val key = "c/aUAorINHBLxWTy3uRiPt8J+vjsOheFG1E0q2X9CYwDZlnmd4Kb5M6gSVzfk7pQ" //key credits to @Modder4869 | ||||||
| 
 | 
 | ||||||
|     private fun getVrf(id: String): String? { |     private fun getVrf(id: String): String? { | ||||||
|         val reversed = ue(encode(id) + "0000000").slice(0..5).reversed() |         val reversed = ue(encode(id) + "0000000").slice(0..5).reversed() | ||||||
|  |  | ||||||
|  | @ -4,10 +4,12 @@ import com.fasterxml.jackson.annotation.JsonProperty | ||||||
| import com.lagradost.cloudstream3.USER_AGENT | import com.lagradost.cloudstream3.USER_AGENT | ||||||
| import com.lagradost.cloudstream3.apmap | import com.lagradost.cloudstream3.apmap | ||||||
| import com.lagradost.cloudstream3.app | import com.lagradost.cloudstream3.app | ||||||
|  | import com.lagradost.cloudstream3.extractors.WcoStream.Companion.cipher | ||||||
|  | import com.lagradost.cloudstream3.extractors.WcoStream.Companion.encrypt | ||||||
| import com.lagradost.cloudstream3.utils.AppUtils.parseJson | import com.lagradost.cloudstream3.utils.AppUtils.parseJson | ||||||
| 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 | import com.lagradost.cloudstream3.utils.M3u8Helper.Companion.generateM3u8 | ||||||
| 
 | 
 | ||||||
| open class Mcloud : ExtractorApi() { | open class Mcloud : ExtractorApi() { | ||||||
|     override var name = "Mcloud" |     override var name = "Mcloud" | ||||||
|  | @ -27,42 +29,47 @@ open class Mcloud : ExtractorApi() { | ||||||
|         "Referer" to "https://animekisa.in/", //Referer works for wco and animekisa, probably with others too |         "Referer" to "https://animekisa.in/", //Referer works for wco and animekisa, probably with others too | ||||||
|         "Pragma" to "no-cache", |         "Pragma" to "no-cache", | ||||||
|         "Cache-Control" to "no-cache",) |         "Cache-Control" to "no-cache",) | ||||||
|  |     private val key = "LCbu3iYC7ln24K7P" // key credits @Modder4869 | ||||||
|     override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink>? { |     override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink>? { | ||||||
|         val link = url.replace("$mainUrl/e/","$mainUrl/info/") |         val id = url.substringAfter("e/").substringAfter("embed/").substringBefore("?") | ||||||
|  |         val encryptedid = encrypt(cipher(key, encrypt(id))).replace("/", "_").replace("=","") | ||||||
|  |         val link = "$mainUrl/info/$encryptedid" | ||||||
|         val response = app.get(link, headers = headers).text |         val response = app.get(link, headers = headers).text | ||||||
| 
 |  | ||||||
|         if(response.startsWith("<!DOCTYPE html>")) { |         if(response.startsWith("<!DOCTYPE html>")) { | ||||||
|             // TODO decrypt html for link |             // TODO decrypt html for link | ||||||
|             return emptyList() |             return emptyList() | ||||||
|         } |         } | ||||||
| 
 |         data class SourcesMcloud ( | ||||||
|         data class Sources ( |             @JsonProperty("file" ) val file : String | ||||||
|             @JsonProperty("file") val file: String |  | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         data class Media ( |         data class MediaMcloud ( | ||||||
|             @JsonProperty("sources") val sources: List<Sources> |             @JsonProperty("sources" ) val sources : ArrayList<SourcesMcloud> = arrayListOf() | ||||||
|  |         ) | ||||||
|  | 
 | ||||||
|  |         data class DataMcloud ( | ||||||
|  |             @JsonProperty("media" ) val media : MediaMcloud? = MediaMcloud() | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         data class JsonMcloud ( |         data class JsonMcloud ( | ||||||
|             @JsonProperty("success") val success: Boolean, |             @JsonProperty("status" ) val status : Int?  = null, | ||||||
|             @JsonProperty("media") val media: Media, |             @JsonProperty("data"   ) val data   : DataMcloud = DataMcloud() | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         val mapped = parseJson<JsonMcloud>(response) |         val mapped = parseJson<JsonMcloud>(response) | ||||||
|         val sources = mutableListOf<ExtractorLink>() |         val sources = mutableListOf<ExtractorLink>() | ||||||
| 
 |         val checkfile = mapped.status == 200 | ||||||
|         if (mapped.success) |         if (checkfile) | ||||||
|             mapped.media.sources.apmap { |             mapped.data.media?.sources?.apmap { | ||||||
|                 if (it.file.contains("m3u8")) { |                 if (it.file.contains("m3u8")) { | ||||||
|                     M3u8Helper.generateM3u8( |                     sources.addAll( | ||||||
|  |                         generateM3u8( | ||||||
|                             name, |                             name, | ||||||
|                             it.file, |                             it.file, | ||||||
|                             url, |                             url, | ||||||
|                         headers = app.get(url).headers.toMap() |                             headers = mapOf("Referer" to url) | ||||||
|                     ).forEach { link -> |                         ) | ||||||
|                         sources.add(link) |                     ) | ||||||
|                     } |  | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         return sources |         return sources | ||||||
|  |  | ||||||
|  | @ -45,43 +45,102 @@ class VizcloudDigital : WcoStream() { | ||||||
|     override var mainUrl = "https://vizcloud.digital" |     override var mainUrl = "https://vizcloud.digital" | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | class VizcloudCloud : WcoStream() { | ||||||
|  |     override var mainUrl = "https://vizcloud.cloud" | ||||||
|  | } | ||||||
|  | 
 | ||||||
| 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 | ||||||
| 
 | 
 | ||||||
|  |     companion object { | ||||||
|  |         private val keytwo = "0wMrYU+ixjJ4QdzgfN2HlyIVAt3sBOZnCT9Lm7uFDovkb/EaKpRWhqXS5168ePcG" | ||||||
|  |         fun encrypt(input: String): String { | ||||||
|  |             if (input.any { it.code >= 256 }) throw Exception("illegal characters!") | ||||||
|  |             var output = "" | ||||||
|  |             for (i in input.indices step 3) { | ||||||
|  |                 val a = intArrayOf(-1, -1, -1, -1) | ||||||
|  |                 a[0] = input[i].code shr 2 | ||||||
|  |                 a[1] = (3 and input[i].code) shl 4 | ||||||
|  |                 if (input.length > i + 1) { | ||||||
|  |                     a[1] = a[1] or (input[i + 1].code shr 4) | ||||||
|  |                     a[2] = (15 and input[i + 1].code) shl 2 | ||||||
|  |                 } | ||||||
|  |                 if (input.length > i + 2) { | ||||||
|  |                     a[2] = a[2] or (input[i + 2].code shr 6) | ||||||
|  |                     a[3] = 63 and input[i + 2].code | ||||||
|  |                 } | ||||||
|  |                 for (n in a) { | ||||||
|  |                     if (n == -1) output += "=" | ||||||
|  |                     else { | ||||||
|  |                         if (n in 0..63) output += keytwo[n] | ||||||
|  |                     } | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             return output; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         fun cipher(inputOne: String, inputTwo: String): String { | ||||||
|  |             val arr = IntArray(256) { it } | ||||||
|  |             var output = "" | ||||||
|  |             var u = 0 | ||||||
|  |             var r: Int | ||||||
|  |             for (a in arr.indices) { | ||||||
|  |                 u = (u + arr[a] + inputOne[a % inputOne.length].code) % 256 | ||||||
|  |                 r = arr[a] | ||||||
|  |                 arr[a] = arr[u] | ||||||
|  |                 arr[u] = r | ||||||
|  |             } | ||||||
|  |             u = 0 | ||||||
|  |             var c = 0 | ||||||
|  |             for (f in inputTwo.indices) { | ||||||
|  |                 c = (c + f) % 256 | ||||||
|  |                 u = (u + arr[c]) % 256 | ||||||
|  |                 r = arr[c] | ||||||
|  |                 arr[c] = arr[u] | ||||||
|  |                 arr[u] = r | ||||||
|  |                 output += (inputTwo[f].code xor arr[(arr[c] + arr[u]) % 256]).toChar() | ||||||
|  |             } | ||||||
|  |             return output | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     private val key = "LCbu3iYC7ln24K7P" // key credits @Modder4869 | ||||||
|     override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> { |     override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> { | ||||||
|         val baseUrl = url.split("/e/")[0] |         val baseUrl = url.split("/e/")[0] | ||||||
| 
 | 
 | ||||||
|         val html = app.get(url, headers = mapOf("Referer" to "https://wcostream.cc/")).text |  | ||||||
|         val (Id) = (Regex("/e/(.*?)?domain").find(url)?.destructured ?: Regex("""/e/(.*)""").find( |         val (Id) = (Regex("/e/(.*?)?domain").find(url)?.destructured ?: Regex("""/e/(.*)""").find( | ||||||
|             url |             url | ||||||
|         )?.destructured) ?: return emptyList() |         )?.destructured) ?: return emptyList() | ||||||
|         val (skey) = Regex("""skey\s=\s['"](.*?)['"];""").find(html)?.destructured |       //  val (skey) = Regex("""skey\s=\s['"](.*?)['"];""").find(html)?.destructured | ||||||
|             ?: return emptyList() |       //     ?: return emptyList() | ||||||
| 
 | 
 | ||||||
|         val apiLink = "$baseUrl/info/$Id?domain=wcostream.cc&skey=$skey" |         val encryptedID = encrypt(cipher(key, encrypt(Id))).replace("/", "_").replace("=","") | ||||||
|  |         val apiLink = "$baseUrl/info/$encryptedID" | ||||||
|         val referrer = "$baseUrl/e/$Id?domain=wcostream.cc" |         val referrer = "$baseUrl/e/$Id?domain=wcostream.cc" | ||||||
| 
 | 
 | ||||||
|         data class Sources( |         data class SourcesWco ( | ||||||
|             @JsonProperty("file") val file: String, |             @JsonProperty("file" ) val file : String | ||||||
|             @JsonProperty("label") val label: String? |  | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         data class Media( |         data class MediaWco ( | ||||||
|             @JsonProperty("sources") val sources: List<Sources> |             @JsonProperty("sources" ) val sources : ArrayList<SourcesWco> = arrayListOf() | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         data class WcoResponse( |         data class DataWco ( | ||||||
|             @JsonProperty("success") val success: Boolean, |             @JsonProperty("media" ) val media : MediaWco? = MediaWco() | ||||||
|             @JsonProperty("media") val media: Media |         ) | ||||||
|  | 
 | ||||||
|  |         data class WcoResponse ( | ||||||
|  |             @JsonProperty("status" ) val status : Int?  = null, | ||||||
|  |             @JsonProperty("data"   ) val data   : DataWco? = DataWco() | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|         val mapped = app.get(apiLink, headers = mapOf("Referer" to referrer)).parsed<WcoResponse>() |         val mapped = app.get(apiLink, headers = mapOf("Referer" to referrer)).parsed<WcoResponse>() | ||||||
|         val sources = mutableListOf<ExtractorLink>() |         val sources = mutableListOf<ExtractorLink>() | ||||||
| 
 |         val check = mapped.status == 200 | ||||||
|         if (mapped.success) { |         if (check) { | ||||||
|             mapped.media.sources.forEach { |             mapped.data?.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 | ||||||
|  | @ -128,7 +187,8 @@ open class WcoStream : ExtractorApi() { | ||||||
|                         "https://vizcloud.live", |                         "https://vizcloud.live", | ||||||
|                         "https://vizcloud.info", |                         "https://vizcloud.info", | ||||||
|                         "https://mwvn.vizcloud.info", |                         "https://mwvn.vizcloud.info", | ||||||
|                         "https://vizcloud.digital" |                         "https://vizcloud.digital", | ||||||
|  |                         "https://vizcloud.cloud" | ||||||
|                     ).contains(mainUrl) |                     ).contains(mainUrl) | ||||||
|                 ) { |                 ) { | ||||||
|                     if (it.file.contains("m3u8")) { |                     if (it.file.contains("m3u8")) { | ||||||
|  |  | ||||||
|  | @ -57,7 +57,7 @@ open class BflixProvider : MainAPI() { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     //Credits to https://github.com/jmir1 |     //Credits to https://github.com/jmir1 | ||||||
|     val key = "eST4kCjadnvlAm5b1BOGyLJzrE90Q6oKgRfhV+M8NDYtcxW3IP/qp2i7XHuwZFUs" |     private val key = "5uLKesbh0nkrpPq9VwMC6+tQBdomjJ4HNl/fWOSiREvAYagT8yIG7zx2D13UZFXc" //key credits to @Modder4869 | ||||||
| 
 | 
 | ||||||
|     private fun getVrf(id: String): String? { |     private fun getVrf(id: String): String? { | ||||||
|         val reversed = ue(encode(id) + "0000000").slice(0..5).reversed() |         val reversed = ue(encode(id) + "0000000").slice(0..5).reversed() | ||||||
|  |  | ||||||
|  | @ -117,6 +117,7 @@ val extractorApis: Array<ExtractorApi> = arrayOf( | ||||||
|     VizcloudInfo(), |     VizcloudInfo(), | ||||||
|     MwvnVizcloudInfo(), |     MwvnVizcloudInfo(), | ||||||
|     VizcloudDigital(), |     VizcloudDigital(), | ||||||
|  |     VizcloudCloud(), | ||||||
|     Mp4Upload(), |     Mp4Upload(), | ||||||
|     StreamTape(), |     StreamTape(), | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -68,7 +68,7 @@ | ||||||
|     "BflixProvider": { |     "BflixProvider": { | ||||||
|         "language": "en", |         "language": "en", | ||||||
|         "name": "Bflix", |         "name": "Bflix", | ||||||
|         "status": 0, |         "status": 1, | ||||||
|         "url": "https://bflix.ru" |         "url": "https://bflix.ru" | ||||||
|     }, |     }, | ||||||
|     "CinecalidadProvider": { |     "CinecalidadProvider": { | ||||||
|  | @ -151,7 +151,7 @@ | ||||||
|     "FmoviesToProvider": { |     "FmoviesToProvider": { | ||||||
|         "language": "en", |         "language": "en", | ||||||
|         "name": "Fmovies.to", |         "name": "Fmovies.to", | ||||||
|         "status": 0, |         "status": 1, | ||||||
|         "url": "https://fmovies.to" |         "url": "https://fmovies.to" | ||||||
|     }, |     }, | ||||||
|     "FrenchStreamProvider": { |     "FrenchStreamProvider": { | ||||||
|  | @ -253,7 +253,7 @@ | ||||||
|     "NineAnimeProvider": { |     "NineAnimeProvider": { | ||||||
|         "language": "en", |         "language": "en", | ||||||
|         "name": "9Anime", |         "name": "9Anime", | ||||||
|         "status": 0, |         "status": 1, | ||||||
|         "url": "https://9anime.id" |         "url": "https://9anime.id" | ||||||
|     }, |     }, | ||||||
|     "NontonAnimeIDProvider": { |     "NontonAnimeIDProvider": { | ||||||
|  | @ -331,7 +331,7 @@ | ||||||
|     "SflixProProvider": { |     "SflixProProvider": { | ||||||
|         "language": "en", |         "language": "en", | ||||||
|         "name": "Sflix.pro", |         "name": "Sflix.pro", | ||||||
|         "status": 0, |         "status": 1, | ||||||
|         "url": "https://sflix.pro" |         "url": "https://sflix.pro" | ||||||
|     }, |     }, | ||||||
|     "SflixProvider": { |     "SflixProvider": { | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue