Merge branch 'feature/filter-ex'

This commit is contained in:
2023-11-23 11:19:48 +02:00
108 changed files with 364 additions and 216 deletions

View File

@@ -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

View File

@@ -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()
}
}

View File

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

View File

@@ -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")

View File

@@ -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()) {

View File

@@ -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 ->

View File

@@ -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) }

View File

@@ -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")

View File

@@ -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 ->

View File

@@ -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()
}

View File

@@ -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

View File

@@ -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('=')

View File

@@ -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(",")

View File

@@ -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()

View File

@@ -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(

View File

@@ -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) {

View File

@@ -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(

View File

@@ -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()
}

View File

@@ -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(

View File

@@ -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()

View File

@@ -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(

View File

@@ -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) }

View File

@@ -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(

View File

@@ -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")

View File

@@ -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("/")

View File

@@ -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()
}

View File

@@ -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 ->

View File

@@ -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()

View File

@@ -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) }

View File

@@ -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)

View File

@@ -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 ->

View File

@@ -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")

View File

@@ -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("/")

View File

@@ -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"

View File

@@ -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,
@@ -99,11 +99,14 @@ internal class BentomangaParser(context: MangaLoaderContext) : PagedMangaParser(
val root = webClient.httpGet(mangaUrl).parseHtml()
.requireElementById("container_manga_show")
return manga.copy(
altTitle = root.selectFirst(".component-manga-title_alt")?.textOrNull().assertNotNull("altTitle"),
altTitle = root.selectFirst(".component-manga-title_alt")?.text(),
description = root.selectFirst(".datas_synopsis")?.html().assertNotNull("description")
?: manga.description,
state = when (root.selectFirst(".datas_more-status-data")?.textOrNull().assertNotNull("status")) {
"En cours" -> MangaState.ONGOING
"Terminé" -> MangaState.FINISHED
"Abandonné" -> MangaState.ABANDONED
"En pause" -> MangaState.PAUSED
else -> null
},
author = root.selectFirst(".datas_more-authors-people")?.textOrNull().assertNotNull("author"),
@@ -156,7 +159,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")

View File

@@ -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(
@@ -29,11 +29,9 @@ internal class FmTeam(context: MangaLoaderContext) :
if (page > 1) {
return emptyList()
}
val jsonManga = if (!query.isNullOrEmpty()) {
//3 letters minimum
webClient.httpGet("https://$domain/api/search/${query.urlEncoded()}").parseJson().getJSONArray("comics")
} else {
webClient.httpGet("https://$domain/api/comics").parseJson().getJSONArray("comics")
}
@@ -99,7 +97,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)

View File

@@ -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 {

View File

@@ -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\"")

View File

@@ -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/", "")

View File

@@ -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()
}

View File

@@ -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('/')

View File

@@ -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]

View File

@@ -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) }

View File

@@ -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,
@@ -100,6 +100,7 @@ internal abstract class HeanCms(
"Ongoing" -> MangaState.ONGOING
"Completed" -> MangaState.FINISHED
"Dropped" -> MangaState.ABANDONED
"Hiatus" -> MangaState.PAUSED
else -> null
},
author = null,
@@ -159,7 +160,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()

View File

@@ -84,6 +84,7 @@ internal class YugenMangasEs(context: MangaLoaderContext) :
"Ongoing" -> MangaState.ONGOING
"Completed" -> MangaState.FINISHED
"Dropped" -> MangaState.ABANDONED
"Hiatus" -> MangaState.PAUSED
else -> null
},
author = null,

View File

@@ -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"

View File

@@ -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")

View File

@@ -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 ->

View File

@@ -21,8 +21,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,
@@ -80,7 +82,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(

View File

@@ -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,
@@ -137,6 +139,16 @@ internal abstract class MadaraParser(
"Abandonné",
)
@JvmField
protected val paused: Set<String> = hashSetOf(
"Hiatus",
"On Hold",
"Pausado",
"En espera",
"En pause",
"En attente",
)
// Change these values only if the site does not support manga listings via ajax
protected open val withoutAjax = false
@@ -232,11 +244,11 @@ internal abstract class MadaraParser(
)
}.orEmpty(),
author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(),
state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText()
?.lowercase()) {
state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText()) {
in ongoing -> MangaState.ONGOING
in finished -> MangaState.FINISHED
in abandoned -> MangaState.ABANDONED
in paused -> MangaState.PAUSED
else -> null
},
source = source,
@@ -245,7 +257,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")
@@ -314,6 +326,7 @@ internal abstract class MadaraParser(
in ongoing -> MangaState.ONGOING
in finished -> MangaState.FINISHED
in abandoned -> MangaState.ABANDONED
in paused -> MangaState.PAUSED
else -> null
}
}

View File

@@ -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)

View File

@@ -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)

View File

@@ -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,

View File

@@ -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,
)

View File

@@ -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,
)

View File

@@ -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"

View File

@@ -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?,

View File

@@ -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

View File

@@ -7,6 +7,6 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
@MangaSourceParser("CERISE_SCANS", "CeriseScans", "pt")
internal class CeriseScans(context: MangaLoaderContext) :
MadaraParser(context, MangaSource.CERISE_SCANS, "cerisescan.net/") {
MadaraParser(context, MangaSource.CERISE_SCANS, "cerisescan.net") {
override val datePattern: String = "dd 'de' MMMMM 'de' yyyy"
}

View File

@@ -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

View File

@@ -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

View File

@@ -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
}

View File

@@ -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('/')

View File

@@ -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("/")

View File

@@ -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(

View File

@@ -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"
@@ -181,20 +181,24 @@ internal abstract class MangaReaderParser(
val mangaState = state?.let {
when (it.text()) {
"مستمرة", "En curso", "En Curso", "Ongoing", "OnGoing", "On going", "Ativo", "En Cours", "En cours",
"En cours \uD83D\uDFE2", "En cours de publication", "Đang tiến hành", "Em lançamento", "em lançamento", "Em Lançamento",
"Онгоінг", "Publishing", "Devam Ediyor", "Em Andamento", "In Corso", "Güncel", "Berjalan", "Продолжается", "Updating",
"Lançando", "In Arrivo", "Emision", "En emision", "مستمر", "Curso", "En marcha", "Publicandose", "Publicando", "连载中",
"Devam ediyor", "Devam Etmekte",
"مستمرة", "En curso", "En Curso", "Ongoing", "OnGoing", "On going", "Ativo", "En Cours", "En cours", "En cours \uD83D\uDFE2",
"En cours de publication", "Đang tiến hành", "Em lançamento", "em lançamento", "Em Lançamento", "Онгоінг", "Publishing",
"Devam Ediyor", "Em Andamento", "In Corso", "Güncel", "Berjalan", "Продолжается", "Updating", "Lançando", "In Arrivo", "Emision",
"En emision", "مستمر", "Curso", "En marcha", "Publicandose", "Publicando", "连载中", "Devam ediyor", "Devam Etmekte",
-> MangaState.ONGOING
"Completed", "Completo", "Complété", "Fini", "Achevé", "Terminé", "Terminé ⚫", "Tamamlandı", "Đã hoàn thành", "Hoàn Thành", "مكتملة",
"Завершено", "Finished", "Finalizado", "Completata", "One-Shot", "Bitti", "Tamat", "Completado", "Concluído", "Concluido", "已完结", "Bitmiş",
"Completed", "Completo", "Complété", "Fini", "Achevé", "Terminé", "Terminé ⚫", "Tamamlandı", "Đã hoàn thành", "Hoàn Thành",
"مكتملة", "Завершено", "Finished", "Finalizado", "Completata", "One-Shot", "Bitti", "Tamat", "Completado", "Concluído",
"Concluido", "已完结", "Bitmiş",
-> MangaState.FINISHED
"Canceled", "Cancelled", "Cancelado", "cancellato", "Cancelados", "Dropped", "Discontinued", "abandonné", "Abandonné",
-> MangaState.ABANDONED
"Hiatus", "On Hold", "Pausado", "En espera", "En pause", "En Pause", "En attente",
-> MangaState.PAUSED
else -> null
}
}
@@ -283,7 +287,7 @@ internal abstract class MangaReaderParser(
}
}
override suspend fun getTags(): Set<MangaTag> {
override suspend fun getAvailableTags(): Set<MangaTag> {
return getOrCreateTagMap().values.toSet()
}

View File

@@ -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("=")

View File

@@ -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(

View File

@@ -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)

View File

@@ -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?,

View File

@@ -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("=")

View File

@@ -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(

View File

@@ -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

View File

@@ -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\"")
@@ -138,12 +138,18 @@ internal abstract class NepnepParser(
return manga.copy(
altTitle = null,
state = when (doc.selectFirstOrThrow(".list-group-item:contains(Status:) a").text()) {
"Ongoing (Scan)", "Ongoing (Publish)" -> MangaState.ONGOING
"Ongoing (Scan)", "Ongoing (Publish)",
-> MangaState.ONGOING
"Complete (Scan)", "Complete (Publish)",
-> MangaState.FINISHED
"Cancelled (Scan)", "Cancelled (Publish)",
"Discontinued (Scan)", "Discontinued (Publish)",
-> MangaState.ABANDONED
"Hiatus (Scan)", "Hiatus (Publish)",
-> MangaState.FINISHED
-> MangaState.PAUSED
else -> null
},

View File

@@ -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("?")

View File

@@ -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 ->

View File

@@ -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(

View File

@@ -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(

View File

@@ -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(

View File

@@ -16,7 +16,7 @@ import java.util.*
@MangaSourceParser("YUGENMANGAS", "YugenMangas.net.br", "pt")
class YugenMangas(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.YUGENMANGAS, 28) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL)
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL, SortOrder.UPDATED)
override val configKeyDomain = ConfigKey.Domain("yugenmangas.net.br")
override suspend fun getListPage(
@@ -86,7 +86,7 @@ class YugenMangas(context: MangaLoaderContext) : PagedMangaParser(context, Manga
when (it) {
"ongoing" -> MangaState.ONGOING
"completed" -> MangaState.FINISHED
//"hiatus" -> MangaState.PAUSED
"hiatus" -> MangaState.PAUSED
else -> null
}
},
@@ -145,5 +145,5 @@ class YugenMangas(context: MangaLoaderContext) : PagedMangaParser(context, Manga
return pages
}
override suspend fun getTags(): Set<MangaTag> = emptySet()
override suspend fun getAvailableTags(): Set<MangaTag> = emptySet()
}

View File

@@ -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()
}

View File

@@ -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()

View File

@@ -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")

View File

@@ -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")

View File

@@ -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")

View File

@@ -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,

View File

@@ -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()

View File

@@ -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")

View File

@@ -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('/')

View File

@@ -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()
}

View File

@@ -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()

View File

@@ -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)

View File

@@ -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(

View File

@@ -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(

View File

@@ -37,7 +37,7 @@ class HoneyMangaParser(context: MangaLoaderContext) : PagedMangaParser(context,
override val configKeyDomain = ConfigKey.Domain("honey-manga.com.ua")
override val sortOrders: Set<SortOrder> = EnumSet.of(
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.POPULARITY,
SortOrder.NEWEST,
)
@@ -167,7 +167,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())

View File

@@ -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")

View File

@@ -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()
}

View File

@@ -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()
}

View File

@@ -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 ->

View File

@@ -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) {

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