From 004d8a4bff0dc89d8e9d8671671c2c22986c9e9c Mon Sep 17 00:00:00 2001 From: tarsin Date: Fri, 28 Apr 2023 13:25:08 +0800 Subject: [PATCH] Cleanup EhFilter --- .../java/com/hippo/ehviewer/AppConfig.java | 7 +- .../com/hippo/ehviewer/client/EhEngine.kt | 126 ++++++------------ .../com/hippo/ehviewer/client/EhFilter.kt | 97 +++----------- .../preference/RestoreDownloadPreference.kt | 13 +- 4 files changed, 65 insertions(+), 178 deletions(-) diff --git a/app/src/main/java/com/hippo/ehviewer/AppConfig.java b/app/src/main/java/com/hippo/ehviewer/AppConfig.java index ef16d897d..c6eeb3130 100644 --- a/app/src/main/java/com/hippo/ehviewer/AppConfig.java +++ b/app/src/main/java/com/hippo/ehviewer/AppConfig.java @@ -20,6 +20,7 @@ import android.annotation.SuppressLint; import android.content.Context; import android.os.Environment; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.hippo.ehviewer.client.exception.ParseException; @@ -134,7 +135,7 @@ public class AppConfig { return FileUtils.createTempFile(getTempDir(), null); } - public static void saveParseErrorBody(ParseException e) { + public static void saveParseErrorBody(@NonNull ParseException e) { File dir = getExternalParseErrorDir(); if (null == dir) { return; @@ -150,9 +151,7 @@ public class AppConfig { os.write(message.getBytes(StandardCharsets.UTF_8)); os.write('\n'); } - if (null != body) { - os.write(body.getBytes(StandardCharsets.UTF_8)); - } + os.write(body.getBytes(StandardCharsets.UTF_8)); os.flush(); } catch (IOException e1) { // Ignore diff --git a/app/src/main/java/com/hippo/ehviewer/client/EhEngine.kt b/app/src/main/java/com/hippo/ehviewer/client/EhEngine.kt index d4587955f..7552511de 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/EhEngine.kt +++ b/app/src/main/java/com/hippo/ehviewer/client/EhEngine.kt @@ -25,7 +25,6 @@ import com.hippo.ehviewer.Settings import com.hippo.ehviewer.client.data.GalleryCommentList import com.hippo.ehviewer.client.data.GalleryDetail import com.hippo.ehviewer.client.data.GalleryInfo -import com.hippo.ehviewer.client.data.GalleryPreview import com.hippo.ehviewer.client.exception.EhException import com.hippo.ehviewer.client.exception.ParseException import com.hippo.ehviewer.client.parser.ArchiveParser @@ -49,6 +48,7 @@ import com.hippo.ehviewer.client.parser.VoteTagParser import com.hippo.ehviewer.dailycheck.showEventNotification import com.hippo.ehviewer.dailycheck.today import com.hippo.network.StatusCodeException +import kotlinx.coroutines.CancellationException import kotlinx.coroutines.delay import moe.tarsin.coroutines.runSuspendCatching import okhttp3.Headers @@ -72,9 +72,11 @@ private const val SAD_PANDA_LENGTH = "9615" private const val KOKOMADE_URL = "https://exhentai.org/img/kokomade.jpg" private const val U_CONFIG_TEXT = "Selected Profile" private val MEDIA_TYPE_JPEG: MediaType = "image/jpeg".toMediaType() -private var sEhFilter = EhFilter -private fun rethrowExactly(code: Int, headers: Headers, body: String, e: Throwable) { +private fun rethrowExactly(code: Int, headers: Headers, body: String, e: Throwable): Nothing { + // Don't translate coroutine cancellation + if (e is CancellationException) throw e + // Check sad panda if (SAD_PANDA_DISPOSITION == headers["Content-Disposition"] && SAD_PANDA_TYPE == headers["Content-Type"] && SAD_PANDA_LENGTH == headers["Content-Length"]) { throw EhException("Sad Panda") @@ -106,12 +108,10 @@ private fun rethrowExactly(code: Int, headers: Headers, body: String, e: Throwab if (e is ParseException) { if (body.isEmpty()) { throw EhException(GetText.getString(R.string.error_empty_html)) - } else if (!body.contains("<")) { + } else if ("<" !in body) { throw EhException(body) } else { - if (Settings.saveParseErrorBody) { - AppConfig.saveParseErrorBody(e as ParseException?) - } + if (Settings.saveParseErrorBody) AppConfig.saveParseErrorBody(e) throw EhException(GetText.getString(R.string.error_parse_error)) } } @@ -124,11 +124,11 @@ private suspend inline fun Request.executeAndParsingWith(block: String.() -> Log.d(TAG, url.toString()) return okHttpClient.newCall(this).executeAsync().use { response -> val body = response.body.string() - runCatching { + try { block(body) - }.onFailure { - rethrowExactly(response.code, response.headers, body, it) - }.getOrThrow() + } catch (e: Exception) { + rethrowExactly(response.code, response.headers, body, e) + } } } @@ -149,15 +149,10 @@ object EhEngine { }.executeAndParsingWith(SignInParser::parse) } - private suspend fun fillGalleryList( - list: MutableList, - url: String, - filter: Boolean, - ) { + private suspend fun fillGalleryList(list: MutableList, url: String, filter: Boolean) { // Filter title and uploader - if (filter) { - list.removeAll { !sEhFilter.filterTitle(it) || !sEhFilter.filterUploader(it) } - } + if (filter) list.removeAll { EhFilter.filterTitle(it) || EhFilter.filterUploader(it) } + var hasTags = false var hasPages = false var hasRated = false @@ -172,57 +167,26 @@ object EhEngine { hasRated = true } } - val needApi = filter && sEhFilter.needTags() && !hasTags || - Settings.showGalleryPages && !hasPages || hasRated - if (needApi) { - fillGalleryListByApi(list, url) + val needApi = filter && EhFilter.needTags() && !hasTags || Settings.showGalleryPages && !hasPages || hasRated + if (needApi) fillGalleryListByApi(list, url) + + // Filter tag, thumbnail mode need filter uploader again + if (filter) list.removeAll { EhFilter.filterUploader(it) || EhFilter.filterTag(it) || EhFilter.filterTagNamespace(it) } + } + + suspend fun getGalleryList(url: String) = ehRequest(url, EhUrl.referer) + .executeAndParsingWith(GalleryListParser::parse) + .apply { fillGalleryList(galleryInfoList, url, true) } + + suspend fun fillGalleryListByApi(galleryInfoList: List, referer: String) = galleryInfoList.chunked(MAX_REQUEST_SIZE).forEach { doFillGalleryListByApi(it, referer) } + + private suspend fun doFillGalleryListByApi(galleryInfoList: List, referer: String) = ehRequest(EhUrl.apiUrl, referer, EhUrl.origin) { + jsonBody { + put("method", "gdata") + array("gidlist") { galleryInfoList.forEach { put(jsonArrayOf(it.gid, it.token)) } } + put("namespace", 1) } - - // Filter tag - if (filter) { - // Thumbnail mode need filter uploader again - list.removeAll { - !sEhFilter.filterUploader(it) || !sEhFilter.filterTag(it) || - !sEhFilter.filterTagNamespace(it) - } - } - } - - suspend fun getGalleryList(url: String): GalleryListParser.Result { - return ehRequest(url, EhUrl.referer).executeAndParsingWith(GalleryListParser::parse) - .apply { fillGalleryList(galleryInfoList, url, true) } - } - - suspend fun fillGalleryListByApi( - galleryInfoList: List, - referer: String, - ): List { - val requestItems: MutableList = ArrayList(MAX_REQUEST_SIZE) - var i = 0 - val size = galleryInfoList.size - while (i < size) { - requestItems.add(galleryInfoList[i]) - if (requestItems.size == MAX_REQUEST_SIZE || i == size - 1) { - doFillGalleryListByApi(requestItems, referer) - requestItems.clear() - } - i++ - } - return galleryInfoList - } - - private suspend fun doFillGalleryListByApi( - galleryInfoList: List, - referer: String, - ) { - return ehRequest(EhUrl.apiUrl, referer, EhUrl.origin) { - jsonBody { - put("method", "gdata") - array("gidlist") { galleryInfoList.forEach { put(jsonArrayOf(it.gid, it.token)) } } - put("namespace", 1) - } - }.executeAndParsingWith { GalleryApiParser.parse(this, galleryInfoList) } - } + }.executeAndParsingWith { GalleryApiParser.parse(this, galleryInfoList) } suspend fun getGalleryDetail(url: String): GalleryDetail { return ehRequest(url, EhUrl.referer).executeAndParsingWith { @@ -234,10 +198,8 @@ object EhEngine { } } - suspend fun getPreviewList(url: String): Pair, Int> { - return ehRequest(url, EhUrl.referer).executeAndParsingWith { - GalleryDetailParser.parsePreviewList(this) to GalleryDetailParser.parsePreviewPages(this) - } + suspend fun getPreviewList(url: String) = ehRequest(url, EhUrl.referer).executeAndParsingWith { + GalleryDetailParser.parsePreviewList(this) to GalleryDetailParser.parsePreviewPages(this) } @Throws(Throwable::class) @@ -360,24 +322,14 @@ object EhEngine { dstCat: Int, ): FavoritesParser.Result { val catStr: String = when (dstCat) { - -1 -> { - "delete" - } - - in 0..9 -> { - "fav$dstCat" - } - - else -> { - throw EhException("Invalid dstCat: $dstCat") - } + -1 -> { "delete" } + in 0..9 -> { "fav$dstCat" } + else -> { throw EhException("Invalid dstCat: $dstCat") } } return ehRequest(url, url, EhUrl.origin) { form { add("ddact", catStr) - for (gid in gidArray) { - add("modifygids[]", gid.toString()) - } + for (gid in gidArray) add("modifygids[]", gid.toString()) add("apply", "Apply") } }.executeAndParsingWith(FavoritesParser::parse).apply { fillGalleryList(galleryInfoList, url, false) } diff --git a/app/src/main/java/com/hippo/ehviewer/client/EhFilter.kt b/app/src/main/java/com/hippo/ehviewer/client/EhFilter.kt index 5180f8a38..a241889c3 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/EhFilter.kt +++ b/app/src/main/java/com/hippo/ehviewer/client/EhFilter.kt @@ -130,56 +130,25 @@ object EhFilter { } } + private inline fun Iterable.contains(predicate: (T) -> Boolean) = firstOrNull(predicate) != null + + private inline fun Array.contains(predicate: (T) -> Boolean) = firstOrNull(predicate) != null + @Synchronized fun needTags(): Boolean { return 0 != mTagFilterList.size || 0 != mTagNamespaceFilterList.size } @Synchronized - fun filterTitle(info: GalleryInfo?): Boolean { - if (null == info) { - return false - } - - // Title - val title = info.title - val filters: List = mTitleFilterList - if (null != title && filters.isNotEmpty()) { - var i = 0 - val n = filters.size - while (i < n) { - if (filters[i].enable!! && title.lowercase(Locale.getDefault()).contains( - filters[i].text!!, - ) - ) { - return false - } - i++ - } - } - return true + fun filterTitle(info: GalleryInfo): Boolean { + val title = info.title ?: return false + return mTitleFilterList.contains { it.enable!! && it.text!! in title.lowercase() } } @Synchronized - fun filterUploader(info: GalleryInfo?): Boolean { - if (null == info) { - return false - } - - // Uploader - val uploader = info.uploader - val filters: List = mUploaderFilterList - if (null != uploader && filters.isNotEmpty()) { - var i = 0 - val n = filters.size - while (i < n) { - if (filters[i].enable!! && uploader == filters[i].text) { - return false - } - i++ - } - } - return true + fun filterUploader(info: GalleryInfo): Boolean { + val uploader = info.uploader ?: return false + return mUploaderFilterList.contains { it.enable!! && it.text == uploader } } private fun matchTag(tag: String?, filter: String?): Boolean { @@ -216,27 +185,9 @@ object EhFilter { } @Synchronized - fun filterTag(info: GalleryInfo?): Boolean { - if (null == info) { - return false - } - - // Tag - val tags = info.simpleTags - val filters: List = mTagFilterList - if (null != tags && filters.isNotEmpty()) { - for (tag in tags) { - var i = 0 - val n = filters.size - while (i < n) { - if (filters[i].enable!! && matchTag(tag, filters[i].text)) { - return false - } - i++ - } - } - } - return true + fun filterTag(info: GalleryInfo): Boolean { + val tags = info.simpleTags ?: return false + return tags.contains { tag -> mTagFilterList.contains { it.enable!! && matchTag(tag, it.text) } } } private fun matchTagNamespace(tag: String?, filter: String?): Boolean { @@ -254,25 +205,9 @@ object EhFilter { } @Synchronized - fun filterTagNamespace(info: GalleryInfo?): Boolean { - if (null == info) { - return false - } - val tags = info.simpleTags - val filters: List = mTagNamespaceFilterList - if (null != tags && filters.isNotEmpty()) { - for (tag in tags) { - var i = 0 - val n = filters.size - while (i < n) { - if (filters[i].enable!! && matchTagNamespace(tag, filters[i].text)) { - return false - } - i++ - } - } - } - return true + fun filterTagNamespace(info: GalleryInfo): Boolean { + val tags = info.simpleTags ?: return false + return tags.contains { tag -> mTagNamespaceFilterList.contains { it.enable!! && matchTagNamespace(tag, it.text) } } } @Synchronized diff --git a/app/src/main/java/com/hippo/ehviewer/preference/RestoreDownloadPreference.kt b/app/src/main/java/com/hippo/ehviewer/preference/RestoreDownloadPreference.kt index 90642f506..d4ea50266 100644 --- a/app/src/main/java/com/hippo/ehviewer/preference/RestoreDownloadPreference.kt +++ b/app/src/main/java/com/hippo/ehviewer/preference/RestoreDownloadPreference.kt @@ -76,12 +76,13 @@ class RestoreDownloadPreference @JvmOverloads constructor( private suspend fun doRealWork(): List? { val dir = Settings.downloadLocation ?: return null val files = dir.listFiles() ?: return null - val restoreItemList = files.mapNotNull { getRestoreItem(it) } - return runSuspendCatching { - fillGalleryListByApi(restoreItemList, EhUrl.referer) - }.onFailure { - it.printStackTrace() - }.getOrNull() + return files.mapNotNull { getRestoreItem(it) }.apply { + runSuspendCatching { + fillGalleryListByApi(this, EhUrl.referer) + }.onFailure { + it.printStackTrace() + } + } } private class RestoreItem : BaseGalleryInfo() {