From c4ad275f91de891f5baded44bdb00bdda57bf3e3 Mon Sep 17 00:00:00 2001 From: GoonGooner <171292526+GoonGooner@users.noreply.github.com> Date: Fri, 31 May 2024 21:22:07 -0700 Subject: [PATCH] Add filters to Hitomi Extension (#3312) * hitomi filters * move filters to seperate file * rename category filter to area filter, tag->area in parse --- src/all/hitomi/build.gradle | 2 +- .../tachiyomi/extension/all/hitomi/Filters.kt | 81 +++++++++++++++++++ .../tachiyomi/extension/all/hitomi/Hitomi.kt | 40 +++++---- 3 files changed, 106 insertions(+), 17 deletions(-) create mode 100644 src/all/hitomi/src/eu/kanade/tachiyomi/extension/all/hitomi/Filters.kt diff --git a/src/all/hitomi/build.gradle b/src/all/hitomi/build.gradle index c23da94e2..a91f5a1c9 100644 --- a/src/all/hitomi/build.gradle +++ b/src/all/hitomi/build.gradle @@ -1,7 +1,7 @@ ext { extName = 'Hitomi' extClass = '.HitomiFactory' - extVersionCode = 26 + extVersionCode = 27 isNsfw = true } diff --git a/src/all/hitomi/src/eu/kanade/tachiyomi/extension/all/hitomi/Filters.kt b/src/all/hitomi/src/eu/kanade/tachiyomi/extension/all/hitomi/Filters.kt new file mode 100644 index 000000000..c9bbb8f8a --- /dev/null +++ b/src/all/hitomi/src/eu/kanade/tachiyomi/extension/all/hitomi/Filters.kt @@ -0,0 +1,81 @@ +package eu.kanade.tachiyomi.extension.all.hitomi + +import eu.kanade.tachiyomi.source.model.Filter +import eu.kanade.tachiyomi.source.model.FilterList + +typealias OrderType = Pair +typealias ParsedFilter = Pair + +private fun parseFilter(query: StringBuilder, area: String, filterState: String) { + filterState + .trim() + .split(',') + .filter { it.isNotBlank() } + .forEach { + val trimmed = it.trim() + val negativePrefix = if (trimmed.startsWith("-")) "-" else "" + query.append(" $negativePrefix$area:${trimmed.removePrefix("-").replace(" ", "_")}") + } +} + +fun parseFilters(filters: FilterList): ParsedFilter { + val query = StringBuilder() + var order: OrderType = Pair("date", "added") + filters.forEach { filter -> + when (filter) { + is SortFilter -> { + order = filter.getOrder + } + is AreaFilter -> { + parseFilter(query, filter.getAreaName, filter.state) + } + else -> { /* Do Nothing */ } + } + } + return Pair(query.toString(), order) +} + +private class OrderFilter(val name: String, val order: OrderType) { + val getFilterName: String + get() = name + val getOrder: OrderType + get() = order +} + +private class SortFilter : UriPartFilter( + "Sort By", + arrayOf( + OrderFilter("Date Added", Pair(null, "index")), + OrderFilter("Date Published", Pair("date", "published")), + OrderFilter("Popular: Today", Pair("popular", "today")), + OrderFilter("Popular: Week", Pair("popular", "week")), + OrderFilter("Popular: Month", Pair("popular", "month")), + OrderFilter("Popular: Year", Pair("popular", "year")), + ), +) + +private open class UriPartFilter(displayName: String, val vals: Array) : + Filter.Select(displayName, vals.map { it.getFilterName }.toTypedArray()) { + val getOrder: OrderType + get() = vals[state].getOrder +} + +private class AreaFilter(displayName: String, val areaName: String) : + Filter.Text(displayName) { + val getAreaName: String + get() = areaName +} + +fun getFilterListInternal(): FilterList = FilterList( + SortFilter(), + Filter.Header("Separate tags with commas (,)"), + Filter.Header("Prepend with dash (-) to exclude"), + AreaFilter("Artist(s)", "artist"), + AreaFilter("Character(s)", "character"), + AreaFilter("Group(s)", "group"), + AreaFilter("Series", "series"), + AreaFilter("Female Tag(s)", "female"), + AreaFilter("Male Tag(s)", "male"), + Filter.Header("Don't put Female/Male tags here, they won't work!"), + AreaFilter("Tag(s)", "tag"), +) diff --git a/src/all/hitomi/src/eu/kanade/tachiyomi/extension/all/hitomi/Hitomi.kt b/src/all/hitomi/src/eu/kanade/tachiyomi/extension/all/hitomi/Hitomi.kt index 26f2d0def..b41ecde4b 100644 --- a/src/all/hitomi/src/eu/kanade/tachiyomi/extension/all/hitomi/Hitomi.kt +++ b/src/all/hitomi/src/eu/kanade/tachiyomi/extension/all/hitomi/Hitomi.kt @@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.extension.all.hitomi import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.await -import eu.kanade.tachiyomi.source.model.Filter import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.Page @@ -76,11 +75,13 @@ class Hitomi( private lateinit var searchResponse: List override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable = Observable.fromCallable { + val parsedFilter = parseFilters(filters) + runBlocking { if (page == 1) { searchResponse = hitomiSearch( - query.trim(), - filters.filterIsInstance().firstOrNull()?.state == 1, + "$query${parsedFilter.first}".trim(), + parsedFilter.second, nozomiLang, ).toList() } @@ -93,11 +94,7 @@ class Hitomi( } } - private class SortFilter : Filter.Select("Sort By", arrayOf("Updated", "Popularity")) - - override fun getFilterList(): FilterList { - return FilterList(SortFilter()) - } + override fun getFilterList(): FilterList = getFilterListInternal() private fun Int.nextPageRange(): LongRange { val byteOffset = ((this - 1) * 25) * 4L @@ -117,7 +114,7 @@ class Hitomi( private suspend fun hitomiSearch( query: String, - sortByPopularity: Boolean = false, + order: OrderType, language: String = "all", ): Set = coroutineScope { @@ -126,9 +123,6 @@ class Hitomi( .replace(Regex("""^\?"""), "") .lowercase() .split(Regex("\\s+")) - .map { - it.replace('_', ' ') - } val positiveTerms = LinkedList() val negativeTerms = LinkedList() @@ -144,7 +138,7 @@ class Hitomi( val positiveResults = positiveTerms.map { async { runCatching { - getGalleryIDsForQuery(it, language) + getGalleryIDsForQuery(it, language, order) }.getOrDefault(emptySet()) } } @@ -152,14 +146,13 @@ class Hitomi( val negativeResults = negativeTerms.map { async { runCatching { - getGalleryIDsForQuery(it, language) + getGalleryIDsForQuery(it, language, order) }.getOrDefault(emptySet()) } } val results = when { - sortByPopularity -> getGalleryIDsFromNozomi(null, "popular", language) - positiveTerms.isEmpty() -> getGalleryIDsFromNozomi(null, "index", language) + positiveTerms.isEmpty() -> getGalleryIDsFromNozomi(order.first, order.second, language) else -> emptySet() }.toMutableSet() @@ -191,6 +184,7 @@ class Hitomi( private suspend fun getGalleryIDsForQuery( query: String, language: String = "all", + order: OrderType, ): Set { query.replace("_", " ").let { if (it.indexOf(':') > -1) { @@ -213,6 +207,20 @@ class Hitomi( } } + if (area != null) { + if (order.first != null) { + area = "$area/${order.first}" + if (tag.isBlank()) { + tag = order.second + } else { + area = "$area/${order.second}" + } + } + } else { + area = order.first + tag = order.second + } + return getGalleryIDsFromNozomi(area, tag, lang) }