Merge branch 'KotatsuApp:master' into master

pull/421/head
Deivid Gabriel Pereira de Oliveira 2 years ago committed by GitHub
commit d4e9a03081
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -35,7 +35,7 @@ internal class BatoToParser(context: MangaLoaderContext) : PagedMangaParser(
override val availableStates: Set<MangaState> = EnumSet.allOf(MangaState::class.java) override val availableStates: Set<MangaState> = EnumSet.allOf(MangaState::class.java)
override val isTagsExclusionSupported = true override val isTagsExclusionSupported: Boolean = true
override val availableContentRating: Set<ContentRating> = EnumSet.of(ContentRating.SAFE) override val availableContentRating: Set<ContentRating> = EnumSet.of(ContentRating.SAFE)
@ -185,7 +185,7 @@ internal class BatoToParser(context: MangaLoaderContext) : PagedMangaParser(
val scripts = webClient.httpGet(fullUrl).parseHtml().select("script") val scripts = webClient.httpGet(fullUrl).parseHtml().select("script")
for (script in scripts) { for (script in scripts) {
val scriptSrc = script.html() val scriptSrc = script.html()
val p = scriptSrc.indexOf("const imgHttpLis =") val p = scriptSrc.indexOf("const imgHttps =")
if (p == -1) continue if (p == -1) continue
val start = scriptSrc.indexOf('[', p) val start = scriptSrc.indexOf('[', p)
val end = scriptSrc.indexOf(';', start) val end = scriptSrc.indexOf(';', start)

@ -187,7 +187,14 @@ internal class ComickFunParser(context: MangaLoaderContext) : PagedMangaParser(c
val chap = jo.getStringOrNull("chap") val chap = jo.getStringOrNull("chap")
val locale = Locale.forLanguageTag(jo.getString("lang")) val locale = Locale.forLanguageTag(jo.getString("lang"))
val group = jo.optJSONArray("group_name")?.joinToString(", ") val group = jo.optJSONArray("group_name")?.joinToString(", ")
val branch = locale.getDisplayName(locale).toTitleCase(locale) + " (" + group + ")" val branch = buildString {
append(locale.getDisplayName(locale).toTitleCase(locale))
if (!group.isNullOrEmpty()) {
append(" (")
append(group)
append(')')
}
}
MangaChapter( MangaChapter(
id = generateUid(jo.getLong("id")), id = generateUid(jo.getLong("id")),
name = buildString { name = buildString {

@ -35,7 +35,7 @@ internal class MangaDexParser(context: MangaLoaderContext) : MangaParser(context
override val availableStates: Set<MangaState> = override val availableStates: Set<MangaState> =
EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.PAUSED, MangaState.ABANDONED) EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.PAUSED, MangaState.ABANDONED)
override val isTagsExclusionSupported = true override val isTagsExclusionSupported: Boolean = true
override suspend fun getList(offset: Int, filter: MangaListFilter?): List<Manga> { override suspend fun getList(offset: Int, filter: MangaListFilter?): List<Manga> {

@ -22,7 +22,7 @@ internal class MangaPark(context: MangaLoaderContext) :
override val availableContentRating: Set<ContentRating> = EnumSet.of(ContentRating.SAFE) override val availableContentRating: Set<ContentRating> = EnumSet.of(ContentRating.SAFE)
override val isTagsExclusionSupported = true override val isTagsExclusionSupported: Boolean = true
override val configKeyDomain = ConfigKey.Domain("mangapark.net") override val configKeyDomain = ConfigKey.Domain("mangapark.net")

@ -40,6 +40,8 @@ internal abstract class NineMangaParser(
MangaState.FINISHED, MangaState.FINISHED,
) )
override val isTagsExclusionSupported: Boolean = true
override fun intercept(chain: Interceptor.Chain): Response { override fun intercept(chain: Interceptor.Chain): Response {
val request = chain.request() val request = chain.request()
val newRequest = if (request.url.host == domain) { val newRequest = if (request.url.host == domain) {
@ -64,12 +66,13 @@ internal abstract class NineMangaParser(
} }
is MangaListFilter.Advanced -> { is MangaListFilter.Advanced -> {
if (filter.tags.isNotEmpty()) {
if (filter.tags.isNotEmpty() || filter.tagsExclude.isNotEmpty() || filter.states.isNotEmpty()) {
append("/search/?category_id=") append("/search/?category_id=")
for (tag in filter.tags) { append(filter.tags.joinToString(separator = ",") { it.key })
append(tag.key)
append(',') append("&out_category_id=")
} append(filter.tagsExclude.joinToString(separator = ",") { it.key })
filter.states.oneOrThrowIfMany()?.let { filter.states.oneOrThrowIfMany()?.let {
append("&completed_series=") append("&completed_series=")
@ -81,20 +84,9 @@ internal abstract class NineMangaParser(
} }
append("&page=") append("&page=")
} else { } else {
append("/category/") append("/category/index_")
if (filter.states.isNotEmpty()) {
filter.states.oneOrThrowIfMany()?.let {
when (it) {
MangaState.ONGOING -> append("updated_")
MangaState.FINISHED -> append("completed_")
else -> append("either")
}
}
} else {
append("index_")
}
} }
append(page) append(page.toString())
append(".html") append(".html")
} }

@ -20,6 +20,7 @@ internal class FlixScans(context: MangaLoaderContext) : PagedMangaParser(context
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val availableStates: Set<MangaState> = EnumSet.allOf(MangaState::class.java) override val availableStates: Set<MangaState> = EnumSet.allOf(MangaState::class.java)
override val availableContentRating: Set<ContentRating> = EnumSet.of(ContentRating.ADULT)
override val configKeyDomain = ConfigKey.Domain("flixscans.com") override val configKeyDomain = ConfigKey.Domain("flixscans.com")
override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> { override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
@ -40,7 +41,7 @@ internal class FlixScans(context: MangaLoaderContext) : PagedMangaParser(context
append("https://api.") append("https://api.")
append(domain) append(domain)
append("/api/v1/") append("/api/v1/")
if (filter.tags.isNotEmpty() || filter.states.isNotEmpty()) { if (filter.tags.isNotEmpty() || filter.states.isNotEmpty() || filter.contentRating.isNotEmpty()) {
if (page > 1) { if (page > 1) {
return emptyList() return emptyList()
} }
@ -64,6 +65,16 @@ internal class FlixScans(context: MangaLoaderContext) : PagedMangaParser(context
) )
} }
} }
filter.contentRating.oneOrThrowIfMany()?.let {
append("&adult=")
append(
when (it) {
ContentRating.ADULT -> "true"
else -> ""
},
)
}
append("&serie_type=webtoon") append("&serie_type=webtoon")
} else { } else {

@ -20,7 +20,7 @@ internal class TeamXNovel(context: MangaLoaderContext) : PagedMangaParser(contex
override val availableStates: Set<MangaState> = override val availableStates: Set<MangaState> =
EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.ABANDONED) EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.ABANDONED)
override val configKeyDomain = ConfigKey.Domain("team11x11.fun") override val configKeyDomain = ConfigKey.Domain("team1x12.com")
override val isMultipleTagsSupported = false override val isMultipleTagsSupported = false
override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> { override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {

@ -1,6 +1,8 @@
package org.koitharu.kotatsu.parsers.site.en package org.koitharu.kotatsu.parsers.site.en
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
import org.json.JSONArray
import org.koitharu.kotatsu.parsers.ErrorMessages import org.koitharu.kotatsu.parsers.ErrorMessages
import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.MangaSourceParser
@ -9,7 +11,7 @@ import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.* import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.json.mapJSON import org.koitharu.kotatsu.parsers.util.json.mapJSON
import java.text.DateFormat import org.koitharu.kotatsu.parsers.util.json.toJSONList
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
@ -18,6 +20,7 @@ internal class FlixScansOrg(context: MangaLoaderContext) : PagedMangaParser(cont
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val availableStates: Set<MangaState> = EnumSet.allOf(MangaState::class.java) override val availableStates: Set<MangaState> = EnumSet.allOf(MangaState::class.java)
override val availableContentRating: Set<ContentRating> = EnumSet.of(ContentRating.ADULT)
override val configKeyDomain = ConfigKey.Domain("flixscans.org") override val configKeyDomain = ConfigKey.Domain("flixscans.org")
override val isSearchSupported = false override val isSearchSupported = false
@ -29,17 +32,45 @@ internal class FlixScansOrg(context: MangaLoaderContext) : PagedMangaParser(cont
} }
is MangaListFilter.Advanced -> { is MangaListFilter.Advanced -> {
val url = buildString { val url = buildString {
append("https://api.") append("https://api.")
append(domain) append(domain)
append("/api/v1/webtoon/homepage/latest/home?page=") append("/api/v1/search/advance?=&serie_type=webtoon&page=")
append(page.toString()) append(page.toString())
append("&genres=")
append(filter.tags.joinToString(separator = ",") { it.key })
filter.states.oneOrThrowIfMany()?.let {
append("&status=")
append(
when (it) {
MangaState.ONGOING -> "ongoing"
MangaState.FINISHED -> "completed"
MangaState.ABANDONED -> "droped"
MangaState.PAUSED -> "onhold"
MangaState.UPCOMING -> "soon"
},
)
}
filter.contentRating.oneOrThrowIfMany()?.let {
append("&adult=")
append(
when (it) {
ContentRating.ADULT -> "true"
else -> ""
},
)
}
append("&serie_type=webtoon")
} }
webClient.httpGet(url).parseJson().getJSONArray("data") webClient.httpGet(url).parseJson().getJSONArray("data")
} }
null -> { null -> {
val url = "https://api.$domain/api/v1/webtoon/homepage/latest/home?page=$page" val url = "https://api.$domain/api/v1/search/advance?=&serie_type=webtoon&page=$page"
webClient.httpGet(url).parseJson().getJSONArray("data") webClient.httpGet(url).parseJson().getJSONArray("data")
} }
} }
@ -69,80 +100,100 @@ internal class FlixScansOrg(context: MangaLoaderContext) : PagedMangaParser(cont
} }
} }
override suspend fun getAvailableTags(): Set<MangaTag> = emptySet() 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(",")
return tagsList.mapNotNullToSet { idTag ->
val id = idTag.toInt()
val idKey = json.getJSONObject(id).getInt("id")
val key = json.getInt(idKey).toString()
val idName = json.getJSONObject(id).getInt("name")
val name = json.getString(idName)
MangaTag(
key = key,
title = name,
source = source,
)
}
}
override suspend fun getDetails(manga: Manga): Manga = coroutineScope { override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml() val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
val dateFormat = SimpleDateFormat("dd/MM/yyyy", sourceLocale) val chaptersDeferred = async { loadChapters(manga.url) }
val json = JSONArray(doc.requireElementById("__NUXT_DATA__").data())
val descId = json.getJSONObject(6).getInt("story")
val desc = json.getString(descId)
val tagsId = json.getJSONObject(6).getInt("genres")
val tagsList = json.getJSONArray(tagsId).toString().replace("[", "").replace("]", "").split(",")
val ratingId = json.getJSONObject(6).getInt("rating")
val rating = json.getString(ratingId)
val nsfwId = json.getJSONObject(6).getInt("nsfw")
val nsfw = json.getBoolean(nsfwId)
manga.copy( manga.copy(
description = doc.selectFirst("div.text-base")?.text(), description = desc,
author = doc.selectFirst("div.gap-1:contains(Authors) span.MuiChip-label")?.text(), tags = tagsList.mapToSet { idTag ->
altTitle = doc.select("div.gap-1:contains(Other names) span.MuiChip-label") val id = idTag.toInt()
.joinToString(" / ") { it.text() }, val idKey = json.getJSONObject(id).getInt("id")
chapters = doc.select("div.nox-scrollbar a").mapChapters(reversed = true) { i, a -> val key = json.get(idKey).toString()
val url = a.attrAsRelativeUrl("href") val idName = json.getJSONObject(id).getInt("name")
val name = a.selectFirstOrThrow("div.font-medium").text() val name = json.get(idName).toString()
val dateText = a.selectLastOrThrow("div").text() MangaTag(
MangaChapter( key = key,
id = generateUid(url), title = name,
url = url,
name = name,
number = i + 1,
branch = null,
uploadDate = parseChapterDate(
dateFormat,
dateText,
),
scanlator = null,
source = source, source = source,
) )
}, },
rating = rating?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
isNsfw = nsfw,
chapters = chaptersDeferred.await(),
) )
} }
private fun parseChapterDate(dateFormat: DateFormat, date: String?): Long { private val dateFormat = SimpleDateFormat("yyyy-MM-dd", sourceLocale)
val d = date?.lowercase() ?: return 0
return when {
d.endsWith(" ago") -> parseRelativeDate(date)
else -> dateFormat.tryParse(date)
}
}
private fun parseRelativeDate(date: String): Long { private suspend fun loadChapters(baseUrl: String): List<MangaChapter> {
val number = Regex("""(\d+)""").find(date)?.value?.toIntOrNull() ?: return 0 val key = baseUrl.substringAfter("-").substringBefore("-")
val cal = Calendar.getInstance() val seriesKey = baseUrl.substringAfterLast("/").substringBefore("-")
return when { val json = JSONArray(
WordSet("second").anyWordIn(date) -> cal.apply { add(Calendar.SECOND, -number) }.timeInMillis webClient.httpGet("https://api.$domain/api/v1/webtoon/chapters/$key-desc").parseRaw(),
WordSet("minute", "minutes", "mins", "min").anyWordIn(date) -> cal.apply { ).toJSONList().reversed()
add( return json.mapChapters { i, j ->
Calendar.MINUTE, val url = "https://$domain/read/webtoon/$seriesKey-${j.getString("id")}-${j.getString("slug")}"
-number, val date = j.getString("createdAt").substringBeforeLast("T")
MangaChapter(
id = generateUid(url),
url = url,
name = j.getString("slug").replace('-', ' '),
number = i + 1,
branch = null,
uploadDate = dateFormat.tryParse(date),
scanlator = null,
source = source,
) )
}.timeInMillis
WordSet("hour", "hours").anyWordIn(date) -> cal.apply { add(Calendar.HOUR, -number) }.timeInMillis
WordSet("day", "days").anyWordIn(date) -> cal.apply { add(Calendar.DAY_OF_MONTH, -number) }.timeInMillis
WordSet("week", "weeks").anyWordIn(date) -> cal.apply { add(Calendar.WEEK_OF_YEAR, -number) }.timeInMillis
WordSet("month", "months").anyWordIn(date) -> cal.apply { add(Calendar.MONTH, -number) }.timeInMillis
WordSet("year").anyWordIn(date) -> cal.apply { add(Calendar.YEAR, -number) }.timeInMillis
else -> 0
} }
} }
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> { override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
val fullUrl = chapter.url.toAbsoluteUrl(domain) val fullUrl = chapter.url.toAbsoluteUrl(domain)
val doc = webClient.httpGet(fullUrl).parseHtml() val doc = webClient.httpGet(fullUrl).parseHtml()
val urls = doc.selectFirstOrThrow("script:containsData(chapterData)").data().replace("\\", "") val json = JSONArray(doc.requireElementById("__NUXT_DATA__").data())
.substringAfterLast("\"webtoon\":[\"").substringBeforeLast("\"]").split("\",\"") val chapterData = json.getJSONObject(6).getInt("chapterData")
return urls.map { url -> val pageLocate = json.getJSONObject(chapterData).getInt("webtoon")
val urlImg = "https://media.$domain/$url" val jsonPages = json.getJSONArray(pageLocate)
val pages = ArrayList<MangaPage>(jsonPages.length())
for (i in 0 until jsonPages.length()) {
val id = jsonPages.getInt(i)
val url = "https://media.$domain/" + json.getString(id)
pages.add(
MangaPage( MangaPage(
id = generateUid(urlImg), id = generateUid(url),
url = urlImg, url = url,
preview = null, preview = null,
source = source, source = source,
),
) )
} }
return pages
} }
} }

@ -30,6 +30,8 @@ class Manhwa18Parser(context: MangaLoaderContext) :
MangaState.PAUSED, MangaState.PAUSED,
) )
override val isTagsExclusionSupported = true
private val tagsMap = SuspendLazy(::parseTags) private val tagsMap = SuspendLazy(::parseTags)
override suspend fun getFavicons(): Favicons { override suspend fun getFavicons(): Favicons {
@ -64,6 +66,13 @@ class Manhwa18Parser(context: MangaLoaderContext) :
) )
} }
append("&reject_genres=")
if (filter.tagsExclude.isNotEmpty()) {
append(
filter.tagsExclude.joinToString(",") { it.key },
)
}
append("&sort=") append("&sort=")
append( append(
when (filter.sortOrder) { when (filter.sortOrder) {

@ -24,6 +24,8 @@ class TuMangaOnlineParser(context: MangaLoaderContext) : PagedMangaParser(
private val chapterDateFormat = SimpleDateFormat("yyyy-MM-dd", sourceLocale) private val chapterDateFormat = SimpleDateFormat("yyyy-MM-dd", sourceLocale)
override val availableContentRating: Set<ContentRating> = EnumSet.of(ContentRating.SAFE, ContentRating.ADULT)
override val availableSortOrders: Set<SortOrder> = EnumSet.of( override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.ALPHABETICAL, SortOrder.ALPHABETICAL,
SortOrder.ALPHABETICAL_DESC, SortOrder.ALPHABETICAL_DESC,
@ -64,6 +66,17 @@ class TuMangaOnlineParser(context: MangaLoaderContext) : PagedMangaParser(
append(tag.key) append(tag.key)
} }
} }
filter.contentRating.oneOrThrowIfMany()?.let {
append("&erotic=")
append(
when (it) {
ContentRating.SAFE -> "false"
ContentRating.ADULT -> "true"
else -> ""
},
)
}
} }
null -> { null -> {

@ -34,6 +34,8 @@ internal abstract class FmreaderParser(
MangaState.ABANDONED, MangaState.ABANDONED,
) )
override val isTagsExclusionSupported = true
protected open val listUrl = "/manga-list.html" protected open val listUrl = "/manga-list.html"
protected open val datePattern = "MMMM d, yyyy" protected open val datePattern = "MMMM d, yyyy"
protected open val tagPrefix = "manga-list-genre-" protected open val tagPrefix = "manga-list-genre-"
@ -81,6 +83,9 @@ internal abstract class FmreaderParser(
append("&genre=") append("&genre=")
append(filter.tags.joinToString(",") { it.key }) append(filter.tags.joinToString(",") { it.key })
append("&ungenre=")
append(filter.tagsExclude.joinToString(",") { it.key })
append("&sort=") append("&sort=")
when (filter.sortOrder) { when (filter.sortOrder) {

@ -38,11 +38,10 @@ internal class Manhwa18Com(context: MangaLoaderContext) :
is MangaListFilter.Advanced -> { is MangaListFilter.Advanced -> {
append("&accept_genres=") append("&accept_genres=")
if (filter.tags.isNotEmpty()) { append(filter.tags.joinToString(",") { it.key })
append(
filter.tags.joinToString(",") { it.key }, append("&reject_genres=")
) append(filter.tagsExclude.joinToString(",") { it.key })
}
append("&sort=") append("&sort=")
append( append(

@ -15,6 +15,7 @@ internal class OlimpoScans(context: MangaLoaderContext) :
override val selectTag = "ul.manga-info li:contains(Género) a" override val selectTag = "ul.manga-info li:contains(Género) a"
override val tagPrefix = "lista-de-comics-genero-" override val tagPrefix = "lista-de-comics-genero-"
override val isMultipleTagsSupported = false override val isMultipleTagsSupported = false
override val isTagsExclusionSupported = false
override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> { override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
val url = buildString { val url = buildString {

@ -32,7 +32,7 @@ internal class BentomangaParser(context: MangaLoaderContext) : PagedMangaParser(
override val availableStates: Set<MangaState> = override val availableStates: Set<MangaState> =
EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.PAUSED, MangaState.ABANDONED) EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.PAUSED, MangaState.ABANDONED)
override val isTagsExclusionSupported = true override val isTagsExclusionSupported: Boolean = true
init { init {
paginator.firstPage = 0 paginator.firstPage = 0

@ -19,6 +19,9 @@ internal class LegacyScansParser(context: MangaLoaderContext) :
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.POPULARITY) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.POPULARITY)
override val availableStates: Set<MangaState> =
EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.ABANDONED, MangaState.PAUSED)
override val configKeyDomain = ConfigKey.Domain("legacy-scans.com") override val configKeyDomain = ConfigKey.Domain("legacy-scans.com")
override val headers: Headers = Headers.Builder() override val headers: Headers = Headers.Builder()
@ -45,7 +48,19 @@ internal class LegacyScansParser(context: MangaLoaderContext) :
val url = buildString { val url = buildString {
append("https://api.") append("https://api.")
append(domain) append(domain)
append("/misc/comic/search/query?status=&order=&genreNames=") append("/misc/comic/search/query?status=")
filter.states.oneOrThrowIfMany()?.let {
append(
when (it) {
MangaState.ONGOING -> "En cours"
MangaState.FINISHED -> "Terminé"
MangaState.ABANDONED -> "Abandonné"
MangaState.PAUSED -> "En pause"
else -> ""
},
)
}
append("&order=&genreNames=")
append(filter.tags.joinToString(",") { it.key }) append(filter.tags.joinToString(",") { it.key })
append("&type=&start=") append("&type=&start=")
append(start) append(start)

@ -35,6 +35,8 @@ internal abstract class MadaraParser(
override val availableStates: Set<MangaState> = EnumSet.allOf(MangaState::class.java) override val availableStates: Set<MangaState> = EnumSet.allOf(MangaState::class.java)
override val availableContentRating: Set<ContentRating> = EnumSet.of(ContentRating.SAFE, ContentRating.ADULT)
protected open val tagPrefix = "manga-genre/" protected open val tagPrefix = "manga-genre/"
protected open val datePattern = "MMMM d, yyyy" protected open val datePattern = "MMMM d, yyyy"
protected open val stylePage = "?style=list" protected open val stylePage = "?style=list"
@ -215,6 +217,18 @@ internal abstract class MadaraParser(
MangaState.UPCOMING -> append("upcoming") MangaState.UPCOMING -> append("upcoming")
} }
} }
filter.contentRating.oneOrThrowIfMany()?.let {
append("&adult=")
append(
when (it) {
ContentRating.SAFE -> "0"
ContentRating.ADULT -> "1"
else -> ""
},
)
}
append("&") append("&")
} }
@ -279,6 +293,16 @@ internal abstract class MadaraParser(
MangaState.UPCOMING -> "upcoming" MangaState.UPCOMING -> "upcoming"
} }
} }
filter.contentRating.oneOrThrowIfMany()?.let {
payload["vars[meta_query][0][1][key]"] = "manga_adult_content"
payload["vars[meta_query][0][1][value]"] =
when (it) {
ContentRating.SAFE -> ""
ContentRating.ADULT -> "a%3A1%3A%7Bi%3A0%3Bs%3A3%3A%22yes%22%3B%7D"
else -> ""
}
}
} }
null -> { null -> {

@ -25,6 +25,8 @@ internal class Manga18Fx(context: MangaLoaderContext) :
searchPaginator.firstPage = 1 searchPaginator.firstPage = 1
} }
override val availableContentRating: Set<ContentRating> = emptySet()
override val availableStates: Set<MangaState> get() = emptySet() override val availableStates: Set<MangaState> get() = emptySet()
override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> { override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {

@ -26,6 +26,8 @@ internal class Manhwa18Cc(context: MangaLoaderContext) :
searchPaginator.firstPage = 1 searchPaginator.firstPage = 1
} }
override val availableContentRating: Set<ContentRating> = emptySet()
override val availableStates: Set<MangaState> get() = emptySet() override val availableStates: Set<MangaState> get() = emptySet()
override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> { override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {

@ -3,6 +3,7 @@ package org.koitharu.kotatsu.parsers.site.madara.en
import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.ContentRating
import org.koitharu.kotatsu.parsers.model.ContentType import org.koitharu.kotatsu.parsers.model.ContentType
import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaListFilter import org.koitharu.kotatsu.parsers.model.MangaListFilter
@ -23,8 +24,6 @@ internal class Hentai4Free(context: MangaLoaderContext) :
override val datePattern = "MMMM dd, yyyy" override val datePattern = "MMMM dd, yyyy"
override val selectGenre = "div.tags-content a" override val selectGenre = "div.tags-content a"
override val availableStates: Set<MangaState> get() = emptySet()
init { init {
paginator.firstPage = 1 paginator.firstPage = 1
searchPaginator.firstPage = 1 searchPaginator.firstPage = 1
@ -54,14 +53,41 @@ internal class Hentai4Free(context: MangaLoaderContext) :
append("page/") append("page/")
append(page.toString()) append(page.toString())
} }
append("/?")
} else { } else {
if (page > 1) { if (page > 1) {
append("/page/") append("/page/")
append(page.toString()) append(page.toString())
} }
append("/?s&post_type=wp-manga")
filter.contentRating.oneOrThrowIfMany()?.let {
append("&adult=")
append(
when (it) {
ContentRating.SAFE -> "0"
ContentRating.ADULT -> "1"
else -> ""
},
)
}
filter.states.forEach {
append("&status[]=")
when (it) {
MangaState.ONGOING -> append("on-going")
MangaState.FINISHED -> append("end")
MangaState.ABANDONED -> append("canceled")
MangaState.PAUSED -> append("on-hold")
MangaState.UPCOMING -> append("upcoming")
}
}
append("&")
} }
append("/?m_orderby=") append("m_orderby=")
when (filter.sortOrder) { when (filter.sortOrder) {
SortOrder.POPULARITY -> append("views") SortOrder.POPULARITY -> append("views")
SortOrder.UPDATED -> append("latest") SortOrder.UPDATED -> append("latest")
@ -70,6 +96,8 @@ internal class Hentai4Free(context: MangaLoaderContext) :
SortOrder.RATING -> append("rating") SortOrder.RATING -> append("rating")
else -> append("latest") else -> append("latest")
} }
} }
null -> { null -> {

@ -16,14 +16,13 @@ internal class InstaManhwa(context: MangaLoaderContext) :
override val listUrl = "latest/" override val listUrl = "latest/"
override val postReq = true override val postReq = true
override val datePattern = "d MMMM, yyyy" override val datePattern = "d MMMM, yyyy"
override val availableSortOrders: Set<SortOrder> = EnumSet.of( override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.ALPHABETICAL, SortOrder.ALPHABETICAL,
SortOrder.UPDATED, SortOrder.UPDATED,
SortOrder.NEWEST, SortOrder.NEWEST,
) )
override val availableStates: Set<MangaState> get() = emptySet() override val availableStates: Set<MangaState> get() = emptySet()
override val availableContentRating: Set<ContentRating> = emptySet()
init { init {
paginator.firstPage = 1 paginator.firstPage = 1

@ -16,13 +16,12 @@ internal class IsekaiScan(context: MangaLoaderContext) :
override val tagPrefix = "mangas/" override val tagPrefix = "mangas/"
override val listUrl = "latest-manga/" override val listUrl = "latest-manga/"
override val datePattern = "MMMM d, HH:mm" override val datePattern = "MMMM d, HH:mm"
override val availableSortOrders: Set<SortOrder> = EnumSet.of( override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.POPULARITY, SortOrder.POPULARITY,
SortOrder.UPDATED, SortOrder.UPDATED,
) )
override val availableContentRating: Set<ContentRating> = emptySet()
override val availableStates: Set<MangaState> get() = emptySet() override val availableStates: Set<MangaState> = emptySet()
init { init {
paginator.firstPage = 1 paginator.firstPage = 1

@ -64,6 +64,18 @@ internal class IsekaiScanEuParser(context: MangaLoaderContext) :
MangaState.UPCOMING -> append("upcoming") MangaState.UPCOMING -> append("upcoming")
} }
} }
filter.contentRating.oneOrThrowIfMany()?.let {
append("&adult=")
append(
when (it) {
ContentRating.SAFE -> "0"
ContentRating.ADULT -> "1"
else -> ""
},
)
}
append("&") append("&")
} }

@ -21,6 +21,8 @@ internal class MangaDass(context: MangaLoaderContext) :
override val availableStates: Set<MangaState> get() = emptySet() override val availableStates: Set<MangaState> get() = emptySet()
override val availableContentRating: Set<ContentRating> = emptySet()
init { init {
paginator.firstPage = 1 paginator.firstPage = 1
searchPaginator.firstPage = 1 searchPaginator.firstPage = 1

@ -18,7 +18,8 @@ internal class MangaDna(context: MangaLoaderContext) :
override val withoutAjax = true override val withoutAjax = true
override val selectDesc = "div.dsct" override val selectDesc = "div.dsct"
override val selectChapter = "li.a-h" override val selectChapter = "li.a-h"
override val availableStates: Set<MangaState> get() = emptySet() override val availableStates: Set<MangaState> = emptySet()
override val availableContentRating: Set<ContentRating> = emptySet()
override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> { override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
val url = buildString { val url = buildString {

@ -21,7 +21,9 @@ internal class MangaPure(context: MangaLoaderContext) :
SortOrder.UPDATED, SortOrder.UPDATED,
) )
override val availableStates: Set<MangaState> get() = emptySet() override val availableStates: Set<MangaState> = emptySet()
override val availableContentRating: Set<ContentRating> = emptySet()
init { init {
paginator.firstPage = 1 paginator.firstPage = 1

@ -16,7 +16,9 @@ internal class Manhwaz(context: MangaLoaderContext) :
override val withoutAjax = true override val withoutAjax = true
override val selectTestAsync = "div.list-chapter" override val selectTestAsync = "div.list-chapter"
override val availableStates: Set<MangaState> get() = emptySet() override val availableStates: Set<MangaState> = emptySet()
override val availableContentRating: Set<ContentRating> = emptySet()
override val availableSortOrders: Set<SortOrder> = EnumSet.of( override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.UPDATED, SortOrder.UPDATED,

@ -2,6 +2,7 @@ package org.koitharu.kotatsu.parsers.site.madara.es
import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.ContentRating
import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaListFilter import org.koitharu.kotatsu.parsers.model.MangaListFilter
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaSource
@ -16,7 +17,8 @@ internal class DragonTranslationParser(context: MangaLoaderContext) :
MadaraParser(context, MangaSource.DRAGONTRANSLATION, "dragontranslation.net", 30) { MadaraParser(context, MangaSource.DRAGONTRANSLATION, "dragontranslation.net", 30) {
override val selectPage = "div#chapter_imgs img" override val selectPage = "div#chapter_imgs img"
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
override val availableStates: Set<MangaState> get() = emptySet() override val availableStates: Set<MangaState> = emptySet()
override val availableContentRating: Set<ContentRating> = emptySet()
init { init {
paginator.firstPage = 1 paginator.firstPage = 1

@ -17,7 +17,8 @@ internal class TmoManga(context: MangaLoaderContext) :
override val selectGenre = "div.summary-content a.tags_manga" override val selectGenre = "div.summary-content a.tags_manga"
override val withoutAjax = true override val withoutAjax = true
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.POPULARITY) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.POPULARITY)
override val availableStates: Set<MangaState> get() = emptySet() override val availableStates: Set<MangaState> = emptySet()
override val availableContentRating: Set<ContentRating> = emptySet()
init { init {
paginator.firstPage = 1 paginator.firstPage = 1

@ -17,7 +17,8 @@ internal class ManhwaHub(context: MangaLoaderContext) :
override val withoutAjax = true override val withoutAjax = true
override val listUrl = "genre/manhwa" override val listUrl = "genre/manhwa"
override val selectTestAsync = "ul.box-list-chapter" override val selectTestAsync = "ul.box-list-chapter"
override val availableStates: Set<MangaState> get() = emptySet() override val availableStates: Set<MangaState> = emptySet()
override val availableContentRating: Set<ContentRating> = emptySet()
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
init { init {

@ -9,6 +9,6 @@ import java.util.Locale
@MangaSourceParser("GEKKOUSCANS", "GekkouScans", "pt", ContentType.HENTAI) @MangaSourceParser("GEKKOUSCANS", "GekkouScans", "pt", ContentType.HENTAI)
internal class GekkouScans(context: MangaLoaderContext) : internal class GekkouScans(context: MangaLoaderContext) :
MadaraParser(context, MangaSource.GEKKOUSCANS, "gekkouscans.top") { MadaraParser(context, MangaSource.GEKKOUSCANS, "gekkou.site") {
override val sourceLocale: Locale = Locale.ENGLISH override val sourceLocale: Locale = Locale.ENGLISH
} }

@ -0,0 +1,12 @@
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.MangaSource
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
@MangaSourceParser("LADYESTELARSCAN", "LadyEstelarScan", "pt")
internal class LadyestelarScan(context: MangaLoaderContext) :
MadaraParser(context, MangaSource.LADYESTELARSCAN, "ladyestelarscan.com.br", 10) {
override val datePattern: String = "dd/MM/yyyy"
}

@ -0,0 +1,12 @@
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.MangaSource
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
@MangaSourceParser("LUNARSCAN", "LunarScan.com.br", "pt")
internal class LunarScan(context: MangaLoaderContext) :
MadaraParser(context, MangaSource.LUNARSCAN, "lunarscan.com.br") {
override val listUrl = "obra/"
}

@ -1,10 +1,12 @@
package org.koitharu.kotatsu.parsers.site.mangareader.tr package org.koitharu.kotatsu.parsers.site.madara.tr
import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
@MangaSourceParser("MAJORSCANS", "MajorScans", "tr") @MangaSourceParser("MAJORSCANS", "MajorScans", "tr")
internal class MajorScans(context: MangaLoaderContext) : internal class MajorScans(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.MAJORSCANS, "www.majorscans.com", pageSize = 20, searchPageSize = 25) MadaraParser(context, MangaSource.MAJORSCANS, "www.majorscans.com", pageSize = 18) {
override val datePattern = "dd/MM/yyyy"
}

@ -12,7 +12,7 @@ import org.koitharu.kotatsu.parsers.util.*
@MangaSourceParser("HENTAICUBE", "HentaiCube", "vi", ContentType.HENTAI) @MangaSourceParser("HENTAICUBE", "HentaiCube", "vi", ContentType.HENTAI)
internal class HentaiCube(context: MangaLoaderContext) : internal class HentaiCube(context: MangaLoaderContext) :
MadaraParser(context, MangaSource.HENTAICUBE, "hentaicube.net") { MadaraParser(context, MangaSource.HENTAICUBE, "cbhentai.net") {
override val datePattern = "dd/MM/yyyy" override val datePattern = "dd/MM/yyyy"
override val tagPrefix = "the-loai/" override val tagPrefix = "the-loai/"

@ -16,7 +16,8 @@ internal class Saytruyenhay(context: MangaLoaderContext) :
override val tagPrefix = "genre/" override val tagPrefix = "genre/"
override val withoutAjax = true override val withoutAjax = true
override val listUrl = "public/genre/manga/" override val listUrl = "public/genre/manga/"
override val availableStates: Set<MangaState> get() = emptySet() override val availableStates: Set<MangaState> = emptySet()
override val availableContentRating: Set<ContentRating> = emptySet()
override val availableSortOrders: Set<SortOrder> = override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.POPULARITY, SortOrder.UPDATED, SortOrder.RATING, SortOrder.NEWEST) EnumSet.of(SortOrder.POPULARITY, SortOrder.UPDATED, SortOrder.RATING, SortOrder.NEWEST)

@ -26,6 +26,8 @@ internal abstract class MangaboxParser(
override val availableStates: Set<MangaState> = EnumSet.of(MangaState.ONGOING, MangaState.FINISHED) override val availableStates: Set<MangaState> = EnumSet.of(MangaState.ONGOING, MangaState.FINISHED)
override val isTagsExclusionSupported = true
protected open val listUrl = "/advanced_search" protected open val listUrl = "/advanced_search"
protected open val searchUrl = "/search/story/" protected open val searchUrl = "/search/story/"
protected open val datePattern = "MMM dd,yy" protected open val datePattern = "MMM dd,yy"
@ -71,6 +73,15 @@ internal abstract class MangaboxParser(
} }
} }
if (filter.tagsExclude.isNotEmpty()) {
append("&g_e=")
filter.tagsExclude.forEach {
append("_")
append(it.key)
append("_")
}
}
filter.states.oneOrThrowIfMany()?.let { filter.states.oneOrThrowIfMany()?.let {
append("&sts=") append("&sts=")
append( append(

@ -37,6 +37,7 @@ internal class Mangairo(context: MangaLoaderContext) :
SortOrder.POPULARITY, SortOrder.POPULARITY,
SortOrder.NEWEST, SortOrder.NEWEST,
) )
override val isTagsExclusionSupported = false
override val isMultipleTagsSupported = false override val isMultipleTagsSupported = false
override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> { override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
val url = buildString { val url = buildString {

@ -19,6 +19,7 @@ internal class Mangakakalot(context: MangaLoaderContext) :
SortOrder.POPULARITY, SortOrder.POPULARITY,
SortOrder.NEWEST, SortOrder.NEWEST,
) )
override val isTagsExclusionSupported = false
override val isMultipleTagsSupported = false override val isMultipleTagsSupported = false
override val otherDomain = "chapmanganato.com" override val otherDomain = "chapmanganato.com"
override val listUrl = "/manga_list" override val listUrl = "/manga_list"

@ -23,6 +23,7 @@ internal class MangakakalotTv(context: MangaLoaderContext) :
SortOrder.NEWEST, SortOrder.NEWEST,
) )
override val isMultipleTagsSupported = false override val isMultipleTagsSupported = false
override val isTagsExclusionSupported = false
override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> { override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
val url = buildString { val url = buildString {

@ -41,6 +41,8 @@ internal abstract class MangaReaderParser(
override val availableStates: Set<MangaState> override val availableStates: Set<MangaState>
get() = EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.PAUSED) get() = EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.PAUSED)
override val isTagsExclusionSupported = true
protected open val listUrl = "/manga" protected open val listUrl = "/manga"
protected open val datePattern = "MMMM d, yyyy" protected open val datePattern = "MMMM d, yyyy"
protected open val isNetShieldProtected = false protected open val isNetShieldProtected = false
@ -77,11 +79,19 @@ internal abstract class MangaReaderParser(
}, },
) )
val tagKey = "genre[]".urlEncoded() filter.tags.forEach {
val tagQuery = append("&")
if (filter.tags.isEmpty()) "" append("genre[]".urlEncoded())
else filter.tags.joinToString(separator = "&", prefix = "&") { "$tagKey=${it.key}" } append("=")
append(tagQuery) append(it.key)
}
filter.tagsExclude.forEach {
append("&")
append("genre[]".urlEncoded())
append("=-")
append(it.key)
}
if (filter.states.isNotEmpty()) { if (filter.states.isNotEmpty()) {
filter.states.oneOrThrowIfMany()?.let { filter.states.oneOrThrowIfMany()?.let {

@ -7,4 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("AREASCANS", "AreaScans", "ar") @MangaSourceParser("AREASCANS", "AreaScans", "ar")
internal class AreaScans(context: MangaLoaderContext) : internal class AreaScans(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.AREASCANS, "www.areascans.net", pageSize = 20, searchPageSize = 10) MangaReaderParser(context, MangaSource.AREASCANS, "www.areascans.net", pageSize = 20, searchPageSize = 10) {
override val isTagsExclusionSupported = false
}

@ -9,4 +9,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
internal class AresManga(context: MangaLoaderContext) : internal class AresManga(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.ARESMANGA, "aresnov.org", pageSize = 20, searchPageSize = 10) { MangaReaderParser(context, MangaSource.ARESMANGA, "aresnov.org", pageSize = 20, searchPageSize = 10) {
override val listUrl = "/series" override val listUrl = "/series"
override val isTagsExclusionSupported = false
} }

@ -7,4 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("BEASTSCANS", "BeastScans", "ar") @MangaSourceParser("BEASTSCANS", "BeastScans", "ar")
internal class BeastScans(context: MangaLoaderContext) : internal class BeastScans(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.BEASTSCANS, "beastscans.net", pageSize = 20, searchPageSize = 10) MangaReaderParser(context, MangaSource.BEASTSCANS, "beastscans.net", pageSize = 20, searchPageSize = 10) {
override val isTagsExclusionSupported = false
}

@ -7,4 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("ELITON", "Eliton", "ar") @MangaSourceParser("ELITON", "Eliton", "ar")
internal class Eliton(context: MangaLoaderContext) : internal class Eliton(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.ELITON, "eliton.lol", pageSize = 20, searchPageSize = 10) MangaReaderParser(context, MangaSource.ELITON, "eliton.lol", pageSize = 20, searchPageSize = 10) {
override val isTagsExclusionSupported = false
}

@ -10,4 +10,5 @@ internal class EnAresManga(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.ENARESMANGA, "en-aresmanga.com", pageSize = 20, searchPageSize = 10) { MangaReaderParser(context, MangaSource.ENARESMANGA, "en-aresmanga.com", pageSize = 20, searchPageSize = 10) {
override val listUrl = "/series" override val listUrl = "/series"
override val encodedSrc = true override val encodedSrc = true
override val isTagsExclusionSupported = false
} }

@ -14,6 +14,7 @@ import java.util.ArrayList
internal class PotatoManga(context: MangaLoaderContext) : internal class PotatoManga(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.POTATOMANGA, "potatomanga.xyz", pageSize = 30, searchPageSize = 10) { MangaReaderParser(context, MangaSource.POTATOMANGA, "potatomanga.xyz", pageSize = 30, searchPageSize = 10) {
override val listUrl = "/series" override val listUrl = "/series"
override val isTagsExclusionSupported = false
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> { override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
val chapterUrl = chapter.url.toAbsoluteUrl(domain) val chapterUrl = chapter.url.toAbsoluteUrl(domain)

@ -16,6 +16,7 @@ internal class SwaTeam(context: MangaLoaderContext) :
override val selectMangaList = ".listupd .bs .bsx" override val selectMangaList = ".listupd .bs .bsx"
override val selectMangaListImg = "img" override val selectMangaListImg = "img"
override val isNetShieldProtected = true override val isNetShieldProtected = true
override val isTagsExclusionSupported = false
override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> { override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
val url = buildString { val url = buildString {

@ -14,6 +14,7 @@ internal class VexManga(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.VEXMANGA, "vexmanga.com", pageSize = 10, searchPageSize = 10) { MangaReaderParser(context, MangaSource.VEXMANGA, "vexmanga.com", pageSize = 10, searchPageSize = 10) {
override val selectMangaList = ".listarchives .latest-recom" override val selectMangaList = ".listarchives .latest-recom"
override val selectChapter = ".ulChapterList > a" override val selectChapter = ".ulChapterList > a"
override val isTagsExclusionSupported = false
override suspend fun getDetails(manga: Manga): Manga { override suspend fun getDetails(manga: Manga): Manga {
val docs = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml() val docs = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()

@ -9,4 +9,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
internal class AgsComics(context: MangaLoaderContext) : internal class AgsComics(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.AGSCOMICS, "agscomics.com", pageSize = 20, searchPageSize = 10) { MangaReaderParser(context, MangaSource.AGSCOMICS, "agscomics.com", pageSize = 20, searchPageSize = 10) {
override val listUrl = "/series" override val listUrl = "/series"
override val isTagsExclusionSupported = false
} }

@ -9,4 +9,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
internal class AnigliScans(context: MangaLoaderContext) : internal class AnigliScans(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.ANIGLISCANS, "anigliscans.xyz", pageSize = 47, searchPageSize = 47) { MangaReaderParser(context, MangaSource.ANIGLISCANS, "anigliscans.xyz", pageSize = 47, searchPageSize = 47) {
override val listUrl = "/series" override val listUrl = "/series"
override val isTagsExclusionSupported = false
} }

@ -7,4 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("ASCALONSCANS", "AscalonScans", "en") @MangaSourceParser("ASCALONSCANS", "AscalonScans", "en")
internal class AscalonScans(context: MangaLoaderContext) : internal class AscalonScans(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.ASCALONSCANS, "ascalonscans.com", pageSize = 20, searchPageSize = 10) MangaReaderParser(context, MangaSource.ASCALONSCANS, "ascalonscans.com", pageSize = 20, searchPageSize = 10) {
override val isTagsExclusionSupported = false
}

@ -7,4 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("ASTRASCANS", "AstraScans", "en") @MangaSourceParser("ASTRASCANS", "AstraScans", "en")
internal class AstraScans(context: MangaLoaderContext) : internal class AstraScans(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.ASTRASCANS, "astrascans.com", pageSize = 30, searchPageSize = 10) MangaReaderParser(context, MangaSource.ASTRASCANS, "astrascans.com", pageSize = 30, searchPageSize = 10) {
override val isTagsExclusionSupported = false
}

@ -10,4 +10,5 @@ internal class AsuraScansParser(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.ASURASCANS, "asuratoon.com", pageSize = 20, searchPageSize = 10) { MangaReaderParser(context, MangaSource.ASURASCANS, "asuratoon.com", pageSize = 20, searchPageSize = 10) {
override val selectPage = "#readerarea img:not(.asurascans)" override val selectPage = "#readerarea img:not(.asurascans)"
override val selectTestScript = "force html" override val selectTestScript = "force html"
override val isTagsExclusionSupported = false
} }

@ -9,4 +9,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
internal class BirdManga(context: MangaLoaderContext) : internal class BirdManga(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.BIRDMANGA, "birdmanga.com", pageSize = 20, searchPageSize = 10) { MangaReaderParser(context, MangaSource.BIRDMANGA, "birdmanga.com", pageSize = 20, searchPageSize = 10) {
override val encodedSrc = true override val encodedSrc = true
override val isTagsExclusionSupported = false
} }

@ -10,6 +10,7 @@ import org.koitharu.kotatsu.parsers.util.*
internal class Constellarcomic(context: MangaLoaderContext) : internal class Constellarcomic(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.CONSTELLARCOMIC, "constellarcomic.com", pageSize = 30, searchPageSize = 18) { MangaReaderParser(context, MangaSource.CONSTELLARCOMIC, "constellarcomic.com", pageSize = 30, searchPageSize = 18) {
override val selectTestScript = "script:containsData(ts_rea_der_._run)" override val selectTestScript = "script:containsData(ts_rea_der_._run)"
override val isTagsExclusionSupported = false
override suspend fun getDetails(manga: Manga): Manga { override suspend fun getDetails(manga: Manga): Manga {
val docs = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml() val docs = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()

@ -9,4 +9,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
internal class CosmicScansParser(context: MangaLoaderContext) : internal class CosmicScansParser(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.COSMICSCANS, "cosmic-scans.com", pageSize = 20, searchPageSize = 10) { MangaReaderParser(context, MangaSource.COSMICSCANS, "cosmic-scans.com", pageSize = 20, searchPageSize = 10) {
override val datePattern = "MMM d, yyyy" override val datePattern = "MMM d, yyyy"
override val isTagsExclusionSupported = false
} }

@ -7,4 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("FREAKCOMIC", "FreakComic", "en") @MangaSourceParser("FREAKCOMIC", "FreakComic", "en")
internal class FreakComic(context: MangaLoaderContext) : internal class FreakComic(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.FREAKCOMIC, "freakcomic.com", pageSize = 20, searchPageSize = 10) MangaReaderParser(context, MangaSource.FREAKCOMIC, "freakcomic.com", pageSize = 20, searchPageSize = 10) {
override val isTagsExclusionSupported = false
}

@ -9,4 +9,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
internal class FreakScans(context: MangaLoaderContext) : internal class FreakScans(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.FREAKSCANS, "freakscans.com", pageSize = 20, searchPageSize = 20) { MangaReaderParser(context, MangaSource.FREAKSCANS, "freakscans.com", pageSize = 20, searchPageSize = 20) {
override val datePattern = "MMM d, yyyy" override val datePattern = "MMM d, yyyy"
override val isTagsExclusionSupported = false
} }

@ -9,4 +9,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
internal class KaiScans(context: MangaLoaderContext) : internal class KaiScans(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.KAISCANS, "kaiscans.com", pageSize = 20, searchPageSize = 10) { MangaReaderParser(context, MangaSource.KAISCANS, "kaiscans.com", pageSize = 20, searchPageSize = 10) {
override val listUrl = "/series" override val listUrl = "/series"
override val isTagsExclusionSupported = false
} }

@ -9,4 +9,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
internal class KomikLabParser(context: MangaLoaderContext) : internal class KomikLabParser(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.KOMIKLAB, "komiklab.com", pageSize = 20, searchPageSize = 10) { MangaReaderParser(context, MangaSource.KOMIKLAB, "komiklab.com", pageSize = 20, searchPageSize = 10) {
override val datePattern = "MMM d, yyyy" override val datePattern = "MMM d, yyyy"
override val isTagsExclusionSupported = false
} }

@ -7,4 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("LIGHTSCANS", "LightScans", "en") @MangaSourceParser("LIGHTSCANS", "LightScans", "en")
internal class LightScans(context: MangaLoaderContext) : internal class LightScans(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.LIGHTSCANS, "lightscans.fun", pageSize = 20, searchPageSize = 10) MangaReaderParser(context, MangaSource.LIGHTSCANS, "lightscans.fun", pageSize = 20, searchPageSize = 10) {
override val isTagsExclusionSupported = false
}

@ -9,4 +9,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
internal class LuminousScans(context: MangaLoaderContext) : internal class LuminousScans(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.LUMINOUSSCANS, "luminousscans.net", pageSize = 20, searchPageSize = 10) { MangaReaderParser(context, MangaSource.LUMINOUSSCANS, "luminousscans.net", pageSize = 20, searchPageSize = 10) {
override val listUrl = "/series" override val listUrl = "/series"
override val isTagsExclusionSupported = false
} }

@ -6,8 +6,9 @@ import org.koitharu.kotatsu.parsers.model.ContentType
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("LUNAR_SCAN", "LunarScan", "en", ContentType.HENTAI) @MangaSourceParser("LUNAR_SCAN", "LunarScan.org", "en", ContentType.HENTAI)
internal class LunarScan(context: MangaLoaderContext) : internal class LunarScan(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.LUNAR_SCAN, "lunarscan.org", pageSize = 20, searchPageSize = 20) { MangaReaderParser(context, MangaSource.LUNAR_SCAN, "lunarscan.org", pageSize = 20, searchPageSize = 20) {
override val listUrl = "/series" override val listUrl = "/series"
override val isTagsExclusionSupported = false
} }

@ -19,6 +19,7 @@ internal class ManhwaFreak(context: MangaLoaderContext) :
override val selectMangaListImg = "img" override val selectMangaListImg = "img"
override val availableStates: Set<MangaState> = emptySet() override val availableStates: Set<MangaState> = emptySet()
override val isMultipleTagsSupported = false override val isMultipleTagsSupported = false
override val isTagsExclusionSupported = false
override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> { override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
val url = buildString { val url = buildString {

@ -10,4 +10,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
internal class ManhwaLover(context: MangaLoaderContext) : internal class ManhwaLover(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.MANHWALOVER, "www.manhwalover.com", pageSize = 20, searchPageSize = 20) { MangaReaderParser(context, MangaSource.MANHWALOVER, "www.manhwalover.com", pageSize = 20, searchPageSize = 20) {
override val datePattern = "MMM d, yyyy" override val datePattern = "MMM d, yyyy"
override val isTagsExclusionSupported = false
} }

@ -10,4 +10,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
internal class Manhwax(context: MangaLoaderContext) : internal class Manhwax(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.MANHWAX, "manhwax.org", pageSize = 20, searchPageSize = 20) { MangaReaderParser(context, MangaSource.MANHWAX, "manhwax.org", pageSize = 20, searchPageSize = 20) {
override val datePattern = "MMM d, yyyy" override val datePattern = "MMM d, yyyy"
override val isTagsExclusionSupported = false
} }

@ -7,4 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("MANJANOON_EN", "Manjanoon.net", "en") @MangaSourceParser("MANJANOON_EN", "Manjanoon.net", "en")
internal class Manjanoon(context: MangaLoaderContext) : internal class Manjanoon(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.MANJANOON_EN, "manjanoon.net", pageSize = 20, searchPageSize = 10) MangaReaderParser(context, MangaSource.MANJANOON_EN, "manjanoon.net", pageSize = 20, searchPageSize = 10) {
override val isTagsExclusionSupported = false
}

@ -10,4 +10,5 @@ internal class Nightscans(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.NIGHTSCANS, "nightscans.net", pageSize = 20, searchPageSize = 10) { MangaReaderParser(context, MangaSource.NIGHTSCANS, "nightscans.net", pageSize = 20, searchPageSize = 10) {
override val listUrl = "/series" override val listUrl = "/series"
override val selectMangaListImg = "img.ts-post-image, picture img" override val selectMangaListImg = "img.ts-post-image, picture img"
override val isTagsExclusionSupported = false
} }

@ -9,4 +9,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
internal class RavenScans(context: MangaLoaderContext) : internal class RavenScans(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.RAVENSCANS, "ravenscans.com", pageSize = 10, searchPageSize = 10) { MangaReaderParser(context, MangaSource.RAVENSCANS, "ravenscans.com", pageSize = 10, searchPageSize = 10) {
override val datePattern = "MMM d, yyyy" override val datePattern = "MMM d, yyyy"
override val isTagsExclusionSupported = false
} }

@ -9,4 +9,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
internal class ReadersPoint(context: MangaLoaderContext) : internal class ReadersPoint(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.READERSPOINT, "readers-point.space", pageSize = 20, searchPageSize = 10) { MangaReaderParser(context, MangaSource.READERSPOINT, "readers-point.space", pageSize = 20, searchPageSize = 10) {
override val listUrl = "/series" override val listUrl = "/series"
override val isTagsExclusionSupported = false
} }

@ -9,5 +9,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
internal class Readkomik(context: MangaLoaderContext) : internal class Readkomik(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.READKOMIK, "readkomik.com", pageSize = 20, searchPageSize = 20) { MangaReaderParser(context, MangaSource.READKOMIK, "readkomik.com", pageSize = 20, searchPageSize = 20) {
override val datePattern = "MMM d, yyyy" override val datePattern = "MMM d, yyyy"
override val isTagsExclusionSupported = false
} }

@ -20,6 +20,7 @@ internal class RizzComic(context: MangaLoaderContext) :
override val availableStates: Set<MangaState> = emptySet() override val availableStates: Set<MangaState> = emptySet()
override val isMultipleTagsSupported = false override val isMultipleTagsSupported = false
override val isSearchSupported = false override val isSearchSupported = false
override val isTagsExclusionSupported = false
// TODO Query created in json // TODO Query created in json
override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> { override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {

@ -7,4 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("SURYASCANS", "SuryaScans", "en") @MangaSourceParser("SURYASCANS", "SuryaScans", "en")
internal class SuryaScans(context: MangaLoaderContext) : internal class SuryaScans(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.SURYASCANS, "suryacomics.com", pageSize = 5, searchPageSize = 10) MangaReaderParser(context, MangaSource.SURYASCANS, "suryacomics.com", pageSize = 5, searchPageSize = 10) {
override val isTagsExclusionSupported = false
}

@ -9,4 +9,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
internal class VoidScans(context: MangaLoaderContext) : internal class VoidScans(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.VOIDSCANS, "void-scans.com", pageSize = 150, searchPageSize = 150) { MangaReaderParser(context, MangaSource.VOIDSCANS, "void-scans.com", pageSize = 150, searchPageSize = 150) {
override val datePattern = "MMM d, yyyy" override val datePattern = "MMM d, yyyy"
override val isTagsExclusionSupported = false
} }

@ -7,4 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("XCALIBRSCANS", "XCalibrScans", "en") @MangaSourceParser("XCALIBRSCANS", "XCalibrScans", "en")
internal class XCalibrScans(context: MangaLoaderContext) : internal class XCalibrScans(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.XCALIBRSCANS, "xcalibrscans.com", pageSize = 20, searchPageSize = 10) MangaReaderParser(context, MangaSource.XCALIBRSCANS, "xcalibrscans.com", pageSize = 20, searchPageSize = 10) {
override val isTagsExclusionSupported = false
}

@ -24,6 +24,7 @@ internal class Zahard(context: MangaLoaderContext) :
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.NEWEST) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.NEWEST)
override val availableStates: Set<MangaState> = emptySet() override val availableStates: Set<MangaState> = emptySet()
override val isMultipleTagsSupported = false override val isMultipleTagsSupported = false
override val isTagsExclusionSupported = false
override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> { override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
val url = buildString { val url = buildString {

@ -7,4 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("GREMORYMANGAS", "GremoryMangas", "es") @MangaSourceParser("GREMORYMANGAS", "GremoryMangas", "es")
internal class GremoryMangas(context: MangaLoaderContext) : internal class GremoryMangas(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.GREMORYMANGAS, "gremorymangas.com", pageSize = 20, searchPageSize = 20) MangaReaderParser(context, MangaSource.GREMORYMANGAS, "gremorymangas.com", pageSize = 20, searchPageSize = 20) {
override val isTagsExclusionSupported = false
}

@ -7,4 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("INARIMANGA", "InariManga", "es") @MangaSourceParser("INARIMANGA", "InariManga", "es")
internal class InariManga(context: MangaLoaderContext) : internal class InariManga(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.INARIMANGA, "inarimanga.net", pageSize = 20, searchPageSize = 10) MangaReaderParser(context, MangaSource.INARIMANGA, "inarimanga.net", pageSize = 20, searchPageSize = 10) {
override val isTagsExclusionSupported = false
}

@ -10,4 +10,5 @@ internal class NekoScans(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.NEKOSCANS, "nekoscans.com", pageSize = 20, searchPageSize = 10) { MangaReaderParser(context, MangaSource.NEKOSCANS, "nekoscans.com", pageSize = 20, searchPageSize = 10) {
override val listUrl = "/proyecto" override val listUrl = "/proyecto"
override val encodedSrc = true override val encodedSrc = true
override val isTagsExclusionSupported = false
} }

@ -7,4 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("RAGNASCAN", "RagnaScan", "es") @MangaSourceParser("RAGNASCAN", "RagnaScan", "es")
internal class RagnaScan(context: MangaLoaderContext) : internal class RagnaScan(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.RAGNASCAN, "ragnascan.com", pageSize = 5, searchPageSize = 10) MangaReaderParser(context, MangaSource.RAGNASCAN, "ragnascan.com", pageSize = 5, searchPageSize = 10) {
override val isTagsExclusionSupported = false
}

@ -8,6 +8,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("SHADOWMANGAS", "ShadowMangas", "es") @MangaSourceParser("SHADOWMANGAS", "ShadowMangas", "es")
internal class Shadowmangas(context: MangaLoaderContext) : internal class Shadowmangas(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.SHADOWMANGAS, "shadowmangas.com", pageSize = 10, searchPageSize = 10) { MangaReaderParser(context, MangaSource.SHADOWMANGAS, "shadowmangas.com", pageSize = 10, searchPageSize = 10) {
override val datePattern = "MMM d, yyyy" override val datePattern = "MMM d, yyyy"
override val isTagsExclusionSupported = false
} }

@ -9,4 +9,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
internal class SkyMangas(context: MangaLoaderContext) : internal class SkyMangas(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.SKYMANGAS, "skymangas.com", pageSize = 20, searchPageSize = 10) { MangaReaderParser(context, MangaSource.SKYMANGAS, "skymangas.com", pageSize = 20, searchPageSize = 10) {
override val encodedSrc = true override val encodedSrc = true
override val isTagsExclusionSupported = false
} }

@ -7,4 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("TECNOSCANN", "TecnoScann", "es") @MangaSourceParser("TECNOSCANN", "TecnoScann", "es")
internal class TecnoScann(context: MangaLoaderContext) : internal class TecnoScann(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.TECNOSCANN, "tecnoscann.com", 20, 10) MangaReaderParser(context, MangaSource.TECNOSCANN, "tecnoscann.com", 20, 10) {
override val isTagsExclusionSupported = false
}

@ -11,4 +11,5 @@ import java.util.Locale
internal class TenkaiScan(context: MangaLoaderContext) : internal class TenkaiScan(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.TENKAISCAN, "tenkaiscan.net", 20, 10) { MangaReaderParser(context, MangaSource.TENKAISCAN, "tenkaiscan.net", 20, 10) {
override val sourceLocale: Locale = Locale.ENGLISH override val sourceLocale: Locale = Locale.ENGLISH
override val isTagsExclusionSupported = false
} }

@ -5,10 +5,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.ContentType import org.koitharu.kotatsu.parsers.model.ContentType
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
import java.util.Locale
@MangaSourceParser("TRADUCCIONESMOONLIGHT", "TraduccionesMoonlight", "es", ContentType.HENTAI) @MangaSourceParser("TRADUCCIONESMOONLIGHT", "TraduccionesMoonlight", "es", ContentType.HENTAI)
internal class TraduccionesMoonlight(context: MangaLoaderContext) : internal class TraduccionesMoonlight(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.TRADUCCIONESMOONLIGHT, "tenkaiscan.net", 20, 10) { MangaReaderParser(context, MangaSource.TRADUCCIONESMOONLIGHT, "traduccionesmoonlight.com", 20, 10)
override val sourceLocale: Locale = Locale.ENGLISH
}

@ -7,4 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("TRESDAOS", "Tresdaos", "es") @MangaSourceParser("TRESDAOS", "Tresdaos", "es")
internal class Tresdaos(context: MangaLoaderContext) : internal class Tresdaos(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.TRESDAOS, "tresdaos.com", 20, 10) MangaReaderParser(context, MangaSource.TRESDAOS, "tresdaos.com", 20, 10) {
override val isTagsExclusionSupported = false
}

@ -20,6 +20,7 @@ internal class TuManhwas(context: MangaLoaderContext) :
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.NEWEST) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.NEWEST)
override val availableStates: Set<MangaState> = emptySet() override val availableStates: Set<MangaState> = emptySet()
override val isMultipleTagsSupported = false override val isMultipleTagsSupported = false
override val isTagsExclusionSupported = false
override suspend fun getAvailableTags(): Set<MangaTag> = emptySet() override suspend fun getAvailableTags(): Set<MangaTag> = emptySet()

@ -8,4 +8,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("EPSILONSCAN", "EpsilonScan", "fr", ContentType.HENTAI) @MangaSourceParser("EPSILONSCAN", "EpsilonScan", "fr", ContentType.HENTAI)
internal class EpsilonscanParser(context: MangaLoaderContext) : internal class EpsilonscanParser(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.EPSILONSCAN, "epsilonscan.fr", pageSize = 20, searchPageSize = 10) MangaReaderParser(context, MangaSource.EPSILONSCAN, "epsilonscan.fr", pageSize = 20, searchPageSize = 10) {
override val isTagsExclusionSupported = false
}

@ -7,4 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("GLORYSCANS", "GloryScans", "fr") @MangaSourceParser("GLORYSCANS", "GloryScans", "fr")
internal class GloryScans(context: MangaLoaderContext) : internal class GloryScans(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.GLORYSCANS, "gloryscans.fr", pageSize = 20, searchPageSize = 10) MangaReaderParser(context, MangaSource.GLORYSCANS, "gloryscans.fr", pageSize = 20, searchPageSize = 10) {
override val isTagsExclusionSupported = false
}

@ -9,4 +9,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
internal class PhenixscansParser(context: MangaLoaderContext) : internal class PhenixscansParser(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.PHENIXSCANS, "phenixscans.fr", pageSize = 20, searchPageSize = 10) { MangaReaderParser(context, MangaSource.PHENIXSCANS, "phenixscans.fr", pageSize = 20, searchPageSize = 10) {
override val datePattern = "MMM d, yyyy" override val datePattern = "MMM d, yyyy"
override val isTagsExclusionSupported = false
} }

@ -7,4 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("VFSCAN", "VfScan", "fr") @MangaSourceParser("VFSCAN", "VfScan", "fr")
internal class VfScan(context: MangaLoaderContext) : internal class VfScan(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.VFSCAN, "www.vfscan.cc", pageSize = 18, searchPageSize = 18) MangaReaderParser(context, MangaSource.VFSCAN, "www.vfscan.cc", pageSize = 18, searchPageSize = 18) {
override val isTagsExclusionSupported = false
}

@ -12,4 +12,5 @@ internal class AinzScans(context: MangaLoaderContext) :
override val listUrl = "/series" override val listUrl = "/series"
override val datePattern = "MMM d, yyyy" override val datePattern = "MMM d, yyyy"
override val sourceLocale: Locale = Locale.ENGLISH override val sourceLocale: Locale = Locale.ENGLISH
override val isTagsExclusionSupported = false
} }

@ -9,4 +9,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
internal class Comicaso(context: MangaLoaderContext) : internal class Comicaso(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.COMICASO, "comicaso.com", pageSize = 20, searchPageSize = 10) { MangaReaderParser(context, MangaSource.COMICASO, "comicaso.com", pageSize = 20, searchPageSize = 10) {
override val encodedSrc = true override val encodedSrc = true
override val isTagsExclusionSupported = false
} }

@ -2,69 +2,13 @@ package org.koitharu.kotatsu.parsers.site.mangareader.id
import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaListFilter
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.model.MangaState
import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
import org.koitharu.kotatsu.parsers.util.domain
import org.koitharu.kotatsu.parsers.util.oneOrThrowIfMany
import org.koitharu.kotatsu.parsers.util.parseHtml
import org.koitharu.kotatsu.parsers.util.urlEncoded
import java.util.EnumSet
import java.util.Locale import java.util.Locale
@MangaSourceParser("COSMIC_SCANS", "CosmicScans.id", "id") @MangaSourceParser("COSMIC_SCANS", "CosmicScans.id", "id")
internal class CosmicScans(context: MangaLoaderContext) : internal class CosmicScans(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.COSMIC_SCANS, "cosmicscans.id", pageSize = 30, searchPageSize = 30) { MangaReaderParser(context, MangaSource.COSMIC_SCANS, "cosmicscans.id", pageSize = 30, searchPageSize = 30) {
override val sourceLocale: Locale = Locale.ENGLISH override val sourceLocale: Locale = Locale.ENGLISH
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED) override val isTagsExclusionSupported = false
override val availableStates: Set<MangaState> = emptySet()
override val isMultipleTagsSupported = false
override val listUrl = "/semua-komik"
override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
val url = buildString {
append("https://")
append(domain)
when (filter) {
is MangaListFilter.Search -> {
append("/page/")
append(page.toString())
append("/?s=")
append(filter.query.urlEncoded())
}
is MangaListFilter.Advanced -> {
if (filter.tags.isNotEmpty()) {
filter.tags.oneOrThrowIfMany()?.let {
append("/genres/")
append(it.key)
append("/page/")
append(page.toString())
append('/')
}
} else {
if (page > 1) {
return emptyList()
}
append(listUrl)
}
}
null -> {
if (page > 1) {
return emptyList()
}
append(listUrl)
}
}
}
return parseMangaList(webClient.httpGet(url).parseHtml())
}
} }

@ -10,4 +10,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
internal class Dojing(context: MangaLoaderContext) : internal class Dojing(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.DOJING, "dojing.net", pageSize = 12, searchPageSize = 12) { MangaReaderParser(context, MangaSource.DOJING, "dojing.net", pageSize = 12, searchPageSize = 12) {
override val datePattern = "MMM d, yyyy" override val datePattern = "MMM d, yyyy"
override val isTagsExclusionSupported = false
} }

@ -8,4 +8,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("DOUJINDESURIP", "DoujinDesu.cfd", "id", ContentType.HENTAI) @MangaSourceParser("DOUJINDESURIP", "DoujinDesu.cfd", "id", ContentType.HENTAI)
internal class DoujinDesuRip(context: MangaLoaderContext) : internal class DoujinDesuRip(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.DOUJINDESURIP, "doujindesu.cfd", pageSize = 20, searchPageSize = 10) MangaReaderParser(context, MangaSource.DOUJINDESURIP, "doujindesu.cfd", pageSize = 20, searchPageSize = 10) {
override val isTagsExclusionSupported = false
}

@ -11,4 +11,5 @@ import java.util.Locale
internal class DoujinKu(context: MangaLoaderContext) : internal class DoujinKu(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.DOUJINKU, "doujinku.xyz", pageSize = 20, searchPageSize = 10) { MangaReaderParser(context, MangaSource.DOUJINKU, "doujinku.xyz", pageSize = 20, searchPageSize = 10) {
override val sourceLocale: Locale = Locale.ENGLISH override val sourceLocale: Locale = Locale.ENGLISH
override val isTagsExclusionSupported = false
} }

@ -7,4 +7,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("FUTARI", "Futari", "id") @MangaSourceParser("FUTARI", "Futari", "id")
internal class Futari(context: MangaLoaderContext) : internal class Futari(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.FUTARI, "futari.info", pageSize = 25, searchPageSize = 10) MangaReaderParser(context, MangaSource.FUTARI, "futari.info", pageSize = 25, searchPageSize = 10) {
override val isTagsExclusionSupported = false
}

@ -8,4 +8,6 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
@MangaSourceParser("KANZENIN", "Kanzenin", "id", ContentType.HENTAI) @MangaSourceParser("KANZENIN", "Kanzenin", "id", ContentType.HENTAI)
internal class Kanzenin(context: MangaLoaderContext) : internal class Kanzenin(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.KANZENIN, "kanzenin.info", pageSize = 27, searchPageSize = 10) MangaReaderParser(context, MangaSource.KANZENIN, "kanzenin.info", pageSize = 27, searchPageSize = 10) {
override val isTagsExclusionSupported = false
}

@ -10,4 +10,5 @@ import java.util.*
internal class KataKomik(context: MangaLoaderContext) : internal class KataKomik(context: MangaLoaderContext) :
MangaReaderParser(context, MangaSource.KATAKOMIK, "katakomik.my.id", pageSize = 20, searchPageSize = 10) { MangaReaderParser(context, MangaSource.KATAKOMIK, "katakomik.my.id", pageSize = 20, searchPageSize = 10) {
override val sourceLocale: Locale = Locale.ENGLISH override val sourceLocale: Locale = Locale.ENGLISH
override val isTagsExclusionSupported = false
} }

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

Loading…
Cancel
Save