diff --git a/src/en/wcofun/build.gradle b/src/en/wcofun/build.gradle index aea0289f8..417966e8a 100644 --- a/src/en/wcofun/build.gradle +++ b/src/en/wcofun/build.gradle @@ -1,11 +1,14 @@ -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' +plugins { + alias(libs.plugins.android.application) + alias(libs.plugins.kotlin.android) + alias(libs.plugins.kotlin.serialization) +} ext { extName = 'Wcofun' pkgNameSuffix = 'en.wcofun' extClass = '.Wcofun' - extVersionCode = 9 + extVersionCode = 10 libVersion = '13' } diff --git a/src/en/wcofun/src/eu/kanade/tachiyomi/animeextension/en/wcofun/RedirectInterceptor.kt b/src/en/wcofun/src/eu/kanade/tachiyomi/animeextension/en/wcofun/RedirectInterceptor.kt deleted file mode 100644 index 9021a8862..000000000 --- a/src/en/wcofun/src/eu/kanade/tachiyomi/animeextension/en/wcofun/RedirectInterceptor.kt +++ /dev/null @@ -1,89 +0,0 @@ -package eu.kanade.tachiyomi.animeextension.en.wcofun - -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 RedirectInterceptor(private val baseUrl: String) : 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 - blockNetworkLoads = true - 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(baseUrl)) { - 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/en/wcofun/src/eu/kanade/tachiyomi/animeextension/en/wcofun/Wcofun.kt b/src/en/wcofun/src/eu/kanade/tachiyomi/animeextension/en/wcofun/Wcofun.kt index e9d4f012a..570e72027 100644 --- a/src/en/wcofun/src/eu/kanade/tachiyomi/animeextension/en/wcofun/Wcofun.kt +++ b/src/en/wcofun/src/eu/kanade/tachiyomi/animeextension/en/wcofun/Wcofun.kt @@ -1,8 +1,6 @@ package eu.kanade.tachiyomi.animeextension.en.wcofun import android.app.Application -import android.content.SharedPreferences -import android.util.Base64 import androidx.preference.ListPreference import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource @@ -14,23 +12,21 @@ import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.util.asJsoup +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable import kotlinx.serialization.decodeFromString import kotlinx.serialization.json.Json -import kotlinx.serialization.json.JsonObject -import kotlinx.serialization.json.jsonPrimitive import okhttp3.FormBody -import okhttp3.Headers +import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response -import org.jsoup.Jsoup import org.jsoup.nodes.Document import org.jsoup.nodes.Element import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get import uy.kohesive.injekt.injectLazy import java.lang.Exception -import java.net.URI class Wcofun : ConfigurableAnimeSource, ParsedAnimeHttpSource() { @@ -46,167 +42,30 @@ class Wcofun : ConfigurableAnimeSource, ParsedAnimeHttpSource() { private val json: Json by injectLazy() - private val preferences: SharedPreferences by lazy { + private val preferences by lazy { Injekt.get().getSharedPreferences("source_$id", 0x0000) } - override fun popularAnimeSelector(): String = "#sidebar_right2 ul.items li" + // ============================== Popular =============================== + override fun popularAnimeRequest(page: Int) = GET(baseUrl, headers = headers) - override fun popularAnimeRequest(page: Int): Request { - val interceptor = client.newBuilder().addInterceptor(RedirectInterceptor(baseUrl)).build() - val headers = interceptor.newCall(GET(baseUrl)).execute().request.headers - return GET(baseUrl, headers = headers) + override fun popularAnimeSelector() = "#sidebar_right2 ul.items li" + + override fun popularAnimeFromElement(element: Element) = SAnime.create().apply { + setUrlWithoutDomain(element.selectFirst("div.img a")!!.attr("href")) + title = element.selectFirst("div.recent-release-episodes a")!!.text() + thumbnail_url = element.selectFirst("div.img a img")!!.attr("abs:src") } - override fun popularAnimeFromElement(element: Element): SAnime { - val anime = SAnime.create() - anime.thumbnail_url = "https:" + element.select("div.img a img").attr("src") - anime.setUrlWithoutDomain(element.select("div.img a").attr("href")) - anime.title = element.select("div.recent-release-episodes a").text() - return anime - } + override fun popularAnimeNextPageSelector() = null - override fun popularAnimeNextPageSelector(): String? = null - - override fun episodeListSelector() = "div.cat-eps a" - - override fun episodeListParse(response: Response): List { - val document = response.asJsoup() - return document.select(episodeListSelector()).map { episodeFromElement(it) } - } - - override fun episodeFromElement(element: Element): SEpisode { - val episode = SEpisode.create() - episode.setUrlWithoutDomain(element.attr("href")) - val epName = element.ownText() - val season = epName.substringAfter("Season ") - val ep = epName.substringAfter("Episode ") - val seasonNo = try { - season.substringBefore(" ").toFloat() - } catch (e: NumberFormatException) { - 0.toFloat() - } - val epNo = try { - ep.substringBefore(" ").toFloat() - } catch (e: NumberFormatException) { - 0.toFloat() - } - var episodeName = if (ep == epName) epName else "Episode $ep" - episodeName = if (season == epName) episodeName else "Season $season" - episode.episode_number = epNo + (seasonNo * 100) - episode.name = episodeName - return episode - } - - override fun videoListParse(response: Response): List