Keyoapp: Update cdn of sources and add paid chapters preference (#5666)
* update cdn and move preference to theme * lint
This commit is contained in:
		
							parent
							
								
									b1c2054428
								
							
						
					
					
						commit
						d7418f4b5f
					
				
							
								
								
									
										3
									
								
								lib-multisrc/keyoapp/assets/i18n/messages_en.properties
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								lib-multisrc/keyoapp/assets/i18n/messages_en.properties
									
									
									
									
									
										Normal 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.
 | 
			
		||||
@ -2,4 +2,8 @@ plugins {
 | 
			
		||||
    id("lib-multisrc")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
baseVersionCode = 7
 | 
			
		||||
baseVersionCode = 8
 | 
			
		||||
 | 
			
		||||
dependencies {
 | 
			
		||||
    api(project(":lib:i18n"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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(قادم)))"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -9,4 +9,6 @@ class ArvenComics : Keyoapp(
 | 
			
		||||
) {
 | 
			
		||||
    // migrated from Mangathemesia to Keyoapp
 | 
			
		||||
    override val versionId = 2
 | 
			
		||||
 | 
			
		||||
    override val cdnUrl = "https://3xfsjdlc.is1.buzz/uploads"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -9,4 +9,6 @@ class EZmanga : Keyoapp(
 | 
			
		||||
) {
 | 
			
		||||
    // Migrated from Madara to Keyoapp
 | 
			
		||||
    override val versionId = 2
 | 
			
		||||
 | 
			
		||||
    override val cdnUrl = "https://3xfsjdlc.is1.buzz/uploads"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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]))"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -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']))"
 | 
			
		||||
}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@ -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()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user