Jinman Tiantang: ID search & auto update domains (#16437)

* Jinman Tiantang: ID search & auto update domains

* Dedupe

* Non-null

* Reorder parameters
This commit is contained in:
stevenyomi 2023-05-19 18:15:45 +08:00 committed by GitHub
parent 3091cd6fdc
commit cd35641f37
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 103 additions and 51 deletions

View File

@ -30,18 +30,6 @@
android:host="jmcomic1.me"
android:pathPattern="/album/..*"
android:scheme="https" />
<data
android:host="jmcomic1.group"
android:pathPattern="/album/..*"
android:scheme="https" />
<data
android:host="jmcomic2.group"
android:pathPattern="/album/..*"
android:scheme="https" />
<data
android:host="jm-comic.cc"
android:pathPattern="/album/..*"
android:scheme="https" />
</intent-filter>
</activity>
</application>

View File

@ -5,7 +5,7 @@ ext {
extName = 'Jinman Tiantang'
pkgNameSuffix = 'zh.jinmantiantang'
extClass = '.Jinmantiantang'
extVersionCode = 35
extVersionCode = 36
isNsfw = true
}

View File

@ -1,6 +1,5 @@
package eu.kanade.tachiyomi.extension.zh.jinmantiantang
import android.app.Application
import android.content.SharedPreferences
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.network.GET
@ -24,8 +23,6 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.jsoup.select.Elements
import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.text.SimpleDateFormat
import java.util.Locale
@ -36,10 +33,12 @@ class Jinmantiantang : ParsedHttpSource(), ConfigurableSource {
override val supportsLatest: Boolean = true
private val preferences: SharedPreferences =
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
getSharedPreferences(id)
override val baseUrl: String = "https://" + preferences.baseUrl
private val updateUrlInterceptor = UpdateUrlInterceptor(preferences)
// 处理URL请求
override val client: OkHttpClient = network.cloudflareClient
.newBuilder()
@ -49,6 +48,7 @@ class Jinmantiantang : ParsedHttpSource(), ConfigurableSource {
preferences.getString(MAINSITE_RATELIMIT_PREF, MAINSITE_RATELIMIT_PREF_DEFAULT)!!.toInt(),
preferences.getString(MAINSITE_RATELIMIT_PERIOD, MAINSITE_RATELIMIT_PERIOD_DEFAULT)!!.toLong(),
)
.addInterceptor(updateUrlInterceptor)
.addInterceptor(ScrambledImageInterceptor).build()
// 点击量排序(人气)
@ -110,8 +110,8 @@ class Jinmantiantang : ParsedHttpSource(), ConfigurableSource {
}
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
return if (query.startsWith(PREFIX_ID_SEARCH)) {
val id = query.removePrefix(PREFIX_ID_SEARCH)
return if (query.startsWith(PREFIX_ID_SEARCH_NO_COLON, true) || query.toIntOrNull() != null) {
val id = query.removePrefix(PREFIX_ID_SEARCH_NO_COLON).removePrefix(":")
client.newCall(searchMangaByIdRequest(id))
.asObservableSuccess()
.map { response -> searchMangaByIdParse(response, id) }
@ -383,9 +383,10 @@ class Jinmantiantang : ParsedHttpSource(), ConfigurableSource {
}
override fun setupPreferenceScreen(screen: PreferenceScreen) {
getPreferenceList(screen.context).forEach { screen.addPreference(it) }
getPreferenceList(screen.context, preferences, updateUrlInterceptor.isUpdated).forEach(screen::addPreference)
}
companion object {
const val PREFIX_ID_SEARCH = "JM:"
private const val PREFIX_ID_SEARCH_NO_COLON = "JM"
const val PREFIX_ID_SEARCH = "$PREFIX_ID_SEARCH_NO_COLON:"
}
}

View File

@ -1,11 +1,18 @@
package eu.kanade.tachiyomi.extension.zh.jinmantiantang
import android.app.Application
import android.content.Context
import android.content.SharedPreferences
import androidx.preference.EditTextPreference
import androidx.preference.ListPreference
import eu.kanade.tachiyomi.network.GET
import okhttp3.Interceptor
import okhttp3.Response
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.IOException
internal fun getPreferenceList(context: Context) = arrayOf(
internal fun getPreferenceList(context: Context, preferences: SharedPreferences, isUrlUpdated: Boolean) = arrayOf(
ListPreference(context).apply {
key = MAINSITE_RATELIMIT_PREF
title = "在限制时间内(下个设置项)允许的请求数量。"
@ -27,23 +34,20 @@ internal fun getPreferenceList(context: Context) = arrayOf(
},
ListPreference(context).apply {
val count = SITE_ENTRIES_ARRAY.size
val urlList = preferences.urlList
val fullList = SITE_ENTRIES_ARRAY + urlList
val fullDesc = SITE_ENTRIES_ARRAY_DESCRIPTION + Array(urlList.size) { "中国大陆线路${it + 1}" }
val count = fullList.size
key = USE_MIRROR_URL_PREF
title = "使用镜像网址"
entries = Array(count) { "${SITE_ENTRIES_ARRAY_DESCRIPTION[it]} (${SITE_ENTRIES_ARRAY[it]})" }
entryValues = Array(count) { "$it" }.apply { this[count - 1] = "-1" }
summary = "%s\n重启后生效。"
entries = Array(count) { "${fullDesc[it]} (${fullList[it]})" }
entryValues = Array(count) { "$it" }
summary = if (isUrlUpdated) "%s\n镜像列表已自动更新,请选择合适的镜像并重启应用。" else "%s\n镜像列表会自动更新。重启后生效。"
setDefaultValue("0")
},
EditTextPreference(context).apply {
key = OVERRIDE_BASE_URL_PREF
title = "自定义网址"
summary = "需要在上一个设置选择“自定义”,重启后生效。" +
"不需要输入 https:// 前缀。最新网址可在 jmcomic1.bet 找到。"
},
EditTextPreference(context).apply {
key = BLOCK_PREF
title = "屏蔽词列表"
@ -58,13 +62,9 @@ internal fun getPreferenceList(context: Context) = arrayOf(
val SharedPreferences.baseUrl: String
get() {
val list = SITE_ENTRIES_ARRAY
val index = getString(USE_MIRROR_URL_PREF, "0")!!.toInt()
.coerceAtMost(list.size - 1)
return if (index == -1) {
getString(OVERRIDE_BASE_URL_PREF, list[0])!!
} else {
list[index]
}
val index = mirrorIndex
if (index in list.indices) return list[index]
return urlList.getOrNull(index - list.size) ?: list[0]
}
internal const val BLOCK_PREF = "BLOCK_GENRES_LIST"
@ -76,28 +76,91 @@ internal const val MAINSITE_RATELIMIT_PERIOD = "mainSiteRateLimitPeriodPreferenc
internal const val MAINSITE_RATELIMIT_PERIOD_DEFAULT = 3.toString()
private const val USE_MIRROR_URL_PREF = "useMirrorWebsitePreference"
private const val OVERRIDE_BASE_URL_PREF = "overrideBaseUrl"
private val SITE_ENTRIES_ARRAY_DESCRIPTION = arrayOf(
private val SITE_ENTRIES_ARRAY_DESCRIPTION get() = arrayOf(
"主站",
"海外分流",
"东南亚线路1",
"东南亚线路2",
"中国大陆线路1",
"中国大陆线路2",
"中国大陆线路3",
"自定义", // -1
)
// List is based on https://jmcomic1.bet/
// Please also update AndroidManifest
private val SITE_ENTRIES_ARRAY = arrayOf(
private val SITE_ENTRIES_ARRAY get() = arrayOf(
"18comic.vip",
"18comic.org",
"jmcomic.me",
"jmcomic1.me",
"jmcomic1.group",
"jmcomic2.group",
"jm-comic.cc",
"自定义", // -1
)
private const val DEFAULT_LIST = "jm-comic2.cc,jm-comic.org,jmcomic2.group"
private const val DEFAULT_LIST_PREF = "defaultBaseUrlList"
private const val URL_LIST_PREF = "baseUrlList"
private val SharedPreferences.mirrorIndex get() = getString(USE_MIRROR_URL_PREF, "0")!!.toInt()
private val SharedPreferences.urlList get() = getString(URL_LIST_PREF, DEFAULT_LIST)!!.split(",")
fun getSharedPreferences(id: Long): SharedPreferences {
val preferences: SharedPreferences = Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
if (preferences.getString(DEFAULT_LIST_PREF, "")!! == DEFAULT_LIST) return preferences
preferences.edit()
.remove("overrideBaseUrl")
.putString(DEFAULT_LIST_PREF, DEFAULT_LIST)
.setUrlList(DEFAULT_LIST, preferences.mirrorIndex)
.apply()
return preferences
}
fun SharedPreferences.Editor.setUrlList(urlList: String, oldIndex: Int): SharedPreferences.Editor {
putString(URL_LIST_PREF, urlList)
val maxIndex = SITE_ENTRIES_ARRAY.size + urlList.count { it == ',' }
if (oldIndex in 0..maxIndex) return this
return putString(USE_MIRROR_URL_PREF, maxIndex.toString())
}
class UpdateUrlInterceptor(private val preferences: SharedPreferences) : Interceptor {
private val baseUrl = "https://" + preferences.baseUrl
var isUpdated = false
override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request()
if (!request.url.toString().startsWith(baseUrl)) return chain.proceed(request)
val failedResponse = try {
val response = chain.proceed(request)
if (response.isSuccessful) return response
Result.success(response)
} catch (e: Throwable) {
if (chain.call().isCanceled()) throw e
Result.failure(e)
}
if (isUpdated || updateUrl(chain)) {
failedResponse.onSuccess(Response::close)
throw IOException("镜像网址已自动更新,请在插件设置中选择合适的镜像网址并重启应用")
}
return failedResponse.getOrThrow()
}
@Synchronized
private fun updateUrl(chain: Interceptor.Chain): Boolean {
if (isUpdated) return true
val response = try {
chain.proceed(GET("https://stevenyomi.github.io/source-domains/jmcomic.txt"))
} catch (_: Throwable) {
return false
}
if (!response.isSuccessful) {
response.close()
return false
}
val newList = response.body.string()
if (newList != preferences.getString(URL_LIST_PREF, "")!!) {
preferences.edit()
.setUrlList(newList, preferences.mirrorIndex)
.apply()
}
isUpdated = true
return true
}
}