diff --git a/src/zh/zaimanhua/build.gradle b/src/zh/zaimanhua/build.gradle index 670881813..f1abbad08 100644 --- a/src/zh/zaimanhua/build.gradle +++ b/src/zh/zaimanhua/build.gradle @@ -1,7 +1,7 @@ ext { extName = 'Zaimanhua' extClass = '.Zaimanhua' - extVersionCode = 14 + extVersionCode = 15 isNsfw = false } diff --git a/src/zh/zaimanhua/src/eu/kanade/tachiyomi/extension/zh/zaimanhua/Filter.kt b/src/zh/zaimanhua/src/eu/kanade/tachiyomi/extension/zh/zaimanhua/Filter.kt index 054a6580b..eefeb9086 100644 --- a/src/zh/zaimanhua/src/eu/kanade/tachiyomi/extension/zh/zaimanhua/Filter.kt +++ b/src/zh/zaimanhua/src/eu/kanade/tachiyomi/extension/zh/zaimanhua/Filter.kt @@ -3,6 +3,8 @@ package eu.kanade.tachiyomi.extension.zh.zaimanhua import eu.kanade.tachiyomi.source.model.Filter import okhttp3.HttpUrl +class SearchByIdFilter : Filter.CheckBox("启用ID跳转(搜索纯数字时)") + open class QueryFilter(name: String, private val key: String, private val params: Array>) : Filter.Select(name, params.map { it.first }.toTypedArray()) { fun addQuery(builder: HttpUrl.Builder) { @@ -13,7 +15,7 @@ open class QueryFilter(name: String, private val key: String, private val params } } class RankingGroup : Filter.Group>( - "排行榜(搜索文本时无效)", + "排行榜(搜索时无效)", listOf>( TimeFilter(), SortFilter(), diff --git a/src/zh/zaimanhua/src/eu/kanade/tachiyomi/extension/zh/zaimanhua/Zaimanhua.kt b/src/zh/zaimanhua/src/eu/kanade/tachiyomi/extension/zh/zaimanhua/Zaimanhua.kt index 7e716da58..2dca416aa 100644 --- a/src/zh/zaimanhua/src/eu/kanade/tachiyomi/extension/zh/zaimanhua/Zaimanhua.kt +++ b/src/zh/zaimanhua/src/eu/kanade/tachiyomi/extension/zh/zaimanhua/Zaimanhua.kt @@ -62,33 +62,50 @@ class Zaimanhua : HttpSource(), ConfigurableSource { .build() private fun authIntercept(chain: Interceptor.Chain): Response { - val request = chain.request() + var request = chain.request() + val username = preferences.getString(USERNAME_PREF, "")!! + val password = preferences.getString(PASSWORD_PREF, "")!! + var token = preferences.getString(TOKEN_PREF, "")!! + var hasTriedLogin = false + + if (request.url.toString().startsWith(apiUrl) && request.header("authorization") == null && username.isNotBlank() && password.isNotBlank()) { + token = getToken(username, password) + apiHeaders = apiHeaders.newBuilder().setToken(token).build() + hasTriedLogin = true + preferences.edit().apply { + if (token.isBlank()) { + putString(TOKEN_PREF, "") + putString(USERNAME_PREF, "") + putString(PASSWORD_PREF, "").apply() + } else { + putString(TOKEN_PREF, token).apply() + request = request.newBuilder().headers(apiHeaders).build() + } + } + } val response = chain.proceed(request) // Only intercept chapter api requests that need token if (!request.url.toString().contains(checkTokenRegex)) return response // If chapter can read, return directly - if (response.peekBody(Long.MAX_VALUE).string().parseAs>>().data.data?.canRead != false) { - return response - } - // If can not read, need login or user permission is not enough - var token: String = preferences.getString(TOKEN_PREF, "")!! - if (!isValid(token)) { - // Token is invalid, need login - val username = preferences.getString(USERNAME_PREF, "")!! - val password = preferences.getString(PASSWORD_PREF, "")!! + val canRead = response.peekBody(Long.MAX_VALUE).string() + .parseAs>>().data.data?.canRead != false + if (canRead) return response + + if (!isValid(token) && !hasTriedLogin) { token = getToken(username, password) - if (token.isBlank()) { - preferences.edit().putString(TOKEN_PREF, "") - .putString(USERNAME_PREF, "") - .putString(PASSWORD_PREF, "").apply() - return response - } else { - preferences.edit().putString(TOKEN_PREF, token).apply() - apiHeaders = apiHeaders.newBuilder().setToken(token).build() - } + apiHeaders = apiHeaders.newBuilder().setToken(token).build() + preferences.edit().apply { + if (token.isBlank()) { + putString(TOKEN_PREF, "") + putString(USERNAME_PREF, "") + putString(PASSWORD_PREF, "") + } else { + putString(TOKEN_PREF, token) + } + }.apply() + if (token.isBlank()) return response } else if (request.header("authorization") == "Bearer $token") { - // The request has already used a valid token, return directly return response } @@ -145,8 +162,9 @@ class Zaimanhua : HttpSource(), ConfigurableSource { } // path: "/comic/detail/mangaId" + private fun getMangaUrl(id: String): HttpUrl = "$apiUrl/comic/detail/$id?_v=2.2.5".toHttpUrl() override fun mangaDetailsRequest(manga: SManga): Request = - GET("$apiUrl/comic/detail/${manga.url}?_v=2.2.5", apiHeaders) + GET(getMangaUrl(manga.url), apiHeaders) override fun mangaDetailsParse(response: Response): SManga { val result = response.parseAs>>() @@ -259,6 +277,7 @@ class Zaimanhua : HttpSource(), ConfigurableSource { override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { val ranking = filters.firstInstanceOrNull() val genres = filters.firstInstanceOrNull() + val searchById = filters.firstInstanceOrNull()?.state ?: false val url = when { query.isEmpty() && ranking != null && (ranking.state[0] as TimeFilter).state != 0 -> rankApiUrl().apply { ranking.state.filterIsInstance().forEach { it.addQuery(this) } @@ -270,6 +289,8 @@ class Zaimanhua : HttpSource(), ConfigurableSource { addQueryParameter("page", page.toString()) }.build() + query.isNotBlank() && searchById && query.toIntOrNull()?.let { it > 0 } ?: false -> getMangaUrl(query) + else -> searchApiUrl().apply { addQueryParameter("keyword", query) addQueryParameter("page", page.toString()) @@ -282,6 +303,8 @@ class Zaimanhua : HttpSource(), ConfigurableSource { val url = response.request.url return if (url.toString().startsWith("$apiUrl/comic/rank/list")) { latestUpdatesParse(response) + } else if (url.toString().startsWith("$apiUrl/comic/detail")) { + MangasPage(listOf(mangaDetailsParse(response)), false) } else { // "$apiUrl/comic/filter/list" or "$apiUrl/search/index" response.parseAs>().data.toMangasPage(url.queryParameter("page")!!.toInt()) @@ -302,6 +325,7 @@ class Zaimanhua : HttpSource(), ConfigurableSource { } override fun getFilterList() = FilterList( + SearchByIdFilter(), RankingGroup(), Filter.Separator(), Filter.Header("分类(搜索/查看排行榜时无效)"),