Keyoapp: Update cdn of sources and add paid chapters preference (#5666)

* update cdn and move preference to theme

* lint
This commit is contained in:
bapeey 2024-10-24 06:43:24 -05:00 committed by Draff
parent b1c2054428
commit d7418f4b5f
No known key found for this signature in database
GPG Key ID: E8A89F3211677653
11 changed files with 87 additions and 80 deletions

View File

@ -0,0 +1,3 @@
pref_show_paid_chapter_title=Display paid chapters
pref_show_paid_chapter_summary_on=Paid chapters will appear.
pref_show_paid_chapter_summary_off=Only free chapters will be displayed.

View File

@ -2,4 +2,8 @@ plugins {
id("lib-multisrc")
}
baseVersionCode = 7
baseVersionCode = 8
dependencies {
api(project(":lib:i18n"))
}

View File

@ -1,6 +1,12 @@
package eu.kanade.tachiyomi.multisrc.keyoapp
import android.app.Application
import android.content.SharedPreferences
import androidx.preference.PreferenceScreen
import androidx.preference.SwitchPreferenceCompat
import eu.kanade.tachiyomi.lib.i18n.Intl
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
@ -17,6 +23,8 @@ import okhttp3.Request
import okhttp3.Response
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.text.ParseException
import java.text.SimpleDateFormat
@ -27,7 +35,12 @@ abstract class Keyoapp(
override val name: String,
override val baseUrl: String,
final override val lang: String,
) : ParsedHttpSource() {
) : ParsedHttpSource(), ConfigurableSource {
protected val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
override val supportsLatest = true
override val client = network.cloudflareClient
@ -39,6 +52,13 @@ abstract class Keyoapp(
private val dateFormat = SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH)
protected val intl = Intl(
language = lang,
baseLanguage = "en",
availableLanguages = setOf("en", "pt-BR", "es"),
classLoader = this::class.java.classLoader!!,
)
// Popular
override fun popularMangaRequest(page: Int): Request = GET(baseUrl, headers)
@ -218,7 +238,12 @@ abstract class Keyoapp(
// Chapter list
override fun chapterListSelector(): String = "#chapters > a:not(:has(.text-sm span:matches(Upcoming)))"
override fun chapterListSelector(): String {
if (!preferences.showPaidChapters) {
return "#chapters > a:not(:has(.text-sm span:matches(Upcoming))):not(:has(img[src*=Coin.svg]))"
}
return "#chapters > a:not(:has(.text-sm span:matches(Upcoming)))"
}
override fun chapterFromElement(element: Element): SChapter = SChapter.create().apply {
setUrlWithoutDomain(element.selectFirst("a[href]")!!.attr("href"))
@ -226,6 +251,9 @@ abstract class Keyoapp(
element.selectFirst(".text-xs")?.run {
date_upload = text().trim().parseDate()
}
if (element.select("img[src*=Coin.svg]").isNotEmpty()) {
name = "🔒 $name"
}
}
// Image list
@ -235,7 +263,7 @@ abstract class Keyoapp(
.map { it.attr("uid") }
.filter { it.isNotEmpty() }
.mapIndexed { index, img ->
Page(index, document.location(), "$cdnUrl/uploads/$img")
Page(index, document.location(), "$cdnUrl/$img")
}
.takeIf { it.isNotEmpty() }
?.also { return it }
@ -249,7 +277,7 @@ abstract class Keyoapp(
}
}
protected val cdnUrl = "https://cdn.igniscans.com"
protected open val cdnUrl = "https://2xffbs-cn8.is1.buzz/uploads"
private val oldImgCdnRegex = Regex("""^(https?:)?//cdn\d*\.keyoapp\.com""")
@ -315,4 +343,22 @@ abstract class Keyoapp(
}
return now.timeInMillis
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
SwitchPreferenceCompat(screen.context).apply {
key = SHOW_PAID_CHAPTERS_PREF
title = intl["pref_show_paid_chapter_title"]
summaryOn = intl["pref_show_paid_chapter_summary_on"]
summaryOff = intl["pref_show_paid_chapter_summary_off"]
setDefaultValue(SHOW_PAID_CHAPTERS_DEFAULT)
}.also(screen::addPreference)
}
protected val SharedPreferences.showPaidChapters: Boolean
get() = getBoolean(SHOW_PAID_CHAPTERS_PREF, SHOW_PAID_CHAPTERS_DEFAULT)
companion object {
private const val SHOW_PAID_CHAPTERS_PREF = "pref_show_paid_chap"
private const val SHOW_PAID_CHAPTERS_DEFAULT = false
}
}

View File

@ -2,4 +2,12 @@ package eu.kanade.tachiyomi.extension.ar.scans4u
import eu.kanade.tachiyomi.multisrc.keyoapp.Keyoapp
class Scans4u : Keyoapp("Scans 4u", "https://4uscans.com", "ar")
class Scans4u : Keyoapp("Scans 4u", "https://4uscans.com", "ar") {
override fun chapterListSelector(): String {
if (!preferences.showPaidChapters) {
return "#chapters > a:not(:has(.text-sm span:matches(قادم))):not(:has(img[src*=Coin.svg]))"
}
return "#chapters > a:not(:has(.text-sm span:matches(قادم)))"
}
}

View File

@ -9,4 +9,6 @@ class ArvenComics : Keyoapp(
) {
// migrated from Mangathemesia to Keyoapp
override val versionId = 2
override val cdnUrl = "https://3xfsjdlc.is1.buzz/uploads"
}

View File

@ -9,4 +9,6 @@ class EZmanga : Keyoapp(
) {
// Migrated from Madara to Keyoapp
override val versionId = 2
override val cdnUrl = "https://3xfsjdlc.is1.buzz/uploads"
}

View File

@ -10,5 +10,5 @@ class LuaScans : Keyoapp(
// migrated from MangaThemesia to Keyoapp
override val versionId = 2
override fun chapterListSelector() = "${super.chapterListSelector()}:not(:has(img[src^='/assets/images/Coin.svg']))"
override val cdnUrl = "https://3xfsjdlc.is1.buzz/uploads"
}

View File

@ -15,6 +15,8 @@ class MagusManga : Keyoapp(
) {
override val versionId = 2
override val cdnUrl = "https://3xfsjdlc.is1.buzz/uploads"
override val client = network.cloudflareClient.newBuilder()
.addInterceptor(::captchaInterceptor)
.rateLimitHost(baseUrl.toHttpUrl(), 1)
@ -39,8 +41,4 @@ class MagusManga : Keyoapp(
return response
}
override fun chapterListSelector(): String {
return "${super.chapterListSelector()}:not(:has(img[src*=coin]))"
}
}

View File

@ -2,4 +2,10 @@ package eu.kanade.tachiyomi.extension.en.necroscans
import eu.kanade.tachiyomi.multisrc.keyoapp.Keyoapp
class NecroScans : Keyoapp("Necro Scans", "https://necroscans.com", "en")
class NecroScans : Keyoapp(
"Necro Scans",
"https://necroscans.com",
"en",
) {
override val cdnUrl = "https://3xfsjdlc.is1.buzz/uploads"
}

View File

@ -6,6 +6,4 @@ class RezoScans : Keyoapp(
"Rezo Scans",
"https://rezoscans.com",
"en",
) {
override fun chapterListSelector() = "${super.chapterListSelector()}:not(:has(img[src^='/assets/images/Coin.svg']))"
}
)

View File

@ -1,30 +1,14 @@
package eu.kanade.tachiyomi.extension.en.suryascans
import android.app.Application
import android.content.SharedPreferences
import androidx.preference.PreferenceScreen
import androidx.preference.SwitchPreferenceCompat
import eu.kanade.tachiyomi.multisrc.keyoapp.Keyoapp
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.concurrent.TimeUnit
class GenzToons :
Keyoapp(
"Genz Toons",
"https://genzupdates.com",
"en",
),
ConfigurableSource {
private val preferences: SharedPreferences =
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
class GenzToons : Keyoapp(
"Genz Toons",
"https://genzupdates.com",
"en",
) {
override val client = super.client.newBuilder()
.rateLimit(3)
@ -32,48 +16,4 @@ class GenzToons :
.writeTimeout(90, TimeUnit.SECONDS)
.readTimeout(90, TimeUnit.SECONDS)
.build()
override fun chapterListSelector(): String {
if (!preferences.showPaidChapters) {
return "#chapters > a:not(:has(.text-sm span:matches(Upcoming))):not(:has(img[src*=Coin.svg]))"
}
return "#chapters > a:not(:has(.text-sm span:matches(Upcoming)))"
}
override fun chapterFromElement(element: Element): SChapter {
return super.chapterFromElement(element).apply {
if (element.select("img[src*=Coin.svg]").isNotEmpty()) {
name = "🔒 $name"
}
}
}
override fun pageListParse(document: Document): List<Page> {
val script = document.select("#pages > script").joinToString("\n") { it.data() }
val realCdnUrl = CDN_URL_REGEX.find(script)?.groupValues?.get(1)?.takeIf { it.startsWith("http") }
?: "$baseUrl/uploads/"
return document.select("#pages > img")
.mapIndexed { index, img ->
Page(index, document.location(), realCdnUrl + img.attr("uid"))
}
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
SwitchPreferenceCompat(screen.context).apply {
key = SHOW_PAID_CHAPTERS_PREF
title = "Display paid chapters"
summaryOn = "Paid chapters will appear."
summaryOff = "Only free chapters will be displayed."
setDefaultValue(SHOW_PAID_CHAPTERS_DEFAULT)
}.also(screen::addPreference)
}
private val SharedPreferences.showPaidChapters: Boolean
get() = getBoolean(SHOW_PAID_CHAPTERS_PREF, SHOW_PAID_CHAPTERS_DEFAULT)
companion object {
private const val SHOW_PAID_CHAPTERS_PREF = "pref_show_paid_chap"
private const val SHOW_PAID_CHAPTERS_DEFAULT = false
private val CDN_URL_REGEX = """realUrl\s*=\s*`([^`]+?)\$""".toRegex()
}
}