From 20b5cdd88c26d748df9e28d2bb0c839dcb193e3c Mon Sep 17 00:00:00 2001 From: Alessandro Jean Date: Fri, 12 Feb 2021 12:26:25 -0300 Subject: [PATCH] Temporary fix Cloudflare bypassing in Leitor.net (#5792) * Temporary fix Cloudflare bypassing in Leitor.net. * Mark extension as NSFW. --- src/pt/mangasproject/build.gradle | 7 +++++- .../pt/mangasproject/MangasProject.kt | 20 ++++++++++++--- .../pt/mangasproject/MangasProjectFactory.kt | 25 +++++++++++++++++++ 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/src/pt/mangasproject/build.gradle b/src/pt/mangasproject/build.gradle index 0f21bc119..d561055f3 100644 --- a/src/pt/mangasproject/build.gradle +++ b/src/pt/mangasproject/build.gradle @@ -5,8 +5,13 @@ ext { extName = 'mangásPROJECT' pkgNameSuffix = 'pt.mangasproject' extClass = '.MangasProjectFactory' - extVersionCode = 16 + extVersionCode = 17 libVersion = '1.2' + containsNsfw = true +} + +dependencies { + implementation project(':lib-ratelimit') } apply from: "$rootDir/common.gradle" diff --git a/src/pt/mangasproject/src/eu/kanade/tachiyomi/extension/pt/mangasproject/MangasProject.kt b/src/pt/mangasproject/src/eu/kanade/tachiyomi/extension/pt/mangasproject/MangasProject.kt index ebadf75b3..01b16637e 100644 --- a/src/pt/mangasproject/src/eu/kanade/tachiyomi/extension/pt/mangasproject/MangasProject.kt +++ b/src/pt/mangasproject/src/eu/kanade/tachiyomi/extension/pt/mangasproject/MangasProject.kt @@ -5,6 +5,7 @@ import com.github.salomonbrys.kotson.obj import com.github.salomonbrys.kotson.string import com.google.gson.JsonObject import com.google.gson.JsonParser +import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.source.model.FilterList @@ -39,6 +40,7 @@ abstract class MangasProject( // Sometimes the site is slow. override val client: OkHttpClient = network.cloudflareClient.newBuilder() + .addInterceptor(RateLimitInterceptor(30, 1, TimeUnit.MINUTES)) .connectTimeout(1, TimeUnit.MINUTES) .readTimeout(1, TimeUnit.MINUTES) .writeTimeout(1, TimeUnit.MINUTES) @@ -244,7 +246,9 @@ abstract class MangasProject( override fun pageListRequest(chapter: SChapter): Request { val newHeaders = headersBuilder() - .set("Referer", baseUrl + chapter.url) + .add("Accept", ACCEPT) + .add("Accept-Language", ACCEPT_LANGUAGE) + .set("Referer", "$baseUrl/home") .build() return GET(baseUrl + chapter.url, newHeaders) @@ -265,7 +269,7 @@ abstract class MangasProject( override fun pageListParse(response: Response): List { val document = response.asJsoup() val readerToken = getReaderToken(document) ?: throw Exception(TOKEN_NOT_FOUND) - val chapterUrl = response.request().url().toString() + val chapterUrl = getChapterUrl(response) val apiRequest = pageListApiRequest(chapterUrl, readerToken) val apiResponse = client.newCall(apiRequest).execute().asJsonObject() @@ -275,10 +279,15 @@ abstract class MangasProject( .mapIndexed { i, obj -> Page(i, chapterUrl, obj.string) } } + protected open fun getChapterUrl(response: Response): String { + return response.request().url().toString() + } + protected open fun getReaderToken(document: Document): String? { return document.select("script[src*=\"reader.\"]").firstOrNull() ?.attr("abs:src") - ?.let { HttpUrl.parse(it)!!.queryParameter("token") } + ?.let { HttpUrl.parse(it) } + ?.queryParameter("token") } override fun fetchImageUrl(page: Page): Observable = Observable.just(page.imageUrl!!) @@ -304,9 +313,12 @@ abstract class MangasProject( } companion object { + private const val ACCEPT = "text/html,application/xhtml+xml,application/xml;q=0.9," + + "image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9" private const val ACCEPT_JSON = "application/json, text/javascript, */*; q=0.01" + private const val ACCEPT_LANGUAGE = "pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,es;q=0.6,gl;q=0.5" private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) " + - "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36" + "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.150 Safari/537.36" private val JSON_PARSER by lazy { JsonParser() } diff --git a/src/pt/mangasproject/src/eu/kanade/tachiyomi/extension/pt/mangasproject/MangasProjectFactory.kt b/src/pt/mangasproject/src/eu/kanade/tachiyomi/extension/pt/mangasproject/MangasProjectFactory.kt index 6e7edea5e..d67d69c96 100644 --- a/src/pt/mangasproject/src/eu/kanade/tachiyomi/extension/pt/mangasproject/MangasProjectFactory.kt +++ b/src/pt/mangasproject/src/eu/kanade/tachiyomi/extension/pt/mangasproject/MangasProjectFactory.kt @@ -1,15 +1,18 @@ package eu.kanade.tachiyomi.extension.pt.mangasproject +import eu.kanade.tachiyomi.annotations.Nsfw import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.SourceFactory import eu.kanade.tachiyomi.source.model.Filter import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.MangasPage +import eu.kanade.tachiyomi.source.model.SChapter import okhttp3.Request import okhttp3.Response import org.jsoup.nodes.Document +@Nsfw class MangasProjectFactory : SourceFactory { override fun createSources(): List = listOf( LeitorNet(), @@ -24,6 +27,28 @@ class LeitorNet : MangasProject("Leitor.net", "https://leitor.net") { // became a different website, but they still use the same structure. // Existing mangas and other titles in the library still work. override val id: Long = 2225174659569980836 + + /** + * Temporary fix to bypass Cloudflare. + */ + override fun pageListRequest(chapter: SChapter): Request { + val newHeaders = super.pageListRequest(chapter).headers().newBuilder() + .set("Referer", "https://mangalivre.net/home") + .build() + + val newChapterUrl = chapter.url + .replace("/manga/", "/ler/") + .replace("/(\\d+)/capitulo-".toRegex(), "/online/$1/capitulo-") + + return GET("https://mangalivre.net$newChapterUrl", newHeaders) + } + + override fun getChapterUrl(response: Response): String { + return super.getChapterUrl(response) + .replace("https://mangalivre.net", baseUrl) + .replace("/ler/", "/manga/") + .replace("/online/", "/") + } } class MangaLivre : MangasProject("Mangá Livre", "https://mangalivre.net") {