LectorTMO: Add preference for save the last CF url (#1203)

Add pref
This commit is contained in:
bapeey 2024-02-12 02:19:50 -05:00 committed by Draff
parent 8bb508d679
commit 6850a721c0
2 changed files with 51 additions and 15 deletions

View File

@ -50,8 +50,10 @@ abstract class LectorTmo(
override val supportsLatest = true override val supportsLatest = true
override fun headersBuilder() = super.headersBuilder() // Needed to ignore the referer header in WebView
private val tmoHeaders = super.headersBuilder()
.set("Referer", "$baseUrl/") .set("Referer", "$baseUrl/")
.build()
protected open val imageCDNUrls = arrayOf( protected open val imageCDNUrls = arrayOf(
"https://img1.followmanga.com", "https://img1.followmanga.com",
@ -99,6 +101,7 @@ abstract class LectorTmo(
.build() .build()
} }
private var lastCFDomain: String = ""
override val client: OkHttpClient by lazy { override val client: OkHttpClient by lazy {
network.client.newBuilder() network.client.newBuilder()
.addInterceptor { chain -> .addInterceptor { chain ->
@ -109,6 +112,15 @@ abstract class LectorTmo(
} }
chain.proceed(request) chain.proceed(request)
} }
.addInterceptor() { chain ->
if (!getSaveLastCFUrlPref()) return@addInterceptor chain.proceed(chain.request())
val request = chain.request()
val response = chain.proceed(request)
if (response.code in CF_ERROR_CODES && response.header("Server") in CF_SERVER_CHECK) {
lastCFDomain = response.request.url.toString()
}
response
}
.rateLimitHost( .rateLimitHost(
baseUrl.toHttpUrl(), baseUrl.toHttpUrl(),
preferences.getString(WEB_RATELIMIT_PREF, WEB_RATELIMIT_PREF_DEFAULT_VALUE)!!.toInt(), preferences.getString(WEB_RATELIMIT_PREF, WEB_RATELIMIT_PREF_DEFAULT_VALUE)!!.toInt(),
@ -125,7 +137,7 @@ abstract class LectorTmo(
// Marks erotic content as false and excludes: Ecchi(6), GirlsLove(17), BoysLove(18), Harem(19), Trap(94) genders // Marks erotic content as false and excludes: Ecchi(6), GirlsLove(17), BoysLove(18), Harem(19), Trap(94) genders
private fun getSFWUrlPart(): String = if (getSFWModePref()) "&exclude_genders%5B%5D=6&exclude_genders%5B%5D=17&exclude_genders%5B%5D=18&exclude_genders%5B%5D=19&exclude_genders%5B%5D=94&erotic=false" else "" private fun getSFWUrlPart(): String = if (getSFWModePref()) "&exclude_genders%5B%5D=6&exclude_genders%5B%5D=17&exclude_genders%5B%5D=18&exclude_genders%5B%5D=19&exclude_genders%5B%5D=94&erotic=false" else ""
override fun popularMangaRequest(page: Int) = GET("$baseUrl/library?order_item=likes_count&order_dir=desc&filter_by=title${getSFWUrlPart()}&_pg=1&page=$page", headers) override fun popularMangaRequest(page: Int) = GET("$baseUrl/library?order_item=likes_count&order_dir=desc&filter_by=title${getSFWUrlPart()}&_pg=1&page=$page", tmoHeaders)
override fun popularMangaNextPageSelector() = "a[rel='next']" override fun popularMangaNextPageSelector() = "a[rel='next']"
@ -139,7 +151,7 @@ abstract class LectorTmo(
} }
} }
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/library?order_item=creation&order_dir=desc&filter_by=title${getSFWUrlPart()}&_pg=1&page=$page", headers) override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/library?order_item=creation&order_dir=desc&filter_by=title${getSFWUrlPart()}&_pg=1&page=$page", tmoHeaders)
override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector() override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
@ -167,7 +179,7 @@ abstract class LectorTmo(
} }
} }
private fun searchMangaBySlugRequest(slug: String) = GET("$baseUrl/$PREFIX_LIBRARY/$slug", headers) private fun searchMangaBySlugRequest(slug: String) = GET("$baseUrl/$PREFIX_LIBRARY/$slug", tmoHeaders)
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val url = "$baseUrl/library".toHttpUrl().newBuilder() val url = "$baseUrl/library".toHttpUrl().newBuilder()
@ -219,7 +231,7 @@ abstract class LectorTmo(
else -> {} else -> {}
} }
} }
return GET(url.build(), headers) return GET(url.build(), tmoHeaders)
} }
override fun searchMangaSelector() = popularMangaSelector() override fun searchMangaSelector() = popularMangaSelector()
@ -227,6 +239,11 @@ abstract class LectorTmo(
override fun searchMangaFromElement(element: Element): SManga = popularMangaFromElement(element) override fun searchMangaFromElement(element: Element): SManga = popularMangaFromElement(element)
override fun getMangaUrl(manga: SManga): String {
if (lastCFDomain.isNotEmpty()) return lastCFDomain.also { lastCFDomain = "" }
return super.getMangaUrl(manga)
}
override fun mangaDetailsParse(document: Document) = SManga.create().apply { override fun mangaDetailsParse(document: Document) = SManga.create().apply {
title = document.select("h2.element-subtitle").text() title = document.select("h2.element-subtitle").text()
document.select("h5.card-title").let { document.select("h5.card-title").let {
@ -249,6 +266,11 @@ abstract class LectorTmo(
protected open val oneShotChapterName = "One Shot" protected open val oneShotChapterName = "One Shot"
override fun getChapterUrl(chapter: SChapter): String {
if (lastCFDomain.isNotEmpty()) return lastCFDomain.also { lastCFDomain = "" }
return super.getChapterUrl(chapter)
}
override fun chapterListParse(response: Response): List<SChapter> { override fun chapterListParse(response: Response): List<SChapter> {
val document = response.asJsoup() val document = response.asJsoup()
@ -294,7 +316,7 @@ abstract class LectorTmo(
} }
override fun pageListRequest(chapter: SChapter): Request { override fun pageListRequest(chapter: SChapter): Request {
return GET(chapter.url, headers) return GET(chapter.url, tmoHeaders)
} }
override fun pageListParse(document: Document): List<Page> = mutableListOf<Page>().apply { override fun pageListParse(document: Document): List<Page> = mutableListOf<Page>().apply {
@ -406,6 +428,10 @@ abstract class LectorTmo(
} }
} }
override fun imageRequest(page: Page): Request {
return GET(page.imageUrl!!, tmoHeaders)
}
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException() override fun imageUrlParse(document: Document) = throw UnsupportedOperationException()
override fun getFilterList() = FilterList( override fun getFilterList() = FilterList(
@ -528,6 +554,8 @@ abstract class LectorTmo(
protected fun getSFWModePref(): Boolean = preferences.getBoolean(SFW_MODE_PREF, SFW_MODE_PREF_DEFAULT_VALUE) protected fun getSFWModePref(): Boolean = preferences.getBoolean(SFW_MODE_PREF, SFW_MODE_PREF_DEFAULT_VALUE)
protected fun getSaveLastCFUrlPref(): Boolean = preferences.getBoolean(SAVE_LAST_CF_URL_PREF, SAVE_LAST_CF_URL_PREF_DEFAULT_VALUE)
override fun setupPreferenceScreen(screen: PreferenceScreen) { override fun setupPreferenceScreen(screen: PreferenceScreen) {
val sfwModePref = CheckBoxPreference(screen.context).apply { val sfwModePref = CheckBoxPreference(screen.context).apply {
key = SFW_MODE_PREF key = SFW_MODE_PREF
@ -562,10 +590,18 @@ abstract class LectorTmo(
setDefaultValue(IMAGE_CDN_RATELIMIT_PREF_DEFAULT_VALUE) setDefaultValue(IMAGE_CDN_RATELIMIT_PREF_DEFAULT_VALUE)
} }
val saveLastCFUrlPreference = CheckBoxPreference(screen.context).apply {
key = SAVE_LAST_CF_URL_PREF
title = SAVE_LAST_CF_URL_PREF_TITLE
summary = SAVE_LAST_CF_URL_PREF_SUMMARY
setDefaultValue(SAVE_LAST_CF_URL_PREF_DEFAULT_VALUE)
}
screen.addPreference(sfwModePref) screen.addPreference(sfwModePref)
screen.addPreference(scanlatorPref) screen.addPreference(scanlatorPref)
screen.addPreference(apiRateLimitPreference) screen.addPreference(apiRateLimitPreference)
screen.addPreference(imgCDNRateLimitPreference) screen.addPreference(imgCDNRateLimitPreference)
screen.addPreference(saveLastCFUrlPreference)
} }
companion object { companion object {
@ -581,23 +617,20 @@ abstract class LectorTmo(
private val SFW_MODE_PREF_EXCLUDE_GENDERS = listOf("6", "17", "18", "19") private val SFW_MODE_PREF_EXCLUDE_GENDERS = listOf("6", "17", "18", "19")
private const val WEB_RATELIMIT_PREF = "webRatelimitPreference" private const val WEB_RATELIMIT_PREF = "webRatelimitPreference"
// Ratelimit permits per second for main website
private const val WEB_RATELIMIT_PREF_TITLE = "Ratelimit por minuto para el sitio web" private const val WEB_RATELIMIT_PREF_TITLE = "Ratelimit por minuto para el sitio web"
// This value affects network request amount to TMO url. Lower this value may reduce the chance to get HTTP 429 error, but loading speed will be slower too. App restart required. \nCurrent value: %s
private const val WEB_RATELIMIT_PREF_SUMMARY = "Este valor afecta la cantidad de solicitudes de red a la URL de TMO. Reducir este valor puede disminuir la posibilidad de obtener un error HTTP 429, pero la velocidad de descarga será más lenta. Se requiere reiniciar la app. \nValor actual: %s" private const val WEB_RATELIMIT_PREF_SUMMARY = "Este valor afecta la cantidad de solicitudes de red a la URL de TMO. Reducir este valor puede disminuir la posibilidad de obtener un error HTTP 429, pero la velocidad de descarga será más lenta. Se requiere reiniciar la app. \nValor actual: %s"
private const val WEB_RATELIMIT_PREF_DEFAULT_VALUE = "8" private const val WEB_RATELIMIT_PREF_DEFAULT_VALUE = "8"
private const val IMAGE_CDN_RATELIMIT_PREF = "imgCDNRatelimitPreference" private const val IMAGE_CDN_RATELIMIT_PREF = "imgCDNRatelimitPreference"
// Ratelimit permits per second for image CDN
private const val IMAGE_CDN_RATELIMIT_PREF_TITLE = "Ratelimit por minuto para descarga de imágenes" private const val IMAGE_CDN_RATELIMIT_PREF_TITLE = "Ratelimit por minuto para descarga de imágenes"
// This value affects network request amount for loading image. Lower this value may reduce the chance to get error when loading image, but loading speed will be slower too. App restart required. \nCurrent value: %s
private const val IMAGE_CDN_RATELIMIT_PREF_SUMMARY = "Este valor afecta la cantidad de solicitudes de red para descargar imágenes. Reducir este valor puede disminuir errores al cargar imagenes, pero la velocidad de descarga será más lenta. Se requiere reiniciar la app. \nValor actual: %s" private const val IMAGE_CDN_RATELIMIT_PREF_SUMMARY = "Este valor afecta la cantidad de solicitudes de red para descargar imágenes. Reducir este valor puede disminuir errores al cargar imagenes, pero la velocidad de descarga será más lenta. Se requiere reiniciar la app. \nValor actual: %s"
private const val IMAGE_CDN_RATELIMIT_PREF_DEFAULT_VALUE = "50" private const val IMAGE_CDN_RATELIMIT_PREF_DEFAULT_VALUE = "50"
private const val SAVE_LAST_CF_URL_PREF = "saveLastCFUrlPreference"
private const val SAVE_LAST_CF_URL_PREF_TITLE = "Guardar la última URL con error de Cloudflare"
private const val SAVE_LAST_CF_URL_PREF_SUMMARY = "Guarda la última URL con error de Cloudflare para que se pueda acceder a ella al abrir la serie en WebView."
private const val SAVE_LAST_CF_URL_PREF_DEFAULT_VALUE = true
private val ENTRIES_ARRAY = listOf(1, 2, 3, 5, 6, 7, 8, 9, 10, 15, 20, 30, 40, 50, 100).map { i -> i.toString() }.toTypedArray() private val ENTRIES_ARRAY = listOf(1, 2, 3, 5, 6, 7, 8, 9, 10, 15, 20, 30, 40, 50, 100).map { i -> i.toString() }.toTypedArray()
const val PREFIX_LIBRARY = "library" const val PREFIX_LIBRARY = "library"
@ -611,5 +644,8 @@ abstract class LectorTmo(
Pair("Fecha estreno", "release_date"), Pair("Fecha estreno", "release_date"),
Pair("Núm. Capítulos", "num_chapters"), Pair("Núm. Capítulos", "num_chapters"),
) )
private val CF_ERROR_CODES = listOf(403, 503)
private val CF_SERVER_CHECK = arrayOf("cloudflare-nginx", "cloudflare")
} }
} }

View File

@ -9,7 +9,7 @@ class LectorTmoGenerator : ThemeSourceGenerator {
override val themeClass = "LectorTmo" override val themeClass = "LectorTmo"
override val baseVersionCode: Int = 2 override val baseVersionCode: Int = 3
override val sources = listOf( override val sources = listOf(
SingleLang("LectorManga", "https://lectormanga.com", "es", isNsfw = true, overrideVersionCode = 34), SingleLang("LectorManga", "https://lectormanga.com", "es", isNsfw = true, overrideVersionCode = 34),