Extract MangaSource interface

master
Koitharu 2 years ago
parent 7ed8c9f787
commit f923acc5a7
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -53,7 +53,7 @@ This library provides manga sources.
3. Usage in code 3. Usage in code
```kotlin ```kotlin
val parser = mangaLoaderContext.newParserInstance(MangaSource.MANGADEX) val parser = mangaLoaderContext.newParserInstance(MangaParserSourceMANGADEX)
``` ```
`mangaLoaderContext` is an implementation of the `MangaLoaderContext` class. `mangaLoaderContext` is an implementation of the `MangaLoaderContext` class.
@ -62,7 +62,7 @@ This library provides manga sources.
and [Non-Android](https://github.com/KotatsuApp/kotatsu-dl/blob/master/src/jvmMain/kotlin/org/koitharu/kotatsu_dl/logic/MangaLoaderContextImpl.kt) and [Non-Android](https://github.com/KotatsuApp/kotatsu-dl/blob/master/src/jvmMain/kotlin/org/koitharu/kotatsu_dl/logic/MangaLoaderContextImpl.kt)
implementation. implementation.
Note that the `MangaSource.LOCAL` and `MangaSource.DUMMY` parsers cannot be instantiated. Note that the `MangaParserSourceLOCAL` and `MangaParserSourceDUMMY` parsers cannot be instantiated.
## Contribution ## Contribution

@ -69,12 +69,9 @@ class ParserProcessor(
""" """
package org.koitharu.kotatsu.parsers package org.koitharu.kotatsu.parsers
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
@Suppress("DEPRECATION") internal fun MangaParserSource.newParser(context: MangaLoaderContext): MangaParser = when (this) {
@InternalParsersApi
@Deprecated("", replaceWith = ReplaceWith("context.newParserInstance(this)"))
fun MangaSource.newParser(context: MangaLoaderContext): MangaParser = when (this) {
""".trimIndent(), """.trimIndent(),
) )
@ -83,14 +80,12 @@ class ParserProcessor(
""" """
package org.koitharu.kotatsu.parsers.model package org.koitharu.kotatsu.parsers.model
enum class MangaSource( enum class MangaParserSource(
val title: String, val title: String,
val locale: String, val locale: String,
val contentType: ContentType, val contentType: ContentType,
val isBroken: Boolean, val isBroken: Boolean,
) { ): MangaSource {
LOCAL("Local", "", ContentType.OTHER, false),
UNKNOWN("Unknown", "", ContentType.OTHER, true),
""".trimIndent(), """.trimIndent(),
) )
@ -102,9 +97,7 @@ class ParserProcessor(
factoryWriter?.write( factoryWriter?.write(
""" """
MangaSource.LOCAL, MangaParserSource.DUMMY -> throw NotImplementedError("Manga parser ${'$'}name cannot be instantiated")
MangaSource.UNKNOWN,
MangaSource.DUMMY -> throw NotImplementedError("Manga parser ${'$'}name cannot be instantiated")
}.also { }.also {
require(it.source == this) { require(it.source == this) {
"Cannot instantiate manga parser: ${'$'}name mapped to ${'$'}{it.source}" "Cannot instantiate manga parser: ${'$'}name mapped to ${'$'}{it.source}"
@ -166,7 +159,7 @@ class ParserProcessor(
logger.warn("Source title duplication: \"$title\" is assigned to both $prevTitleClass and $className") logger.warn("Source title duplication: \"$title\" is assigned to both $prevTitleClass and $className")
} }
factoryWriter?.write("\tMangaSource.$name -> $className(context)\n") factoryWriter?.write("\tMangaParserSource.$name -> $className(context)\n")
val deprecationString = val deprecationString =
if (deprecation != null) { if (deprecation != null) {
val reason = val reason =

@ -5,6 +5,7 @@ import okhttp3.OkHttpClient
import okhttp3.Response import okhttp3.Response
import org.koitharu.kotatsu.parsers.bitmap.Bitmap import org.koitharu.kotatsu.parsers.bitmap.Bitmap
import org.koitharu.kotatsu.parsers.config.MangaSourceConfig import org.koitharu.kotatsu.parsers.config.MangaSourceConfig
import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaSource
import java.util.* import java.util.*
@ -14,8 +15,7 @@ abstract class MangaLoaderContext {
abstract val cookieJar: CookieJar abstract val cookieJar: CookieJar
@Suppress("DEPRECATION") fun newParserInstance(source: MangaParserSource): MangaParser = source.newParser(this)
fun newParserInstance(source: MangaSource): MangaParser = source.newParser(this)
open fun encodeBase64(data: ByteArray): String = Base64.getEncoder().encodeToString(data) open fun encodeBase64(data: ByteArray): String = Base64.getEncoder().encodeToString(data)
@ -42,7 +42,7 @@ abstract class MangaLoaderContext {
*/ */
abstract fun redrawImageResponse( abstract fun redrawImageResponse(
response: Response, response: Response,
redraw: (image: Bitmap) -> Bitmap redraw: (image: Bitmap) -> Bitmap,
): Response ): Response
/** /**
@ -50,6 +50,6 @@ abstract class MangaLoaderContext {
*/ */
abstract fun createBitmap( abstract fun createBitmap(
width: Int, width: Int,
height: Int height: Int,
): Bitmap ): Bitmap
} }

@ -6,7 +6,6 @@ import okhttp3.Headers
import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.network.OkHttpWebClient import org.koitharu.kotatsu.parsers.network.OkHttpWebClient
import org.koitharu.kotatsu.parsers.network.UserAgents
import org.koitharu.kotatsu.parsers.network.WebClient import org.koitharu.kotatsu.parsers.network.WebClient
import org.koitharu.kotatsu.parsers.util.FaviconParser import org.koitharu.kotatsu.parsers.util.FaviconParser
import org.koitharu.kotatsu.parsers.util.RelatedMangaFinder import org.koitharu.kotatsu.parsers.util.RelatedMangaFinder
@ -16,7 +15,7 @@ import java.util.*
abstract class MangaParser @InternalParsersApi constructor( abstract class MangaParser @InternalParsersApi constructor(
@property:InternalParsersApi val context: MangaLoaderContext, @property:InternalParsersApi val context: MangaLoaderContext,
val source: MangaSource, val source: MangaParserSource,
) { ) {
/** /**
@ -63,7 +62,7 @@ abstract class MangaParser @InternalParsersApi constructor(
val config by lazy { context.getConfig(source) } val config by lazy { context.getConfig(source) }
open val sourceLocale: Locale open val sourceLocale: Locale
get() = source.locale?.let { Locale(it) } ?: Locale.ROOT get() = if (source.locale.isEmpty()) Locale.ROOT else Locale(source.locale)
val isNsfwSource = source.contentType == ContentType.HENTAI val isNsfwSource = source.contentType == ContentType.HENTAI
@ -245,7 +244,7 @@ abstract class MangaParser @InternalParsersApi constructor(
return RelatedMangaFinder(listOf(this)).invoke(seed) return RelatedMangaFinder(listOf(this)).invoke(seed)
} }
protected fun getParser(source: MangaSource) = if (this.source == source) { protected fun getParser(source: MangaParserSource) = if (this.source == source) {
this this
} else { } else {
context.newParserInstance(source) context.newParserInstance(source)

@ -7,7 +7,7 @@ import org.koitharu.kotatsu.parsers.util.Paginator
@InternalParsersApi @InternalParsersApi
abstract class PagedMangaParser( abstract class PagedMangaParser(
context: MangaLoaderContext, context: MangaLoaderContext,
source: MangaSource, source: MangaParserSource,
@VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) @JvmField internal val pageSize: Int, @VisibleForTesting(otherwise = VisibleForTesting.PROTECTED) @JvmField internal val pageSize: Int,
searchPageSize: Int = pageSize, searchPageSize: Int = pageSize,
) : MangaParser(context, source) { ) : MangaParser(context, source) {

@ -2,7 +2,7 @@ package org.koitharu.kotatsu.parsers.model
class Favicons internal constructor( class Favicons internal constructor(
favicons: Collection<Favicon>, favicons: Collection<Favicon>,
@JvmField val referer: String, @JvmField val referer: String?,
) : Collection<Favicon> { ) : Collection<Favicon> {
private val icons = favicons.sortedDescending() private val icons = favicons.sortedDescending()
@ -47,4 +47,12 @@ class Favicons internal constructor(
} }
return result return result
} }
companion object {
@JvmStatic
fun empty() = Favicons(emptySet(), null)
fun single(url: String) = Favicons(setOf(Favicon(url, 0, null)), null)
}
} }

@ -0,0 +1,6 @@
package org.koitharu.kotatsu.parsers.model
interface MangaSource {
val name: String
}

@ -11,7 +11,6 @@ import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.exception.ParseException import org.koitharu.kotatsu.parsers.exception.ParseException
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.isNullOrEmpty
import java.nio.charset.StandardCharsets import java.nio.charset.StandardCharsets
import java.security.MessageDigest import java.security.MessageDigest
import java.util.* import java.util.*
@ -22,7 +21,7 @@ import javax.crypto.spec.SecretKeySpec
@MangaSourceParser("BATOTO", "Bato.To") @MangaSourceParser("BATOTO", "Bato.To")
internal class BatoToParser(context: MangaLoaderContext) : PagedMangaParser( internal class BatoToParser(context: MangaLoaderContext) : PagedMangaParser(
context = context, context = context,
source = MangaSource.BATOTO, source = MangaParserSource.BATOTO,
pageSize = 60, pageSize = 60,
searchPageSize = 20, searchPageSize = 20,
) { ) {

@ -21,7 +21,8 @@ import java.util.*
private const val CHAPTERS_LIMIT = 99999 private const val CHAPTERS_LIMIT = 99999
@MangaSourceParser("COMICK_FUN", "ComicK") @MangaSourceParser("COMICK_FUN", "ComicK")
internal class ComickFunParser(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.COMICK_FUN, 20) { internal class ComickFunParser(context: MangaLoaderContext) :
PagedMangaParser(context, MangaParserSource.COMICK_FUN, 20) {
override val configKeyDomain = ConfigKey.Domain("comick.io", "comick.cc") override val configKeyDomain = ConfigKey.Domain("comick.io", "comick.cc")

@ -24,7 +24,7 @@ private const val DOMAIN_AUTHORIZED = "exhentai.org"
@MangaSourceParser("EXHENTAI", "ExHentai", type = ContentType.HENTAI) @MangaSourceParser("EXHENTAI", "ExHentai", type = ContentType.HENTAI)
internal class ExHentaiParser( internal class ExHentaiParser(
context: MangaLoaderContext, context: MangaLoaderContext,
) : PagedMangaParser(context, MangaSource.EXHENTAI, pageSize = 25), MangaParserAuthProvider { ) : PagedMangaParser(context, MangaParserSource.EXHENTAI, pageSize = 25), MangaParserAuthProvider {
override val availableSortOrders: Set<SortOrder> = setOf(SortOrder.NEWEST) override val availableSortOrders: Set<SortOrder> = setOf(SortOrder.NEWEST)
override val isTagsExclusionSupported: Boolean = true override val isTagsExclusionSupported: Boolean = true

@ -27,7 +27,7 @@ import kotlin.math.min
@OptIn(ExperimentalUnsignedTypes::class) @OptIn(ExperimentalUnsignedTypes::class)
@MangaSourceParser("HITOMILA", "Hitomi.La", type = ContentType.HENTAI) @MangaSourceParser("HITOMILA", "Hitomi.La", type = ContentType.HENTAI)
class HitomiLaParser(context: MangaLoaderContext) : MangaParser(context, MangaSource.HITOMILA) { class HitomiLaParser(context: MangaLoaderContext) : MangaParser(context, MangaParserSource.HITOMILA) {
override val configKeyDomain = ConfigKey.Domain("hitomi.la") override val configKeyDomain = ConfigKey.Domain("hitomi.la")
private val ltnBaseUrl get() = "https://${getDomain("ltn")}" private val ltnBaseUrl get() = "https://${getDomain("ltn")}"

@ -15,7 +15,7 @@ import java.util.*
@MangaSourceParser("IMHENTAI", "ImHentai", type = ContentType.HENTAI) @MangaSourceParser("IMHENTAI", "ImHentai", type = ContentType.HENTAI)
internal class ImHentai(context: MangaLoaderContext) : internal class ImHentai(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.IMHENTAI, pageSize = 20) { PagedMangaParser(context, MangaParserSource.IMHENTAI, pageSize = 20) {
override val availableSortOrders: Set<SortOrder> = override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.RATING) EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.RATING)

@ -21,7 +21,7 @@ import javax.crypto.spec.SecretKeySpec
internal abstract class LineWebtoonsParser( internal abstract class LineWebtoonsParser(
context: MangaLoaderContext, context: MangaLoaderContext,
source: MangaSource, source: MangaParserSource,
) : MangaParser(context, source) { ) : MangaParser(context, source) {
override val isMultipleTagsSupported = false override val isMultipleTagsSupported = false
@ -307,25 +307,25 @@ internal abstract class LineWebtoonsParser(
} }
@MangaSourceParser("LINEWEBTOONS_EN", "LineWebtoons English", "en", type = ContentType.MANGA) @MangaSourceParser("LINEWEBTOONS_EN", "LineWebtoons English", "en", type = ContentType.MANGA)
class English(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaSource.LINEWEBTOONS_EN) class English(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaParserSource.LINEWEBTOONS_EN)
@MangaSourceParser("LINEWEBTOONS_ZH", "LineWebtoons Chinese", "zh", type = ContentType.MANGA) @MangaSourceParser("LINEWEBTOONS_ZH", "LineWebtoons Chinese", "zh", type = ContentType.MANGA)
class Chinese(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaSource.LINEWEBTOONS_ZH) class Chinese(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaParserSource.LINEWEBTOONS_ZH)
@MangaSourceParser("LINEWEBTOONS_TH", "LineWebtoons Thai", "th", type = ContentType.MANGA) @MangaSourceParser("LINEWEBTOONS_TH", "LineWebtoons Thai", "th", type = ContentType.MANGA)
class Thai(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaSource.LINEWEBTOONS_TH) class Thai(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaParserSource.LINEWEBTOONS_TH)
@MangaSourceParser("LINEWEBTOONS_ID", "LineWebtoons Indonesian", "id", type = ContentType.MANGA) @MangaSourceParser("LINEWEBTOONS_ID", "LineWebtoons Indonesian", "id", type = ContentType.MANGA)
class Indonesian(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaSource.LINEWEBTOONS_ID) class Indonesian(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaParserSource.LINEWEBTOONS_ID)
@MangaSourceParser("LINEWEBTOONS_ES", "LineWebtoons Spanish", "es", type = ContentType.MANGA) @MangaSourceParser("LINEWEBTOONS_ES", "LineWebtoons Spanish", "es", type = ContentType.MANGA)
class Spanish(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaSource.LINEWEBTOONS_ES) class Spanish(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaParserSource.LINEWEBTOONS_ES)
@MangaSourceParser("LINEWEBTOONS_FR", "LineWebtoons French", "fr", type = ContentType.MANGA) @MangaSourceParser("LINEWEBTOONS_FR", "LineWebtoons French", "fr", type = ContentType.MANGA)
class French(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaSource.LINEWEBTOONS_FR) class French(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaParserSource.LINEWEBTOONS_FR)
@MangaSourceParser("LINEWEBTOONS_DE", "LineWebtoons German", "de", type = ContentType.MANGA) @MangaSourceParser("LINEWEBTOONS_DE", "LineWebtoons German", "de", type = ContentType.MANGA)
class German(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaSource.LINEWEBTOONS_DE) class German(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaParserSource.LINEWEBTOONS_DE)
private inner class WebtoonsUrlSigner(private val secret: String) { private inner class WebtoonsUrlSigner(private val secret: String) {

@ -24,7 +24,7 @@ private const val CHAPTERS_MAX_COUNT = 10_000 // strange api behavior, looks lik
private const val LOCALE_FALLBACK = "en" private const val LOCALE_FALLBACK = "en"
@MangaSourceParser("MANGADEX", "MangaDex") @MangaSourceParser("MANGADEX", "MangaDex")
internal class MangaDexParser(context: MangaLoaderContext) : MangaParser(context, MangaSource.MANGADEX) { internal class MangaDexParser(context: MangaLoaderContext) : MangaParser(context, MangaParserSource.MANGADEX) {
override val configKeyDomain = ConfigKey.Domain("mangadex.org") override val configKeyDomain = ConfigKey.Domain("mangadex.org")

@ -1,6 +1,8 @@
package org.koitharu.kotatsu.parsers.site.all package org.koitharu.kotatsu.parsers.site.all
import kotlinx.coroutines.* import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Interceptor import okhttp3.Interceptor
import okhttp3.Response import okhttp3.Response
@ -22,9 +24,9 @@ private const val MIN_SPLIT_COUNT = 5
internal abstract class MangaFireParser( internal abstract class MangaFireParser(
context: MangaLoaderContext, context: MangaLoaderContext,
source: MangaSource, source: MangaParserSource,
private val siteLang: String private val siteLang: String,
): PagedMangaParser(context, source, 30), Interceptor { ) : PagedMangaParser(context, source, 30), Interceptor {
override val configKeyDomain: ConfigKey.Domain = ConfigKey.Domain("mangafire.to") override val configKeyDomain: ConfigKey.Domain = ConfigKey.Domain("mangafire.to")
@ -44,7 +46,7 @@ internal abstract class MangaFireParser(
MangaTag( MangaTag(
title = it.selectFirstOrThrow("label").ownText().toTitleCase(sourceLocale), title = it.selectFirstOrThrow("label").ownText().toTitleCase(sourceLocale),
key = it.selectFirstOrThrow("input").attr("value"), key = it.selectFirstOrThrow("input").attr("value"),
source = source source = source,
) )
}.associateBy { it.title } }.associateBy { it.title }
} }
@ -73,7 +75,7 @@ internal abstract class MangaFireParser(
SortOrder.NEWEST -> "release_date" SortOrder.NEWEST -> "release_date"
SortOrder.ALPHABETICAL -> "title_az" SortOrder.ALPHABETICAL -> "title_az"
else -> "" else -> ""
} },
) )
} }
} }
@ -97,7 +99,7 @@ internal abstract class MangaFireParser(
MangaState.ABANDONED -> "discontinued" MangaState.ABANDONED -> "discontinued"
MangaState.PAUSED -> "on_hiatus" MangaState.PAUSED -> "on_hiatus"
MangaState.UPCOMING -> "info" MangaState.UPCOMING -> "info"
} },
) )
} }
addQueryParameter( addQueryParameter(
@ -109,7 +111,7 @@ internal abstract class MangaFireParser(
SortOrder.NEWEST -> "release_date" SortOrder.NEWEST -> "release_date"
SortOrder.ALPHABETICAL -> "title_az" SortOrder.ALPHABETICAL -> "title_az"
else -> "" else -> ""
} },
) )
} }
@ -176,14 +178,14 @@ internal abstract class MangaFireParser(
author = document.select("div.meta a[href*=/author/]") author = document.select("div.meta a[href*=/author/]")
.joinToString { it.ownText().trim() }, .joinToString { it.ownText().trim() },
description = document.selectFirstOrThrow("#synopsis div.modal-content").html(), description = document.selectFirstOrThrow("#synopsis div.modal-content").html(),
chapters = getChapters(manga.url, document) chapters = getChapters(manga.url, document),
) )
} }
private data class ChapterBranch( private data class ChapterBranch(
val type: String, val type: String,
val langCode: String, val langCode: String,
val langTitle: String val langTitle: String,
) )
private suspend fun getChapters(mangaUrl: String, document: Document): List<MangaChapter> { private suspend fun getChapters(mangaUrl: String, document: Document): List<MangaChapter> {
@ -252,7 +254,7 @@ internal abstract class MangaFireParser(
scanlator = null, scanlator = null,
uploadDate = dateFormat.tryParse(it.attr("upload-date")), uploadDate = dateFormat.tryParse(it.attr("upload-date")),
branch = "${branch.langTitle} ${branch.type.toTitleCase()}", branch = "${branch.langTitle} ${branch.type.toTitleCase()}",
source = source source = source,
) )
} }
} }
@ -263,7 +265,7 @@ internal abstract class MangaFireParser(
override suspend fun getRelatedManga(seed: Manga): List<Manga> = coroutineScope { override suspend fun getRelatedManga(seed: Manga): List<Manga> = coroutineScope {
val document = webClient.httpGet(seed.url.toAbsoluteUrl(domain)).parseHtml() val document = webClient.httpGet(seed.url.toAbsoluteUrl(domain)).parseHtml()
val total = document.select( val total = document.select(
"section.m-related a[href*=/manga/], .side-manga:not(:has(.head:contains(trending))) .unit" "section.m-related a[href*=/manga/], .side-manga:not(:has(.head:contains(trending))) .unit",
).size ).size
val mangas = ArrayList<Manga>(total) val mangas = ArrayList<Manga>(total)
@ -322,7 +324,7 @@ internal abstract class MangaFireParser(
rating = RATING_UNKNOWN, rating = RATING_UNKNOWN,
state = null, state = null,
tags = emptySet(), tags = emptySet(),
) ),
) )
} }
@ -366,8 +368,8 @@ internal abstract class MangaFireParser(
"$url#scrambled_$offset" "$url#scrambled_$offset"
}, },
preview = null, preview = null,
source = source source = source,
) ),
) )
} }
@ -425,23 +427,25 @@ internal abstract class MangaFireParser(
private fun Int.ceilDiv(other: Int) = (this + (other - 1)) / other private fun Int.ceilDiv(other: Int) = (this + (other - 1)) / other
@MangaSourceParser("MANGAFIRE_EN", "MangaFire English", "en") @MangaSourceParser("MANGAFIRE_EN", "MangaFire English", "en")
class English(context: MangaLoaderContext) : MangaFireParser(context, MangaSource.MANGAFIRE_EN, "en") class English(context: MangaLoaderContext) : MangaFireParser(context, MangaParserSource.MANGAFIRE_EN, "en")
@MangaSourceParser("MANGAFIRE_ES", "MangaFire Spanish", "es") @MangaSourceParser("MANGAFIRE_ES", "MangaFire Spanish", "es")
class Spanish(context: MangaLoaderContext) : MangaFireParser(context, MangaSource.MANGAFIRE_ES, "es") class Spanish(context: MangaLoaderContext) : MangaFireParser(context, MangaParserSource.MANGAFIRE_ES, "es")
@MangaSourceParser("MANGAFIRE_ESLA", "MangaFire Spanish (Latim)", "es") @MangaSourceParser("MANGAFIRE_ESLA", "MangaFire Spanish (Latim)", "es")
class SpanishLatim(context: MangaLoaderContext) : MangaFireParser(context, MangaSource.MANGAFIRE_ESLA, "es-la") class SpanishLatim(context: MangaLoaderContext) :
MangaFireParser(context, MangaParserSource.MANGAFIRE_ESLA, "es-la")
@MangaSourceParser("MANGAFIRE_FR", "MangaFire French", "fr") @MangaSourceParser("MANGAFIRE_FR", "MangaFire French", "fr")
class French(context: MangaLoaderContext) : MangaFireParser(context, MangaSource.MANGAFIRE_FR, "fr") class French(context: MangaLoaderContext) : MangaFireParser(context, MangaParserSource.MANGAFIRE_FR, "fr")
@MangaSourceParser("MANGAFIRE_JA", "MangaFire Japanese", "ja") @MangaSourceParser("MANGAFIRE_JA", "MangaFire Japanese", "ja")
class Japanese(context: MangaLoaderContext) : MangaFireParser(context, MangaSource.MANGAFIRE_JA, "ja") class Japanese(context: MangaLoaderContext) : MangaFireParser(context, MangaParserSource.MANGAFIRE_JA, "ja")
@MangaSourceParser("MANGAFIRE_PT", "MangaFire Portuguese", "pt") @MangaSourceParser("MANGAFIRE_PT", "MangaFire Portuguese", "pt")
class Portuguese(context: MangaLoaderContext) : MangaFireParser(context, MangaSource.MANGAFIRE_PT, "pt") class Portuguese(context: MangaLoaderContext) : MangaFireParser(context, MangaParserSource.MANGAFIRE_PT, "pt")
@MangaSourceParser("MANGAFIRE_PTBR", "MangaFire Portuguese (Brazil)", "pt") @MangaSourceParser("MANGAFIRE_PTBR", "MangaFire Portuguese (Brazil)", "pt")
class PortugueseBR(context: MangaLoaderContext) : MangaFireParser(context, MangaSource.MANGAFIRE_PTBR, "pt-br") class PortugueseBR(context: MangaLoaderContext) :
MangaFireParser(context, MangaParserSource.MANGAFIRE_PTBR, "pt-br")
} }

@ -14,7 +14,7 @@ import java.util.*
@MangaSourceParser("MANGAPARK", "MangaPark") @MangaSourceParser("MANGAPARK", "MangaPark")
internal class MangaPark(context: MangaLoaderContext) : internal class MangaPark(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.MANGAPARK, pageSize = 36) { PagedMangaParser(context, MangaParserSource.MANGAPARK, pageSize = 36) {
override val availableSortOrders: Set<SortOrder> = EnumSet.allOf(SortOrder::class.java) override val availableSortOrders: Set<SortOrder> = EnumSet.allOf(SortOrder::class.java)

@ -22,7 +22,7 @@ import java.util.*
internal abstract class MangaPlusParser( internal abstract class MangaPlusParser(
context: MangaLoaderContext, context: MangaLoaderContext,
source: MangaSource, source: MangaParserSource,
private val sourceLang: String, private val sourceLang: String,
) : MangaParser(context, source), Interceptor { ) : MangaParser(context, source), Interceptor {
@ -267,63 +267,63 @@ internal abstract class MangaPlusParser(
@MangaSourceParser("MANGAPLUSPARSER_EN", "MANGA Plus English", "en") @MangaSourceParser("MANGAPLUSPARSER_EN", "MANGA Plus English", "en")
class English(context: MangaLoaderContext) : MangaPlusParser( class English(context: MangaLoaderContext) : MangaPlusParser(
context, context,
MangaSource.MANGAPLUSPARSER_EN, MangaParserSource.MANGAPLUSPARSER_EN,
"ENGLISH", "ENGLISH",
) )
@MangaSourceParser("MANGAPLUSPARSER_ES", "MANGA Plus Spanish", "es") @MangaSourceParser("MANGAPLUSPARSER_ES", "MANGA Plus Spanish", "es")
class Spanish(context: MangaLoaderContext) : MangaPlusParser( class Spanish(context: MangaLoaderContext) : MangaPlusParser(
context, context,
MangaSource.MANGAPLUSPARSER_ES, MangaParserSource.MANGAPLUSPARSER_ES,
"SPANISH", "SPANISH",
) )
@MangaSourceParser("MANGAPLUSPARSER_FR", "MANGA Plus French", "fr") @MangaSourceParser("MANGAPLUSPARSER_FR", "MANGA Plus French", "fr")
class French(context: MangaLoaderContext) : MangaPlusParser( class French(context: MangaLoaderContext) : MangaPlusParser(
context, context,
MangaSource.MANGAPLUSPARSER_FR, MangaParserSource.MANGAPLUSPARSER_FR,
"FRENCH", "FRENCH",
) )
@MangaSourceParser("MANGAPLUSPARSER_ID", "MANGA Plus Indonesian", "id") @MangaSourceParser("MANGAPLUSPARSER_ID", "MANGA Plus Indonesian", "id")
class Indonesian(context: MangaLoaderContext) : MangaPlusParser( class Indonesian(context: MangaLoaderContext) : MangaPlusParser(
context, context,
MangaSource.MANGAPLUSPARSER_ID, MangaParserSource.MANGAPLUSPARSER_ID,
"INDONESIAN", "INDONESIAN",
) )
@MangaSourceParser("MANGAPLUSPARSER_PTBR", "MANGA Plus Portuguese (Brazil)", "pt") @MangaSourceParser("MANGAPLUSPARSER_PTBR", "MANGA Plus Portuguese (Brazil)", "pt")
class Portuguese(context: MangaLoaderContext) : MangaPlusParser( class Portuguese(context: MangaLoaderContext) : MangaPlusParser(
context, context,
MangaSource.MANGAPLUSPARSER_PTBR, MangaParserSource.MANGAPLUSPARSER_PTBR,
"PORTUGUESE_BR", "PORTUGUESE_BR",
) )
@MangaSourceParser("MANGAPLUSPARSER_RU", "MANGA Plus Russian", "ru") @MangaSourceParser("MANGAPLUSPARSER_RU", "MANGA Plus Russian", "ru")
class Russian(context: MangaLoaderContext) : MangaPlusParser( class Russian(context: MangaLoaderContext) : MangaPlusParser(
context, context,
MangaSource.MANGAPLUSPARSER_RU, MangaParserSource.MANGAPLUSPARSER_RU,
"RUSSIAN", "RUSSIAN",
) )
@MangaSourceParser("MANGAPLUSPARSER_TH", "MANGA Plus Thai", "th") @MangaSourceParser("MANGAPLUSPARSER_TH", "MANGA Plus Thai", "th")
class Thai(context: MangaLoaderContext) : MangaPlusParser( class Thai(context: MangaLoaderContext) : MangaPlusParser(
context, context,
MangaSource.MANGAPLUSPARSER_TH, MangaParserSource.MANGAPLUSPARSER_TH,
"THAI", "THAI",
) )
@MangaSourceParser("MANGAPLUSPARSER_VI", "MANGA Plus Vietnamese", "vi") @MangaSourceParser("MANGAPLUSPARSER_VI", "MANGA Plus Vietnamese", "vi")
class Vietnamese(context: MangaLoaderContext) : MangaPlusParser( class Vietnamese(context: MangaLoaderContext) : MangaPlusParser(
context, context,
MangaSource.MANGAPLUSPARSER_VI, MangaParserSource.MANGAPLUSPARSER_VI,
"VIETNAMESE", "VIETNAMESE",
) )
@MangaSourceParser("MANGAPLUSPARSER_DE", "MANGA Plus German", "de") @MangaSourceParser("MANGAPLUSPARSER_DE", "MANGA Plus German", "de")
class German(context: MangaLoaderContext) : MangaPlusParser( class German(context: MangaLoaderContext) : MangaPlusParser(
context, context,
MangaSource.MANGAPLUSPARSER_DE, MangaParserSource.MANGAPLUSPARSER_DE,
"GERMAN" "GERMAN",
) )
} }

@ -20,7 +20,7 @@ import javax.crypto.spec.SecretKeySpec
import kotlin.math.min import kotlin.math.min
@MangaSourceParser("MANGAREADERTO", "MangaReader.To") @MangaSourceParser("MANGAREADERTO", "MangaReader.To")
class MangaReaderToParser(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.MANGAREADERTO, 16), class MangaReaderToParser(context: MangaLoaderContext) : PagedMangaParser(context, MangaParserSource.MANGAREADERTO, 16),
Interceptor { Interceptor {
override val configKeyDomain = ConfigKey.Domain("mangareader.to") override val configKeyDomain = ConfigKey.Domain("mangareader.to")

@ -17,7 +17,7 @@ import java.util.*
internal abstract class NineMangaParser( internal abstract class NineMangaParser(
context: MangaLoaderContext, context: MangaLoaderContext,
source: MangaSource, source: MangaParserSource,
defaultDomain: String, defaultDomain: String,
) : PagedMangaParser(context, source, pageSize = 26), Interceptor { ) : PagedMangaParser(context, source, pageSize = 26), Interceptor {
@ -266,49 +266,49 @@ internal abstract class NineMangaParser(
@MangaSourceParser("NINEMANGA_EN", "NineManga English", "en") @MangaSourceParser("NINEMANGA_EN", "NineManga English", "en")
class English(context: MangaLoaderContext) : NineMangaParser( class English(context: MangaLoaderContext) : NineMangaParser(
context, context,
MangaSource.NINEMANGA_EN, MangaParserSource.NINEMANGA_EN,
"www.ninemanga.com", "www.ninemanga.com",
) )
@MangaSourceParser("NINEMANGA_ES", "NineManga Español", "es") @MangaSourceParser("NINEMANGA_ES", "NineManga Español", "es")
class Spanish(context: MangaLoaderContext) : NineMangaParser( class Spanish(context: MangaLoaderContext) : NineMangaParser(
context, context,
MangaSource.NINEMANGA_ES, MangaParserSource.NINEMANGA_ES,
"es.ninemanga.com", "es.ninemanga.com",
) )
@MangaSourceParser("NINEMANGA_RU", "NineManga Русский", "ru") @MangaSourceParser("NINEMANGA_RU", "NineManga Русский", "ru")
class Russian(context: MangaLoaderContext) : NineMangaParser( class Russian(context: MangaLoaderContext) : NineMangaParser(
context, context,
MangaSource.NINEMANGA_RU, MangaParserSource.NINEMANGA_RU,
"ru.ninemanga.com", "ru.ninemanga.com",
) )
@MangaSourceParser("NINEMANGA_DE", "NineManga Deutsch", "de") @MangaSourceParser("NINEMANGA_DE", "NineManga Deutsch", "de")
class Deutsch(context: MangaLoaderContext) : NineMangaParser( class Deutsch(context: MangaLoaderContext) : NineMangaParser(
context, context,
MangaSource.NINEMANGA_DE, MangaParserSource.NINEMANGA_DE,
"de.ninemanga.com", "de.ninemanga.com",
) )
@MangaSourceParser("NINEMANGA_BR", "NineManga Brasil", "pt") @MangaSourceParser("NINEMANGA_BR", "NineManga Brasil", "pt")
class Brazil(context: MangaLoaderContext) : NineMangaParser( class Brazil(context: MangaLoaderContext) : NineMangaParser(
context, context,
MangaSource.NINEMANGA_BR, MangaParserSource.NINEMANGA_BR,
"br.ninemanga.com", "br.ninemanga.com",
) )
@MangaSourceParser("NINEMANGA_IT", "NineManga Italiano", "it") @MangaSourceParser("NINEMANGA_IT", "NineManga Italiano", "it")
class Italiano(context: MangaLoaderContext) : NineMangaParser( class Italiano(context: MangaLoaderContext) : NineMangaParser(
context, context,
MangaSource.NINEMANGA_IT, MangaParserSource.NINEMANGA_IT,
"it.ninemanga.com", "it.ninemanga.com",
) )
@MangaSourceParser("NINEMANGA_FR", "NineManga Français", "fr") @MangaSourceParser("NINEMANGA_FR", "NineManga Français", "fr")
class Francais(context: MangaLoaderContext) : NineMangaParser( class Francais(context: MangaLoaderContext) : NineMangaParser(
context, context,
MangaSource.NINEMANGA_FR, MangaParserSource.NINEMANGA_FR,
"fr.ninemanga.com", "fr.ninemanga.com",
) )
} }

@ -20,7 +20,7 @@ import java.util.*
@MangaSourceParser("NINENINENINEHENTAI", "999Hentai", type = ContentType.HENTAI) @MangaSourceParser("NINENINENINEHENTAI", "999Hentai", type = ContentType.HENTAI)
internal class NineNineNineHentaiParser(context: MangaLoaderContext) : internal class NineNineNineHentaiParser(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.NINENINENINEHENTAI, size), Interceptor { PagedMangaParser(context, MangaParserSource.NINENINENINEHENTAI, size), Interceptor {
override val configKeyDomain = ConfigKey.Domain("999hentai.net") override val configKeyDomain = ConfigKey.Domain("999hentai.net")

@ -14,39 +14,16 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.exception.NotFoundException import org.koitharu.kotatsu.parsers.exception.NotFoundException
import org.koitharu.kotatsu.parsers.exception.ParseException import org.koitharu.kotatsu.parsers.exception.ParseException
import org.koitharu.kotatsu.parsers.model.ContentType import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.util.json.*
import org.koitharu.kotatsu.parsers.model.MangaListFilter import java.util.*
import org.koitharu.kotatsu.parsers.model.MangaPage
import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.parsers.model.RATING_UNKNOWN
import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.parsers.util.SoftSuspendLazy
import org.koitharu.kotatsu.parsers.util.SuspendLazy
import org.koitharu.kotatsu.parsers.util.domain
import org.koitharu.kotatsu.parsers.util.generateUid
import org.koitharu.kotatsu.parsers.util.json.getBooleanOrDefault
import org.koitharu.kotatsu.parsers.util.json.getFloatOrDefault
import org.koitharu.kotatsu.parsers.util.json.getIntOrDefault
import org.koitharu.kotatsu.parsers.util.json.getStringOrNull
import org.koitharu.kotatsu.parsers.util.json.mapJSON
import org.koitharu.kotatsu.parsers.util.json.mapJSONIndexed
import org.koitharu.kotatsu.parsers.util.mapChapters
import org.koitharu.kotatsu.parsers.util.oneOrThrowIfMany
import org.koitharu.kotatsu.parsers.util.parseJson
import org.koitharu.kotatsu.parsers.util.splitTwoParts
import org.koitharu.kotatsu.parsers.util.toAbsoluteUrl
import org.koitharu.kotatsu.parsers.util.urlEncoded
import java.util.Calendar
import java.util.EnumSet
import javax.crypto.Mac import javax.crypto.Mac
import javax.crypto.spec.SecretKeySpec import javax.crypto.spec.SecretKeySpec
internal abstract class WebtoonsParser( internal abstract class WebtoonsParser(
context: MangaLoaderContext, context: MangaLoaderContext,
source: MangaSource, source: MangaParserSource,
) : MangaParser(context, source) { ) : MangaParser(context, source) {
override val isMultipleTagsSupported = false override val isMultipleTagsSupported = false
@ -223,7 +200,8 @@ internal abstract class WebtoonsParser(
description = null, description = null,
state = null, state = null,
source = source, source = source,
)) ),
)
} }
} }
@ -305,25 +283,25 @@ internal abstract class WebtoonsParser(
} }
@MangaSourceParser("WEBTOONS_EN", "Webtoons English", "en", type = ContentType.MANGA) @MangaSourceParser("WEBTOONS_EN", "Webtoons English", "en", type = ContentType.MANGA)
class English(context: MangaLoaderContext) : WebtoonsParser(context, MangaSource.WEBTOONS_EN) class English(context: MangaLoaderContext) : WebtoonsParser(context, MangaParserSource.WEBTOONS_EN)
@MangaSourceParser("WEBTOONS_ID", "Webtoons Indonesia", "id", type = ContentType.MANGA) @MangaSourceParser("WEBTOONS_ID", "Webtoons Indonesia", "id", type = ContentType.MANGA)
class Indonesian(context: MangaLoaderContext) : WebtoonsParser(context, MangaSource.WEBTOONS_ID) class Indonesian(context: MangaLoaderContext) : WebtoonsParser(context, MangaParserSource.WEBTOONS_ID)
@MangaSourceParser("WEBTOONS_ES", "Webtoons Spanish", "es", type = ContentType.MANGA) @MangaSourceParser("WEBTOONS_ES", "Webtoons Spanish", "es", type = ContentType.MANGA)
class Spanish(context: MangaLoaderContext) : WebtoonsParser(context, MangaSource.WEBTOONS_ES) class Spanish(context: MangaLoaderContext) : WebtoonsParser(context, MangaParserSource.WEBTOONS_ES)
@MangaSourceParser("WEBTOONS_FR", "Webtoons French", "fr", type = ContentType.MANGA) @MangaSourceParser("WEBTOONS_FR", "Webtoons French", "fr", type = ContentType.MANGA)
class French(context: MangaLoaderContext) : WebtoonsParser(context, MangaSource.WEBTOONS_FR) class French(context: MangaLoaderContext) : WebtoonsParser(context, MangaParserSource.WEBTOONS_FR)
@MangaSourceParser("WEBTOONS_TH", "Webtoons Thai", "th", type = ContentType.MANGA) @MangaSourceParser("WEBTOONS_TH", "Webtoons Thai", "th", type = ContentType.MANGA)
class Thai(context: MangaLoaderContext) : WebtoonsParser(context, MangaSource.WEBTOONS_TH) class Thai(context: MangaLoaderContext) : WebtoonsParser(context, MangaParserSource.WEBTOONS_TH)
@MangaSourceParser("WEBTOONS_ZH", "Webtoons Chinese", "zh", type = ContentType.MANGA) @MangaSourceParser("WEBTOONS_ZH", "Webtoons Chinese", "zh", type = ContentType.MANGA)
class Chinese(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaSource.WEBTOONS_ZH) class Chinese(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaParserSource.WEBTOONS_ZH)
@MangaSourceParser("WEBTOONS_DE", "Webtoons German", "de", type = ContentType.MANGA) @MangaSourceParser("WEBTOONS_DE", "Webtoons German", "de", type = ContentType.MANGA)
class German(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaSource.WEBTOONS_DE) class German(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaParserSource.WEBTOONS_DE)
private inner class WebtoonsUrlSigner(private val secret: String) { private inner class WebtoonsUrlSigner(private val secret: String) {

@ -13,7 +13,7 @@ import java.util.*
internal abstract class AnimeBootstrapParser( internal abstract class AnimeBootstrapParser(
context: MangaLoaderContext, context: MangaLoaderContext,
source: MangaSource, source: MangaParserSource,
domain: String, domain: String,
pageSize: Int = 24, pageSize: Int = 24,
) : PagedMangaParser(context, source, pageSize) { ) : PagedMangaParser(context, source, pageSize) {

@ -9,12 +9,11 @@ import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.site.animebootstrap.AnimeBootstrapParser import org.koitharu.kotatsu.parsers.site.animebootstrap.AnimeBootstrapParser
import org.koitharu.kotatsu.parsers.util.* import org.koitharu.kotatsu.parsers.util.*
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.EnumSet import java.util.*
import java.util.Locale
@MangaSourceParser("PAPSCAN", "PapScan", "fr") @MangaSourceParser("PAPSCAN", "PapScan", "fr")
internal class PapScan(context: MangaLoaderContext) : internal class PapScan(context: MangaLoaderContext) :
AnimeBootstrapParser(context, MangaSource.PAPSCAN, "papscan.com") { AnimeBootstrapParser(context, MangaParserSource.PAPSCAN, "papscan.com") {
override val sourceLocale: Locale = Locale.ENGLISH override val sourceLocale: Locale = Locale.ENGLISH
override val isMultipleTagsSupported = false override val isMultipleTagsSupported = false
override val listUrl = "/liste-manga" override val listUrl = "/liste-manga"

@ -2,9 +2,9 @@ package org.koitharu.kotatsu.parsers.site.animebootstrap.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.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.animebootstrap.AnimeBootstrapParser import org.koitharu.kotatsu.parsers.site.animebootstrap.AnimeBootstrapParser
@MangaSourceParser("KOMIKZOID", "KomikzoId", "id") @MangaSourceParser("KOMIKZOID", "KomikzoId", "id")
internal class KomikzoId(context: MangaLoaderContext) : internal class KomikzoId(context: MangaLoaderContext) :
AnimeBootstrapParser(context, MangaSource.KOMIKZOID, "komikzoid.id") AnimeBootstrapParser(context, MangaParserSource.KOMIKZOID, "komikzoid.id")

@ -2,9 +2,9 @@ package org.koitharu.kotatsu.parsers.site.animebootstrap.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.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.animebootstrap.AnimeBootstrapParser import org.koitharu.kotatsu.parsers.site.animebootstrap.AnimeBootstrapParser
@MangaSourceParser("NEUMANGA", "NeuManga.xyz", "id") @MangaSourceParser("NEUMANGA", "NeuManga.xyz", "id")
internal class NeuManga(context: MangaLoaderContext) : internal class NeuManga(context: MangaLoaderContext) :
AnimeBootstrapParser(context, MangaSource.NEUMANGA, "neumanga.xyz") AnimeBootstrapParser(context, MangaParserSource.NEUMANGA, "neumanga.xyz")

@ -2,9 +2,9 @@ package org.koitharu.kotatsu.parsers.site.animebootstrap.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.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.animebootstrap.AnimeBootstrapParser import org.koitharu.kotatsu.parsers.site.animebootstrap.AnimeBootstrapParser
@MangaSourceParser("SEKTEKOMIK", "SekteKomik", "id") @MangaSourceParser("SEKTEKOMIK", "SekteKomik", "id")
internal class SekteKomik(context: MangaLoaderContext) : internal class SekteKomik(context: MangaLoaderContext) :
AnimeBootstrapParser(context, MangaSource.SEKTEKOMIK, "sektekomik.xyz") AnimeBootstrapParser(context, MangaParserSource.SEKTEKOMIK, "sektekomik.xyz")

@ -16,7 +16,7 @@ import java.text.SimpleDateFormat
import java.util.* import java.util.*
@MangaSourceParser("FLIXSCANS", "FlixScans.net", "ar") @MangaSourceParser("FLIXSCANS", "FlixScans.net", "ar")
internal class FlixScans(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.FLIXSCANS, 18) { internal class FlixScans(context: MangaLoaderContext) : PagedMangaParser(context, MangaParserSource.FLIXSCANS, 18) {
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)

@ -11,7 +11,7 @@ import org.koitharu.kotatsu.parsers.util.*
import java.util.* import java.util.*
@MangaSourceParser("MANGASTORM", "MangaStorm", "ar") @MangaSourceParser("MANGASTORM", "MangaStorm", "ar")
internal class MangaStorm(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.MANGASTORM, 30) { internal class MangaStorm(context: MangaLoaderContext) : PagedMangaParser(context, MangaParserSource.MANGASTORM, 30) {
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.POPULARITY, SortOrder.UPDATED) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.POPULARITY, SortOrder.UPDATED)
override val configKeyDomain = ConfigKey.Domain("mangastorm.org") override val configKeyDomain = ConfigKey.Domain("mangastorm.org")

@ -14,7 +14,7 @@ import java.text.SimpleDateFormat
import java.util.* import java.util.*
@MangaSourceParser("TEAMXNOVEL", "TeamXNovel", "ar") @MangaSourceParser("TEAMXNOVEL", "TeamXNovel", "ar")
internal class TeamXNovel(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.TEAMXNOVEL, 10) { internal class TeamXNovel(context: MangaLoaderContext) : PagedMangaParser(context, MangaParserSource.TEAMXNOVEL, 10) {
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY)
override val availableStates: Set<MangaState> = override val availableStates: Set<MangaState> =

@ -21,7 +21,7 @@ import java.util.*
@Broken @Broken
@MangaSourceParser("ANIBEL", "Anibel", "be") @MangaSourceParser("ANIBEL", "Anibel", "be")
internal class AnibelParser(context: MangaLoaderContext) : MangaParser(context, MangaSource.ANIBEL) { internal class AnibelParser(context: MangaLoaderContext) : MangaParser(context, MangaParserSource.ANIBEL) {
override val configKeyDomain = ConfigKey.Domain("anibel.net") override val configKeyDomain = ConfigKey.Domain("anibel.net")

@ -11,7 +11,7 @@ import java.util.*
@MangaSourceParser("BEETOON", "BeeToon.net", "en") @MangaSourceParser("BEETOON", "BeeToon.net", "en")
internal class BeeToon(context: MangaLoaderContext) : internal class BeeToon(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.BEETOON, pageSize = 30) { PagedMangaParser(context, MangaParserSource.BEETOON, pageSize = 30) {
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY)

@ -10,7 +10,7 @@ import org.koitharu.kotatsu.parsers.util.*
import java.util.* import java.util.*
@MangaSourceParser("CLONEMANGA", "CloneManga", "en") @MangaSourceParser("CLONEMANGA", "CloneManga", "en")
internal class CloneMangaParser(context: MangaLoaderContext) : MangaParser(context, MangaSource.CLONEMANGA) { internal class CloneMangaParser(context: MangaLoaderContext) : MangaParser(context, MangaParserSource.CLONEMANGA) {
override val availableSortOrders: Set<SortOrder> = Collections.singleton( override val availableSortOrders: Set<SortOrder> = Collections.singleton(
SortOrder.POPULARITY, SortOrder.POPULARITY,

@ -13,7 +13,7 @@ import java.text.SimpleDateFormat
import java.util.* import java.util.*
@MangaSourceParser("COMICEXTRA", "ComicExtra", "en") @MangaSourceParser("COMICEXTRA", "ComicExtra", "en")
internal class ComicExtra(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.COMICEXTRA, 25) { internal class ComicExtra(context: MangaLoaderContext) : PagedMangaParser(context, MangaParserSource.COMICEXTRA, 25) {
override val availableSortOrders: Set<SortOrder> = override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.POPULARITY, SortOrder.UPDATED, SortOrder.NEWEST) EnumSet.of(SortOrder.POPULARITY, SortOrder.UPDATED, SortOrder.NEWEST)

@ -19,7 +19,8 @@ import java.text.SimpleDateFormat
import java.util.* import java.util.*
@MangaSourceParser("DYNASTYSCANS", "DynastyScans", "en") @MangaSourceParser("DYNASTYSCANS", "DynastyScans", "en")
internal class DynastyScans(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.DYNASTYSCANS, 117) { internal class DynastyScans(context: MangaLoaderContext) :
PagedMangaParser(context, MangaParserSource.DYNASTYSCANS, 117) {
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL)
override val configKeyDomain = ConfigKey.Domain("dynasty-scans.com") override val configKeyDomain = ConfigKey.Domain("dynasty-scans.com")

@ -16,7 +16,8 @@ import java.text.SimpleDateFormat
import java.util.* import java.util.*
@MangaSourceParser("FLIXSCANSORG", "FlixScans.org", "en") @MangaSourceParser("FLIXSCANSORG", "FlixScans.org", "en")
internal class FlixScansOrg(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.FLIXSCANSORG, 18) { internal class FlixScansOrg(context: MangaLoaderContext) :
PagedMangaParser(context, MangaParserSource.FLIXSCANSORG, 18) {
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)

@ -14,7 +14,7 @@ import java.text.SimpleDateFormat
import java.util.* import java.util.*
@MangaSourceParser("MANGAGEKO", "MangaGeko", "en") @MangaSourceParser("MANGAGEKO", "MangaGeko", "en")
internal class MangaGeko(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.MANGAGEKO, 30) { internal class MangaGeko(context: MangaLoaderContext) : PagedMangaParser(context, MangaParserSource.MANGAGEKO, 30) {
override val availableSortOrders: Set<SortOrder> = override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.POPULARITY, SortOrder.UPDATED, SortOrder.NEWEST) EnumSet.of(SortOrder.POPULARITY, SortOrder.UPDATED, SortOrder.NEWEST)

@ -1,6 +1,8 @@
package org.koitharu.kotatsu.parsers.site.en package org.koitharu.kotatsu.parsers.site.en
import org.koitharu.kotatsu.parsers.* import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.PagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey 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.*
@ -9,7 +11,8 @@ import java.text.SimpleDateFormat
import java.util.* import java.util.*
@MangaSourceParser("MANGATOWN", "MangaTown", "en") @MangaSourceParser("MANGATOWN", "MangaTown", "en")
internal class MangaTownParser(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.MANGATOWN, 30) { internal class MangaTownParser(context: MangaLoaderContext) :
PagedMangaParser(context, MangaParserSource.MANGATOWN, 30) {
override val configKeyDomain = ConfigKey.Domain("www.mangatown.com") override val configKeyDomain = ConfigKey.Domain("www.mangatown.com")
@ -27,7 +30,7 @@ internal class MangaTownParser(context: MangaLoaderContext) : PagedMangaParser(c
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 {
append("https://") append("https://")
append(domain) append(domain)
@ -102,7 +105,7 @@ internal class MangaTownParser(context: MangaLoaderContext) : PagedMangaParser(c
id = generateUid(href), id = generateUid(href),
title = a.attr("title"), title = a.attr("title"),
coverUrl = a.selectFirst("img")?.absUrl("src").orEmpty(), coverUrl = a.selectFirst("img")?.absUrl("src").orEmpty(),
source = MangaSource.MANGATOWN, source = MangaParserSource.MANGATOWN,
altTitle = null, altTitle = null,
rating = li.selectFirst("p.score")?.selectFirst("b") rating = li.selectFirst("p.score")?.selectFirst("b")
?.ownText()?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN, ?.ownText()?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
@ -118,7 +121,7 @@ internal class MangaTownParser(context: MangaLoaderContext) : PagedMangaParser(c
MangaTag( MangaTag(
title = x.attr("title").toTitleCase(), title = x.attr("title").toTitleCase(),
key = x.attr("href").substringAfter("/directory/0-").substringBefore("-0-"), key = x.attr("href").substringAfter("/directory/0-").substringBefore("-0-"),
source = MangaSource.MANGATOWN, source = MangaParserSource.MANGATOWN,
) )
}.orEmpty(), }.orEmpty(),
url = href, url = href,
@ -143,7 +146,7 @@ internal class MangaTownParser(context: MangaLoaderContext) : PagedMangaParser(c
MangaTag( MangaTag(
title = a.attr("title").toTitleCase(), title = a.attr("title").toTitleCase(),
key = a.attr("href").substringAfter("/directory/0-").substringBefore("-0-"), key = a.attr("href").substringAfter("/directory/0-").substringBefore("-0-"),
source = MangaSource.MANGATOWN, source = MangaParserSource.MANGATOWN,
) )
}.orEmpty(), }.orEmpty(),
description = info?.getElementById("show")?.ownText(), description = info?.getElementById("show")?.ownText(),
@ -156,7 +159,7 @@ internal class MangaTownParser(context: MangaLoaderContext) : PagedMangaParser(c
MangaChapter( MangaChapter(
id = generateUid(href), id = generateUid(href),
url = href, url = href,
source = MangaSource.MANGATOWN, source = MangaParserSource.MANGATOWN,
number = i + 1, number = i + 1,
uploadDate = parseChapterDate( uploadDate = parseChapterDate(
dateFormat, dateFormat,
@ -176,7 +179,7 @@ internal class MangaTownParser(context: MangaLoaderContext) : PagedMangaParser(c
val root = doc.body().selectFirstOrThrow("div.page_select") val root = doc.body().selectFirstOrThrow("div.page_select")
val isManga = root.select("select") val isManga = root.select("select")
if(isManga.isEmpty()){//Webtoon if (isManga.isEmpty()) {//Webtoon
val imgElements = doc.select("div#viewer.read_img img.image") val imgElements = doc.select("div#viewer.read_img img.image")
return imgElements.map { return imgElements.map {
val href = it.attr("src") val href = it.attr("src")
@ -184,11 +187,11 @@ internal class MangaTownParser(context: MangaLoaderContext) : PagedMangaParser(c
id = generateUid(href), id = generateUid(href),
url = href, url = href,
preview = null, preview = null,
source = MangaSource.MANGATOWN, source = MangaParserSource.MANGATOWN,
) )
} }
}else{ //Manga } else { //Manga
return isManga.select("option").mapNotNull { return isManga.select("option").mapNotNull {
val href = it.attrAsRelativeUrlOrNull("value") val href = it.attrAsRelativeUrlOrNull("value")
if (href == null || href.endsWith("featured.html")) { if (href == null || href.endsWith("featured.html")) {
@ -198,14 +201,14 @@ internal class MangaTownParser(context: MangaLoaderContext) : PagedMangaParser(c
id = generateUid(href), id = generateUid(href),
url = href, url = href,
preview = null, preview = null,
source = MangaSource.MANGATOWN, source = MangaParserSource.MANGATOWN,
) )
} }
} }
} }
override suspend fun getPageUrl(page: MangaPage): String { override suspend fun getPageUrl(page: MangaPage): String {
if(page.url.startsWith("//")){//Webtoon if (page.url.startsWith("//")) {//Webtoon
return page.url.toAbsoluteUrl(domain) return page.url.toAbsoluteUrl(domain)
} }
@ -223,7 +226,7 @@ internal class MangaTownParser(context: MangaLoaderContext) : PagedMangaParser(c
val a = li.selectFirst("a") ?: return@mapNotNullToSet null val a = li.selectFirst("a") ?: return@mapNotNullToSet null
val key = a.attr("href").substringAfter("/directory/0-").substringBefore("-0-") val key = a.attr("href").substringAfter("/directory/0-").substringBefore("-0-")
MangaTag( MangaTag(
source = MangaSource.MANGATOWN, source = MangaParserSource.MANGATOWN,
key = key, key = key,
title = a.text().toTitleCase(), title = a.text().toTitleCase(),
) )
@ -252,7 +255,7 @@ internal class MangaTownParser(context: MangaLoaderContext) : PagedMangaParser(c
MangaChapter( MangaChapter(
id = generateUid(href), id = generateUid(href),
url = href, url = href,
source = MangaSource.MANGATOWN, source = MangaParserSource.MANGATOWN,
number = i + 1, number = i + 1,
uploadDate = parseChapterDate( uploadDate = parseChapterDate(
dateFormat, dateFormat,

@ -16,7 +16,7 @@ import java.util.*
@MangaSourceParser("MANGAOWL", "MangaOwl.to", "en") @MangaSourceParser("MANGAOWL", "MangaOwl.to", "en")
internal class Mangaowl(context: MangaLoaderContext) : internal class Mangaowl(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.MANGAOWL, pageSize = 24) { PagedMangaParser(context, MangaParserSource.MANGAOWL, pageSize = 24) {
override val availableSortOrders: Set<SortOrder> = EnumSet.of( override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.POPULARITY, SortOrder.POPULARITY,

@ -11,7 +11,7 @@ import java.util.*
@MangaSourceParser("MANHWA18", "Manhwa18.net", "en", type = ContentType.HENTAI) @MangaSourceParser("MANHWA18", "Manhwa18.net", "en", type = ContentType.HENTAI)
class Manhwa18Parser(context: MangaLoaderContext) : class Manhwa18Parser(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.MANHWA18, pageSize = 18, searchPageSize = 18) { PagedMangaParser(context, MangaParserSource.MANHWA18, pageSize = 18, searchPageSize = 18) {
override val configKeyDomain: ConfigKey.Domain = ConfigKey.Domain("manhwa18.net") override val configKeyDomain: ConfigKey.Domain = ConfigKey.Domain("manhwa18.net")
@ -122,7 +122,7 @@ class Manhwa18Parser(context: MangaLoaderContext) :
author = null, author = null,
largeCoverUrl = null, largeCoverUrl = null,
description = null, description = null,
source = MangaSource.MANHWA18, source = MangaParserSource.MANHWA18,
) )
} }
} }
@ -166,7 +166,7 @@ class Manhwa18Parser(context: MangaLoaderContext) :
scanlator = null, scanlator = null,
uploadDate = uploadDate, uploadDate = uploadDate,
branch = null, branch = null,
source = MangaSource.MANHWA18, source = MangaParserSource.MANHWA18,
) )
}, },
) )
@ -209,7 +209,7 @@ class Manhwa18Parser(context: MangaLoaderContext) :
id = generateUid(url), id = generateUid(url),
url = url, url = url,
preview = null, preview = null,
source = MangaSource.MANHWA18, source = MangaParserSource.MANHWA18,
) )
} }
} }

@ -12,7 +12,7 @@ import java.util.*
@MangaSourceParser("MANHWASMEN", "ManhwasMen", "en", type = ContentType.HENTAI) @MangaSourceParser("MANHWASMEN", "ManhwasMen", "en", type = ContentType.HENTAI)
class ManhwasMen(context: MangaLoaderContext) : class ManhwasMen(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.MANHWASMEN, pageSize = 30, searchPageSize = 30) { PagedMangaParser(context, MangaParserSource.MANHWASMEN, pageSize = 30, searchPageSize = 30) {
override val configKeyDomain: ConfigKey.Domain = ConfigKey.Domain("manhwas.men") override val configKeyDomain: ConfigKey.Domain = ConfigKey.Domain("manhwas.men")

@ -10,7 +10,7 @@ import java.text.SimpleDateFormat
import java.util.* import java.util.*
@MangaSourceParser("PO2SCANS", "Po2Scans", "en") @MangaSourceParser("PO2SCANS", "Po2Scans", "en")
internal class Po2Scans(context: MangaLoaderContext) : MangaParser(context, MangaSource.PO2SCANS) { internal class Po2Scans(context: MangaLoaderContext) : MangaParser(context, MangaParserSource.PO2SCANS) {
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL)
override val configKeyDomain = ConfigKey.Domain("po2scans.com") override val configKeyDomain = ConfigKey.Domain("po2scans.com")

@ -15,7 +15,7 @@ import java.util.*
@MangaSourceParser("PURURIN", "Pururin", "en", ContentType.HENTAI) @MangaSourceParser("PURURIN", "Pururin", "en", ContentType.HENTAI)
internal class Pururin(context: MangaLoaderContext) : internal class Pururin(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.PURURIN, pageSize = 20) { PagedMangaParser(context, MangaParserSource.PURURIN, pageSize = 20) {
override val availableSortOrders: Set<SortOrder> = override val availableSortOrders: Set<SortOrder> =
EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.RATING, SortOrder.ALPHABETICAL) EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.RATING, SortOrder.ALPHABETICAL)

@ -29,7 +29,7 @@ private val JSON_MEDIA_TYPE get() = "application/json; charset=utf-8".toMediaTyp
@MangaSourceParser("REAPERCOMICS", "ReaperComics", "en") @MangaSourceParser("REAPERCOMICS", "ReaperComics", "en")
internal class ReaperComics(context: MangaLoaderContext) : internal class ReaperComics(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.REAPERCOMICS, pageSize = 32) { PagedMangaParser(context, MangaParserSource.REAPERCOMICS, pageSize = 32) {
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.ALPHABETICAL) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.ALPHABETICAL)

@ -15,7 +15,7 @@ import java.util.*
@MangaSourceParser("TEMPLESCANESP", "TempleScanEsp", "es", ContentType.HENTAI) @MangaSourceParser("TEMPLESCANESP", "TempleScanEsp", "es", ContentType.HENTAI)
internal class TempleScanEsp(context: MangaLoaderContext) : internal class TempleScanEsp(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.TEMPLESCANESP, pageSize = 15) { PagedMangaParser(context, MangaParserSource.TEMPLESCANESP, pageSize = 15) {
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.NEWEST, SortOrder.UPDATED) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.NEWEST, SortOrder.UPDATED)

@ -16,7 +16,7 @@ import java.util.*
@MangaSourceParser("TUMANGAONLINE", "TuMangaOnline", "es") @MangaSourceParser("TUMANGAONLINE", "TuMangaOnline", "es")
class TuMangaOnlineParser(context: MangaLoaderContext) : PagedMangaParser( class TuMangaOnlineParser(context: MangaLoaderContext) : PagedMangaParser(
context, context,
source = MangaSource.TUMANGAONLINE, source = MangaParserSource.TUMANGAONLINE,
pageSize = 24, pageSize = 24,
) { ) {

@ -14,7 +14,7 @@ import java.util.*
internal abstract class FmreaderParser( internal abstract class FmreaderParser(
context: MangaLoaderContext, context: MangaLoaderContext,
source: MangaSource, source: MangaParserSource,
domain: String, domain: String,
pageSize: Int = 20, pageSize: Int = 20,
) : PagedMangaParser(context, source, pageSize) { ) : PagedMangaParser(context, source, pageSize) {

@ -12,7 +12,7 @@ import java.text.SimpleDateFormat
@MangaSourceParser("MANHWA18COM", "Manhwa18.com", "en", ContentType.HENTAI) @MangaSourceParser("MANHWA18COM", "Manhwa18.com", "en", ContentType.HENTAI)
internal class Manhwa18Com(context: MangaLoaderContext) : internal class Manhwa18Com(context: MangaLoaderContext) :
FmreaderParser(context, MangaSource.MANHWA18COM, "manhwa18.com") { FmreaderParser(context, MangaParserSource.MANHWA18COM, "manhwa18.com") {
override val listUrl = "/tim-kiem" override val listUrl = "/tim-kiem"
override val selectState = "div.info-item:contains(Status) span.info-value " override val selectState = "div.info-item:contains(Status) span.info-value "

@ -8,7 +8,7 @@ import org.koitharu.kotatsu.parsers.util.*
@MangaSourceParser("OLIMPOSCANS", "OlimpoScans", "es") @MangaSourceParser("OLIMPOSCANS", "OlimpoScans", "es")
internal class OlimpoScans(context: MangaLoaderContext) : internal class OlimpoScans(context: MangaLoaderContext) :
FmreaderParser(context, MangaSource.OLIMPOSCANS, "olimposcans.com") { FmreaderParser(context, MangaParserSource.OLIMPOSCANS, "olimposcans.com") {
override val selectState = "ul.manga-info li:contains(Estado) a" override val selectState = "ul.manga-info li:contains(Estado) a"
override val selectAlt = "ul.manga-info li:contains(Otros nombres)" override val selectAlt = "ul.manga-info li:contains(Otros nombres)"

@ -11,7 +11,7 @@ import java.text.SimpleDateFormat
@MangaSourceParser("KLZ9", "Klz9", "ja") @MangaSourceParser("KLZ9", "Klz9", "ja")
internal class Klz9(context: MangaLoaderContext) : internal class Klz9(context: MangaLoaderContext) :
FmreaderParser(context, MangaSource.KLZ9, "klz9.com") { FmreaderParser(context, MangaParserSource.KLZ9, "klz9.com") {
override val selectDesc = "div.row:contains(Description)" override val selectDesc = "div.row:contains(Description)"
override val selectState = "ul.manga-info li:contains(Status) a" override val selectState = "ul.manga-info li:contains(Status) a"

@ -5,14 +5,14 @@ import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaChapter
import org.koitharu.kotatsu.parsers.model.MangaPage import org.koitharu.kotatsu.parsers.model.MangaPage
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.fmreader.FmreaderParser import org.koitharu.kotatsu.parsers.site.fmreader.FmreaderParser
import org.koitharu.kotatsu.parsers.util.* import org.koitharu.kotatsu.parsers.util.*
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
@MangaSourceParser("WELOVEMANGA", "WeLoveManga", "ja") @MangaSourceParser("WELOVEMANGA", "WeLoveManga", "ja")
internal class WeLoveManga(context: MangaLoaderContext) : internal class WeLoveManga(context: MangaLoaderContext) :
FmreaderParser(context, MangaSource.WELOVEMANGA, "welovemanga.one") { FmreaderParser(context, MangaParserSource.WELOVEMANGA, "welovemanga.one") {
override suspend fun getChapters(doc: Document): List<MangaChapter> { override suspend fun getChapters(doc: Document): List<MangaChapter> {
val mid = doc.selectFirstOrThrow("div.cmt input").attr("value") val mid = doc.selectFirstOrThrow("div.cmt input").attr("value")

@ -2,9 +2,9 @@ package org.koitharu.kotatsu.parsers.site.fmreader.ja
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.MangaParserSource
import org.koitharu.kotatsu.parsers.site.fmreader.FmreaderParser import org.koitharu.kotatsu.parsers.site.fmreader.FmreaderParser
@MangaSourceParser("WELOMA", "Weloma", "ja") @MangaSourceParser("WELOMA", "Weloma", "ja")
internal class Weloma(context: MangaLoaderContext) : internal class Weloma(context: MangaLoaderContext) :
FmreaderParser(context, MangaSource.WELOMA, "weloma.art") FmreaderParser(context, MangaParserSource.WELOMA, "weloma.art")

@ -13,7 +13,7 @@ import java.util.*
internal abstract class FoolSlideParser( internal abstract class FoolSlideParser(
context: MangaLoaderContext, context: MangaLoaderContext,
source: MangaSource, source: MangaParserSource,
domain: String, domain: String,
pageSize: Int = 25, pageSize: Int = 25,
) : PagedMangaParser(context, source, pageSize) { ) : PagedMangaParser(context, source, pageSize) {

@ -2,9 +2,9 @@ package org.koitharu.kotatsu.parsers.site.foolslide.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.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser
@MangaSourceParser("DEATHTOLLSCANS", "DeathTollScans", "en") @MangaSourceParser("DEATHTOLLSCANS", "DeathTollScans", "en")
internal class Deathtollscans(context: MangaLoaderContext) : internal class Deathtollscans(context: MangaLoaderContext) :
FoolSlideParser(context, MangaSource.DEATHTOLLSCANS, "reader.deathtollscans.net", 26) FoolSlideParser(context, MangaParserSource.DEATHTOLLSCANS, "reader.deathtollscans.net", 26)

@ -2,11 +2,11 @@ package org.koitharu.kotatsu.parsers.site.foolslide.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.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser
@MangaSourceParser("MANGATELLERS", "Mangatellers", "en") @MangaSourceParser("MANGATELLERS", "Mangatellers", "en")
internal class Mangatellers(context: MangaLoaderContext) : internal class Mangatellers(context: MangaLoaderContext) :
FoolSlideParser(context, MangaSource.MANGATELLERS, "reader.mangatellers.gr") { FoolSlideParser(context, MangaParserSource.MANGATELLERS, "reader.mangatellers.gr") {
override val pagination = false override val pagination = false
} }

@ -2,9 +2,9 @@ package org.koitharu.kotatsu.parsers.site.foolslide.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.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser
@MangaSourceParser("READER_EVILFLOWERS", "Evil Flowers", "en") @MangaSourceParser("READER_EVILFLOWERS", "Evil Flowers", "en")
internal class ReaderEvilflowers(context: MangaLoaderContext) : internal class ReaderEvilflowers(context: MangaLoaderContext) :
FoolSlideParser(context, MangaSource.READER_EVILFLOWERS, "reader.evilflowers.com") FoolSlideParser(context, MangaParserSource.READER_EVILFLOWERS, "reader.evilflowers.com")

@ -3,13 +3,14 @@ package org.koitharu.kotatsu.parsers.site.foolslide.en
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
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.* import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser
import org.koitharu.kotatsu.parsers.util.* import org.koitharu.kotatsu.parsers.util.*
@MangaSourceParser("SEINAGI", "Seinagi", "en") @MangaSourceParser("SEINAGI", "Seinagi", "en")
internal class Seinagi(context: MangaLoaderContext) : internal class Seinagi(context: MangaLoaderContext) :
FoolSlideParser(context, MangaSource.SEINAGI, "reader.seinagi.org.es") { FoolSlideParser(context, MangaParserSource.SEINAGI, "reader.seinagi.org.es") {
override val pagination = false override val pagination = false

@ -2,12 +2,12 @@ package org.koitharu.kotatsu.parsers.site.foolslide.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.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser
@MangaSourceParser("MENUDO_FANSUB", "Menudo Fansub", "es") @MangaSourceParser("MENUDO_FANSUB", "Menudo Fansub", "es")
internal class MenudoFansub(context: MangaLoaderContext) : internal class MenudoFansub(context: MangaLoaderContext) :
FoolSlideParser(context, MangaSource.MENUDO_FANSUB, "www.menudo-fansub.com", 25) { FoolSlideParser(context, MangaParserSource.MENUDO_FANSUB, "www.menudo-fansub.com", 25) {
override val searchUrl = "slide/search/" override val searchUrl = "slide/search/"
override val listUrl = "slide/directory/" override val listUrl = "slide/directory/"
} }

@ -3,13 +3,15 @@ package org.koitharu.kotatsu.parsers.site.foolslide.es
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
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.* import org.koitharu.kotatsu.parsers.model.ContentType
import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser
import org.koitharu.kotatsu.parsers.util.* import org.koitharu.kotatsu.parsers.util.*
@MangaSourceParser("PZYKOSIS666HFANSUB", "Pzykosis666h Fansub", "es", ContentType.HENTAI) @MangaSourceParser("PZYKOSIS666HFANSUB", "Pzykosis666h Fansub", "es", ContentType.HENTAI)
internal class Pzykosis666hFansub(context: MangaLoaderContext) : internal class Pzykosis666hFansub(context: MangaLoaderContext) :
FoolSlideParser(context, MangaSource.PZYKOSIS666HFANSUB, "lector.pzykosis666hfansub.com") { FoolSlideParser(context, MangaParserSource.PZYKOSIS666HFANSUB, "lector.pzykosis666hfansub.com") {
override suspend fun getDetails(manga: Manga): Manga = coroutineScope { override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
val fullUrl = manga.url.toAbsoluteUrl(domain) val fullUrl = manga.url.toAbsoluteUrl(domain)

@ -5,17 +5,13 @@ import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser 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.Manga import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser
import org.koitharu.kotatsu.parsers.util.domain import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.parseHtml
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
import org.koitharu.kotatsu.parsers.util.src
import org.koitharu.kotatsu.parsers.util.toAbsoluteUrl
@MangaSourceParser("SEINAGIADULTO", "Seinagi Adulto", "es", ContentType.HENTAI) @MangaSourceParser("SEINAGIADULTO", "Seinagi Adulto", "es", ContentType.HENTAI)
internal class SeinagiAdulto(context: MangaLoaderContext) : internal class SeinagiAdulto(context: MangaLoaderContext) :
FoolSlideParser(context, MangaSource.SEINAGIADULTO, "adulto.seinagi.org.es") { FoolSlideParser(context, MangaParserSource.SEINAGIADULTO, "adulto.seinagi.org.es") {
override suspend fun getDetails(manga: Manga): Manga = coroutineScope { override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
val fullUrl = manga.url.toAbsoluteUrl(domain) val fullUrl = manga.url.toAbsoluteUrl(domain)

@ -2,12 +2,12 @@ package org.koitharu.kotatsu.parsers.site.foolslide.fr
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.MangaParserSource
import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser
@MangaSourceParser("HNISCANTRAD", "HniScantrad", "fr") @MangaSourceParser("HNISCANTRAD", "HniScantrad", "fr")
internal class HniScantrad(context: MangaLoaderContext) : internal class HniScantrad(context: MangaLoaderContext) :
FoolSlideParser(context, MangaSource.HNISCANTRAD, "hni-scantrad.com") { FoolSlideParser(context, MangaParserSource.HNISCANTRAD, "hni-scantrad.com") {
override val pagination = false override val pagination = false
override val searchUrl = "lel/search/" override val searchUrl = "lel/search/"
override val listUrl = "lel/directory/" override val listUrl = "lel/directory/"

@ -2,11 +2,11 @@ package org.koitharu.kotatsu.parsers.site.foolslide.it
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.MangaParserSource
import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser
@MangaSourceParser("POWERMANGA", "PowerManga", "it") @MangaSourceParser("POWERMANGA", "PowerManga", "it")
internal class PowerManga(context: MangaLoaderContext) : internal class PowerManga(context: MangaLoaderContext) :
FoolSlideParser(context, MangaSource.POWERMANGA, "reader.powermanga.org") { FoolSlideParser(context, MangaParserSource.POWERMANGA, "reader.powermanga.org") {
override val pagination = false override val pagination = false
} }

@ -2,12 +2,12 @@ package org.koitharu.kotatsu.parsers.site.foolslide.it
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.MangaParserSource
import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser
@MangaSourceParser("RAMAREADER", "RamaReader", "it") @MangaSourceParser("RAMAREADER", "RamaReader", "it")
internal class Ramareader(context: MangaLoaderContext) : internal class Ramareader(context: MangaLoaderContext) :
FoolSlideParser(context, MangaSource.RAMAREADER, "www.ramareader.it") { FoolSlideParser(context, MangaParserSource.RAMAREADER, "www.ramareader.it") {
override val searchUrl = "read/search/" override val searchUrl = "read/search/"
override val listUrl = "read/directory/" override val listUrl = "read/directory/"
} }

@ -2,12 +2,12 @@ package org.koitharu.kotatsu.parsers.site.foolslide.it
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.MangaParserSource
import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser import org.koitharu.kotatsu.parsers.site.foolslide.FoolSlideParser
@MangaSourceParser("READNIFTEAM", "ReadNifTeam", "it") @MangaSourceParser("READNIFTEAM", "ReadNifTeam", "it")
internal class ReadNifteam(context: MangaLoaderContext) : internal class ReadNifteam(context: MangaLoaderContext) :
FoolSlideParser(context, MangaSource.READNIFTEAM, "read-nifteam.info") { FoolSlideParser(context, MangaParserSource.READNIFTEAM, "read-nifteam.info") {
override val searchUrl = "slide/search/" override val searchUrl = "slide/search/"
override val listUrl = "slide/directory/" override val listUrl = "slide/directory/"
} }

@ -16,7 +16,8 @@ import org.koitharu.kotatsu.parsers.util.json.getIntOrDefault
import java.util.* import java.util.*
@MangaSourceParser("BENTOMANGA", "BentoManga", "fr") @MangaSourceParser("BENTOMANGA", "BentoManga", "fr")
internal class BentomangaParser(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.BENTOMANGA, 10) { internal class BentomangaParser(context: MangaLoaderContext) :
PagedMangaParser(context, MangaParserSource.BENTOMANGA, 10) {
override val availableSortOrders: Set<SortOrder> = EnumSet.of( override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.UPDATED, SortOrder.UPDATED,

@ -17,7 +17,7 @@ import java.util.*
@MangaSourceParser("FURYOSOCIETY", "FuryoSociety", "fr") @MangaSourceParser("FURYOSOCIETY", "FuryoSociety", "fr")
internal class FuryoSociety(context: MangaLoaderContext) : internal class FuryoSociety(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.FURYOSOCIETY, 0) { PagedMangaParser(context, MangaParserSource.FURYOSOCIETY, 0) {
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL, SortOrder.UPDATED) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL, SortOrder.UPDATED)

@ -1,13 +1,11 @@
package org.koitharu.kotatsu.parsers.site.fr package org.koitharu.kotatsu.parsers.site.fr
import okhttp3.Headers
import org.json.JSONObject import org.json.JSONObject
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.PagedMangaParser import org.koitharu.kotatsu.parsers.PagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.network.UserAgents
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.SimpleDateFormat import java.text.SimpleDateFormat
@ -15,7 +13,7 @@ import java.util.*
@MangaSourceParser("LEGACY_SCANS", "LegacyScans", "fr") @MangaSourceParser("LEGACY_SCANS", "LegacyScans", "fr")
internal class LegacyScansParser(context: MangaLoaderContext) : internal class LegacyScansParser(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.LEGACY_SCANS, 18) { PagedMangaParser(context, MangaParserSource.LEGACY_SCANS, 18) {
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.POPULARITY) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.POPULARITY)

@ -1,18 +1,16 @@
package org.koitharu.kotatsu.parsers.site.fr package org.koitharu.kotatsu.parsers.site.fr
import okhttp3.Headers
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.PagedMangaParser import org.koitharu.kotatsu.parsers.PagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.network.UserAgents
import org.koitharu.kotatsu.parsers.util.* import org.koitharu.kotatsu.parsers.util.*
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
@MangaSourceParser("LIRESCAN", "LireScan", "fr") @MangaSourceParser("LIRESCAN", "LireScan", "fr")
internal class LireScan(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.LIRESCAN, 20) { internal class LireScan(context: MangaLoaderContext) : PagedMangaParser(context, MangaParserSource.LIRESCAN, 20) {
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED) override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)

@ -16,7 +16,8 @@ import java.text.SimpleDateFormat
import java.util.* import java.util.*
@MangaSourceParser("LUGNICASCANS", "LugnicaScans", "fr") @MangaSourceParser("LUGNICASCANS", "LugnicaScans", "fr")
internal class LugnicaScans(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.LUGNICASCANS, 10) { internal class LugnicaScans(context: MangaLoaderContext) :
PagedMangaParser(context, MangaParserSource.LUGNICASCANS, 10) {
override val availableSortOrders: Set<SortOrder> = EnumSet.of( override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.ALPHABETICAL, SortOrder.ALPHABETICAL,

@ -15,7 +15,7 @@ import java.util.*
@MangaSourceParser("SCANS_MANGAS_ME", "ScansMangas.me", "fr") @MangaSourceParser("SCANS_MANGAS_ME", "ScansMangas.me", "fr")
internal class ScansMangasMe(context: MangaLoaderContext) : internal class ScansMangasMe(context: MangaLoaderContext) :
PagedMangaParser(context, MangaSource.SCANS_MANGAS_ME, 0) { PagedMangaParser(context, MangaParserSource.SCANS_MANGAS_ME, 0) {
override val availableSortOrders: Set<SortOrder> = EnumSet.of( override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.ALPHABETICAL, SortOrder.ALPHABETICAL,

@ -13,7 +13,8 @@ import java.text.SimpleDateFormat
import java.util.* import java.util.*
@MangaSourceParser("SCANTRADUNION", "ScantradUnion", "fr") @MangaSourceParser("SCANTRADUNION", "ScantradUnion", "fr")
internal class ScantradUnion(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.SCANTRADUNION, 10) { internal class ScantradUnion(context: MangaLoaderContext) :
PagedMangaParser(context, MangaParserSource.SCANTRADUNION, 10) {
override val availableSortOrders: Set<SortOrder> = EnumSet.of( override val availableSortOrders: Set<SortOrder> = EnumSet.of(
SortOrder.ALPHABETICAL, SortOrder.ALPHABETICAL,

@ -16,7 +16,7 @@ import java.util.*
internal abstract class GalleryAdultsParser( internal abstract class GalleryAdultsParser(
context: MangaLoaderContext, context: MangaLoaderContext,
source: MangaSource, source: MangaParserSource,
domain: String, domain: String,
pageSize: Int = 20, pageSize: Int = 20,
) : PagedMangaParser(context, source, pageSize) { ) : PagedMangaParser(context, source, pageSize) {

@ -4,7 +4,7 @@ import org.jsoup.nodes.Element
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.ContentType import org.koitharu.kotatsu.parsers.model.ContentType
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.parsers.site.galleryadults.GalleryAdultsParser import org.koitharu.kotatsu.parsers.site.galleryadults.GalleryAdultsParser
import org.koitharu.kotatsu.parsers.util.mapToSet import org.koitharu.kotatsu.parsers.util.mapToSet
@ -13,7 +13,7 @@ import java.util.*
@MangaSourceParser("ASMHENTAI", "AsmHentai", type = ContentType.HENTAI) @MangaSourceParser("ASMHENTAI", "AsmHentai", type = ContentType.HENTAI)
internal class AsmHentai(context: MangaLoaderContext) : internal class AsmHentai(context: MangaLoaderContext) :
GalleryAdultsParser(context, MangaSource.ASMHENTAI, "asmhentai.com") { GalleryAdultsParser(context, MangaParserSource.ASMHENTAI, "asmhentai.com") {
override val selectGallery = ".preview_item" override val selectGallery = ".preview_item"
override val selectGalleryLink = ".image a" override val selectGalleryLink = ".image a"
override val selectGalleryImg = ".image img" override val selectGalleryImg = ".image img"

@ -10,7 +10,7 @@ import java.util.*
@MangaSourceParser("DOUJINDESUUK", "DoujinDesu.uk", type = ContentType.HENTAI) @MangaSourceParser("DOUJINDESUUK", "DoujinDesu.uk", type = ContentType.HENTAI)
internal class DoujinDesuUk(context: MangaLoaderContext) : internal class DoujinDesuUk(context: MangaLoaderContext) :
GalleryAdultsParser(context, MangaSource.DOUJINDESUUK, "doujindesu.uk", 25) { GalleryAdultsParser(context, MangaParserSource.DOUJINDESUUK, "doujindesu.uk", 25) {
override val selectGallery = ".gallery" override val selectGallery = ".gallery"
override val selectGalleryLink = "a" override val selectGalleryLink = "a"
override val selectGalleryTitle = ".caption" override val selectGalleryTitle = ".caption"

@ -10,7 +10,7 @@ import java.util.*
@MangaSourceParser("HENTAI3", "3Hentai", type = ContentType.HENTAI) @MangaSourceParser("HENTAI3", "3Hentai", type = ContentType.HENTAI)
internal class Hentai3(context: MangaLoaderContext) : internal class Hentai3(context: MangaLoaderContext) :
GalleryAdultsParser(context, MangaSource.HENTAI3, "3hentai.net", pageSize = 30) { GalleryAdultsParser(context, MangaParserSource.HENTAI3, "3hentai.net", pageSize = 30) {
override val selectGallery = ".doujin " override val selectGallery = ".doujin "
override val selectGalleryLink = "a" override val selectGalleryLink = "a"

@ -13,7 +13,7 @@ import java.util.*
@MangaSourceParser("HENTAIENVY", "HentaiEnvy", type = ContentType.HENTAI) @MangaSourceParser("HENTAIENVY", "HentaiEnvy", type = ContentType.HENTAI)
internal class HentaiEnvy(context: MangaLoaderContext) : internal class HentaiEnvy(context: MangaLoaderContext) :
GalleryAdultsParser(context, MangaSource.HENTAIENVY, "hentaienvy.com", pageSize = 24) { GalleryAdultsParser(context, MangaParserSource.HENTAIENVY, "hentaienvy.com", pageSize = 24) {
override val selectGalleryLink = "a" override val selectGalleryLink = "a"
override val selectGalleryTitle = "div.title" override val selectGalleryTitle = "div.title"
override val selectTags = ".tags_items" override val selectTags = ".tags_items"

@ -10,7 +10,7 @@ import java.util.*
@MangaSourceParser("HENTAIERA", "HentaiEra", type = ContentType.HENTAI) @MangaSourceParser("HENTAIERA", "HentaiEra", type = ContentType.HENTAI)
internal class HentaiEra(context: MangaLoaderContext) : internal class HentaiEra(context: MangaLoaderContext) :
GalleryAdultsParser(context, MangaSource.HENTAIERA, "hentaiera.com", 25) { GalleryAdultsParser(context, MangaParserSource.HENTAIERA, "hentaiera.com", 25) {
override val selectTags = ".tags_section" override val selectTags = ".tags_section"
override val selectTag = ".galleries_info li:contains(Tags) div.info_tags" override val selectTag = ".galleries_info li:contains(Tags) div.info_tags"
override val selectAuthor = ".galleries_info li:contains(Artists) span.item_name" override val selectAuthor = ".galleries_info li:contains(Artists) span.item_name"

@ -10,7 +10,7 @@ import java.util.*
@MangaSourceParser("HENTAIFORCE", "HentaiForce", type = ContentType.HENTAI) @MangaSourceParser("HENTAIFORCE", "HentaiForce", type = ContentType.HENTAI)
internal class HentaiForce(context: MangaLoaderContext) : internal class HentaiForce(context: MangaLoaderContext) :
GalleryAdultsParser(context, MangaSource.HENTAIFORCE, "hentaiforce.net", pageSize = 30) { GalleryAdultsParser(context, MangaParserSource.HENTAIFORCE, "hentaiforce.net", pageSize = 30) {
override val selectGallery = ".gallery" override val selectGallery = ".gallery"
override val selectGalleryLink = "a.gallery-thumb" override val selectGalleryLink = "a.gallery-thumb"
override val pathTagUrl = "/tags/popular/" override val pathTagUrl = "/tags/popular/"

@ -11,7 +11,7 @@ import java.util.*
@MangaSourceParser("HENTAIFOX", "HentaiFox", type = ContentType.HENTAI) @MangaSourceParser("HENTAIFOX", "HentaiFox", type = ContentType.HENTAI)
internal class HentaiFox(context: MangaLoaderContext) : internal class HentaiFox(context: MangaLoaderContext) :
GalleryAdultsParser(context, MangaSource.HENTAIFOX, "hentaifox.com") { GalleryAdultsParser(context, MangaParserSource.HENTAIFOX, "hentaifox.com") {
override val selectGallery = ".lc_galleries .thumb, .related_galleries .thumb" override val selectGallery = ".lc_galleries .thumb, .related_galleries .thumb"
override val pathTagUrl = "/tags/popular/pag/" override val pathTagUrl = "/tags/popular/pag/"
override val selectTags = ".list_tags" override val selectTags = ".list_tags"

@ -4,7 +4,7 @@ import org.jsoup.nodes.Element
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.ContentType import org.koitharu.kotatsu.parsers.model.ContentType
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.parsers.site.galleryadults.GalleryAdultsParser import org.koitharu.kotatsu.parsers.site.galleryadults.GalleryAdultsParser
import org.koitharu.kotatsu.parsers.util.mapToSet import org.koitharu.kotatsu.parsers.util.mapToSet
@ -13,7 +13,7 @@ import java.util.*
@MangaSourceParser("HENTAIROX", "HentaiRox", type = ContentType.HENTAI) @MangaSourceParser("HENTAIROX", "HentaiRox", type = ContentType.HENTAI)
internal class HentaiRox(context: MangaLoaderContext) : internal class HentaiRox(context: MangaLoaderContext) :
GalleryAdultsParser(context, MangaSource.HENTAIROX, "hentairox.com") { GalleryAdultsParser(context, MangaParserSource.HENTAIROX, "hentairox.com") {
override val selectGalleryImg = ".inner_thumb img" override val selectGalleryImg = ".inner_thumb img"
override val selectTags = ".gtags" override val selectTags = ".gtags"
override val selectTag = "li:contains(Tags:)" override val selectTag = "li:contains(Tags:)"

@ -14,7 +14,7 @@ import java.util.*
@MangaSourceParser("NHENTAI", "NHentai.net", type = ContentType.HENTAI) @MangaSourceParser("NHENTAI", "NHentai.net", type = ContentType.HENTAI)
internal class NHentaiParser(context: MangaLoaderContext) : internal class NHentaiParser(context: MangaLoaderContext) :
GalleryAdultsParser(context, MangaSource.NHENTAI, "nhentai.net", 25) { GalleryAdultsParser(context, MangaParserSource.NHENTAI, "nhentai.net", 25) {
override val selectGallery = "div.index-container:not(.index-popular) .gallery, #related-container .gallery" override val selectGallery = "div.index-container:not(.index-popular) .gallery, #related-container .gallery"
override val selectGalleryLink = "a" override val selectGalleryLink = "a"
override val selectGalleryTitle = ".caption" override val selectGalleryTitle = ".caption"

@ -11,7 +11,7 @@ import java.util.*
internal abstract class GattsuParser( internal abstract class GattsuParser(
context: MangaLoaderContext, context: MangaLoaderContext,
source: MangaSource, source: MangaParserSource,
domain: String, domain: String,
pageSize: Int = 20, pageSize: Int = 20,
) : PagedMangaParser(context, source, pageSize) { ) : PagedMangaParser(context, source, pageSize) {

@ -3,9 +3,9 @@ package org.koitharu.kotatsu.parsers.site.gattsu.pt
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.ContentType import org.koitharu.kotatsu.parsers.model.ContentType
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.gattsu.GattsuParser import org.koitharu.kotatsu.parsers.site.gattsu.GattsuParser
@MangaSourceParser("HENTAISEASON", "HentaiSeason", "pt", ContentType.HENTAI) @MangaSourceParser("HENTAISEASON", "HentaiSeason", "pt", ContentType.HENTAI)
internal class HentaiSeason(context: MangaLoaderContext) : internal class HentaiSeason(context: MangaLoaderContext) :
GattsuParser(context, MangaSource.HENTAISEASON, "hentaiseason.com") GattsuParser(context, MangaParserSource.HENTAISEASON, "hentaiseason.com")

@ -3,11 +3,11 @@ package org.koitharu.kotatsu.parsers.site.gattsu.pt
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.ContentType import org.koitharu.kotatsu.parsers.model.ContentType
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.gattsu.GattsuParser import org.koitharu.kotatsu.parsers.site.gattsu.GattsuParser
@MangaSourceParser("HENTAITOKYO", "HentaiTokyo", "pt", ContentType.HENTAI) @MangaSourceParser("HENTAITOKYO", "HentaiTokyo", "pt", ContentType.HENTAI)
internal class HentaiTokyo(context: MangaLoaderContext) : internal class HentaiTokyo(context: MangaLoaderContext) :
GattsuParser(context, MangaSource.HENTAITOKYO, "hentaitokyo.net") { GattsuParser(context, MangaParserSource.HENTAITOKYO, "hentaitokyo.net") {
override val tagUrl = "tags" override val tagUrl = "tags"
} }

@ -5,18 +5,14 @@ import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser 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.Manga import org.koitharu.kotatsu.parsers.model.Manga
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.model.RATING_UNKNOWN import org.koitharu.kotatsu.parsers.model.RATING_UNKNOWN
import org.koitharu.kotatsu.parsers.site.gattsu.GattsuParser import org.koitharu.kotatsu.parsers.site.gattsu.GattsuParser
import org.koitharu.kotatsu.parsers.util.attrAsAbsoluteUrl import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.domain
import org.koitharu.kotatsu.parsers.util.generateUid
import org.koitharu.kotatsu.parsers.util.selectLastOrThrow
import org.koitharu.kotatsu.parsers.util.src
@MangaSourceParser("MUNDOHENTAIOFICIAL", "MundoHentaiOficial", "pt", ContentType.HENTAI) @MangaSourceParser("MUNDOHENTAIOFICIAL", "MundoHentaiOficial", "pt", ContentType.HENTAI)
internal class MundoHentaiOficial(context: MangaLoaderContext) : internal class MundoHentaiOficial(context: MangaLoaderContext) :
GattsuParser(context, MangaSource.MUNDOHENTAIOFICIAL, "mundohentaioficial.com") { GattsuParser(context, MangaParserSource.MUNDOHENTAIOFICIAL, "mundohentaioficial.com") {
override val tagUrl = "tags" override val tagUrl = "tags"

@ -3,17 +3,13 @@ package org.koitharu.kotatsu.parsers.site.gattsu.pt
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
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.ContentType import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.model.MangaChapter
import org.koitharu.kotatsu.parsers.model.MangaPage
import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.parsers.site.gattsu.GattsuParser import org.koitharu.kotatsu.parsers.site.gattsu.GattsuParser
import org.koitharu.kotatsu.parsers.util.* import org.koitharu.kotatsu.parsers.util.*
@MangaSourceParser("UNIVERSOHENTAI", "UniversoHentai", "pt", ContentType.HENTAI) @MangaSourceParser("UNIVERSOHENTAI", "UniversoHentai", "pt", ContentType.HENTAI)
internal class UniversoHentai(context: MangaLoaderContext) : internal class UniversoHentai(context: MangaLoaderContext) :
GattsuParser(context, MangaSource.UNIVERSOHENTAI, "universohentai.com") { GattsuParser(context, MangaParserSource.UNIVERSOHENTAI, "universohentai.com") {
override val tagPrefix = "category" override val tagPrefix = "category"

@ -10,7 +10,7 @@ import java.util.*
internal abstract class GuyaParser( internal abstract class GuyaParser(
context: MangaLoaderContext, context: MangaLoaderContext,
source: MangaSource, source: MangaParserSource,
domain: String, domain: String,
pageSize: Int = 0, pageSize: Int = 0,
) : PagedMangaParser(context, source, pageSize) { ) : PagedMangaParser(context, source, pageSize) {

@ -2,9 +2,9 @@ package org.koitharu.kotatsu.parsers.site.guya.all
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.MangaParserSource
import org.koitharu.kotatsu.parsers.site.guya.GuyaParser import org.koitharu.kotatsu.parsers.site.guya.GuyaParser
@MangaSourceParser("MAHOUSHOUJOBU", "MahouShoujobu") @MangaSourceParser("MAHOUSHOUJOBU", "MahouShoujobu")
internal class MahouShoujobu(context: MangaLoaderContext) : internal class MahouShoujobu(context: MangaLoaderContext) :
GuyaParser(context, MangaSource.MAHOUSHOUJOBU, "mahoushoujobu.com") GuyaParser(context, MangaParserSource.MAHOUSHOUJOBU, "mahoushoujobu.com")

@ -2,9 +2,9 @@ package org.koitharu.kotatsu.parsers.site.guya.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.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.guya.GuyaParser import org.koitharu.kotatsu.parsers.site.guya.GuyaParser
@MangaSourceParser("DANKE", "DankeFursLesen", "en") @MangaSourceParser("DANKE", "DankeFursLesen", "en")
internal class Danke(context: MangaLoaderContext) : internal class Danke(context: MangaLoaderContext) :
GuyaParser(context, MangaSource.DANKE, "danke.moe") GuyaParser(context, MangaParserSource.DANKE, "danke.moe")

@ -2,9 +2,9 @@ package org.koitharu.kotatsu.parsers.site.guya.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.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.guya.GuyaParser import org.koitharu.kotatsu.parsers.site.guya.GuyaParser
@MangaSourceParser("GUYACUBARI", "GuyaCubari", "en") @MangaSourceParser("GUYACUBARI", "GuyaCubari", "en")
internal class GuyaCubari(context: MangaLoaderContext) : internal class GuyaCubari(context: MangaLoaderContext) :
GuyaParser(context, MangaSource.GUYACUBARI, "guya.cubari.moe") GuyaParser(context, MangaParserSource.GUYACUBARI, "guya.cubari.moe")

@ -3,9 +3,9 @@ package org.koitharu.kotatsu.parsers.site.guya.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.ContentType import org.koitharu.kotatsu.parsers.model.ContentType
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.guya.GuyaParser import org.koitharu.kotatsu.parsers.site.guya.GuyaParser
@MangaSourceParser("HACHIRUMI", "Hachirumi", "en", ContentType.HENTAI) @MangaSourceParser("HACHIRUMI", "Hachirumi", "en", ContentType.HENTAI)
internal class Hachirumi(context: MangaLoaderContext) : internal class Hachirumi(context: MangaLoaderContext) :
GuyaParser(context, MangaSource.HACHIRUMI, "hachirumi.com") GuyaParser(context, MangaParserSource.HACHIRUMI, "hachirumi.com")

@ -13,7 +13,7 @@ import java.util.*
internal abstract class HeanCms( internal abstract class HeanCms(
context: MangaLoaderContext, context: MangaLoaderContext,
source: MangaSource, source: MangaParserSource,
domain: String, domain: String,
pageSize: Int = 20, pageSize: Int = 20,
) : PagedMangaParser(context, source, pageSize) { ) : PagedMangaParser(context, source, pageSize) {

@ -14,7 +14,8 @@ import java.text.SimpleDateFormat
import java.util.* import java.util.*
@MangaSourceParser("OMEGASCANS", "OmegaScans", "en", ContentType.HENTAI) @MangaSourceParser("OMEGASCANS", "OmegaScans", "en", ContentType.HENTAI)
internal class OmegaScans(context: MangaLoaderContext) : HeanCms(context, MangaSource.OMEGASCANS, "omegascans.org") { internal class OmegaScans(context: MangaLoaderContext) :
HeanCms(context, MangaParserSource.OMEGASCANS, "omegascans.org") {
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 {
append("https://api.") append("https://api.")

@ -2,13 +2,13 @@ package org.koitharu.kotatsu.parsers.site.heancms.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.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.heancms.HeanCms import org.koitharu.kotatsu.parsers.site.heancms.HeanCms
import org.koitharu.kotatsu.parsers.util.domain import org.koitharu.kotatsu.parsers.util.domain
@MangaSourceParser("TEMPLESCAN", "TempleScan", "en") @MangaSourceParser("TEMPLESCAN", "TempleScan", "en")
internal class TempleScan(context: MangaLoaderContext) : internal class TempleScan(context: MangaLoaderContext) :
HeanCms(context, MangaSource.TEMPLESCAN, "templescan.net") { HeanCms(context, MangaParserSource.TEMPLESCAN, "templescan.net") {
override val pathManga = "comic" override val pathManga = "comic"
override val apiPath: String override val apiPath: String

@ -4,12 +4,12 @@ import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.site.heancms.HeanCms import org.koitharu.kotatsu.parsers.site.heancms.HeanCms
import org.koitharu.kotatsu.parsers.util.json.mapJSON
import org.koitharu.kotatsu.parsers.util.* import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.json.mapJSON
@MangaSourceParser("YUGEN_MANGAS_ES", "YugenMangas.lat", "es", ContentType.HENTAI) @MangaSourceParser("YUGEN_MANGAS_ES", "YugenMangas.lat", "es", ContentType.HENTAI)
internal class YugenMangasEs(context: MangaLoaderContext) : internal class YugenMangasEs(context: MangaLoaderContext) :
HeanCms(context, MangaSource.YUGEN_MANGAS_ES, "yugenmangas.lat") { HeanCms(context, MangaParserSource.YUGEN_MANGAS_ES, "yugenmangas.lat") {
private val domainAlt = "yugenmangas.net" private val domainAlt = "yugenmangas.net"

@ -2,9 +2,9 @@ package org.koitharu.kotatsu.parsers.site.heancms.fr
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.MangaParserSource
import org.koitharu.kotatsu.parsers.site.heancms.HeanCms import org.koitharu.kotatsu.parsers.site.heancms.HeanCms
@MangaSourceParser("PERF_SCAN", "PerfScan", "fr") @MangaSourceParser("PERF_SCAN", "PerfScan", "fr")
internal class PerfScan(context: MangaLoaderContext) : internal class PerfScan(context: MangaLoaderContext) :
HeanCms(context, MangaSource.PERF_SCAN, "perf-scan.fr") HeanCms(context, MangaParserSource.PERF_SCAN, "perf-scan.fr")

@ -13,7 +13,7 @@ import java.util.*
@MangaSourceParser("MODESCANLATOR", "ModeScanlator", "pt") @MangaSourceParser("MODESCANLATOR", "ModeScanlator", "pt")
internal class ModeScanlator( internal class ModeScanlator(
context: MangaLoaderContext, context: MangaLoaderContext,
) : HeanCms(context, MangaSource.MODESCANLATOR, "modescanlator.com") { ) : HeanCms(context, MangaParserSource.MODESCANLATOR, "modescanlator.com") {
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,7 +14,7 @@ import java.util.*
internal abstract class HeanCmsAlt( internal abstract class HeanCmsAlt(
context: MangaLoaderContext, context: MangaLoaderContext,
source: MangaSource, source: MangaParserSource,
domain: String, domain: String,
pageSize: Int = 18, pageSize: Int = 18,
) : PagedMangaParser(context, source, pageSize) { ) : PagedMangaParser(context, source, pageSize) {

@ -4,20 +4,14 @@ 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.Manga
import org.koitharu.kotatsu.parsers.model.MangaChapter import org.koitharu.kotatsu.parsers.model.MangaChapter
import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.heancmsalt.HeanCmsAlt import org.koitharu.kotatsu.parsers.site.heancmsalt.HeanCmsAlt
import org.koitharu.kotatsu.parsers.util.attrAsRelativeUrl import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.domain
import org.koitharu.kotatsu.parsers.util.generateUid
import org.koitharu.kotatsu.parsers.util.mapChapters
import org.koitharu.kotatsu.parsers.util.parseHtml
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
import org.koitharu.kotatsu.parsers.util.toAbsoluteUrl
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
@MangaSourceParser("BRAKEOUT", "Brakeout", "es") @MangaSourceParser("BRAKEOUT", "Brakeout", "es")
internal class Brakeout(context: MangaLoaderContext) : internal class Brakeout(context: MangaLoaderContext) :
HeanCmsAlt(context, MangaSource.BRAKEOUT, "brakeout.xyz", 10) { HeanCmsAlt(context, MangaParserSource.BRAKEOUT, "brakeout.xyz", 10) {
override val selectManga = "div.grid.grid-cols-2 figure" override val selectManga = "div.grid.grid-cols-2 figure"
override val selectMangaTitle = "figcaption" override val selectMangaTitle = "figcaption"

@ -2,9 +2,9 @@ package org.koitharu.kotatsu.parsers.site.heancmsalt.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.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.heancmsalt.HeanCmsAlt import org.koitharu.kotatsu.parsers.site.heancmsalt.HeanCmsAlt
@MangaSourceParser("LEGIONSCANS", "CerberusSeries", "es") @MangaSourceParser("LEGIONSCANS", "CerberusSeries", "es")
internal class CerberuSeries(context: MangaLoaderContext) : internal class CerberuSeries(context: MangaLoaderContext) :
HeanCmsAlt(context, MangaSource.LEGIONSCANS, "cerberuseries.xyz") HeanCmsAlt(context, MangaParserSource.LEGIONSCANS, "cerberuseries.xyz")

@ -2,12 +2,12 @@ package org.koitharu.kotatsu.parsers.site.heancmsalt.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.MangaSource import org.koitharu.kotatsu.parsers.model.MangaParserSource
import org.koitharu.kotatsu.parsers.site.heancmsalt.HeanCmsAlt import org.koitharu.kotatsu.parsers.site.heancmsalt.HeanCmsAlt
@MangaSourceParser("MANGAESP", "MangaEsp", "es") @MangaSourceParser("MANGAESP", "MangaEsp", "es")
internal class MangaEsp(context: MangaLoaderContext) : internal class MangaEsp(context: MangaLoaderContext) :
HeanCmsAlt(context, MangaSource.MANGAESP, "mangaesp.net", 15) { HeanCmsAlt(context, MangaParserSource.MANGAESP, "mangaesp.net", 15) {
override val listUrl = "/comic" override val listUrl = "/comic"

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

Loading…
Cancel
Save