diff --git a/src/en/mangafox/build.gradle b/src/en/mangafox/build.gradle index ed52d140e..8b4940894 100644 --- a/src/en/mangafox/build.gradle +++ b/src/en/mangafox/build.gradle @@ -6,7 +6,12 @@ ext { extName = 'MangaFox' pkgNameSuffix = 'en.mangafox' extClass = '.MangaFox' - extVersionCode = 5 + extVersionCode = 6 + isNsfw = true +} + +dependencies { + implementation(project(":lib-unpacker")) } apply from: "$rootDir/common.gradle" diff --git a/src/en/mangafox/src/eu/kanade/tachiyomi/extension/en/mangafox/MangaFox.kt b/src/en/mangafox/src/eu/kanade/tachiyomi/extension/en/mangafox/MangaFox.kt index 6f671862b..3dbdd3d54 100644 --- a/src/en/mangafox/src/eu/kanade/tachiyomi/extension/en/mangafox/MangaFox.kt +++ b/src/en/mangafox/src/eu/kanade/tachiyomi/extension/en/mangafox/MangaFox.kt @@ -1,5 +1,7 @@ package eu.kanade.tachiyomi.extension.en.mangafox +import android.webkit.CookieManager +import eu.kanade.tachiyomi.lib.unpacker.Unpacker import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.interceptor.rateLimit import eu.kanade.tachiyomi.source.model.Filter @@ -8,12 +10,19 @@ import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.online.ParsedHttpSource +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.jsonArray +import kotlinx.serialization.json.jsonPrimitive +import okhttp3.Cookie +import okhttp3.CookieJar import okhttp3.Headers +import okhttp3.HttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.OkHttpClient import okhttp3.Request import org.jsoup.nodes.Document import org.jsoup.nodes.Element +import uy.kohesive.injekt.injectLazy import java.text.SimpleDateFormat import java.util.Calendar import java.util.Locale @@ -30,8 +39,36 @@ class MangaFox : ParsedHttpSource() { override val supportsLatest: Boolean = true + private val json by injectLazy() + override val client: OkHttpClient = network.cloudflareClient.newBuilder() .rateLimit(1, 1) + // Force readway=2 cookie to get all page URLs at once + .cookieJar(object : CookieJar { + private val cookieManager by lazy { CookieManager.getInstance() } + + init { + cookieManager.setCookie(mobileUrl.toHttpUrl().host, "readway=2") + cookieManager.setCookie(baseUrl.toHttpUrl().host, "isAdult=1") + } + + override fun saveFromResponse(url: HttpUrl, cookies: List) { + val urlString = url.toString() + cookies.forEach { cookieManager.setCookie(urlString, it.toString()) } + } + + override fun loadForRequest(url: HttpUrl): List { + val cookies = cookieManager.getCookie(url.toString()) + + return if (cookies != null && cookies.isNotEmpty()) { + cookies.split(";").mapNotNull { + Cookie.parse(url, it) + } + } else { + emptyList() + } + } + }) .build() override fun headersBuilder(): Headers.Builder = super.headersBuilder().add("Referer", "$baseUrl/") @@ -149,17 +186,27 @@ class MangaFox : ParsedHttpSource() { } override fun pageListRequest(chapter: SChapter): Request { - val mobilePath = chapter.url.replace("/manga/", "/roll_manga/") - - val headers = headersBuilder().set("Referer", "$mobileUrl/").build() - - return GET("$mobileUrl$mobilePath", headers) + val headers = headersBuilder() + .set("Referer", "$mobileUrl/") + .build() + return GET("$mobileUrl${chapter.url}", headers) } - override fun pageListParse(document: Document): List = - document.select("#viewer img").mapIndexed { idx, it -> - Page(idx, imageUrl = it.attr("abs:data-original")) + override fun pageListParse(document: Document): List { + val packed = document.selectFirst("script:containsData(p,a,c,k,e)").data() + val imagesRaw = Unpacker.unpack(packed) + .substringAfter("newImgs=") + .substringBefore(";") + return json.parseToJsonElement(imagesRaw).jsonArray.mapIndexed { idx, it -> + val rawImageUrl = it.jsonPrimitive.content + val imageUrl = if (rawImageUrl.startsWith("http")) { + rawImageUrl + } else { + "${mobileUrl.substringBefore("://")}:$rawImageUrl" + } + Page(idx, imageUrl = imageUrl) } + } override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used")