@@ -44,6 +44,7 @@ internal abstract class AnimeBootstrapParser(
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -59,9 +60,7 @@ internal abstract class AnimeBootstrapParser(
|
||||
|
||||
if (!tags.isNullOrEmpty()) {
|
||||
append("&categorie=")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
}
|
||||
|
||||
append("&sort=")
|
||||
|
||||
@@ -6,27 +6,9 @@ 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.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaState
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.model.RATING_UNKNOWN
|
||||
import org.koitharu.kotatsu.parsers.model.SortOrder
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.site.animebootstrap.AnimeBootstrapParser
|
||||
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.host
|
||||
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.removeSuffix
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
import org.koitharu.kotatsu.parsers.util.toAbsoluteUrl
|
||||
import org.koitharu.kotatsu.parsers.util.toTitleCase
|
||||
import org.koitharu.kotatsu.parsers.util.tryParse
|
||||
import org.koitharu.kotatsu.parsers.util.urlEncoded
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.EnumSet
|
||||
import java.util.Locale
|
||||
@@ -56,6 +38,9 @@ internal class PapScan(context: MangaLoaderContext) :
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -70,9 +55,7 @@ internal class PapScan(context: MangaLoaderContext) :
|
||||
|
||||
if (!tags.isNullOrEmpty()) {
|
||||
append("&cat=")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
}
|
||||
append("&sortBy=")
|
||||
when (sortOrder) {
|
||||
|
||||
@@ -54,6 +54,7 @@ internal abstract class FmreaderParser(
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -69,9 +70,7 @@ internal abstract class FmreaderParser(
|
||||
|
||||
!tags.isNullOrEmpty() -> {
|
||||
append("&genre=")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,8 +91,9 @@ internal abstract class FmreaderParser(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
|
||||
coverUrl = div.selectFirstOrThrow("div.img-in-ratio").attr("style").substringAfter("('")
|
||||
.substringBeforeLast("')"),
|
||||
coverUrl = div.selectFirstOrThrow("div.img-in-ratio").attr("data-bg")
|
||||
?: div.selectFirstOrThrow("div.img-in-ratio").attr("style").substringAfter("('")
|
||||
.substringBeforeLast("')"),
|
||||
title = div.selectFirstOrThrow("div.series-title").text().orEmpty(),
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
@@ -106,10 +106,11 @@ internal abstract class FmreaderParser(
|
||||
}
|
||||
}
|
||||
|
||||
protected open val selectBodyTag = "ul.filter-type li a"
|
||||
|
||||
override suspend fun getTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/$listeurl").parseHtml()
|
||||
return doc.select("ul.filter-type li").mapNotNullToSet { li ->
|
||||
val a = li.selectFirst("a") ?: return@mapNotNullToSet null
|
||||
return doc.select(selectBodyTag).mapNotNullToSet { a ->
|
||||
val href = a.attr("href").substringAfter("manga-list-genre-").substringBeforeLast(".html")
|
||||
MangaTag(
|
||||
key = href,
|
||||
|
||||
@@ -6,22 +6,9 @@ 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.ContentType
|
||||
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.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.site.fmreader.FmreaderParser
|
||||
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.toTitleCase
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.text.SimpleDateFormat
|
||||
|
||||
@MangaSourceParser("MANHWA18COM", "Manhwa18 Com", "en", ContentType.HENTAI)
|
||||
@@ -35,6 +22,87 @@ internal class Manhwa18Com(context: MangaLoaderContext) :
|
||||
override val selectTag = "div.info-item:contains(Genre) span.info-value a"
|
||||
override val datePattern = "dd/MM/yyyy"
|
||||
override val selectPage = "div#chapter-content img"
|
||||
override val selectBodyTag = "div.genres-menu a"
|
||||
|
||||
override suspend fun getListPage(
|
||||
page: Int,
|
||||
query: String?,
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
if (!tags.isNullOrEmpty()) {
|
||||
append("/genre/")
|
||||
append(tag?.key.orEmpty())
|
||||
append("?page=")
|
||||
append(page.toString())
|
||||
append("&sort=")
|
||||
when (sortOrder) {
|
||||
SortOrder.POPULARITY -> append("views")
|
||||
SortOrder.UPDATED -> append("last_update")
|
||||
SortOrder.ALPHABETICAL -> append("name")
|
||||
else -> append("last_update")
|
||||
}
|
||||
} else {
|
||||
append(listeurl)
|
||||
append("?page=")
|
||||
append(page.toString())
|
||||
when {
|
||||
!query.isNullOrEmpty() -> {
|
||||
append("&q=")
|
||||
append(query.urlEncoded())
|
||||
}
|
||||
}
|
||||
|
||||
append("&sort=")
|
||||
when (sortOrder) {
|
||||
SortOrder.POPULARITY -> append("views")
|
||||
SortOrder.UPDATED -> append("last_update")
|
||||
SortOrder.ALPHABETICAL -> append("name")
|
||||
else -> append("last_update")
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
|
||||
return doc.select("div.thumb-item-flow").map { div ->
|
||||
|
||||
val href = div.selectFirstOrThrow("div.series-title a").attrAsRelativeUrl("href")
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
|
||||
coverUrl = div.selectFirstOrThrow("div.img-in-ratio").attr("data-bg")
|
||||
?: div.selectFirstOrThrow("div.img-in-ratio").attr("style").substringAfter("('")
|
||||
.substringBeforeLast("')"),
|
||||
title = div.selectFirstOrThrow("div.series-title").text().orEmpty(),
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/$listeurl").parseHtml()
|
||||
return doc.select(selectBodyTag).mapNotNullToSet { a ->
|
||||
val href = a.attr("href").substringAfterLast("/")
|
||||
MangaTag(
|
||||
key = href,
|
||||
title = a.text(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
|
||||
@@ -27,6 +27,7 @@ internal class Klz9(context: MangaLoaderContext) :
|
||||
override val selectChapter = "tr"
|
||||
override val selectDate = "td i"
|
||||
override val selectPage = "img"
|
||||
override val selectBodyTag = "div.panel-body a"
|
||||
|
||||
override suspend fun getListPage(
|
||||
page: Int,
|
||||
@@ -34,6 +35,7 @@ internal class Klz9(context: MangaLoaderContext) :
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -49,9 +51,7 @@ internal class Klz9(context: MangaLoaderContext) :
|
||||
|
||||
!tags.isNullOrEmpty() -> {
|
||||
append("&genre=")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -137,13 +137,12 @@ internal abstract class MadaraParser(
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val doc = if (withoutAjax) {
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
val pages = page + 1
|
||||
|
||||
when {
|
||||
!query.isNullOrEmpty() -> {
|
||||
append("/page/")
|
||||
@@ -155,9 +154,7 @@ internal abstract class MadaraParser(
|
||||
|
||||
!tags.isNullOrEmpty() -> {
|
||||
append("/$tagPrefix")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
append("/page/")
|
||||
append(pages.toString())
|
||||
append("?")
|
||||
@@ -182,8 +179,6 @@ internal abstract class MadaraParser(
|
||||
}
|
||||
webClient.httpGet(url).parseHtml()
|
||||
} else {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
|
||||
val payload = if (sortOrder == SortOrder.RATING) {
|
||||
createRequestTemplate(ratingRequest)
|
||||
} else {
|
||||
@@ -273,7 +268,7 @@ internal abstract class MadaraParser(
|
||||
"div.description-summary div.summary__content, div.summary_content div.post-content_item > h5 + div, div.summary_content div.manga-excerpt, div.post-content div.manga-summary, div.post-content div.desc, div.c-page__content div.summary__content"
|
||||
protected open val selectGenre = "div.genres-content a"
|
||||
protected open val selectTestAsync = "div.listing-chapters_wrap"
|
||||
|
||||
protected open val selectState = ""
|
||||
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
@@ -289,18 +284,23 @@ internal abstract class MadaraParser(
|
||||
|
||||
val desc = body.select(selectDesc).html()
|
||||
|
||||
val stateDiv = (body.selectFirst("div.post-content_item:contains(Status)")
|
||||
?: body.selectFirst("div.post-content_item:contains(Statut)")
|
||||
?: body.selectFirst("div.post-content_item:contains(État)")
|
||||
?: body.selectFirst("div.post-content_item:contains(حالة العمل)")
|
||||
?: body.selectFirst("div.post-content_item:contains(Estado)")
|
||||
?: body.selectFirst("div.post-content_item:contains(สถานะ)")
|
||||
?: body.selectFirst("div.post-content_item:contains(Stato)")
|
||||
?: body.selectFirst("div.post-content_item:contains(Durum)")
|
||||
?: body.selectFirst("div.post-content_item:contains(Statüsü)")
|
||||
?: body.selectFirst("div.post-content_item:contains(Статус)")
|
||||
?: body.selectFirst("div.post-content_item:contains(状态)")
|
||||
?: body.selectFirst("div.post-content_item:contains(الحالة)"))?.selectLast("div.summary-content")
|
||||
val stateDiv = if (selectState.isEmpty()) {
|
||||
(body.selectFirst("div.post-content_item:contains(Status)")
|
||||
?: body.selectFirst("div.post-content_item:contains(Statut)")
|
||||
?: body.selectFirst("div.post-content_item:contains(État)")
|
||||
?: body.selectFirst("div.post-content_item:contains(حالة العمل)")
|
||||
?: body.selectFirst("div.post-content_item:contains(Estado)")
|
||||
?: body.selectFirst("div.post-content_item:contains(สถานะ)")
|
||||
?: body.selectFirst("div.post-content_item:contains(Stato)")
|
||||
?: body.selectFirst("div.post-content_item:contains(Durum)")
|
||||
?: body.selectFirst("div.post-content_item:contains(Statüsü)")
|
||||
?: body.selectFirst("div.post-content_item:contains(Статус)")
|
||||
?: body.selectFirst("div.post-content_item:contains(状态)")
|
||||
?: body.selectFirst("div.post-content_item:contains(الحالة)"))?.selectLast("div.summary-content")
|
||||
} else {
|
||||
body.selectFirst(selectState)
|
||||
}
|
||||
|
||||
|
||||
val state = stateDiv?.let {
|
||||
when (it.text()) {
|
||||
@@ -553,10 +553,13 @@ internal abstract class MadaraParser(
|
||||
}
|
||||
}
|
||||
|
||||
private val ratingRequest = "action=madara_load_more&page=1&template=madara-core%2Fcontent%2Fcontent-search&vars%5Bs%5D=&vars%5Borderby%5D%5Bquery_avarage_reviews%5D=DESC&vars%5Borderby%5D%5Bquery_total_reviews%5D=DESC&vars%5Bpaged%5D=1&vars%5Btemplate%5D=search&vars%5Bmeta_query%5D%5B0%5D%5Brelation%5D=AND&vars%5Bmeta_query%5D%5B0%5D%5Bquery_avarage_reviews%5D%5Bkey%5D=_manga_avarage_reviews&vars%5Bmeta_query%5D%5B0%5D%5Bquery_total_reviews%5D%5Bkey%5D=_manga_total_votes&vars%5Bmeta_query%5D%5Brelation%5D=AND&vars%5Bpost_type%5D=wp-manga&vars%5Bpost_status%5D=publish&vars%5Bmanga_archives_item_layout%5D=default"
|
||||
private val defaultRequest = "action=madara_load_more&page=1&template=madara-core%2Fcontent%2Fcontent-search&vars%5Bs%5D=&vars%5Borderby%5D=meta_value_num&vars%5Bpaged%5D=1&vars%5Btemplate%5D=search&vars%5Bmeta_query%5D%5B0%5D%5Brelation%5D=AND&vars%5Bmeta_query%5D%5Brelation%5D=OR&vars%5Bpost_type%5D=wp-manga&vars%5Bpost_status%5D=publish&vars%5Bmeta_key%5D=_latest_update&vars%5Border%5D=desc&vars%5Bmanga_archives_item_layout%5D=default"
|
||||
private val ratingRequest =
|
||||
"action=madara_load_more&page=1&template=madara-core%2Fcontent%2Fcontent-search&vars%5Bs%5D=&vars%5Borderby%5D%5Bquery_avarage_reviews%5D=DESC&vars%5Borderby%5D%5Bquery_total_reviews%5D=DESC&vars%5Bpaged%5D=1&vars%5Btemplate%5D=search&vars%5Bmeta_query%5D%5B0%5D%5Brelation%5D=AND&vars%5Bmeta_query%5D%5B0%5D%5Bquery_avarage_reviews%5D%5Bkey%5D=_manga_avarage_reviews&vars%5Bmeta_query%5D%5B0%5D%5Bquery_total_reviews%5D%5Bkey%5D=_manga_total_votes&vars%5Bmeta_query%5D%5Brelation%5D=AND&vars%5Bpost_type%5D=wp-manga&vars%5Bpost_status%5D=publish&vars%5Bmanga_archives_item_layout%5D=default"
|
||||
private val defaultRequest =
|
||||
"action=madara_load_more&page=1&template=madara-core%2Fcontent%2Fcontent-search&vars%5Bs%5D=&vars%5Borderby%5D=meta_value_num&vars%5Bpaged%5D=1&vars%5Btemplate%5D=search&vars%5Bmeta_query%5D%5B0%5D%5Brelation%5D=AND&vars%5Bmeta_query%5D%5Brelation%5D=OR&vars%5Bpost_type%5D=wp-manga&vars%5Bpost_status%5D=publish&vars%5Bmeta_key%5D=_latest_update&vars%5Border%5D=desc&vars%5Bmanga_archives_item_layout%5D=default"
|
||||
|
||||
private companion object {
|
||||
private fun createRequestTemplate(query : String) =
|
||||
private fun createRequestTemplate(query: String) =
|
||||
(query).split(
|
||||
'&',
|
||||
).map {
|
||||
|
||||
@@ -7,4 +7,6 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("MANGALEK", "MangaLek", "ar")
|
||||
internal class MangaLek(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGALEK, "mangalek.com", pageSize = 20)
|
||||
MadaraParser(context, MangaSource.MANGALEK, "mangalek.com", pageSize = 20) {
|
||||
override val datePattern = "dd-MM-yyyy"
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ internal class BestManhuaCom(context: MangaLoaderContext) :
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -47,9 +47,7 @@ internal class BestManhuaCom(context: MangaLoaderContext) :
|
||||
|
||||
!tags.isNullOrEmpty() -> {
|
||||
append("/$tagPrefix")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
append("/")
|
||||
append(pages.toString())
|
||||
append("?")
|
||||
@@ -67,7 +65,7 @@ internal class BestManhuaCom(context: MangaLoaderContext) :
|
||||
SortOrder.UPDATED -> append("latest-updated")
|
||||
SortOrder.NEWEST -> append("release-date")
|
||||
SortOrder.ALPHABETICAL -> append("name-az")
|
||||
else -> append("latest")
|
||||
SortOrder.RATING -> append("rating")
|
||||
}
|
||||
}
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
|
||||
@@ -28,6 +28,9 @@ internal class Hentai4Free(context: MangaLoaderContext) :
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -43,9 +46,7 @@ internal class Hentai4Free(context: MangaLoaderContext) :
|
||||
|
||||
!tags.isNullOrEmpty() -> {
|
||||
append("/$tagPrefix")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
append("/")
|
||||
if (pages > 1) {
|
||||
append("page/")
|
||||
@@ -65,7 +66,7 @@ internal class Hentai4Free(context: MangaLoaderContext) :
|
||||
SortOrder.UPDATED -> append("latest")
|
||||
SortOrder.NEWEST -> append("new-manga")
|
||||
SortOrder.ALPHABETICAL -> append("alphabet")
|
||||
else -> append("latest")
|
||||
SortOrder.RATING -> append("rating")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ internal class IsekaiScan(context: MangaLoaderContext) :
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -45,10 +46,7 @@ internal class IsekaiScan(context: MangaLoaderContext) :
|
||||
|
||||
!tags.isNullOrEmpty() -> {
|
||||
append("/mangas/")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
|
||||
append(tag?.key.orEmpty())
|
||||
append("?orderby=2&page=")
|
||||
append(pages.toString())
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ internal class IsekaiScanEuParser(context: MangaLoaderContext) :
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -36,9 +37,7 @@ internal class IsekaiScanEuParser(context: MangaLoaderContext) :
|
||||
|
||||
!tags.isNullOrEmpty() -> {
|
||||
append("/$tagPrefix")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
append("/page/")
|
||||
append(pages.toString())
|
||||
append("?")
|
||||
@@ -58,7 +57,7 @@ internal class IsekaiScanEuParser(context: MangaLoaderContext) :
|
||||
SortOrder.UPDATED -> append("latest")
|
||||
SortOrder.NEWEST -> append("new-manga")
|
||||
SortOrder.ALPHABETICAL -> append("alphabet")
|
||||
else -> append("latest")
|
||||
SortOrder.RATING -> append("rating")
|
||||
}
|
||||
}
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
|
||||
@@ -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("JAIMINISBOX", "Jaiminisbox", "en")
|
||||
internal class Jaiminisbox(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.JAIMINISBOX, "jaiminisbox.net")
|
||||
@@ -25,7 +25,7 @@ internal class MangaDass(context: MangaLoaderContext) :
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -42,9 +42,7 @@ internal class MangaDass(context: MangaLoaderContext) :
|
||||
|
||||
!tags.isNullOrEmpty() -> {
|
||||
append("/$tagPrefix")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
append("/")
|
||||
append(pages.toString())
|
||||
append("?")
|
||||
@@ -64,7 +62,7 @@ internal class MangaDass(context: MangaLoaderContext) :
|
||||
SortOrder.UPDATED -> append("latest")
|
||||
SortOrder.NEWEST -> append("new-manga")
|
||||
SortOrder.ALPHABETICAL -> append("alphabet")
|
||||
else -> append("latest")
|
||||
SortOrder.RATING -> append("rating")
|
||||
}
|
||||
}
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
|
||||
@@ -25,7 +25,7 @@ internal class MangaDna(context: MangaLoaderContext) :
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -42,9 +42,7 @@ internal class MangaDna(context: MangaLoaderContext) :
|
||||
|
||||
!tags.isNullOrEmpty() -> {
|
||||
append("/$tagPrefix")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
append("/page/")
|
||||
append(pages.toString())
|
||||
append("?")
|
||||
@@ -64,7 +62,7 @@ internal class MangaDna(context: MangaLoaderContext) :
|
||||
SortOrder.UPDATED -> append("latest")
|
||||
SortOrder.NEWEST -> append("new-manga")
|
||||
SortOrder.ALPHABETICAL -> append("alphabet")
|
||||
else -> append("latest")
|
||||
SortOrder.RATING -> append("rating")
|
||||
}
|
||||
}
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
|
||||
@@ -21,7 +21,7 @@ internal class Manhwaz(context: MangaLoaderContext) :
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -38,9 +38,7 @@ internal class Manhwaz(context: MangaLoaderContext) :
|
||||
|
||||
!tags.isNullOrEmpty() -> {
|
||||
append("/$tagPrefix")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
append("?page=")
|
||||
append(pages.toString())
|
||||
append("&")
|
||||
@@ -60,7 +58,7 @@ internal class Manhwaz(context: MangaLoaderContext) :
|
||||
SortOrder.UPDATED -> append("latest")
|
||||
SortOrder.NEWEST -> append("new-manga")
|
||||
SortOrder.ALPHABETICAL -> append("alphabet")
|
||||
else -> append("latest")
|
||||
SortOrder.RATING -> append("rating")
|
||||
}
|
||||
}
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
|
||||
@@ -14,9 +14,7 @@ import java.util.*
|
||||
internal class DragonTranslationParser(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.DRAGONTRANSLATION, "dragontranslation.net", 30) {
|
||||
|
||||
override val sortOrders: Set<SortOrder> = EnumSet.of(
|
||||
SortOrder.UPDATED,
|
||||
)
|
||||
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
|
||||
|
||||
override val selectPage = "div#chapter_imgs img"
|
||||
|
||||
@@ -27,6 +25,8 @@ internal class DragonTranslationParser(context: MangaLoaderContext) :
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -42,9 +42,7 @@ internal class DragonTranslationParser(context: MangaLoaderContext) :
|
||||
|
||||
!tags.isNullOrEmpty() -> {
|
||||
append("/mangas?tag=")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
append("&page=")
|
||||
append(pages.toString())
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
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("MANGA_CRAB", "Manga Crab", "es")
|
||||
internal class MangaCrab(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANGA_CRAB, "manga-crab.com") {
|
||||
|
||||
override val datePattern = "dd/MM/yyyy"
|
||||
override val tagPrefix = "manga-genero/"
|
||||
override val listUrl = "series/"
|
||||
override val selectChapter = "div.listing-chapters_wrap > ul > li"
|
||||
override val selectDesc = "div.c-page__content div.modal-contenido p"
|
||||
override val selectState = "div.summary-content2"
|
||||
}
|
||||
@@ -15,7 +15,7 @@ import java.text.SimpleDateFormat
|
||||
internal class ManhwaLatino(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANHWALATINO, "manhwa-latino.com", 10) {
|
||||
|
||||
override val datePattern = "MM/dd/yyyy"
|
||||
override val datePattern = "dd 'de' MMMM"
|
||||
override val withoutAjax = true
|
||||
|
||||
|
||||
|
||||
@@ -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("MANTRAZSCAN", "MantrazScan", "es")
|
||||
internal class MantrazScan(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.MANTRAZSCAN, "mantrazscan.com") {
|
||||
|
||||
override val datePattern = "dd/MM/yyyy"
|
||||
override val tagPrefix = "generos-de-manga/"
|
||||
}
|
||||
@@ -19,7 +19,7 @@ internal class MonarcaManga(context: MangaLoaderContext) :
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -36,9 +36,7 @@ internal class MonarcaManga(context: MangaLoaderContext) :
|
||||
|
||||
!tags.isNullOrEmpty() -> {
|
||||
append("/$tagPrefix")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
append("/page/")
|
||||
append(pages.toString())
|
||||
append("?")
|
||||
@@ -58,7 +56,7 @@ internal class MonarcaManga(context: MangaLoaderContext) :
|
||||
SortOrder.UPDATED -> append("latest")
|
||||
SortOrder.NEWEST -> append("new-manga")
|
||||
SortOrder.ALPHABETICAL -> append("alphabet")
|
||||
else -> append("latest")
|
||||
SortOrder.RATING -> append("rating")
|
||||
}
|
||||
}
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
|
||||
@@ -6,11 +6,11 @@ import org.koitharu.kotatsu.parsers.model.ContentType
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("TEMPLESCANESP", "TempleScanEsp", "es" , ContentType.HENTAI)
|
||||
@MangaSourceParser("TEMPLESCANESP", "TempleScanEsp", "es", ContentType.HENTAI)
|
||||
internal class TempleScanEsp(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.TEMPLESCANESP, "templescanesp.com") {
|
||||
|
||||
override val listUrl = "series/"
|
||||
override val listUrl = "series/"
|
||||
override val tagPrefix = "genero/"
|
||||
override val datePattern = "dd.MM.yyyy"
|
||||
}
|
||||
|
||||
@@ -6,6 +6,6 @@ import org.koitharu.kotatsu.parsers.model.ContentType
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
|
||||
@MangaSourceParser("TENKAISCAN", "Tenkai Scan", "es" , ContentType.HENTAI)
|
||||
@MangaSourceParser("TENKAISCAN", "Tenkai Scan", "es", ContentType.HENTAI)
|
||||
internal class TenkaiScan(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.TENKAISCAN, "tenkaiscan.net")
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
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.ContentType
|
||||
import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
import java.util.Locale
|
||||
|
||||
@MangaSourceParser("BIRDTOON", "BirdToon", "id", ContentType.HENTAI)
|
||||
internal class BirdToon(context: MangaLoaderContext) :
|
||||
MadaraParser(context, MangaSource.BIRDTOON, "birdtoon.net", 10) {
|
||||
override val sourceLocale: Locale = Locale.ENGLISH
|
||||
override val tagPrefix = "komik-genre/"
|
||||
override val listUrl = "komik/"
|
||||
}
|
||||
@@ -24,7 +24,7 @@ internal class ManhwaPlus(context: MangaLoaderContext) :
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -41,9 +41,7 @@ internal class ManhwaPlus(context: MangaLoaderContext) :
|
||||
|
||||
!tags.isNullOrEmpty() -> {
|
||||
append("/$tagPrefix")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
append("/page/")
|
||||
append(pages.toString())
|
||||
append("?")
|
||||
|
||||
@@ -35,6 +35,7 @@ internal class HachiManga(context: MangaLoaderContext) : MadaraParser(context, M
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -51,9 +52,7 @@ internal class HachiManga(context: MangaLoaderContext) : MadaraParser(context, M
|
||||
|
||||
!tags.isNullOrEmpty() -> {
|
||||
append("/$tagPrefix")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
append("/")
|
||||
append(pages.toString())
|
||||
append("/")
|
||||
|
||||
@@ -24,8 +24,7 @@ internal class Saytruyenhay(context: MangaLoaderContext) :
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
|
||||
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -42,15 +41,12 @@ internal class Saytruyenhay(context: MangaLoaderContext) :
|
||||
|
||||
!tags.isNullOrEmpty() -> {
|
||||
append("/$tagPrefix")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
append("?page=")
|
||||
append(pages.toString())
|
||||
}
|
||||
|
||||
else -> {
|
||||
|
||||
append("/$listUrl")
|
||||
append("?page=")
|
||||
append(pages.toString())
|
||||
@@ -62,7 +58,7 @@ internal class Saytruyenhay(context: MangaLoaderContext) :
|
||||
SortOrder.UPDATED -> append("latest")
|
||||
SortOrder.NEWEST -> append("new-manga")
|
||||
SortOrder.ALPHABETICAL -> append("alphabet")
|
||||
else -> append("latest")
|
||||
SortOrder.RATING -> append("rating")
|
||||
}
|
||||
}
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
|
||||
@@ -3,7 +3,6 @@ package org.koitharu.kotatsu.parsers.site.manga18
|
||||
import kotlinx.coroutines.async
|
||||
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.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
@@ -54,6 +53,7 @@ internal abstract class Manga18Parser(
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -68,9 +68,7 @@ internal abstract class Manga18Parser(
|
||||
|
||||
!tags.isNullOrEmpty() -> {
|
||||
append("/$tagUrl")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
append("/")
|
||||
append(page.toString())
|
||||
append("?")
|
||||
|
||||
@@ -18,6 +18,7 @@ internal class Hentai3zCc(context: MangaLoaderContext) :
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -33,9 +34,7 @@ internal class Hentai3zCc(context: MangaLoaderContext) :
|
||||
|
||||
!tags.isNullOrEmpty() -> {
|
||||
append("/$tagUrl")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
append("/")
|
||||
append(pages.toString())
|
||||
append("?")
|
||||
|
||||
@@ -50,6 +50,7 @@ internal abstract class MangaboxParser(
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -62,9 +63,7 @@ internal abstract class MangaboxParser(
|
||||
|
||||
} else if (!tags.isNullOrEmpty()) {
|
||||
append("/")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
append("/")
|
||||
append(page.toString())
|
||||
} else {
|
||||
|
||||
@@ -45,6 +45,7 @@ internal class Mangairo(context: MangaLoaderContext) :
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -70,9 +71,7 @@ internal class Mangairo(context: MangaLoaderContext) :
|
||||
|
||||
if (!tags.isNullOrEmpty()) {
|
||||
append("/ctg-")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
} else {
|
||||
append("/ctg-all")
|
||||
}
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
package org.koitharu.kotatsu.parsers.site.mangabox.en
|
||||
|
||||
|
||||
import org.jsoup.nodes.Document
|
||||
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.*
|
||||
import org.koitharu.kotatsu.parsers.site.mangabox.MangaboxParser
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.text.SimpleDateFormat
|
||||
|
||||
|
||||
@MangaSourceParser("MANGAKAKALOT", "Mangakakalot", "en")
|
||||
internal class Mangakakalot(context: MangaLoaderContext) :
|
||||
MangaboxParser(context, MangaSource.MANGAKAKALOT) {
|
||||
|
||||
override val configKeyDomain = ConfigKey.Domain("mangakakalot.com", "chapmanganato.com")
|
||||
|
||||
override val otherDomain = "chapmanganato.com"
|
||||
|
||||
override val listUrl = "/manga_list"
|
||||
|
||||
override suspend fun getListPage(
|
||||
page: Int,
|
||||
query: String?,
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
|
||||
if (!query.isNullOrEmpty()) {
|
||||
append(searchUrl)
|
||||
append(query.replace(" ", "_").urlEncoded())
|
||||
append("?page=")
|
||||
append(page.toString())
|
||||
|
||||
}else {
|
||||
append("$listUrl/")
|
||||
when (sortOrder) {
|
||||
SortOrder.POPULARITY -> append("?type=topview")
|
||||
SortOrder.UPDATED -> append("")
|
||||
SortOrder.NEWEST -> append("?type=newest")
|
||||
else -> append("")
|
||||
}
|
||||
if (!tags.isNullOrEmpty()) {
|
||||
append("&category=")
|
||||
append(tag?.key.orEmpty())
|
||||
}else{
|
||||
append("&category=all")
|
||||
}
|
||||
append("&state=all&page=")
|
||||
append(page)
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
|
||||
return doc.select("div.list-truyen-item-wrap").ifEmpty {
|
||||
doc.select("div.story_item")
|
||||
}.map { div ->
|
||||
val href = div.selectFirstOrThrow("a").attrAsRelativeUrl("href")
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
|
||||
coverUrl = div.selectFirst("img")?.src().orEmpty(),
|
||||
title = div.selectFirstOrThrow("h3").text().orEmpty(),
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getChapters(manga: Manga, doc: Document): List<MangaChapter> {
|
||||
|
||||
return doc.body().select(selectChapter).mapChapters(reversed = true) { i, li ->
|
||||
val a = li.selectFirstOrThrow("a")
|
||||
val href = a.attrAsRelativeUrl("href")
|
||||
val dateText = li.select(selectDate).last()?.text() ?: "0"
|
||||
val dateFormat = if(dateText.contains("-"))
|
||||
{
|
||||
SimpleDateFormat("MMM-dd-yy", sourceLocale)
|
||||
}else
|
||||
{
|
||||
SimpleDateFormat(datePattern, sourceLocale)
|
||||
}
|
||||
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
name = a.text(),
|
||||
number = i + 1,
|
||||
url = href,
|
||||
uploadDate = parseChapterDate(
|
||||
dateFormat,
|
||||
dateText,
|
||||
),
|
||||
source = source,
|
||||
scanlator = null,
|
||||
branch = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -220,13 +220,13 @@ internal abstract class MangaReaderParser(
|
||||
|
||||
protected open val encodedSrc = false
|
||||
protected open val selectScript = "div.wrapper script"
|
||||
|
||||
protected open val selectPage = "div#readerarea img"
|
||||
protected open val selectTestScript = "script:containsData(ts_reader)"
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val chapterUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val docs = webClient.httpGet(chapterUrl).parseHtml()
|
||||
|
||||
val test = docs.select("script:containsData(ts_reader)")
|
||||
val test = docs.select(selectTestScript)
|
||||
if (test.isNullOrEmpty() and !encodedSrc) {
|
||||
return docs.select(selectPage).map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
@@ -257,7 +257,7 @@ internal abstract class MangaReaderParser(
|
||||
.getJSONArray("images")
|
||||
|
||||
} else {
|
||||
val script = docs.selectFirstOrThrow("script:containsData(ts_reader)")
|
||||
val script = docs.selectFirstOrThrow(selectTestScript)
|
||||
JSONObject(script.data().substringAfter('(').substringBeforeLast(')'))
|
||||
.getJSONArray("sources")
|
||||
.getJSONObject(0)
|
||||
|
||||
@@ -7,7 +7,11 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
|
||||
@MangaSourceParser("ASURASCANS", "Asura Scans", "en")
|
||||
internal class AsuraScansParser(context: MangaLoaderContext) :
|
||||
MangaReaderParser(context, MangaSource.ASURASCANS, "asura.gg", pageSize = 20, searchPageSize = 10) {
|
||||
MangaReaderParser(context, MangaSource.ASURASCANS, "asura.nacm.xyz", pageSize = 20, searchPageSize = 10) {
|
||||
|
||||
override val datePattern = "MMM d, yyyy"
|
||||
override val selectPage = "div#readerarea p img"
|
||||
|
||||
// A little dummy text to avoid importing the whole getpage part
|
||||
override val selectTestScript = "Force to parse html"
|
||||
}
|
||||
|
||||
@@ -9,5 +9,5 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
@MangaSourceParser("BIRDMANGA", "Bird Manga", "en")
|
||||
internal class BirdManga(context: MangaLoaderContext) :
|
||||
MangaReaderParser(context, MangaSource.BIRDMANGA, "birdmanga.com", pageSize = 20, searchPageSize = 10) {
|
||||
override val encodedSrc = true
|
||||
override val encodedSrc = true
|
||||
}
|
||||
|
||||
@@ -7,4 +7,4 @@ import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser
|
||||
|
||||
@MangaSourceParser("MIAUSCAN", "Miau Scan", "es")
|
||||
internal class MiauScan(context: MangaLoaderContext) :
|
||||
MangaReaderParser(context, MangaSource.MIAUSCAN, "miauscan.com", pageSize = 20, searchPageSize = 20)
|
||||
MangaReaderParser(context, MangaSource.MIAUSCAN, "miauscans.com", pageSize = 20, searchPageSize = 20)
|
||||
|
||||
@@ -61,7 +61,7 @@ internal abstract class MmrcmsParser(
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = if (sortOrder == SortOrder.UPDATED) {
|
||||
//the Updated page doesn't really exist, we just use the home page to weight the latest chapters, so it doesn't include tag and page management.
|
||||
buildString {
|
||||
@@ -75,23 +75,19 @@ internal abstract class MmrcmsParser(
|
||||
buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
|
||||
append("/$listUrl/")
|
||||
append("?page=")
|
||||
append(page.toString())
|
||||
append("&asc=true&author=&tag=")
|
||||
|
||||
append("&alpha=")
|
||||
|
||||
if (!query.isNullOrEmpty()) {
|
||||
append(query.urlEncoded())
|
||||
}
|
||||
|
||||
append("&cat=")
|
||||
if (!tags.isNullOrEmpty()) {
|
||||
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
}
|
||||
|
||||
append("&sortBy=")
|
||||
|
||||
@@ -146,12 +146,12 @@ class HentaiVNParser(context: MangaLoaderContext) : MangaParser(context, MangaSo
|
||||
val url = "/forum/search-plus.php".toAbsoluteUrl(domain)
|
||||
val docs = webClient.httpGet(url).parseHtml()
|
||||
return docs.selectFirstOrThrow("ul.ul-search").select("li").mapNotNull { el ->
|
||||
MangaTag(
|
||||
title = el.text(),
|
||||
key = el.selectFirst("input")?.attr("value") ?: return@mapNotNull null,
|
||||
source = source,
|
||||
)
|
||||
}.associateBy { it.title }
|
||||
MangaTag(
|
||||
title = el.text(),
|
||||
key = el.selectFirst("input")?.attr("value") ?: return@mapNotNull null,
|
||||
source = source,
|
||||
)
|
||||
}.associateBy { it.title }
|
||||
}
|
||||
|
||||
private fun getSortCookies(sortOrder: SortOrder): Array<String> {
|
||||
@@ -225,19 +225,19 @@ class HentaiVNParser(context: MangaLoaderContext) : MangaParser(context, MangaSo
|
||||
val chaptersEl = webClient.httpGet(chaptersAjax).parseHtml()
|
||||
val chapterDateFormat = SimpleDateFormat("dd/MM/yyyy")
|
||||
return chaptersEl.select("tbody > tr").mapChapters(reversed = true) { index, element ->
|
||||
val titleEl = element.selectFirst("td > a") ?: return@mapChapters null
|
||||
val dateStr = element.selectLast("td")?.text()
|
||||
MangaChapter(
|
||||
id = generateUid(titleEl.attrAsRelativeUrl("href")),
|
||||
name = titleEl.text(),
|
||||
number = index + 1,
|
||||
url = titleEl.attrAsRelativeUrl("href"),
|
||||
scanlator = null,
|
||||
uploadDate = chapterDateFormat.tryParse(dateStr),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
val titleEl = element.selectFirst("td > a") ?: return@mapChapters null
|
||||
val dateStr = element.selectLast("td")?.text()
|
||||
MangaChapter(
|
||||
id = generateUid(titleEl.attrAsRelativeUrl("href")),
|
||||
name = titleEl.text(),
|
||||
number = index + 1,
|
||||
url = titleEl.attrAsRelativeUrl("href"),
|
||||
scanlator = null,
|
||||
uploadDate = chapterDateFormat.tryParse(dateStr),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Element.infoText(title: String) =
|
||||
|
||||
@@ -16,7 +16,6 @@ internal abstract class VmpParser(
|
||||
) : PagedMangaParser(context, source, pageSize) {
|
||||
|
||||
override val configKeyDomain = ConfigKey.Domain(domain)
|
||||
|
||||
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED)
|
||||
|
||||
protected open val listUrl = "xxx/"
|
||||
@@ -33,20 +32,15 @@ internal abstract class VmpParser(
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://$domain/")
|
||||
if(!tags.isNullOrEmpty())
|
||||
{
|
||||
append(geneUrl)
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append("/page/")
|
||||
append(page.toString())
|
||||
|
||||
}else
|
||||
{
|
||||
if (!tags.isNullOrEmpty()) {
|
||||
append(geneUrl)
|
||||
append(tag?.key.orEmpty())
|
||||
append("/page/")
|
||||
append(page.toString())
|
||||
} else {
|
||||
append(listUrl)
|
||||
append("/page/")
|
||||
append(page.toString())
|
||||
@@ -92,10 +86,10 @@ internal abstract class VmpParser(
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val doc= webClient.httpGet(fullUrl).parseHtml()
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
|
||||
manga.copy(
|
||||
tags = doc.select("div.tax_box div.links ul:not(.post-categories) li a").mapNotNullToSet { a ->
|
||||
tags = doc.select("div.tax_box div.links ul:not(.post-categories) li a").mapNotNullToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast(geneUrl, ""),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -55,6 +55,7 @@ internal abstract class WpComicsParser(
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -62,9 +63,7 @@ internal abstract class WpComicsParser(
|
||||
|
||||
if (!tags.isNullOrEmpty()) {
|
||||
append("/")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
}
|
||||
|
||||
append("?page=")
|
||||
|
||||
@@ -8,7 +8,7 @@ import org.koitharu.kotatsu.parsers.site.wpcomics.WpComicsParser
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.util.EnumSet
|
||||
|
||||
@MangaSourceParser("XOXOCOMICS", "Xoxo Comics", "vi", ContentType.COMICS)
|
||||
@MangaSourceParser("XOXOCOMICS", "Xoxo Comics", "en", ContentType.COMICS)
|
||||
internal class XoxoComics(context: MangaLoaderContext) :
|
||||
WpComicsParser(context, MangaSource.XOXOCOMICS, "xoxocomics.net", 50) {
|
||||
|
||||
@@ -28,6 +28,7 @@ internal class XoxoComics(context: MangaLoaderContext) :
|
||||
tags: Set<MangaTag>?,
|
||||
sortOrder: SortOrder,
|
||||
): List<Manga> {
|
||||
val tag = tags.oneOrThrowIfMany()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
append(domain)
|
||||
@@ -41,9 +42,7 @@ internal class XoxoComics(context: MangaLoaderContext) :
|
||||
append(listUrl)
|
||||
if (!tags.isNullOrEmpty()) {
|
||||
append("/")
|
||||
for (tag in tags) {
|
||||
append(tag.key)
|
||||
}
|
||||
append(tag?.key.orEmpty())
|
||||
}
|
||||
|
||||
append("/")
|
||||
|
||||
@@ -7,6 +7,6 @@ import org.koitharu.kotatsu.parsers.model.MangaSource
|
||||
import org.koitharu.kotatsu.parsers.site.zmanga.ZMangaParser
|
||||
|
||||
|
||||
@MangaSourceParser("NEU_MANGA", "Neu Manga", "id")
|
||||
@MangaSourceParser("NEU_MANGA", "Neu Manga Net", "id")
|
||||
internal class NeuManga(context: MangaLoaderContext) :
|
||||
ZMangaParser(context, MangaSource.NEU_MANGA, "neumanga.net")
|
||||
|
||||
Reference in New Issue
Block a user