diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/JapScanParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/JapScanParser.kt index 98a590d07..f9bb0a91e 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/JapScanParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/JapScanParser.kt @@ -49,7 +49,7 @@ internal class JapScanParser(context: MangaLoaderContext) : PagedMangaParser(con override val configKeyDomain = ConfigKey.Domain("www.japscan.lol", "japscan.ws") override val headers: Headers = Headers.Builder() - .add("User-Agent", UserAgents.CHROME_DESKTOP) + .add("User-Agent", UserAgents.CHROME_MOBILE) .build() override suspend fun getListPage( @@ -68,21 +68,19 @@ internal class JapScanParser(context: MangaLoaderContext) : PagedMangaParser(con .build() val root = webClient.httpGet(url).parseHtml() .requireElementById("main") - .selectFirstOrThrow(".flex-wrap") - return root.select(".mainTitle") - .map { p -> - val div = checkNotNull(p.parent()) - val a = div.selectFirstOrThrow("a") - val href = a.attrAsRelativeUrl("href") + .selectFirstOrThrow(".p-2.row.d-flex") + return root.select("div.col-4") + .map { div -> + val href = div.selectFirstOrThrow("a").attrAsRelativeUrl("href") Manga( id = generateUid(href), - title = p.text(), + title = div.selectFirstOrThrow("p.p-1 a").text(), altTitle = null, url = href, publicUrl = href.toAbsoluteUrl(domain), rating = RATING_UNKNOWN, isNsfw = false, - coverUrl = div.selectFirstOrThrow("img").attrAsAbsoluteUrl("src"), + coverUrl = div.selectFirstOrThrow("img.img-fluid").attrAsAbsoluteUrl("src"), tags = setOf(), state = null, author = null, @@ -128,6 +126,27 @@ internal class JapScanParser(context: MangaLoaderContext) : PagedMangaParser(con ) } + private fun extractQuotedContent(input: String): List { + val regex = Regex("'(.*?)'") + return regex.findAll(input).map { it.groupValues[1] }.toList() + } + + private fun listJSToKey(jsList: MutableList, offsettab: Int, listKey: List): MutableList { + for (i in 0 until jsList.size) { + if (jsList[i].contains("0x")) { + var decoupeHexa = jsList[i].split("('")[1] + decoupeHexa = decoupeHexa.split("')")[0] + var indexkey = Integer.decode(decoupeHexa) - offsettab - 1 + if (indexkey < 0) { + indexkey = listKey.size - 1 + } + jsList[i] = listKey[indexkey] + } + } + + return jsList + } + override suspend fun getPages(chapter: MangaChapter): List { val chapterUrl = chapter.url.toAbsoluteUrl(domain) val doc = webClient.httpGet(chapterUrl).parseHtml() @@ -137,20 +156,67 @@ internal class JapScanParser(context: MangaLoaderContext) : PagedMangaParser(con val embeddedData = doc.requireElementById("data").attr("data-data") val script = webClient.httpGet(scriptUrl).parseRaw() - val shortkeyRegex = Regex("""'([\dA-Z]{2})'""", RegexOption.IGNORE_CASE) - val longkeyRegex = Regex("""'([\dA-Z]{20})'""", RegexOption.IGNORE_CASE) + var tabKey = "'" + script.split("=['")[1] + tabKey = tabKey.split("];")[0] + val listKey = tabKey.split("','").toMutableList() + + var decoupeOffset = script.split("-0x")[1] + decoupeOffset = "0x" + decoupeOffset.split(";")[0] + + val offsettab = Integer.decode(decoupeOffset) + + var decoupeFuncOrder = script.split("while(!![])")[1] + decoupeFuncOrder = decoupeFuncOrder.split("if")[0] + + val listKeyOrder = extractQuotedContent(decoupeFuncOrder).toMutableList() + + if (listKeyOrder.size < 3) { + throw Exception("L'ordre des clés n'a pas pu être déterminé") + } + var goodorder = false + for (i in 0 until listKey.size) { + for (z in 0 until listKeyOrder.size) { + if (listKey[Integer.decode(listKeyOrder[z]) - offsettab - 1].contains("[0-9]".toRegex())) { + goodorder = true + } else { + goodorder = false + break + } + } + + if (goodorder) { + break + } + + val firstElement = listKey.removeAt(0) + listKey.add(firstElement) + } + + if (!goodorder) { + throw Exception("L'ordre des clés n'a pas pu être déterminé") + } + + val zjscalc = script.split("/[A-Z0-9]/gi,")[1] + + val calc1 = zjscalc.split(",")[0] + var calc1tab = calc1.split("+").toMutableList() + calc1tab = listJSToKey(calc1tab, offsettab, listKey) + + val calc2 = zjscalc.split(",")[1] + var calc2tab = calc2.split("+").toMutableList() + calc2tab = listJSToKey(calc2tab, offsettab, listKey) - val longTables = longkeyRegex.findAll(script).map { - it.groupValues[1] - }.toList() + var key1 = calc1tab.joinToString("") + var key2 = calc2tab.joinToString("") - val shortTables = shortkeyRegex.findAll(script).map { - it.groupValues[1] - }.toList() + key1 = key1.replace("'", "") + key2 = key2.replace("'", "") + key1 = key1.replace(" ", "") + key2 = key2.replace(" ", "") val keyTables = listOf( - shortTables[1].reversed() + longTables[1].reversed() + longTables[4].reversed() + longTables[0].reversed(), - shortTables[2].reversed() + longTables[3].reversed() + longTables[5].reversed() + longTables[2].reversed(), + key1.reversed(), + key2.reversed(), ) var error: Exception? = null diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MadaraParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MadaraParser.kt index 774661fa3..1df46ad59 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MadaraParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/MadaraParser.kt @@ -264,13 +264,14 @@ internal abstract class MadaraParser( protected open val selectgenre = "div.genres-content a" protected open val selectdate = "span.chapter-release-date i" protected open val selectchapter = "li.wp-manga-chapter" + protected open val selectTestAsync = "div.listing-chapters_wrap" override suspend fun getDetails(manga: Manga): Manga = coroutineScope { val fullUrl = manga.url.toAbsoluteUrl(domain) val doc = webClient.httpGet(fullUrl).parseHtml() val body = doc.body() - val testchekasync = body.select("div.listing-chapters_wrap") + val testchekasync = body.select(selectTestAsync) val chaptersDeferred = if (testchekasync.isNullOrEmpty()) { async { loadChapters(manga.url, doc) } @@ -329,10 +330,10 @@ internal abstract class MadaraParser( ) } + protected open suspend fun getChapters(manga: Manga, doc: Document): List { - val root2 = doc.body().selectFirstOrThrow("div.content-area") val dateFormat = SimpleDateFormat(datePattern, sourceLocale) - return root2.select(selectchapter).mapChapters(reversed = true) { i, li -> + return doc.body().select(selectchapter).mapChapters(reversed = true) { i, li -> val a = li.selectFirst("a") val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing") val link = href + stylepage @@ -389,6 +390,8 @@ internal abstract class MadaraParser( } } + protected open val selectPage = "div.page-break" + override suspend fun getPages(chapter: MangaChapter): List { val fullUrl = chapter.url.toAbsoluteUrl(domain) val doc = webClient.httpGet(fullUrl).parseHtml() @@ -396,7 +399,7 @@ internal abstract class MadaraParser( val chapterProtector = doc.getElementById("chapter-protector-data") if (chapterProtector == null) { val root = doc.body().selectFirstOrThrow("div.main-col-inner").selectFirstOrThrow("div.reading-content") - return root.select("div.page-break").map { div -> + return root.select(selectPage).map { div -> val img = div.selectFirstOrThrow("img") val url = img.src()?.toRelativeUrl(domain) ?: div.parseFailed("Image src not found") MangaPage( @@ -436,30 +439,31 @@ internal abstract class MadaraParser( val d = date?.lowercase() ?: return 0 return when { d.endsWith(" ago") || d.endsWith(" atrás") || // Handle translated 'ago' in Portuguese. - d.startsWith("há ") || // other translated 'ago' in Portuguese. - d.endsWith(" hace") || // other translated 'ago' in Spanish - d.endsWith(" önce") || // Handle translated 'ago' in Turkish. - d.endsWith(" trước") || // Handle translated 'ago' in Viêt Nam. - d.startsWith("il y a") || // Handle translated 'ago' in French. - //If there is no ago but just a motion of time - // short Hours - d.endsWith(" h") || - // short Day - d.endsWith(" d") || - // Day in Portuguese - d.endsWith(" días") || d.endsWith(" día") || - // Day in French - d.endsWith(" jour") || d.endsWith(" jours") || - // Hours in Portuguese - d.endsWith(" horas") || d.endsWith(" hora") || - // Hours in french - d.endsWith(" heure") || d.endsWith(" heures") || - // Minutes in English - d.endsWith(" mins") || - // Minutes in Portuguese - d.endsWith(" minutos") || d.endsWith(" minuto") || - //Minutes in French - d.endsWith(" minute") || d.endsWith(" minutes") -> parseRelativeDate(date) + d.startsWith("há ") || // other translated 'ago' in Portuguese. + d.endsWith(" hace") || // other translated 'ago' in Spanish + d.endsWith(" назад") || // other translated 'ago' in Russian + d.endsWith(" önce") || // Handle translated 'ago' in Turkish. + d.endsWith(" trước") || // Handle translated 'ago' in Viêt Nam. + d.startsWith("il y a") || // Handle translated 'ago' in French. + //If there is no ago but just a motion of time + // short Hours + d.endsWith(" h") || + // short Day + d.endsWith(" d") || + // Day in Portuguese + d.endsWith(" días") || d.endsWith(" día") || + // Day in French + d.endsWith(" jour") || d.endsWith(" jours") || + // Hours in Portuguese + d.endsWith(" horas") || d.endsWith(" hora") || + // Hours in french + d.endsWith(" heure") || d.endsWith(" heures") || + // Minutes in English + d.endsWith(" mins") || + // Minutes in Portuguese + d.endsWith(" minutos") || d.endsWith(" minuto") || + //Minutes in French + d.endsWith(" minute") || d.endsWith(" minutes") -> parseRelativeDate(date) // Handle 'yesterday' and 'today', using midnight d.startsWith("year") -> Calendar.getInstance().apply { @@ -505,6 +509,7 @@ internal abstract class MadaraParser( "day", "days", "d", + "день", ).anyWordIn(date) -> cal.apply { add(Calendar.DAY_OF_MONTH, -number) }.timeInMillis WordSet("jam", "saat", "heure", "hora", "horas", "hour", "hours", "h").anyWordIn(date) -> cal.apply { @@ -523,6 +528,7 @@ internal abstract class MadaraParser( "minuto", "mins", "phút", + "минут", ).anyWordIn(date) -> cal.apply { add( Calendar.MINUTE, @@ -554,10 +560,10 @@ internal abstract class MadaraParser( private fun createRequestTemplate() = ("action=madara_load_more&page=1&template=madara-core%2Fcontent%2Fcontent-search&vars%5Bs%5D=&vars%5B" + - "orderby%5D=meta_value_num&vars%5Bpaged%5D=1&vars%5Btemplate%5D=search&vars%5Bmeta_query" + - "%5D%5B0%5D%5Brelation%5D=AND&vars%5Bmeta_query%5D%5Brelation%5D=OR&vars%5Bpost_type" + - "%5D=wp-manga&vars%5Bpost_status%5D=publish&vars%5Bmeta_key%5D=_latest_update&vars%5Border" + - "%5D=desc&vars%5Bmanga_archives_item_layout%5D=default").split( + "orderby%5D=meta_value_num&vars%5Bpaged%5D=1&vars%5Btemplate%5D=search&vars%5Bmeta_query" + + "%5D%5B0%5D%5Brelation%5D=AND&vars%5Bmeta_query%5D%5Brelation%5D=OR&vars%5Bpost_type" + + "%5D=wp-manga&vars%5Bpost_status%5D=publish&vars%5Bmeta_key%5D=_latest_update&vars%5Border" + + "%5D=desc&vars%5Bmanga_archives_item_layout%5D=default").split( '&', ).map { val pos = it.indexOf('=') diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ar/FalconManga.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ar/FalconManga.kt new file mode 100644 index 000000000..adb4508cb --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ar/FalconManga.kt @@ -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("FALCONMANGA", "FalconManga", "ar") +internal class FalconManga(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.FALCONMANGA, "falconmanga.com") { + + override val datePattern = "d MMMM، yyyy" +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ar/KolManga.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ar/KolManga.kt new file mode 100644 index 000000000..69d87f6ba --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ar/KolManga.kt @@ -0,0 +1,11 @@ +package org.koitharu.kotatsu.parsers.site.madara.pt + + +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.site.madara.MadaraParser + +@MangaSourceParser("KOLMANGA", "KolManga", "ar") +internal class KolManga(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.KOLMANGA, "kolmanga.com") diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ar/MangaLeks.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ar/MangaLeks.kt new file mode 100644 index 000000000..167a6abd9 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ar/MangaLeks.kt @@ -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("MANGALEKS", "MangaLeks", "ar") +internal class MangaLeks(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.MANGALEKS, "mangaleks.com") { + + override val datePattern = "yyyy/MM/dd" + override val postreq = true +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/ArcaneScans.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/ArcaneScans.kt new file mode 100644 index 000000000..14f2b5c0f --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/ArcaneScans.kt @@ -0,0 +1,11 @@ +package org.koitharu.kotatsu.parsers.site.madara.en + + +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.site.madara.MadaraParser + +@MangaSourceParser("ARCANESCANS", "ArcaneScans", "en") +internal class ArcaneScans(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.ARCANESCANS, "arcanescans.com", 10) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Comiz.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Comiz.kt new file mode 100644 index 000000000..c9481c207 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Comiz.kt @@ -0,0 +1,14 @@ +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("COMIZ", "Comiz", "en") +internal class Comiz(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.COMIZ, "v2.comiz.net", 10) { + + override val isNsfwSource = true +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/DuckManga.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/DuckManga.kt new file mode 100644 index 000000000..1d358f94e --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/DuckManga.kt @@ -0,0 +1,14 @@ +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("DUCKMANGA", "DuckManga", "en") +internal class DuckManga(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.DUCKMANGA, "duckmanga.com", 20) { + + override val isNsfwSource = true +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Grabber.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Grabber.kt new file mode 100644 index 000000000..beb7dffd9 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Grabber.kt @@ -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("GRABBER", "Grabber", "en") +internal class Grabber(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.GRABBER, "grabber.zone", 20) { + + override val tagPrefix = "type/" + override val datePattern = "dd.MM.yyyy" +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Hentai3z.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Hentai3z.kt new file mode 100644 index 000000000..9fc1a5647 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Hentai3z.kt @@ -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("HENTAI3Z", "Hentai3z", "en") +internal class Hentai3z(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.HENTAI3Z, "hentai3z.xyz", pageSize = 20) { + + override val isNsfwSource = true + override val withoutAjax = true +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Hentaixdickgirl.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Hentaixdickgirl.kt new file mode 100644 index 000000000..f03054bfb --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Hentaixdickgirl.kt @@ -0,0 +1,49 @@ +package org.koitharu.kotatsu.parsers.site.madara.pt + + +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.site.madara.MadaraParser +import org.koitharu.kotatsu.parsers.util.attrAsRelativeUrlOrNull +import org.koitharu.kotatsu.parsers.util.generateUid +import org.koitharu.kotatsu.parsers.util.mapChapters +import org.koitharu.kotatsu.parsers.util.parseFailed +import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow +import java.text.SimpleDateFormat + +@MangaSourceParser("HENTAIXDICKGIRL", "Hentaixdickgirl", "en") +internal class Hentaixdickgirl(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.HENTAIXDICKGIRL, "hentaixdickgirl.com", 16) { + + override val isNsfwSource = true + override val postreq = true + + override suspend fun getChapters(manga: Manga, doc: Document): List { + val root2 = doc.body().selectFirstOrThrow("div.listing-chapters_wrap") + val dateFormat = SimpleDateFormat(datePattern, sourceLocale) + return root2.select(selectchapter).mapChapters(reversed = true) { i, li -> + val a = li.selectFirst("a") + val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing") + val link = href + stylepage + val dateText = li.selectFirst("a.c-new-tag")?.attr("title") ?: li.selectFirst(selectdate)?.text() + val name = a.selectFirst("p")?.text() ?: a.ownText() + MangaChapter( + id = generateUid(href), + name = name, + number = i + 1, + url = link, + uploadDate = parseChapterDate( + dateFormat, + dateText, + ), + source = source, + scanlator = null, + branch = null, + ) + } + } +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/JiManga.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/JiManga.kt new file mode 100644 index 000000000..c660f327b --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/JiManga.kt @@ -0,0 +1,11 @@ +package org.koitharu.kotatsu.parsers.site.madara.en + + +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.site.madara.MadaraParser + +@MangaSourceParser("JIMANGA", "JiManga", "en") +internal class JiManga(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.JIMANGA, "jimanga.com") diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/MangaDass.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/MangaDass.kt new file mode 100644 index 000000000..89ecb306e --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/MangaDass.kt @@ -0,0 +1,202 @@ +package org.koitharu.kotatsu.parsers.site.madara.en + + +import kotlinx.coroutines.async +import kotlinx.coroutines.coroutineScope +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.MangaPage +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.model.MangaState +import org.koitharu.kotatsu.parsers.model.MangaTag +import org.koitharu.kotatsu.parsers.model.SortOrder +import org.koitharu.kotatsu.parsers.site.madara.MadaraParser +import org.koitharu.kotatsu.parsers.util.* +import java.text.SimpleDateFormat + +@MangaSourceParser("MANGADASS", "MangaDass", "en") +internal class MangaDass(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.MANGADASS, "mangadass.com", 20) { + + override val isNsfwSource = true + override val datePattern = "dd MMM yyyy" + override val withoutAjax = true + override val selectchapter = "li.a-h" + override val selectdesc = "div.ss-manga" + + override suspend fun getListPage( + page: Int, + query: String?, + tags: Set?, + sortOrder: SortOrder, + ): List { + + val url = buildString { + append("https://") + append(domain) + val pages = page + 1 + + when { + !query.isNullOrEmpty() -> { + + append("/?s=") + append(query.urlEncoded()) + append("&page=") + append(pages.toString()) + } + + !tags.isNullOrEmpty() -> { + append("/$tagPrefix") + for (tag in tags) { + append(tag.key) + } + append("/") + append(pages.toString()) + append("?") + } + + else -> { + + append("/$listeurl") + append("/") + append(pages.toString()) + append("?") + } + } + append("orderby=") + when (sortOrder) { + SortOrder.POPULARITY -> append("views") + SortOrder.UPDATED -> append("latest") + SortOrder.NEWEST -> append("new-manga") + SortOrder.ALPHABETICAL -> append("alphabet") + else -> append("latest") + } + } + val doc = webClient.httpGet(url).parseHtml() + + + return doc.select("div.row.c-tabs-item__content").ifEmpty { + doc.select("div.page-item-detail") + }.map { div -> + val href = div.selectFirst("a")?.attrAsRelativeUrlOrNull("href") ?: div.parseFailed("Link not found") + val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".item-summary") + Manga( + id = generateUid(href), + url = href, + publicUrl = href.toAbsoluteUrl(div.host ?: domain), + coverUrl = div.selectFirst("img")?.src().orEmpty(), + title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4"))?.text().orEmpty(), + altTitle = null, + rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f, + tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a -> + MangaTag( + key = a.attr("href").removeSuffix('/').substringAfterLast('/'), + title = a.text().ifEmpty { return@mapNotNullToSet null }.toTitleCase(), + source = source, + ) + }.orEmpty(), + author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(), + state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText() + ?.lowercase()) { + in ongoing -> MangaState.ONGOING + in finished -> MangaState.FINISHED + else -> null + }, + source = source, + isNsfw = isNsfwSource, + ) + } + } + + override suspend fun getDetails(manga: Manga): Manga = coroutineScope { + val fullUrl = manga.url.toAbsoluteUrl(domain) + val doc = webClient.httpGet(fullUrl).parseHtml() + val body = doc.body() + + val chaptersDeferred = async { getChapters(manga, doc) } + + val desc = body.select(selectdesc).let { + if (it.select("p").text().isNotEmpty()) { + it.select("p").joinToString(separator = "\n\n") { p -> + p.text().replace("
", "\n") + } + } else { + it.text() + } + } + + val stateDiv = (body.selectFirst("div.post-content_item:contains(Status)"))?.selectLast("div.summary-content") + + val state = stateDiv?.let { + when (it.text()) { + in ongoing -> MangaState.ONGOING + in finished -> MangaState.FINISHED + else -> null + } + } + + val alt = + doc.body().select(".post-content_item:contains(Alt) .summary-content").firstOrNull()?.tableValue()?.text() + ?.trim() ?: doc.body().select(".post-content_item:contains(Nomes alternativos: ) .summary-content") + .firstOrNull()?.tableValue()?.text()?.trim() + + manga.copy( + tags = doc.body().select(selectgenre).mapNotNullToSet { a -> + MangaTag( + key = a.attr("href").removeSuffix("/").substringAfterLast('/'), + title = a.text().toTitleCase(), + source = source, + ) + }, + description = desc, + altTitle = alt, + state = state, + chapters = chaptersDeferred.await(), + ) + } + + override suspend fun getChapters(manga: Manga, doc: Document): List { + val root2 = doc.body().selectFirstOrThrow("div.panel-manga-chapter") + val dateFormat = SimpleDateFormat(datePattern, sourceLocale) + return root2.select(selectchapter).mapChapters(reversed = true) { i, li -> + val a = li.selectFirst("a") + val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing") + val link = href + stylepage + val dateText = li.selectFirst("a.c-new-tag")?.attr("title") ?: li.selectFirst(selectdate)?.text() + val name = a.selectFirst("p")?.text() ?: a.ownText() + MangaChapter( + id = generateUid(href), + name = name, + number = i + 1, + url = link, + uploadDate = parseChapterDate( + dateFormat, + dateText, + ), + source = source, + scanlator = null, + branch = null, + ) + } + } + + override suspend fun getPages(chapter: MangaChapter): List { + val fullUrl = chapter.url.toAbsoluteUrl(domain) + val doc = webClient.httpGet(fullUrl).parseHtml() + val root = doc.body().selectFirstOrThrow("div.read-manga").selectFirstOrThrow("div.read-content") + return root.select("img").map { img -> + val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found") + MangaPage( + id = generateUid(url), + url = url, + preview = null, + source = source, + ) + } + } + + +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/MangaDna.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/MangaDna.kt new file mode 100644 index 000000000..6d19f071b --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/MangaDna.kt @@ -0,0 +1,198 @@ +package org.koitharu.kotatsu.parsers.site.madara.en + + +import kotlinx.coroutines.async +import kotlinx.coroutines.coroutineScope +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.MangaPage +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.model.MangaState +import org.koitharu.kotatsu.parsers.model.MangaTag +import org.koitharu.kotatsu.parsers.model.SortOrder +import org.koitharu.kotatsu.parsers.site.madara.MadaraParser +import org.koitharu.kotatsu.parsers.util.* +import java.text.SimpleDateFormat + +@MangaSourceParser("MANGADNA", "MangaDna", "en") +internal class MangaDna(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.MANGADNA, "mangadna.com", 20) { + + override val isNsfwSource = true + override val datePattern = "dd MMM yyyy" + override val withoutAjax = true + override val selectdesc = "div.dsct" + override val selectchapter = "li.a-h" + + override suspend fun getListPage( + page: Int, + query: String?, + tags: Set?, + sortOrder: SortOrder, + ): List { + + val url = buildString { + append("https://") + append(domain) + val pages = page + 1 + + when { + !query.isNullOrEmpty() -> { + append("/page/") + append(pages.toString()) + append("/?s=") + append(query.urlEncoded()) + append("&post_type=wp-manga&") + } + + !tags.isNullOrEmpty() -> { + append("/$tagPrefix") + for (tag in tags) { + append(tag.key) + } + append("/page/") + append(pages.toString()) + append("?") + } + + else -> { + + append("/$listeurl") + append("/page/") + append(pages.toString()) + append("?") + } + } + append("m_orderby=") + when (sortOrder) { + SortOrder.POPULARITY -> append("views") + SortOrder.UPDATED -> append("latest") + SortOrder.NEWEST -> append("new-manga") + SortOrder.ALPHABETICAL -> append("alphabet") + else -> append("latest") + } + } + val doc = webClient.httpGet(url).parseHtml() + + + return doc.select("div.home-item").map { div -> + val href = div.selectFirst("a")?.attrAsRelativeUrlOrNull("href") ?: div.parseFailed("Link not found") + val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".hcontent") + Manga( + id = generateUid(href), + url = href, + publicUrl = href.toAbsoluteUrl(div.host ?: domain), + coverUrl = div.selectFirst("img")?.src().orEmpty(), + title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4"))?.text().orEmpty(), + altTitle = null, + rating = div.selectFirst("div.hitem-rate span")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f, + tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a -> + MangaTag( + key = a.attr("href").removeSuffix('/').substringAfterLast('/'), + title = a.text().ifEmpty { return@mapNotNullToSet null }.toTitleCase(), + source = source, + ) + }.orEmpty(), + author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(), + state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText() + ?.lowercase()) { + in ongoing -> MangaState.ONGOING + in finished -> MangaState.FINISHED + else -> null + }, + source = source, + isNsfw = isNsfwSource, + ) + } + } + + override suspend fun getDetails(manga: Manga): Manga = coroutineScope { + val fullUrl = manga.url.toAbsoluteUrl(domain) + val doc = webClient.httpGet(fullUrl).parseHtml() + val body = doc.body() + + val chaptersDeferred = async { getChapters(manga, doc) } + + val desc = body.select(selectdesc).let { + if (it.select("p").text().isNotEmpty()) { + it.select("p").joinToString(separator = "\n\n") { p -> + p.text().replace("
", "\n") + } + } else { + it.text() + } + } + + val stateDiv = (body.selectFirst("div.post-content_item:contains(Status)"))?.selectLast("div.summary-content") + + val state = stateDiv?.let { + when (it.text()) { + in ongoing -> MangaState.ONGOING + in finished -> MangaState.FINISHED + else -> null + } + } + + val alt = + doc.body().select(".post-content_item:contains(Alt) .summary-content").firstOrNull()?.tableValue()?.text() + ?.trim() ?: doc.body().select(".post-content_item:contains(Nomes alternativos: ) .summary-content") + .firstOrNull()?.tableValue()?.text()?.trim() + + manga.copy( + tags = doc.body().select(selectgenre).mapNotNullToSet { a -> + MangaTag( + key = a.attr("href").removeSuffix("/").substringAfterLast('/'), + title = a.text().toTitleCase(), + source = source, + ) + }, + description = desc, + altTitle = alt, + state = state, + chapters = chaptersDeferred.await(), + ) + } + + override suspend fun getChapters(manga: Manga, doc: Document): List { + val root2 = doc.body().selectFirstOrThrow("div.panel-manga-chapter") + val dateFormat = SimpleDateFormat(datePattern, sourceLocale) + return root2.select(selectchapter).mapChapters(reversed = true) { i, li -> + val a = li.selectFirst("a") + val href = a?.attrAsRelativeUrlOrNull("href") ?: li.parseFailed("Link is missing") + val link = href + stylepage + val dateText = li.selectFirst("a.c-new-tag")?.attr("title") ?: li.selectFirst(selectdate)?.text() + val name = a.selectFirst("p")?.text() ?: a.ownText() + MangaChapter( + id = generateUid(href), + name = name, + number = i + 1, + url = link, + uploadDate = parseChapterDate( + dateFormat, + dateText, + ), + source = source, + scanlator = null, + branch = null, + ) + } + } + + override suspend fun getPages(chapter: MangaChapter): List { + val fullUrl = chapter.url.toAbsoluteUrl(domain) + val doc = webClient.httpGet(fullUrl).parseHtml() + val root = doc.body().selectFirstOrThrow("div.read-manga").selectFirstOrThrow("div.read-content") + return root.select("img").map { img -> + val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found") + MangaPage( + id = generateUid(url), + url = url, + preview = null, + source = source, + ) + } + } +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/MangaFastNet.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/MangaFastNet.kt new file mode 100644 index 000000000..d109fe6b7 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/MangaFastNet.kt @@ -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("MANGAFASTNET", "Manga Fast Net", "en") +internal class MangaFastNet(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.MANGAFASTNET, "manhuafast.net") { + + override val withoutAjax = true +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Mangagoyaoi.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Mangagoyaoi.kt new file mode 100644 index 000000000..6486c3bf6 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Mangagoyaoi.kt @@ -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("MANGAGOYAOI", "Mangagoyaoi", "en") +internal class Mangagoyaoi(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.MANGAGOYAOI, "mangagoyaoi.com") { + + override val isNsfwSource = true +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Manhwaz.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Manhwaz.kt new file mode 100644 index 000000000..a05c72948 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Manhwaz.kt @@ -0,0 +1,105 @@ +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.Manga +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.model.MangaState +import org.koitharu.kotatsu.parsers.model.MangaTag +import org.koitharu.kotatsu.parsers.model.SortOrder +import org.koitharu.kotatsu.parsers.site.madara.MadaraParser +import org.koitharu.kotatsu.parsers.util.* + +@MangaSourceParser("MANHWAZ", "Manhwaz", "en") +internal class Manhwaz(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.MANHWAZ, "manhwaz.com", 40) { + + override val listeurl = "genre/manhwa" + override val tagPrefix = "genre/" + override val withoutAjax = true + override val selectTestAsync = "div.list-chapter" + + override suspend fun getListPage( + page: Int, + query: String?, + tags: Set?, + sortOrder: SortOrder, + ): List { + + val url = buildString { + append("https://") + append(domain) + val pages = page + 1 + + when { + !query.isNullOrEmpty() -> { + + append("/search?s=") + append(query.urlEncoded()) + append("&page=") + append(pages.toString()) + } + + !tags.isNullOrEmpty() -> { + append("/$tagPrefix") + for (tag in tags) { + append(tag.key) + } + append("?page=") + append(pages.toString()) + append("&") + } + + else -> { + + append("/$listeurl") + append("?page=") + append(pages.toString()) + append("&") + } + } + append("m_orderby=") + when (sortOrder) { + SortOrder.POPULARITY -> append("views") + SortOrder.UPDATED -> append("latest") + SortOrder.NEWEST -> append("new-manga") + SortOrder.ALPHABETICAL -> append("alphabet") + else -> append("latest") + } + } + val doc = webClient.httpGet(url).parseHtml() + + return doc.select("div.row.c-tabs-item__content").ifEmpty { + doc.select("div.page-item-detail") + }.map { div -> + val href = div.selectFirst("a")?.attrAsRelativeUrlOrNull("href") ?: div.parseFailed("Link not found") + val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".item-summary") + Manga( + id = generateUid(href), + url = href, + publicUrl = href.toAbsoluteUrl(div.host ?: domain), + coverUrl = div.selectFirst("img")?.src().orEmpty(), + title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4"))?.text().orEmpty(), + altTitle = null, + rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f, + tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a -> + MangaTag( + key = a.attr("href").removeSuffix('/').substringAfterLast('/'), + title = a.text().ifEmpty { return@mapNotNullToSet null }.toTitleCase(), + source = source, + ) + }.orEmpty(), + author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(), + state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText() + ?.lowercase()) { + in ongoing -> MangaState.ONGOING + in finished -> MangaState.FINISHED + else -> null + }, + source = source, + isNsfw = isNsfwSource, + ) + } + } +} + diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Paritehaber.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Paritehaber.kt new file mode 100644 index 000000000..93d77e4f8 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Paritehaber.kt @@ -0,0 +1,14 @@ +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("PARITEHABER", "Paritehaber", "en") +internal class Paritehaber(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.PARITEHABER, "www.paritehaber.com", 10) { + + override val isNsfwSource = true +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Rio2MangaNet.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Rio2MangaNet.kt new file mode 100644 index 000000000..cf47b6219 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/Rio2MangaNet.kt @@ -0,0 +1,11 @@ +package org.koitharu.kotatsu.parsers.site.madara.en + + +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.site.madara.MadaraParser + +@MangaSourceParser("RIO2MANGANET", "Rio2MangaNet", "en") +internal class Rio2MangaNet(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.RIO2MANGANET, "rio2manga.net", 10) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/ShibaManga.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/ShibaManga.kt new file mode 100644 index 000000000..b8a7eb0f5 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/ShibaManga.kt @@ -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("SHIBAMANGA", "Shiba Manga", "en") +internal class ShibaManga(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.SHIBAMANGA, "shibamanga.com") { + + override val datePattern = "MM/dd/yyyy" +} + diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/WebComic.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/WebComic.kt new file mode 100644 index 000000000..8a2856c9b --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/en/WebComic.kt @@ -0,0 +1,14 @@ +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("WEBCOMIC", "WebComic", "en") +internal class WebComic(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.WEBCOMIC, "webcomic.me") { + + override val postreq = true +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/Cocorip.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/Cocorip.kt new file mode 100644 index 000000000..b3b72dab1 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/Cocorip.kt @@ -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("COCORIP", "Cocorip", "es") +internal class Cocorip(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.COCORIP, "cocorip.net", 16) { + + override val datePattern = "dd/MM/yyyy" +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/DragonTranslationParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/DragonTranslationParser.kt new file mode 100644 index 000000000..177932eb8 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/DragonTranslationParser.kt @@ -0,0 +1,88 @@ +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.Manga +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.model.MangaTag +import org.koitharu.kotatsu.parsers.model.SortOrder +import org.koitharu.kotatsu.parsers.site.madara.MadaraParser +import org.koitharu.kotatsu.parsers.util.attrAsRelativeUrlOrNull +import org.koitharu.kotatsu.parsers.util.domain +import org.koitharu.kotatsu.parsers.util.generateUid +import org.koitharu.kotatsu.parsers.util.host +import org.koitharu.kotatsu.parsers.util.parseFailed +import org.koitharu.kotatsu.parsers.util.parseHtml +import org.koitharu.kotatsu.parsers.util.toAbsoluteUrl +import org.koitharu.kotatsu.parsers.util.urlEncoded +import java.util.EnumSet + +@MangaSourceParser("DRAGONTRANSLATION", "DragonTranslation", "es") +internal class DragonTranslationParser(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.DRAGONTRANSLATION, "dragontranslation.net", 30) { + + override val sortOrders: Set = EnumSet.of( + SortOrder.UPDATED, + ) + + override val selectPage = "div#chapter_imgs img" + + override suspend fun getListPage( + page: Int, + query: String?, + tags: Set?, + sortOrder: SortOrder, + ): List { + + val url = buildString { + append("https://") + append(domain) + val pages = page + 1 + + when { + !query.isNullOrEmpty() -> { + append("/mangas?buscar=") + append(query.urlEncoded()) + append("&page=") + append(pages.toString()) + } + + !tags.isNullOrEmpty() -> { + append("/mangas?tag=") + for (tag in tags) { + append(tag.key) + } + append("&page=") + append(pages.toString()) + } + + else -> { + + append("/mangas") + append("?page=") + append(pages.toString()) + } + } + } + val doc = webClient.httpGet(url).parseHtml() + + return doc.select("div.video-bg div.col-6 ").map { div -> + val href = + div.selectFirst("a.series-link")?.attrAsRelativeUrlOrNull("href") ?: div.parseFailed("Link not found") + Manga( + id = generateUid(href), + url = href, + publicUrl = href.toAbsoluteUrl(div.host ?: domain), + coverUrl = div.selectFirst("img.thumb-img")?.src().orEmpty(), + title = div.selectFirst("div.series-box h5")?.text().orEmpty(), + altTitle = null, + rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f, + tags = emptySet(), + author = null, + state = null, + source = source, + isNsfw = isNsfwSource, + ) + } + } +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/KoinoboriScan.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/KoinoboriScan.kt new file mode 100644 index 000000000..9524ef254 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/KoinoboriScan.kt @@ -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("KOINOBORISCAN", "Koinobori Scan", "es") +internal class KoinoboriScan(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.KOINOBORISCAN, "koinoboriscan.com") { + + override val postreq = true +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/Lectorunitoon.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/Lectorunitoon.kt new file mode 100644 index 000000000..c1acf9f41 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/Lectorunitoon.kt @@ -0,0 +1,15 @@ +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("LECTORUNITOON", "Lectorunitoon", "es") +internal class Lectorunitoon(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.LECTORUNITOON, "lectorunitoon.com", 10) { + + override val tagPrefix = "generos/" + override val datePattern = "dd/MM/yyyy" +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/RightdarkScan.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/RightdarkScan.kt new file mode 100644 index 000000000..105eaa34b --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/RightdarkScan.kt @@ -0,0 +1,11 @@ +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("RIGHTDARKSCAN", "Rightdark Scan", "es") +internal class RightdarkScan(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.RIGHTDARKSCAN, "rightdark-scan.com", 10) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/TraduccionesMoonlight.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/TraduccionesMoonlight.kt new file mode 100644 index 000000000..c35df13b1 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/es/TraduccionesMoonlight.kt @@ -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("TRADUCCIONESMOONLIGHT", "Traducciones Moonlight", "es") +internal class TraduccionesMoonlight(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.TRADUCCIONESMOONLIGHT, "traduccionesmoonlight.com") { + + override val datePattern = "d MMMM, yyyy" +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/id/Indo18h.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/id/Indo18h.kt new file mode 100644 index 000000000..7d9a4053b --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/id/Indo18h.kt @@ -0,0 +1,14 @@ +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 + +@MangaSourceParser("INDO18H", "Indo18h", "id") +internal class Indo18h(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.INDO18H, "indo18h.com", 24) { + + override val isNsfwSource = true + override val withoutAjax = true +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/id/ManhwaPlus.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/id/ManhwaPlus.kt new file mode 100644 index 000000000..078dc626b --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/id/ManhwaPlus.kt @@ -0,0 +1,103 @@ +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.Manga +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.model.MangaState +import org.koitharu.kotatsu.parsers.model.MangaTag +import org.koitharu.kotatsu.parsers.model.SortOrder +import org.koitharu.kotatsu.parsers.site.madara.MadaraParser +import org.koitharu.kotatsu.parsers.util.* +import java.util.Locale + +@MangaSourceParser("MANHWAPLUS", "Manhwa Plus", "id") +internal class ManhwaPlus(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.MANHWAPLUS, "manhwaplus.pro", 10) { + + override val isNsfwSource = true + override val tagPrefix = "genre/" + override val datePattern = "MMMM d, yyyy" + override val sourceLocale: Locale = Locale.ENGLISH + override val withoutAjax = true + override val listeurl = "series/" + + override suspend fun getListPage( + page: Int, + query: String?, + tags: Set?, + sortOrder: SortOrder, + ): List { + + val url = buildString { + append("https://") + append(domain) + val pages = page + 1 + + when { + !query.isNullOrEmpty() -> { + append("/page/") + append(pages.toString()) + append("/?s=") + append(query.urlEncoded()) + append("&post_type=wp-manga&") + } + + !tags.isNullOrEmpty() -> { + append("/$tagPrefix") + for (tag in tags) { + append(tag.key) + } + append("/page/") + append(pages.toString()) + append("?") + } + + else -> { + + append("/$listeurl") + append("/page/") + append(pages.toString()) + append("?") + } + } + } + val doc = webClient.httpGet(url).parseHtml() + + return doc.select("div.row.c-tabs-item__content").ifEmpty { + doc.select("div.page-item-detail") + }.map { div -> + val href = div.selectFirst("a")?.attrAsRelativeUrlOrNull("href") ?: div.parseFailed("Link not found") + val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".item-summary") + Manga( + id = generateUid(href), + url = href, + publicUrl = href.toAbsoluteUrl(div.host ?: domain), + coverUrl = div.selectFirst("img")?.attr("data-wpfc-original-src") ?: div.selectFirst("img")?.src() + .orEmpty(), + title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4") + ?: div.selectFirst("h5.series-title"))?.text().orEmpty(), + altTitle = null, + rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f, + tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a -> + MangaTag( + key = a.attr("href").removeSuffix('/').substringAfterLast('/'), + title = a.text().ifEmpty { return@mapNotNullToSet null }.toTitleCase(), + source = source, + ) + }.orEmpty(), + author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(), + state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText() + ?.lowercase()) { + in ongoing -> MangaState.ONGOING + in finished -> MangaState.FINISHED + else -> null + }, + source = source, + isNsfw = isNsfwSource, + ) + } + } + +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ru/Mangazavr.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ru/Mangazavr.kt new file mode 100644 index 000000000..b43be1e45 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/ru/Mangazavr.kt @@ -0,0 +1,16 @@ +package org.koitharu.kotatsu.parsers.site.madara.ru + + +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("MANGAZAVR", "Mangazavr", "ru") +internal class Mangazavr(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.MANGAZAVR, "mangazavr.ru") { + + override val datePattern = "dd.MM.yyyy" + override val isNsfwSource = true +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/th/Manhuabug.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/th/Manhuabug.kt new file mode 100644 index 000000000..c5e6b13dc --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/th/Manhuabug.kt @@ -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 +import java.util.Locale + +@MangaSourceParser("MANHUABUG", "Manhuabug", "th") +internal class Manhuabug(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.MANHUABUG, "www.manhuabug.com", 10) { + + override val datePattern: String = "d MMMM yyyy" + override val sourceLocale: Locale = Locale.ENGLISH +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/th/Manhuakey.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/th/Manhuakey.kt new file mode 100644 index 000000000..35c5bfa60 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/th/Manhuakey.kt @@ -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 +import java.util.Locale + +@MangaSourceParser("MANHUAKEY", "Manhuakey", "th") +internal class Manhuakey(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.MANHUAKEY, "www.manhuakey.com", 10) { + + override val datePattern: String = "d MMMM yyyy" + override val sourceLocale: Locale = Locale.ENGLISH +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/tr/KuroiManga.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/tr/KuroiManga.kt new file mode 100644 index 000000000..a847eda9b --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/tr/KuroiManga.kt @@ -0,0 +1,16 @@ +package org.koitharu.kotatsu.parsers.site.madara.tr + + +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.site.madara.MadaraParser + + +@MangaSourceParser("KUROIMANGA", "Kuroi Manga", "tr") +internal class KuroiManga(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.KUROIMANGA, "www.kuroimanga.com") { + + override val datePattern = "d MMMM yyyy" + override val isNsfwSource = true +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/tr/NiveraFansub.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/tr/NiveraFansub.kt new file mode 100644 index 000000000..e08c505a1 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/tr/NiveraFansub.kt @@ -0,0 +1,16 @@ +package org.koitharu.kotatsu.parsers.site.madara.tr + + +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.site.madara.MadaraParser + + +@MangaSourceParser("NIVERAFANSUB", "Nivera Fansub", "tr") +internal class NiveraFansub(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.NIVERAFANSUB, "niverafansub.com") { + + override val datePattern = "d MMMM yyyy" + override val isNsfwSource = true +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/tr/ViyaFansub.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/tr/ViyaFansub.kt new file mode 100644 index 000000000..3ffb527a3 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/tr/ViyaFansub.kt @@ -0,0 +1,16 @@ +package org.koitharu.kotatsu.parsers.site.madara.tr + + +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.site.madara.MadaraParser + + +@MangaSourceParser("VIYAFANSUB", "Viya Fansub", "tr") +internal class ViyaFansub(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.VIYAFANSUB, "viyafansub.com") { + + override val datePattern = "d MMMM yyyy" + override val isNsfwSource = true +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/MangaZodiac.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/MangaZodiac.kt new file mode 100644 index 000000000..251ef94e7 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/MangaZodiac.kt @@ -0,0 +1,12 @@ +package org.koitharu.kotatsu.parsers.site.madara.vi + + +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("MANGAZODIAC", "Manga Zodiac", "vi") +internal class MangaZodiac(context: MangaLoaderContext) : + MadaraParser(context, MangaSource.MANGAZODIAC, "mangazodiac.com") diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/MangaReaderParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/MangaReaderParser.kt index 83a384644..ab1db9032 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/MangaReaderParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/MangaReaderParser.kt @@ -29,6 +29,7 @@ import org.koitharu.kotatsu.parsers.util.toAbsoluteUrl import org.koitharu.kotatsu.parsers.util.tryParse import org.koitharu.kotatsu.parsers.util.urlEncoded import java.text.SimpleDateFormat +import java.util.Base64 import java.util.EnumSet import java.util.Locale @@ -92,6 +93,7 @@ internal abstract class MangaReaderParser( tablemode.selectFirst(".infotable td:contains(Status)") ?: tablemode.selectFirst(".infotable td:contains(Statut)") ?: tablemode.selectFirst(".infotable td:contains(حالة العمل)") + ?: tablemode.selectFirst(".infotable td:contains(الحالة)") ?: tablemode.selectFirst(".infotable td:contains(Estado)") ?: docs.selectFirst(".infotable td:contains(สถานะ)") ?: tablemode.selectFirst(".infotable td:contains(Stato )") @@ -103,7 +105,7 @@ internal abstract class MangaReaderParser( ?: 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(Statüsü)") - ?: docs.selectFirst(".tsinfo div:contains(Statü)") + ?: docs.selectFirst(".tsinfo div:contains(Statü)") ?: docs.selectFirst(".tsinfo div:contains(الحالة)") } val state = if (tablemode != null) { @@ -120,7 +122,7 @@ internal abstract class MangaReaderParser( "En cours \uD83D\uDFE2", "En cours de publication", "Đang tiến hành", "Em lançamento", "em lançamento", "Em Lançamento", "Онгоінг", "Publishing", "Devam Ediyor", "Em Andamento", "In Corso", "Güncel", "Berjalan", "Продолжается", "Updating", "Lançando", "In Arrivo", "Emision", "En emision", "مستمر", "Curso", "En marcha", "Publicandose", "Publicando", "连载中", - "Devam ediyor", + "Devam ediyor", "Devam Etmekte", -> MangaState.ONGOING "Completed", "Completo", "Complété", "Fini", "Achevé", "Terminé", "Terminé ⚫", "Tamamlandı", "Đã hoàn thành", "Hoàn Thành", "مكتملة", @@ -204,8 +206,10 @@ internal abstract class MangaReaderParser( return parseMangaList(webClient.httpGet(url).parseHtml()) } + protected open val selectMangaliste = ".postbody .listupd .bs .bsx" + protected open fun parseMangaList(docs: Document): List { - return docs.select(".postbody .listupd .bs .bsx").mapNotNull { + return docs.select(selectMangaliste).mapNotNull { val a = it.selectFirst("a") ?: return@mapNotNull null val relativeUrl = a.attrAsRelativeUrl("href") val rating = it.selectFirst(".numscore")?.text() @@ -228,12 +232,15 @@ internal abstract class MangaReaderParser( } } + protected open val encodedSrc = false + protected open val selectScript = "div.wrapper script" + override suspend fun getPages(chapter: MangaChapter): List { val chapterUrl = chapter.url.toAbsoluteUrl(domain) val docs = webClient.httpGet(chapterUrl).parseHtml() val test = docs.select("script:containsData(ts_reader)") - if (test.isNullOrEmpty()) { + if (test.isNullOrEmpty() and !encodedSrc) { return docs.select("div#readerarea img").map { img -> val url = img.imageUrl() MangaPage( @@ -244,11 +251,32 @@ internal abstract class MangaReaderParser( ) } } else { - val script = docs.selectFirstOrThrow("script:containsData(ts_reader)") - val images = JSONObject(script.data().substringAfter('(').substringBeforeLast(')')) - .getJSONArray("sources") - .getJSONObject(0) - .getJSONArray("images") + val images = if (encodedSrc) { + val script = docs.select(selectScript) + var decode = "" + for (i in script) { + if (i.attr("src").startsWith("data:text/javascript;base64,")) { + decode = Base64.getDecoder().decode(i.attr("src").replace("data:text/javascript;base64,", "")) + .decodeToString() + if (decode.startsWith("ts_reader.run")) { + break + } + } + + } + JSONObject(decode.substringAfter('(').substringBeforeLast(')')) + .getJSONArray("sources") + .getJSONObject(0) + .getJSONArray("images") + + } else { + val script = docs.selectFirstOrThrow("script:containsData(ts_reader)") + JSONObject(script.data().substringAfter('(').substringBeforeLast(')')) + .getJSONArray("sources") + .getJSONObject(0) + .getJSONArray("images") + } + val pages = ArrayList(images.length()) for (i in 0 until images.length()) { pages.add( @@ -292,7 +320,7 @@ internal abstract class MangaReaderParser( return@withLock tagMap } - private fun Element.imageUrl(): String { + protected open fun Element.imageUrl(): String { return attrAsAbsoluteUrlOrNull("src") ?: attrAsAbsoluteUrlOrNull("data-src") ?: attrAsAbsoluteUrlOrNull("data-cfsrc") diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/ar/Areascans.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/ar/Areascans.kt new file mode 100644 index 000000000..ee750f164 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/ar/Areascans.kt @@ -0,0 +1,20 @@ +package org.koitharu.kotatsu.parsers.site.mangareader.ar + +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("AREASCANS", "Areascans", "ar") +internal class Areascans(context: MangaLoaderContext) : + MangaReaderParser(context, MangaSource.AREASCANS, pageSize = 20, searchPageSize = 10) { + + override val configKeyDomain: ConfigKey.Domain + get() = ConfigKey.Domain("www.areascans.net") + + override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMMM d, yyyy", Locale("ar", "AR")) + +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/ar/BeastScans.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/ar/BeastScans.kt new file mode 100644 index 000000000..b54276283 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/ar/BeastScans.kt @@ -0,0 +1,20 @@ +package org.koitharu.kotatsu.parsers.site.mangareader.ar + +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("BEASTSCANS", "Beast Scans", "ar") +internal class BeastScans(context: MangaLoaderContext) : + MangaReaderParser(context, MangaSource.BEASTSCANS, pageSize = 20, searchPageSize = 10) { + + override val configKeyDomain: ConfigKey.Domain + get() = ConfigKey.Domain("beast-scans.com") + + override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMMM d, yyyy", Locale("ar", "AR")) + +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/BabelToon.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/BabelToon.kt new file mode 100644 index 000000000..70f14dc92 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/BabelToon.kt @@ -0,0 +1,65 @@ +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.Manga +import org.koitharu.kotatsu.parsers.model.MangaChapter +import org.koitharu.kotatsu.parsers.model.MangaPage +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser +import org.koitharu.kotatsu.parsers.util.attrAsRelativeUrl +import org.koitharu.kotatsu.parsers.util.domain +import org.koitharu.kotatsu.parsers.util.generateUid +import org.koitharu.kotatsu.parsers.util.mapChapters +import org.koitharu.kotatsu.parsers.util.parseHtml +import org.koitharu.kotatsu.parsers.util.toAbsoluteUrl +import org.koitharu.kotatsu.parsers.util.tryParse +import java.text.SimpleDateFormat +import java.util.Locale + +@MangaSourceParser("BABELTOON", "BabelToon", "en") +internal class BabelToon(context: MangaLoaderContext) : + MangaReaderParser(context, MangaSource.BABELTOON, pageSize = 20, searchPageSize = 10) { + override val configKeyDomain: ConfigKey.Domain + get() = ConfigKey.Domain("babeltoon.com") + + override val listUrl = "/series" + override val selectMangaliste = ".postbody .listupd .maindet .inmain" + override val chapterDateFormat = SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH) + + + override suspend fun getDetails(manga: Manga): Manga { + val docs = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml() + val chapters = docs.select(".eplister > ul > li").mapChapters(reversed = true) { index, element -> + val url = element.selectFirst("a")?.attrAsRelativeUrl("href") ?: return@mapChapters null + MangaChapter( + id = generateUid(url), + name = element.selectFirst(".epl-num")?.text() ?: "Chapter ${index + 1}", + url = url, + number = index + 1, + scanlator = null, + uploadDate = chapterDateFormat.tryParse(element.selectFirst(".epl-date")?.text()), + branch = null, + source = source, + ) + } + return parseInfo(docs, manga, chapters) + } + + override suspend fun getPages(chapter: MangaChapter): List { + val chapterUrl = chapter.url.toAbsoluteUrl(domain) + val docs = webClient.httpGet(chapterUrl).parseHtml() + + return docs.select("div.epcontent img").map { img -> + val url = img.imageUrl() + MangaPage( + id = generateUid(url), + url = url, + preview = null, + source = source, + ) + } + } +} + diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/FreakScans.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/FreakScans.kt new file mode 100644 index 000000000..e03058697 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/FreakScans.kt @@ -0,0 +1,15 @@ +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 + +@MangaSourceParser("FREAKSCANS", "FreakScans", "en") +internal class FreakScans(context: MangaLoaderContext) : + MangaReaderParser(context, MangaSource.FREAKSCANS, pageSize = 20, searchPageSize = 20) { + override val configKeyDomain: ConfigKey.Domain + get() = ConfigKey.Domain("freakscans.com") + +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/QueenScans.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/QueenScans.kt new file mode 100644 index 000000000..95b9fec29 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/QueenScans.kt @@ -0,0 +1,17 @@ +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 + +@MangaSourceParser("QUEENSCANS", "QueenScans", "en") +internal class QueenScans(context: MangaLoaderContext) : + MangaReaderParser(context, MangaSource.QUEENSCANS, pageSize = 30, searchPageSize = 10) { + override val configKeyDomain: ConfigKey.Domain + get() = ConfigKey.Domain("queenscans.com") + + override val listUrl = "/comics" + +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/es/DragonTranslationParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/es/SkyMangas.kt similarity index 61% rename from src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/es/DragonTranslationParser.kt rename to src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/es/SkyMangas.kt index be71c2108..c4f911a2f 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/es/DragonTranslationParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/es/SkyMangas.kt @@ -8,12 +8,13 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser import java.text.SimpleDateFormat import java.util.Locale -@MangaSourceParser("DRAGONTRANSLATION", "DragonTranslation", "es") -internal class DragonTranslationParser(context: MangaLoaderContext) : - MangaReaderParser(context, MangaSource.DRAGONTRANSLATION, pageSize = 20, searchPageSize = 10) { +@MangaSourceParser("SKYMANGAS", "Sky Mangas", "es") +internal class SkyMangas(context: MangaLoaderContext) : + MangaReaderParser(context, MangaSource.SKYMANGAS, pageSize = 20, searchPageSize = 10) { override val configKeyDomain: ConfigKey.Domain - get() = ConfigKey.Domain("dragontranslation.net") + get() = ConfigKey.Domain("skymangas.com") - override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH) + override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMMM d, yyyy", Locale("es", "ES")) + override val encodedSrc = true } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/DoujinDesuRip.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/DoujinDesuRip.kt new file mode 100644 index 000000000..646591cc9 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/DoujinDesuRip.kt @@ -0,0 +1,20 @@ +package org.koitharu.kotatsu.parsers.site.mangareader.id + +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("DOUJINDESURIP", "Doujin Desu Rip", "id") +internal class DoujinDesuRip(context: MangaLoaderContext) : + MangaReaderParser(context, MangaSource.DOUJINDESURIP, pageSize = 10, searchPageSize = 10) { + override val configKeyDomain: ConfigKey.Domain + get() = ConfigKey.Domain("doujindesu.rip") + + override val isNsfwSource = true + override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale("in", "ID")) + +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/Komikcast.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/Komikcast.kt index 2a58038e3..7418c703c 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/Komikcast.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/Komikcast.kt @@ -2,29 +2,12 @@ package org.koitharu.kotatsu.parsers.site.mangareader.id import org.json.JSONObject 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.config.ConfigKey -import org.koitharu.kotatsu.parsers.model.Manga -import org.koitharu.kotatsu.parsers.model.MangaChapter -import org.koitharu.kotatsu.parsers.model.MangaPage -import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.parsers.model.MangaState -import org.koitharu.kotatsu.parsers.model.RATING_UNKNOWN -import org.koitharu.kotatsu.parsers.model.WordSet +import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser -import org.koitharu.kotatsu.parsers.util.attrAsAbsoluteUrl -import org.koitharu.kotatsu.parsers.util.attrAsAbsoluteUrlOrNull -import org.koitharu.kotatsu.parsers.util.attrAsRelativeUrl -import org.koitharu.kotatsu.parsers.util.domain -import org.koitharu.kotatsu.parsers.util.generateUid -import org.koitharu.kotatsu.parsers.util.mapChapters -import org.koitharu.kotatsu.parsers.util.mapNotNullToSet -import org.koitharu.kotatsu.parsers.util.parseHtml -import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow -import org.koitharu.kotatsu.parsers.util.toAbsoluteUrl -import org.koitharu.kotatsu.parsers.util.tryParse +import org.koitharu.kotatsu.parsers.util.* import java.text.DateFormat import java.util.Calendar @@ -118,13 +101,6 @@ internal class Komikcast(context: MangaLoaderContext) : } } - private fun Element.imageUrl(): String { - return attrAsAbsoluteUrlOrNull("src") - ?: attrAsAbsoluteUrlOrNull("data-src") - ?: attrAsAbsoluteUrlOrNull("data-cfsrc") - ?: "" - } - override suspend fun getPages(chapter: MangaChapter): List { val chapterUrl = chapter.url.toAbsoluteUrl(domain) val docs = webClient.httpGet(chapterUrl).parseHtml() diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/KomiklokalCfd.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/KomiklokalCfd.kt new file mode 100644 index 000000000..d5a237a10 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/KomiklokalCfd.kt @@ -0,0 +1,20 @@ +package org.koitharu.kotatsu.parsers.site.mangareader.id + +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("KOMIKLOKALCFD", "Komiklokal Cfd", "id") +internal class KomiklokalCfd(context: MangaLoaderContext) : + MangaReaderParser(context, MangaSource.KOMIKLOKALCFD, pageSize = 30, searchPageSize = 10) { + + override val configKeyDomain: ConfigKey.Domain + get() = ConfigKey.Domain("komiklokal.cfd") + + override val isNsfwSource = true + override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH) +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/ManhwaIndoIcu.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/ManhwaIndoIcu.kt new file mode 100644 index 000000000..41213148b --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/ManhwaIndoIcu.kt @@ -0,0 +1,20 @@ +package org.koitharu.kotatsu.parsers.site.mangareader.id + +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("MANHWAINDOICU", "Manhwa Indo Icu", "id") +internal class ManhwaIndoIcu(context: MangaLoaderContext) : + MangaReaderParser(context, MangaSource.MANHWAINDOICU, pageSize = 30, searchPageSize = 10) { + + override val configKeyDomain: ConfigKey.Domain + get() = ConfigKey.Domain("manhwaindo.icu") + + override val isNsfwSource = true + override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH) +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/Nonbiri.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/Nonbiri.kt new file mode 100644 index 000000000..0936db890 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/Nonbiri.kt @@ -0,0 +1,18 @@ +package org.koitharu.kotatsu.parsers.site.mangareader.id + +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("NONBIRI", "Nonbiri", "id") +internal class Nonbiri(context: MangaLoaderContext) : + MangaReaderParser(context, MangaSource.NONBIRI, pageSize = 15, searchPageSize = 10) { + override val configKeyDomain: ConfigKey.Domain + get() = ConfigKey.Domain("nonbiri.space") + + override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale("in", "ID")) +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/ja/MangaMate.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/ja/MangaMate.kt new file mode 100644 index 000000000..03422c3ec --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/ja/MangaMate.kt @@ -0,0 +1,21 @@ +package org.koitharu.kotatsu.parsers.site.mangareader.ja + +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("MANGAMATE", "Manga Mate", "ja") +internal class MangaMate(context: MangaLoaderContext) : + MangaReaderParser(context, MangaSource.MANGAMATE, pageSize = 10, searchPageSize = 10) { + override val configKeyDomain: ConfigKey.Domain + get() = ConfigKey.Domain("manga-mate.org") + + + override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("M月 d, yyyy", Locale.ENGLISH) + override val encodedSrc = true + +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/th/MangaMoons.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/th/MangaMoons.kt new file mode 100644 index 000000000..cf0be2229 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/th/MangaMoons.kt @@ -0,0 +1,18 @@ +package org.koitharu.kotatsu.parsers.site.mangareader.th + +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("MANGAMOONS", "Manga Moons", "th") +internal class MangaMoons(context: MangaLoaderContext) : + MangaReaderParser(context, MangaSource.MANGAMOONS, pageSize = 20, searchPageSize = 10) { + override val configKeyDomain: ConfigKey.Domain + get() = ConfigKey.Domain("manga-moons.net") + + override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMMM d, yyyy", Locale("th", "TH")) +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/tr/AfroditScans.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/tr/AfroditScans.kt new file mode 100644 index 000000000..a87369b82 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/tr/AfroditScans.kt @@ -0,0 +1,18 @@ +package org.koitharu.kotatsu.parsers.site.mangareader.tr + +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("AFRODITSCANS", "Afrodit Scans", "tr") +internal class AfroditScans(context: MangaLoaderContext) : + MangaReaderParser(context, MangaSource.AFRODITSCANS, pageSize = 24, searchPageSize = 10) { + override val configKeyDomain: ConfigKey.Domain + get() = ConfigKey.Domain("afroditscans.com") + + override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMM d, yyyy", Locale("tr")) +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/tr/AthenaFansub.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/tr/AthenaFansub.kt new file mode 100644 index 000000000..a1b098499 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/tr/AthenaFansub.kt @@ -0,0 +1,19 @@ +package org.koitharu.kotatsu.parsers.site.mangareader.tr + +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("ATHENAFANSUB", "AthenaFansub", "tr") +internal class AthenaFansub(context: MangaLoaderContext) : + MangaReaderParser(context, MangaSource.ATHENAFANSUB, pageSize = 20, searchPageSize = 10) { + override val configKeyDomain: ConfigKey.Domain + get() = ConfigKey.Domain("athenafansub.com") + + override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMMM d, yyyy", Locale("tr", "TR")) +} + diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/tr/NyxManga.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/tr/NyxManga.kt new file mode 100644 index 000000000..fe8c121a4 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/tr/NyxManga.kt @@ -0,0 +1,19 @@ +package org.koitharu.kotatsu.parsers.site.mangareader.tr + +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("NYXMANGA", "Nyx Manga", "tr") +internal class NyxManga(context: MangaLoaderContext) : + MangaReaderParser(context, MangaSource.NYXMANGA, pageSize = 14, searchPageSize = 10) { + override val configKeyDomain: ConfigKey.Domain + get() = ConfigKey.Domain("nyxmanga.com") + + override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMMM d, yyyy", Locale("tr", "TR")) +} + diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/tr/SpartanManga.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/tr/SpartanManga.kt new file mode 100644 index 000000000..7dd15675e --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/tr/SpartanManga.kt @@ -0,0 +1,19 @@ +package org.koitharu.kotatsu.parsers.site.mangareader.tr + +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("SPARTANMANGA", "Spartan Manga", "tr") +internal class SpartanManga(context: MangaLoaderContext) : + MangaReaderParser(context, MangaSource.SPARTANMANGA, pageSize = 40, searchPageSize = 20) { + override val configKeyDomain: ConfigKey.Domain + get() = ConfigKey.Domain("spartanmanga.com.tr") + + override val chapterDateFormat: SimpleDateFormat = SimpleDateFormat("MMMM d, yyyy", Locale("tr", "TR")) +} +