From 36295f9b699dacdb80e596b94f8723fd949d70b9 Mon Sep 17 00:00:00 2001 From: Tejas Sharma Date: Fri, 23 May 2025 19:53:06 -0700 Subject: [PATCH] Comick: option to de-duplicate chapters based on "score" (#8923) * Adds the ability to automatically filter chapters in comick based on their "score" * wording update, version bump * use chapter_ prefix when referring to score filtering * Update src/all/comickfun/assets/i18n/messages_en.properties Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com> * change syntax for filtering based on PR feedback * figured out how to make an extension * updated, thanks! --------- Co-authored-by: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com> --- .../assets/i18n/messages_en.properties | 3 ++ src/all/comickfun/build.gradle | 2 +- .../extension/all/comickfun/Comick.kt | 29 +++++++++++++++++++ .../tachiyomi/extension/all/comickfun/Dto.kt | 6 +++- 4 files changed, 38 insertions(+), 2 deletions(-) diff --git a/src/all/comickfun/assets/i18n/messages_en.properties b/src/all/comickfun/assets/i18n/messages_en.properties index 654015d98..5a559b779 100644 --- a/src/all/comickfun/assets/i18n/messages_en.properties +++ b/src/all/comickfun/assets/i18n/messages_en.properties @@ -22,3 +22,6 @@ score_position_top=Top score_position_middle=Middle score_position_bottom=Bottom score_position_none=Hide Score +chapter_score_filtering_title=Automatically de-duplicate chapters +chapter_score_filtering_on=For each chapter, only displays the scanlator with the highest score +chapter_score_filtering_off=Does not filterout any chapters based on score (any other scanlator filtering will still apply) diff --git a/src/all/comickfun/build.gradle b/src/all/comickfun/build.gradle index 5832dfd6a..381352ccb 100644 --- a/src/all/comickfun/build.gradle +++ b/src/all/comickfun/build.gradle @@ -1,7 +1,7 @@ ext { extName = 'Comick' extClass = '.ComickFactory' - extVersionCode = 56 + extVersionCode = 57 isNsfw = true } diff --git a/src/all/comickfun/src/eu/kanade/tachiyomi/extension/all/comickfun/Comick.kt b/src/all/comickfun/src/eu/kanade/tachiyomi/extension/all/comickfun/Comick.kt index 6d6b95398..c8052860f 100644 --- a/src/all/comickfun/src/eu/kanade/tachiyomi/extension/all/comickfun/Comick.kt +++ b/src/all/comickfun/src/eu/kanade/tachiyomi/extension/all/comickfun/Comick.kt @@ -178,6 +178,20 @@ abstract class Comick( .commit() } }.also(screen::addPreference) + + SwitchPreferenceCompat(screen.context).apply { + key = CHAPTER_SCORE_FILTERING_PREF + title = intl["chapter_score_filtering_title"] + summaryOff = intl["chapter_score_filtering_off"] + summaryOn = intl["chapter_score_filtering_on"] + setDefaultValue(CHAPTER_SCORE_FILTERING_DEFAULT) + + setOnPreferenceChangeListener { _, newValue -> + preferences.edit() + .putBoolean(CHAPTER_SCORE_FILTERING_PREF, newValue as Boolean) + .commit() + } + }.also(screen::addPreference) } private val SharedPreferences.ignoredGroups: Set @@ -224,6 +238,9 @@ abstract class Comick( private val SharedPreferences.scorePosition: String get() = getString(SCORE_POSITION_PREF, SCORE_POSITION_DEFAULT) ?: SCORE_POSITION_DEFAULT + private val SharedPreferences.chapterScoreFiltering: Boolean + get() = getBoolean(CHAPTER_SCORE_FILTERING_PREF, CHAPTER_SCORE_FILTERING_DEFAULT) + override fun headersBuilder() = Headers.Builder().apply { add("Referer", "$baseUrl/") add("User-Agent", "Tachiyomi ${System.getProperty("http.agent")}") @@ -546,9 +563,19 @@ abstract class Comick( publishedChapter && noGroupBlock } + .filterOnScore(preferences.chapterScoreFiltering) .map { it.toSChapter(mangaUrl) } } + private fun List.filterOnScore(shouldFilter: Boolean): Collection { + if (shouldFilter) { + return groupBy { it.chap } + .map { (_, chapters) -> chapters.maxBy { it.score } } + } else { + return this + } + } + private val publishedDateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ENGLISH).apply { timeZone = TimeZone.getTimeZone("UTC") @@ -626,6 +653,8 @@ abstract class Comick( const val SCORE_POSITION_DEFAULT = "top" private const val LOCAL_TITLE_PREF = "LocalTitle" private const val LOCAL_TITLE_DEFAULT = false + private const val CHAPTER_SCORE_FILTERING_PREF = "ScoreAutoFiltering" + private const val CHAPTER_SCORE_FILTERING_DEFAULT = false private const val LIMIT = 20 private const val CHAPTERS_LIMIT = 99999 } diff --git a/src/all/comickfun/src/eu/kanade/tachiyomi/extension/all/comickfun/Dto.kt b/src/all/comickfun/src/eu/kanade/tachiyomi/extension/all/comickfun/Dto.kt index 8bed4379d..cfad0da0a 100644 --- a/src/all/comickfun/src/eu/kanade/tachiyomi/extension/all/comickfun/Dto.kt +++ b/src/all/comickfun/src/eu/kanade/tachiyomi/extension/all/comickfun/Dto.kt @@ -199,10 +199,14 @@ class Chapter( private val title: String = "", @SerialName("created_at") private val createdAt: String = "", @SerialName("publish_at") val publishedAt: String = "", - private val chap: String = "", + val chap: String = "", private val vol: String = "", @SerialName("group_name") val groups: List = emptyList(), + @SerialName("up_count") private val upCount: Int, + @SerialName("down_count") private val downCount: Int, ) { + val score get() = upCount - downCount + fun toSChapter(mangaUrl: String) = SChapter.create().apply { url = "$mangaUrl/$hid-chapter-$chap-$lang" name = beautifyChapterName(vol, chap, title)