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.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.mvvm.normalSafeApiCall | ||||
| import com.lagradost.cloudstream3.mvvm.safeApiCall | ||||
| import com.lagradost.cloudstream3.utils.* | ||||
| 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") | ||||
| 
 | ||||
|         // 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 | ||||
|         private fun cryptoHandler( | ||||
|             string: String, | ||||
|             iv: ByteArray, | ||||
|             secretKeyString: ByteArray, | ||||
|             iv: String, | ||||
|             secretKeyString: String, | ||||
|             encrypt: Boolean = true | ||||
|         ): String { | ||||
|             val ivParameterSpec = IvParameterSpec(iv) | ||||
|             val secretKey = SecretKeySpec(secretKeyString, "AES") | ||||
|             println("IV: $iv, Key: $secretKeyString, encrypt: $encrypt, Message: $string") | ||||
|             val ivParameterSpec = IvParameterSpec(iv.toByteArray()) | ||||
|             val secretKey = SecretKeySpec(secretKeyString.toByteArray(), "AES") | ||||
|             val cipher = Cipher.getInstance("AES/CBC/PKCS5Padding") | ||||
|             return if (!encrypt) { | ||||
|                 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 mainApiName used for ExtractorLink names and source | ||||
|          * @param iv secret iv from site, required non-null | ||||
|          * @param secretKey secret key for decryption from site, required non-null | ||||
|          * @param secretDecryptKey secret key to decrypt the response json, 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 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() | ||||
|          * */ | ||||
|         suspend fun extractVidstream( | ||||
|             iframeUrl: String, | ||||
|             mainApiName: String, | ||||
|             callback: (ExtractorLink) -> Unit, | ||||
|             iv: ByteArray?, | ||||
|             secretKey: ByteArray?, | ||||
|             secretDecryptKey: ByteArray? | ||||
|             iv: String?, | ||||
|             secretKey: String?, | ||||
|             secretDecryptKey: String?, | ||||
|             // This could be removed, but i prefer it verbose | ||||
|             isUsingAdaptiveKeys: 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 | ||||
|             // 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 | ||||
| 
 | ||||
|             if (iv == null || secretKey == null || secretDecryptKey == null) | ||||
|             if ((iv == null || secretKey == null || secretDecryptKey == null) && !isUsingAdaptiveKeys) | ||||
|                 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 mainUrl = "https://" + uri.host | ||||
| 
 | ||||
|             val id = Regex("id=([^&]+)").find(iframeUrl)!!.value.removePrefix("id=") | ||||
|             val encryptedId = cryptoHandler(id, iv, secretKey) | ||||
|             val encryptedId = cryptoHandler(id, foundIv, foundKey) | ||||
|             val jsonResponse = | ||||
|                 app.get( | ||||
|                     "$mainUrl/encrypt-ajax.php?id=$encryptedId&alias=$id", | ||||
|  | @ -91,7 +115,7 @@ class GogoanimeProvider : MainAPI() { | |||
|                 ) | ||||
|             val dataencrypted = | ||||
|                 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) | ||||
| 
 | ||||
|             fun invokeGogoSource( | ||||
|  | @ -372,12 +396,18 @@ class GogoanimeProvider : MainAPI() { | |||
|                             loadExtractor(data, streamingResponse.url, callback) | ||||
|                         } | ||||
|                 }, { | ||||
|                     val iv = "8244002440089157".toByteArray() | ||||
|                     val secretKey = | ||||
|                         "93106165734640459728346589106791".toByteArray() | ||||
|                     val secretDecryptKey = | ||||
|                         "97952160493714852094564712118349".toByteArray() | ||||
|                     extractVidstream(iframe, this.name, callback, iv, secretKey, secretDecryptKey) | ||||
|                     val iv = null //"2094564712118349" | ||||
|                     val secretKey = null | ||||
|                     val secretDecryptKey = null | ||||
|                     extractVidstream( | ||||
|                         iframe, | ||||
|                         this.name, | ||||
|                         callback, | ||||
|                         iv, | ||||
|                         secretKey, | ||||
|                         secretDecryptKey, | ||||
|                         true | ||||
|                     ) | ||||
|                 }) | ||||
|             } | ||||
|         ) | ||||
|  |  | |||
|  | @ -17,8 +17,8 @@ class AsianLoadProvider : VidstreamProviderTemplate() { | |||
|         "$mainUrl/ongoing-series" | ||||
|     ) | ||||
| 
 | ||||
|     override val iv = "9262859232435825".toByteArray() | ||||
|     override val secretKey = "93422192433952489752342908585752".toByteArray() | ||||
|     override val iv = "9262859232435825" | ||||
|     override val secretKey = "93422192433952489752342908585752" | ||||
| 
 | ||||
|     override val supportedTypes = setOf(TvType.AsianDrama) | ||||
| } | ||||
|  |  | |||
|  | @ -197,9 +197,9 @@ class DramaSeeProvider : MainAPI() { | |||
|                 //Log.i(this.name, "Result => (url) ${url}") | ||||
|                 when { | ||||
|                     url.startsWith("https://asianembed.io") || url.startsWith("https://asianload.io") -> { | ||||
|                         val iv = "9262859232435825".toByteArray() | ||||
|                         val secretKey = "93422192433952489752342908585752".toByteArray() | ||||
|                         extractVidstream(url, this.name, callback, iv, secretKey, secretKey) | ||||
|                         val iv = "9262859232435825" | ||||
|                         val secretKey = "93422192433952489752342908585752" | ||||
|                         extractVidstream(url, this.name, callback, iv, secretKey, secretKey, false) | ||||
|                         AsianEmbedHelper.getUrls(url, callback) | ||||
|                     } | ||||
|                     url.startsWith("https://embedsito.com") -> { | ||||
|  |  | |||
|  | @ -20,8 +20,9 @@ class VidEmbedProvider : VidstreamProviderTemplate() { | |||
|         "$mainUrl/cinema-movies" | ||||
|     ) | ||||
| 
 | ||||
|     override val iv = "9225679083961858".toByteArray() | ||||
|     override val secretKey = "25742532592138496744665879883281".toByteArray() | ||||
|     override val iv = "9225679083961858" | ||||
|     override val secretKey = "25742532592138496744665879883281" | ||||
|     override val secretDecryptKey = secretKey | ||||
| 
 | ||||
|     // This is just extra metadata about what type of movies the provider has. | ||||
|     // Needed for search functionality. | ||||
|  |  | |||
|  | @ -64,9 +64,12 @@ open class VidstreamProviderTemplate : MainAPI() { | |||
|      */ | ||||
|      */ | ||||
| 
 | ||||
|     open val iv: ByteArray? = null | ||||
|     open val secretKey: ByteArray? = null | ||||
|     open val secretDecryptKey: ByteArray? = null | ||||
|     open val iv: String? = null | ||||
|     open val secretKey: String? = 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. | ||||
| //    override val mainUrl: String | ||||
|  | @ -252,7 +255,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) | ||||
|         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. | ||||
|         // 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) | ||||
|  |  | |||
|  | @ -214,9 +214,9 @@ class WatchAsianProvider : MainAPI() { | |||
|             //Log.i(this.name, "Result => (url) $url") | ||||
|             when { | ||||
|                 url.startsWith("https://asianembed.io") || url.startsWith("https://asianload.io") -> { | ||||
|                     val iv = "9262859232435825".toByteArray() | ||||
|                     val secretKey = "93422192433952489752342908585752".toByteArray() | ||||
|                     extractVidstream(url, this.name, callback, iv, secretKey, secretKey) | ||||
|                     val iv = "9262859232435825" | ||||
|                     val secretKey = "93422192433952489752342908585752" | ||||
|                     extractVidstream(url, this.name, callback, iv, secretKey, secretKey, false) | ||||
|                     AsianEmbedHelper.getUrls(url, callback) | ||||
|                 } | ||||
|                 url.startsWith("https://embedsito.com") -> { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue