diff --git a/src/zh/jinmantiantang/build.gradle b/src/zh/jinmantiantang/build.gradle index 376442d29..9f10661a7 100644 --- a/src/zh/jinmantiantang/build.gradle +++ b/src/zh/jinmantiantang/build.gradle @@ -5,7 +5,7 @@ ext { extName = 'Jinmantiantang' pkgNameSuffix = 'zh.jinmantiantang' extClass = '.Jinmantiantang' - extVersionCode = 9 + extVersionCode = 10 libVersion = '1.2' containsNsfw = 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 c815d9d6f..4b00de03e 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 @@ -1,11 +1,16 @@ package eu.kanade.tachiyomi.extension.zh.jinmantiantang +import android.app.Application +import android.content.SharedPreferences import android.graphics.Bitmap import android.graphics.BitmapFactory import android.graphics.Canvas import android.graphics.Rect +import androidx.preference.EditTextPreference +import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.annotations.Nsfw 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.Page @@ -22,13 +27,18 @@ import okhttp3.ResponseBody import org.jsoup.nodes.Document import org.jsoup.nodes.Element import org.jsoup.select.Elements +import uy.kohesive.injekt.Injekt +import uy.kohesive.injekt.api.get import java.io.ByteArrayOutputStream import java.io.InputStream import java.text.SimpleDateFormat import java.util.Locale +import kotlin.math.floor +import android.support.v7.preference.EditTextPreference as LegacyEditTextPreference +import android.support.v7.preference.PreferenceScreen as LegacyPreferenceScreen @Nsfw -class Jinmantiantang : ParsedHttpSource() { +class Jinmantiantang : ConfigurableSource, ParsedHttpSource() { override val baseUrl: String = "https://18comic5.biz" override val lang: String = "zh" @@ -38,7 +48,7 @@ class Jinmantiantang : ParsedHttpSource() { // 220980 // 算法 html页面 1800 行左右 // 图片开始分割的ID编号 - val scramble_id = 220980 + private val scrambleId = 220980 // 对只有一章的漫画进行判断条件 private var chapterArea = "a[class=col btn btn-primary dropdown-toggle reading]" @@ -49,7 +59,7 @@ class Jinmantiantang : ParsedHttpSource() { val url = chain.request().url().toString() val response = chain.proceed(chain.request()) if (!url.contains("media/photos", ignoreCase = true)) return response // 对非漫画图片连接直接放行 - if (url.substring(url.indexOf("photos/") + 7, url.lastIndexOf("/")).toInt() < scramble_id) return response // 对在漫画章节ID为220980之前的图片未进行图片分割,直接放行 + if (url.substring(url.indexOf("photos/") + 7, url.lastIndexOf("/")).toInt() < scrambleId) return response // 对在漫画章节ID为220980之前的图片未进行图片分割,直接放行 // 章节ID:220980(包含)之后的漫画(2020.10.27之后)图片进行了分割倒序处理 val res = response.body()!!.byteStream().use { decodeImage(it) @@ -70,20 +80,20 @@ class Jinmantiantang : ParsedHttpSource() { // 水平分割10个小图 val rows = 10 // 未除尽像素 - var remainder = (height % rows) + val remainder = (height % rows) // 创建新的图片对象 val resultBitmap = Bitmap.createBitmap(input.width, input.height, Bitmap.Config.ARGB_8888) val canvas = Canvas(resultBitmap) // 分割图片 for (x in 0 until rows) { // 分割算法(详情见html源码页的方法"function scramble_image(img)") - var copyH = Math.floor(height / rows.toDouble()).toInt() + var copyH = floor(height / rows.toDouble()).toInt() var py = copyH * (x) - var y = height - (copyH * (x + 1)) - remainder + val y = height - (copyH * (x + 1)) - remainder if (x == 0) { - copyH = copyH + remainder + copyH += remainder } else { - py = py + remainder + py += remainder } // 要裁剪的区域 val crop = Rect(0, y, width, y + copyH) @@ -103,12 +113,21 @@ class Jinmantiantang : ParsedHttpSource() { return GET("$baseUrl/albums?o=mv&page=$page", headers) } - override fun popularMangaNextPageSelector(): String? = "a.prevnext" - override fun popularMangaSelector(): String = "div.col-xs-6.col-sm-6.col-md-4.col-lg-3.list-col div.well.well-sm" + override fun popularMangaNextPageSelector(): String = "a.prevnext" + override fun popularMangaSelector(): String { + val baseSelector = "div.col-xs-6.col-sm-6.col-md-4.col-lg-3.list-col div.well.well-sm" + 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 + } 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].replace("_3x4", "") + thumbnail_url = element.select("img").attr("data-original").split("?")[0] author = element.select("div.title-truncate").select("a").first().text() } @@ -117,7 +136,7 @@ class Jinmantiantang : ParsedHttpSource() { return GET("$baseUrl/albums?o=mr&page=$page", headers) } - override fun latestUpdatesNextPageSelector(): String? = popularMangaNextPageSelector() + override fun latestUpdatesNextPageSelector(): String = popularMangaNextPageSelector() override fun latestUpdatesSelector(): String = popularMangaSelector() override fun latestUpdatesFromElement(element: Element): SManga = popularMangaFromElement(element) @@ -153,7 +172,7 @@ class Jinmantiantang : ParsedHttpSource() { return GET(url.toString(), headers) } - override fun searchMangaNextPageSelector(): String? = popularMangaNextPageSelector() + override fun searchMangaNextPageSelector(): String = popularMangaNextPageSelector() override fun searchMangaSelector(): String = popularMangaSelector() override fun searchMangaFromElement(element: Element): SManga = popularMangaFromElement(element) @@ -164,7 +183,8 @@ class Jinmantiantang : ParsedHttpSource() { override fun mangaDetailsParse(document: Document): SManga = SManga.create().apply { determineChapterInfo(document) title = document.select("div.panel-heading").select("div.pull-left").first().text() - thumbnail_url = document.select("img.lazy_img.img-responsive").attr("src").split("?")[0].replace("_3x4", "") + // 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") author = selectAuthor(document) artist = author genre = selectDetailsStatusAndGenre(document, 0).trim().split(" ").joinToString(", ") @@ -389,4 +409,41 @@ class Jinmantiantang : ParsedHttpSource() { Filter.Select(displayName, vals.map { it.first }.toTypedArray(), defaultValue) { open fun toUriPart() = vals[state].second } + + private val preferences: SharedPreferences by lazy { + Injekt.get().getSharedPreferences("source_$id", 0x0000) + } + + private val BLOCK_PREF_TITLE = "屏蔽词列表" + private val BLOCK_PREF_DEFAULT = "// 例如 \"YAOI cos 扶他 毛絨絨 獵奇 韩漫 韓漫\", " + + "关键词之间用空格分离, 大小写不敏感, \"//\"后的字符会被忽略" + private val BLOCK_PREF_DIALOGTITLE = "关键词列表" + + override fun setupPreferenceScreen(screen: PreferenceScreen) { + EditTextPreference(screen.context).apply { + key = "BLOCK_GENRES_LIST" + title = BLOCK_PREF_TITLE + setDefaultValue(BLOCK_PREF_DEFAULT) + dialogTitle = BLOCK_PREF_DIALOGTITLE + setOnPreferenceChangeListener { _, newValue -> + preferences.edit().putString("BLOCK_GENRES_LIST", newValue as String).commit() + } + }.let { + screen.addPreference(it) + } + } + + override fun setupPreferenceScreen(screen: LegacyPreferenceScreen) { + LegacyEditTextPreference(screen.context).apply { + key = "BLOCK_GENRES_LIST" + title = BLOCK_PREF_TITLE + setDefaultValue(BLOCK_PREF_DEFAULT) + dialogTitle = BLOCK_PREF_DIALOGTITLE + setOnPreferenceChangeListener { _, newValue -> + preferences.edit().putString("BLOCK_GENRES_LIST", newValue as String).commit() + } + }.let { + screen.addPreference(it) + } + } }