Remove redundant trim and mapNotNullToSet usage

master
Koitharu 1 year ago
parent 3ffcefaa1b
commit 08b1241a68
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -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)

Loading…
Cancel
Save