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:
parent
e277149bc5
commit
93d6a9b328
|
@ -1,7 +1,7 @@
|
||||||
ext {
|
ext {
|
||||||
extName = 'Hitomi'
|
extName = 'Hitomi'
|
||||||
extClass = '.HitomiFactory'
|
extClass = '.HitomiFactory'
|
||||||
extVersionCode = 26
|
extVersionCode = 27
|
||||||
isNsfw = true
|
isNsfw = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"),
|
||||||
|
)
|
|
@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.extension.all.hitomi
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.await
|
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.FilterList
|
||||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||||
import eu.kanade.tachiyomi.source.model.Page
|
import eu.kanade.tachiyomi.source.model.Page
|
||||||
|
@ -76,11 +75,13 @@ class Hitomi(
|
||||||
private lateinit var searchResponse: List<Int>
|
private lateinit var searchResponse: List<Int>
|
||||||
|
|
||||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> = Observable.fromCallable {
|
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> = Observable.fromCallable {
|
||||||
|
val parsedFilter = parseFilters(filters)
|
||||||
|
|
||||||
runBlocking {
|
runBlocking {
|
||||||
if (page == 1) {
|
if (page == 1) {
|
||||||
searchResponse = hitomiSearch(
|
searchResponse = hitomiSearch(
|
||||||
query.trim(),
|
"$query${parsedFilter.first}".trim(),
|
||||||
filters.filterIsInstance<SortFilter>().firstOrNull()?.state == 1,
|
parsedFilter.second,
|
||||||
nozomiLang,
|
nozomiLang,
|
||||||
).toList()
|
).toList()
|
||||||
}
|
}
|
||||||
|
@ -93,11 +94,7 @@ class Hitomi(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SortFilter : Filter.Select<String>("Sort By", arrayOf("Updated", "Popularity"))
|
override fun getFilterList(): FilterList = getFilterListInternal()
|
||||||
|
|
||||||
override fun getFilterList(): FilterList {
|
|
||||||
return FilterList(SortFilter())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Int.nextPageRange(): LongRange {
|
private fun Int.nextPageRange(): LongRange {
|
||||||
val byteOffset = ((this - 1) * 25) * 4L
|
val byteOffset = ((this - 1) * 25) * 4L
|
||||||
|
@ -117,7 +114,7 @@ class Hitomi(
|
||||||
|
|
||||||
private suspend fun hitomiSearch(
|
private suspend fun hitomiSearch(
|
||||||
query: String,
|
query: String,
|
||||||
sortByPopularity: Boolean = false,
|
order: OrderType,
|
||||||
language: String = "all",
|
language: String = "all",
|
||||||
): Set<Int> =
|
): Set<Int> =
|
||||||
coroutineScope {
|
coroutineScope {
|
||||||
|
@ -126,9 +123,6 @@ class Hitomi(
|
||||||
.replace(Regex("""^\?"""), "")
|
.replace(Regex("""^\?"""), "")
|
||||||
.lowercase()
|
.lowercase()
|
||||||
.split(Regex("\\s+"))
|
.split(Regex("\\s+"))
|
||||||
.map {
|
|
||||||
it.replace('_', ' ')
|
|
||||||
}
|
|
||||||
|
|
||||||
val positiveTerms = LinkedList<String>()
|
val positiveTerms = LinkedList<String>()
|
||||||
val negativeTerms = LinkedList<String>()
|
val negativeTerms = LinkedList<String>()
|
||||||
|
@ -144,7 +138,7 @@ class Hitomi(
|
||||||
val positiveResults = positiveTerms.map {
|
val positiveResults = positiveTerms.map {
|
||||||
async {
|
async {
|
||||||
runCatching {
|
runCatching {
|
||||||
getGalleryIDsForQuery(it, language)
|
getGalleryIDsForQuery(it, language, order)
|
||||||
}.getOrDefault(emptySet())
|
}.getOrDefault(emptySet())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,14 +146,13 @@ class Hitomi(
|
||||||
val negativeResults = negativeTerms.map {
|
val negativeResults = negativeTerms.map {
|
||||||
async {
|
async {
|
||||||
runCatching {
|
runCatching {
|
||||||
getGalleryIDsForQuery(it, language)
|
getGalleryIDsForQuery(it, language, order)
|
||||||
}.getOrDefault(emptySet())
|
}.getOrDefault(emptySet())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val results = when {
|
val results = when {
|
||||||
sortByPopularity -> getGalleryIDsFromNozomi(null, "popular", language)
|
positiveTerms.isEmpty() -> getGalleryIDsFromNozomi(order.first, order.second, language)
|
||||||
positiveTerms.isEmpty() -> getGalleryIDsFromNozomi(null, "index", language)
|
|
||||||
else -> emptySet()
|
else -> emptySet()
|
||||||
}.toMutableSet()
|
}.toMutableSet()
|
||||||
|
|
||||||
|
@ -191,6 +184,7 @@ class Hitomi(
|
||||||
private suspend fun getGalleryIDsForQuery(
|
private suspend fun getGalleryIDsForQuery(
|
||||||
query: String,
|
query: String,
|
||||||
language: String = "all",
|
language: String = "all",
|
||||||
|
order: OrderType,
|
||||||
): Set<Int> {
|
): Set<Int> {
|
||||||
query.replace("_", " ").let {
|
query.replace("_", " ").let {
|
||||||
if (it.indexOf(':') > -1) {
|
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)
|
return getGalleryIDsFromNozomi(area, tag, lang)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue