Remove redundant trim and mapNotNullToSet usage
This commit is contained in:
@@ -210,7 +210,7 @@ internal class BatoToParser(context: MangaLoaderContext) : PagedMangaParser(
|
||||
.requireElementById("mainer")
|
||||
val details = root.selectFirstOrThrow(".detail-set")
|
||||
val attrs = details.selectFirst(".attr-main")?.select(".attr-item")?.associate {
|
||||
it.child(0).text().trim() to it.child(1)
|
||||
it.child(0).text() to it.child(1)
|
||||
}.orEmpty()
|
||||
return manga.copy(
|
||||
title = root.selectFirst("h3.item-title")?.text() ?: manga.title,
|
||||
@@ -227,7 +227,7 @@ internal class BatoToParser(context: MangaLoaderContext) : PagedMangaParser(
|
||||
"Hiatus" -> MangaState.PAUSED
|
||||
else -> manga.state
|
||||
},
|
||||
author = attrs["Authors:"]?.text()?.trim() ?: manga.author,
|
||||
author = attrs["Authors:"]?.textOrNull() ?: manga.author,
|
||||
chapters = root.selectFirst(".episode-list")
|
||||
?.selectFirst(".main")
|
||||
?.children()
|
||||
|
||||
@@ -181,7 +181,7 @@ internal abstract class MangaFireParser(
|
||||
coverUrl = document.selectFirstOrThrow("div.manga-detail div.poster img")
|
||||
.attrAsAbsoluteUrl("src"),
|
||||
tags = document.select("div.meta a[href*=/genre/]").mapNotNullToSet {
|
||||
val tag = it.ownText().trim()
|
||||
val tag = it.ownText()
|
||||
if (tag == "Hentai" || tag == "Ecchi") {
|
||||
isNsfw = true
|
||||
}
|
||||
@@ -189,7 +189,7 @@ internal abstract class MangaFireParser(
|
||||
},
|
||||
isNsfw = isNsfw,
|
||||
state = document.selectFirst(".info > p")?.ownText()?.let {
|
||||
when (it.lowercase().trim()) {
|
||||
when (it.lowercase()) {
|
||||
"releasing" -> MangaState.ONGOING
|
||||
"completed" -> MangaState.FINISHED
|
||||
"discontinued" -> MangaState.ABANDONED
|
||||
@@ -199,7 +199,7 @@ internal abstract class MangaFireParser(
|
||||
}
|
||||
},
|
||||
author = document.select("div.meta a[href*=/author/]")
|
||||
.joinToString { it.ownText().trim() },
|
||||
.joinToString { it.ownText() },
|
||||
description = document.selectFirstOrThrow("#synopsis div.modal-content").html(),
|
||||
chapters = getChapters(manga.url, document),
|
||||
)
|
||||
|
||||
@@ -62,7 +62,7 @@ internal class MangaReaderToParser(context: MangaLoaderContext) :
|
||||
|
||||
document.select("div.f-genre-item").map {
|
||||
MangaTag(
|
||||
title = it.ownText().trim(),
|
||||
title = it.ownText().toTitleCase(sourceLocale),
|
||||
key = it.attr("data-id"),
|
||||
source = source,
|
||||
)
|
||||
@@ -176,7 +176,7 @@ internal class MangaReaderToParser(context: MangaLoaderContext) :
|
||||
?.text()?.toFloatOrNull()?.div(10) ?: RATING_UNKNOWN,
|
||||
coverUrl = document.selectFirst(".manga-poster > img")!!.attr("src"),
|
||||
tags = document.select("div.genres > a[href*=/genre/]").mapNotNullToSet {
|
||||
val tag = it.ownText().trim()
|
||||
val tag = it.ownText()
|
||||
if (tag == "Hentai" || tag == "Ecchi") {
|
||||
isNsfw = true
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ internal abstract class AnimeBootstrapParser(
|
||||
}
|
||||
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectTag).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectTag).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast('='),
|
||||
title = a.text().toTitleCase().replace(",", ""),
|
||||
|
||||
@@ -81,7 +81,7 @@ internal class PapScan(context: MangaLoaderContext) :
|
||||
|
||||
override suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain$listUrl").parseHtml()
|
||||
return doc.select("a.category ").mapNotNullToSet { a ->
|
||||
return doc.select("a.category ").mapToSet { a ->
|
||||
val key = a.attr("href").substringAfterLast('=')
|
||||
val name = a.text()
|
||||
MangaTag(
|
||||
@@ -103,7 +103,7 @@ internal class PapScan(context: MangaLoaderContext) :
|
||||
MangaState.ONGOING
|
||||
}
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectTag).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectTag).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -132,7 +132,7 @@ internal class FlixScans(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
val doc = webClient.httpGet("https://$domain/search/advance").parseHtml()
|
||||
val json = JSONArray(doc.requireElementById("__NUXT_DATA__").data())
|
||||
val tagsList = json.getJSONArray(3).toString().replace("[", "").replace("]", "").split(",")
|
||||
return tagsList.mapNotNullToSet { idTag ->
|
||||
return tagsList.mapToSet { idTag ->
|
||||
val id = idTag.toInt()
|
||||
val idKey = json.getJSONObject(id).getInt("id")
|
||||
val key = json.getInt(idKey).toString()
|
||||
|
||||
@@ -90,7 +90,7 @@ internal class MangaStorm(context: MangaLoaderContext) : PagedMangaParser(contex
|
||||
return manga.copy(
|
||||
altTitle = null,
|
||||
state = null,
|
||||
tags = root.select(".flex-wrap a").mapNotNullToSet { a ->
|
||||
tags = root.select(".flex-wrap a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast('/'),
|
||||
title = a.text(),
|
||||
|
||||
@@ -125,7 +125,7 @@ internal class TeamXNovel(context: MangaLoaderContext) : PagedMangaParser(contex
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/series").parseHtml()
|
||||
return doc.requireElementById("select_genre").select("option").mapNotNullToSet {
|
||||
return doc.requireElementById("select_genre").select("option").mapToSet {
|
||||
MangaTag(
|
||||
key = it.attr("value"),
|
||||
title = it.text().toTitleCase(sourceLocale),
|
||||
@@ -155,7 +155,7 @@ internal class TeamXNovel(context: MangaLoaderContext) : PagedMangaParser(contex
|
||||
"متوقف" -> MangaState.ABANDONED
|
||||
else -> null
|
||||
},
|
||||
tags = doc.select(".review-author-info a").mapNotNullToSet { a ->
|
||||
tags = doc.select(".review-author-info a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast("="),
|
||||
title = a.text(),
|
||||
|
||||
@@ -126,9 +126,9 @@ internal abstract class CupFoxParser(
|
||||
return manga.copy(
|
||||
altTitle = doc.selectFirst(selectMangaDetailsAltTitle)?.text()?.substringAfter(":"),
|
||||
state = null,
|
||||
tags = doc.select(selectMangaDetailsTags).mapNotNullToSet { a ->
|
||||
tags = doc.select(selectMangaDetailsTags).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
@@ -198,9 +198,9 @@ internal abstract class CupFoxParser(
|
||||
protected open suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/category/").parseHtml()
|
||||
return doc.select(selectAvailableTags)
|
||||
.mapNotNullToSet { a ->
|
||||
.mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -92,7 +92,7 @@ internal class BeeToon(context: MangaLoaderContext) :
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/").parseHtml()
|
||||
return doc.requireElementById("menu-item-3").select("ul.sub-menu li a").mapNotNullToSet {
|
||||
return doc.requireElementById("menu-item-3").select("ul.sub-menu li a").mapToSet {
|
||||
MangaTag(
|
||||
key = it.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = it.text(),
|
||||
@@ -106,7 +106,7 @@ internal class BeeToon(context: MangaLoaderContext) :
|
||||
return manga.copy(
|
||||
description = doc.getElementById("desc")?.text().orEmpty(),
|
||||
rating = doc.selectFirst(".counter")?.text()?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
|
||||
tags = doc.body().select(".info .genre a").mapNotNullToSet {
|
||||
tags = doc.body().select(".info .genre a").mapToSet {
|
||||
MangaTag(
|
||||
key = it.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = it.text(),
|
||||
|
||||
@@ -114,7 +114,7 @@ internal class ComicExtra(context: MangaLoaderContext) : PagedMangaParser(contex
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/popular-comic").parseHtml()
|
||||
return doc.select("li.tag-item a").mapNotNullToSet { a ->
|
||||
return doc.select("li.tag-item a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast('/'),
|
||||
title = a.text(),
|
||||
@@ -133,9 +133,9 @@ internal class ComicExtra(context: MangaLoaderContext) : PagedMangaParser(contex
|
||||
"Completed" -> MangaState.FINISHED
|
||||
else -> null
|
||||
},
|
||||
tags = doc.select("dt.movie-dt:contains(Genres:) + dd a").mapNotNullToSet { a ->
|
||||
tags = doc.select("dt.movie-dt:contains(Genres:) + dd a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast("/"),
|
||||
key = a.attr("href").substringAfterLast('/'),
|
||||
title = a.text(),
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -113,7 +113,7 @@ internal class DynastyScans(context: MangaLoaderContext) :
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
coverUrl = "",
|
||||
tags = div.select("span.tags a").mapNotNullToSet { a ->
|
||||
tags = div.select("span.tags a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text(),
|
||||
|
||||
@@ -4,11 +4,7 @@ import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import org.koitharu.kotatsu.parsers.Broken
|
||||
import org.koitharu.kotatsu.parsers.ErrorMessages
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.*
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
@@ -115,7 +111,7 @@ internal class FlixScansOrg(context: MangaLoaderContext) :
|
||||
val doc = webClient.httpGet("https://$domain/search/advance").parseHtml()
|
||||
val json = JSONArray(doc.requireElementById("__NUXT_DATA__").data())
|
||||
val tagsList = json.getJSONArray(3).toString().replace("[", "").replace("]", "").split(",")
|
||||
return tagsList.mapNotNullToSet { idTag ->
|
||||
return tagsList.mapToSet { idTag ->
|
||||
val id = idTag.toInt()
|
||||
val idKey = json.getJSONObject(id).getInt("id")
|
||||
val key = json.getInt(idKey).toString()
|
||||
|
||||
@@ -96,7 +96,7 @@ internal class MangaGeko(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/browse-comics/").parseHtml()
|
||||
return doc.selectFirstOrThrow("div.genre-select-i").select("label").mapNotNullToSet { label ->
|
||||
return doc.selectFirstOrThrow("div.genre-select-i").select("label").mapToSet { label ->
|
||||
MangaTag(
|
||||
key = label.selectFirstOrThrow("input").attr("value"),
|
||||
title = label.text(),
|
||||
@@ -115,9 +115,9 @@ internal class MangaGeko(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
"Completed" -> MangaState.FINISHED
|
||||
else -> null
|
||||
},
|
||||
tags = doc.select(".categories ul li a").mapNotNullToSet { a ->
|
||||
tags = doc.select(".categories ul li a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast("="),
|
||||
key = a.attr("href").substringAfterLast('='),
|
||||
title = a.text(),
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -164,7 +164,7 @@ internal class MangaKawaiiEn(context: MangaLoaderContext) :
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/manga-list/").parseHtml()
|
||||
return doc.select("ul li a.category").mapNotNullToSet { a ->
|
||||
return doc.select("ul li a.category").mapToSet { a ->
|
||||
val name = a.text()
|
||||
val key = name.lowercase().replace(" ", "-").replace("é", "e").replace("è", "e")
|
||||
MangaTag(
|
||||
|
||||
@@ -126,7 +126,7 @@ internal class MangaTownParser(context: MangaLoaderContext) :
|
||||
"completed" -> MangaState.FINISHED
|
||||
else -> null
|
||||
},
|
||||
tags = li.selectFirst("p.keyWord")?.select("a")?.mapNotNullToSet tags@{ x ->
|
||||
tags = li.selectFirst("p.keyWord")?.select("a")?.mapToSet tags@{ x ->
|
||||
MangaTag(
|
||||
title = x.attr("title").toTitleCase(),
|
||||
key = x.attr("href").substringAfter("/directory/0-").substringBefore("-0-"),
|
||||
|
||||
@@ -119,8 +119,8 @@ internal class Mangaowl(context: MangaLoaderContext) :
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/10-genres").parseHtml()
|
||||
return doc.select("div.genres-container span.genre-item a").mapNotNullToSet { a ->
|
||||
val key = a.attr("href").removeSuffix('/').substringAfterLast('/').substringBefore("-")
|
||||
return doc.select("div.genres-container span.genre-item a").mapToSet { a ->
|
||||
val key = a.attr("href").removeSuffix('/').substringAfterLast('/').substringBefore('-')
|
||||
MangaTag(
|
||||
key = key,
|
||||
title = a.text(),
|
||||
@@ -133,9 +133,9 @@ internal class Mangaowl(context: MangaLoaderContext) :
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
manga.copy(
|
||||
tags = doc.body().select("div.comic-attrs div.column.my-2:contains(Genres) a").mapNotNullToSet { a ->
|
||||
tags = doc.body().select("div.comic-attrs div.column.my-2:contains(Genres) a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/').substringBefore("-"),
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/').substringBefore('-'),
|
||||
title = a.text().toTitleCase().replace(",", ""),
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -99,9 +99,9 @@ internal class ManhwasMen(context: MangaLoaderContext) :
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val tags = webClient.httpGet("https://$domain/manga-list").parseHtml()
|
||||
.selectLastOrThrow(".filter-bx .form-group select.custom-select").select("option").drop(1)
|
||||
return tags.mapNotNullToSet { option ->
|
||||
return tags.mapToSet { option ->
|
||||
MangaTag(
|
||||
key = option.attr("value").substringAfterLast("="),
|
||||
key = option.attr("value").substringAfterLast('='),
|
||||
title = option.text(),
|
||||
source = source,
|
||||
)
|
||||
@@ -112,7 +112,7 @@ internal class ManhwasMen(context: MangaLoaderContext) :
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val simpleDateFormat = SimpleDateFormat("dd/MM/yyyy", sourceLocale)
|
||||
return manga.copy(
|
||||
tags = doc.body().select(".genres a").mapNotNullToSet { a ->
|
||||
tags = doc.body().select(".genres a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast('='),
|
||||
title = a.text(),
|
||||
|
||||
@@ -136,7 +136,7 @@ internal class Pururin(context: MangaLoaderContext) :
|
||||
manga.copy(
|
||||
description = doc.selectFirst("p.mb-2")?.text().orEmpty(),
|
||||
rating = doc.selectFirst("td span.rating")?.attr("content")?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
|
||||
tags = doc.body().select("tr:contains(Contents) ul.list-inline a").mapNotNullToSet {
|
||||
tags = doc.body().select("tr:contains(Contents) ul.list-inline a").mapToSet {
|
||||
val href = it.attr("href").substringAfterLast("content/").substringBeforeLast('/')
|
||||
MangaTag(
|
||||
key = href,
|
||||
|
||||
@@ -120,7 +120,7 @@ internal class VyManga(context: MangaLoaderContext) :
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/search").parseHtml()
|
||||
return doc.select("#advance-search .check-genre .d-flex").mapNotNullToSet {
|
||||
return doc.select("#advance-search .check-genre .d-flex").mapToSet {
|
||||
MangaTag(
|
||||
key = it.selectFirstOrThrow(".checkbox-genre").attr("data-value"),
|
||||
title = it.selectFirstOrThrow("label").text(),
|
||||
@@ -133,7 +133,7 @@ internal class VyManga(context: MangaLoaderContext) :
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val simpleDateFormat = SimpleDateFormat("MMM dd, yyy", sourceLocale)
|
||||
return manga.copy(
|
||||
tags = doc.select("div.col-md-7 p a[href*=genre]").mapNotNullToSet { a ->
|
||||
tags = doc.select("div.col-md-7 p a[href*=genre]").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast('/'),
|
||||
title = a.text(),
|
||||
|
||||
@@ -176,9 +176,9 @@ internal class TuMangaOnlineParser(context: MangaLoaderContext) : PagedMangaPars
|
||||
val contents = doc.body().selectFirstOrThrow("section.element-header-content")
|
||||
return manga.copy(
|
||||
description = contents.selectFirst("p.element-description")?.html(),
|
||||
tags = contents.select("h6 a").mapNotNullToSet { a ->
|
||||
tags = contents.select("h6 a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringBefore("&").substringAfterLast("="),
|
||||
key = a.attr("href").substringBefore('&').substringAfterLast('='),
|
||||
title = a.text(),
|
||||
source = source,
|
||||
)
|
||||
@@ -342,7 +342,7 @@ internal class TuMangaOnlineParser(context: MangaLoaderContext) : PagedMangaPars
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/library", getRequestHeaders()).parseHtml()
|
||||
val elements = doc.body().select("div#books-genders > div > div")
|
||||
return elements.mapNotNullToSet { element ->
|
||||
return elements.mapToSet { element ->
|
||||
MangaTag(
|
||||
title = element.select("label").text(),
|
||||
key = element.select("input").attr("value"),
|
||||
|
||||
@@ -159,7 +159,7 @@ internal abstract class FmreaderParser(
|
||||
|
||||
protected open suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/$listUrl").parseHtml()
|
||||
return doc.select(selectBodyTag).mapNotNullToSet { a ->
|
||||
return doc.select(selectBodyTag).mapToSet { a ->
|
||||
val href = a.attr("href").substringAfter(tagPrefix).substringBeforeLast(".html")
|
||||
MangaTag(
|
||||
key = href,
|
||||
@@ -192,7 +192,7 @@ internal abstract class FmreaderParser(
|
||||
val alt = doc.body().selectFirst(selectAlt)?.text()?.replace("Other names", "")
|
||||
val auth = doc.body().selectFirst(selectAut)?.text()
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectTag).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectTag).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfter(tagPrefix).substringBeforeLast(".html"),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -172,7 +172,7 @@ internal class LegacyScansParser(context: MangaLoaderContext) :
|
||||
val dateFormat = SimpleDateFormat("dd/MM/yyyy", Locale.FRENCH)
|
||||
return manga.copy(
|
||||
altTitle = null,
|
||||
tags = root.select("div.serieGenre span").mapNotNullToSet { span ->
|
||||
tags = root.select("div.serieGenre span").mapToSet { span ->
|
||||
MangaTag(
|
||||
key = span.text(),
|
||||
title = span.text(),
|
||||
@@ -221,7 +221,7 @@ internal class LegacyScansParser(context: MangaLoaderContext) :
|
||||
val script = doc.requireElementById("__NUXT_DATA__").data()
|
||||
.substringAfterLast("\"genres\"").substringBeforeLast("\"comics\"")
|
||||
.split("\",\"").drop(1)
|
||||
return script.mapNotNullToSet { tag ->
|
||||
return script.mapToSet { tag ->
|
||||
MangaTag(
|
||||
key = tag.substringBeforeLast("\",{"),
|
||||
title = tag.substringBeforeLast("\",{"),
|
||||
|
||||
@@ -94,7 +94,7 @@ internal class LireScan(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
else -> null
|
||||
},
|
||||
tags = root.select("ul.pmovie__list li:contains(Genre:)").text()
|
||||
.replace("Genre:", "").split(" / ").mapNotNullToSet { tag ->
|
||||
.replace("Genre:", "").split(" / ").mapToSet { tag ->
|
||||
MangaTag(
|
||||
key = tag.lowercase(),
|
||||
title = tag,
|
||||
@@ -142,7 +142,7 @@ internal class LireScan(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/").parseHtml()
|
||||
return doc.select(".nav-menu li a").mapNotNullToSet { a ->
|
||||
return doc.select(".nav-menu li a").mapToSet { a ->
|
||||
val key = a.attr("href").removeSuffix('/').substringAfterLast("manga/", "")
|
||||
MangaTag(
|
||||
key = key,
|
||||
|
||||
@@ -163,7 +163,7 @@ internal class MangaKawaii(context: MangaLoaderContext) : PagedMangaParser(conte
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/manga-list/").parseHtml()
|
||||
return doc.select("ul li a.category").mapNotNullToSet { a ->
|
||||
return doc.select("ul li a.category").mapToSet { a ->
|
||||
val name = a.text()
|
||||
val key = name.lowercase().replace(" ", "-").replace("é", "e").replace("è", "e")
|
||||
MangaTag(
|
||||
|
||||
@@ -186,7 +186,7 @@ internal class MangaMana(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
isNsfw = isNsfw,
|
||||
coverUrl = img.orEmpty(),
|
||||
description = div.selectFirst(".mangalist_item_description")?.text().orEmpty(),
|
||||
tags = div.select("div.mb-1 a").mapNotNullToSet {
|
||||
tags = div.select("div.mb-1 a").mapToSet {
|
||||
val key = it.attr("href").substringAfterLast('=')
|
||||
MangaTag(
|
||||
key = key,
|
||||
@@ -246,7 +246,7 @@ internal class MangaMana(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
author = doc.selectFirst("div.show_details span[itemprop=author]")?.text().orEmpty(),
|
||||
description = doc.selectFirst("dd[itemprop=description]")?.text(),
|
||||
rating = doc.getElementById("avgrating")?.ownText()?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
|
||||
tags = doc.select("ul.list-unstyled li a.category").mapNotNullToSet {
|
||||
tags = doc.select("ul.list-unstyled li a.category").mapToSet {
|
||||
val key = it.attr("href").substringAfterLast('=')
|
||||
MangaTag(
|
||||
key = key,
|
||||
@@ -333,7 +333,7 @@ internal class MangaMana(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/liste-mangas").parseHtml()
|
||||
return doc.select("select.selectpicker option").drop(1).mapNotNullToSet {
|
||||
return doc.select("select.selectpicker option").drop(1).mapToSet {
|
||||
MangaTag(
|
||||
key = it.attr("value"),
|
||||
title = it.text(),
|
||||
|
||||
@@ -97,7 +97,7 @@ internal class ScansMangasMe(context: MangaLoaderContext) :
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/tous-nos-mangas/").parseHtml()
|
||||
return doc.select("ul.genre li").mapNotNullToSet { li ->
|
||||
return doc.select("ul.genre li").mapToSet { li ->
|
||||
val key = li.selectFirstOrThrow("a").attr("href").removeSuffix('/').substringAfterLast('/')
|
||||
val name = li.selectFirstOrThrow("a").text()
|
||||
MangaTag(
|
||||
@@ -116,7 +116,7 @@ internal class ScansMangasMe(context: MangaLoaderContext) :
|
||||
val alt = doc.body().select("div.infox span.alter").text()
|
||||
val aut = doc.select("div.spe span")[2].text().replace("Auteur:", "")
|
||||
manga.copy(
|
||||
tags = doc.select("div.spe span:contains(Genres) a").mapNotNullToSet { a ->
|
||||
tags = doc.select("div.spe span:contains(Genres) a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -130,7 +130,7 @@ internal class ScantradUnion(context: MangaLoaderContext) :
|
||||
"Terminé", "Abondonné", "One Shot" -> MangaState.FINISHED
|
||||
else -> null
|
||||
},
|
||||
tags = root.select("div.project-details a[href*=tag]").mapNotNullToSet { a ->
|
||||
tags = root.select("div.project-details a[href*=tag]").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -193,7 +193,7 @@ internal abstract class FuzzyDoodleParser(
|
||||
},
|
||||
author = doc.selectFirst(selectAuthor)?.text().orEmpty(),
|
||||
description = doc.select(selectDescription).text(),
|
||||
tags = doc.select(selectTagManga).mapNotNullToSet {
|
||||
tags = doc.select(selectTagManga).mapToSet {
|
||||
val key = it.attr("href").substringAfterLast('=')
|
||||
MangaTag(
|
||||
key = key,
|
||||
|
||||
@@ -81,7 +81,7 @@ internal class NHentaiParser(context: MangaLoaderContext) :
|
||||
|
||||
private suspend fun fetchMangaTitle(url: String): String {
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
return doc.selectFirstOrThrow("h1.title").text().trim()
|
||||
return doc.selectFirstOrThrow("h1.title").text()
|
||||
}
|
||||
|
||||
override fun parseMangaList(doc: Document): List<Manga> {
|
||||
|
||||
@@ -81,7 +81,7 @@ internal class HentaiCrot(context: MangaLoaderContext) :
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
return doc.select("ul.megamenu li").mapNotNullToSet { li ->
|
||||
return doc.select("ul.megamenu li").mapToSet { li ->
|
||||
val key = li.selectFirstOrThrow("a").attr("href").removeSuffix('/').substringAfterLast('/')
|
||||
val name = li.selectFirstOrThrow("a").text()
|
||||
MangaTag(
|
||||
|
||||
@@ -81,7 +81,7 @@ internal class PixHentai(context: MangaLoaderContext) :
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
return doc.select("ul.megamenu li").mapNotNullToSet { li ->
|
||||
return doc.select("ul.megamenu li").mapToSet { li ->
|
||||
val key = li.selectFirstOrThrow("a").attr("href").removeSuffix('/').substringAfterLast('/')
|
||||
val name = li.selectFirstOrThrow("a").text()
|
||||
MangaTag(
|
||||
|
||||
@@ -96,7 +96,7 @@ internal class NicovideoSeigaParser(context: MangaLoaderContext) :
|
||||
tags = item.getElementsByAttributeValueContaining("href", "?category=").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast('='),
|
||||
title = a.ownText().trim(),
|
||||
title = a.ownText(),
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
@@ -187,7 +187,7 @@ internal class NicovideoSeigaParser(context: MangaLoaderContext) :
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(item.host ?: domain),
|
||||
title = item.selectFirst(".search_result__item__info > .search_result__item__info--title > a")
|
||||
?.text()?.trim() ?: return@mapNotNull null,
|
||||
?.textOrNull() ?: return@mapNotNull null,
|
||||
altTitle = null,
|
||||
author = null,
|
||||
tags = emptySet(),
|
||||
|
||||
@@ -131,7 +131,7 @@ internal abstract class KeyoappParser(
|
||||
title = div.selectFirstOrThrow("h3").text().orEmpty(),
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = div.select("div.gap-1 a").mapNotNullToSet { a ->
|
||||
tags = div.select("div.gap-1 a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast('='),
|
||||
title = a.text().toTitleCase(),
|
||||
@@ -169,7 +169,7 @@ internal abstract class KeyoappParser(
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectTag).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectTag).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast('='),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -127,9 +127,9 @@ internal abstract class LikeMangaParser(
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/genres/").parseHtml()
|
||||
return doc.select("ul.nav-genres li:not(.text-center) a").mapNotNullToSet { a ->
|
||||
return doc.select("ul.nav-genres li:not(.text-center) a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text(),
|
||||
source = source,
|
||||
)
|
||||
@@ -152,9 +152,9 @@ internal abstract class LikeMangaParser(
|
||||
return manga.copy(
|
||||
altTitle = doc.selectFirstOrThrow(".list-info li.othername h2").text(),
|
||||
state = null,
|
||||
tags = doc.select("li.kind a").mapNotNullToSet { a ->
|
||||
tags = doc.select("li.kind a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -508,7 +508,7 @@ internal abstract class MadaraParser(
|
||||
val keySet = HashSet<String>(list.size)
|
||||
return list.mapNotNullToSet { li ->
|
||||
val a = li.selectFirst("a") ?: return@mapNotNullToSet null
|
||||
val href = a.attr("href").removeSuffix("/").substringAfterLast(tagPrefix, "")
|
||||
val href = a.attr("href").removeSuffix('/').substringAfterLast(tagPrefix, "")
|
||||
if (href.isEmpty() || !keySet.add(href)) {
|
||||
return@mapNotNullToSet null
|
||||
}
|
||||
@@ -560,12 +560,12 @@ internal abstract class MadaraParser(
|
||||
}
|
||||
}
|
||||
|
||||
val alt = doc.body().select(selectAlt).firstOrNull()?.tableValue()?.text()?.trim()
|
||||
val alt = doc.body().select(selectAlt).firstOrNull()?.tableValue()?.textOrNull()
|
||||
|
||||
manga.copy(
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
tags = doc.body().select(selectGenre).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectGenre).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -94,8 +94,8 @@ internal class Manga18Fx(context: MangaLoaderContext) :
|
||||
}
|
||||
MangaTag(
|
||||
key = href,
|
||||
title = a.ownText().trim().ifEmpty {
|
||||
a.selectFirst(".menu-image-title")?.text()?.trim() ?: return@mapNotNullToSet null
|
||||
title = a.ownText().ifEmpty {
|
||||
a.selectFirst(".menu-image-title")?.text() ?: return@mapNotNullToSet null
|
||||
}.toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -100,8 +100,8 @@ internal class Manhwa18Cc(context: MangaLoaderContext) :
|
||||
}
|
||||
MangaTag(
|
||||
key = href,
|
||||
title = a.ownText().trim().ifEmpty {
|
||||
a.selectFirst(".menu-image-title")?.text()?.trim() ?: return@mapNotNullToSet null
|
||||
title = a.ownText().ifEmpty {
|
||||
a.selectFirst(".menu-image-title")?.text() ?: return@mapNotNullToSet null
|
||||
}.toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -15,7 +15,7 @@ import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Base64
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("ADULT_WEBTOON", "AdultWebtoon", "en", ContentType.HENTAI)
|
||||
internal class AdultWebtoon(context: MangaLoaderContext) :
|
||||
@@ -106,11 +106,11 @@ internal class AdultWebtoon(context: MangaLoaderContext) :
|
||||
}
|
||||
|
||||
val alt =
|
||||
doc.body().select(".post-content_item:contains(Alt) .summary-content").firstOrNull()?.tableValue()?.text()
|
||||
?.trim()
|
||||
doc.body().select(".post-content_item:contains(Alt) .summary-content").firstOrNull()?.tableValue()
|
||||
?.textOrNull()
|
||||
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectGenre).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectGenre).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -100,13 +100,13 @@ internal class HentaiManga(context: MangaLoaderContext) :
|
||||
}
|
||||
|
||||
val alt =
|
||||
doc.body().select(".post-content_item:contains(Alt) .summary-content").firstOrNull()?.tableValue()?.text()
|
||||
?.trim()
|
||||
doc.body().select(".post-content_item:contains(Alt) .summary-content").firstOrNull()?.tableValue()
|
||||
?.textOrNull()
|
||||
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectGenre).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectGenre).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -100,13 +100,13 @@ internal class HentaiWebtoon(context: MangaLoaderContext) :
|
||||
}
|
||||
|
||||
val alt =
|
||||
doc.body().select(".post-content_item:contains(Alt) .summary-content").firstOrNull()?.tableValue()?.text()
|
||||
?.trim()
|
||||
doc.body().select(".post-content_item:contains(Alt) .summary-content").firstOrNull()?.tableValue()
|
||||
?.textOrNull()
|
||||
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectGenre).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectGenre).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -93,7 +93,7 @@ internal class IsekaiScan(context: MangaLoaderContext) :
|
||||
)
|
||||
}.orEmpty(),
|
||||
author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(),
|
||||
state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText()?.trim()
|
||||
state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText()
|
||||
?.lowercase()) {
|
||||
"ongoing" -> MangaState.ONGOING
|
||||
"completed " -> MangaState.FINISHED
|
||||
|
||||
@@ -123,12 +123,13 @@ internal class MangaDass(context: MangaLoaderContext) :
|
||||
}
|
||||
|
||||
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()
|
||||
doc.body().select(".post-content_item:contains(Alt) .summary-content").firstOrNull()?.tableValue()
|
||||
?.textOrNull()
|
||||
?: doc.body().select(".post-content_item:contains(Nomes alternativos: ) .summary-content")
|
||||
.firstOrNull()?.tableValue()?.textOrNull()
|
||||
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectGenre).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectGenre).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -116,14 +116,15 @@ internal class MangaDna(context: MangaLoaderContext) :
|
||||
}
|
||||
|
||||
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()
|
||||
doc.body().select(".post-content_item:contains(Alt) .summary-content").firstOrNull()?.tableValue()
|
||||
?.textOrNull()
|
||||
?: doc.body().select(".post-content_item:contains(Nomes alternativos: ) .summary-content")
|
||||
.firstOrNull()?.tableValue()?.textOrNull()
|
||||
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectGenre).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectGenre).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -98,7 +98,7 @@ internal class MangaPure(context: MangaLoaderContext) :
|
||||
)
|
||||
}.orEmpty(),
|
||||
author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(),
|
||||
state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText()?.trim()
|
||||
state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText()
|
||||
?.lowercase()) {
|
||||
"ongoing" -> MangaState.ONGOING
|
||||
"completed" -> MangaState.FINISHED
|
||||
|
||||
@@ -54,12 +54,13 @@ internal class ManhwaHentai(context: MangaLoaderContext) :
|
||||
}
|
||||
|
||||
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()
|
||||
doc.body().select(".post-content_item:contains(Alt) .summary-content").firstOrNull()?.tableValue()
|
||||
?.textOrNull()
|
||||
?: doc.body().select(".post-content_item:contains(Nomes alternativos: ) .summary-content")
|
||||
.firstOrNull()?.tableValue()?.textOrNull()
|
||||
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectGenre).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectGenre).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -103,11 +103,11 @@ internal class ManyToon(context: MangaLoaderContext) :
|
||||
}
|
||||
|
||||
val alt =
|
||||
doc.body().select(".post-content_item:contains(Alt) .summary-content").firstOrNull()?.tableValue()?.text()
|
||||
?.trim()
|
||||
doc.body().select(".post-content_item:contains(Alt) .summary-content").firstOrNull()?.tableValue()
|
||||
?.textOrNull()
|
||||
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectGenre).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectGenre).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -6,12 +6,7 @@ import org.jsoup.nodes.Document
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.exception.ParseException
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaPage
|
||||
import org.koitharu.kotatsu.parsers.model.MangaParserSource
|
||||
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.madara.MadaraParser
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.text.SimpleDateFormat
|
||||
@@ -26,9 +21,9 @@ internal class MangasNoSekai(context: MangaLoaderContext) :
|
||||
val body = doc.body()
|
||||
val chaptersDeferred = async { loadChapters(manga.url, doc) }
|
||||
manga.copy(
|
||||
tags = doc.body().select("#section-sinopsis a[href*=genre]").mapNotNullToSet { a ->
|
||||
tags = doc.body().select("#section-sinopsis a[href*=genre]").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -102,8 +102,8 @@ internal class ManhwaHub(context: MangaLoaderContext) :
|
||||
val href = a.attr("href").removeSuffix("/").substringAfterLast(tagPrefix, "")
|
||||
MangaTag(
|
||||
key = href,
|
||||
title = a.ownText().trim().ifEmpty {
|
||||
a.selectFirst(".menu-image-title")?.text()?.trim() ?: return@mapNotNullToSet null
|
||||
title = a.ownText().ifEmpty {
|
||||
a.selectFirst(".menu-image-title")?.text() ?: return@mapNotNullToSet null
|
||||
}.toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -139,14 +139,15 @@ internal class Saytruyenhay(context: MangaLoaderContext) :
|
||||
}
|
||||
|
||||
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()
|
||||
doc.body().select(".post-content_item:contains(Alt) .summary-content").firstOrNull()?.tableValue()
|
||||
?.textOrNull()
|
||||
?: doc.body().select(".post-content_item:contains(Nomes alternativos: ) .summary-content")
|
||||
.firstOrNull()?.tableValue()?.textOrNull()
|
||||
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectGenre).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectGenre).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -123,7 +123,7 @@ internal abstract class MadthemeParser(
|
||||
title = div.selectFirst("div.meta")?.selectFirst("div.title")?.text().orEmpty(),
|
||||
altTitle = null,
|
||||
rating = div.selectFirst("div.meta span.score")?.ownText()?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
|
||||
tags = doc.body().select("div.meta div.genres span").mapNotNullToSet { span ->
|
||||
tags = doc.body().select("div.meta div.genres span").mapToSet { span ->
|
||||
MangaTag(
|
||||
key = span.attr("class"),
|
||||
title = span.text().toTitleCase(),
|
||||
@@ -179,7 +179,7 @@ internal abstract class MadthemeParser(
|
||||
val nsfw = doc.getElementById("adt-warning") != null
|
||||
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectTag).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectTag).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text().toTitleCase().replace(",", ""),
|
||||
|
||||
@@ -157,7 +157,7 @@ internal abstract class Manga18Parser(
|
||||
val alt = body.selectFirst(selectAlt)?.text().takeIf { it != "Updating" || it.isNotEmpty() }
|
||||
val author = body.selectFirst(selectAuthor)?.text().takeIf { it != "Updating" }
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectTag).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectTag).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -144,7 +144,7 @@ internal abstract class MangaboxParser(
|
||||
protected open suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/$listUrl").parseHtml()
|
||||
val tags = doc.select(selectTagMap).drop(1) // remove all tags
|
||||
return tags.mapNotNullToSet { a ->
|
||||
return tags.mapToSet { a ->
|
||||
val key = a.attr("href").removeSuffix('/').substringAfterLast('/')
|
||||
val name = a.attr("title").replace(" Manga", "")
|
||||
MangaTag(
|
||||
@@ -177,7 +177,7 @@ internal abstract class MangaboxParser(
|
||||
val alt = doc.body().select(selectAlt).text().replace("Alternative : ", "")
|
||||
val aut = doc.body().select(selectAut).eachText().joinToString()
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectTag).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectTag).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast("category=").substringBefore("&"),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -111,7 +111,7 @@ internal class Mangairo(context: MangaLoaderContext) :
|
||||
|
||||
override suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/$listUrl/type-latest/ctg-all/state-all/page-1").parseHtml()
|
||||
return doc.select("div.panel_category a:not(.ctg_select)").mapNotNullToSet { a ->
|
||||
return doc.select("div.panel_category a:not(.ctg_select)").mapToSet { a ->
|
||||
val key = a.attr("href").substringAfterLast("ctg-").substringBefore("/")
|
||||
val name = a.attr("title").replace("Category ", "")
|
||||
MangaTag(
|
||||
@@ -139,7 +139,7 @@ internal class Mangairo(context: MangaLoaderContext) :
|
||||
val alt = doc.body().select(selectAlt).text().replace("Alternative : ", "")
|
||||
val aut = doc.body().select(selectAut).eachText().joinToString()
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectTag).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectTag).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href")
|
||||
.substringAfterLast("page-"), // Yes the site, it's crashing between page is tag id
|
||||
|
||||
@@ -101,7 +101,7 @@ internal class Mangakakalot(context: MangaLoaderContext) :
|
||||
override suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/$listUrl").parseHtml()
|
||||
val tags = doc.select("ul.tag li a").drop(1)
|
||||
return tags.mapNotNullToSet { a ->
|
||||
return tags.mapToSet { a ->
|
||||
val key = a.attr("href").substringAfterLast("category=").substringBefore("&")
|
||||
val name = a.attr("title").replace(" Manga", "")
|
||||
MangaTag(
|
||||
|
||||
@@ -111,7 +111,7 @@ internal class MangakakalotTv(context: MangaLoaderContext) :
|
||||
val alt = doc.body().select(selectAlt).text().replace("Alternative : ", "")
|
||||
val aut = doc.body().select(selectAut).eachText().joinToString()
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectTag).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectTag).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast("category=").substringBefore("&"),
|
||||
title = a.text().toTitleCase(),
|
||||
@@ -131,7 +131,7 @@ internal class MangakakalotTv(context: MangaLoaderContext) :
|
||||
|
||||
override suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/$listUrl").parseHtml()
|
||||
return doc.select(selectTagMap).mapNotNullToSet { a ->
|
||||
return doc.select(selectTagMap).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast("category=").substringBefore("&"),
|
||||
title = a.attr("title"),
|
||||
|
||||
@@ -95,7 +95,7 @@ internal class TuManhwas(context: MangaLoaderContext) :
|
||||
state = mangaState,
|
||||
author = null,
|
||||
isNsfw = manga.isNsfw || nsfw,
|
||||
tags = docs.select(".wd-full .mgen > a").mapNotNullToSet { a ->
|
||||
tags = docs.select(".wd-full .mgen > a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast('='),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -143,7 +143,7 @@ internal abstract class MangaWorldParser(
|
||||
return doc.select(".comics-grid .entry").map { div ->
|
||||
val href = div.selectFirstOrThrow("a.thumb").attrAsRelativeUrl("href")
|
||||
val tags = div.select(".genres a[href*=/archive?genre=]")
|
||||
.mapNotNullToSet { MangaTag(it.ownText().toTitleCase(sourceLocale), it.attr("href"), source) }
|
||||
.mapToSet { MangaTag(it.ownText().toTitleCase(sourceLocale), it.attr("href"), source) }
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
@@ -155,13 +155,13 @@ internal abstract class MangaWorldParser(
|
||||
tags = tags,
|
||||
author = div.selectFirst(".author a")?.text(),
|
||||
state =
|
||||
when (div.selectFirst(".status a")?.text()?.lowercase()) {
|
||||
"in corso" -> MangaState.ONGOING
|
||||
"finito" -> MangaState.FINISHED
|
||||
"droppato" -> MangaState.ABANDONED
|
||||
"in pausa" -> MangaState.PAUSED
|
||||
else -> null
|
||||
},
|
||||
when (div.selectFirst(".status a")?.text()?.lowercase()) {
|
||||
"in corso" -> MangaState.ONGOING
|
||||
"finito" -> MangaState.FINISHED
|
||||
"droppato" -> MangaState.ABANDONED
|
||||
"in pausa" -> MangaState.PAUSED
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
)
|
||||
@@ -171,7 +171,7 @@ internal abstract class MangaWorldParser(
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/").parseHtml()
|
||||
return doc.select("div[aria-labelledby=genresDropdown] a").mapNotNullToSet {
|
||||
return doc.select("div[aria-labelledby=genresDropdown] a").mapToSet {
|
||||
MangaTag(
|
||||
key = it.attr("href").substringAfterLast('='),
|
||||
title = it.text().toTitleCase(sourceLocale),
|
||||
@@ -184,30 +184,30 @@ internal abstract class MangaWorldParser(
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
return manga.copy(
|
||||
altTitle =
|
||||
doc.selectFirst(".meta-data .font-weight-bold:contains(Titoli alternativi:)")
|
||||
?.parent()
|
||||
?.ownText()
|
||||
?.substringAfter(": ")
|
||||
?.trim(),
|
||||
doc.selectFirst(".meta-data .font-weight-bold:contains(Titoli alternativi:)")
|
||||
?.parent()
|
||||
?.ownText()
|
||||
?.substringAfter(": ")
|
||||
?.trim(),
|
||||
description = doc.getElementById("noidungm")?.text().orEmpty(),
|
||||
chapters =
|
||||
doc.select(".chapters-wrapper .chapter a").mapChapters(reversed = true) { i, a ->
|
||||
val url = a.attrAsRelativeUrl("href").toAbsoluteUrl(domain)
|
||||
MangaChapter(
|
||||
id = generateUid(url),
|
||||
name = a.selectFirst("span.d-inline-block")?.text() ?: "Chapter : ${i + 1f}",
|
||||
number = i + 1f,
|
||||
volume = 0,
|
||||
url = "$url?style=list",
|
||||
scanlator = null,
|
||||
uploadDate =
|
||||
SimpleDateFormat("dd MMMM yyyy", Locale.ITALIAN).tryParse(
|
||||
a.selectFirst(".chap-date")?.text(),
|
||||
),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
doc.select(".chapters-wrapper .chapter a").mapChapters(reversed = true) { i, a ->
|
||||
val url = a.attrAsRelativeUrl("href").toAbsoluteUrl(domain)
|
||||
MangaChapter(
|
||||
id = generateUid(url),
|
||||
name = a.selectFirst("span.d-inline-block")?.text() ?: "Chapter : ${i + 1f}",
|
||||
number = i + 1f,
|
||||
volume = 0,
|
||||
url = "$url?style=list",
|
||||
scanlator = null,
|
||||
uploadDate =
|
||||
SimpleDateFormat("dd MMMM yyyy", Locale.ITALIAN).tryParse(
|
||||
a.selectFirst(".chap-date")?.text(),
|
||||
),
|
||||
branch = null,
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -197,7 +197,7 @@ internal abstract class MmrcmsParser(
|
||||
val auth = doc.body().selectFirst(selectAut)?.nextElementSibling()?.text()
|
||||
val tags = doc.body().selectFirst(selectTag)?.nextElementSibling()?.select("a") ?: emptySet()
|
||||
manga.copy(
|
||||
tags = tags.mapNotNullToSet { a ->
|
||||
tags = tags.mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -59,7 +59,7 @@ internal class Onma(context: MangaLoaderContext) :
|
||||
val auth = doc.body().selectFirst(selectAut)?.text()
|
||||
val tags = doc.body().selectFirst(selectTag)?.select("a") ?: emptySet()
|
||||
manga.copy(
|
||||
tags = tags.mapNotNullToSet { a ->
|
||||
tags = tags.mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -201,7 +201,7 @@ internal abstract class NepnepParser(
|
||||
|
||||
else -> null
|
||||
},
|
||||
tags = doc.select(".list-group-item:contains(Genre(s):) a").mapNotNullToSet { a ->
|
||||
tags = doc.select(".list-group-item:contains(Genre(s):) a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast('='),
|
||||
title = a.text(),
|
||||
|
||||
@@ -127,8 +127,8 @@ internal abstract class OtakuSanctuaryParser(
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/Home/LoadingGenresMenu").parseHtml()
|
||||
return doc.select(selectBodyTag).mapNotNullToSet { a ->
|
||||
val href = a.attr("href").substringAfterLast("/").substringBefore("?")
|
||||
return doc.select(selectBodyTag).mapToSet { a ->
|
||||
val href = a.attr("href").substringAfterLast('/').substringBefore('?')
|
||||
MangaTag(
|
||||
key = href,
|
||||
title = a.text(),
|
||||
@@ -165,8 +165,8 @@ internal abstract class OtakuSanctuaryParser(
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectTag).mapNotNullToSet { a ->
|
||||
val href = a.attr("href").substringAfterLast("/").substringBefore("?")
|
||||
tags = doc.body().select(selectTag).mapToSet { a ->
|
||||
val href = a.attr("href").substringAfterLast('/').substringBefore('?')
|
||||
MangaTag(
|
||||
key = href,
|
||||
title = a.text(),
|
||||
|
||||
@@ -110,7 +110,7 @@ internal class BrMangas(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/lista-de-generos-de-manga/").parseHtml()
|
||||
return doc.select(".genres_page a").mapNotNullToSet { a ->
|
||||
return doc.select(".genres_page a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text(),
|
||||
@@ -124,7 +124,7 @@ internal class BrMangas(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
return manga.copy(
|
||||
altTitle = null,
|
||||
state = null,
|
||||
tags = doc.select("div.serie-infos li:contains(Categorias:) a").mapNotNullToSet { a ->
|
||||
tags = doc.select("div.serie-infos li:contains(Categorias:) a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text(),
|
||||
|
||||
@@ -103,9 +103,9 @@ internal class LerManga(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml().requireElementById("menu-header")
|
||||
return doc.select("#menu-item:contains(GÊNERO) ul li a").mapNotNullToSet { a ->
|
||||
return doc.select("#menu-item:contains(GÊNERO) ul li a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast("/"),
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text(),
|
||||
source = source,
|
||||
)
|
||||
@@ -117,9 +117,9 @@ internal class LerManga(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
val dateFormat = SimpleDateFormat("dd-MM-yyyy", sourceLocale)
|
||||
return manga.copy(
|
||||
description = doc.selectFirstOrThrow("div.boxAnimeSobreLast p").html(),
|
||||
tags = doc.selectFirst("ul.genre-list")?.select("li a")?.mapNotNullToSet { a ->
|
||||
tags = doc.selectFirst("ul.genre-list")?.select("li a")?.mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast("/"),
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text(),
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -92,7 +92,7 @@ internal class LerMangaOnline(context: MangaLoaderContext) :
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/").parseHtml().requireElementById("sub-menu")
|
||||
return doc.select("ul.container li a").mapNotNullToSet { a ->
|
||||
return doc.select("ul.container li a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removePrefix("/"),
|
||||
title = a.text(),
|
||||
|
||||
@@ -84,7 +84,7 @@ internal class MangaOnline(context: MangaLoaderContext) : PagedMangaParser(conte
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/generos/").parseHtml()
|
||||
return doc.select(".wp-content p a").mapNotNullToSet { a ->
|
||||
return doc.select(".wp-content p a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast("/", ""),
|
||||
title = a.text(),
|
||||
@@ -98,7 +98,7 @@ internal class MangaOnline(context: MangaLoaderContext) : PagedMangaParser(conte
|
||||
val dateFormat = SimpleDateFormat("dd/MM/yyyy", Locale.ROOT)
|
||||
return manga.copy(
|
||||
description = doc.selectLast(".data p")?.html(),
|
||||
tags = doc.selectFirst(".sgeneros")?.select("a")?.mapNotNullToSet { a ->
|
||||
tags = doc.selectFirst(".sgeneros")?.select("a")?.mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast("/", ""),
|
||||
title = a.text(),
|
||||
|
||||
@@ -79,7 +79,7 @@ internal class MuitoHentai(context: MangaLoaderContext) : PagedMangaParser(conte
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/generos-dos-mangas/").parseHtml()
|
||||
return doc.select("div.content a.profileSideBar").mapNotNullToSet { a ->
|
||||
return doc.select("div.content a.profileSideBar").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast("/"),
|
||||
title = a.text(),
|
||||
@@ -92,7 +92,7 @@ internal class MuitoHentai(context: MangaLoaderContext) : PagedMangaParser(conte
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
return manga.copy(
|
||||
description = doc.selectFirstOrThrow(".backgroundpost:contains(Sinopse)").html(),
|
||||
tags = doc.select("a.genero_btn").mapNotNullToSet { a ->
|
||||
tags = doc.select("a.genero_btn").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast("/"),
|
||||
title = a.text(),
|
||||
|
||||
@@ -493,7 +493,7 @@ internal abstract class GroupleParser(
|
||||
?: throw ParseException("Genres filter element not found", url)
|
||||
val result = MutableScatterMap<String, String>(properties.size)
|
||||
properties.forEach { li ->
|
||||
val name = li.text().trim().lowercase()
|
||||
val name = li.text().lowercase()
|
||||
val id = li.selectFirstOrThrow("input").id()
|
||||
result[name] = id
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ internal class YaoiChanParser(context: MangaLoaderContext) : ChanParser(context,
|
||||
val href = a.attrAsRelativeUrl("href")
|
||||
MangaChapter(
|
||||
id = generateUid(href),
|
||||
name = a.text().trim(),
|
||||
name = a.text(),
|
||||
number = i + 1f,
|
||||
volume = 0,
|
||||
url = href,
|
||||
|
||||
@@ -125,7 +125,7 @@ internal abstract class SinmhParser(
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/$listUrl").parseHtml()
|
||||
return doc.select(".filter-item:contains(按剧情) li a:not(.active)").mapNotNullToSet { a ->
|
||||
return doc.select(".filter-item:contains(按剧情) li a:not(.active)").mapToSet { a ->
|
||||
val href = a.attr("href").removeSuffix('/').substringAfterLast('/')
|
||||
MangaTag(
|
||||
key = href,
|
||||
@@ -152,7 +152,7 @@ internal abstract class SinmhParser(
|
||||
}
|
||||
}
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectGenre).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectGenre).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -150,7 +150,7 @@ internal class TrWebtoon(context: MangaLoaderContext) :
|
||||
val tags =
|
||||
webClient.httpGet("https://$domain/webtoon-listesi").parseHtml().requireElementById("collapseExample")
|
||||
.select(".pt-12 a").drop(1)
|
||||
return tags.mapNotNullToSet { a ->
|
||||
return tags.mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast("genre=").substringBefore("&sort"),
|
||||
title = a.text(),
|
||||
@@ -162,7 +162,7 @@ internal class TrWebtoon(context: MangaLoaderContext) :
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
return manga.copy(
|
||||
tags = doc.body().select("li.movie__year a").mapNotNullToSet { a ->
|
||||
tags = doc.body().select("li.movie__year a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast('='),
|
||||
title = a.text(),
|
||||
|
||||
@@ -120,7 +120,7 @@ internal class BlogTruyenParser(context: MangaLoaderContext) :
|
||||
|
||||
val tagMap = availableTags().associateBy { it.title }
|
||||
val tags = descriptionElement.select("p > span.category").mapNotNullToSet {
|
||||
val tagName = it.selectFirst("a")?.text()?.trim() ?: return@mapNotNullToSet null
|
||||
val tagName = it.selectFirst("a")?.textOrNull() ?: return@mapNotNullToSet null
|
||||
tagMap[tagName]
|
||||
}
|
||||
|
||||
|
||||
@@ -135,8 +135,8 @@ internal class BlogTruyenVN(context: MangaLoaderContext) :
|
||||
val tagItems = doc.select("li[data-id]")
|
||||
val tagMap = ArrayMap<String, MangaTag>(tagItems.size)
|
||||
for (tag in tagItems) {
|
||||
val title = tag.text().trim()
|
||||
tagMap[tag.text().trim()] = MangaTag(
|
||||
val title = tag.text()
|
||||
tagMap[title] = MangaTag(
|
||||
title = title,
|
||||
key = tag.attr("data-id"),
|
||||
source = source,
|
||||
@@ -173,7 +173,7 @@ internal class BlogTruyenVN(context: MangaLoaderContext) :
|
||||
|
||||
val tags = cacheTags.getOrNull()?.let { tagMap ->
|
||||
descriptionElement.select("p > span.category").mapNotNullToSet {
|
||||
val tagName = it.selectFirst("a")?.text()?.trim() ?: return@mapNotNullToSet null
|
||||
val tagName = it.selectFirst("a")?.textOrNull() ?: return@mapNotNullToSet null
|
||||
tagMap[tagName]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,8 +122,8 @@ internal class HentaiVNParser(context: MangaLoaderContext) : MangaParser(context
|
||||
}
|
||||
},
|
||||
rating = docs.selectFirst("div.page_like")?.let {
|
||||
val like = it.selectFirst("div.but_like")?.text()?.trim()?.toIntOrNull() ?: return@let null
|
||||
val dislike = it.selectFirst("div.but_unlike")?.text()?.trim()?.toIntOrNull() ?: return@let null
|
||||
val like = it.selectFirst("div.but_like")?.text()?.toIntOrNull() ?: return@let null
|
||||
val dislike = it.selectFirst("div.but_unlike")?.text()?.toIntOrNull() ?: return@let null
|
||||
when {
|
||||
like == 0 && dislike == 0 -> RATING_UNKNOWN
|
||||
else -> like.toFloat() / (like + dislike)
|
||||
|
||||
@@ -4,8 +4,8 @@ import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.network.UserAgents
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.network.UserAgents
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
@@ -146,7 +146,7 @@ internal class TruyenQQ(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/tim-kiem-nang-cao.html").parseHtml()
|
||||
return doc.select(".advsearch-form div.genre-item").mapNotNullToSet {
|
||||
return doc.select(".advsearch-form div.genre-item").mapToSet {
|
||||
MangaTag(
|
||||
key = it.selectFirstOrThrow("span").attr("data-id"),
|
||||
title = it.text(),
|
||||
@@ -160,7 +160,7 @@ internal class TruyenQQ(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
val dateFormat = SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH)
|
||||
return manga.copy(
|
||||
altTitle = doc.selectFirst("h2.other-name")?.text(),
|
||||
tags = doc.select("ul.list01 li").mapNotNullToSet {
|
||||
tags = doc.select("ul.list01 li").mapToSet {
|
||||
val key = it.attr("href").substringAfterLast("-").substringBeforeLast(".")
|
||||
MangaTag(
|
||||
key = key,
|
||||
|
||||
@@ -98,7 +98,7 @@ internal abstract class VmpParser(
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/$listUrl").parseHtml()
|
||||
return doc.select("div.tagcloud a").mapNotNullToSet { a ->
|
||||
return doc.select("div.tagcloud a").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast(geneUrl, ""),
|
||||
title = a.text().toTitleCase(),
|
||||
@@ -112,7 +112,7 @@ internal abstract class VmpParser(
|
||||
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").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix("/").substringAfterLast(geneUrl, ""),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -130,7 +130,7 @@ internal class XoxoComics(context: MangaLoaderContext) :
|
||||
}
|
||||
val aut = doc.body().select(selectAut).text()
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectTag).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectTag).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -185,7 +185,7 @@ internal abstract class ZeistMangaParser(
|
||||
|
||||
protected open suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
return doc.selectFirstOrThrow("div.filter").select("ul li").mapNotNullToSet {
|
||||
return doc.selectFirstOrThrow("div.filter").select("ul li").mapToSet {
|
||||
MangaTag(
|
||||
key = it.selectFirstOrThrow("input").attr("value"),
|
||||
title = it.selectFirstOrThrow("label").text().toTitleCase(sourceLocale),
|
||||
@@ -225,7 +225,7 @@ internal abstract class ZeistMangaParser(
|
||||
val chaptersDeferred = async { loadChapters(manga.url, doc) }
|
||||
manga.copy(
|
||||
author = author?.text(),
|
||||
tags = doc.select(selectTags).mapNotNullToSet { a ->
|
||||
tags = doc.select(selectTags).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast("label/").substringBefore("?"),
|
||||
title = a.text().toTitleCase(),
|
||||
|
||||
@@ -6,7 +6,7 @@ import org.koitharu.kotatsu.parsers.model.MangaParserSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.mapNotNullToSet
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
import org.koitharu.kotatsu.parsers.util.requireElementById
|
||||
|
||||
@@ -19,7 +19,7 @@ internal class MangaAiLand(context: MangaLoaderContext) :
|
||||
|
||||
override suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
return doc.requireElementById("LinkList1").select("ul li a").mapNotNullToSet {
|
||||
return doc.requireElementById("LinkList1").select("ul li a").mapToSet {
|
||||
MangaTag(
|
||||
key = it.attr("href").substringBefore("?").substringAfterLast('/'),
|
||||
title = it.text(),
|
||||
|
||||
@@ -23,7 +23,7 @@ internal class MangaHub(context: MangaLoaderContext) :
|
||||
|
||||
override suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
return doc.requireElementById("Genre").select("div.items-center").mapNotNullToSet {
|
||||
return doc.requireElementById("Genre").select("div.items-center").mapToSet {
|
||||
MangaTag(
|
||||
key = it.selectFirstOrThrow("input").attr("value"),
|
||||
title = it.selectFirstOrThrow("label").text().substringBefore(')').toTitleCase(sourceLocale),
|
||||
|
||||
@@ -7,7 +7,7 @@ import org.koitharu.kotatsu.parsers.model.MangaParserSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.mapNotNullToSet
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
import org.koitharu.kotatsu.parsers.util.requireElementById
|
||||
|
||||
@@ -17,7 +17,7 @@ internal class KlManhua(context: MangaLoaderContext) :
|
||||
|
||||
override suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
return doc.requireElementById("LinkList1").select("ul li a").mapNotNullToSet {
|
||||
return doc.requireElementById("LinkList1").select("ul li a").mapToSet {
|
||||
MangaTag(
|
||||
key = it.attr("href").substringBefore("?").substringAfterLast('/'),
|
||||
title = it.text(),
|
||||
|
||||
@@ -14,7 +14,7 @@ internal class Mikoroku(context: MangaLoaderContext) :
|
||||
|
||||
override suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
return doc.requireElementById("Genre").select("div.items-center").mapNotNullToSet {
|
||||
return doc.requireElementById("Genre").select("div.items-center").mapToSet {
|
||||
MangaTag(
|
||||
key = it.selectFirstOrThrow("input").attr("value"),
|
||||
title = it.selectFirstOrThrow("label").text().substringBefore('('),
|
||||
|
||||
@@ -6,7 +6,7 @@ import org.koitharu.kotatsu.parsers.model.MangaParserSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.mapNotNullToSet
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
|
||||
@MangaSourceParser("SHIYURASUB", "ShiyuraSub", "id")
|
||||
@@ -17,7 +17,7 @@ internal class ShiyuraSub(context: MangaLoaderContext) :
|
||||
|
||||
override suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
return doc.select("div.list-label-widget-content ul li a").mapNotNullToSet {
|
||||
return doc.select("div.list-label-widget-content ul li a").mapToSet {
|
||||
MangaTag(
|
||||
key = it.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
title = it.html().substringBefore("<span"),
|
||||
|
||||
@@ -16,7 +16,7 @@ internal class ToonCubus(context: MangaLoaderContext) :
|
||||
|
||||
override suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/p/genre-list.html").parseHtml()
|
||||
return doc.select(".dzdes-genre ul li a").mapNotNullToSet {
|
||||
return doc.select(".dzdes-genre ul li a").mapToSet {
|
||||
MangaTag(
|
||||
key = it.attr("href").removeSuffix("/").substringAfterLast("/"),
|
||||
title = it.selectFirstOrThrow("span").text(),
|
||||
|
||||
@@ -19,7 +19,7 @@ internal class AnimeXNovel(context: MangaLoaderContext) :
|
||||
|
||||
override suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
return doc.requireElementById("LinkList1").select("ul li a").mapNotNullToSet {
|
||||
return doc.requireElementById("LinkList1").select("ul li a").mapToSet {
|
||||
MangaTag(
|
||||
key = it.attr("href").removeSuffix("/").substringAfterLast('/'),
|
||||
title = it.text(),
|
||||
|
||||
@@ -6,7 +6,7 @@ import org.koitharu.kotatsu.parsers.model.MangaParserSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.mapNotNullToSet
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
import org.koitharu.kotatsu.parsers.util.requireElementById
|
||||
|
||||
@@ -16,7 +16,7 @@ internal class GuildaTierDraw(context: MangaLoaderContext) :
|
||||
|
||||
override suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
return doc.requireElementById("LinkList2").select("ul li a").mapNotNullToSet {
|
||||
return doc.requireElementById("LinkList2").select("ul li a").mapToSet {
|
||||
MangaTag(
|
||||
key = it.attr("href").substringBefore("?").substringAfterLast('/'),
|
||||
title = it.text(),
|
||||
|
||||
@@ -6,7 +6,7 @@ import org.koitharu.kotatsu.parsers.model.MangaParserSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.mapNotNullToSet
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
import org.koitharu.kotatsu.parsers.util.requireElementById
|
||||
|
||||
@@ -19,7 +19,7 @@ internal class EpikMan(context: MangaLoaderContext) :
|
||||
|
||||
override suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
return doc.requireElementById("LinkList1").select("ul li a").mapNotNullToSet {
|
||||
return doc.requireElementById("LinkList1").select("ul li a").mapToSet {
|
||||
MangaTag(
|
||||
key = it.attr("href").substringBefore("?").substringAfterLast('/'),
|
||||
title = it.text(),
|
||||
|
||||
@@ -7,7 +7,7 @@ import org.koitharu.kotatsu.parsers.model.MangaParserSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.mapNotNullToSet
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
|
||||
@@ -22,7 +22,7 @@ internal class Mikrokosmosfb(context: MangaLoaderContext) :
|
||||
val doc = webClient.httpGet("https://$domain").parseHtml()
|
||||
val tags = doc.selectFirstOrThrow("script:containsData(label: )").data()
|
||||
.substringAfter("label: [").substringBefore("]").replace("\"", "").split(", ")
|
||||
return tags.mapNotNullToSet {
|
||||
return tags.mapToSet {
|
||||
MangaTag(
|
||||
key = it,
|
||||
title = it,
|
||||
|
||||
@@ -7,7 +7,7 @@ import org.koitharu.kotatsu.parsers.model.MangaParserSource
|
||||
import org.koitharu.kotatsu.parsers.model.MangaTag
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.mapNotNullToSet
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
|
||||
@@ -22,7 +22,7 @@ internal class SnscoeurTurkey(context: MangaLoaderContext) :
|
||||
|
||||
override suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/p/gelismis-arama.html").parseHtml()
|
||||
return doc.selectFirstOrThrow("div.filter").select("ul li").mapNotNullToSet {
|
||||
return doc.selectFirstOrThrow("div.filter").select("ul li").mapToSet {
|
||||
MangaTag(
|
||||
key = it.selectFirstOrThrow("input").attr("value"),
|
||||
title = it.selectFirstOrThrow("label").text(),
|
||||
|
||||
@@ -168,7 +168,7 @@ internal abstract class ZMangaParser(
|
||||
altTitle = null,
|
||||
rating = div.selectFirstOrThrow("div.info div.score").ownText().toFloatOrNull()?.div(10f)
|
||||
?: RATING_UNKNOWN,
|
||||
tags = doc.body().select("div.genres a").mapNotNullToSet { span ->
|
||||
tags = doc.body().select("div.genres a").mapToSet { span ->
|
||||
MangaTag(
|
||||
key = span.attr("class"),
|
||||
title = span.text().toTitleCase(),
|
||||
@@ -225,7 +225,7 @@ internal abstract class ZMangaParser(
|
||||
val aut = doc.body().select(selectAut).text()
|
||||
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectTag).mapNotNullToSet { a ->
|
||||
tags = doc.body().select(selectTag).mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
|
||||
title = a.text().toTitleCase().replace(",", ""),
|
||||
|
||||
@@ -27,7 +27,7 @@ public inline fun <T, R> Collection<T>.mapToSet(transform: (T) -> R): Set<R> {
|
||||
return mapTo(ArraySet(size), transform)
|
||||
}
|
||||
|
||||
public inline fun <T, R> Collection<T>.mapNotNullToSet(transform: (T) -> R?): Set<R> {
|
||||
public inline fun <T, R : Any> Collection<T>.mapNotNullToSet(transform: (T) -> R?): Set<R> {
|
||||
val destination = ArraySet<R>(size)
|
||||
for (item in this) {
|
||||
destination.add(transform(item) ?: continue)
|
||||
|
||||
Reference in New Issue
Block a user