diff --git a/src/zh/jinmantiantang/AndroidManifest.xml b/src/zh/jinmantiantang/AndroidManifest.xml
index 363a1f0f8..c454edbba 100644
--- a/src/zh/jinmantiantang/AndroidManifest.xml
+++ b/src/zh/jinmantiantang/AndroidManifest.xml
@@ -27,7 +27,7 @@
android:pathPattern="/album/..*"
android:scheme="https" />
diff --git a/src/zh/jinmantiantang/build.gradle b/src/zh/jinmantiantang/build.gradle
index 060175030..c4d7e31b5 100644
--- a/src/zh/jinmantiantang/build.gradle
+++ b/src/zh/jinmantiantang/build.gradle
@@ -1,4 +1,3 @@
-
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
@@ -6,7 +5,7 @@ ext {
extName = 'Jinmantiantang'
pkgNameSuffix = 'zh.jinmantiantang'
extClass = '.Jinmantiantang'
- extVersionCode = 27
+ extVersionCode = 28
isNsfw = true
}
diff --git a/src/zh/jinmantiantang/src/eu/kanade/tachiyomi/extension/zh/jinmantiantang/Jinmantiantang.kt b/src/zh/jinmantiantang/src/eu/kanade/tachiyomi/extension/zh/jinmantiantang/Jinmantiantang.kt
index 0ffbc1f18..cc1192901 100644
--- a/src/zh/jinmantiantang/src/eu/kanade/tachiyomi/extension/zh/jinmantiantang/Jinmantiantang.kt
+++ b/src/zh/jinmantiantang/src/eu/kanade/tachiyomi/extension/zh/jinmantiantang/Jinmantiantang.kt
@@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.extension.zh.jinmantiantang
import android.app.Application
import android.content.SharedPreferences
import androidx.preference.EditTextPreference
+import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
@@ -16,7 +17,6 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup
-import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.OkHttpClient
import okhttp3.Request
@@ -30,28 +30,26 @@ import uy.kohesive.injekt.api.get
import java.text.SimpleDateFormat
import java.util.Locale
-class Jinmantiantang : ConfigurableSource, ParsedHttpSource() {
+class Jinmantiantang : ParsedHttpSource(), ConfigurableSource {
override val lang: String = "zh"
override val name: String = "禁漫天堂"
override val supportsLatest: Boolean = true
- private val preferences: SharedPreferences by lazy {
+ private val preferences: SharedPreferences =
Injekt.get().getSharedPreferences("source_$id", 0x0000)
- }
override val baseUrl: String = "https://" +
SITE_ENTRIES_ARRAY[preferences.getString(USE_MIRROR_URL_PREF, "0")!!.toInt()]
- private val baseHttpUrl: HttpUrl = baseUrl.toHttpUrlOrNull()!!
// 处理URL请求
override val client: OkHttpClient = network.cloudflareClient
.newBuilder()
// Add rate limit to fix manga thumbnail load failure
.rateLimitHost(
- baseHttpUrl,
- preferences.getString(MAINSITE_RATELIMIT_PREF, "1")!!.toInt(),
- preferences.getString(MAINSITE_RATELIMIT_PERIOD, "3")!!.toLong(),
+ baseUrl.toHttpUrlOrNull()!!,
+ preferences.getString(MAINSITE_RATELIMIT_PREF, MAINSITE_RATELIMIT_PREF_DEFAULT)!!.toInt(),
+ preferences.getString(MAINSITE_RATELIMIT_PERIOD, MAINSITE_RATELIMIT_PERIOD_DEFAULT)!!.toLong(),
)
.addInterceptor(ScrambledImageInterceptor).build()
@@ -62,21 +60,32 @@ class Jinmantiantang : ConfigurableSource, ParsedHttpSource() {
override fun popularMangaNextPageSelector(): String = "a.prevnext"
override fun popularMangaSelector(): String {
- val baseSelector = "div.list-col:not([style])"
+ return "div.list-col:not([style])"
+ }
+
+ private fun List.filterGenre(): List {
val removedGenres = preferences.getString("BLOCK_GENRES_LIST", "")!!.substringBefore("//").trim()
- // Extra selector is jquery-like selector, it uses regex to match element.text().
- // If string after 標籤 contains any word of removedGenres, the element would be ignored.
- return if (removedGenres != "")
- baseSelector + ":not(:matches((?i).*標籤: .*(${removedGenres.split(' ').joinToString("|")}).*))"
- else
- baseSelector
+ if (removedGenres.isEmpty()) return this
+ val removedList = removedGenres.lowercase().split(' ')
+ return this.filterNot { manga ->
+ manga.genre.orEmpty().lowercase().split(", ").any { removedList.contains(it) }
+ }
}
override fun popularMangaFromElement(element: Element): SManga = SManga.create().apply {
- title = element.select("span.video-title").text()
- setUrlWithoutDomain(element.select("a").first().attr("href"))
- thumbnail_url = element.select("img").attr("data-original").split("?")[0]
- author = element.select("div.title-truncate").select("a").first().text()
+ val children = element.child(0).children()
+ if (children[0].tagName() == "a") children.removeFirst()
+ title = children[1].text()
+ setUrlWithoutDomain(children[0].selectFirst("a").attr("href"))
+ val img = children[0].selectFirst("img")
+ thumbnail_url = img.attr("data-original").ifEmpty { img.attr("src") }.substringBeforeLast('?')
+ author = children[2].select("a").joinToString(", ") { it.text() }
+ genre = children[3].select("a").joinToString(", ") { it.text() }
+ }
+
+ override fun popularMangaParse(response: Response): MangasPage {
+ val page = super.popularMangaParse(response)
+ return MangasPage(page.mangas.filterGenre(), page.hasNextPage)
}
// 最新排序
@@ -88,6 +97,11 @@ class Jinmantiantang : ConfigurableSource, ParsedHttpSource() {
override fun latestUpdatesSelector(): String = popularMangaSelector()
override fun latestUpdatesFromElement(element: Element): SManga = popularMangaFromElement(element)
+ override fun latestUpdatesParse(response: Response): MangasPage {
+ val page = super.latestUpdatesParse(response)
+ return MangasPage(page.mangas.filterGenre(), page.hasNextPage)
+ }
+
// For JinmantiantangUrlActivity
private fun searchMangaByIdRequest(id: String) = GET("$baseUrl/album/$id", headers)
@@ -110,11 +124,7 @@ class Jinmantiantang : ConfigurableSource, ParsedHttpSource() {
// 查询信息
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
- var params = filters.map {
- if (it is UriPartFilter) {
- it.toUriPart()
- } else ""
- }.filter { it != "" }.joinToString("")
+ var params = filters.filterIsInstance().joinToString("") { it.toUriPart() }
val url = if (query != "" && !query.contains("-")) {
// 禁漫天堂特有搜索方式: A +B --> A and B, A B --> A or B
@@ -144,22 +154,24 @@ class Jinmantiantang : ConfigurableSource, ParsedHttpSource() {
override fun searchMangaSelector(): String = popularMangaSelector()
override fun searchMangaFromElement(element: Element): SManga = popularMangaFromElement(element)
+ override fun searchMangaParse(response: Response): MangasPage {
+ val page = super.searchMangaParse(response)
+ return MangasPage(page.mangas.filterGenre(), page.hasNextPage)
+ }
+
// 漫画详情
- // url网址 , title标题 , artist艺术家 , author作者 , description描述 , genre类型 , thumbnail_url缩图网址 , initialized是否初始化
- // status状态 0未知,1连载,2完结,3领取牌照
override fun mangaDetailsParse(document: Document): SManga = SManga.create().apply {
- title = document.select("div.panel-heading").select("div.pull-left").first().text()
+ title = document.selectFirst("h1").text()
// keep thumbnail_url same as the one in popularMangaFromElement()
- thumbnail_url = document.select("img.lazy_img.img-responsive").attr("src").split("?")[0].replace(".jpg", "_3x4.jpg")
+ thumbnail_url = document.selectFirst(".thumb-overlay > img").attr("src").substringBeforeLast('.') + "_3x4.jpg"
author = selectAuthor(document)
- artist = author
genre = selectDetailsStatusAndGenre(document, 0).trim().split(" ").joinToString(", ")
// When the index passed by the "selectDetailsStatusAndGenre(document: Document, index: Int)" index is 1,
// it will definitely return a String type of 0, 1 or 2. This warning can be ignored
status = selectDetailsStatusAndGenre(document, 1).trim().toInt()
- description = document.select("#intro-block .p-t-5.p-b-5").text().substringAfter("敘述:").trim()
+ description = document.selectFirst("#intro-block .p-t-5.p-b-5").text().substringAfter("敘述:").trim()
}
// 查询作者信息
@@ -207,8 +219,9 @@ class Jinmantiantang : ConfigurableSource, ParsedHttpSource() {
// 漫画章节信息
override fun chapterListSelector(): String = "div[id=episode-block] a[href^=/photo/]"
+ private val sdf = SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH)
+
override fun chapterFromElement(element: Element): SChapter = SChapter.create().apply {
- val sdf = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
url = element.select("a").attr("href")
name = element.select("a li").first().ownText()
date_upload = sdf.parse(element.select("a li span.hidden-xs").text().trim())?.time ?: 0
@@ -218,7 +231,6 @@ class Jinmantiantang : ConfigurableSource, ParsedHttpSource() {
val document = response.asJsoup()
if (document.select("div[id=episode-block] a li").size == 0) {
val singleChapter = SChapter.create().apply {
- val sdf = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
name = "单章节"
url = document.select("a[class=col btn btn-primary dropdown-toggle reading]").attr("href")
date_upload = sdf.parse(document.select("div[itemprop='datePublished']").attr("content"))?.time
@@ -377,45 +389,33 @@ class Jinmantiantang : ConfigurableSource, ParsedHttpSource() {
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
- val mainSiteRateLimitPreference = androidx.preference.ListPreference(screen.context).apply {
+ val mainSiteRateLimitPreference = ListPreference(screen.context).apply {
key = MAINSITE_RATELIMIT_PREF
title = MAINSITE_RATELIMIT_PREF_TITLE
entries = PREF_ENTRIES_ARRAY
entryValues = PREF_ENTRIES_ARRAY
summary = MAINSITE_RATELIMIT_PREF_SUMMARY
- setDefaultValue("1")
+ setDefaultValue(MAINSITE_RATELIMIT_PREF_DEFAULT)
setOnPreferenceChangeListener { _, newValue ->
- try {
- val setting = preferences.edit().putString(MAINSITE_RATELIMIT_PREF, newValue as String).commit()
- setting
- } catch (e: Exception) {
- e.printStackTrace()
- false
- }
+ preferences.edit().putString(MAINSITE_RATELIMIT_PREF, newValue as String).commit()
}
}
- val mainSiteRateLimitPeriodPreference = androidx.preference.ListPreference(screen.context).apply {
+ val mainSiteRateLimitPeriodPreference = ListPreference(screen.context).apply {
key = MAINSITE_RATELIMIT_PERIOD
title = MAINSITE_RATELIMIT_PERIOD_TITLE
entries = PERIOD_ENTRIES_ARRAY
entryValues = PERIOD_ENTRIES_ARRAY
summary = MAINSITE_RATELIMIT_PERIOD_SUMMARY
- setDefaultValue("3")
+ setDefaultValue(MAINSITE_RATELIMIT_PERIOD_DEFAULT)
setOnPreferenceChangeListener { _, newValue ->
- try {
- val setting = preferences.edit().putString(MAINSITE_RATELIMIT_PERIOD, newValue as String).commit()
- setting
- } catch (e: Exception) {
- e.printStackTrace()
- false
- }
+ preferences.edit().putString(MAINSITE_RATELIMIT_PERIOD, newValue as String).commit()
}
}
- val mirrorURLPreference = androidx.preference.ListPreference(screen.context).apply {
+ val mirrorURLPreference = ListPreference(screen.context).apply {
key = USE_MIRROR_URL_PREF
title = USE_MIRROR_URL_PREF_TITLE
entries = SITE_ENTRIES_ARRAY_DESCRIPTION
@@ -424,37 +424,31 @@ class Jinmantiantang : ConfigurableSource, ParsedHttpSource() {
setDefaultValue("0")
setOnPreferenceChangeListener { _, newValue ->
- try {
- val setting = preferences.edit().putString(USE_MIRROR_URL_PREF, newValue as String).commit()
- setting
- } catch (e: Exception) {
- e.printStackTrace()
- false
- }
+ preferences.edit().putString(USE_MIRROR_URL_PREF, newValue as String).commit()
}
}
- EditTextPreference(screen.context).apply {
- key = "BLOCK_GENRES_LIST"
+ val blockGenrePreference = EditTextPreference(screen.context).apply {
+ key = BLOCK_PREF
title = BLOCK_PREF_TITLE
setDefaultValue(BLOCK_PREF_DEFAULT)
dialogTitle = BLOCK_PREF_DIALOGTITLE
setOnPreferenceChangeListener { _, newValue ->
- preferences.edit().putString("BLOCK_GENRES_LIST", newValue as String).commit()
+ preferences.edit().putString(BLOCK_PREF, newValue as String).commit()
}
- }.let {
- screen.addPreference(it)
}
screen.addPreference(mainSiteRateLimitPreference)
screen.addPreference(mainSiteRateLimitPeriodPreference)
screen.addPreference(mirrorURLPreference)
+ screen.addPreference(blockGenrePreference)
}
companion object {
private const val DEFAULT_SITE = "18comic.vip"
const val PREFIX_ID_SEARCH = "JM:"
+ private const val BLOCK_PREF = "BLOCK_GENRES_LIST"
private const val BLOCK_PREF_TITLE = "屏蔽词列表"
private const val BLOCK_PREF_DEFAULT = "// 例如 \"YAOI cos 扶他 毛絨絨 獵奇 韩漫 韓漫\", " +
"关键词之间用空格分离, 大小写不敏感, \"//\"后的字符会被忽略"
@@ -463,17 +457,19 @@ class Jinmantiantang : ConfigurableSource, ParsedHttpSource() {
private const val MAINSITE_RATELIMIT_PREF = "mainSiteRateLimitPreference"
private const val MAINSITE_RATELIMIT_PREF_TITLE = "在限制时间内(下个设置项)允许的请求数量。" // Number of requests allowed within a period of units.
private const val MAINSITE_RATELIMIT_PREF_SUMMARY = "此值影响更新书架时发起连接请求的数量。调低此值可能减小IP被屏蔽的几率,但加载速度也会变慢。需要重启软件以生效。\n当前值:%s"
+ private val PREF_ENTRIES_ARRAY = (1..10).map { i -> i.toString() }.toTypedArray()
+ private const val MAINSITE_RATELIMIT_PREF_DEFAULT = 1.toString()
private const val MAINSITE_RATELIMIT_PERIOD = "mainSiteRateLimitPeriodPreference"
private const val MAINSITE_RATELIMIT_PERIOD_TITLE = "限制持续时间。单位秒" // The limiting duration. Defaults to 3.
private const val MAINSITE_RATELIMIT_PERIOD_SUMMARY = "此值影响更新书架时请求的间隔时间。调大此值可能减小IP被屏蔽的几率,但更新时间也会变慢。需要重启软件以生效。\n当前值:%s"
+ private val PERIOD_ENTRIES_ARRAY = (1..60).map { i -> i.toString() }.toTypedArray()
+ private const val MAINSITE_RATELIMIT_PERIOD_DEFAULT = 3.toString()
private const val USE_MIRROR_URL_PREF = "useMirrorWebsitePreference"
private const val USE_MIRROR_URL_PREF_TITLE = "使用镜像网址"
private const val USE_MIRROR_URL_PREF_SUMMARY = "使用镜像网址。需要重启软件以生效。" // "Use mirror url. Defaults to main site"
- private val PREF_ENTRIES_ARRAY = (1..10).map { i -> i.toString() }.toTypedArray()
- private val PERIOD_ENTRIES_ARRAY = (1..60).map { i -> i.toString() }.toTypedArray()
private val SITE_ENTRIES_ARRAY_DESCRIPTION = arrayOf(
"主站", "海外分流",
"中国大陆总站", "中国大陆分流1", "中国大陆分流1"
@@ -484,7 +480,7 @@ class Jinmantiantang : ConfigurableSource, ParsedHttpSource() {
// Please also update AndroidManifest
private val SITE_ENTRIES_ARRAY = arrayOf(
DEFAULT_SITE, "18comic.org",
- "jmcomic.asia", "jmcomic1.asia", "jmcomic1.asia"
+ "jmcomic.asia", "jmcomic.city", "jmcomic.city"
)
}
}
diff --git a/src/zh/jinmantiantang/src/eu/kanade/tachiyomi/extension/zh/jinmantiantang/JinmantiantangUrlActivity.kt b/src/zh/jinmantiantang/src/eu/kanade/tachiyomi/extension/zh/jinmantiantang/JinmantiantangUrlActivity.kt
index f708309c7..8d9f7235f 100644
--- a/src/zh/jinmantiantang/src/eu/kanade/tachiyomi/extension/zh/jinmantiantang/JinmantiantangUrlActivity.kt
+++ b/src/zh/jinmantiantang/src/eu/kanade/tachiyomi/extension/zh/jinmantiantang/JinmantiantangUrlActivity.kt
@@ -29,10 +29,10 @@ class JinmantiantangUrlActivity : Activity() {
try {
startActivity(mainIntent)
} catch (e: ActivityNotFoundException) {
- Log.e("JinmantiantangUrlActivity", e.toString())
+ Log.e("JinmantiantangUrl", e.toString())
}
} else {
- Log.e("JinmantiantangUrlActivity", "could not parse uri from intent $intent")
+ Log.e("JinmantiantangUrl", "could not parse uri from intent $intent")
}
finish()