Merge pull request #202 from davvarrr/master
rework madara theme and fix many parser
This commit is contained in:
@@ -112,16 +112,21 @@ internal class JapScanParser(context: MangaLoaderContext) : PagedMangaParser(con
|
||||
val embeddedData = doc.requireElementById("data").attr("data-data")
|
||||
val script = webClient.httpGet(scriptUrl).parseRaw()
|
||||
|
||||
val sample = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toList()
|
||||
val keyRegex = Regex("""'([\dA-Z]{62})'""", RegexOption.IGNORE_CASE)
|
||||
val shortkeyRegex = Regex("""'([\dA-Z]{2})'""", RegexOption.IGNORE_CASE)
|
||||
val longkeyRegex = Regex("""'([\dA-Z]{20})'""", RegexOption.IGNORE_CASE)
|
||||
|
||||
val keyTables = keyRegex.findAll(script)
|
||||
.mapNotNullTo(ArrayList(2)) { match ->
|
||||
match.groupValues[1].takeIf {
|
||||
it.toList().sorted() == sample
|
||||
}
|
||||
}
|
||||
check(keyTables.size == 2)
|
||||
val longTables = longkeyRegex.findAll(script).map {
|
||||
it.groupValues[1]
|
||||
}.toList()
|
||||
|
||||
val shortTables = shortkeyRegex.findAll(script).map {
|
||||
it.groupValues[1]
|
||||
}.toList()
|
||||
|
||||
val keyTables = listOf(
|
||||
ShortTables[1].reversed() + LongTables[5].reversed() + LongTables[2].reversed() + LongTables[0].reversed(),
|
||||
ShortTables[2].reversed() + LongTables[3].reversed() + LongTables[4].reversed() + LongTables[1].reversed(),
|
||||
)
|
||||
|
||||
var error: Exception? = null
|
||||
repeat(2) { i ->
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import org.jsoup.nodes.Element
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaState
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
|
||||
@MangaSourceParser("AIYUMANGASCANLATION", "AiyuMangaScanlation", "es")
|
||||
internal class AiyuMangaScanlation(context: MangaLoaderContext) :
|
||||
Madara6Parser(context, MangaSource.AIYUMANGASCANLATION, "aiyumangascanlation.com") {
|
||||
|
||||
override val tagPrefix = "manga-genre/"
|
||||
override val datePattern = "MM/dd/yyyy"
|
||||
|
||||
override fun parseDetails(manga: Manga, body: Element, chapters: List<MangaChapter>): Manga {
|
||||
val root = body.selectFirstOrThrow(".site-content")
|
||||
val postContent = root.selectFirstOrThrow(".post-content")
|
||||
val tags = postContent.getElementsContainingOwnText("Genre(s)")
|
||||
.firstOrNull()?.tableValue()
|
||||
?.getElementsByAttributeValueContaining("href", tagPrefix)
|
||||
?.mapToSet { a -> a.asMangaTag() } ?: manga.tags
|
||||
return manga.copy(
|
||||
description = postContent.getElementsContainingOwnText("Summary")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
altTitle = postContent.getElementsContainingOwnText("Alternative")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
state = postContent.getElementsContainingOwnText("Status")
|
||||
.firstOrNull()?.tableValue()?.text()?.asMangaState(),
|
||||
tags = tags,
|
||||
isNsfw = body.hasClass("adult-content"),
|
||||
chapters = chapters,
|
||||
)
|
||||
}
|
||||
|
||||
override fun String.asMangaState(): MangaState? = when (this) {
|
||||
"OnGoing",
|
||||
"Upcoming",
|
||||
-> MangaState.ONGOING
|
||||
|
||||
"Completed",
|
||||
"Dropped",
|
||||
-> MangaState.FINISHED
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import org.jsoup.nodes.Element
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaState
|
||||
import org.koitharu.kotatsu.parsers.util.assertNotNull
|
||||
import org.koitharu.kotatsu.parsers.util.attrAsAbsoluteUrlOrNull
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
|
||||
@MangaSourceParser("ASTRALMANGA", "AstralManga", "fr")
|
||||
internal class AstralManga(context: MangaLoaderContext) :
|
||||
Madara6Parser(context, MangaSource.ASTRALMANGA, "astral-manga.fr", pageSize = 12) {
|
||||
|
||||
override val datePattern = "dd/MM/yyyy"
|
||||
|
||||
override fun String.asMangaState(): MangaState? = when (this) {
|
||||
"En cours",
|
||||
-> MangaState.ONGOING
|
||||
|
||||
"Terminé",
|
||||
"Complété",
|
||||
-> MangaState.FINISHED
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
override fun parseDetails(manga: Manga, body: Element, chapters: List<MangaChapter>): Manga {
|
||||
val root = body.selectFirstOrThrow(".site-content")
|
||||
val postContent = root.selectFirstOrThrow(".post-content")
|
||||
val tags = postContent.getElementsContainingOwnText("Genre(s)")
|
||||
.firstOrNull()?.tableValue()
|
||||
?.getElementsByAttributeValueContaining("href", tagPrefix)
|
||||
?.mapToSet { a -> a.asMangaTag() } ?: manga.tags
|
||||
return manga.copy(
|
||||
rating = postContent.selectFirstOrThrow(".post-rating")
|
||||
.selectFirstOrThrow(".total_votes").text().toFloat() / 5f,
|
||||
largeCoverUrl = root.selectFirst(".summary_image")
|
||||
?.selectFirst("img[data-src]")
|
||||
?.attrAsAbsoluteUrlOrNull("data-src")
|
||||
.assertNotNull("largeCoverUrl"),
|
||||
description = root.selectFirstOrThrow(".manga-excerpt")
|
||||
.firstElementChild()?.html(),
|
||||
author = postContent.getElementsContainingOwnText("Auteur(s)")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
altTitle = postContent.getElementsContainingOwnText("Alternatif")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
state = postContent.getElementsContainingOwnText("Statut")
|
||||
.firstOrNull()?.tableValue()?.text()?.asMangaState(),
|
||||
tags = tags,
|
||||
isNsfw = body.hasClass("adult-content"),
|
||||
chapters = chapters,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import org.jsoup.nodes.Element
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaState
|
||||
import org.koitharu.kotatsu.parsers.util.assertNotNull
|
||||
import org.koitharu.kotatsu.parsers.util.attrAsAbsoluteUrlOrNull
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
|
||||
|
||||
@MangaSourceParser("ATLANTISSCAN", "Atlantisscan", "pt")
|
||||
internal class Atlantisscan(context: MangaLoaderContext) :
|
||||
Madara6Parser(context, MangaSource.ATLANTISSCAN, "atlantisscan.com") {
|
||||
|
||||
override val datePattern = "dd/MM/yyyy"
|
||||
|
||||
override fun String.asMangaState(): MangaState? = when (this) {
|
||||
"OnGoing",
|
||||
-> MangaState.ONGOING
|
||||
|
||||
"finished",
|
||||
-> MangaState.FINISHED
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
override fun parseDetails(manga: Manga, body: Element, chapters: List<MangaChapter>): Manga {
|
||||
val root = body.selectFirstOrThrow(".site-content")
|
||||
val postContent = root.selectFirstOrThrow(".summary_content")
|
||||
val tags = postContent.getElementsContainingOwnText("Genre(s) ")
|
||||
.firstOrNull()?.tableValue()
|
||||
?.getElementsByAttributeValueContaining("href", tagPrefix)
|
||||
?.mapToSet { a -> a.asMangaTag() } ?: manga.tags
|
||||
return manga.copy(
|
||||
largeCoverUrl = root.selectFirst(".summary_image")
|
||||
?.selectFirst("img[data-src]")
|
||||
?.attrAsAbsoluteUrlOrNull("data-src")
|
||||
.assertNotNull("largeCoverUrl"),
|
||||
description = root.selectFirstOrThrow(".description-summary")
|
||||
.firstElementChild()?.html(),
|
||||
author = postContent.getElementsContainingOwnText("Author(s)")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
altTitle = postContent.getElementsContainingOwnText("Alternative")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
state = postContent.getElementsContainingOwnText("Status")
|
||||
.firstOrNull()?.tableValue()?.text()?.asMangaState(),
|
||||
tags = tags,
|
||||
isNsfw = body.hasClass("adult-content"),
|
||||
chapters = chapters,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,60 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import org.jsoup.nodes.Element
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaState
|
||||
import org.koitharu.kotatsu.parsers.util.assertNotNull
|
||||
import org.koitharu.kotatsu.parsers.util.attrAsAbsoluteUrlOrNull
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("FRSCAN", "FrScan", "fr")
|
||||
internal class FrScan(context: MangaLoaderContext) :
|
||||
Madara6Parser(context, MangaSource.FRSCAN, "fr-scan.com") {
|
||||
|
||||
override val datePattern = "MMMM d, yyyy"
|
||||
override val sourceLocale: Locale = Locale.FRENCH
|
||||
|
||||
override fun String.asMangaState(): MangaState? = when (this) {
|
||||
"OnGoing",
|
||||
-> MangaState.ONGOING
|
||||
|
||||
"Complété",
|
||||
-> MangaState.FINISHED
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
override fun parseDetails(manga: Manga, body: Element, chapters: List<MangaChapter>): Manga {
|
||||
val root = body.selectFirstOrThrow(".site-content")
|
||||
val postContent = root.selectFirstOrThrow(".post-content")
|
||||
val tags = postContent.getElementsContainingOwnText("Genre(s)")
|
||||
.firstOrNull()?.tableValue()
|
||||
?.getElementsByAttributeValueContaining("href", tagPrefix)
|
||||
?.mapToSet { a -> a.asMangaTag() } ?: manga.tags
|
||||
return manga.copy(
|
||||
rating = postContent.selectFirstOrThrow(".post-rating")
|
||||
.selectFirstOrThrow(".total_votes").text().toFloat() / 5f,
|
||||
largeCoverUrl = root.selectFirst(".summary_image")
|
||||
?.selectFirst("img[data-src]")
|
||||
?.attrAsAbsoluteUrlOrNull("data-src")
|
||||
.assertNotNull("largeCoverUrl"),
|
||||
description = root.selectFirstOrThrow(".description-summary")
|
||||
.firstElementChild()?.html(),
|
||||
author = postContent.getElementsContainingOwnText("Auteur(s)")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
altTitle = postContent.getElementsContainingOwnText("Alternatif")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
state = postContent.getElementsContainingOwnText("Statut")
|
||||
.firstOrNull()?.tableValue()?.text()?.asMangaState(),
|
||||
tags = tags,
|
||||
isNsfw = body.hasClass("adult-content"),
|
||||
chapters = chapters,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import org.jsoup.nodes.Document
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("HENTAI_4FREE", "Hentai4Free", "en")
|
||||
internal class Hentai4Free(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.HENTAI_4FREE, "hentai4free.net", pageSize = 24) {
|
||||
|
||||
override val tagPrefix = "hentai-tag/"
|
||||
|
||||
override val isNsfwSource = true
|
||||
|
||||
override suspend fun getTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/").parseHtml()
|
||||
val body = doc.body()
|
||||
val root1 = body.selectFirst("header")?.selectFirst("ul.second-menu")
|
||||
val list = root1?.select("li").orEmpty()
|
||||
val keySet = HashSet<String>(list.size)
|
||||
return list.mapNotNullToSet { li ->
|
||||
val a = li.selectFirst("a") ?: return@mapNotNullToSet null
|
||||
val href = a.attr("href").removeSuffix("/")
|
||||
.substringAfterLast(tagPrefix, "")
|
||||
if (href.isEmpty() || !keySet.add(href)) {
|
||||
return@mapNotNullToSet null
|
||||
}
|
||||
MangaTag(
|
||||
key = href,
|
||||
title = a.ownText().trim().toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getChapters(manga: Manga, doc: Document): List<MangaChapter> {
|
||||
val slug = manga.url.removeSuffix('/').substringAfterLast('/')
|
||||
val doc2 = webClient.httpPost(
|
||||
"https://$domain/hentai/$slug/ajax/chapters/",
|
||||
mapOf(),
|
||||
).parseHtml()
|
||||
val ul = doc2.body().selectFirstOrThrow("ul")
|
||||
val dateFormat = SimpleDateFormat(datePattern, Locale.US)
|
||||
return ul.select("li").mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirst("a")
|
||||
val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing")
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
name = a.ownText(),
|
||||
number = i + 1,
|
||||
url = href,
|
||||
uploadDate = parseChapterDate(
|
||||
dateFormat,
|
||||
li.selectFirst("span.chapter-release-date i")?.text(),
|
||||
),
|
||||
source = source,
|
||||
scanlator = null,
|
||||
branch = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import org.jsoup.nodes.Element
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaState
|
||||
import org.koitharu.kotatsu.parsers.util.assertNotNull
|
||||
import org.koitharu.kotatsu.parsers.util.attrAsAbsoluteUrlOrNull
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
|
||||
@MangaSourceParser("HENTAITECA", "Hentaiteca", "pt")
|
||||
internal class Hentaiteca(context: MangaLoaderContext) :
|
||||
Madara6Parser(context, MangaSource.HENTAITECA, "hentaiteca.net", pageSize = 10) {
|
||||
|
||||
override val datePattern = "MM/dd/yyyy"
|
||||
|
||||
override val tagPrefix = "genero/"
|
||||
|
||||
override val isNsfwSource = true
|
||||
|
||||
override fun String.asMangaState(): MangaState? = when (this) {
|
||||
"Em Lançamento",
|
||||
-> MangaState.ONGOING
|
||||
|
||||
"Completo",
|
||||
-> MangaState.FINISHED
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
override fun parseDetails(manga: Manga, body: Element, chapters: List<MangaChapter>): Manga {
|
||||
val root = body.selectFirstOrThrow(".site-content")
|
||||
val postContent = root.selectFirstOrThrow(".summary_content")
|
||||
val tags = postContent.getElementsContainingOwnText("Gênero(s)")
|
||||
.firstOrNull()?.tableValue()
|
||||
?.getElementsByAttributeValueContaining("href", tagPrefix)
|
||||
?.mapToSet { a -> a.asMangaTag() } ?: manga.tags
|
||||
return manga.copy(
|
||||
rating = postContent.selectFirstOrThrow(".post-rating")
|
||||
.selectFirstOrThrow(".total_votes").text().toFloat() / 5f,
|
||||
largeCoverUrl = root.selectFirst(".summary_image")
|
||||
?.selectFirst("img[data-src]")
|
||||
?.attrAsAbsoluteUrlOrNull("data-src")
|
||||
.assertNotNull("largeCoverUrl"),
|
||||
description = root.selectFirstOrThrow(".description-summary")
|
||||
.firstElementChild()?.html(),
|
||||
author = postContent.getElementsContainingOwnText("Autor(es)")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
altTitle = postContent.getElementsContainingOwnText("Alternatif")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
state = postContent.getElementsContainingOwnText("Status")
|
||||
.firstOrNull()?.tableValue()?.text()?.asMangaState(),
|
||||
tags = tags,
|
||||
isNsfw = body.hasClass("adult-content"),
|
||||
chapters = chapters,
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaState
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
|
||||
@MangaSourceParser("HENTAIZONE", "Hentaizone", "fr")
|
||||
internal class Hentaizone(context: MangaLoaderContext) :
|
||||
Madara6Parser(context, MangaSource.HENTAIZONE, "hentaizone.xyz", pageSize = 10) {
|
||||
|
||||
override val datePattern = "MMM d, yyyy"
|
||||
override val sourceLocale: Locale = Locale.FRENCH
|
||||
|
||||
override val isNsfwSource = true
|
||||
|
||||
override fun String.asMangaState(): MangaState? = when (this) {
|
||||
"En Cours",
|
||||
-> MangaState.ONGOING
|
||||
|
||||
"Terminé",
|
||||
-> MangaState.FINISHED
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
override fun parseDetails(manga: Manga, body: Element, chapters: List<MangaChapter>): Manga {
|
||||
val root = body.selectFirstOrThrow(".site-content")
|
||||
val postContent = root.selectFirstOrThrow(".summary_content")
|
||||
val tags = postContent.getElementsContainingOwnText("Genre(s)")
|
||||
.firstOrNull()?.tableValue()
|
||||
?.getElementsByAttributeValueContaining("href", tagPrefix)
|
||||
?.mapToSet { a -> a.asMangaTag() } ?: manga.tags
|
||||
return manga.copy(
|
||||
rating = postContent.selectFirstOrThrow(".post-rating")
|
||||
.selectFirstOrThrow(".total_votes").text().toFloat() / 5f,
|
||||
description = root.selectFirst("div.description-summary")?.selectFirst("div.summary__content")?.select("p")
|
||||
?.filterNot { it.ownText().startsWith("A brief description") }?.joinToString { it.html() },
|
||||
author = postContent.getElementsContainingOwnText("Auteur(s)")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
altTitle = postContent.getElementsContainingOwnText("Alternatif")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
state = postContent.getElementsContainingOwnText("Statut")
|
||||
.firstOrNull()?.tableValue()?.text()?.asMangaState(),
|
||||
tags = tags,
|
||||
chapters = chapters,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
override suspend fun getChapters(manga: Manga, doc: Document): List<MangaChapter> {
|
||||
val root2 = doc.body().selectFirstOrThrow("div.content-area").selectFirstOrThrow("div.c-page")
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
return root2.select("li").mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirst("a")
|
||||
val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing")
|
||||
|
||||
// correct parse date missing a "."
|
||||
val date_org = li.selectFirst("span.chapter-release-date i")?.text() ?: "janv 1, 2000"
|
||||
val date_corect_parse = date_org
|
||||
.replace("janv", "janv.")
|
||||
.replace("févr", "févr.")
|
||||
.replace("avr", "avr.")
|
||||
.replace("juil", "juil.")
|
||||
.replace("sept", "sept.")
|
||||
.replace("nov", "nov.")
|
||||
.replace("oct", "oct.")
|
||||
.replace("déc", "déc.")
|
||||
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
name = a.ownText(),
|
||||
number = i + 1,
|
||||
url = href,
|
||||
uploadDate = parseChapterDate(
|
||||
dateFormat,
|
||||
date_corect_parse,
|
||||
),
|
||||
source = source,
|
||||
scanlator = null,
|
||||
branch = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import org.jsoup.nodes.Element
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaState
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.insertCookies
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
import java.util.*
|
||||
|
||||
|
||||
@MangaSourceParser("HHENTAIFR", "HhentaiFr", "fr")
|
||||
internal class HhentaiFr(context: MangaLoaderContext) :
|
||||
Madara6Parser(context, MangaSource.HHENTAIFR, "hhentai.fr") {
|
||||
|
||||
override val datePattern = "MMMM d, yyyy"
|
||||
override val sourceLocale: Locale = Locale.FRENCH
|
||||
|
||||
override val isNsfwSource = true
|
||||
|
||||
init {
|
||||
context.cookieJar.insertCookies(
|
||||
domain,
|
||||
"age_gate=32;",
|
||||
)
|
||||
}
|
||||
|
||||
override fun String.asMangaState(): MangaState? = when (this) {
|
||||
"En Cours",
|
||||
-> MangaState.ONGOING
|
||||
|
||||
"Terminé",
|
||||
-> MangaState.FINISHED
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
override fun parseDetails(manga: Manga, body: Element, chapters: List<MangaChapter>): Manga {
|
||||
val root = body.selectFirstOrThrow(".site-content")
|
||||
val postContent = root.selectFirstOrThrow(".summary_content")
|
||||
val tags = postContent.getElementsContainingOwnText("Genre(s)")
|
||||
.firstOrNull()?.tableValue()
|
||||
?.getElementsByAttributeValueContaining("href", tagPrefix)
|
||||
?.mapToSet { a -> a.asMangaTag() } ?: manga.tags
|
||||
return manga.copy(
|
||||
rating = postContent.selectFirstOrThrow(".post-rating")
|
||||
.selectFirstOrThrow(".total_votes").text().toFloat() / 5f,
|
||||
description = root.selectFirstOrThrow(".description-summary")
|
||||
.firstElementChild()?.html(),
|
||||
author = postContent.getElementsContainingOwnText("Auteur(s)")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
altTitle = postContent.getElementsContainingOwnText("Alternatif")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
state = postContent.getElementsContainingOwnText("Statut")
|
||||
.firstOrNull()?.tableValue()?.text()?.asMangaState(),
|
||||
tags = tags,
|
||||
isNsfw = body.hasClass("adult-content"),
|
||||
chapters = chapters,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import org.jsoup.nodes.Element
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaState
|
||||
import org.koitharu.kotatsu.parsers.util.attrAsAbsoluteUrlOrNull
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
import java.util.*
|
||||
|
||||
|
||||
@MangaSourceParser("HIPERCOOL", "Hipercool", "pt")
|
||||
internal class Hipercool(context: MangaLoaderContext) :
|
||||
Madara6Parser(context, MangaSource.HIPERCOOL, "hipercool.xyz", pageSize = 20) {
|
||||
|
||||
override val datePattern = "MMMM d, yyyy"
|
||||
|
||||
override val tagPrefix = "manga-tag/"
|
||||
|
||||
override val isNsfwSource = true
|
||||
|
||||
override fun parseDetails(manga: Manga, body: Element, chapters: List<MangaChapter>): Manga {
|
||||
val root = body.selectFirstOrThrow(".site-content")
|
||||
val postContent = root.selectFirstOrThrow(".main-col")
|
||||
val tags = postContent.getElementsByClass("tags-content")
|
||||
.firstOrNull()?.tableValue()
|
||||
?.getElementsByAttributeValueContaining("href", tagPrefix)
|
||||
?.mapToSet { a -> a.asMangaTag() } ?: manga.tags
|
||||
|
||||
return manga.copy(
|
||||
|
||||
|
||||
largeCoverUrl = root.selectFirst("picture")
|
||||
?.selectFirst("img[data-src]")
|
||||
?.attrAsAbsoluteUrlOrNull("data-src"),
|
||||
description = root.selectFirst("div.description-summary")?.selectFirst("div.summary__content")?.select("p")
|
||||
?.filterNot { it.ownText().startsWith("A brief description") }?.joinToString { it.html() },
|
||||
tags = tags,
|
||||
isNsfw = body.hasClass("adult-content"),
|
||||
chapters = chapters,
|
||||
)
|
||||
}
|
||||
|
||||
override fun String.asMangaState() = when (trim().lowercase(Locale.ROOT)) {
|
||||
"em lançamento" -> MangaState.ONGOING
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("ISEKAISCAN_EU", "IsekaiScan", "en")
|
||||
internal class IsekaiScanEuParser(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.ISEKAISCAN_EU, "isekaiscan.to") {
|
||||
|
||||
override val datePattern = "MM/dd/yyyy"
|
||||
|
||||
override suspend fun getChapters(manga: Manga, doc: Document): List<MangaChapter> {
|
||||
doc.selectFirst("ul.version-chap")?.let {
|
||||
return parseChapters(it)
|
||||
}
|
||||
val mangaId = doc.body().requireElementById("manga-chapters-holder").attr("data-id")
|
||||
val ul = webClient.httpPost(
|
||||
"https://${domain}/wp-admin/admin-ajax.php",
|
||||
mapOf(
|
||||
"action" to "manga_get_chapters",
|
||||
"manga" to mangaId,
|
||||
),
|
||||
).parseHtml().body().selectFirstOrThrow("ul")
|
||||
return parseChapters(ul)
|
||||
}
|
||||
|
||||
override suspend fun getTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/mangax/").parseHtml()
|
||||
val body = doc.body()
|
||||
val root1 = body.selectFirst("header")?.selectFirst("ul.second-menu")
|
||||
val root2 = body.selectFirst("div.genres_wrap")?.selectFirst("ul.list-unstyled")
|
||||
if (root1 == null && root2 == null) {
|
||||
doc.parseFailed("Root not found")
|
||||
}
|
||||
val list = root1?.select("li").orEmpty() + root2?.select("li").orEmpty()
|
||||
val keySet = HashSet<String>(list.size)
|
||||
return list.mapNotNullToSet { li ->
|
||||
val a = li.selectFirst("a") ?: return@mapNotNullToSet null
|
||||
val href = a.attr("href").removeSuffix("/")
|
||||
.substringAfterLast(tagPrefix, "")
|
||||
if (href.isEmpty() || !keySet.add(href)) {
|
||||
return@mapNotNullToSet null
|
||||
}
|
||||
MangaTag(
|
||||
key = href,
|
||||
title = a.ownText().toTitleCase(Locale.ENGLISH),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseChapters(ul: Element): List<MangaChapter> {
|
||||
val dateFormat = SimpleDateFormat(datePattern, Locale.US)
|
||||
return ul.select("li").mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirst("a")
|
||||
val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing")
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
name = a.ownText(),
|
||||
number = i + 1,
|
||||
url = href,
|
||||
uploadDate = parseChapterDate(
|
||||
dateFormat,
|
||||
li.selectFirst("span.chapter-release-date i")?.text(),
|
||||
),
|
||||
source = source,
|
||||
scanlator = null,
|
||||
branch = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,183 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import androidx.collection.arraySetOf
|
||||
import org.jsoup.nodes.Element
|
||||
import org.koitharu.kotatsu.parsers.InternalParsersApi
|
||||
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.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
abstract class Madara5Parser @InternalParsersApi constructor(
|
||||
context: MangaLoaderContext,
|
||||
source: MangaSource,
|
||||
domain: String,
|
||||
) : PagedMangaParser(context, source, pageSize = 22) {
|
||||
|
||||
protected open val datePattern = "MMMM dd, HH:mm"
|
||||
protected open val tagPrefix = "/mangas/"
|
||||
protected open val nsfwTags = arraySetOf("yaoi", "yuri", "mature")
|
||||
|
||||
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
|
||||
|
||||
override val configKeyDomain = ConfigKey.Domain(domain)
|
||||
|
||||
override suspend fun getListPage(
|
||||
page: Int,
|
||||
query: String?,
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val domain = domain
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
append("/search?s=")
|
||||
if (!query.isNullOrEmpty()) {
|
||||
append(query.urlEncoded())
|
||||
}
|
||||
append("&post_type=wp-manga")
|
||||
if (!tags.isNullOrEmpty()) {
|
||||
for (tag in tags) {
|
||||
append("&genre%5B%5D=")
|
||||
append(tag.key)
|
||||
}
|
||||
}
|
||||
append("&op=1&author=&artist=&page=")
|
||||
append(page)
|
||||
}
|
||||
val root = webClient.httpGet(url).parseHtml().body().selectFirstOrThrow(".search-wrap")
|
||||
return root.select(".c-tabs-item__content").map { div ->
|
||||
val a = div.selectFirstOrThrow("a")
|
||||
val img = div.selectLastOrThrow("img")
|
||||
val href = a.attrAsRelativeUrl("href")
|
||||
val postContent = root.selectFirstOrThrow(".post-content")
|
||||
val tagSet = postContent.getElementsContainingOwnText("Genre")
|
||||
.firstOrNull()?.tableValue()
|
||||
?.getElementsByAttributeValueContaining("href", tagPrefix)
|
||||
?.mapToSet { it.asMangaTag() }.orEmpty()
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
title = a.attr("title"),
|
||||
altTitle = postContent.getElementsContainingOwnText("Alternative")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
url = href,
|
||||
publicUrl = a.attrAsAbsoluteUrl("href"),
|
||||
coverUrl = img.src().orEmpty(),
|
||||
author = postContent.getElementsContainingOwnText("Author")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
state = postContent.getElementsContainingOwnText("Status")
|
||||
.firstOrNull()?.tableValue()?.text()?.asMangaState(),
|
||||
isNsfw = isNsfw(tagSet),
|
||||
rating = div.selectFirstOrThrow(".score").text()
|
||||
.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
|
||||
tags = tagSet,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val root = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml().body()
|
||||
.selectFirstOrThrow(".site-content")
|
||||
val postContent = root.selectFirstOrThrow(".post-content")
|
||||
val tags = postContent.getElementsContainingOwnText("Genre")
|
||||
.firstOrNull()?.tableValue()
|
||||
?.getElementsByAttributeValueContaining("href", tagPrefix)
|
||||
?.mapToSet { a -> a.asMangaTag() } ?: manga.tags
|
||||
val mangaId = root.getElementById("manga-chapters-holder")?.attr("data-id")?.toLongOrNull()
|
||||
?: root.parseFailed("Cannot find mangaId")
|
||||
return manga.copy(
|
||||
description = (root.selectFirst(".detail-content")
|
||||
?: root.selectFirstOrThrow(".description-summary")).html(),
|
||||
author = postContent.getElementsContainingOwnText("Author")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
state = postContent.getElementsContainingOwnText("Status")
|
||||
.firstOrNull()?.tableValue()?.text()?.asMangaState(),
|
||||
tags = tags,
|
||||
isNsfw = isNsfw(tags),
|
||||
chapters = loadChapters(mangaId),
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val arrayData = doc.getElementById("arraydata") ?: doc.parseFailed("#arraydata not found")
|
||||
return arrayData.html().split(',').map { url ->
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
preview = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("http://${domain}/").parseHtml().body()
|
||||
return doc.getElementsByAttributeValueContaining("href", tagPrefix)
|
||||
.mapToSet { it.asMangaTag() }
|
||||
}
|
||||
|
||||
private suspend fun loadChapters(mangaId: Long): List<MangaChapter> {
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
val doc = webClient.httpGet("https://${domain}/ajax-list-chapter?mangaID=$mangaId").parseHtml()
|
||||
return doc.select("li.wp-manga-chapter").mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirstOrThrow("a")
|
||||
val href = a.attrAsRelativeUrl("href")
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
name = a.text(),
|
||||
number = i + 1,
|
||||
branch = null,
|
||||
uploadDate = dateFormat.tryParse(
|
||||
li.selectFirst(".chapter-release-date")?.text()?.trim(),
|
||||
),
|
||||
scanlator = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
protected fun isNsfw(tags: Set<MangaTag>): Boolean {
|
||||
return tags.any { it.key in nsfwTags }
|
||||
}
|
||||
|
||||
private fun Element.src(): String? {
|
||||
return absUrl("data-src").ifEmpty {
|
||||
absUrl("src")
|
||||
}.takeUnless { it.isEmpty() }
|
||||
}
|
||||
|
||||
private fun Element.tableValue(): Element {
|
||||
for (p in parents()) {
|
||||
val children = p.children()
|
||||
if (children.size == 2) {
|
||||
return children[1]
|
||||
}
|
||||
}
|
||||
parseFailed("Cannot find tableValue for node ${text()}")
|
||||
}
|
||||
|
||||
private fun String.asMangaState() = when (trim().lowercase(sourceLocale)) {
|
||||
"ongoing" -> MangaState.ONGOING
|
||||
"completed" -> MangaState.FINISHED
|
||||
else -> null
|
||||
}
|
||||
|
||||
private fun Element.asMangaTag() = MangaTag(
|
||||
title = ownText(),
|
||||
key = attr("href").removeSuffix('/').substringAfterLast('/')
|
||||
.replace('-', '+'),
|
||||
source = source,
|
||||
)
|
||||
|
||||
@MangaSourceParser("MANGAOWLS", "BeautyManga", "en")
|
||||
class BeautyManga(context: MangaLoaderContext) : Madara5Parser(context, MangaSource.MANGAOWLS, "beautymanga.com")
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import org.jsoup.nodes.Element
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.text.SimpleDateFormat
|
||||
|
||||
internal abstract class Madara6Parser(
|
||||
context: MangaLoaderContext,
|
||||
source: MangaSource,
|
||||
domain: String,
|
||||
pageSize: Int = 12,
|
||||
) : MadaraParser(context, source, domain, pageSize) {
|
||||
|
||||
override val datePattern: String = "dd MMMM yyyy"
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
return coroutineScope {
|
||||
val chapters = async { loadChapters(manga.url) }
|
||||
val body = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml().body()
|
||||
parseDetails(manga, body, chapters.await())
|
||||
}
|
||||
}
|
||||
|
||||
protected fun Element.tableValue(): Element {
|
||||
for (p in parents()) {
|
||||
val children = p.children()
|
||||
if (children.size == 2) {
|
||||
return children[1]
|
||||
}
|
||||
}
|
||||
parseFailed("Cannot find tableValue for node ${text()}")
|
||||
}
|
||||
|
||||
protected abstract fun String.asMangaState(): MangaState?
|
||||
|
||||
protected fun Element.asMangaTag() = MangaTag(
|
||||
title = ownText(),
|
||||
key = attr("href").removeSuffix('/').substringAfterLast('/')
|
||||
.replace('-', '+'),
|
||||
source = source,
|
||||
)
|
||||
|
||||
protected open suspend fun loadChapters(mangaUrl: String): List<MangaChapter> {
|
||||
val url = mangaUrl.toAbsoluteUrl(domain).removeSuffix('/') + "/ajax/chapters/"
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
val doc = webClient.httpPost(url, emptyMap()).parseHtml()
|
||||
return doc.select("li.wp-manga-chapter").mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirstOrThrow("a")
|
||||
val href = a.attrAsRelativeUrl("href") + "?style=list"
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
name = a.text(),
|
||||
number = i + 1,
|
||||
branch = null,
|
||||
uploadDate = parseChapterDate(
|
||||
dateFormat,
|
||||
li.selectFirst("span.chapter-release-date i")?.text(),
|
||||
),
|
||||
scanlator = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun parseDetails(manga: Manga, body: Element, chapters: List<MangaChapter>): Manga
|
||||
}
|
||||
@@ -5,7 +5,6 @@ import kotlinx.coroutines.coroutineScope
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
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.exception.ParseException
|
||||
@@ -15,6 +14,7 @@ import java.text.DateFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
|
||||
internal abstract class MadaraParser(
|
||||
context: MangaLoaderContext,
|
||||
source: MangaSource,
|
||||
@@ -38,6 +38,28 @@ internal abstract class MadaraParser(
|
||||
searchPaginator.firstPage = 0
|
||||
}
|
||||
|
||||
protected fun Element.tableValue(): Element {
|
||||
for (p in parents()) {
|
||||
val children = p.children()
|
||||
if (children.size == 2) {
|
||||
return children[1]
|
||||
}
|
||||
}
|
||||
parseFailed("Cannot find tableValue for node ${text()}")
|
||||
}
|
||||
|
||||
|
||||
protected val ongoing: Array<String> = arrayOf(
|
||||
"مستمرة", "En curso", "En Curso","Ongoing", "OnGoing","On going",
|
||||
"Ativo", "En Cours", "En cours", "Đang tiến hành", "Em lançamento", "em lançamento", "Em Lançamento", "Онгоінг", "Publishing",
|
||||
"Devam Ediyor", "Em Andamento", "In Corso", "Güncel", "Berjalan", "Продолжается", "Updating",
|
||||
"Lançando", "In Arrivo", "Emision", "En emision", "مستمر", "Curso", "En marcha", "Publicandose", "连载中",)
|
||||
|
||||
protected val finished: Array<String> = arrayOf(
|
||||
"Completed", "Completo", "Complété", "Fini", "Terminé", "Tamamlandı", "Đã hoàn thành", "مكتملة", "Завершено",
|
||||
"Finished", "Finalizado", "Completata", "One-Shot", "Bitti", "Tamat", "Completado", "Concluído", "Concluido", "已完结",)
|
||||
|
||||
|
||||
override suspend fun getListPage(
|
||||
page: Int,
|
||||
query: String?,
|
||||
@@ -80,9 +102,16 @@ internal abstract class MadaraParser(
|
||||
}.orEmpty(),
|
||||
author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(),
|
||||
state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText()?.trim()
|
||||
?.lowercase()) {
|
||||
"ongoing" -> MangaState.ONGOING
|
||||
"completed" -> MangaState.FINISHED
|
||||
?.lowercase())
|
||||
{
|
||||
"مستمرة", "En curso", "En Curso","Ongoing", "OnGoing","On going",
|
||||
"Ativo", "En Cours", "En cours", "Đang tiến hành", "Em lançamento", "em lançamento", "Em Lançamento", "Онгоінг", "Publishing",
|
||||
"Devam Ediyor", "Em Andamento", "In Corso", "Güncel", "Berjalan", "Продолжается", "Updating",
|
||||
"Lançando", "In Arrivo", "Emision", "En emision", "مستمر", "Curso", "En marcha", "Publicandose", "连载中",
|
||||
-> MangaState.ONGOING
|
||||
"Completed", "Completo", "Complété", "Fini", "Terminé", "Tamamlandı", "Đã hoàn thành", "مكتملة", "Завершено",
|
||||
"Finished", "Finalizado", "Completata", "One-Shot", "Bitti", "Tamat", "Completado", "Concluído", "Concluido", "已完结",
|
||||
-> MangaState.FINISHED
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
@@ -120,36 +149,68 @@ internal abstract class MadaraParser(
|
||||
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val chaptersDeferred = async { getChapters(manga, doc) }
|
||||
val root = doc.body().selectFirst("div.profile-manga")?.selectFirst("div.summary_content")
|
||||
?.selectFirst("div.post-content") ?: throw ParseException("Root not found", fullUrl)
|
||||
val root2 = doc.body().selectFirst("div.content-area")?.selectFirst("div.c-page")
|
||||
?: throw ParseException("Root2 not found", fullUrl)
|
||||
manga.copy(
|
||||
tags = root.selectFirst("div.genres-content")?.select("a")?.mapNotNullToSet { a ->
|
||||
|
||||
val testchekasync = doc.body().select("div.listing-chapters_wrap")
|
||||
|
||||
val chaptersDeferred = if(testchekasync.isNullOrEmpty())
|
||||
{
|
||||
async { loadChapters(manga.url) }
|
||||
|
||||
}else
|
||||
{
|
||||
async { getChapters(manga, doc) }
|
||||
}
|
||||
|
||||
val desc = doc.body().selectFirst("div.description-summary div.summary__content") ?:
|
||||
doc.body().selectFirst("div.summary_content div.post-content_item > h5 + div") ?:
|
||||
doc.body().selectFirst("div.summary_content div.manga-excerpt")
|
||||
|
||||
|
||||
val stateselect =
|
||||
doc.body().select("div.post-content_item:contains(Status) > div.summary-content").last() ?: doc.body().select("div.post-content_item:contains(Statut) > div.summary-content").last()
|
||||
?: doc.body().select("div.post-content_item:contains(حالة العمل) > div.summary-content").last() ?: doc.body().select("div.post-content_item:contains(Estado) > div.summary-content").last()
|
||||
?: doc.body().select("div.post-content_item:contains(สถานะ) > div.summary-content").last() ?: doc.body().select("div.post-content_item:contains(Stato) > div.summary-content").last()
|
||||
?: doc.body().select("div.post-content_item:contains(Durum) > div.summary-content").last() ?: doc.body().select("div.post-content_item:contains(Statüsü) > div.summary-content").last()
|
||||
?: doc.body().select("div.summary-content").last()
|
||||
|
||||
val state =
|
||||
stateselect?.let {
|
||||
when (it.text()) {
|
||||
in ongoing -> MangaState.ONGOING
|
||||
in finished -> MangaState.FINISHED
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
manga.copy(
|
||||
tags = doc.body().select("div.genres-content a").mapNotNullToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
} ?: manga.tags,
|
||||
description = root2.selectFirst("div.description-summary")?.selectFirst("div.summary__content")?.select("p")
|
||||
?.filterNot { it.ownText().startsWith("A brief description") }?.joinToString { it.html() },
|
||||
},
|
||||
description = desc?.select("p")?.filterNot { it.ownText().startsWith("A brief description") }?.joinToString { it.text() },
|
||||
altTitle =
|
||||
doc.body().select(".post-content_item:contains(Alt) .summary-content").firstOrNull()?.tableValue()?.text()?.trim() ?:
|
||||
doc.body().select(".post-content_item:contains(Nomes alternativos: ) .summary-content").firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
state = state,
|
||||
chapters = chaptersDeferred.await(),
|
||||
)
|
||||
}
|
||||
|
||||
protected open suspend fun getChapters(manga: Manga, doc: Document): List<MangaChapter> {
|
||||
val root2 = doc.body().selectFirstOrThrow("div.content-area").selectFirstOrThrow("div.c-page")
|
||||
val root2 = doc.body().selectFirstOrThrow("div.content-area")
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
return root2.select("li").mapChapters(reversed = true) { i, li ->
|
||||
return root2.select("li.wp-manga-chapter").mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirst("a")
|
||||
val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing")
|
||||
val link = href + "?style=list"
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
name = a.ownText(),
|
||||
number = i + 1,
|
||||
url = href,
|
||||
url = link,
|
||||
uploadDate = parseChapterDate(
|
||||
dateFormat,
|
||||
li.selectFirst("span.chapter-release-date i")?.text(),
|
||||
@@ -161,6 +222,30 @@ internal abstract class MadaraParser(
|
||||
}
|
||||
}
|
||||
|
||||
protected open suspend fun loadChapters(mangaUrl: String): List<MangaChapter> {
|
||||
val url = mangaUrl.toAbsoluteUrl(domain).removeSuffix('/') + "/ajax/chapters/"
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
val doc = webClient.httpPost(url, emptyMap()).parseHtml()
|
||||
return doc.select("li.wp-manga-chapter").mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirst("a")
|
||||
val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing")
|
||||
val link = href + "?style=list"
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
url = link,
|
||||
name = a.text(),
|
||||
number = i + 1,
|
||||
branch = null,
|
||||
uploadDate = parseChapterDate(
|
||||
dateFormat,
|
||||
li.selectFirst("span.chapter-release-date i")?.text(),
|
||||
),
|
||||
scanlator = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
@@ -289,193 +374,4 @@ internal abstract class MadaraParser(
|
||||
it.substring(0, pos) to it.substring(pos + 1)
|
||||
}.toMutableMap()
|
||||
|
||||
@MangaSourceParser("MANGAWEEBS", "MangaWeebs", "en")
|
||||
class MangaWeebs(context: MangaLoaderContext) : MadaraParser(
|
||||
context, MangaSource.MANGAWEEBS, "mangaweebs.in",
|
||||
pageSize = 20,
|
||||
) {
|
||||
override val datePattern = "dd MMMM HH:mm"
|
||||
}
|
||||
|
||||
@MangaSourceParser("HACHIMANGA", "HachiManga", "ja")
|
||||
class HachiManga(context: MangaLoaderContext) : MadaraParser(context, MangaSource.HACHIMANGA, "hachiraw.com") {
|
||||
|
||||
override val sourceLocale: Locale = Locale.ENGLISH
|
||||
}
|
||||
|
||||
@MangaSourceParser("PIANMANGA", "PianManga", "en")
|
||||
class PianManga(context: MangaLoaderContext) : MadaraParser(
|
||||
context, MangaSource.PIANMANGA, "pianmanga.me",
|
||||
pageSize = 10,
|
||||
)
|
||||
|
||||
@MangaSourceParser("MANGAROSIE", "MangaRosie", "en")
|
||||
class MangaRosie(context: MangaLoaderContext) : MadaraParser(
|
||||
context, MangaSource.MANGAROSIE, "mangarosie.in",
|
||||
pageSize = 16,
|
||||
)
|
||||
|
||||
@MangaSourceParser("MANGATX", "MangaTx", "en")
|
||||
class MangaTx(context: MangaLoaderContext) : MadaraParser(context, MangaSource.MANGATX, "mangatx.com")
|
||||
|
||||
@MangaSourceParser("MANGAEFFECT", "MangaEffect", "en")
|
||||
class MangaEffect(context: MangaLoaderContext) : MadaraParser(context, MangaSource.MANGAEFFECT, "mangaeffect.com") {
|
||||
override val datePattern = "dd.MM.yyyy"
|
||||
}
|
||||
|
||||
@MangaSourceParser("AQUAMANGA", "AquaManga", "en")
|
||||
class AquaManga(context: MangaLoaderContext) : MadaraParser(context, MangaSource.AQUAMANGA, "aquamanga.com")
|
||||
|
||||
@MangaSourceParser("MANGALEK", "MangaLek", "ar")
|
||||
class MangaLek(context: MangaLoaderContext) : MadaraParser(
|
||||
context, MangaSource.MANGALEK, "mangalek.com",
|
||||
pageSize = 10,
|
||||
)
|
||||
|
||||
@MangaSourceParser("HARIMANGA", "HariManga", "en")
|
||||
class HariManga(context: MangaLoaderContext) : MadaraParser(
|
||||
context, MangaSource.HARIMANGA, "harimanga.com",
|
||||
pageSize = 10,
|
||||
) {
|
||||
override val datePattern = "MM/dd/yyyy"
|
||||
}
|
||||
|
||||
@MangaSourceParser("KISSMANGA", "KissManga", "en")
|
||||
class KissManga(context: MangaLoaderContext) : MadaraParser(context, MangaSource.KISSMANGA, "kissmanga.in")
|
||||
|
||||
@MangaSourceParser("MANGAROCK", "MangaRock", "en")
|
||||
class MangaRock(context: MangaLoaderContext) : MadaraParser(context, MangaSource.MANGAROCK, "mangarockteam.com")
|
||||
|
||||
@MangaSourceParser("FREEMANGA", "FreeManga", "en")
|
||||
class FreeManga(context: MangaLoaderContext) : MadaraParser(context, MangaSource.FREEMANGA, "freemanga.me")
|
||||
|
||||
@MangaSourceParser("MANGA_KOMI", "MangaKomi", "en")
|
||||
class MangaKomi(context: MangaLoaderContext) : MadaraParser(
|
||||
context, MangaSource.MANGA_KOMI, "mangakomi.io",
|
||||
pageSize = 18,
|
||||
)
|
||||
|
||||
@MangaSourceParser("MANHWACLAN", "ManhwaClan", "en")
|
||||
class ManhwaClan(context: MangaLoaderContext) : MadaraParser(
|
||||
context, MangaSource.MANHWACLAN, "manhwaclan.com",
|
||||
pageSize = 10,
|
||||
)
|
||||
|
||||
@MangaSourceParser("MANGA_3S", "Manga3s", "en")
|
||||
class Manga3s(context: MangaLoaderContext) : MadaraParser(context, MangaSource.MANGA_3S, "manga3s.com") {
|
||||
override val tagPrefix = "manhwa-genre/"
|
||||
}
|
||||
|
||||
@MangaSourceParser("MANHWAKOOL", "Manhwa Kool", "en")
|
||||
class ManhwaKool(context: MangaLoaderContext) : MadaraParser(
|
||||
context, MangaSource.MANHWAKOOL, "manhwakool.com",
|
||||
pageSize = 10,
|
||||
) {
|
||||
override val datePattern: String = "MM/dd"
|
||||
}
|
||||
|
||||
@MangaSourceParser("TOPMANHUA", "Top Manhua", "en")
|
||||
class TopManhua(context: MangaLoaderContext) : MadaraParser(context, MangaSource.TOPMANHUA, "www.topmanhua.com") {
|
||||
override val tagPrefix = "manhua-genre/"
|
||||
override val datePattern = "MM/dd/yyyy"
|
||||
}
|
||||
|
||||
@MangaSourceParser("S2MANGA", "S2Manga", "en")
|
||||
class S2Manga(context: MangaLoaderContext) : MadaraParser(context, MangaSource.S2MANGA, "s2manga.com")
|
||||
|
||||
@MangaSourceParser("SKY_MANGA", "Sky Manga", "en")
|
||||
class SkyManga(context: MangaLoaderContext) : MadaraParser(context, MangaSource.SKY_MANGA, "skymanga.xyz") {
|
||||
|
||||
override val isNsfwSource = true
|
||||
|
||||
}
|
||||
|
||||
@MangaSourceParser("BAKAMAN", "BakaMan", "th")
|
||||
class BakaMan(context: MangaLoaderContext) : MadaraParser(
|
||||
context, MangaSource.BAKAMAN, "bakaman.net",
|
||||
pageSize = 18,
|
||||
) {
|
||||
|
||||
override val isNsfwSource = false
|
||||
}
|
||||
|
||||
@MangaSourceParser("HENTAI20", "Hentai20", "en")
|
||||
class Hentai20(context: MangaLoaderContext) : MadaraParser(context, MangaSource.HENTAI20, "hentai20.io") {
|
||||
|
||||
override val tagPrefix = "manga-genre/"
|
||||
|
||||
override val isNsfwSource = true
|
||||
}
|
||||
|
||||
@MangaSourceParser("ALLPORN_COMIC", "All Porn Comic", "en")
|
||||
class AllPornComic(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.ALLPORN_COMIC, "allporncomic.com", pageSize = 24) {
|
||||
|
||||
override val tagPrefix = "porncomic-genre/"
|
||||
|
||||
override val isNsfwSource = true
|
||||
|
||||
}
|
||||
|
||||
@MangaSourceParser("CAT_300", "Cat300", "th")
|
||||
class Cat300(context: MangaLoaderContext) : MadaraParser(context, MangaSource.CAT_300, "cat300.com") {
|
||||
|
||||
override val isNsfwSource = true
|
||||
}
|
||||
|
||||
@MangaSourceParser("BIBIMANGA", "BibiManga", "en")
|
||||
class BibiManga(context: MangaLoaderContext) : MadaraParser(context, MangaSource.BIBIMANGA, "bibimanga.com") {
|
||||
|
||||
override val isNsfwSource = false
|
||||
}
|
||||
|
||||
@MangaSourceParser("TREE_MANGA", "Tree Manga", "en")
|
||||
class TreeManga(context: MangaLoaderContext) : MadaraParser(context, MangaSource.TREE_MANGA, "treemanga.com") {
|
||||
|
||||
override val datePattern = "MM/dd/yyyy"
|
||||
|
||||
}
|
||||
|
||||
@MangaSourceParser("MANGACV", "Manga Cv", "en")
|
||||
class MangaCv(context: MangaLoaderContext) : MadaraParser(
|
||||
context, MangaSource.MANGACV, "mangacv.com",
|
||||
pageSize = 10,
|
||||
)
|
||||
|
||||
@MangaSourceParser("TOONILY", "Toonily", "en")
|
||||
class Toonily(context: MangaLoaderContext) : MadaraParser(
|
||||
context, MangaSource.TOONILY, "toonily.com",
|
||||
pageSize = 18,
|
||||
) {
|
||||
|
||||
override val tagPrefix = "webtoon-genre/"
|
||||
|
||||
override val isNsfwSource = false
|
||||
}
|
||||
|
||||
@MangaSourceParser("MANGA_MANHUA", "Manga Manhua", "en")
|
||||
class MangaManhua(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGA_MANHUA, "mangamanhua.online", pageSize = 10)
|
||||
|
||||
@MangaSourceParser("MANGA_247", "247MANGA", "en")
|
||||
class Manga247(context: MangaLoaderContext) : MadaraParser(context, MangaSource.MANGA_247, "247manga.com") {
|
||||
override val tagPrefix = "manhwa-genre/"
|
||||
}
|
||||
|
||||
@MangaSourceParser("MANGA_365", "365Manga", "en")
|
||||
class Manga365(context: MangaLoaderContext) : MadaraParser(context, MangaSource.MANGA_365, "365manga.com")
|
||||
|
||||
@MangaSourceParser("MANGACLASH", "Mangaclash", "en")
|
||||
class Mangaclash(context: MangaLoaderContext) : MadaraParser(
|
||||
context, MangaSource.MANGACLASH, "mangaclash.com",
|
||||
pageSize = 18,
|
||||
) {
|
||||
override val datePattern = "MM/dd/yyyy"
|
||||
}
|
||||
|
||||
@MangaSourceParser("ZINMANGA", "ZINMANGA", "en")
|
||||
class Zinmanga(context: MangaLoaderContext) : MadaraParser(context, MangaSource.ZINMANGA, "zinmanga.com")
|
||||
|
||||
@MangaSourceParser("STKISSMANGA", "Stkissmanga", "en")
|
||||
class Stkissmanga(context: MangaLoaderContext) : MadaraParser(context, MangaSource.STKISSMANGA, "1stkissmanga.me")
|
||||
}
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import org.jsoup.nodes.Element
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaState
|
||||
import org.koitharu.kotatsu.parsers.util.assertNotNull
|
||||
import org.koitharu.kotatsu.parsers.util.attrAsAbsoluteUrlOrNull
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("MANGA_SCANTRAD", "Manga Scantrad", "fr")
|
||||
internal class MangaScantrad(context: MangaLoaderContext) :
|
||||
Madara6Parser(context, MangaSource.MANGA_SCANTRAD, "manga-scantrad.io") {
|
||||
|
||||
override val datePattern = "d MMMM yyyy"
|
||||
override val sourceLocale: Locale = Locale.FRENCH
|
||||
|
||||
override fun String.asMangaState(): MangaState? = when (this) {
|
||||
"OnGoing",
|
||||
-> MangaState.ONGOING
|
||||
|
||||
"Complété",
|
||||
-> MangaState.FINISHED
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
override fun parseDetails(manga: Manga, body: Element, chapters: List<MangaChapter>): Manga {
|
||||
val root = body.selectFirstOrThrow(".site-content")
|
||||
val postContent = root.selectFirstOrThrow(".summary_content")
|
||||
val tags = postContent.getElementsContainingOwnText("Genre(s)")
|
||||
.firstOrNull()?.tableValue()
|
||||
?.getElementsByAttributeValueContaining("href", tagPrefix)
|
||||
?.mapToSet { a -> a.asMangaTag() } ?: manga.tags
|
||||
return manga.copy(
|
||||
rating = postContent.selectFirstOrThrow(".post-rating")
|
||||
.selectFirstOrThrow(".total_votes").text().toFloat() / 5f,
|
||||
largeCoverUrl = root.selectFirst(".summary_image")
|
||||
?.selectFirst("img[data-src]")
|
||||
?.attrAsAbsoluteUrlOrNull("data-src")
|
||||
.assertNotNull("largeCoverUrl"),
|
||||
description = root.selectFirstOrThrow(".description-summary")
|
||||
.firstElementChild()?.html(),
|
||||
author = postContent.getElementsContainingOwnText("Auteur(s)")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
altTitle = postContent.getElementsContainingOwnText("Alternatif")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
state = postContent.getElementsContainingOwnText("État")
|
||||
.firstOrNull()?.tableValue()?.text()?.asMangaState(),
|
||||
tags = tags,
|
||||
isNsfw = body.hasClass("adult-content"),
|
||||
chapters = chapters,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.exception.ParseException
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
|
||||
@MangaSourceParser("MANGALINK_AR", "Mangalink", "ar")
|
||||
internal class MangalinkParser(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGALINK_AR, "mangalink.online", pageSize = 10) {
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val chaptersDeferred = async { getChapters(manga, doc) }
|
||||
val root = doc.body().selectFirst("div.profile-manga")
|
||||
?.selectFirst("div.summary_content")
|
||||
?.selectFirst("div.post-content")
|
||||
?: throw ParseException("Root not found", fullUrl)
|
||||
val root2 = doc.body().selectFirst("div.content-area")
|
||||
?.selectFirst("div.c-page")
|
||||
?: throw ParseException("Root2 not found", fullUrl)
|
||||
manga.copy(
|
||||
tags = root.selectFirst("div.genres-content")?.select("a")
|
||||
?.mapNotNullToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
} ?: manga.tags,
|
||||
description = root2.selectFirst("div.description-summary")
|
||||
?.selectFirst("div.summary__content")
|
||||
?.select("p")
|
||||
?.filterNot { it.ownText().startsWith("A brief description") }
|
||||
?.joinToString { it.html() },
|
||||
chapters = chaptersDeferred.await(),
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.exception.ParseException
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("NEATMANGA", "NeatManga", "en")
|
||||
internal class NeatManga(context: MangaLoaderContext) : MadaraParser(
|
||||
context, MangaSource.NEATMANGA, "neatmangas.com",
|
||||
pageSize = 20,
|
||||
) {
|
||||
|
||||
override val datePattern = "dd MMMM yyyy"
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
|
||||
val chaptersDeferred = async { getChapters(manga) }
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val root = doc.body().selectFirst("div.profile-manga")
|
||||
?.selectFirst("div.summary_content")
|
||||
?.selectFirst("div.post-content")
|
||||
?: throw ParseException("Root not found", fullUrl)
|
||||
val root2 = doc.body().selectFirst("div.content-area")
|
||||
?.selectFirst("div.c-page")
|
||||
?: throw ParseException("Root2 not found", fullUrl)
|
||||
manga.copy(
|
||||
tags = root.selectFirst("div.genres-content")?.select("a")
|
||||
?.mapNotNullToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
} ?: manga.tags,
|
||||
description = root2.getElementsMatchingOwnText("Summary")
|
||||
.firstOrNull()
|
||||
?.nextElementSibling()
|
||||
?.select("p")
|
||||
?.filterNot { it.ownText().startsWith("A brief description") }
|
||||
?.joinToString { it.html() },
|
||||
chapters = chaptersDeferred.await(),
|
||||
)
|
||||
}
|
||||
|
||||
private suspend fun getChapters(manga: Manga): List<MangaChapter> {
|
||||
val slug = manga.url.removeSuffix('/').substringAfterLast('/')
|
||||
val doc2 = webClient.httpPost(
|
||||
"https://$domain/manga/$slug/ajax/chapters/",
|
||||
mapOf(),
|
||||
).parseHtml()
|
||||
val ul = doc2.body().selectFirstOrThrow("ul")
|
||||
val dateFormat = SimpleDateFormat(datePattern, Locale.US)
|
||||
return ul.select("li").mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirst("a")
|
||||
val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing")
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
name = a.ownText(),
|
||||
number = i + 1,
|
||||
url = href,
|
||||
uploadDate = parseChapterDate(
|
||||
dateFormat,
|
||||
li.selectFirst("span.chapter-release-date i")?.text(),
|
||||
),
|
||||
source = source,
|
||||
scanlator = null,
|
||||
branch = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val root = doc.body().selectFirst("div.main-col-inner")
|
||||
?.selectFirst("div.reading-content")
|
||||
?: throw ParseException("Root not found", fullUrl)
|
||||
return root.select("div.page-break").mapNotNull { div ->
|
||||
val img = div.selectFirst("img")
|
||||
if (img == null || img.attr("id").isNullOrEmpty()) {
|
||||
return@mapNotNull null
|
||||
}
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: div.parseFailed("Image src not found")
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
preview = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import org.jsoup.nodes.Element
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaState
|
||||
import org.koitharu.kotatsu.parsers.util.attrAsAbsoluteUrlOrNull
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
|
||||
@MangaSourceParser("PRISMA_SCANS", "Prisma Scans", "pt")
|
||||
internal class PrismaScansParser(context: MangaLoaderContext) :
|
||||
Madara6Parser(context, MangaSource.PRISMA_SCANS, "prismascans.net", 10) {
|
||||
|
||||
override val tagPrefix = "manga-genre/"
|
||||
override val datePattern = "MMM dd, yyyy"
|
||||
|
||||
override fun parseDetails(manga: Manga, body: Element, chapters: List<MangaChapter>): Manga {
|
||||
val root = body.selectFirstOrThrow(".site-content")
|
||||
val postContent = root.selectFirstOrThrow(".post-content")
|
||||
val tags = postContent.getElementsContainingOwnText("Gênero")
|
||||
.firstOrNull()?.tableValue()
|
||||
?.getElementsByAttributeValueContaining("href", tagPrefix)
|
||||
?.mapToSet { a -> a.asMangaTag() } ?: manga.tags
|
||||
return manga.copy(
|
||||
largeCoverUrl = root.selectFirst("picture")
|
||||
?.selectFirst("img[data-src]")
|
||||
?.attrAsAbsoluteUrlOrNull("data-src"),
|
||||
description = root.selectFirstOrThrow(".manga-excerpt").firstElementChild()?.html(),
|
||||
author = postContent.getElementsContainingOwnText("Artista")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
altTitle = postContent.getElementsContainingOwnText("Título Alternativo")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
state = postContent.getElementsContainingOwnText("Status")
|
||||
.firstOrNull()?.tableValue()?.text()?.asMangaState(),
|
||||
tags = tags,
|
||||
isNsfw = body.hasClass("adult-content"),
|
||||
chapters = chapters,
|
||||
)
|
||||
}
|
||||
|
||||
override fun String.asMangaState() = when (trim().lowercase(sourceLocale)) {
|
||||
"em lançamento" -> MangaState.ONGOING
|
||||
"completo",
|
||||
"cancelado",
|
||||
-> MangaState.FINISHED
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
|
||||
@MangaSourceParser("REAPERSCANS_FR", "ReaperScansFr", "fr")
|
||||
internal class ReaperScansFr(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.REAPERSCANS_FR, "reaperscans.fr") {
|
||||
|
||||
override val datePattern = "MM/dd/yyyy"
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val chaptersDeferred = async { getChapters(manga, doc) }
|
||||
val root = doc.body().selectFirstOrThrow(".site-content")
|
||||
manga.copy(
|
||||
tags = root.selectFirst("div.genres-content")?.select("a")?.mapNotNullToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
} ?: manga.tags,
|
||||
description = root.requireElementById("nav-profile")
|
||||
.selectFirstOrThrow(".description-summary")
|
||||
.firstElementChild()?.html(),
|
||||
chapters = chaptersDeferred.await(),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import org.jsoup.nodes.Element
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("REAPER_SCANS_ID", "ReaperScansID", "id")
|
||||
internal class ReaperScansParser(context: MangaLoaderContext) :
|
||||
Madara6Parser(context, MangaSource.REAPER_SCANS_ID, "reaperscans.id") {
|
||||
|
||||
override val datePattern = "MMMM dd, yyyy"
|
||||
override val tagPrefix = "genre/"
|
||||
override val sourceLocale: Locale = Locale.ENGLISH
|
||||
|
||||
override fun String.asMangaState(): MangaState? = when (this) {
|
||||
"OnGoing",
|
||||
"Upcoming",
|
||||
-> MangaState.ONGOING
|
||||
|
||||
"Completed",
|
||||
"Dropped",
|
||||
-> MangaState.FINISHED
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
override fun parseDetails(manga: Manga, body: Element, chapters: List<MangaChapter>): Manga {
|
||||
val root = body.selectFirstOrThrow(".site-content")
|
||||
val postContent = root.requireElementById("nav-info")
|
||||
val tags = postContent.getElementsContainingOwnText("Gênero")
|
||||
.firstOrNull()?.tableValue()
|
||||
?.getElementsByAttributeValueContaining("href", tagPrefix)
|
||||
?.mapToSet { a -> a.asMangaTag() } ?: manga.tags
|
||||
return manga.copy(
|
||||
rating = postContent.selectFirstOrThrow(".post-rating")
|
||||
.selectFirstOrThrow(".total_votes").text().toFloat() / 5f,
|
||||
largeCoverUrl = root.selectFirst(".summary_image")
|
||||
?.selectFirst("img[data-src]")
|
||||
?.attrAsAbsoluteUrlOrNull("data-src")
|
||||
.assertNotNull("largeCoverUrl"),
|
||||
description = root.requireElementById("nav-profile")
|
||||
.selectFirstOrThrow(".description-summary")
|
||||
.firstElementChild()?.html(),
|
||||
author = postContent.getElementsContainingOwnText("Author(s)")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
altTitle = postContent.getElementsContainingOwnText("Alternative")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
state = postContent.getElementsContainingOwnText("Status")
|
||||
.firstOrNull()?.tableValue()?.text()?.asMangaState(),
|
||||
tags = tags,
|
||||
isNsfw = body.hasClass("adult-content"),
|
||||
chapters = chapters,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://${domain}/semua-komik/").parseHtml()
|
||||
val body = doc.body()
|
||||
val root1 = body.selectFirst("header")?.selectFirst("ul.second-menu")
|
||||
val root2 = body.selectFirst("div.genres_wrap")?.selectFirst("ul.list-unstyled")
|
||||
if (root1 == null && root2 == null) {
|
||||
doc.parseFailed("Root not found")
|
||||
}
|
||||
val list = root1?.select("li").orEmpty() + root2?.select("li").orEmpty()
|
||||
val keySet = HashSet<String>(list.size)
|
||||
return list.mapNotNullToSet { li ->
|
||||
val a = li.selectFirst("a") ?: return@mapNotNullToSet null
|
||||
val href = a.attr("href").removeSuffix("/")
|
||||
.substringAfterLast(tagPrefix, "")
|
||||
if (href.isEmpty() || !keySet.add(href)) {
|
||||
return@mapNotNullToSet null
|
||||
}
|
||||
MangaTag(
|
||||
key = href,
|
||||
title = a.ownText().trim().ifEmpty {
|
||||
a.selectFirst(".menu-image-title")?.text()?.trim() ?: return@mapNotNullToSet null
|
||||
}.toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,76 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import org.jsoup.nodes.Element
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
|
||||
@MangaSourceParser("SCANTRADVF", "ScantradVf", "fr")
|
||||
internal class ScantradVf(context: MangaLoaderContext) :
|
||||
Madara6Parser(context, MangaSource.SCANTRADVF, "scantrad-vf.co") {
|
||||
|
||||
override val datePattern = "d MMMM yyyy"
|
||||
|
||||
override val tagPrefix = "genre/"
|
||||
|
||||
override fun String.asMangaState(): MangaState? = when (this) {
|
||||
"En cours",
|
||||
-> MangaState.ONGOING
|
||||
|
||||
"Complété",
|
||||
"Terminé",
|
||||
-> MangaState.FINISHED
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
override fun parseDetails(manga: Manga, body: Element, chapters: List<MangaChapter>): Manga {
|
||||
val root = body.selectFirstOrThrow(".site-content")
|
||||
val postContent = root.selectFirstOrThrow(".summary_content")
|
||||
val tags = postContent.getElementsContainingOwnText("Genre(s)")
|
||||
.firstOrNull()?.tableValue()
|
||||
?.getElementsByAttributeValueContaining("href", tagPrefix)
|
||||
?.mapToSet { a -> a.asMangaTag() } ?: manga.tags
|
||||
return manga.copy(
|
||||
rating = postContent.selectFirstOrThrow(".post-rating")
|
||||
.selectFirstOrThrow(".total_votes").text().toFloat() / 5f,
|
||||
description = root.selectFirstOrThrow(".description-summary")
|
||||
.firstElementChild()?.html(),
|
||||
author = postContent.getElementsContainingOwnText("Auteur(s)")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
state = postContent.getElementsContainingOwnText("Status")
|
||||
.firstOrNull()?.tableValue()?.text()?.asMangaState(),
|
||||
tags = tags,
|
||||
isNsfw = body.hasClass("adult-content"),
|
||||
chapters = chapters,
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun getTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://${domain}/genre/action/").parseHtml()
|
||||
val body = doc.body()
|
||||
val root1 = body.selectFirst("header")?.selectFirst("ul.second-menu")
|
||||
val root2 = body.selectFirst("div.genres_wrap")?.selectFirst("ul.list-unstyled")
|
||||
if (root1 == null && root2 == null) {
|
||||
doc.parseFailed("Root not found")
|
||||
}
|
||||
val list = root2?.select("li").orEmpty()
|
||||
val keySet = HashSet<String>(list.size)
|
||||
return list.mapNotNullToSet { li ->
|
||||
val a = li.selectFirst("a") ?: return@mapNotNullToSet null
|
||||
val href = a.attr("href").removeSuffix("/")
|
||||
.substringAfterLast(tagPrefix, "")
|
||||
if (href.isEmpty() || !keySet.add(href)) {
|
||||
return@mapNotNullToSet null
|
||||
}
|
||||
MangaTag(
|
||||
key = href,
|
||||
title = a.ownText().trim().ifEmpty {
|
||||
return@mapNotNullToSet null
|
||||
}.toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
|
||||
import org.jsoup.nodes.Element
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaState
|
||||
import org.koitharu.kotatsu.parsers.util.attrAsAbsoluteUrlOrNull
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("TATAKAE_SCANS", "Tatakae Scans", "pt")
|
||||
internal class TatakaeScansParser(context: MangaLoaderContext) :
|
||||
Madara6Parser(context, MangaSource.TATAKAE_SCANS, "tatakaescan.com", pageSize = 10) {
|
||||
|
||||
override val datePattern: String = "dd 'de' MMMMM 'de' yyyy"
|
||||
|
||||
override fun parseDetails(manga: Manga, body: Element, chapters: List<MangaChapter>): Manga {
|
||||
val root = body.selectFirstOrThrow(".site-content")
|
||||
val postContent = root.selectFirstOrThrow(".post-content")
|
||||
val tags = postContent.getElementsContainingOwnText("Gênero")
|
||||
.firstOrNull()?.tableValue()
|
||||
?.getElementsByAttributeValueContaining("href", tagPrefix)
|
||||
?.mapToSet { a -> a.asMangaTag() } ?: manga.tags
|
||||
return manga.copy(
|
||||
largeCoverUrl = root.selectFirst("picture")
|
||||
?.selectFirst("img[data-src]")
|
||||
?.attrAsAbsoluteUrlOrNull("data-src"),
|
||||
description = (root.selectFirst(".detail-content")
|
||||
?: root.selectFirstOrThrow(".manga-excerpt")).html(),
|
||||
author = postContent.getElementsContainingOwnText("Autor")
|
||||
.firstOrNull()?.tableValue()?.text()?.trim(),
|
||||
state = postContent.getElementsContainingOwnText("Status")
|
||||
.firstOrNull()?.tableValue()?.text()?.asMangaState(),
|
||||
tags = tags,
|
||||
isNsfw = body.hasClass("adult-content"),
|
||||
chapters = chapters,
|
||||
)
|
||||
}
|
||||
|
||||
override fun String.asMangaState() = when (trim().lowercase(Locale.ROOT)) {
|
||||
"em lançamento" -> MangaState.ONGOING
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGALEK", "MangaLek", "ar")
|
||||
internal class MangaLek(context: MangaLoaderContext) : MadaraParser(
|
||||
context, MangaSource.MANGALEK, "mangalek.com",
|
||||
pageSize = 10,
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.ar
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGALINK_AR", "Mangalink", "ar")
|
||||
internal class MangalinkParser(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGALINK_AR, "mangalink.online", pageSize = 10)
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("ALLPORN_COMIC", "All Porn Comic", "en")
|
||||
internal class AllPornComic(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.ALLPORN_COMIC, "allporncomic.com", pageSize = 24) {
|
||||
|
||||
override val tagPrefix = "porncomic-genre/"
|
||||
|
||||
override val isNsfwSource = true
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("AQUAMANGA", "AquaManga", "en")
|
||||
internal class AquaManga(context: MangaLoaderContext) : MadaraParser(context, MangaSource.AQUAMANGA, "aquamanga.com")
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("BIBIMANGA", "BibiManga", "en")
|
||||
internal class BibiManga(context: MangaLoaderContext) : MadaraParser(context, MangaSource.BIBIMANGA, "bibimanga.com") {
|
||||
|
||||
override val isNsfwSource = false
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("FREEMANGA", "FreeManga", "en")
|
||||
internal class FreeManga(context: MangaLoaderContext) : MadaraParser(context, MangaSource.FREEMANGA, "freemanga.me")
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("HARIMANGA", "HariManga", "en")
|
||||
internal class HariManga(context: MangaLoaderContext) :
|
||||
MadaraParser( context, MangaSource.HARIMANGA, "harimanga.com", pageSize = 10,) {
|
||||
|
||||
override val datePattern = "MMMM d, yyyy"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("HENTAI20", "Hentai20", "en")
|
||||
internal class Hentai20(context: MangaLoaderContext) : MadaraParser(context, MangaSource.HENTAI20, "hentai20.io") {
|
||||
|
||||
override val tagPrefix = "manga-genre/"
|
||||
|
||||
override val isNsfwSource = true
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.en
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("HENTAI_4FREE", "Hentai4Free", "en")
|
||||
internal class Hentai4Free(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.HENTAI_4FREE, "hentai4free.net", pageSize = 24) {
|
||||
|
||||
override val tagPrefix = "hentai-tag/"
|
||||
|
||||
override val isNsfwSource = true
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.en
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("ISEKAISCAN_EU", "IsekaiScan", "en")
|
||||
internal class IsekaiScanEuParser(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.ISEKAISCAN_EU, "isekaiscan.to") {
|
||||
|
||||
override val datePattern = "MM/dd/yyyy"
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("KISSMANGA", "KissManga", "en")
|
||||
internal class KissManga(context: MangaLoaderContext) : MadaraParser(context, MangaSource.KISSMANGA, "kissmanga.in")
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGA_247", "247MANGA", "en")
|
||||
internal class Manga247(context: MangaLoaderContext) : MadaraParser(context, MangaSource.MANGA_247, "247manga.com") {
|
||||
override val tagPrefix = "manhwa-genre/"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGA_365", "365Manga", "en")
|
||||
internal class Manga365(context: MangaLoaderContext) : MadaraParser(context, MangaSource.MANGA_365, "365manga.com")
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGA_3S", "Manga3s", "en")
|
||||
internal class Manga3s(context: MangaLoaderContext) : MadaraParser(context, MangaSource.MANGA_3S, "manga3s.com") {
|
||||
|
||||
override val tagPrefix = "manhwa-genre/"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGACV", "Manga Cv", "en")
|
||||
internal class MangaCv(context: MangaLoaderContext) : MadaraParser(context, MangaSource.MANGACV, "mangacv.com", pageSize = 10,)
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
package org.koitharu.kotatsu.parsers.site.madara.en
|
||||
|
||||
import org.jsoup.nodes.Document
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
@@ -6,6 +6,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGAEFFECT", "MangaEffect", "en")
|
||||
internal class MangaEffect(context: MangaLoaderContext) : MadaraParser(context, MangaSource.MANGAEFFECT, "mangaeffect.com") {
|
||||
override val datePattern = "dd.MM.yyyy"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGA_KOMI", "MangaKomi", "en")
|
||||
internal class MangaKomi(context: MangaLoaderContext) : MadaraParser( context, MangaSource.MANGA_KOMI, "mangakomi.io", pageSize = 18,)
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGA_MANHUA", "Manga Manhua", "en")
|
||||
internal class MangaManhua(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGA_MANHUA, "mangamanhua.online", pageSize = 10)
|
||||
{
|
||||
override val datePattern = "d MMMM، yyyy"
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara
|
||||
package org.koitharu.kotatsu.parsers.site.madara.en
|
||||
|
||||
import androidx.collection.arraySetOf
|
||||
import org.jsoup.nodes.Element
|
||||
@@ -6,6 +6,7 @@ import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.exception.ParseException
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.util.*
|
||||
|
||||
@@ -97,15 +98,6 @@ internal class MangaRead(context: MangaLoaderContext) :
|
||||
}
|
||||
}
|
||||
|
||||
private fun Element.tableValue(): Element {
|
||||
for (p in parents()) {
|
||||
val children = p.children()
|
||||
if (children.size == 2) {
|
||||
return children[1]
|
||||
}
|
||||
}
|
||||
parseFailed("Cannot find tableValue for node ${text()}")
|
||||
}
|
||||
|
||||
private fun isNsfw(tags: Set<MangaTag>): Boolean {
|
||||
return tags.any { it.key in nsfwTags }
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGAROCK", "MangaRock", "en")
|
||||
internal class MangaRock(context: MangaLoaderContext) : MadaraParser(context, MangaSource.MANGAROCK, "mangarockteam.com")
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGAROSIE", "MangaRosie", "en")
|
||||
internal class MangaRosie(context: MangaLoaderContext) : MadaraParser(
|
||||
context, MangaSource.MANGAROSIE, "mangarosie.in",
|
||||
pageSize = 16,
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGATX", "MangaTx", "en")
|
||||
internal class MangaTx(context: MangaLoaderContext) : MadaraParser(context, MangaSource.MANGATX, "mangatx.com")
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGAWEEBS", "MangaWeebs", "en")
|
||||
internal class MangaWeebs(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGAWEEBS, "mangaweebs.in", pageSize = 20,) {
|
||||
|
||||
override val datePattern = "dd MMMM HH:mm"
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGACLASH", "Mangaclash", "en")
|
||||
internal class Mangaclash(context: MangaLoaderContext) : MadaraParser(context, MangaSource.MANGACLASH, "mangaclash.com", pageSize = 18,) {
|
||||
override val datePattern = "MM/dd/yyyy"
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANHWACLAN", "ManhwaClan", "en")
|
||||
internal class ManhwaClan(context: MangaLoaderContext) : MadaraParser( context, MangaSource.MANHWACLAN, "manhwaclan.com", pageSize = 10,)
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANHWAKOOL", "Manhwa Kool", "en")
|
||||
internal class ManhwaKool(context: MangaLoaderContext) : MadaraParser( context, MangaSource.MANHWAKOOL, "manhwakool.com", pageSize = 10,) {
|
||||
|
||||
override val datePattern: String = "MMMM d, yyyy"
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.en
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("NEATMANGA", "NeatManga", "en")
|
||||
internal class NeatManga(context: MangaLoaderContext) : MadaraParser(
|
||||
context, MangaSource.NEATMANGA, "neatmangas.com",
|
||||
pageSize = 20,
|
||||
) {
|
||||
|
||||
override val datePattern = "dd MMMM yyyy"
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.en
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("PIANMANGA", "PianManga", "en")
|
||||
internal class PianManga(context: MangaLoaderContext) : MadaraParser(
|
||||
context, MangaSource.PIANMANGA, "pianmanga.me",
|
||||
pageSize = 10,
|
||||
)
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("S2MANGA", "S2Manga", "en")
|
||||
internal class S2Manga(context: MangaLoaderContext) : MadaraParser(context, MangaSource.S2MANGA, "s2manga.com")
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("STKISSMANGA", "Stkissmanga", "en")
|
||||
internal class Stkissmanga(context: MangaLoaderContext) : MadaraParser(context, MangaSource.STKISSMANGA, "1stkissmanga.me")
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("TOONILY", "Toonily", "en")
|
||||
internal class Toonily(context: MangaLoaderContext) : MadaraParser(context, MangaSource.TOONILY, "toonily.com", pageSize = 18,) {
|
||||
|
||||
override val tagPrefix = "webtoon-genre/"
|
||||
|
||||
override val isNsfwSource = false
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("TOPMANHUA", "Top Manhua", "en")
|
||||
internal class TopManhua(context: MangaLoaderContext) : MadaraParser(context, MangaSource.TOPMANHUA, "www.topmanhua.com") {
|
||||
|
||||
override val tagPrefix = "manhua-genre/"
|
||||
override val datePattern = "MM/dd/yyyy"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("TREE_MANGA", "Tree Manga", "en")
|
||||
internal class TreeManga(context: MangaLoaderContext) : MadaraParser(context, MangaSource.TREE_MANGA, "treemanga.com") {
|
||||
|
||||
override val datePattern = "MM/dd/yyyy"
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("ZINMANGA", "ZINMANGA", "en")
|
||||
internal class Zinmanga(context: MangaLoaderContext) : MadaraParser(context, MangaSource.ZINMANGA, "zinmanga.com")
|
||||
{
|
||||
override val datePattern = "MM/dd/yyyy"
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.es
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("AIYUMANGASCANLATION", "AiyuMangaScanlation", "es")
|
||||
internal class AiyuMangaScanlation(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.AIYUMANGASCANLATION, "aiyumangascanlation.com") {
|
||||
|
||||
override val tagPrefix = "manga-genre/"
|
||||
override val datePattern = "MM/dd/yyyy"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.fr
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("ASTRALMANGA", "AstralManga", "fr")
|
||||
internal class AstralManga(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.ASTRALMANGA, "astral-manga.fr", pageSize = 12) {
|
||||
|
||||
override val datePattern = "dd/MM/yyyy"
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.fr
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
import java.util.Locale
|
||||
|
||||
@MangaSourceParser("FRSCAN", "FrScan", "fr")
|
||||
internal class FrScan(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.FRSCAN, "fr-scan.com") {
|
||||
|
||||
override val datePattern = "MMMM d, yyyy"
|
||||
override val sourceLocale: Locale = Locale.FRENCH
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.fr
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
|
||||
@MangaSourceParser("HENTAIZONE", "Hentaizone", "fr")
|
||||
internal class Hentaizone(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.HENTAIZONE, "hentaizone.xyz", pageSize = 10) {
|
||||
|
||||
override val datePattern = "MMM d, yyyy"
|
||||
override val sourceLocale: Locale = Locale.FRENCH
|
||||
|
||||
override val isNsfwSource = true
|
||||
|
||||
|
||||
override suspend fun loadChapters(mangaUrl: String): List<MangaChapter> {
|
||||
val url = mangaUrl.toAbsoluteUrl(domain).removeSuffix('/') + "/ajax/chapters/"
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
val doc = webClient.httpPost(url, emptyMap()).parseHtml()
|
||||
|
||||
return doc.select("li.wp-manga-chapter").mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirstOrThrow("a")
|
||||
val href = a.attrAsRelativeUrl("href") + "?style=list"
|
||||
|
||||
// correct parse date missing a "."
|
||||
val date_org = li.selectFirst("span.chapter-release-date i")?.text() ?: "janv 1, 2000"
|
||||
val date_corect_parse = date_org
|
||||
.replace("janv", "janv.")
|
||||
.replace("févr", "févr.")
|
||||
.replace("avr", "avr.")
|
||||
.replace("juil", "juil.")
|
||||
.replace("sept", "sept.")
|
||||
.replace("nov", "nov.")
|
||||
.replace("oct", "oct.")
|
||||
.replace("déc", "déc.")
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
name = a.text(),
|
||||
number = i + 1,
|
||||
branch = null,
|
||||
uploadDate = parseChapterDate(
|
||||
dateFormat,
|
||||
date_corect_parse,
|
||||
),
|
||||
scanlator = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.fr
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.insertCookies
|
||||
import java.util.Locale
|
||||
|
||||
|
||||
@MangaSourceParser("HHENTAIFR", "HhentaiFr", "fr")
|
||||
internal class HhentaiFr(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.HHENTAIFR, "hhentai.fr") {
|
||||
|
||||
override val datePattern = "MMMM d, yyyy"
|
||||
override val sourceLocale: Locale = Locale.FRENCH
|
||||
|
||||
override val isNsfwSource = true
|
||||
|
||||
init {
|
||||
context.cookieJar.insertCookies(
|
||||
domain,
|
||||
"age_gate=32;",
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.fr
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
import java.util.Locale
|
||||
|
||||
@MangaSourceParser("MANGA_SCANTRAD", "Manga Scantrad", "fr")
|
||||
internal class MangaScantrad(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGA_SCANTRAD, "manga-scantrad.io") {
|
||||
|
||||
override val datePattern = "d MMMM yyyy"
|
||||
override val sourceLocale: Locale = Locale.FRENCH
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.fr
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("REAPERSCANS_FR", "ReaperScansFr", "fr")
|
||||
internal class ReaperScansFr(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.REAPERSCANS_FR, "reaperscans.fr") {
|
||||
|
||||
override val datePattern = "MM/dd/yyyy"
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.fr
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("SCANTRADVF", "ScantradVf", "fr")
|
||||
internal class ScantradVf(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.SCANTRADVF, "scantrad-vf.co") {
|
||||
|
||||
override val datePattern = "d MMMM yyyy"
|
||||
|
||||
override val tagPrefix = "genre/"
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.id
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
import java.util.Locale
|
||||
|
||||
@MangaSourceParser("REAPER_SCANS_ID", "ReaperScansID", "id")
|
||||
internal class ReaperScansParser(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.REAPER_SCANS_ID, "reaperscans.id") {
|
||||
|
||||
override val datePattern = "MMMM dd, yyyy"
|
||||
override val tagPrefix = "genre/"
|
||||
override val sourceLocale: Locale = Locale.ENGLISH
|
||||
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.en
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("HACHIMANGA", "HachiManga", "ja")
|
||||
internal class HachiManga(context: MangaLoaderContext) : MadaraParser(context, MangaSource.HACHIMANGA, "hachiraw.com")
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
|
||||
@MangaSourceParser("ATLANTISSCAN", "Atlantisscan", "pt")
|
||||
internal class Atlantisscan(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.ATLANTISSCAN, "atlantisscan.com") {
|
||||
|
||||
override val datePattern = "dd/MM/yyyy"
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("HENTAITECA", "Hentaiteca", "pt")
|
||||
internal class Hentaiteca(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.HENTAITECA, "hentaiteca.net", pageSize = 10) {
|
||||
|
||||
override val datePattern = "MM/dd/yyyy"
|
||||
|
||||
override val tagPrefix = "genero/"
|
||||
|
||||
override val isNsfwSource = true
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
|
||||
@MangaSourceParser("HIPERCOOL", "Hipercool", "pt")
|
||||
internal class Hipercool(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.HIPERCOOL, "hipercool.xyz", pageSize = 20) {
|
||||
|
||||
override val datePattern = "MMMM d, yyyy"
|
||||
|
||||
override val tagPrefix = "manga-tag/"
|
||||
|
||||
override val isNsfwSource = true
|
||||
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("PRISMA_SCANS", "Prisma Scans", "pt")
|
||||
internal class PrismaScansParser(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.PRISMA_SCANS, "prismascans.net", 10) {
|
||||
|
||||
override val tagPrefix = "manga-genre/"
|
||||
override val datePattern = "MMM dd, yyyy"
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("TATAKAE_SCANS", "Tatakae Scans", "pt")
|
||||
internal class TatakaeScansParser(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.TATAKAE_SCANS, "tatakaescan.com", pageSize = 10) {
|
||||
|
||||
override val datePattern: String = "dd 'de' MMMMM 'de' yyyy"
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("BAKAMAN", "BakaMan", "th")
|
||||
internal class BakaMan(context: MangaLoaderContext) : MadaraParser( context, MangaSource.BAKAMAN, "bakaman.net", pageSize = 18,) {
|
||||
|
||||
override val isNsfwSource = false
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package org.koitharu.kotatsu.parsers.site.madara.pt
|
||||
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("CAT_300", "Cat300", "th")
|
||||
internal class Cat300(context: MangaLoaderContext) : MadaraParser(context, MangaSource.CAT_300, "cat300.com") {
|
||||
|
||||
override val isNsfwSource = true
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
|
||||
|
||||
internal abstract class MangaReaderParser(
|
||||
context: MangaLoaderContext,
|
||||
source: MangaSource,
|
||||
@@ -24,13 +25,9 @@ internal abstract class MangaReaderParser(
|
||||
override val sortOrders: Set<SortOrder>
|
||||
get() = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.ALPHABETICAL, SortOrder.NEWEST)
|
||||
|
||||
protected val idLocale
|
||||
get() = Locale("in", "ID")
|
||||
|
||||
abstract val listUrl: String
|
||||
abstract val tableMode: Boolean
|
||||
protected open val listUrl = "/manga"
|
||||
protected open val isNsfwSource = false
|
||||
open val chapterDateFormat = SimpleDateFormat("MMM d, yyyy", idLocale)
|
||||
open val chapterDateFormat = SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH)
|
||||
|
||||
private var tagCache: ArrayMap<String, MangaTag>? = null
|
||||
private val mutex = Mutex()
|
||||
@@ -51,128 +48,87 @@ internal abstract class MangaReaderParser(
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
return if (tableMode) parseInfoTable(docs, manga, chapters) else parseInfoList(docs, manga, chapters)
|
||||
return parseInfo(docs, manga, chapters)
|
||||
}
|
||||
|
||||
open suspend fun parseInfoTable(docs: Document, manga: Manga, chapters: List<MangaChapter>): Manga {
|
||||
val mangaInfo =
|
||||
open suspend fun parseInfo(docs: Document, manga: Manga, chapters: List<MangaChapter>): Manga {
|
||||
|
||||
/// set if is table
|
||||
val tablemode =
|
||||
docs.selectFirst("div.seriestucontent > div.seriestucontentr") ?: docs.selectFirst("div.seriestucontentr")
|
||||
?: docs.selectFirst("div.seriestucon")
|
||||
|
||||
val state_select =
|
||||
docs.selectFirst(".tsinfo div:contains(Status)") ?: docs.selectFirst(".tsinfo div:contains(Statut)")
|
||||
?: docs.selectFirst(".tsinfo div:contains(حالة العمل)") ?: docs.selectFirst(".tsinfo div:contains(Estado)")
|
||||
?: docs.selectFirst(".tsinfo div:contains(สถานะ)") ?: docs.selectFirst(".tsinfo div:contains(Stato )")
|
||||
?: docs.selectFirst(".tsinfo div:contains(Durum)")
|
||||
|
||||
val mangaState = state_select?.lastElementChild()?.let {
|
||||
when (it.text()) {
|
||||
"مستمرةا",
|
||||
"En curso",
|
||||
"Ongoing",
|
||||
"On going",
|
||||
"Ativo",
|
||||
"En Cours",
|
||||
"OnGoing",
|
||||
"Đang tiến hành",
|
||||
"em lançamento",
|
||||
"Онгоінг",
|
||||
"Publishing",
|
||||
"Devam Ediyor",
|
||||
"Em Andamento",
|
||||
"In Corso",
|
||||
-> MangaState.ONGOING
|
||||
|
||||
"Completed",
|
||||
"Completo",
|
||||
"Complété",
|
||||
"Fini",
|
||||
"Terminé",
|
||||
"Tamamlandı",
|
||||
"Đã hoàn thành",
|
||||
"مكتملة",
|
||||
"Завершено",
|
||||
"Finished",
|
||||
"Finalizado",
|
||||
"Completata",
|
||||
-> MangaState.FINISHED
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
val tagMap = getOrCreateTagMap()
|
||||
val tags = mangaInfo?.select(".seriestugenre > a")?.mapNotNullToSet { tagMap[it.text()] }
|
||||
|
||||
return manga.copy(
|
||||
description = mangaInfo?.selectFirst("div.entry-content")?.html(),
|
||||
state = mangaState,
|
||||
author = mangaInfo?.selectFirst(".infotable td:contains(Author)")?.lastElementSibling()?.text(),
|
||||
isNsfw = manga.isNsfw || docs.selectFirst(".restrictcontainer") != null,
|
||||
tags = tags.orEmpty(),
|
||||
chapters = chapters,
|
||||
)
|
||||
}
|
||||
val selecttag = if(tablemode != null)
|
||||
{
|
||||
tablemode.select(".seriestugenre > a")
|
||||
}else
|
||||
{
|
||||
docs.select(".wd-full .mgen > a")
|
||||
}
|
||||
|
||||
open suspend fun parseInfoList(docs: Document, manga: Manga, chapters: List<MangaChapter>): Manga {
|
||||
val tags = selecttag.mapNotNullToSet { tagMap[it.text()] }
|
||||
|
||||
val state_select =
|
||||
|
||||
val stateselect = if(tablemode != null)
|
||||
{
|
||||
tablemode.selectFirst(".infotable td:contains(Status)") ?: tablemode.selectFirst(".infotable td:contains(Statut)")
|
||||
?: tablemode.selectFirst(".infotable td:contains(حالة العمل)") ?: tablemode.selectFirst(".infotable td:contains(Estado)")
|
||||
?: docs.selectFirst(".infotable td:contains(สถานะ)") ?: tablemode.selectFirst(".infotable td:contains(Stato )")
|
||||
?: tablemode.selectFirst(".infotable td:contains(Durum)") ?: tablemode.selectFirst(".infotable td:contains(Statüsü)")
|
||||
|
||||
}else
|
||||
{
|
||||
docs.selectFirst(".tsinfo div:contains(Status)") ?: docs.selectFirst(".tsinfo div:contains(Statut)")
|
||||
?: docs.selectFirst(".tsinfo div:contains(حالة العمل)") ?: docs.selectFirst(".tsinfo div:contains(Estado)")
|
||||
?: docs.selectFirst(".tsinfo div:contains(สถานะ)") ?: docs.selectFirst(".tsinfo div:contains(Stato )")
|
||||
?: docs.selectFirst(".tsinfo div:contains(Durum)")
|
||||
?: docs.selectFirst(".tsinfo div:contains(Durum)") ?: docs.selectFirst(".tsinfo div:contains(Statüsü)")
|
||||
}
|
||||
|
||||
val mangaState = state_select?.lastElementChild()?.let {
|
||||
val state = if(tablemode != null)
|
||||
{
|
||||
stateselect?.lastElementSibling()
|
||||
|
||||
}else
|
||||
{
|
||||
stateselect?.lastElementChild()
|
||||
}
|
||||
|
||||
|
||||
val mangaState = state?.let {
|
||||
when (it.text()) {
|
||||
"مستمرةا",
|
||||
"En curso",
|
||||
"Ongoing",
|
||||
"On going",
|
||||
"Ativo",
|
||||
"En Cours",
|
||||
"OnGoing",
|
||||
"Đang tiến hành",
|
||||
"em lançamento",
|
||||
"Онгоінг",
|
||||
"Publishing",
|
||||
"Devam Ediyor",
|
||||
"Em Andamento",
|
||||
"In Corso",
|
||||
"مستمرة", "En curso", "Ongoing", "On going",
|
||||
"Ativo", "En Cours", "OnGoing", "Đang tiến hành", "em lançamento", "Онгоінг", "Publishing",
|
||||
"Devam Ediyor", "Em Andamento", "In Corso", "Güncel", "Berjalan", "Продолжается", "Updating",
|
||||
"Lançando", "In Arrivo", "Emision", "En emision", "مستمر", "Curso", "En marcha", "Publicandose", "连载中",
|
||||
-> MangaState.ONGOING
|
||||
|
||||
"Completed",
|
||||
"Completo",
|
||||
"Complété",
|
||||
"Fini",
|
||||
"Terminé",
|
||||
"Tamamlandı",
|
||||
"Đã hoàn thành",
|
||||
"مكتملة",
|
||||
"Завершено",
|
||||
"Finished",
|
||||
"Finalizado",
|
||||
"Completata",
|
||||
"Completed", "Completo", "Complété", "Fini", "Terminé", "Tamamlandı", "Đã hoàn thành", "مكتملة", "Завершено",
|
||||
"Finished", "Finalizado", "Completata", "One-Shot", "Bitti", "Tamat", "Completado", "Concluído", "Concluido", "已完结",
|
||||
-> MangaState.FINISHED
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
val tags = docs.select(".wd-full .mgen > a").mapNotNullToSet { getOrCreateTagMap()[it.text()] }
|
||||
|
||||
|
||||
val author = tablemode?.selectFirst(".infotable td:contains(Author)")?.lastElementSibling()?.text()?:
|
||||
docs.selectFirst(".tsinfo div:contains(Author)")?.lastElementChild()?.text() ?:
|
||||
docs.selectFirst(".tsinfo div:contains(Auteur)")?.lastElementChild()?.text() ?:
|
||||
docs.selectFirst(".tsinfo div:contains(Artist)")?.lastElementChild()?.text() ?:
|
||||
docs.selectFirst(".tsinfo div:contains(Durum)")?.lastElementChild()?.text()
|
||||
|
||||
val nsfw = docs.selectFirst(".restrictcontainer") != null
|
||||
|| docs.selectFirst(".info-right .alr") != null
|
||||
|| docs.selectFirst(".postbody .alr") != null
|
||||
|
||||
return manga.copy(
|
||||
description =
|
||||
description = tablemode?.selectFirst("div.entry-content")?.html() ?:
|
||||
docs.selectFirst("div.entry-content")?.html(),
|
||||
|
||||
state = mangaState,
|
||||
author =
|
||||
docs.selectFirst(".tsinfo div:contains(Author)")?.lastElementChild()?.text()
|
||||
?: docs.selectFirst(".tsinfo div:contains(Auteur)")?.lastElementChild()?.text()
|
||||
?: docs.selectFirst(".tsinfo div:contains(Artist)")?.lastElementChild()?.text()
|
||||
?: docs.selectFirst(".tsinfo div:contains(Durum)")?.lastElementChild()?.text(),
|
||||
|
||||
isNsfw = manga.isNsfw
|
||||
|| docs.selectFirst(".info-right .alr") != null
|
||||
|| docs.selectFirst(".postbody .alr") != null,
|
||||
author = author,
|
||||
isNsfw = manga.isNsfw || nsfw,
|
||||
tags = tags,
|
||||
chapters = chapters,
|
||||
)
|
||||
@@ -257,25 +213,45 @@ internal abstract class MangaReaderParser(
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val chapterUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val docs = webClient.httpGet(chapterUrl).parseHtml()
|
||||
val script = docs.selectFirstOrThrow("script:containsData(ts_reader)")
|
||||
val images = JSONObject(script.data().substringAfter('(').substringBeforeLast(')'))
|
||||
.getJSONArray("sources")
|
||||
.getJSONObject(0)
|
||||
.getJSONArray("images")
|
||||
|
||||
val pages = ArrayList<MangaPage>(images.length())
|
||||
for (i in 0 until images.length()) {
|
||||
pages.add(
|
||||
val test = docs.select("script:containsData(ts_reader)")
|
||||
if(test.isNullOrEmpty())
|
||||
{
|
||||
return docs.select("div#readerarea img").map { img ->
|
||||
val url = img.imageUrl()
|
||||
MangaPage(
|
||||
id = generateUid(images.getString(i)),
|
||||
url = images.getString(i),
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
preview = null,
|
||||
source = source,
|
||||
),
|
||||
)
|
||||
)
|
||||
}
|
||||
}else
|
||||
{
|
||||
val script = docs.selectFirstOrThrow("script:containsData(ts_reader)")
|
||||
val images = JSONObject(script.data().substringAfter('(').substringBeforeLast(')'))
|
||||
.getJSONArray("sources")
|
||||
.getJSONObject(0)
|
||||
.getJSONArray("images")
|
||||
val pages = ArrayList<MangaPage>(images.length())
|
||||
for (i in 0 until images.length()) {
|
||||
pages.add(
|
||||
MangaPage(
|
||||
id = generateUid(images.getString(i)),
|
||||
url = images.getString(i),
|
||||
preview = null,
|
||||
source = source,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
return pages
|
||||
|
||||
}
|
||||
|
||||
return pages
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
override suspend fun getTags(): Set<MangaTag> {
|
||||
|
||||
@@ -14,8 +14,5 @@ internal class Ozulscans(context: MangaLoaderContext) :
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("ozulscans.com")
|
||||
|
||||
override val listUrl: String get() = "/manga"
|
||||
override val tableMode: Boolean get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("yyyy,d MMM", Locale("ar", "AR"))
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMMM d, yyyy", Locale("ar", "AR"))
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("ANIGLISCANS", "Anigli Scans", "en")
|
||||
internal class AnigliScans(context: MangaLoaderContext) :
|
||||
@@ -16,8 +14,5 @@ internal class AnigliScans(context: MangaLoaderContext) :
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/series"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH)
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("ARENASCANS", "Arena Scans", "en")
|
||||
internal class ArenaScans(context: MangaLoaderContext) :
|
||||
@@ -14,10 +12,4 @@ internal class ArenaScans(context: MangaLoaderContext) :
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("arenascans.net")
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/manga"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH)
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("ASURASCANS", "Asura Scans", "en")
|
||||
internal class AsuraScansParser(context: MangaLoaderContext) :
|
||||
@@ -14,11 +12,5 @@ internal class AsuraScansParser(context: MangaLoaderContext) :
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("asurascans.com")
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/manga"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH)
|
||||
|
||||
}
|
||||
|
||||
@@ -5,8 +5,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
|
||||
@MangaSourceParser("AZUREMANGA", "Azure Manga", "en")
|
||||
internal class AzureManga(context: MangaLoaderContext) :
|
||||
@@ -14,10 +13,4 @@ internal class AzureManga(context: MangaLoaderContext) :
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("azuremanga.com")
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/manga"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH)
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("COSMICSCANS", "CosmicScans", "en")
|
||||
internal class CosmicScansParser(context: MangaLoaderContext) :
|
||||
@@ -14,10 +12,4 @@ internal class CosmicScansParser(context: MangaLoaderContext) :
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("cosmicscans.com")
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/manga"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import java.util.Locale
|
||||
|
||||
@MangaSourceParser("ELARCPAGE", "Elarcpage", "en")
|
||||
internal class Elarcpage(context: MangaLoaderContext) :
|
||||
@@ -16,8 +16,7 @@ internal class Elarcpage(context: MangaLoaderContext) :
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/series"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH)
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("FLAMESCANS", "Flame Scans", "en")
|
||||
internal class FlameScans(context: MangaLoaderContext) :
|
||||
@@ -16,8 +14,4 @@ internal class FlameScans(context: MangaLoaderContext) :
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/series"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH)
|
||||
}
|
||||
|
||||
@@ -5,8 +5,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
|
||||
@MangaSourceParser("KUMASCANS", "Kuma Scans", "en")
|
||||
internal class KumaScans(context: MangaLoaderContext) :
|
||||
@@ -14,10 +13,4 @@ internal class KumaScans(context: MangaLoaderContext) :
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("kumascans.com")
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/manga"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH)
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("MANHWALOVER", "ManhwaLover", "en")
|
||||
internal class ManhwaLover(context: MangaLoaderContext) :
|
||||
@@ -14,12 +12,6 @@ internal class ManhwaLover(context: MangaLoaderContext) :
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("manhwalover.com")
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/manga"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
override val isNsfwSource: Boolean = true
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH)
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("MANHWAX", "Manhwax", "en")
|
||||
internal class Manhwax(context: MangaLoaderContext) :
|
||||
@@ -14,12 +12,5 @@ internal class Manhwax(context: MangaLoaderContext) :
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("manhwax.org")
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/manga"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
override val isNsfwSource: Boolean = true
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH)
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("NIGHTSCANS", "Nightscans", "en")
|
||||
internal class Nightscans(context: MangaLoaderContext) :
|
||||
@@ -14,10 +12,4 @@ internal class Nightscans(context: MangaLoaderContext) :
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("nightscans.org")
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/manga"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH)
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("PHANTOMSCANS", "Phantomscans", "en")
|
||||
internal class Phantomscans(context: MangaLoaderContext) :
|
||||
@@ -14,10 +12,4 @@ internal class Phantomscans(context: MangaLoaderContext) :
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("phantomscans.com")
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/manga"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH)
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("RAVENSCANS", "Ravenscans", "en")
|
||||
internal class Ravenscans(context: MangaLoaderContext) :
|
||||
@@ -14,10 +12,4 @@ internal class Ravenscans(context: MangaLoaderContext) :
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("ravenscans.com")
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/manga"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH)
|
||||
}
|
||||
|
||||
@@ -5,8 +5,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
|
||||
@MangaSourceParser("READKOMIK", "Readkomik", "en")
|
||||
internal class Readkomik(context: MangaLoaderContext) :
|
||||
@@ -14,11 +13,5 @@ internal class Readkomik(context: MangaLoaderContext) :
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("readkomik.com")
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/manga"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.koitharu.kotatsu.parsers.site.mangareader.en
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
|
||||
@MangaSourceParser("SKY_MANGA", "Sky Manga", "en")
|
||||
internal class SkyManga(context: MangaLoaderContext) :
|
||||
MangaReaderParser(context, MangaSource.SKY_MANGA, pageSize = 20, searchPageSize = 20) {
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("skymanga.work")
|
||||
|
||||
override val listUrl = "/manga-list"
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("DD-MM-yyy", Locale.ENGLISH)
|
||||
}
|
||||
@@ -5,8 +5,6 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("SURYASCANS", "Suryascans", "en")
|
||||
internal class Suryascans(context: MangaLoaderContext) :
|
||||
@@ -14,10 +12,4 @@ internal class Suryascans(context: MangaLoaderContext) :
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("suryascans.com")
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/manga"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH)
|
||||
}
|
||||
|
||||
@@ -5,19 +5,10 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("VOIDSCANS", "Void Scans", "en")
|
||||
internal class VoidScans(context: MangaLoaderContext) :
|
||||
MangaReaderParser(context, MangaSource.VOIDSCANS, pageSize = 150, searchPageSize = 150) {
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("void-scans.com")
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/manga"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH)
|
||||
}
|
||||
|
||||
@@ -16,8 +16,6 @@ internal class CartelDeManhwas(context: MangaLoaderContext) :
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/series"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale("es", "ES"))
|
||||
}
|
||||
|
||||
@@ -14,9 +14,6 @@ internal class DragonTranslationParser(context: MangaLoaderContext) :
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("dragontranslation.com")
|
||||
|
||||
override val listUrl: String get() = "/manga"
|
||||
override val tableMode: Boolean get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH)
|
||||
|
||||
}
|
||||
|
||||
@@ -14,10 +14,6 @@ internal class GREMORYMANGAS(context: MangaLoaderContext) :
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("gremorymangas.com")
|
||||
|
||||
override val listUrl: String get() = "/manga"
|
||||
|
||||
override val tableMode: Boolean
|
||||
get() = true
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMMM d, yyyy", Locale("es", "ES"))
|
||||
}
|
||||
|
||||
@@ -14,8 +14,6 @@ internal class MiauScan(context: MangaLoaderContext) :
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("miauscan.com")
|
||||
|
||||
override val listUrl: String get() = "/manga"
|
||||
override val tableMode: Boolean get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMMM d, yyyy", Locale("es", "ES"))
|
||||
|
||||
|
||||
@@ -14,10 +14,5 @@ internal class Raikiscan(context: MangaLoaderContext) :
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("raikiscan.com")
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/manga"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale("es", "ES"))
|
||||
}
|
||||
|
||||
@@ -14,10 +14,6 @@ internal class Senpaiediciones(context: MangaLoaderContext) :
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("senpaiediciones.com")
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/manga"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale("es", "ES"))
|
||||
}
|
||||
|
||||
@@ -14,10 +14,6 @@ internal class Shadowmangas(context: MangaLoaderContext) :
|
||||
override val configKeyDomain: ConfigKey.Domain
|
||||
get() = ConfigKey.Domain("shadowmangas.com")
|
||||
|
||||
override val listUrl: String
|
||||
get() = "/manga"
|
||||
override val tableMode: Boolean
|
||||
get() = false
|
||||
|
||||
override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale("es", "ES"))
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user