Advanced filtering support

feature/filter-ex
Koitharu 2 years ago
parent 98f5d115b3
commit 43a8caa687
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -23,7 +23,27 @@ abstract class MangaParser @InternalParsersApi constructor(
*
* For better performance use [EnumSet] for more than one item.
*/
abstract val sortOrders: Set<SortOrder>
abstract val availableSortOrders: Set<SortOrder>
/**
* Supported [MangaState] variants for filtering. May be empty.
*
* For better performance use [EnumSet] for more than one item.
*/
open val availableStates: Set<MangaState>
get() = emptySet()
/**
* Whether parser supports filtering by more than one tag
*/
open val isMultipleTagsSupported: Boolean = true
@Deprecated(
message = "Use availableSortOrders instead",
replaceWith = ReplaceWith("availableSortOrders"),
)
val sortOrders: Set<SortOrder>
get() = availableSortOrders
val config by lazy { context.getConfig(source) }
@ -49,7 +69,7 @@ abstract class MangaParser @InternalParsersApi constructor(
*/
protected open val defaultSortOrder: SortOrder
get() {
val supported = sortOrders
val supported = availableSortOrders
return SortOrder.entries.first { it in supported }
}
@ -62,11 +82,15 @@ abstract class MangaParser @InternalParsersApi constructor(
* @param offset starting from 0 and used for pagination.
* Note than passed value may not be divisible by internal page size, so you should adjust it manually.
* @param query search query, may be null or empty if no search needed
* @param tags genres for filtering, values from [getTags] and [Manga.tags]. May be null or empty
* @param sortOrder one of [sortOrders] or null for default value
* @param tags genres for filtering, values from [getAvailableTags] and [Manga.tags]. May be null or empty
* @param sortOrder one of [availableSortOrders] or null for default value
*/
@JvmSynthetic
@InternalParsersApi
@Deprecated(
"Use getList with filter instead",
replaceWith = ReplaceWith("getList(offset, filter)"),
)
abstract suspend fun getList(
offset: Int,
query: String?,
@ -80,8 +104,15 @@ abstract class MangaParser @InternalParsersApi constructor(
* @param offset starting from 0 and used for pagination.
* @param query search query
*/
@Deprecated(
"Use getList with filter instead",
ReplaceWith(
"getList(offset, MangaListFilter.Search(query))",
"org.koitharu.kotatsu.parsers.model.MangaListFilter",
),
)
open suspend fun getList(offset: Int, query: String): List<Manga> {
return getList(offset, query, null, defaultSortOrder)
return getList(offset, MangaListFilter.Search(query))
}
/**
@ -89,11 +120,29 @@ abstract class MangaParser @InternalParsersApi constructor(
*
* @param offset starting from 0 and used for pagination.
* Note than passed value may not be divisible by internal page size, so you should adjust it manually.
* @param tags genres for filtering, values from [getTags] and [Manga.tags]. May be null or empty
* @param sortOrder one of [sortOrders] or null for default value
* @param tags genres for filtering, values from [getAvailableTags] and [Manga.tags]. May be null or empty
* @param sortOrder one of [availableSortOrders] or null for default value
*/
@Deprecated(
"Use getList with filter instead",
ReplaceWith(
"getList(offset, MangaListFilter.Advanced(sortOrder, tags, null, emptySet()))",
"org.koitharu.kotatsu.parsers.model.MangaListFilter",
),
)
open suspend fun getList(offset: Int, tags: Set<MangaTag>?, sortOrder: SortOrder?): List<Manga> {
return getList(offset, null, tags, sortOrder ?: defaultSortOrder)
return getList(
offset,
MangaListFilter.Advanced(sortOrder ?: defaultSortOrder, tags.orEmpty(), null, emptySet()),
)
}
open suspend fun getList(offset: Int, filter: MangaListFilter?): List<Manga> {
return when (filter) {
is MangaListFilter.Advanced -> getList(offset, null, filter.tags, filter.sortOrder)
is MangaListFilter.Search -> getList(offset, filter.query, null, defaultSortOrder)
null -> getList(offset, null, null, defaultSortOrder)
}
}
/**
@ -117,7 +166,18 @@ abstract class MangaParser @InternalParsersApi constructor(
/**
* Fetch available tags (genres) for source
*/
abstract suspend fun getTags(): Set<MangaTag>
abstract suspend fun getAvailableTags(): Set<MangaTag>
/**
* Fetch available locales for multilingual sources
*/
open suspend fun getAvailableLocales(): Set<Locale> = emptySet()
@Deprecated(
message = "Use getAvailableTags instead",
replaceWith = ReplaceWith("getAvailableTags()"),
)
suspend fun getTags(): Set<MangaTag> = getAvailableTags()
/**
* Parse favicons from the main page of the source`s website

@ -0,0 +1,29 @@
package org.koitharu.kotatsu.parsers.model
import java.util.*
sealed interface MangaListFilter {
fun isEmpty(): Boolean
val sortOrder: SortOrder?
data class Search(
@JvmField val query: String,
) : MangaListFilter {
override val sortOrder: SortOrder? = null
override fun isEmpty() = query.isBlank()
}
data class Advanced(
override val sortOrder: SortOrder,
@JvmField val tags: Set<MangaTag>,
@JvmField val locale: Locale?,
@JvmField val states: Set<MangaState>,
) : MangaListFilter {
override fun isEmpty(): Boolean = tags.isEmpty() && locale == null && states.isEmpty()
}
}

@ -1,5 +1,5 @@
package org.koitharu.kotatsu.parsers.model
enum class MangaState {
ONGOING, FINISHED, ABANDONED
ONGOING, FINISHED, ABANDONED, PAUSED
}

@ -26,7 +26,7 @@ internal class BatoToParser(context: MangaLoaderContext) : PagedMangaParser(
searchPageSize = 20,
) {
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.NEWEST,
SortOrder.UPDATED,
SortOrder.POPULARITY,
@ -159,7 +159,7 @@ internal class BatoToParser(context: MangaLoaderContext) : PagedMangaParser(
throw ParseException("Cannot find images list", fullUrl)
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val scripts = webClient.httpGet(
"https://${domain}/browse",
).parseHtml().selectOrThrow("script")

@ -25,7 +25,7 @@ internal class ComickFunParser(context: MangaLoaderContext) : MangaParser(contex
override val configKeyDomain = ConfigKey.Domain("comick.app")
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.POPULARITY,
SortOrder.UPDATED,
SortOrder.RATING,
@ -137,7 +137,7 @@ internal class ComickFunParser(context: MangaLoaderContext) : MangaParser(contex
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val sparseArray = cachedTags ?: loadTags()
val set = ArraySet<MangaTag>(sparseArray.size())
for (i in 0 until sparseArray.size()) {

@ -23,7 +23,7 @@ internal class ExHentaiParser(
context: MangaLoaderContext,
) : PagedMangaParser(context, MangaSource.EXHENTAI, pageSize = 25), MangaParserAuthProvider {
override val sortOrders: Set<SortOrder> = Collections.singleton(
override val availableSortOrders: Set<SortOrder> = Collections.singleton(
SortOrder.NEWEST,
)
@ -213,7 +213,7 @@ internal class ExHentaiParser(
return doc.body().requireElementById("img").attrAsAbsoluteUrl("src")
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://${domain}").parseHtml()
val root = doc.body().requireElementById("searchbox").selectFirstOrThrow("table")
return root.select("div.cs").mapNotNullToSet { div ->

@ -17,11 +17,13 @@ import java.util.*
internal class ImHentai(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.IMHENTAI, pageSize = 20) {
override val sortOrders: Set<SortOrder> =
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.RATING)
override val configKeyDomain = ConfigKey.Domain("imhentai.xxx")
override val isMultipleTagsSupported = false
override suspend fun getListPage(
page: Int,
query: String?,
@ -83,7 +85,7 @@ internal class ImHentai(context: MangaLoaderContext) :
//Tags are deliberately reduced because there are too many and this slows down the application.
//only the most popular ones are taken.
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
return coroutineScope {
(1..3).map { page ->
async { getTags(page) }

@ -24,6 +24,8 @@ internal abstract class LineWebtoonsParser(
source: MangaSource,
) : MangaParser(context, source) {
override val isMultipleTagsSupported = false
private val signer by lazy {
WebtoonsUrlSigner("gUtPzJFZch4ZyAGviiyH94P99lQ3pFdRTwpJWDlSGFfwgpr6ses5ALOxWHOIT7R1")
}
@ -39,7 +41,7 @@ internal abstract class LineWebtoonsParser(
private val apiDomain = "global.apis.naver.com"
private val staticDomain = "webtoon-phinf.pstatic.net"
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.POPULARITY,
// doesn't actually sort by rating, but by likes
// this should be fine though
@ -235,7 +237,7 @@ internal abstract class LineWebtoonsParser(
)
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
return makeRequest("/lineWebtoon/webtoon/challengeGenreList.json")
.getJSONObject("genreList")
.getJSONArray("challengeGenres")

@ -30,7 +30,7 @@ internal class MangaDexParser(context: MangaLoaderContext) : MangaParser(context
override val configKeyDomain = ConfigKey.Domain("mangadex.org")
override val sortOrders: EnumSet<SortOrder> = EnumSet.of(
override val availableSortOrders: EnumSet<SortOrder> = EnumSet.of(
SortOrder.UPDATED,
SortOrder.ALPHABETICAL,
SortOrder.NEWEST,
@ -159,7 +159,7 @@ internal class MangaDexParser(context: MangaLoaderContext) : MangaParser(context
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val tags = webClient.httpGet("https://api.${domain}/manga/tag").parseJson()
.getJSONArray("data")
return tags.mapJSONToSet { jo ->

@ -31,7 +31,7 @@ internal abstract class NineMangaParser(
.add("Accept-Language", "en-US;q=0.7,en;q=0.3")
.build()
override val sortOrders: Set<SortOrder> = Collections.singleton(
override val availableSortOrders: Set<SortOrder> = Collections.singleton(
SortOrder.POPULARITY,
)
@ -158,7 +158,7 @@ internal abstract class NineMangaParser(
private var tagCache: ArrayMap<String, MangaTag>? = null
private val mutex = Mutex()
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
return getOrCreateTagMap().values.toSet()
}

@ -22,7 +22,9 @@ internal abstract class AnimeBootstrapParser(
override val configKeyDomain = ConfigKey.Domain(domain)
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val isMultipleTagsSupported = false
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.UPDATED,
SortOrder.POPULARITY,
SortOrder.ALPHABETICAL,
@ -93,7 +95,7 @@ internal abstract class AnimeBootstrapParser(
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain$listUrl").parseHtml()
return doc.select("div.product__page__filter div:contains(Genre:) option ").mapNotNullToSet { option ->
val key = option.attr("value") ?: return@mapNotNullToSet null

@ -20,6 +20,8 @@ internal class PapScan(context: MangaLoaderContext) :
override val sourceLocale: Locale = Locale.ENGLISH
override val isMultipleTagsSupported = false
override val listUrl = "/liste-manga"
override val selectState = "div.anime__details__widget li:contains(En cours)"
@ -27,7 +29,7 @@ internal class PapScan(context: MangaLoaderContext) :
override val selectChapter = "ul.chapters li"
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.POPULARITY,
SortOrder.ALPHABETICAL,
)
@ -85,7 +87,7 @@ internal class PapScan(context: MangaLoaderContext) :
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain$listUrl").parseHtml()
return doc.select("a.category ").mapNotNullToSet { a ->
val key = a.attr("href").substringAfterLast('=')

@ -18,7 +18,7 @@ import java.util.*
@MangaSourceParser("FLIXSCANS", "FlixScans", "ar")
internal class FlixScans(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.FLIXSCANS, 18) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val configKeyDomain = ConfigKey.Domain("flixscans.com")
override suspend fun getListPage(
@ -70,7 +70,7 @@ internal class FlixScans(context: MangaLoaderContext) : PagedMangaParser(context
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/search/advance").parseHtml()
val json = JSONArray(doc.requireElementById("__NUXT_DATA__").data())
val tagsList = json.getJSONArray(3).toString().replace("[", "").replace("]", "").split(",")

@ -13,8 +13,9 @@ import java.util.*
@MangaSourceParser("MANGASTORM", "MangaStorm", "ar")
internal class MangaStorm(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.MANGASTORM, 30) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.POPULARITY)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.POPULARITY)
override val configKeyDomain = ConfigKey.Domain("mangastorm.org")
override val isMultipleTagsSupported = false
override val headers: Headers = Headers.Builder()
.add("User-Agent", UserAgents.CHROME_DESKTOP)
@ -69,7 +70,7 @@ internal class MangaStorm(context: MangaLoaderContext) : PagedMangaParser(contex
}
}
override suspend fun getTags(): Set<MangaTag> = emptySet()
override suspend fun getAvailableTags(): Set<MangaTag> = emptySet()
override suspend fun getDetails(manga: Manga): Manga {
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()

@ -16,8 +16,9 @@ import java.util.*
@MangaSourceParser("TEAMXNOVEL", "TeamXNovel", "ar")
internal class TeamXNovel(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.TEAMXNOVEL, 10) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY)
override val configKeyDomain = ConfigKey.Domain("team11x11.com")
override val isMultipleTagsSupported = false
override suspend fun getListPage(
page: Int,
@ -82,7 +83,7 @@ internal class TeamXNovel(context: MangaLoaderContext) : PagedMangaParser(contex
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/series").parseHtml()
return doc.requireElementById("select_genre").select("option").mapNotNullToSet {
MangaTag(

@ -23,7 +23,7 @@ internal class AnibelParser(context: MangaLoaderContext) : MangaParser(context,
override val configKeyDomain = ConfigKey.Domain("anibel.net")
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.NEWEST,
)
@ -176,7 +176,7 @@ internal class AnibelParser(context: MangaLoaderContext) : MangaParser(context,
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val json = apiCall(
"""
getFilters(mediaType: manga) {

@ -13,10 +13,12 @@ import java.util.*
internal class BeeToon(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.BEETOON, pageSize = 30) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY)
override val configKeyDomain = ConfigKey.Domain("ww7.beetoon.net")
override val isMultipleTagsSupported = false
override suspend fun getListPage(
page: Int,
query: String?,
@ -80,7 +82,7 @@ internal class BeeToon(context: MangaLoaderContext) :
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/").parseHtml()
return doc.requireElementById("menu-item-3").select("ul.sub-menu li a").mapNotNullToSet {
MangaTag(

@ -12,7 +12,7 @@ import java.util.*
@MangaSourceParser("CLONEMANGA", "CloneManga", "en")
internal class CloneMangaParser(context: MangaLoaderContext) : MangaParser(context, MangaSource.CLONEMANGA) {
override val sortOrders: Set<SortOrder> = Collections.singleton(
override val availableSortOrders: Set<SortOrder> = Collections.singleton(
SortOrder.POPULARITY,
)
@ -89,5 +89,5 @@ internal class CloneMangaParser(context: MangaLoaderContext) : MangaParser(conte
)
}
override suspend fun getTags(): Set<MangaTag> = emptySet()
override suspend fun getAvailableTags(): Set<MangaTag> = emptySet()
}

@ -14,10 +14,13 @@ import java.util.*
@MangaSourceParser("COMICEXTRA", "ComicExtra", "en")
internal class ComicExtra(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.COMICEXTRA, 25) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.POPULARITY, SortOrder.UPDATED, SortOrder.NEWEST)
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.POPULARITY, SortOrder.UPDATED, SortOrder.NEWEST)
override val configKeyDomain = ConfigKey.Domain("comicextra.me")
override val isMultipleTagsSupported = false
override val headers: Headers = Headers.Builder()
.add("User-Agent", UserAgents.CHROME_DESKTOP)
.build()
@ -80,7 +83,7 @@ internal class ComicExtra(context: MangaLoaderContext) : PagedMangaParser(contex
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/popular-comic").parseHtml()
return doc.select("li.tag-item a").mapNotNullToSet { a ->
MangaTag(

@ -15,7 +15,7 @@ import java.util.*
@MangaSourceParser("DYNASTYSCANS", "DynastyScans", "en")
internal class DynastyScans(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.DYNASTYSCANS, 117) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL)
override val configKeyDomain = ConfigKey.Domain("dynasty-scans.com")
override val headers: Headers = Headers.Builder()
@ -100,7 +100,7 @@ internal class DynastyScans(context: MangaLoaderContext) : PagedMangaParser(cont
}
}
override suspend fun getTags(): Set<MangaTag> = emptySet()
override suspend fun getAvailableTags(): Set<MangaTag> = emptySet()
override suspend fun getDetails(manga: Manga): Manga {
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()

@ -15,11 +15,13 @@ import java.util.*
internal class Fakku(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.FAKKU, pageSize = 25) {
override val sortOrders: Set<SortOrder> =
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.ALPHABETICAL, SortOrder.NEWEST, SortOrder.UPDATED)
override val configKeyDomain = ConfigKey.Domain("fakku.cc")
override val isMultipleTagsSupported = false
override suspend fun getListPage(
page: Int,
query: String?,
@ -77,7 +79,7 @@ internal class Fakku(context: MangaLoaderContext) :
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val root = webClient.httpGet("https://$domain/tags").parseHtml()
return root.select("div.entries .entry a").mapToSet {
MangaTag(

@ -20,9 +20,10 @@ import java.util.*
@MangaSourceParser("KSKMOE", "Ksk.moe", "en", ContentType.HENTAI)
internal class KskMoe(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.KSKMOE, 35) {
override val sortOrders: Set<SortOrder> =
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL)
override val configKeyDomain = ConfigKey.Domain("ksk.moe")
override val isMultipleTagsSupported = false
override suspend fun getListPage(
page: Int,
@ -91,7 +92,7 @@ internal class KskMoe(context: MangaLoaderContext) : PagedMangaParser(context, M
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
return coroutineScope {
(1..2).map { page ->
async { getTags(page) }

@ -14,10 +14,13 @@ import java.util.*
@MangaSourceParser("MANGAGEKO", "MangaGeko", "en")
internal class MangaGeko(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.MANGAGEKO, 30) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.POPULARITY, SortOrder.UPDATED, SortOrder.NEWEST)
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.POPULARITY, SortOrder.UPDATED, SortOrder.NEWEST)
override val configKeyDomain = ConfigKey.Domain("www.mangageko.com")
override val isMultipleTagsSupported = false
override val headers: Headers = Headers.Builder()
.add("User-Agent", UserAgents.CHROME_DESKTOP)
.build()
@ -77,7 +80,7 @@ internal class MangaGeko(context: MangaLoaderContext) : PagedMangaParser(context
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/browse-comics/").parseHtml()
return doc.select("label.checkbox-inline").mapNotNullToSet { label ->
MangaTag(

@ -15,7 +15,7 @@ internal class MangaTownParser(context: MangaLoaderContext) : MangaParser(contex
override val configKeyDomain = ConfigKey.Domain("www.mangatown.com")
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.ALPHABETICAL,
SortOrder.RATING,
SortOrder.POPULARITY,
@ -157,7 +157,7 @@ internal class MangaTownParser(context: MangaLoaderContext) : MangaParser(contex
return doc.requireElementById("image").attrAsAbsoluteUrl("src")
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("/directory/".toAbsoluteUrl(domain)).parseHtml()
val root = doc.body().selectFirst("aside.right")
?.getElementsContainingOwnText("Genres")

@ -18,7 +18,7 @@ import java.util.*
internal class Mangaowl(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.MANGAOWL, pageSize = 24) {
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.POPULARITY,
SortOrder.NEWEST,
SortOrder.UPDATED,
@ -94,7 +94,7 @@ internal class Mangaowl(context: MangaLoaderContext) :
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/8-genres").parseHtml()
return doc.select("div.genres-container span.genre-item a").mapNotNullToSet { a ->
val key = a.attr("href").substringAfterLast("/")

@ -15,7 +15,7 @@ class Manhwa18Parser(context: MangaLoaderContext) :
override val configKeyDomain: ConfigKey.Domain = ConfigKey.Domain("manhwa18.net")
override val sortOrders: Set<SortOrder>
override val availableSortOrders: Set<SortOrder>
get() = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.ALPHABETICAL, SortOrder.NEWEST)
private val tagsMap = SuspendLazy(::parseTags)
@ -169,7 +169,7 @@ class Manhwa18Parser(context: MangaLoaderContext) :
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
return tagsMap.get().values.toSet()
}

@ -16,7 +16,9 @@ class ManhwasMen(context: MangaLoaderContext) :
override val configKeyDomain: ConfigKey.Domain = ConfigKey.Domain("manhwas.men")
override val sortOrders: Set<SortOrder>
override val isMultipleTagsSupported = false
override val availableSortOrders: Set<SortOrder>
get() = EnumSet.of(SortOrder.POPULARITY)
override suspend fun getListPage(
@ -64,7 +66,7 @@ class ManhwasMen(context: MangaLoaderContext) :
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val tags = webClient.httpGet("https://$domain/manga-list").parseHtml()
.selectLastOrThrow(".filter-bx .form-group select.custom-select").select("option").drop(1)
return tags.mapNotNullToSet { option ->

@ -12,7 +12,7 @@ import java.util.*
@MangaSourceParser("PO2SCANS", "Po2Scans", "en")
internal class Po2Scans(context: MangaLoaderContext) : MangaParser(context, MangaSource.PO2SCANS) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL)
override val configKeyDomain = ConfigKey.Domain("po2scans.com")
override suspend fun getList(offset: Int, query: String?, tags: Set<MangaTag>?, sortOrder: SortOrder): List<Manga> {
@ -46,7 +46,7 @@ internal class Po2Scans(context: MangaLoaderContext) : MangaParser(context, Mang
}
}
override suspend fun getTags(): Set<MangaTag> = emptySet()
override suspend fun getAvailableTags(): Set<MangaTag> = emptySet()
override suspend fun getDetails(manga: Manga): Manga {
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()

@ -17,11 +17,13 @@ import java.util.*
internal class Pururin(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.PURURIN, pageSize = 20) {
override val sortOrders: Set<SortOrder> =
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.RATING, SortOrder.ALPHABETICAL)
override val configKeyDomain = ConfigKey.Domain("pururin.to")
override val isMultipleTagsSupported = false
override suspend fun getListPage(
page: Int,
query: String?,
@ -76,7 +78,7 @@ internal class Pururin(context: MangaLoaderContext) :
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
return coroutineScope {
(1..4).map { page ->
async { getTags(page) }

@ -16,7 +16,7 @@ import java.util.*
internal class TempleScanEsp(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.TEMPLESCANESP, pageSize = 15) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.NEWEST, SortOrder.UPDATED)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.NEWEST, SortOrder.UPDATED)
override val configKeyDomain = ConfigKey.Domain("templescanesp.net")
@ -66,7 +66,7 @@ internal class TempleScanEsp(context: MangaLoaderContext) :
}
}
override suspend fun getTags(): Set<MangaTag> = emptySet()
override suspend fun getAvailableTags(): Set<MangaTag> = emptySet()
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
val fullUrl = manga.url.toAbsoluteUrl(domain)

@ -24,7 +24,7 @@ class TuMangaOnlineParser(context: MangaLoaderContext) : PagedMangaParser(
private val chapterDateFormat = SimpleDateFormat("yyyy-MM-dd", sourceLocale)
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.ALPHABETICAL,
SortOrder.UPDATED,
SortOrder.NEWEST,
@ -207,7 +207,7 @@ class TuMangaOnlineParser(context: MangaLoaderContext) : PagedMangaParser(
return document
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/library", headers).parseHtml()
val elements = doc.body().select("div#books-genders > div > div")
return elements.mapNotNullToSet { element ->

@ -21,12 +21,14 @@ internal abstract class FmreaderParser(
override val configKeyDomain = ConfigKey.Domain(domain)
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.UPDATED,
SortOrder.POPULARITY,
SortOrder.ALPHABETICAL,
)
override val isMultipleTagsSupported = false
protected open val listUrl = "/manga-list.html"
protected open val datePattern = "MMMM d, yyyy"
protected open val tagPrefix = "manga-list-genre-"
@ -113,7 +115,7 @@ internal abstract class FmreaderParser(
protected open val selectBodyTag = "ul.filter-type li a"
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/$listUrl").parseHtml()
return doc.select(selectBodyTag).mapNotNullToSet { a ->
val href = a.attr("href").substringAfter(tagPrefix).substringBeforeLast(".html")

@ -86,7 +86,7 @@ internal class Manhwa18Com(context: MangaLoaderContext) :
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/$listUrl").parseHtml()
return doc.select(selectBodyTag).mapNotNullToSet { a ->
val href = a.attr("href").substringAfterLast("/")

@ -20,7 +20,7 @@ internal abstract class FoolSlideParser(
override val configKeyDomain = ConfigKey.Domain(domain)
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL)
protected open val listUrl = "directory/"
protected open val searchUrl = "search/"
@ -81,7 +81,7 @@ internal abstract class FoolSlideParser(
}
override suspend fun getTags(): Set<MangaTag> = emptySet()
override suspend fun getAvailableTags(): Set<MangaTag> = emptySet()
protected open val selectInfo = "div.info"

@ -18,7 +18,7 @@ import java.util.*
@MangaSourceParser("BENTOMANGA", "BentoManga", "fr")
internal class BentomangaParser(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.BENTOMANGA, 10) {
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.UPDATED,
SortOrder.POPULARITY,
SortOrder.RATING,
@ -156,7 +156,7 @@ internal class BentomangaParser(context: MangaLoaderContext) : PagedMangaParser(
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val root = webClient.httpGet(urlBuilder().addPathSegment("manga_list").build())
.parseHtml()
.requireElementById("search_options-form")

@ -17,7 +17,7 @@ import java.util.*
internal class FmTeam(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.FMTEAM, 0) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL)
override val configKeyDomain = ConfigKey.Domain("fmteam.fr")
override suspend fun getListPage(
@ -99,7 +99,7 @@ internal class FmTeam(context: MangaLoaderContext) :
}
override suspend fun getTags(): Set<MangaTag> = emptySet()
override suspend fun getAvailableTags(): Set<MangaTag> = emptySet()
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
val fullUrl = manga.url.toAbsoluteUrl(domain)

@ -18,7 +18,7 @@ import java.util.*
internal class FuryoSociety(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.FURYOSOCIETY, 0) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL, SortOrder.UPDATED)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL, SortOrder.UPDATED)
override val configKeyDomain = ConfigKey.Domain("furyosociety.com")
@ -76,7 +76,7 @@ internal class FuryoSociety(context: MangaLoaderContext) :
}
override suspend fun getTags(): Set<MangaTag> = emptySet()
override suspend fun getAvailableTags(): Set<MangaTag> = emptySet()
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {

@ -16,7 +16,7 @@ import java.util.*
internal class LegacyScansParser(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.LEGACY_SCANS, 18) {
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.POPULARITY,
)
@ -151,7 +151,7 @@ internal class LegacyScansParser(context: MangaLoaderContext) :
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/comics").parseHtml()
val script = doc.requireElementById("__NUXT_DATA__").data()
.substringAfterLast("\"genres\"").substringBeforeLast("\"comics\"")

@ -14,10 +14,12 @@ import java.util.*
@MangaSourceParser("LIRESCAN", "LireScan", "fr")
internal class LireScan(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.LIRESCAN, 20) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val configKeyDomain = ConfigKey.Domain("lire-scan.me")
override val isMultipleTagsSupported = false
override val headers: Headers = Headers.Builder()
.add("User-Agent", UserAgents.CHROME_MOBILE)
.build()
@ -130,7 +132,7 @@ internal class LireScan(context: MangaLoaderContext) : PagedMangaParser(context,
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/").parseHtml()
return doc.select(".nav-menu li a").mapNotNullToSet { a ->
val key = a.attr("href").removeSuffix('/').substringAfterLast("manga/", "")

@ -16,7 +16,7 @@ import java.util.*
@MangaSourceParser("LUGNICASCANS", "LugnicaScans", "fr")
internal class LugnicaScans(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.LUGNICASCANS, 10) {
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.ALPHABETICAL,
SortOrder.UPDATED,
)
@ -176,6 +176,6 @@ internal class LugnicaScans(context: MangaLoaderContext) : PagedMangaParser(cont
return pages
}
override suspend fun getTags(): Set<MangaTag> = emptySet()
override suspend fun getAvailableTags(): Set<MangaTag> = emptySet()
}

@ -17,7 +17,7 @@ import java.util.*
internal class ScansMangasMe(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.SCANS_MANGAS_ME, 0) {
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.ALPHABETICAL,
SortOrder.UPDATED,
SortOrder.NEWEST,
@ -91,7 +91,7 @@ internal class ScansMangasMe(context: MangaLoaderContext) :
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/tous-nos-mangas/").parseHtml()
return doc.select("ul.genre li").mapNotNullToSet { li ->
val key = li.selectFirstOrThrow("a").attr("href").removeSuffix('/').substringAfterLast('/')

@ -15,7 +15,7 @@ import java.util.*
@MangaSourceParser("SCANTRADUNION", "ScantradUnion", "fr")
internal class ScantradUnion(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.SCANTRADUNION, 10) {
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.ALPHABETICAL,
SortOrder.UPDATED,
)
@ -174,7 +174,7 @@ internal class ScantradUnion(context: MangaLoaderContext) : PagedMangaParser(con
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/").parseHtml()
val body = doc.body()
val root = body.select(".asp_gochosen")[1]

@ -20,8 +20,9 @@ internal abstract class GalleryAdultsParser(
pageSize: Int = 20,
) : PagedMangaParser(context, source, pageSize) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val configKeyDomain = ConfigKey.Domain(domain)
override val isMultipleTagsSupported = false
override suspend fun getListPage(
page: Int,
@ -87,7 +88,7 @@ internal abstract class GalleryAdultsParser(
//Tags are deliberately reduced because there are too many and this slows down the application.
//only the most popular ones are taken.
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
return coroutineScope {
(1..3).map { page ->
async { getTags(page) }

@ -20,7 +20,7 @@ internal abstract class HeanCms(
override val configKeyDomain = ConfigKey.Domain(domain)
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.ALPHABETICAL,
SortOrder.UPDATED,
SortOrder.NEWEST,
@ -159,7 +159,7 @@ internal abstract class HeanCms(
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/comics").parseHtml()
val tags = doc.selectFirstOrThrow("script:containsData(Genres)").data()

@ -20,7 +20,7 @@ internal abstract class HeanCmsAlt(
override val configKeyDomain = ConfigKey.Domain(domain)
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
protected open val listUrl = "/comics"
protected open val datePattern = "MMMM d, yyyy"
@ -73,7 +73,7 @@ internal abstract class HeanCmsAlt(
}
}
override suspend fun getTags(): Set<MangaTag> = emptySet()
override suspend fun getAvailableTags(): Set<MangaTag> = emptySet()
protected open val selectDesc = "div.description-container"
protected open val selectAlt = "div.series-alternative-names"

@ -15,7 +15,7 @@ class DoujinDesuParser(context: MangaLoaderContext) : PagedMangaParser(context,
override val configKeyDomain: ConfigKey.Domain
get() = ConfigKey.Domain("doujindesu.tv")
override val sortOrders: Set<SortOrder>
override val availableSortOrders: Set<SortOrder>
get() = EnumSet.of(SortOrder.UPDATED, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.POPULARITY)
override suspend fun getDetails(manga: Manga): Manga {
@ -125,7 +125,7 @@ class DoujinDesuParser(context: MangaLoaderContext) : PagedMangaParser(context,
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
return webClient.httpGet("/genre/".toAbsoluteUrl(domain)).parseHtml()
.requireElementById("taxonomy")
.selectFirstOrThrow(".entries")

@ -34,7 +34,7 @@ class NicovideoSeigaParser(context: MangaLoaderContext) :
return body.selectFirst("#userinfo > div > div > strong")?.text() ?: throw AuthRequiredException(source)
}
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.UPDATED,
SortOrder.POPULARITY,
)
@ -143,7 +143,7 @@ class NicovideoSeigaParser(context: MangaLoaderContext) :
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://${getDomain("seiga")}/manga/list").parseHtml()
val root = doc.body().selectOrThrow("#mg_category_list > ul > li")
return root.mapToSet { li ->

@ -20,8 +20,10 @@ internal abstract class LikeMangaParser(
pageSize: Int = 36,
) : PagedMangaParser(context, source, pageSize) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST)
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST)
override val configKeyDomain = ConfigKey.Domain(domain)
override val isMultipleTagsSupported = false
override suspend fun getListPage(
page: Int,
@ -79,7 +81,7 @@ internal abstract class LikeMangaParser(
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/genres/").parseHtml()
return doc.select("ul.nav-genres li:not(.text-center) a").mapNotNullToSet { a ->
MangaTag(

@ -23,7 +23,9 @@ internal abstract class MadaraParser(
override val configKeyDomain = ConfigKey.Domain(domain)
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val isMultipleTagsSupported = false
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.UPDATED,
SortOrder.POPULARITY,
SortOrder.NEWEST,
@ -245,7 +247,7 @@ internal abstract class MadaraParser(
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/$listUrl").parseHtml()
val body = doc.body()
val root1 = body.selectFirst("header")?.selectFirst("ul.second-menu")

@ -5,9 +5,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
import org.koitharu.kotatsu.parsers.util.*
import java.util.EnumSet
import java.util.HashSet
import java.util.Locale
import java.util.*
@MangaSourceParser("MANGA18FX", "Manga18Fx", "", ContentType.HENTAI)
internal class Manga18Fx(context: MangaLoaderContext) :
@ -15,7 +13,7 @@ internal class Manga18Fx(context: MangaLoaderContext) :
override val sourceLocale: Locale = Locale.ENGLISH
override val datePattern = "dd MMM yy"
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val listUrl = ""
override val selectTestAsync = "ul.row-content-chapter"
override val selectDate = "span.chapter-time"
@ -79,7 +77,7 @@ internal class Manga18Fx(context: MangaLoaderContext) :
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/$listUrl").parseHtml()
val list = doc.body().selectFirstOrThrow("div.genre-menu").select("ul li").orEmpty()
val keySet = HashSet<String>(list.size)

@ -90,7 +90,7 @@ internal class Manhwa18Cc(context: MangaLoaderContext) :
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/$listUrl").parseHtml()
val list = doc.body().selectFirstOrThrow("div.sub-menu").select("ul li").orEmpty()
val keySet = HashSet<String>(list.size)

@ -17,7 +17,7 @@ internal class InstaManhwa(context: MangaLoaderContext) :
override val postReq = true
override val datePattern = "d MMMM, yyyy"
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.ALPHABETICAL,
SortOrder.UPDATED,
SortOrder.NEWEST,

@ -17,7 +17,7 @@ internal class IsekaiScan(context: MangaLoaderContext) :
override val listUrl = "latest-manga/"
override val datePattern = "MMMM d, HH:mm"
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.POPULARITY,
SortOrder.UPDATED,
)

@ -16,7 +16,7 @@ internal class MangaPure(context: MangaLoaderContext) :
override val listUrl = "latest-manga/"
override val datePattern = "MMMM d, HH:mm"
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.POPULARITY,
SortOrder.UPDATED,
)

@ -14,7 +14,7 @@ import java.util.*
internal class DragonTranslationParser(context: MangaLoaderContext) :
MadaraParser(context, MangaSource.DRAGONTRANSLATION, "dragontranslation.net", 30) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val selectPage = "div#chapter_imgs img"

@ -22,7 +22,7 @@ internal class TmoManga(context: MangaLoaderContext) :
searchPaginator.firstPage = 1
}
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.POPULARITY)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.POPULARITY)
override suspend fun getListPage(
page: Int,
query: String?,

@ -105,7 +105,7 @@ internal class ManhwaHub(context: MangaLoaderContext) :
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain").parseHtml()
return doc.select("div.genres li").mapNotNullToSet { li ->
val a = li.selectFirst("a") ?: return@mapNotNullToSet null

@ -21,7 +21,7 @@ internal abstract class MadthemeParser(
override val configKeyDomain = ConfigKey.Domain(domain)
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.UPDATED,
SortOrder.POPULARITY,
SortOrder.ALPHABETICAL,
@ -115,7 +115,7 @@ internal abstract class MadthemeParser(
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/$listUrl").parseHtml()
return doc.select("div.genres label.checkbox").mapNotNullToSet { checkbox ->
val key = checkbox.selectFirstOrThrow("input").attr("value") ?: return@mapNotNullToSet null

@ -20,7 +20,7 @@ internal abstract class Manga18Parser(
override val configKeyDomain = ConfigKey.Domain(domain)
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.UPDATED,
SortOrder.POPULARITY,
SortOrder.ALPHABETICAL,
@ -109,7 +109,7 @@ internal abstract class Manga18Parser(
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/$listUrl/").parseHtml()
return doc.select("div.grid_cate li").mapNotNullToSet { li ->
val a = li.selectFirst("a") ?: return@mapNotNullToSet null

@ -34,5 +34,5 @@ internal class Hanman18(context: MangaLoaderContext) :
}
}
override suspend fun getTags(): Set<MangaTag> = emptySet() // search by tag does not work
override suspend fun getAvailableTags(): Set<MangaTag> = emptySet() // search by tag does not work
}

@ -17,7 +17,7 @@ internal abstract class MangaboxParser(
pageSize: Int = 24,
) : PagedMangaParser(context, source, pageSize) {
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.UPDATED,
SortOrder.POPULARITY,
SortOrder.NEWEST,
@ -107,7 +107,7 @@ internal abstract class MangaboxParser(
protected open val selectTagMap = "div.panel-genres-list a:not(.genres-select)"
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/$listUrl").parseHtml()
return doc.select(selectTagMap).mapNotNullToSet { a ->
val key = a.attr("href").removeSuffix('/').substringAfterLast('/')

@ -99,7 +99,7 @@ internal class Mangairo(context: MangaLoaderContext) :
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/$listUrl/type-latest/ctg-all/state-all/page-1").parseHtml()
return doc.select("div.panel_category a:not(.ctg_select)").mapNotNullToSet { a ->
val key = a.attr("href").substringAfterLast("ctg-").substringBefore("/")

@ -73,7 +73,7 @@ internal class MangakakalotTv(context: MangaLoaderContext) :
override val selectTagMap = "ul.tag li a"
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/$listUrl").parseHtml()
return doc.select(selectTagMap).mapNotNullToSet { a ->
MangaTag(

@ -29,7 +29,7 @@ internal abstract class MangaReaderParser(
override val configKeyDomain = ConfigKey.Domain(domain)
override val sortOrders: Set<SortOrder>
override val availableSortOrders: Set<SortOrder>
get() = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.ALPHABETICAL, SortOrder.NEWEST)
protected open val listUrl = "/manga"
@ -283,7 +283,7 @@ internal abstract class MangaReaderParser(
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
return getOrCreateTagMap().values.toSet()
}

@ -75,7 +75,7 @@ internal class ManhwaFreak(context: MangaLoaderContext) :
return parseMangaList(webClient.httpGet(url).parseHtml())
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/genres/").parseHtml()
return doc.select("ul.genre-list li a").mapNotNullToSet { a ->
val href = a.attr("href").substringAfterLast("=")

@ -19,7 +19,7 @@ internal class RizzComic(context: MangaLoaderContext) :
override val datePattern = "dd MMM yyyy"
override val listUrl = "/series"
override val sortOrders: Set<SortOrder>
override val availableSortOrders: Set<SortOrder>
get() = EnumSet.of(SortOrder.ALPHABETICAL)
override suspend fun getListPage(

@ -21,7 +21,7 @@ internal class Zahard(context: MangaLoaderContext) :
override val selectPage = "div#chapter_imgs img"
override val sortOrders: Set<SortOrder>
override val availableSortOrders: Set<SortOrder>
get() = EnumSet.of(SortOrder.NEWEST)

@ -19,10 +19,10 @@ internal class TuManhwas(context: MangaLoaderContext) :
override val selectPage = "div#readerarea img"
override val sortOrders: Set<SortOrder>
override val availableSortOrders: Set<SortOrder>
get() = EnumSet.of(SortOrder.NEWEST)
override suspend fun getTags(): Set<MangaTag> = emptySet()
override suspend fun getAvailableTags(): Set<MangaTag> = emptySet()
override suspend fun getListPage(
page: Int,
query: String?,

@ -77,7 +77,7 @@ internal class ManhwaFreakFr(context: MangaLoaderContext) :
return parseMangaList(webClient.httpGet(url).parseHtml())
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/genres/").parseHtml()
return doc.select("ul.genre-list li a").mapNotNullToSet { a ->
val href = a.attr("href").substringAfterLast("=")

@ -18,7 +18,7 @@ internal class Komikcast(context: MangaLoaderContext) :
override val listUrl = "/daftar-komik"
override val datePattern = "MMM d, yyyy"
override val sourceLocale: Locale = Locale.ENGLISH
override val sortOrders: Set<SortOrder>
override val availableSortOrders: Set<SortOrder>
get() = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.ALPHABETICAL)
override suspend fun getListPage(

@ -20,7 +20,7 @@ internal abstract class MmrcmsParser(
override val configKeyDomain = ConfigKey.Domain(domain)
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.POPULARITY,
SortOrder.UPDATED,
SortOrder.ALPHABETICAL,
@ -138,7 +138,7 @@ internal abstract class MmrcmsParser(
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/$tagUrl/").parseHtml()
return doc.select("ul.list-category li").mapNotNullToSet { li ->
val a = li.selectFirst("a") ?: return@mapNotNullToSet null

@ -22,7 +22,7 @@ internal class Animaregia(context: MangaLoaderContext) :
override val sourceLocale: Locale = Locale.ENGLISH
//temporary
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.POPULARITY,
SortOrder.ALPHABETICAL,
)

@ -23,7 +23,7 @@ internal abstract class NepnepParser(
override val configKeyDomain = ConfigKey.Domain(domain)
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL)
override val headers: Headers = Headers.Builder()
.add("User-Agent", UserAgents.CHROME_DESKTOP)
@ -104,7 +104,7 @@ internal abstract class NepnepParser(
)
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/search/").parseHtml()
val tags = doc.selectFirstOrThrow("script:containsData(vm.AvailableFilters)").data()
.substringAfter("\"Genre\"")

@ -20,7 +20,7 @@ internal abstract class OtakuSanctuaryParser(
override val configKeyDomain = ConfigKey.Domain(domain)
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.UPDATED,
SortOrder.NEWEST,
)
@ -114,7 +114,7 @@ internal abstract class OtakuSanctuaryParser(
protected open val selectBodyTag = "div#genre-table a"
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/Home/LoadingGenresMenu").parseHtml()
return doc.select(selectBodyTag).mapNotNullToSet { a ->
val href = a.attr("href").substringAfterLast("/").substringBefore("?")

@ -13,7 +13,7 @@ import java.util.*
@MangaSourceParser("BAKAI", "Bakai", "pt", ContentType.HENTAI)
internal class Bakai(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.BAKAI, 15) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val configKeyDomain = ConfigKey.Domain("bakai.org")
override val headers: Headers = Headers.Builder()
.add("User-Agent", UserAgents.CHROME_MOBILE)
@ -89,7 +89,7 @@ internal class Bakai(context: MangaLoaderContext) : PagedMangaParser(context, Ma
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain").parseHtml()
return doc.requireElementById("elNavigation_17_menu").select("li.ipsMenu_item a").mapNotNullToSet { a ->

@ -13,7 +13,7 @@ import java.util.*
@MangaSourceParser("BRMANGAS", "BrMangas", "pt")
internal class BrMangas(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.BRMANGAS, 25) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.POPULARITY, SortOrder.UPDATED)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.POPULARITY, SortOrder.UPDATED)
override val configKeyDomain = ConfigKey.Domain("www.brmangas.net")
@ -81,7 +81,7 @@ internal class BrMangas(context: MangaLoaderContext) : PagedMangaParser(context,
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/lista-de-generos-de-manga/").parseHtml()
return doc.select(".genres_page a").mapNotNullToSet { a ->
MangaTag(

@ -14,7 +14,7 @@ import java.util.*
@MangaSourceParser("LERMANGAONLINE", "LerMangaOnline", "pt")
class LerMangaOnline(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.LERMANGAONLINE, 20) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val configKeyDomain = ConfigKey.Domain("lermangaonline.com.br")
@ -67,7 +67,7 @@ class LerMangaOnline(context: MangaLoaderContext) : PagedMangaParser(context, Ma
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/").parseHtml().requireElementById("sub-menu")
return doc.select("ul.container li a").mapNotNullToSet { a ->
MangaTag(

@ -12,7 +12,7 @@ import java.util.*
@MangaSourceParser("MANGAONLINE", "MangaOnline.biz", "pt")
class MangaOnline(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.MANGAONLINE, 20) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val configKeyDomain = ConfigKey.Domain("mangaonline.biz")
@ -71,7 +71,7 @@ class MangaOnline(context: MangaLoaderContext) : PagedMangaParser(context, Manga
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/generos/").parseHtml()
return doc.select(".wp-content p a").mapNotNullToSet { a ->
MangaTag(

@ -13,7 +13,7 @@ import java.util.*
@MangaSourceParser("YUGENMANGAS", "YugenMangas.org", "pt")
class YugenMangas(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.YUGENMANGAS, 28) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL, SortOrder.UPDATED)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL, SortOrder.UPDATED)
override val configKeyDomain = ConfigKey.Domain("yugenmangas.org")
override suspend fun getListPage(
@ -142,5 +142,5 @@ class YugenMangas(context: MangaLoaderContext) : PagedMangaParser(context, Manga
return pages
}
override suspend fun getTags(): Set<MangaTag> = emptySet()
override suspend fun getAvailableTags(): Set<MangaTag> = emptySet()
}

@ -20,7 +20,7 @@ internal class DesuMeParser(context: MangaLoaderContext) : PagedMangaParser(cont
override val configKeyDomain = ConfigKey.Domain("desu.me", "desu.win")
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.UPDATED,
SortOrder.POPULARITY,
SortOrder.NEWEST,
@ -148,7 +148,7 @@ internal class DesuMeParser(context: MangaLoaderContext) : PagedMangaParser(cont
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
return tagsCache.get().values.toSet()
}

@ -30,7 +30,7 @@ internal class NudeMoonParser(
}
}
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.NEWEST,
SortOrder.POPULARITY,
SortOrder.RATING,
@ -144,7 +144,7 @@ internal class NudeMoonParser(
return page.url.toAbsoluteUrl("img.$domain")
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val domain = domain
val doc = webClient.httpGet("https://$domain/tags").parseHtml()
val root = doc.body().getElementsByAttributeValue("name", "multitags").first()

@ -47,7 +47,7 @@ internal class RemangaParser(
override val authUrl: String
get() = "https://${domain}/user/login"
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.UPDATED,
SortOrder.POPULARITY,
SortOrder.RATING,
@ -221,7 +221,7 @@ internal class RemangaParser(
return result
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val domain = domain
val content = webClient.httpGet("https://api.$domain/api/forms/titles/?get=genres")
.parseJson().getJSONObject("content").getJSONArray("genres")

@ -46,7 +46,7 @@ internal abstract class GroupleParser(
override val headers: Headers = Headers.Builder().add("User-Agent", config[userAgentKey]).build()
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.UPDATED,
SortOrder.POPULARITY,
SortOrder.NEWEST,
@ -218,7 +218,7 @@ internal abstract class GroupleParser(
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://${domain}/list/genres/sort_name").parseHtml()
val root = doc.body().getElementById("mangaBox")?.selectFirst("div.leftContent")?.selectFirst("table.table")
?: doc.parseFailed("Cannot find root")

@ -15,7 +15,7 @@ internal abstract class ChanParser(
source: MangaSource,
) : MangaParser(context, source), MangaParserAuthProvider {
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.NEWEST,
SortOrder.POPULARITY,
SortOrder.ALPHABETICAL,
@ -126,7 +126,7 @@ internal abstract class ChanParser(
doc.parseFailed("Pages list not found at ${chapter.url}")
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val domain = domain
val doc = webClient.httpGet("https://$domain/mostfavorites&sort=manga").parseHtml()
val root = doc.body().selectFirst("div.main_fon")?.getElementById("side")

@ -21,7 +21,7 @@ internal class HenChanParser(context: MangaLoaderContext) : ChanParser(context,
"hentaichan.pro",
)
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.NEWEST,
SortOrder.POPULARITY,
SortOrder.RATING,

@ -17,7 +17,7 @@ internal class YaoiChanParser(context: MangaLoaderContext) : ChanParser(context,
"yaoi-chan.me",
)
override val sortOrders: Set<SortOrder> = setOf(SortOrder.NEWEST)
override val availableSortOrders: Set<SortOrder> = setOf(SortOrder.NEWEST)
override suspend fun getDetails(manga: Manga): Manga {
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()

@ -32,7 +32,7 @@ internal open class MangaLibParser(
override val authUrl: String
get() = "https://$domain/login"
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.RATING,
SortOrder.ALPHABETICAL,
SortOrder.POPULARITY,
@ -232,7 +232,7 @@ internal open class MangaLibParser(
} ?: concatUrl(defaultServer, pageUrl)
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val url = "https://$domain/manga-list"
val doc = webClient.httpGet(url).parseHtml()
val scripts = doc.body().select("script")

@ -18,7 +18,7 @@ internal abstract class SinmhParser(
override val configKeyDomain = ConfigKey.Domain(domain)
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.UPDATED,
SortOrder.POPULARITY,
)
@ -101,7 +101,7 @@ internal abstract class SinmhParser(
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/$listUrl").parseHtml()
return doc.select(".filter-item:contains(按剧情) li a:not(.active)").mapNotNullToSet { a ->
val href = a.attr("href").removeSuffix('/').substringAfterLast('/')

@ -15,7 +15,7 @@ import java.util.*
@MangaSourceParser("MANGAAY", "MangaAy", "tr")
class MangaAy(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.MANGAAY, 45) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val configKeyDomain = ConfigKey.Domain("manga-ay.com")
@ -93,7 +93,7 @@ class MangaAy(context: MangaLoaderContext) : PagedMangaParser(context, MangaSour
private var tagCache: ArrayMap<String, MangaTag>? = null
private val mutex = Mutex()
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
return getOrCreateTagMap().values.toSet()
}

@ -12,7 +12,7 @@ import java.util.*
@MangaSourceParser("SADSCANS", "SadScans", "tr")
internal class SadScans(context: MangaLoaderContext) : MangaParser(context, MangaSource.SADSCANS) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL)
override val configKeyDomain = ConfigKey.Domain("sadscans.com")
override suspend fun getList(offset: Int, query: String?, tags: Set<MangaTag>?, sortOrder: SortOrder): List<Manga> {
@ -46,7 +46,7 @@ internal class SadScans(context: MangaLoaderContext) : MangaParser(context, Mang
}
}
override suspend fun getTags(): Set<MangaTag> = emptySet()
override suspend fun getAvailableTags(): Set<MangaTag> = emptySet()
override suspend fun getDetails(manga: Manga): Manga {
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()

@ -16,7 +16,7 @@ class TrWebtoon(context: MangaLoaderContext) :
override val configKeyDomain: ConfigKey.Domain = ConfigKey.Domain("trwebtoon.com")
override val sortOrders: Set<SortOrder>
override val availableSortOrders: Set<SortOrder>
get() = EnumSet.of(SortOrder.POPULARITY, SortOrder.ALPHABETICAL, SortOrder.UPDATED)
override suspend fun getListPage(
@ -112,7 +112,7 @@ class TrWebtoon(context: MangaLoaderContext) :
return mangas
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val tags =
webClient.httpGet("https://$domain/webtoon-listesi").parseHtml().requireElementById("collapseExample")
.select(".pt-12 a").drop(1)

@ -12,7 +12,7 @@ import java.util.*
@MangaSourceParser("YAOIFLIX", "YaoiFlix", "tr", ContentType.HENTAI)
class YaoiFlix(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.YAOIFLIX, 8) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val configKeyDomain = ConfigKey.Domain("www.yaoiflix.pro")
@ -79,7 +79,7 @@ class YaoiFlix(context: MangaLoaderContext) : PagedMangaParser(context, MangaSou
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain").parseHtml()
return doc.select(".tags .cat-item a").mapNotNullToSet { a ->
MangaTag(

@ -33,7 +33,7 @@ class HentaiUkrParser(context: MangaLoaderContext) : MangaParser(context, MangaS
override val configKeyDomain: ConfigKey.Domain = ConfigKey.Domain("hentaiukr.com")
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.NEWEST,
)
@ -119,7 +119,7 @@ class HentaiUkrParser(context: MangaLoaderContext) : MangaParser(context, MangaS
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
return allManga.get().flatMapTo(HashSet()) { x ->
x.getJSONArray("tags").mapJSON { t ->
MangaTag(

@ -37,7 +37,7 @@ class HoneyMangaParser(context: MangaLoaderContext) : PagedMangaParser(context,
override val configKeyDomain: ConfigKey.Domain
get() = ConfigKey.Domain("honey-manga.com.ua")
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.POPULARITY,
SortOrder.NEWEST,
)
@ -166,7 +166,7 @@ class HoneyMangaParser(context: MangaLoaderContext) : PagedMangaParser(context,
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
// https://data.api.honey-manga.com.ua/genres-tags/genres-list
val content = webClient.httpGet(genresListApi).parseJsonArray()
val tagsSet = ArraySet<MangaTag>(content.length())

@ -19,7 +19,7 @@ class MangaInUaParser(context: MangaLoaderContext) : PagedMangaParser(
searchPageSize = 10,
) {
override val sortOrders: Set<SortOrder> = setOf(SortOrder.UPDATED)
override val availableSortOrders: Set<SortOrder> = setOf(SortOrder.UPDATED)
override val configKeyDomain: ConfigKey.Domain = ConfigKey.Domain("manga.in.ua")
@ -151,7 +151,7 @@ class MangaInUaParser(context: MangaLoaderContext) : PagedMangaParser(
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val domain = domain
val doc = webClient.httpGet("https://$domain/mangas").parseHtml()
val root = doc.body().requireElementById("menu_1").selectFirstOrThrow("div.menu__wrapper")

@ -22,7 +22,7 @@ class BlogTruyenParser(context: MangaLoaderContext) :
override val configKeyDomain: ConfigKey.Domain
get() = ConfigKey.Domain("blogtruyenmoi.com")
override val sortOrders: Set<SortOrder>
override val availableSortOrders: Set<SortOrder>
get() = EnumSet.of(SortOrder.UPDATED)
override val headers: Headers = Headers.Builder()
@ -219,7 +219,7 @@ class BlogTruyenParser(context: MangaLoaderContext) :
return pages
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
return cacheTags.get().values.toSet()
}

@ -28,7 +28,7 @@ class HentaiVNParser(context: MangaLoaderContext) : MangaParser(context, MangaSo
// hentaivn has created 2 different interfaces for mobile and desktop, and Cloudflare detects whether it's mobile or not even with a desktop user agent.
override val headers: Headers = Headers.Builder().add("User-Agent", UserAgents.CHROME_MOBILE).build()
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.UPDATED,
SortOrder.POPULARITY,
SortOrder.RATING,
@ -137,7 +137,7 @@ class HentaiVNParser(context: MangaLoaderContext) : MangaParser(context, MangaSo
private var tagCache: ArrayMap<String, MangaTag>? = null
private val mutex = Mutex()
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
return getOrCreateTagMap().values.toSet()
}

@ -14,7 +14,7 @@ import java.util.*
@MangaSourceParser("LXMANGA", "LxManga", "vi")
internal class LxManga(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.LXMANGA, 60) {
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.ALPHABETICAL,
SortOrder.UPDATED,
SortOrder.NEWEST,
@ -150,7 +150,7 @@ internal class LxManga(context: MangaLoaderContext) : PagedMangaParser(context,
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/").parseHtml()
val body = doc.body()
return body.select("ul.absolute.w-full a").mapToSet { a ->

@ -26,7 +26,7 @@ class NetTruyenParser(context: MangaLoaderContext) :
"nettruyenin.com",
)
override val sortOrders: Set<SortOrder>
override val availableSortOrders: Set<SortOrder>
get() = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.RATING)
private val mutex = Mutex()
@ -194,7 +194,7 @@ class NetTruyenParser(context: MangaLoaderContext) :
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val map = getOrCreateTagMap()
val tagSet = ArraySet<MangaTag>(map.size)
for (entry in map) {

@ -12,7 +12,8 @@ import java.util.*
@MangaSourceParser("TRUYENQQ", "Truyenqq", "vi")
internal class Truyenqq(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.TRUYENQQ, 42) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST)
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST)
override val configKeyDomain = ConfigKey.Domain("truyenqqvn.com")
override suspend fun getListPage(
@ -67,7 +68,7 @@ internal class Truyenqq(context: MangaLoaderContext) : PagedMangaParser(context,
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
val doc = webClient.httpGet("https://$domain/tim-kiem-nang-cao.html").parseHtml()
return doc.select(".advsearch-form div.genre-item").mapNotNullToSet {
MangaTag(

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save