Add filters to Hitomi Extension (#3312)

* hitomi filters

* move filters to seperate file

* rename category filter to area filter, tag->area in parse
This commit is contained in:
GoonGooner 2024-05-31 21:22:07 -07:00 committed by GitHub
parent b698c31d53
commit c4ad275f91
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 106 additions and 17 deletions

View File

@ -1,7 +1,7 @@
ext {
extName = 'Hitomi'
extClass = '.HitomiFactory'
extVersionCode = 26
extVersionCode = 27
isNsfw = true
}

View File

@ -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<String?, String>
typealias ParsedFilter = Pair<String, OrderType>
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<OrderFilter>) :
Filter.Select<String>(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"),
)

View File

@ -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<Int>
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> = Observable.fromCallable {
val parsedFilter = parseFilters(filters)
runBlocking {
if (page == 1) {
searchResponse = hitomiSearch(
query.trim(),
filters.filterIsInstance<SortFilter>().firstOrNull()?.state == 1,
"$query${parsedFilter.first}".trim(),
parsedFilter.second,
nozomiLang,
).toList()
}
@ -93,11 +94,7 @@ class Hitomi(
}
}
private class SortFilter : Filter.Select<String>("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<Int> =
coroutineScope {
@ -126,9 +123,6 @@ class Hitomi(
.replace(Regex("""^\?"""), "")
.lowercase()
.split(Regex("\\s+"))
.map {
it.replace('_', ' ')
}
val positiveTerms = LinkedList<String>()
val negativeTerms = LinkedList<String>()
@ -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<Int> {
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)
}