Temporary fix Cloudflare bypassing in Leitor.net (#5792)

* Temporary fix Cloudflare bypassing in Leitor.net.

* Mark extension as NSFW.
This commit is contained in:
Alessandro Jean 2021-02-12 12:26:25 -03:00 committed by GitHub
parent f47cba6bd9
commit 20b5cdd88c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 5 deletions

View File

@ -5,8 +5,13 @@ ext {
extName = 'mangásPROJECT' extName = 'mangásPROJECT'
pkgNameSuffix = 'pt.mangasproject' pkgNameSuffix = 'pt.mangasproject'
extClass = '.MangasProjectFactory' extClass = '.MangasProjectFactory'
extVersionCode = 16 extVersionCode = 17
libVersion = '1.2' libVersion = '1.2'
containsNsfw = true
}
dependencies {
implementation project(':lib-ratelimit')
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View File

@ -5,6 +5,7 @@ import com.github.salomonbrys.kotson.obj
import com.github.salomonbrys.kotson.string import com.github.salomonbrys.kotson.string
import com.google.gson.JsonObject import com.google.gson.JsonObject
import com.google.gson.JsonParser import com.google.gson.JsonParser
import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
@ -39,6 +40,7 @@ abstract class MangasProject(
// Sometimes the site is slow. // Sometimes the site is slow.
override val client: OkHttpClient = network.cloudflareClient.newBuilder() override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.addInterceptor(RateLimitInterceptor(30, 1, TimeUnit.MINUTES))
.connectTimeout(1, TimeUnit.MINUTES) .connectTimeout(1, TimeUnit.MINUTES)
.readTimeout(1, TimeUnit.MINUTES) .readTimeout(1, TimeUnit.MINUTES)
.writeTimeout(1, TimeUnit.MINUTES) .writeTimeout(1, TimeUnit.MINUTES)
@ -244,7 +246,9 @@ abstract class MangasProject(
override fun pageListRequest(chapter: SChapter): Request { override fun pageListRequest(chapter: SChapter): Request {
val newHeaders = headersBuilder() val newHeaders = headersBuilder()
.set("Referer", baseUrl + chapter.url) .add("Accept", ACCEPT)
.add("Accept-Language", ACCEPT_LANGUAGE)
.set("Referer", "$baseUrl/home")
.build() .build()
return GET(baseUrl + chapter.url, newHeaders) return GET(baseUrl + chapter.url, newHeaders)
@ -265,7 +269,7 @@ abstract class MangasProject(
override fun pageListParse(response: Response): List<Page> { override fun pageListParse(response: Response): List<Page> {
val document = response.asJsoup() val document = response.asJsoup()
val readerToken = getReaderToken(document) ?: throw Exception(TOKEN_NOT_FOUND) 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 apiRequest = pageListApiRequest(chapterUrl, readerToken)
val apiResponse = client.newCall(apiRequest).execute().asJsonObject() val apiResponse = client.newCall(apiRequest).execute().asJsonObject()
@ -275,10 +279,15 @@ abstract class MangasProject(
.mapIndexed { i, obj -> Page(i, chapterUrl, obj.string) } .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? { protected open fun getReaderToken(document: Document): String? {
return document.select("script[src*=\"reader.\"]").firstOrNull() return document.select("script[src*=\"reader.\"]").firstOrNull()
?.attr("abs:src") ?.attr("abs:src")
?.let { HttpUrl.parse(it)!!.queryParameter("token") } ?.let { HttpUrl.parse(it) }
?.queryParameter("token")
} }
override fun fetchImageUrl(page: Page): Observable<String> = Observable.just(page.imageUrl!!) override fun fetchImageUrl(page: Page): Observable<String> = Observable.just(page.imageUrl!!)
@ -304,9 +313,12 @@ abstract class MangasProject(
} }
companion object { 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_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) " + 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() } private val JSON_PARSER by lazy { JsonParser() }

View File

@ -1,15 +1,18 @@
package eu.kanade.tachiyomi.extension.pt.mangasproject package eu.kanade.tachiyomi.extension.pt.mangasproject
import eu.kanade.tachiyomi.annotations.Nsfw
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.Source import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceFactory import eu.kanade.tachiyomi.source.SourceFactory
import eu.kanade.tachiyomi.source.model.Filter import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.SChapter
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
@Nsfw
class MangasProjectFactory : SourceFactory { class MangasProjectFactory : SourceFactory {
override fun createSources(): List<Source> = listOf( override fun createSources(): List<Source> = listOf(
LeitorNet(), LeitorNet(),
@ -24,6 +27,28 @@ class LeitorNet : MangasProject("Leitor.net", "https://leitor.net") {
// became a different website, but they still use the same structure. // became a different website, but they still use the same structure.
// Existing mangas and other titles in the library still work. // Existing mangas and other titles in the library still work.
override val id: Long = 2225174659569980836 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") { class MangaLivre : MangasProject("Mangá Livre", "https://mangalivre.net") {