diff --git a/src/de/xcine/build.gradle b/src/de/xcine/build.gradle index da36529ae..78690d970 100644 --- a/src/de/xcine/build.gradle +++ b/src/de/xcine/build.gradle @@ -6,7 +6,7 @@ ext { extName = 'xCine' pkgNameSuffix = 'de.xcine' extClass = '.xCine' - extVersionCode = 2 + extVersionCode = 3 libVersion = '12' } diff --git a/src/de/xcine/src/eu/kanade/tachiyomi/animeextension/de/xcine/CookieInterceptor.kt b/src/de/xcine/src/eu/kanade/tachiyomi/animeextension/de/xcine/CookieInterceptor.kt new file mode 100644 index 000000000..df494e387 --- /dev/null +++ b/src/de/xcine/src/eu/kanade/tachiyomi/animeextension/de/xcine/CookieInterceptor.kt @@ -0,0 +1,88 @@ +package eu.kanade.tachiyomi.animeextension.de.xcine + +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 CookieInterceptor : 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("favicon.ico")) { + 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/de/xcine/src/eu/kanade/tachiyomi/animeextension/de/xcine/extractors/HDFilmExtractor.kt b/src/de/xcine/src/eu/kanade/tachiyomi/animeextension/de/xcine/extractors/HDFilmExtractor.kt index f2e132b88..2ade52917 100644 --- a/src/de/xcine/src/eu/kanade/tachiyomi/animeextension/de/xcine/extractors/HDFilmExtractor.kt +++ b/src/de/xcine/src/eu/kanade/tachiyomi/animeextension/de/xcine/extractors/HDFilmExtractor.kt @@ -1,5 +1,6 @@ package eu.kanade.tachiyomi.animeextension.de.xcine.extractors +import eu.kanade.tachiyomi.animeextension.de.xcine.CookieInterceptor import eu.kanade.tachiyomi.animesource.model.Video import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.POST @@ -16,8 +17,8 @@ class HDFilmExtractor(private val client: OkHttpClient) { val link = if (document.select("#breadcrumbDiv a[title=\"Serien stream\"]").attr("href").contains("/serien1")) { document.select("link[rel=canonical]").attr("href") } else { - val movielink = - document.select("a.play-film").attr("href") + val movielink = document.select("a.play-film").attr("href") + // val cookies = cookieClient.newCall(GET(movielink)).execute().request.headers val moviehtml = client.newCall(GET(movielink)).execute().asJsoup() moviehtml.select("link[rel=canonical]").attr("href") } @@ -27,10 +28,12 @@ class HDFilmExtractor(private val client: OkHttpClient) { val moviehtml = client.newCall(GET(link)).execute().asJsoup() moviehtml.select("a#nextEpisodeToPlay").attr("data-episode-id") } + val cookieClient = client.newBuilder().addInterceptor(CookieInterceptor()).build() + val cookieheaders = cookieClient.newCall(GET(link)).execute().headers val headers = Headers.Builder() + .addAll(cookieheaders) .add("origin", "https://xcine.me") .add("referer", link) - .add("user-agent", "Mozilla/5.0 (Linux; Android 12; Pixel 5 Build/SP2A.220405.004; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/100.0.4896.127 Safari/537.36") .add("X-Requested-With", "XMLHttpRequest") .add("Content-Type", "application/x-www-form-urlencoded") .build()