diff --git a/src/en/dramacool/src/eu/kanade/tachiyomi/animeextension/en/dramacool/DramaCool.kt b/src/en/dramacool/src/eu/kanade/tachiyomi/animeextension/en/dramacool/DramaCool.kt index 95543e6e2..e4e89e1f7 100644 --- a/src/en/dramacool/src/eu/kanade/tachiyomi/animeextension/en/dramacool/DramaCool.kt +++ b/src/en/dramacool/src/eu/kanade/tachiyomi/animeextension/en/dramacool/DramaCool.kt @@ -1,8 +1,8 @@ package eu.kanade.tachiyomi.animeextension.en.dramacool import android.app.Application -import android.widget.Toast import android.content.SharedPreferences +import android.widget.Toast import androidx.preference.ListPreference import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.BuildConfig diff --git a/src/en/nineanime/src/eu/kanade/tachiyomi/animeextension/en/nineanime/NineAnime.kt b/src/en/nineanime/src/eu/kanade/tachiyomi/animeextension/en/nineanime/NineAnime.kt index a892e3cd1..a25f95ab3 100644 --- a/src/en/nineanime/src/eu/kanade/tachiyomi/animeextension/en/nineanime/NineAnime.kt +++ b/src/en/nineanime/src/eu/kanade/tachiyomi/animeextension/en/nineanime/NineAnime.kt @@ -12,7 +12,6 @@ import eu.kanade.tachiyomi.animesource.model.SEpisode import eu.kanade.tachiyomi.animesource.model.Video import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.util.asJsoup import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json @@ -126,15 +125,13 @@ class NineAnime : ConfigurableAnimeSource, ParsedAnimeHttpSource() { val episodeBody = getEpisodeBody() ?: getEpisodeBody()!! val encryptedSourceUrl = json.decodeFromString(episodeBody)["url"]!!.jsonPrimitive.content val embedLink = getLink(encryptedSourceUrl) + val vizcloudClient = client.newBuilder().addInterceptor(VizcloudInterceptor()).build() val referer = Headers.headersOf("Referer", "$baseUrl/") - val embed = client.newCall(GET(embedLink, referer)).execute().asJsoup() - val skey = embed.selectFirst("script:containsData(window.skey = )") - .data().substringAfter("window.skey = \'").substringBefore("\'") val sourceObject = json.decodeFromString( - client.newCall(GET(embedLink.replace("/embed/", "/info/") + "?skey=$skey", referer)) + vizcloudClient.newCall(GET(embedLink, referer)) .execute().body!!.string() ) - val mediaSources = sourceObject["media"]!!.jsonObject["sources"]!!.jsonArray + val mediaSources = sourceObject["data"]!!.jsonObject["media"]!!.jsonObject["sources"]!!.jsonArray val masterUrls = mediaSources.map { it.jsonObject["file"]!!.jsonPrimitive.content } val masterUrl = masterUrls.find { !it.contains("/simple/") } ?: masterUrls.first() val origin = Headers.headersOf("origin", "https://" + masterUrl.toHttpUrl().topPrivateDomain()) @@ -362,4 +359,4 @@ class NineAnime : ConfigurableAnimeSource, ParsedAnimeHttpSource() { private fun decode(input: String): String = java.net.URLDecoder.decode(input, "utf-8") } -private const val key = "0wMrYU+ixjJ4QdzgfN2HlyIVAt3sBOZnCT9Lm7uFDovkb/EaKpRWhqXS5168ePcG" +private const val key = "c/aUAorINHBLxWTy3uRiPt8J+vjsOheFG1E0q2X9CYwDZlnmd4Kb5M6gSVzfk7pQ" diff --git a/src/en/nineanime/src/eu/kanade/tachiyomi/animeextension/en/nineanime/VizcloudInterceptor.kt b/src/en/nineanime/src/eu/kanade/tachiyomi/animeextension/en/nineanime/VizcloudInterceptor.kt new file mode 100644 index 000000000..291532a7d --- /dev/null +++ b/src/en/nineanime/src/eu/kanade/tachiyomi/animeextension/en/nineanime/VizcloudInterceptor.kt @@ -0,0 +1,88 @@ +package eu.kanade.tachiyomi.animeextension.en.nineanime + +import android.annotation.SuppressLint +import android.app.Application +import android.os.Handler +import android.os.Looper +import android.webkit.WebResourceRequest +import android.webkit.WebResourceResponse +import android.webkit.WebView +import android.webkit.WebViewClient +import eu.kanade.tachiyomi.network.GET +import okhttp3.Headers.Companion.toHeaders +import okhttp3.Interceptor +import okhttp3.Request +import okhttp3.Response +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit + +class VizcloudInterceptor : Interceptor { + + private val context = Injekt.get() + private val handler by lazy { Handler(Looper.getMainLooper()) } + + override fun intercept(chain: Interceptor.Chain): Response { + val originalRequest = chain.request() + + val newRequest = resolveWithWebView(originalRequest) ?: throw Exception("bruh") + + return chain.proceed(newRequest) + } + + @SuppressLint("SetJavaScriptEnabled") + private fun resolveWithWebView(request: Request): Request? { + // We need to lock this thread until the WebView finds the challenge solution url, because + // OkHttp doesn't support asynchronous interceptors. + val latch = CountDownLatch(1) + + var webView: WebView? = null + + val origRequestUrl = request.url.toString() + val headers = request.headers.toMultimap().mapValues { it.value.getOrNull(0) ?: "" }.toMutableMap() + + var newRequest: Request? = null + + handler.post { + val webview = WebView(context) + webView = webview + with(webview.settings) { + javaScriptEnabled = true + domStorageEnabled = true + databaseEnabled = true + useWideViewPort = false + loadWithOverviewMode = false + userAgentString = request.header("User-Agent") + ?: "\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36 Edg/88.0.705.63\"" + } + + webview.webViewClient = object : WebViewClient() { + override fun shouldInterceptRequest( + view: WebView, + request: WebResourceRequest, + ): WebResourceResponse? { + if (request.url.toString().contains("/mediainfo")) { + newRequest = GET(request.url.toString(), request.requestHeaders.toHeaders()) + latch.countDown() + } + return super.shouldInterceptRequest(view, request) + } + } + + webView?.loadUrl(origRequestUrl, headers) + } + + // Wait a reasonable amount of time to retrieve the solution. The minimum should be + // around 4 seconds but it can take more due to slow networks or server issues. + latch.await(12, TimeUnit.SECONDS) + + handler.post { + webView?.stopLoading() + webView?.destroy() + webView = null + } + + return newRequest + } +} diff --git a/src/es/hentaila/src/eu/kanade/tachiyomi/animeextension/es/hentaila/Hentaila.kt b/src/es/hentaila/src/eu/kanade/tachiyomi/animeextension/es/hentaila/Hentaila.kt index f414761b6..9611bc779 100644 --- a/src/es/hentaila/src/eu/kanade/tachiyomi/animeextension/es/hentaila/Hentaila.kt +++ b/src/es/hentaila/src/eu/kanade/tachiyomi/animeextension/es/hentaila/Hentaila.kt @@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.animeextension.es.hentaila import android.app.Application import android.content.SharedPreferences -import android.util.Log import androidx.preference.ListPreference import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.animeextension.es.hentaila.extractors.FembedExtractor diff --git a/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplushd.kt b/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplushd.kt index 99499c294..36787add0 100644 --- a/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplushd.kt +++ b/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplushd.kt @@ -77,7 +77,6 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() { episode.setUrlWithoutDomain(element.attr("href")) episodes.add(episode) } - } return episodes }