Refonte madara :

Add tagsExclude
Add support multiple tags
Add RATING_ASC ( and prepare RELEVANCE )
simplify postrequest
Preparation for query, year, author and artist filters
Change withoutAjax for some sources
master
devi 2 years ago
parent ad726a3fd7
commit fd7684866e

@ -54,7 +54,7 @@ internal abstract class MadaraParser(
}
}
override val isMultipleTagsSupported = false
override val isMultipleTagsSupported = true
override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.UPDATED,
@ -66,12 +66,15 @@ internal abstract class MadaraParser(
SortOrder.ALPHABETICAL,
SortOrder.ALPHABETICAL_DESC,
SortOrder.RATING,
SortOrder.RATING_ASC,
)
override val availableStates: Set<MangaState> = EnumSet.allOf(MangaState::class.java)
override val availableContentRating: Set<ContentRating> = EnumSet.of(ContentRating.SAFE, ContentRating.ADULT)
override val isTagsExclusionSupported = true
protected open val tagPrefix = "manga-genre/"
protected open val datePattern = "MMMM d, yyyy"
protected open val stylePage = "?style=list"
@ -224,24 +227,25 @@ internal abstract class MadaraParser(
}
is MangaListFilter.Advanced -> {
if (filter.tags.isNotEmpty()) {
filter.tags.oneOrThrowIfMany()?.let {
append("/$tagPrefix")
append(it.key)
if (pages > 1) {
append("/page/")
append(pages.toString())
}
append("/?")
}
} else {
append("/?s=")
if (pages > 1) {
append("/page/")
append(pages.toString())
//Support query
//append(filter.query.urlEncoded())
append("&post_type=wp-manga")
// Known bug: in some cases, if there are no manga with the associated tags, the source returns the full list of manga
if (filter.tags.isNotEmpty()) {
filter.tags.forEach {
append("&genre[]=")
append(it.key)
}
}
append("/?s=&post_type=wp-manga")
filter.states.forEach {
append("&status[]=")
when (it) {
@ -264,32 +268,46 @@ internal abstract class MadaraParser(
)
}
append("&")
}
// Support year
//filter.year?.let {
// append("&release=")
// append(filter.year)
//}
// Support author
//filter.author?.let {
// append("&author=")
// append(filter.author)
//}
append("m_orderby=")
// Support artist
//filter.artist?.let {
// append("&artist=")
// append(filter.artist)
//}
append("&m_orderby=")
when (filter.sortOrder) {
SortOrder.POPULARITY -> append("views")
SortOrder.UPDATED -> append("latest")
SortOrder.NEWEST -> append("new-manga")
SortOrder.ALPHABETICAL -> append("alphabet")
SortOrder.RATING -> append("rating")
// SortOrder.RELEVANCE -> {}
else -> append("latest")
}
}
null -> {
append("?s&post_type=wp-manga&m_orderby=latest")
append("/?s=&post_type=wp-manga&m_orderby=latest")
}
}
}
return parseMangaList(webClient.httpGet(url).parseHtml())
} else {
val payload = if (filter?.sortOrder == SortOrder.RATING) {
createRequestTemplate(ratingRequest)
} else {
createRequestTemplate(defaultRequest)
}
val payload = createRequestTemplate()
payload["page"] = page.toString()
@ -301,8 +319,61 @@ internal abstract class MadaraParser(
is MangaListFilter.Advanced -> {
filter.tags.oneOrThrowIfMany()?.let {
payload["vars[wp-manga-genre]"] = it.key
// Support query
// filter.query.let {
// payload["vars[s]"] = filter.query.urlEncoded()
// }
if (filter.tags.isNotEmpty()) {
var nTag = 0
payload["vars[tax_query][0][taxonomy]"] = "wp-manga-genre"
payload["vars[tax_query][0][field]"] = "slug"
filter.tags.forEach {
payload["vars[tax_query][0][terms][$nTag]"] = it.key
nTag++
}
payload["vars[tax_query][0][operator]"] = "IN"
}
if (filter.tagsExclude.isNotEmpty()) {
var ntagsExclude = 0
payload["vars[tax_query][1][taxonomy]"] = "wp-manga-genre"
payload["vars[tax_query][1][field]"] = "slug"
filter.tagsExclude.forEach {
payload["vars[tax_query][1][terms][$ntagsExclude]"] = it.key
ntagsExclude++
}
payload["vars[tax_query][1][operator]"] = "NOT IN"
}
// Support year
//filter.year?.let {
// payload["vars[tax_query][2][taxonomy]"] = wp-manga-release
// payload["vars[tax_query][2][field]"] = slug
// payload["vars[tax_query][2][terms][]"] = filter.year
//}
// Support author
// filter.author.let {
// payload["vars[tax_query][3][taxonomy]"] = "wp-manga-author"
// payload["vars[tax_query][3][field]"] = "slug"
// payload["vars[tax_query][3][terms][0]"] = filter.author
// payload["vars[tax_query][3][operator]"] = "IN"
//}
// Support artist
// filter.artist.let {
// payload["vars[tax_query][3][taxonomy]"] = "wp-manga-artist"
// payload["vars[tax_query][3][field]"] = "slug"
// payload["vars[tax_query][3][terms][0]"] = filter.artist
// payload["vars[tax_query][3][operator]"] = "IN"
//}
/// for add filter.year need to add || filter.year
if (filter.tags.isNotEmpty() || filter.tagsExclude.isNotEmpty()) {
payload["vars[tax_query][relation]"] = "AND"
}
when (filter.sortOrder) {
@ -346,12 +417,32 @@ internal abstract class MadaraParser(
payload["vars[order]"] = "desc"
}
SortOrder.RATING -> {}
SortOrder.RATING -> {
payload["vars[meta_query][0][query_avarage_reviews][key]"] = "_manga_avarage_reviews"
payload["vars[meta_query][0][query_total_reviews][key]"] = "_manga_total_votes"
payload["vars[orderby][query_avarage_reviews]"] = "DESC"
payload["vars[orderby][query_total_reviews]"] = "DESC"
}
SortOrder.RATING_ASC -> {
payload["vars[meta_query][0][query_avarage_reviews][key]"] = "_manga_avarage_reviews"
payload["vars[meta_query][0][query_total_reviews][key]"] = "_manga_total_votes"
payload["vars[orderby][query_avarage_reviews]"] = "ASC"
payload["vars[orderby][query_total_reviews]"] = "ASC"
}
// SortOrder.RELEVANCE -> {
// payload["vars[orderby]"] = ""
// }
else -> payload["vars[meta_key]"] = "_latest_update"
}
filter.states.forEach {
payload["vars[meta_query][0][0][key]"] = "_wp_manga_status"
payload["vars[meta_query][0][0][compare]"] = "IN"
payload["vars[meta_query][0][0][value][]"] =
when (it) {
MangaState.ONGOING -> "on-going"
@ -398,10 +489,10 @@ internal abstract class MadaraParser(
url = href,
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src().orEmpty(),
title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4")
?: div.selectFirst(".manga-name") ?: div.selectFirst(".post-title"))?.text().orEmpty(),
title = (summary?.selectFirst("h3, h4") ?: div.selectFirst(".manga-name, .post-title"))?.text()
.orEmpty(),
altTitle = null,
rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a ->
MangaTag(
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
@ -459,13 +550,19 @@ internal abstract class MadaraParser(
"div.description-summary div.summary__content, div.summary_content div.post-content_item > h5 + div, div.summary_content div.manga-excerpt, div.post-content div.manga-summary, div.post-content div.desc, div.c-page__content div.summary__content"
protected open val selectGenre = "div.genres-content a"
protected open val selectTestAsync = "div.listing-chapters_wrap"
protected open val selectState = ""
protected open val selectState =
"div.post-content_item:contains(Status), div.post-content_item:contains(Statut), " +
"div.post-content_item:contains(État), div.post-content_item:contains(حالة العمل), div.post-content_item:contains(Estado), div.post-content_item:contains(สถานะ)," +
"div.post-content_item:contains(Stato), div.post-content_item:contains(Durum), div.post-content_item:contains(Statüsü), div.post-content_item:contains(Статус)," +
"div.post-content_item:contains(状态), div.post-content_item:contains(الحالة)"
protected open val selectAlt =
".post-content_item:contains(Alt) .summary-content, .post-content_item:contains(Nomes alternativos: ) .summary-content"
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
val fullUrl = manga.url.toAbsoluteUrl(domain)
val doc = webClient.httpGet(fullUrl).parseHtml()
val body = doc.body()
val testCheckAsync = body.select(selectTestAsync)
val testCheckAsync = doc.select(selectTestAsync)
val chaptersDeferred = if (testCheckAsync.isNullOrEmpty()) {
async { loadChapters(manga.url, doc) }
@ -473,25 +570,9 @@ internal abstract class MadaraParser(
async { getChapters(manga, doc) }
}
val desc = body.select(selectDesc).html()
val stateDiv = if (selectState.isEmpty()) {
(body.selectFirst("div.post-content_item:contains(Status)")
?: body.selectFirst("div.post-content_item:contains(Statut)")
?: body.selectFirst("div.post-content_item:contains(État)")
?: body.selectFirst("div.post-content_item:contains(حالة العمل)")
?: body.selectFirst("div.post-content_item:contains(Estado)")
?: body.selectFirst("div.post-content_item:contains(สถานะ)")
?: body.selectFirst("div.post-content_item:contains(Stato)")
?: body.selectFirst("div.post-content_item:contains(Durum)")
?: body.selectFirst("div.post-content_item:contains(Statüsü)")
?: body.selectFirst("div.post-content_item:contains(Статус)")
?: body.selectFirst("div.post-content_item:contains(状态)")
?: body.selectFirst("div.post-content_item:contains(الحالة)"))?.selectLast("div.summary-content")
} else {
body.selectFirst(selectState)
}
val desc = doc.select(selectDesc).html()
val stateDiv = doc.selectFirst(selectState)?.selectLast("div.summary-content")
val state = stateDiv?.let {
when (it.text()) {
@ -503,10 +584,7 @@ internal abstract class MadaraParser(
}
}
val alt =
doc.body().select(".post-content_item:contains(Alt) .summary-content").firstOrNull()?.tableValue()?.text()
?.trim() ?: doc.body().select(".post-content_item:contains(Nomes alternativos: ) .summary-content")
.firstOrNull()?.tableValue()?.text()?.trim()
val alt = doc.body().select(selectAlt).firstOrNull()?.tableValue()?.text()?.trim()
manga.copy(
tags = doc.body().select(selectGenre).mapNotNullToSet { a ->
@ -807,14 +885,10 @@ internal abstract class MadaraParser(
}
}
private val ratingRequest =
"action=madara_load_more&page=1&template=madara-core%2Fcontent%2Fcontent-search&vars%5Bs%5D=&vars%5Borderby%5D%5Bquery_avarage_reviews%5D=DESC&vars%5Borderby%5D%5Bquery_total_reviews%5D=DESC&vars%5Bpaged%5D=1&vars%5Btemplate%5D=search&vars%5Bmeta_query%5D%5B0%5D%5Brelation%5D=AND&vars%5Bmeta_query%5D%5B0%5D%5Bquery_avarage_reviews%5D%5Bkey%5D=_manga_avarage_reviews&vars%5Bmeta_query%5D%5B0%5D%5Bquery_total_reviews%5D%5Bkey%5D=_manga_total_votes&vars%5Bmeta_query%5D%5Brelation%5D=AND&vars%5Bpost_type%5D=wp-manga&vars%5Bpost_status%5D=publish&vars%5Bmanga_archives_item_layout%5D=default&vars%5Bmeta_query%5D%5B0%5D%5B0%5D%5Bkey%5D=_wp_manga_status&vars%5Bmeta_query%5D%5B0%5D%5B0%5D%5Bcompare%5D=IN"
private val defaultRequest =
"action=madara_load_more&page=1&template=madara-core%2Fcontent%2Fcontent-search&vars%5Bs%5D=&vars%5Borderby%5D=meta_value_num&vars%5Bpaged%5D=1&vars%5Btemplate%5D=search&vars%5Bmeta_query%5D%5B0%5D%5Brelation%5D=AND&vars%5Bmeta_query%5D%5Brelation%5D=OR&vars%5Bpost_type%5D=wp-manga&vars%5Bpost_status%5D=publish&vars%5Bmeta_key%5D=_latest_update&vars%5Border%5D=desc&vars%5Bmanga_archives_item_layout%5D=default&vars%5Bmeta_query%5D%5B0%5D%5B0%5D%5Bkey%5D=_wp_manga_status&vars%5Bmeta_query%5D%5B0%5D%5B0%5D%5Bcompare%5D=IN"
private companion object {
private fun createRequestTemplate(query: String) =
(query).split(
private fun createRequestTemplate() =
("action=madara_load_more&page=0&template=madara-core%2Fcontent%2Fcontent-search&vars%5Bs%5D=&vars%5Bpaged%5D=1&vars%5Btemplate%5D=search&vars%5Bmeta_query%5D%5B0%5D%5Brelation%5D=AND&vars%5Bmeta_query%5D%5Brelation%5D=AND&vars%5Bpost_type%5D=wp-manga&vars%5Bpost_status%5D=publish&vars%5Bmanga_archives_item_layout%5D=default").split(
'&',
).map {
val pos = it.indexOf('=')
@ -826,6 +900,5 @@ internal abstract class MadaraParser(
return chunked(2).map { it.toInt(16).toByte() }.toByteArray()
}
}
}

@ -7,7 +7,6 @@ import org.koitharu.kotatsu.parsers.model.ContentType
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaChapter
import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
import org.koitharu.kotatsu.parsers.util.attrAsRelativeUrl
import org.koitharu.kotatsu.parsers.util.generateUid
@ -21,10 +20,6 @@ internal class Ero18x(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.ERO18X, "ero18x.com", 10) {
override val datePattern = "MM/dd"
override val sourceLocale: Locale = Locale.ENGLISH
override val withoutAjax = true
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
override suspend fun getChapters(manga: Manga, doc: Document): List<MangaChapter> {
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
return doc.body().select(selectChapter).mapChapters(reversed = true) { i, li ->

@ -15,6 +15,7 @@ internal class Manhwa18Cc(context: MangaLoaderContext) :
override val listUrl = "webtoons/"
override val tagPrefix = "webtoon-genre/"
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
override val selectTestAsync = "ul.row-content-chapter"

@ -7,23 +7,17 @@ import org.koitharu.kotatsu.parsers.model.ContentType
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaChapter
import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
import org.koitharu.kotatsu.parsers.util.attrAsRelativeUrlOrNull
import org.koitharu.kotatsu.parsers.util.generateUid
import org.koitharu.kotatsu.parsers.util.mapChapters
import org.koitharu.kotatsu.parsers.util.parseFailed
import java.text.SimpleDateFormat
import java.util.EnumSet
@MangaSourceParser("MANHWARAW", "ManhwaRaw", "", ContentType.HENTAI)
internal class ManhwaRaw(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.MANHWARAW, "manhwa-raw.com", 10) {
override val datePattern = "MM/dd"
override val withoutAjax = true
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
override suspend fun getChapters(manga: Manga, doc: Document): List<MangaChapter> {
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
return doc.body().select(selectChapter).mapChapters(reversed = true) { i, li ->

@ -14,6 +14,7 @@ internal class GateManga(context: MangaLoaderContext) :
override val datePattern = "d MMMM، yyyy"
override val listUrl = "ar/"
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)

@ -25,6 +25,7 @@ internal class AdultWebtoon(context: MangaLoaderContext) :
override val listUrl = "adult-webtoon/"
override val postReq = true
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)

@ -11,6 +11,7 @@ import java.util.EnumSet
internal class BestManhuaCom(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.BESTMANHUACOM, "bestmanhua.com", 10) {
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)

@ -14,6 +14,7 @@ import java.util.EnumSet
internal class Hentai3z(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.HENTAI3Z, "manga18h.xyz", pageSize = 20) {
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)

@ -15,6 +15,7 @@ internal class Hentai4Free(context: MangaLoaderContext) :
override val tagPrefix = "hentai-tag/"
override val listUrl = ""
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
override val datePattern = "MMMM dd, yyyy"

@ -23,6 +23,7 @@ internal class HentaiManga(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.HENTAIMANGA, "hentaimanga.me", 36) {
override val postReq = true
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
override val availableStates: Set<MangaState> = emptySet()

@ -23,6 +23,7 @@ internal class HentaiWebtoon(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.HENTAIWEBTOON, "hentaiwebtoon.com") {
override val postReq = true
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
override val availableStates: Set<MangaState> = emptySet()

@ -3,16 +3,11 @@ package org.koitharu.kotatsu.parsers.site.madara.en
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
import java.util.EnumSet
@MangaSourceParser("HUNTERSSCANEN", "EnHuntersScan", "en")
internal class HuntersScanEn(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.HUNTERSSCANEN, "en.huntersscan.xyz") {
override val withoutAjax = true
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
override val datePattern = "MM/dd/yyyy"
override val tagPrefix = "series-genre/"
override val listUrl = "manga/"

@ -13,6 +13,7 @@ internal class IsekaiScanEuParser(context: MangaLoaderContext) :
override val datePattern = "MM/dd/yyyy"
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
override val listUrl = "mangax/"

@ -14,6 +14,7 @@ import java.util.EnumSet
internal class Manga1k(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.MANGA1K, "manga1k.com", 20) {
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
}

@ -13,6 +13,7 @@ import java.util.EnumSet
internal class Manga68(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.MANGA68, "manga68.com") {
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
}

@ -17,6 +17,7 @@ internal class MangaDass(context: MangaLoaderContext) :
override val datePattern = "dd MMM yyyy"
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
override val selectChapter = "li.a-h"

@ -17,6 +17,7 @@ internal class MangaDna(context: MangaLoaderContext) :
override val datePattern = "dd MMM yyyy"
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
override val selectDesc = "div.dsct"

@ -14,6 +14,7 @@ internal class MangaEffect(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.MANGAEFFECT, "mangaeffect.com") {
override val datePattern = "dd.MM.yyyy"
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
}

@ -11,6 +11,7 @@ import java.util.EnumSet
internal class MangaFastNet(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.MANGAFASTNET, "manhuafast.net") {
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
}

@ -3,16 +3,11 @@ package org.koitharu.kotatsu.parsers.site.madara.en
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
import java.util.EnumSet
@MangaSourceParser("MANGAREAD", "MangaRead", "en")
internal class MangaRead(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.MANGAREAD, "www.mangaread.org") {
override val tagPrefix = "genres/"
override val datePattern = "dd.MM.yyyy"
override val withoutAjax = true
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
}

@ -13,6 +13,7 @@ import java.util.EnumSet
internal class Mangaus(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.MANGAUS, "mangaus.xyz") {
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
}

@ -16,6 +16,7 @@ internal class Manhuaplus(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.MANHUAPLUS, "manhuaplus.com") {
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)

@ -11,6 +11,7 @@ import java.util.EnumSet
internal class Manhuauss(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.MANHUAUSS, "manhuauss.com") {
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
}

@ -23,6 +23,7 @@ internal class ManhwaHentai(context: MangaLoaderContext) :
override val tagPrefix = "webtoon-genre/"
override val listUrl = "webtoon/"
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
override val postReq = true

@ -14,6 +14,7 @@ internal class Manhwaz(context: MangaLoaderContext) :
override val listUrl = "genre/manhwa"
override val tagPrefix = "genre/"
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val selectTestAsync = "div.list-chapter"
override val availableStates: Set<MangaState> = emptySet()

@ -24,6 +24,7 @@ internal class ManyToon(context: MangaLoaderContext) :
override val listUrl = "comic/"
override val postReq = true
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)

@ -15,6 +15,7 @@ internal class MmScans(context: MangaLoaderContext) :
override val selectChapter = "li.chapter-li"
override val selectDesc = "div.summary-text"
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
}

@ -3,16 +3,11 @@ package org.koitharu.kotatsu.parsers.site.madara.en
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
import java.util.EnumSet
@MangaSourceParser("MURIMSCAN", "InkReads", "en")
internal class MurimScan(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.MURIMSCAN, "inkreads.com", 100) {
override val withoutAjax = true
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
override val postReq = true
override val listUrl = "mangax/"
}

@ -15,6 +15,7 @@ internal class ToonGod(context: MangaLoaderContext) :
override val tagPrefix = "webtoon-genre/"
override val datePattern = "d MMM yyyy"
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
}

@ -12,6 +12,7 @@ internal class Zinmanga(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.ZINMANGA, "zinmanga.net") {
override val datePattern = "MM/dd/yyyy"
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
}

@ -6,24 +6,17 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaChapter
import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
import org.koitharu.kotatsu.parsers.util.attrAsRelativeUrl
import org.koitharu.kotatsu.parsers.util.generateUid
import org.koitharu.kotatsu.parsers.util.mapChapters
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
import java.text.SimpleDateFormat
import java.util.EnumSet
@MangaSourceParser("MANHWA_ES", "Manhwa-Es", "es")
internal class ManhwaEs(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.MANHWA_ES, "manhwa-es.com", 10) {
override val withoutAjax = true
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
override val datePattern = "MM/dd"
override suspend fun getChapters(manga: Manga, doc: Document): List<MangaChapter> {
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
return doc.body().select(selectChapter).mapChapters(reversed = true) { i, li ->

@ -7,20 +7,14 @@ import org.koitharu.kotatsu.parsers.model.ContentType
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaChapter
import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
import org.koitharu.kotatsu.parsers.util.*
import java.text.SimpleDateFormat
import java.util.EnumSet
@MangaSourceParser("MANHWALATINO", "ManhwaLatino", "es", ContentType.HENTAI)
internal class ManhwaLatino(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.MANHWALATINO, "manhwa-latino.com", 10) {
override val datePattern = "MM/dd"
override val withoutAjax = true
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
override val selectPage = "div.page-break img.wp-manga-chapter-img"
override suspend fun getChapters(manga: Manga, doc: Document): List<MangaChapter> {
val root2 = doc.body().selectFirstOrThrow("div.content-area")

@ -16,6 +16,7 @@ internal class TmoManga(context: MangaLoaderContext) :
override val listUrl = "biblioteca/"
override val selectGenre = "div.summary-content a.tags_manga"
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.POPULARITY)
override val availableStates: Set<MangaState> = emptySet()
override val availableContentRating: Set<ContentRating> = emptySet()

@ -4,14 +4,8 @@ import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.ContentType
import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
import java.util.EnumSet
@MangaSourceParser("VERMANHWA", "Vermanhwa", "es", ContentType.HENTAI)
internal class Vermanhwa(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.VERMANHWA, "vermanhwa.com", 10) {
override val withoutAjax = true
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
}
MadaraParser(context, MangaParserSource.VERMANHWA, "vermanhwa.com", 10)

@ -14,6 +14,7 @@ import java.util.EnumSet
internal class Indo18h(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.INDO18H, "indo18h.com", 24) {
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
}

@ -15,6 +15,7 @@ internal class ManhwaHub(context: MangaLoaderContext) :
override val datePattern = "MMMM d, yyyy"
override val sourceLocale: Locale = Locale.ENGLISH
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val listUrl = "genre/manhwa"
override val selectTestAsync = "ul.box-list-chapter"
override val availableStates: Set<MangaState> = emptySet()

@ -14,6 +14,7 @@ internal class AncientComics(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.ANCIENTCOMICS, "ancientcomics.com.br") {
override val datePattern: String = "dd/MM/yyyy"
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
}

@ -12,6 +12,7 @@ internal class Atemporal(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.ATEMPORAL, "atemporal.cloud") {
override val datePattern: String = "d 'de' MMMM 'de' yyyy"
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
}

@ -12,6 +12,7 @@ internal class GalinhaSamurai(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.GALINHASAMURAI, "galinhasamurai.com") {
override val datePattern = "dd/MM/yyyy"
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
}

@ -3,16 +3,11 @@ package org.koitharu.kotatsu.parsers.site.madara.pt
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
import java.util.EnumSet
@MangaSourceParser("HUNTERSSCAN", "HuntersScan", "pt")
internal class HuntersScan(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.HUNTERSSCAN, "hunterscomics.com", pageSize = 50) {
override val withoutAjax = true
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
override val datePattern = "MM/dd/yyyy"
override val tagPrefix = "series-genre/"
override val listUrl = "series/"

@ -12,6 +12,7 @@ internal class ImperiodaBritannia(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.IMPERIODABRITANNIA, "imperiodabritannia.com", 10) {
override val datePattern: String = "dd 'de' MMMMM 'de' yyyy"
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
}

@ -12,6 +12,7 @@ internal class Norterose(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.NORTEROSE, "norterose.com.br", 10) {
override val datePattern: String = "dd/MM/yyyy"
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
}

@ -4,14 +4,9 @@ import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.ContentType
import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
import java.util.EnumSet
@MangaSourceParser("CAT_300", "Cat300", "th", ContentType.HENTAI)
internal class Cat300(context: MangaLoaderContext) : MadaraParser(context, MangaParserSource.CAT_300, "cat300.net") {
override val datePattern = "MMMM dd, yyyy"
override val withoutAjax = true
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
}

@ -12,6 +12,7 @@ import java.util.EnumSet
internal class Doujinza(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.DOUJINZA, "doujinza.com", 24) {
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
override val datePattern = "MMMM dd, yyyy"

@ -3,16 +3,11 @@ package org.koitharu.kotatsu.parsers.site.madara.tr
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
import java.util.EnumSet
@MangaSourceParser("RUYAMANGA", "RuyaManga", "tr")
internal class RuyaManga(context: MangaLoaderContext) :
MadaraParser(context, MangaParserSource.RUYAMANGA, "www.ruya-manga.com", 18) {
override val tagPrefix = "manga-kategori/"
override val datePattern = "dd/MM/yyyy"
override val withoutAjax = true
override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.NEWEST, SortOrder.ALPHABETICAL, SortOrder.RATING)
}

@ -17,6 +17,7 @@ internal class Saytruyenhay(context: MangaLoaderContext) :
override val tagPrefix = "genre/"
override val withoutAjax = true
override val isTagsExclusionSupported = false
override val listUrl = "public/genre/manga/"
override val availableStates: Set<MangaState> = emptySet()
override val availableContentRating: Set<ContentRating> = emptySet()

Loading…
Cancel
Save