forked from recloudstream/cloudstream
		
	update gogo for adaptive encryption keys
This commit is contained in:
		
							parent
							
								
									f451b71b0b
								
							
						
					
					
						commit
						e2841847f1
					
				
					 6 changed files with 68 additions and 34 deletions
				
			
		|  | @ -2,6 +2,7 @@ package com.lagradost.cloudstream3.animeproviders | ||||||
| 
 | 
 | ||||||
| import com.fasterxml.jackson.annotation.JsonProperty | import com.fasterxml.jackson.annotation.JsonProperty | ||||||
| import com.lagradost.cloudstream3.* | import com.lagradost.cloudstream3.* | ||||||
|  | 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 | ||||||
|  | @ -27,18 +28,31 @@ class GogoanimeProvider : MainAPI() { | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         /** | ||||||
|  |          * @param id base64Decode(show_id) + IV | ||||||
|  |          * @return the encryption key | ||||||
|  |          * */ | ||||||
|  |         private fun getKey(id: String): String? { | ||||||
|  |             return normalSafeApiCall { | ||||||
|  |                  id.map { | ||||||
|  |                     it.code.toString(16) | ||||||
|  |                 }.joinToString("").substring(0, 32) | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         val qualityRegex = Regex("(\\d+)P") |         val qualityRegex = Regex("(\\d+)P") | ||||||
| 
 | 
 | ||||||
|         // https://github.com/saikou-app/saikou/blob/3e756bd8e876ad7a9318b17110526880525a5cd3/app/src/main/java/ani/saikou/anime/source/extractors/GogoCDN.kt#L60 |         // https://github.com/saikou-app/saikou/blob/3e756bd8e876ad7a9318b17110526880525a5cd3/app/src/main/java/ani/saikou/anime/source/extractors/GogoCDN.kt#L60 | ||||||
|         // No Licence on the function |         // No Licence on the function | ||||||
|         private fun cryptoHandler( |         private fun cryptoHandler( | ||||||
|             string: String, |             string: String, | ||||||
|             iv: ByteArray, |             iv: String, | ||||||
|             secretKeyString: ByteArray, |             secretKeyString: String, | ||||||
|             encrypt: Boolean = true |             encrypt: Boolean = true | ||||||
|         ): String { |         ): String { | ||||||
|             val ivParameterSpec = IvParameterSpec(iv) |             println("IV: $iv, Key: $secretKeyString, encrypt: $encrypt, Message: $string") | ||||||
|             val secretKey = SecretKeySpec(secretKeyString, "AES") |             val ivParameterSpec = IvParameterSpec(iv.toByteArray()) | ||||||
|  |             val secretKey = SecretKeySpec(secretKeyString.toByteArray(), "AES") | ||||||
|             val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") |             val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") | ||||||
|             return if (!encrypt) { |             return if (!encrypt) { | ||||||
|                 cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec) |                 cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec) | ||||||
|  | @ -59,31 +73,41 @@ class GogoanimeProvider : MainAPI() { | ||||||
|         /** |         /** | ||||||
|          * @param iframeUrl something like https://gogoplay4.com/streaming.php?id=XXXXXX |          * @param iframeUrl something like https://gogoplay4.com/streaming.php?id=XXXXXX | ||||||
|          * @param mainApiName used for ExtractorLink names and source |          * @param mainApiName used for ExtractorLink names and source | ||||||
|          * @param iv secret iv from site, required non-null |          * @param iv secret iv from site, required non-null if isUsingAdaptiveKeys is off | ||||||
|          * @param secretKey secret key for decryption from site, required non-null |          * @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 |          * @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() | ||||||
|          * */ |          * */ | ||||||
|         suspend fun extractVidstream( |         suspend fun extractVidstream( | ||||||
|             iframeUrl: String, |             iframeUrl: String, | ||||||
|             mainApiName: String, |             mainApiName: String, | ||||||
|             callback: (ExtractorLink) -> Unit, |             callback: (ExtractorLink) -> Unit, | ||||||
|             iv: ByteArray?, |             iv: String?, | ||||||
|             secretKey: ByteArray?, |             secretKey: String?, | ||||||
|             secretDecryptKey: ByteArray? |             secretDecryptKey: String?, | ||||||
|  |             // This could be removed, but i prefer it verbose | ||||||
|  |             isUsingAdaptiveKeys: 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 | ||||||
|             // Also modified of https://github.com/jmir1/aniyomi-extensions/blob/master/src/en/gogoanime/src/eu/kanade/tachiyomi/animeextension/en/gogoanime/extractors/GogoCdnExtractor.kt |             // Also modified of https://github.com/jmir1/aniyomi-extensions/blob/master/src/en/gogoanime/src/eu/kanade/tachiyomi/animeextension/en/gogoanime/extractors/GogoCdnExtractor.kt | ||||||
|             // License on the code above  https://github.com/jmir1/aniyomi-extensions/blob/master/LICENSE |             // License on the code above  https://github.com/jmir1/aniyomi-extensions/blob/master/LICENSE | ||||||
| 
 | 
 | ||||||
|             if (iv == null || secretKey == null || secretDecryptKey == null) |             if ((iv == null || secretKey == null || secretDecryptKey == null) && !isUsingAdaptiveKeys) | ||||||
|                 return@safeApiCall |                 return@safeApiCall | ||||||
| 
 | 
 | ||||||
|  |             val id = Regex("id=([^&]+)").find(iframeUrl)!!.value.removePrefix("id=") | ||||||
|  | 
 | ||||||
|  |             val foundIv = | ||||||
|  |                 iv ?: app.get(iframeUrl).document.select("""div.wrapper[class*=container]""") | ||||||
|  |                     .attr("class").split("-").lastOrNull() ?: return@safeApiCall | ||||||
|  |             val foundKey = secretKey ?: getKey(base64Decode(id) + foundIv) ?: return@safeApiCall | ||||||
|  |             val foundDecryptKey = secretDecryptKey ?: foundKey | ||||||
|  | 
 | ||||||
|             val uri = URI(iframeUrl) |             val uri = URI(iframeUrl) | ||||||
|             val mainUrl = "https://" + uri.host |             val mainUrl = "https://" + uri.host | ||||||
| 
 | 
 | ||||||
|             val id = Regex("id=([^&]+)").find(iframeUrl)!!.value.removePrefix("id=") |             val encryptedId = cryptoHandler(id, foundIv, foundKey) | ||||||
|             val encryptedId = cryptoHandler(id, iv, secretKey) |  | ||||||
|             val jsonResponse = |             val jsonResponse = | ||||||
|                 app.get( |                 app.get( | ||||||
|                     "$mainUrl/encrypt-ajax.php?id=$encryptedId&alias=$id", |                     "$mainUrl/encrypt-ajax.php?id=$encryptedId&alias=$id", | ||||||
|  | @ -91,7 +115,7 @@ class GogoanimeProvider : MainAPI() { | ||||||
|                 ) |                 ) | ||||||
|             val dataencrypted = |             val dataencrypted = | ||||||
|                 jsonResponse.text.substringAfter("{\"data\":\"").substringBefore("\"}") |                 jsonResponse.text.substringAfter("{\"data\":\"").substringBefore("\"}") | ||||||
|             val datadecrypted = cryptoHandler(dataencrypted, iv, secretDecryptKey, false) |             val datadecrypted = cryptoHandler(dataencrypted, foundIv, foundDecryptKey, false) | ||||||
|             val sources = AppUtils.parseJson<GogoSources>(datadecrypted) |             val sources = AppUtils.parseJson<GogoSources>(datadecrypted) | ||||||
| 
 | 
 | ||||||
|             fun invokeGogoSource( |             fun invokeGogoSource( | ||||||
|  | @ -372,12 +396,18 @@ class GogoanimeProvider : MainAPI() { | ||||||
|                             loadExtractor(data, streamingResponse.url, callback) |                             loadExtractor(data, streamingResponse.url, callback) | ||||||
|                         } |                         } | ||||||
|                 }, { |                 }, { | ||||||
|                     val iv = "8244002440089157".toByteArray() |                     val iv = null //"2094564712118349" | ||||||
|                     val secretKey = |                     val secretKey = null | ||||||
|                         "93106165734640459728346589106791".toByteArray() |                     val secretDecryptKey = null | ||||||
|                     val secretDecryptKey = |                     extractVidstream( | ||||||
|                         "97952160493714852094564712118349".toByteArray() |                         iframe, | ||||||
|                     extractVidstream(iframe, this.name, callback, iv, secretKey, secretDecryptKey) |                         this.name, | ||||||
|  |                         callback, | ||||||
|  |                         iv, | ||||||
|  |                         secretKey, | ||||||
|  |                         secretDecryptKey, | ||||||
|  |                         true | ||||||
|  |                     ) | ||||||
|                 }) |                 }) | ||||||
|             } |             } | ||||||
|         ) |         ) | ||||||
|  |  | ||||||
|  | @ -17,8 +17,8 @@ class AsianLoadProvider : VidstreamProviderTemplate() { | ||||||
|         "$mainUrl/ongoing-series" |         "$mainUrl/ongoing-series" | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     override val iv = "9262859232435825".toByteArray() |     override val iv = "9262859232435825" | ||||||
|     override val secretKey = "93422192433952489752342908585752".toByteArray() |     override val secretKey = "93422192433952489752342908585752" | ||||||
| 
 | 
 | ||||||
|     override val supportedTypes = setOf(TvType.AsianDrama) |     override val supportedTypes = setOf(TvType.AsianDrama) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -197,9 +197,9 @@ class DramaSeeProvider : MainAPI() { | ||||||
|                 //Log.i(this.name, "Result => (url) ${url}") |                 //Log.i(this.name, "Result => (url) ${url}") | ||||||
|                 when { |                 when { | ||||||
|                     url.startsWith("https://asianembed.io") || url.startsWith("https://asianload.io") -> { |                     url.startsWith("https://asianembed.io") || url.startsWith("https://asianload.io") -> { | ||||||
|                         val iv = "9262859232435825".toByteArray() |                         val iv = "9262859232435825" | ||||||
|                         val secretKey = "93422192433952489752342908585752".toByteArray() |                         val secretKey = "93422192433952489752342908585752" | ||||||
|                         extractVidstream(url, this.name, callback, iv, secretKey, secretKey) |                         extractVidstream(url, this.name, callback, iv, secretKey, secretKey, false) | ||||||
|                         AsianEmbedHelper.getUrls(url, callback) |                         AsianEmbedHelper.getUrls(url, callback) | ||||||
|                     } |                     } | ||||||
|                     url.startsWith("https://embedsito.com") -> { |                     url.startsWith("https://embedsito.com") -> { | ||||||
|  |  | ||||||
|  | @ -20,8 +20,9 @@ class VidEmbedProvider : VidstreamProviderTemplate() { | ||||||
|         "$mainUrl/cinema-movies" |         "$mainUrl/cinema-movies" | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     override val iv = "9225679083961858".toByteArray() |     override val iv = "9225679083961858" | ||||||
|     override val secretKey = "25742532592138496744665879883281".toByteArray() |     override val secretKey = "25742532592138496744665879883281" | ||||||
|  |     override val secretDecryptKey = secretKey | ||||||
| 
 | 
 | ||||||
|     // This is just extra metadata about what type of movies the provider has. |     // This is just extra metadata about what type of movies the provider has. | ||||||
|     // Needed for search functionality. |     // Needed for search functionality. | ||||||
|  |  | ||||||
|  | @ -64,9 +64,12 @@ open class VidstreamProviderTemplate : MainAPI() { | ||||||
|      */ |      */ | ||||||
|      */ |      */ | ||||||
| 
 | 
 | ||||||
|     open val iv: ByteArray? = null |     open val iv: String? = null | ||||||
|     open val secretKey: ByteArray? = null |     open val secretKey: String? = null | ||||||
|     open val secretDecryptKey: ByteArray? = null |     open val secretDecryptKey: String? = null | ||||||
|  |     /** Generated the key from IV and ID */ | ||||||
|  |     open val isUsingAdaptiveKeys: 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. | ||||||
| //    override val mainUrl: String | //    override val mainUrl: String | ||||||
|  | @ -252,7 +255,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) |         extractVidstream(iframeLink, this.name, callback, iv, secretKey, secretDecryptKey, isUsingAdaptiveKeys) | ||||||
|         // 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) | ||||||
|  |  | ||||||
|  | @ -214,9 +214,9 @@ class WatchAsianProvider : MainAPI() { | ||||||
|             //Log.i(this.name, "Result => (url) $url") |             //Log.i(this.name, "Result => (url) $url") | ||||||
|             when { |             when { | ||||||
|                 url.startsWith("https://asianembed.io") || url.startsWith("https://asianload.io") -> { |                 url.startsWith("https://asianembed.io") || url.startsWith("https://asianload.io") -> { | ||||||
|                     val iv = "9262859232435825".toByteArray() |                     val iv = "9262859232435825" | ||||||
|                     val secretKey = "93422192433952489752342908585752".toByteArray() |                     val secretKey = "93422192433952489752342908585752" | ||||||
|                     extractVidstream(url, this.name, callback, iv, secretKey, secretKey) |                     extractVidstream(url, this.name, callback, iv, secretKey, secretKey, 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