From cd569b44c8da7d792e4657e58072edd8f9f534e4 Mon Sep 17 00:00:00 2001 From: LagradOst <11805592+LagradOst@users.noreply.github.com> Date: Thu, 28 Jul 2022 17:49:44 +0200 Subject: [PATCH] small fix --- .../animeproviders/NineAnimeProvider.kt | 27 ++- .../cloudstream3/extractors/Mcloud.kt | 77 +------ .../cloudstream3/extractors/WcoStream.kt | 214 +++++------------- .../movieproviders/BflixProvider.kt | 133 ++--------- .../cloudstream3/ui/player/CS3IPlayer.kt | 7 +- .../cloudstream3/ui/settings/SettingsLang.kt | 10 +- .../cloudstream3/utils/ExtractorApi.kt | 1 + 7 files changed, 102 insertions(+), 367 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/NineAnimeProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/NineAnimeProvider.kt index 43648764..fb22c791 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/NineAnimeProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/NineAnimeProvider.kt @@ -17,6 +17,8 @@ class NineAnimeProvider : MainAPI() { override val supportedTypes = setOf(TvType.Anime) override val hasQuickSearch = true + // taken from https://github.com/saikou-app/saikou/blob/b35364c8c2a00364178a472fccf1ab72f09815b4/app/src/main/java/ani/saikou/parsers/anime/NineAnime.kt + // GNU General Public License v3.0 https://github.com/saikou-app/saikou/blob/main/LICENSE.md companion object { fun getDubStatus(title: String): DubStatus { return if (title.contains("(dub)", ignoreCase = true)) { @@ -31,17 +33,17 @@ class NineAnimeProvider : MainAPI() { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" private const val cipherKey = "rTKp3auwu0ULA6II" - private fun encodeVrf(text: String): String { + fun encodeVrf(text: String, mainKey: String): String { return encode( encrypt( - cipher(cipherKey, encode(text)), + cipher(mainKey, encode(text)), nineAnimeKey ).replace("""=+$""".toRegex(), "") ) } - private fun decodeVrf(text: String): String { - return decode(cipher(cipherKey, decrypt(text, nineAnimeKey))) + fun decodeVrf(text: String, mainKey: String): String { + return decode(cipher(mainKey, decrypt(text, nineAnimeKey))) } fun encrypt(input: String, key: String): String { @@ -129,7 +131,7 @@ class NineAnimeProvider : MainAPI() { } } - private fun encode(input: String): String = + fun encode(input: String): String = java.net.URLEncoder.encode(input, "utf-8").replace("+", "%20") private fun decode(input: String): String = java.net.URLDecoder.decode(input, "utf-8") @@ -192,7 +194,7 @@ class NineAnimeProvider : MainAPI() { ) override suspend fun quickSearch(query: String): List? { - val vrf = encodeVrf(query) + val vrf = encodeVrf(query, cipherKey) val url = "$mainUrl/ajax/anime/search?keyword=$query&vrf=$vrf" val response = app.get(url).parsedSafe() @@ -207,7 +209,7 @@ class NineAnimeProvider : MainAPI() { } override suspend fun search(query: String): List { - val vrf = encodeVrf(query) + val vrf = encodeVrf(query, cipherKey) //?language%5B%5D=${if (selectDub) "dubbed" else "subbed"}& val url = "$mainUrl/filter?keyword=${encode(query)}&vrf=${vrf}&page=1" @@ -236,7 +238,8 @@ class NineAnimeProvider : MainAPI() { ?: throw ErrorLoadingException("Could not find title") val body = - app.get("$mainUrl/ajax/episode/list/$id?vrf=${encodeVrf(id)}").parsed().html + app.get("$mainUrl/ajax/episode/list/$id?vrf=${encodeVrf(id, cipherKey)}") + .parsed().html val subEpisodes = ArrayList() val dubEpisodes = ArrayList() @@ -253,7 +256,7 @@ class NineAnimeProvider : MainAPI() { ids.getOrNull(1)?.let { dub -> dubEpisodes.add( Episode( - "$mainUrl/ajax/server/list/$dub?vrf=${encodeVrf(dub)}", + "$mainUrl/ajax/server/list/$dub?vrf=${encodeVrf(dub, cipherKey)}", epTitle, episode = epNum ) @@ -262,7 +265,7 @@ class NineAnimeProvider : MainAPI() { ids.getOrNull(0)?.let { sub -> subEpisodes.add( Episode( - "$mainUrl/ajax/server/list/$sub?vrf=${encodeVrf(sub)}", + "$mainUrl/ajax/server/list/$sub?vrf=${encodeVrf(sub, cipherKey)}", epTitle, episode = epNum ) @@ -321,7 +324,7 @@ class NineAnimeProvider : MainAPI() { //TODO 9anime outro into {"status":200,"result":{"url":"","skip_data":{"intro_begin":67,"intro_end":154,"outro_begin":1337,"outro_end":1415,"count":3}},"message":"","messages":[]} private suspend fun getEpisodeLinks(id: String): Links? { - return app.get("$mainUrl/ajax/server/$id?vrf=${encodeVrf(id)}").parsedSafe() + return app.get("$mainUrl/ajax/server/$id?vrf=${encodeVrf(id, cipherKey)}").parsedSafe() } override suspend fun loadLinks( @@ -338,7 +341,7 @@ class NineAnimeProvider : MainAPI() { val name = it.text() val encodedStreamUrl = getEpisodeLinks(it.attr("data-link-id"))?.result?.url ?: return@apmap - val url = decodeVrf(encodedStreamUrl) + val url = decodeVrf(encodedStreamUrl, cipherKey) if (!loadExtractor(url, mainUrl, subtitleCallback, callback)) { callback( ExtractorLink( diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/Mcloud.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/Mcloud.kt index 3f332480..29d98557 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/Mcloud.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/Mcloud.kt @@ -1,82 +1,7 @@ package com.lagradost.cloudstream3.extractors -import com.fasterxml.jackson.annotation.JsonProperty -import com.lagradost.cloudstream3.USER_AGENT -import com.lagradost.cloudstream3.apmap -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.extractors.WcoStream.Companion.keytwo -import com.lagradost.cloudstream3.extractors.helper.WcoHelper.Companion.getNewWcoKey -import com.lagradost.cloudstream3.extractors.helper.WcoHelper.Companion.getWcoKey -import com.lagradost.cloudstream3.utils.AppUtils.parseJson -import com.lagradost.cloudstream3.utils.ExtractorApi -import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.M3u8Helper.Companion.generateM3u8 - -open class Mcloud : ExtractorApi() { +open class Mcloud : WcoStream() { override var name = "Mcloud" override var mainUrl = "https://mcloud.to" override val requiresReferer = true - val headers = mapOf( - "Host" to "mcloud.to", - "User-Agent" to USER_AGENT, - "Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8", - "Accept-Language" to "en-US,en;q=0.5", - "DNT" to "1", - "Connection" to "keep-alive", - "Upgrade-Insecure-Requests" to "1", - "Sec-Fetch-Dest" to "iframe", - "Sec-Fetch-Mode" to "navigate", - "Sec-Fetch-Site" to "cross-site", - "Referer" to "https://animekisa.in/", //Referer works for wco and animekisa, probably with others too - "Pragma" to "no-cache", - "Cache-Control" to "no-cache",) - private val key = "LCbu3iYC7ln24K7P" // key credits @Modder4869 - override suspend fun getUrl(url: String, referer: String?): List? { - val id = url.substringAfter("e/").substringAfter("embed/").substringBefore("?") - val keys = getNewWcoKey() - keytwo = keys?.encryptKey ?: return null - val encryptedid = encrypt(cipher(keys.cipherkey!!, encrypt(id))).replace("/", "_").replace("=","") - val link = "$mainUrl/mediainfo/$encryptedid?key=${keys.mainKey}" - val response = app.get(link, referer = "https://animekisa.in/").text - if(response.startsWith("")) { - // TODO decrypt html for link - return emptyList() - } - data class SourcesMcloud ( - @JsonProperty("file" ) val file : String - ) - - data class MediaMcloud ( - @JsonProperty("sources" ) val sources : ArrayList = arrayListOf() - ) - - data class DataMcloud ( - @JsonProperty("media" ) val media : MediaMcloud? = MediaMcloud() - ) - - data class JsonMcloud ( - @JsonProperty("status" ) val status : Int? = null, - @JsonProperty("data" ) val data : DataMcloud = DataMcloud() - ) - - val mapped = parseJson(response) - val sources = mutableListOf() - val checkfile = mapped.status == 200 - if (checkfile) - mapped.data.media?.sources?.apmap { - if (it.file.contains("m3u8")) { - sources.addAll( - generateM3u8( - name, - it.file, - url, - headers = mapOf("Referer" to url) - ) - ) - } - } - return sources - } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/WcoStream.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/WcoStream.kt index 0c9c6db7..3a01d602 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/WcoStream.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/WcoStream.kt @@ -1,15 +1,13 @@ package com.lagradost.cloudstream3.extractors import com.fasterxml.jackson.annotation.JsonProperty -import com.lagradost.cloudstream3.apmap +import com.lagradost.cloudstream3.ErrorLoadingException +import com.lagradost.cloudstream3.animeproviders.NineAnimeProvider.Companion.cipher +import com.lagradost.cloudstream3.animeproviders.NineAnimeProvider.Companion.encrypt import com.lagradost.cloudstream3.app -import com.lagradost.cloudstream3.extractors.helper.WcoHelper.Companion.getNewWcoKey -import com.lagradost.cloudstream3.extractors.helper.WcoHelper.Companion.getWcoKey import com.lagradost.cloudstream3.utils.ExtractorApi import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.M3u8Helper.Companion.generateM3u8 import com.lagradost.cloudstream3.utils.Qualities -import com.lagradost.cloudstream3.utils.getQualityFromName class Vidstreamz : WcoStream() { override var mainUrl = "https://vidstreamz.online" @@ -51,173 +49,79 @@ class VizcloudCloud : WcoStream() { override var mainUrl = "https://vizcloud.cloud" } +class VizcloudSite : WcoStream() { + override var mainUrl = "https://vizcloud.site" +} + open class WcoStream : ExtractorApi() { override var name = "VidStream" // Cause works for animekisa and wco override var mainUrl = "https://vidstream.pro" override val requiresReferer = false + private val regex = Regex("(.+?/)e(?:mbed)?/([a-zA-Z0-9]+)") companion object { - var keytwo = "" - 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 + // taken from https://github.com/saikou-app/saikou/blob/b35364c8c2a00364178a472fccf1ab72f09815b4/app/src/main/java/ani/saikou/parsers/anime/extractors/VizCloud.kt + // GNU General Public License v3.0 https://github.com/saikou-app/saikou/blob/main/LICENSE.md + private var lastChecked = 0L + private const val jsonLink = + "https://raw.githubusercontent.com/chenkaslowankiya/BruhFlow/main/keys.json" + private var cipherKey: VizCloudKey? = null + suspend fun getKey(): VizCloudKey { + cipherKey = + if (cipherKey != null && (lastChecked - System.currentTimeMillis()) < 1000 * 60 * 30) cipherKey!! + else { + lastChecked = System.currentTimeMillis() + app.get(jsonLink).parsed() } - 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; + return cipherKey!! } - 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 + data class VizCloudKey( + @JsonProperty("cipherKey") val cipherKey: String, + @JsonProperty("mainKey") val mainKey: String, + @JsonProperty("encryptKey") val encryptKey: String, + @JsonProperty("dashTable") val dashTable: String + ) + + private const val baseTable = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+=/_" + + private fun dashify(id: String, dashTable: String): String { + val table = dashTable.split(" ") + return id.mapIndexedNotNull { i, c -> + table.getOrNull((baseTable.indexOf(c) * 16) + (i % 16)) + }.joinToString("-") } } - private val key = "LCbu3iYC7ln24K7P" // key credits @Modder4869 + + //private val key = "LCbu3iYC7ln24K7P" // key credits @Modder4869 override suspend fun getUrl(url: String, referer: String?): List { - val baseUrl = url.split("/e/")[0] + val group = regex.find(url)?.groupValues!! - val (Id) = (Regex("/e/(.*?)?domain").find(url)?.destructured ?: Regex("""/e/(.*)""").find( - url - )?.destructured) ?: return emptyList() - // val (skey) = Regex("""skey\s=\s['"](.*?)['"];""").find(html)?.destructured - // ?: return emptyList() - val keys = getNewWcoKey() - keytwo = keys?.encryptKey ?: return emptyList() - val encryptedID = encrypt(cipher(keys.cipherkey!!, encrypt(Id))).replace("/", "_").replace("=","") - val apiLink = "$baseUrl/mediainfo/$encryptedID?key=${keys.mainKey}" - val referrer = "$baseUrl/e/$Id?domain=wcostream.cc" + val host = group[1] + val viz = getKey() + val id = encrypt( + cipher( + viz.cipherKey, + encrypt(group[2], viz.encryptKey).also { println(it) } + ).also { println(it) }, + viz.encryptKey + ).also { println(it) } - data class SourcesWco ( - @JsonProperty("file" ) val file : String - ) + val link = + "${host}mediainfo/${dashify(id, viz.dashTable)}?key=${viz.mainKey}" // + val response = app.get(link, referer = referer) - data class MediaWco ( - @JsonProperty("sources" ) val sources : ArrayList = arrayListOf() - ) + data class Sources(@JsonProperty("file") val file: String) + data class Media(@JsonProperty("sources") val sources: List) + data class Data(@JsonProperty("media") val media: Media) + data class Response(@JsonProperty("data") val data: Data) - data class DataWco ( - @JsonProperty("media" ) val media : MediaWco? = MediaWco() - ) - 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() - val sources = mutableListOf() - val check = mapped.status == 200 - if (check) { - mapped.data?.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 - 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") - val link360 = it.file.replace("list.m3u8#.mp4", "H1/v.m3u8") - val linkauto = it.file.replace("#.mp4", "") - listOf( - link1080, - link720, - link480, - link360, - linkauto - ).apmap { serverurl -> - val testurl = app.get(serverurl, headers = mapOf("Referer" to url)).text - if (testurl.contains("EXTM3")) { - val quality = when { - serverurl.contains("H4") -> "1080p" - serverurl.contains("H3") -> "720p" - serverurl.contains("H2") -> "480p" - serverurl.contains("H1") -> "360p" - else -> "Auto" - } - sources.add( - ExtractorLink( - "VidStream", - "VidStream", - serverurl, - url, - getQualityFromName(quality), - true, - ) - ) - } - } - } - } 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", - "https://vizcloud.cloud" - ).contains(mainUrl) - ) { - if (it.file.contains("m3u8")) { - sources.addAll( - generateM3u8( - name, - it.file.replace("#.mp4", ""), - url, - headers = mapOf("Referer" to url) - ) - ) - } else { - sources.add( - ExtractorLink( - name, - name = name, - it.file, - "", - Qualities.P720.value, - false - ) - ) - } - } - } + if (!response.text.startsWith("{")) throw ErrorLoadingException("Seems like 9Anime kiddies changed stuff again, Go touch some grass for bout an hour Or use a different Server") + return response.parsed().data.media.sources.map { + ExtractorLink(name, it.file,it.file,host,Qualities.Unknown.value,it.file.contains(".m3u8")) } - return sources + } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/BflixProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/BflixProvider.kt index fef586c9..2ca2ab88 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/BflixProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/BflixProvider.kt @@ -2,6 +2,9 @@ package com.lagradost.cloudstream3.movieproviders import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.animeproviders.NineAnimeProvider.Companion.decodeVrf +import com.lagradost.cloudstream3.animeproviders.NineAnimeProvider.Companion.encode +import com.lagradost.cloudstream3.animeproviders.NineAnimeProvider.Companion.encodeVrf import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.loadExtractor @@ -62,113 +65,8 @@ open class BflixProvider : MainAPI() { return HomePageResponse(items) } - //Credits to https://github.com/jmir1 - private val key = - "5uLKesbh0nkrpPq9VwMC6+tQBdomjJ4HNl/fWOSiREvAYagT8yIG7zx2D13UZFXc" //key credits to @Modder4869 - - private fun getVrf(id: String): String? { - val reversed = ue(encode(id) + "0000000").slice(0..5).reversed() - return reversed + ue(je(reversed, encode(id)?.replace("+", "%20") ?: return null)).replace( - """=+$""".toRegex(), - "" - ) - } - - private fun getLink(url: String): String? { - val i = url.slice(0..5) - val n = url.slice(6..url.lastIndex) - return decode(je(i, ze(n))) - } - - private fun ue(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 += key[n] - } - } - } - return output - } - - private fun je(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 fun ze(input: String): String { - val t = if (input.replace("""[\t\n\f\r]""".toRegex(), "").length % 4 == 0) { - input.replace("""/==?$/""".toRegex(), "") - } else input - if (t.length % 4 == 1 || t.contains("""[^+/0-9A-Za-z]""".toRegex())) throw Exception("bad input") - var i: Int - var r = "" - var e = 0 - var u = 0 - for (o in t.indices) { - e = e shl 6 - i = key.indexOf(t[o]) - e = e or i - u += 6 - if (24 == u) { - r += ((16711680 and e) shr 16).toChar() - r += ((65280 and e) shr 8).toChar() - r += (255 and e).toChar() - e = 0 - u = 0 - } - } - return if (12 == u) { - e = e shr 4 - r + e.toChar() - } else { - if (18 == u) { - e = e shr 2 - r += ((65280 and e) shr 8).toChar() - r += (255 and e).toChar() - } - r - } - } - - private fun encode(input: String): String? = java.net.URLEncoder.encode(input, "utf-8") - private fun decode(input: String): String? = java.net.URLDecoder.decode(input, "utf-8") - override suspend fun search(query: String): List? { - val encodedquery = getVrf(query)?.let { encode(it) } ?: return null + val encodedquery = encodeVrf(query, mainKey) val url = "$mainUrl/search?keyword=$query&vrf=$encodedquery" val html = app.get(url).text val document = Jsoup.parse(html) @@ -210,10 +108,14 @@ open class BflixProvider : MainAPI() { @JsonProperty("html") val html: String ) + companion object { + val mainKey = "OrAimkpzm6phmN3j" + } + override suspend fun load(url: String): LoadResponse? { val soup = app.get(url).document val movieid = soup.selectFirst("div#watch")!!.attr("data-id") - val movieidencoded = encode(getVrf(movieid) ?: return null) + val movieidencoded = encodeVrf(movieid, mainKey) val title = soup.selectFirst("div.info h1")!!.text() val description = soup.selectFirst(".info .desc")?.text()?.trim() val poster: String? = try { @@ -223,9 +125,11 @@ open class BflixProvider : MainAPI() { } val tags = soup.select("div.info .meta div:contains(Genre) a").map { it.text() } + val vrfUrl = "$mainUrl/ajax/film/servers?id=$movieid&vrf=$movieidencoded" + println("VRF___ $vrfUrl") val episodes = Jsoup.parse( app.get( - "$mainUrl/ajax/film/servers?id=$movieid&vrf=$movieidencoded" + vrfUrl ).parsed().html ).select("div.episode").map { val a = it.selectFirst("a") @@ -251,7 +155,7 @@ open class BflixProvider : MainAPI() { if (url.contains("/movie/") && episodes.size == 1) TvType.Movie else TvType.TvSeries val recommendations = soup.select("div.bl-2 section.bl div.content div.filmlist div.item") - ?.mapNotNull { element -> + .mapNotNull { element -> val recTitle = element.select("h3 a").text() ?: return@mapNotNull null val image = element.select("a.poster img")?.attr("src") val recUrl = fixUrl(element.select("a").attr("href")) @@ -267,13 +171,13 @@ open class BflixProvider : MainAPI() { val rating = soup.selectFirst(".info span.imdb")?.text()?.toRatingInt() val durationdoc = soup.selectFirst("div.info div.meta").toString() val durationregex = Regex("((\\d+) min)") - val yearegex = Regex("(\\d+)<\\/span>") + val yearegex = Regex("(\\d+)") val duration = if (durationdoc.contains("na min")) null else durationregex.find(durationdoc)?.destructured?.component1()?.replace(" min", "") ?.toIntOrNull() val year = if (mainUrl == "https://bflix.ru") { yearegex.find(durationdoc)?.destructured?.component1() - ?.replace(Regex("|<\\/span>"), "") + ?.replace(Regex("|"), "") } else null return when (tvType) { TvType.TvSeries -> { @@ -341,7 +245,7 @@ open class BflixProvider : MainAPI() { val soup = app.get(data).document val movieid = encode(soup.selectFirst("div#watch")?.attr("data-id") ?: return false) - val movieidencoded = encode(getVrf(movieid!!) ?: return false) + val movieidencoded = encodeVrf(movieid, mainKey) Jsoup.parse( parseJson( app.get( @@ -372,8 +276,9 @@ open class BflixProvider : MainAPI() { val epserver = app.get("$mainUrl/ajax/episode/info?id=$it").text (if (epserver.contains("url")) { parseJson(epserver) - } else null)?.url?.let { it1 -> getLink(it1.replace("=", "")) } - ?.replace("/embed/", "/e/")?.replace(Regex("(\\?sub.info.*)"), "") + } else null)?.url?.let { + decodeVrf(it, mainKey) + } }.apmap { url -> loadExtractor( url, data, subtitleCallback, callback diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt index 2052a370..0eb72f19 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/CS3IPlayer.kt @@ -22,7 +22,7 @@ import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvicto import com.google.android.exoplayer2.upstream.cache.SimpleCache import com.google.android.exoplayer2.util.MimeTypes import com.google.android.exoplayer2.video.VideoSize -import com.lagradost.cloudstream3.APIHolder.getApiFromName +import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull import com.lagradost.cloudstream3.USER_AGENT import com.lagradost.cloudstream3.app import com.lagradost.cloudstream3.mvvm.logError @@ -210,6 +210,7 @@ class CS3IPlayer : IPlayer { } var currentSubtitles: SubtitleData? = null + /** * @return True if the player should be reloaded * */ @@ -353,8 +354,8 @@ class CS3IPlayer : IPlayer { var requestSubtitleUpdate: (() -> Unit)? = null private fun createOnlineSource(link: ExtractorLink): DataSource.Factory { - val provider = getApiFromName(link.source) - val interceptor = provider.getVideoInterceptor(link) + val provider = getApiFromNameNull(link.source) + val interceptor = provider?.getVideoInterceptor(link) val source = if (interceptor == null) { DefaultHttpDataSource.Factory() //TODO USE app.baseClient diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsLang.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsLang.kt index 6265771c..84b40444 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsLang.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsLang.kt @@ -149,18 +149,14 @@ class SettingsLang : PreferenceFragmentCompat() { getPref(R.string.provider_lang_key)?.setOnPreferenceClickListener { activity?.getApiProviderLangSettings()?.let { current -> - var allLangs: MutableSet = mutableSetOf() - for (api in APIHolder.apis) { - allLangs.add(api.lang) - } - allLangs = allLangs.sortedBy { SubtitleHelper.fromTwoLettersToLanguage(it) }.toMutableSet() + val langs = APIHolder.apis.map { it.lang }.toSet().sortedBy { SubtitleHelper.fromTwoLettersToLanguage(it) } val currentList = ArrayList() for (i in current) { - currentList.add(allLangs.indexOf(i)) + currentList.add(langs.indexOf(i)) } - val names = allLangs.map { + val names = langs.map { val emoji = SubtitleHelper.getFlagFromIso(it) val name = SubtitleHelper.fromTwoLettersToLanguage(it) val fullName = "$emoji $name" diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt index 9ce3e211..79275c50 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt @@ -202,6 +202,7 @@ val extractorApis: Array = arrayOf( MwvnVizcloudInfo(), VizcloudDigital(), VizcloudCloud(), + VizcloudSite(), VideoVard(), VideovardSX(), Mp4Upload(),