Migrate altTitle to Set<String>

master
Koitharu 1 year ago
parent cdbb004ca1
commit ed578e5bff
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -58,10 +58,10 @@ afterEvaluate {
}
dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.1'
implementation 'com.squareup.okhttp3:okhttp:4.12.0'
implementation 'com.squareup.okio:okio:3.9.0'
api 'org.jsoup:jsoup:1.18.1'
implementation 'com.squareup.okio:okio:3.10.2'
api 'org.jsoup:jsoup:1.18.3'
implementation 'org.json:json:20240303'
implementation 'androidx.collection:collection:1.4.5'
@ -70,7 +70,7 @@ dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.10.1'
testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.10.1'
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.10.1'
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.7.3'
testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.10.1'
testImplementation 'io.webfolder:quickjs:1.1.0'
}

@ -14,5 +14,5 @@ dependencies {
implementation gradleApi()
implementation 'org.simpleframework:simple-xml:2.7.1'
implementation 'com.soywiz.korlibs.korte:korte-jvm:4.0.10'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.9.0'
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.10.1'
}

@ -14,9 +14,9 @@ public data class Manga(
*/
@JvmField public val title: String,
/**
* Alternative title (for example on other language), may be null
* Alternative titles (for example on other language), may be empty
*/
@JvmField public val altTitle: String?,
@JvmField public val altTitles: Set<String>,
/**
* Relative url to manga (**without** a domain) or any other uri.
* Used principally in parsers
@ -140,7 +140,7 @@ public data class Manga(
) : this(
id = id,
title = title,
altTitle = altTitle?.nullIfEmpty(),
altTitles = setOfNotNull(altTitle?.nullIfEmpty()),
url = url,
publicUrl = publicUrl,
rating = rating,
@ -162,6 +162,13 @@ public data class Manga(
public val author: String?
get() = authors.firstOrNull()
/**
* Alternative title (for example on other language), may be null
*/
@Deprecated("Please use altTitles")
public val altTitle: String?
get() = altTitles.firstOrNull()
/**
* Return if manga has a specified rating
* @see rating

@ -7,8 +7,8 @@ import org.jsoup.nodes.Element
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaParserAuthProvider
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.exception.ParseException
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
@ -334,7 +334,7 @@ internal class BatoToParser(context: MangaLoaderContext) : LegacyPagedMangaParse
Manga(
id = generateUid(href),
title = title,
altTitle = div.selectFirst(".item-alias")?.text()?.takeUnless { it == title },
altTitles = setOfNotNull(div.selectFirst(".item-alias")?.textOrNull()?.takeUnless { it == title }),
url = href,
publicUrl = a.absUrl("href"),
rating = RATING_UNKNOWN,

@ -7,8 +7,8 @@ import org.json.JSONArray
import org.json.JSONObject
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.json.*
@ -152,7 +152,7 @@ internal class ComickFunParser(context: MangaLoaderContext) :
Manga(
id = generateUid(slug),
title = jo.getString("title"),
altTitle = null,
altTitles = emptySet(),
url = slug,
publicUrl = "https://$domain/comic/$slug",
rating = jo.getDoubleOrDefault("rating", -10.0).toFloat() / 10f,
@ -179,12 +179,12 @@ internal class ComickFunParser(context: MangaLoaderContext) :
val url = "https://api.$domain/comic/${manga.url}?tachiyomi=true"
val jo = webClient.httpGet(url).parseJson()
val comic = jo.getJSONObject("comic")
val alt = comic.getJSONArray("md_titles").asTypedList<JSONObject>().joinToString("\n") {
it.getStringOrNull("title").orEmpty()
val alt = comic.getJSONArray("md_titles").asTypedList<JSONObject>().mapNotNullToSet {
it.getStringOrNull("title")
}
val author = jo.getJSONArray("artists").optJSONObject(0)?.getStringOrNull("name")
return manga.copy(
altTitle = alt.nullIfEmpty(),
altTitles = alt,
contentRating = if (jo.getBooleanOrDefault("matureContent", false)
|| comic.getBooleanOrDefault("hentai", false)
) {

@ -13,8 +13,8 @@ import org.jsoup.nodes.Element
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaParserAuthProvider
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.exception.AuthRequiredException
import org.koitharu.kotatsu.parsers.exception.TooManyRequestExceptions
import org.koitharu.kotatsu.parsers.model.*
@ -173,7 +173,7 @@ internal class ExHentaiParser(
Manga(
id = generateUid(href),
title = rawTitle.cleanupTitle(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = a.absUrl("href"),
rating = td2.selectFirst("div.ir")?.parseRating() ?: RATING_UNKNOWN,
@ -213,7 +213,7 @@ internal class ExHentaiParser(
return manga.copy(
title = title?.getElementById("gn")?.text()?.cleanupTitle() ?: manga.title,
altTitle = (title?.getElementById("gj")?.text()?.cleanupTitle() ?: manga.altTitle)?.nullIfEmpty(),
altTitles = setOfNotNull(title?.getElementById("gj")?.text()?.cleanupTitle()?.nullIfEmpty()),
publicUrl = doc.baseUri().ifEmpty { manga.publicUrl },
rating = root.getElementById("rating_label")?.text()
?.substringAfterLast(' ')

@ -11,9 +11,9 @@ import org.json.JSONArray
import org.json.JSONObject
import org.jsoup.Jsoup
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.core.LegacyMangaParser
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.json.getStringOrNull
@ -528,7 +528,7 @@ internal class HitomiLaParser(context: MangaLoaderContext) : LegacyMangaParser(c
tags = emptySet(),
contentRating = ContentRating.ADULT,
rating = RATING_UNKNOWN,
altTitle = null,
altTitles = emptySet(),
state = null,
source = source,
)

@ -7,8 +7,8 @@ import kotlinx.coroutines.coroutineScope
import org.jsoup.nodes.Element
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.util.*
@ -122,7 +122,7 @@ internal class ImHentai(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(domain),
coverUrl = a.selectFirst("img")?.src(),
title = div.selectFirst(".caption")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),
@ -200,7 +200,7 @@ internal class ImHentai(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(domain),
coverUrl = a.selectFirst("img")?.src(),
title = div.selectFirst(".caption")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),

@ -6,9 +6,9 @@ import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import org.json.JSONObject
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.core.LegacyMangaParser
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyMangaParser
import org.koitharu.kotatsu.parsers.exception.NotFoundException
import org.koitharu.kotatsu.parsers.exception.ParseException
import org.koitharu.kotatsu.parsers.model.*
@ -126,7 +126,7 @@ internal abstract class LineWebtoonsParser(
Manga(
id = generateUid(titleNo),
title = jo.getString("title"),
altTitle = null,
altTitles = emptySet(),
url = "$titleNo",
publicUrl = "https://$domain/$languageCode/canvas/a/list?title_no=${titleNo}",
rating = jo.getFloatOrDefault("starScoreAverage", -10f) / 10f,
@ -157,7 +157,7 @@ internal abstract class LineWebtoonsParser(
Manga(
id = generateUid(titleNo),
title = jo.getString("title"),
altTitle = null,
altTitles = emptySet(),
url = titleNo.toString(),
publicUrl = "https://$domain/$languageCode/canvas/a/list?title_no=$titleNo",
rating = RATING_UNKNOWN,
@ -203,7 +203,7 @@ internal abstract class LineWebtoonsParser(
Manga(
id = generateUid(titleNo),
title = jo.getString("title"),
altTitle = null,
altTitles = emptySet(),
url = titleNo.toString(),
publicUrl = "https://$domain/$languageCode/canvas/a/list?title_no=$titleNo",
rating = jo.getFloatOrDefault("starScoreAverage", -10f) / 10f,

@ -7,10 +7,10 @@ import kotlinx.coroutines.coroutineScope
import okhttp3.HttpUrl
import org.json.JSONArray
import org.json.JSONObject
import org.koitharu.kotatsu.parsers.core.AbstractMangaParser
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.AbstractMangaParser
import org.koitharu.kotatsu.parsers.exception.ParseException
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.model.search.MangaSearchQuery
@ -353,7 +353,7 @@ internal class MangaDexParser(context: MangaLoaderContext) : AbstractMangaParser
title = requireNotNull(attrs.getJSONObject("title").selectByLocale()) {
"Title should not be null"
},
altTitle = attrs.optJSONArray("altTitles")?.flatten()?.selectByLocale(),
altTitles = setOfNotNull(attrs.optJSONArray("altTitles")?.flatten()?.selectByLocale()), // TODO
url = id,
publicUrl = "https://$domain/title/$id",
rating = RATING_UNKNOWN,

@ -11,9 +11,9 @@ import org.jsoup.nodes.Document
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaParserAuthProvider
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.bitmap.Rect
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.suspendlazy.suspendLazy
@ -163,7 +163,7 @@ internal abstract class MangaFireParser(
title = a.ownText(),
coverUrl = it.selectFirstOrThrow("img").attrAsAbsoluteUrl("src"),
source = source,
altTitle = null,
altTitles = emptySet(),
largeCoverUrl = null,
authors = emptySet(),
contentRating = null,
@ -184,7 +184,7 @@ internal abstract class MangaFireParser(
return manga.copy(
title = document.selectFirstOrThrow(".info > h1").ownText(),
altTitle = document.selectFirst(".info > h6")?.ownTextOrNull(),
altTitles = setOfNotNull(document.selectFirst(".info > h6")?.ownTextOrNull()),
rating = document.selectFirst("div.rating-box")?.attr("data-score")
?.toFloatOrNull()?.div(10) ?: RATING_UNKNOWN,
coverUrl = document.selectFirstOrThrow("div.manga-detail div.poster img")
@ -331,7 +331,7 @@ internal abstract class MangaFireParser(
coverUrl = mangaDocument.selectFirstOrThrow("div.manga-detail div.poster img")
.attrAsAbsoluteUrl("src"),
source = source,
altTitle = null,
altTitles = emptySet(),
largeCoverUrl = null,
authors = emptySet(),
contentRating = null,
@ -354,7 +354,7 @@ internal abstract class MangaFireParser(
title = it.selectFirstOrThrow(".info h6").ownText(),
coverUrl = it.selectFirstOrThrow(".poster img").attrAsAbsoluteUrl("src"),
source = source,
altTitle = null,
altTitles = emptySet(),
largeCoverUrl = null,
authors = emptySet(),
contentRating = null,

@ -4,8 +4,8 @@ import androidx.collection.ArrayMap
import kotlinx.coroutines.coroutineScope
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.suspendlazy.suspendLazy
@ -157,7 +157,7 @@ internal class MangaPark(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src(),
title = div.selectFirst("h3")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = div.selectFirst("span.text-yellow-500")?.text()?.toFloatOrNull()?.div(10F) ?: RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),
@ -195,7 +195,7 @@ internal class MangaPark(context: MangaLoaderContext) :
val dateFormat = SimpleDateFormat("dd/MM/yyyy", sourceLocale)
val author = doc.selectFirst("div[q:key=tz_4]")?.textOrNull()
manga.copy(
altTitle = doc.selectFirst("div[q:key=tz_2]")?.textOrNull(),
altTitles = setOfNotNull(doc.selectFirst("div[q:key=tz_2]")?.textOrNull()),
authors = author?.let { setOf(it) } ?: emptySet(),
description = doc.selectFirst("react-island[q:key=0a_9]")?.html(),
state = when (doc.selectFirst("span[q:key=Yn_5]")?.text()?.lowercase()) {

@ -10,8 +10,8 @@ import org.json.JSONArray
import org.json.JSONObject
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacySinglePageMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacySinglePageMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.json.asTypedList
@ -121,7 +121,7 @@ internal abstract class MangaPlusParser(
publicUrl = "/titles/$titleId".toAbsoluteUrl(domain),
title = name,
coverUrl = it.getString("portraitImageUrl"),
altTitle = null,
altTitles = emptySet(),
authors = setOf(author),
contentRating = null,
rating = RATING_UNKNOWN,

@ -9,10 +9,10 @@ import org.jsoup.nodes.Document
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaParserAuthProvider
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.bitmap.Bitmap
import org.koitharu.kotatsu.parsers.bitmap.Rect
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.suspendlazy.suspendLazy
@ -131,7 +131,7 @@ internal class MangaReaderToParser(context: MangaLoaderContext) :
title = thumb.attr("alt"),
coverUrl = thumb.attr("src"),
source = source,
altTitle = null,
altTitles = emptySet(),
authors = emptySet(),
contentRating = null,
rating = RATING_UNKNOWN,
@ -154,7 +154,7 @@ internal class MangaReaderToParser(context: MangaLoaderContext) :
title = thumb.attr("alt"),
coverUrl = thumb.attrAsAbsoluteUrlOrNull("src"),
source = source,
altTitle = null,
altTitles = emptySet(),
authors = emptySet(),
contentRating = null,
rating = RATING_UNKNOWN,
@ -174,7 +174,7 @@ internal class MangaReaderToParser(context: MangaLoaderContext) :
return manga.copy(
title = document.selectFirst("h2.manga-name")!!.ownText(),
altTitle = document.selectFirst("div.manga-name-or")?.ownTextOrNull(),
altTitles = setOfNotNull(document.selectFirst("div.manga-name-or")?.ownTextOrNull()),
rating = document.selectFirst("div.anisc-info .item:contains(score:) > .name")
?.text()?.toFloatOrNull()?.div(10) ?: RATING_UNKNOWN,
coverUrl = document.selectFirst(".manga-poster > img")?.attrAsAbsoluteUrlOrNull("src"),

@ -8,8 +8,8 @@ import okhttp3.Interceptor
import okhttp3.Response
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.text.SimpleDateFormat
@ -113,7 +113,7 @@ internal abstract class NineMangaParser(
url = relUrl,
publicUrl = href,
title = dd?.selectFirst("a.bookname")?.text()?.toCamelCase().orEmpty(),
altTitle = null,
altTitles = emptySet(),
coverUrl = node.selectFirst("img")?.src(),
rating = RATING_UNKNOWN,
authors = emptySet(),

@ -8,8 +8,8 @@ import org.json.JSONObject
import org.koitharu.kotatsu.parsers.Broken
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.json.asTypedList
@ -200,7 +200,7 @@ internal class NineNineNineHentaiParser(context: MangaLoaderContext) :
Manga(
id = generateUid(id),
title = name.replace(shortenTitleRegex, "").trim(),
altTitle = name,
altTitles = setOf(name),
coverUrl = when {
cover?.startsWith("http") == true -> cover
cover == null -> null
@ -267,7 +267,7 @@ internal class NineNineNineHentaiParser(context: MangaLoaderContext) :
val author = tags?.filter { it.type == "artist" }?.joinToString { it.name.toCamelCase() }?.nullIfEmpty()
return manga.copy(
title = name.replace(shortenTitleRegex, "").trim(),
altTitle = name,
altTitles = setOf(name),
coverUrl = cover.first,
largeCoverUrl = cover.second,
authors = author?.let { setOf(it) } ?: emptySet(),

@ -8,9 +8,9 @@ import okhttp3.HttpUrl.Companion.toHttpUrl
import org.json.JSONArray
import org.json.JSONObject
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.core.LegacyMangaParser
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyMangaParser
import org.koitharu.kotatsu.parsers.exception.NotFoundException
import org.koitharu.kotatsu.parsers.exception.ParseException
import org.koitharu.kotatsu.parsers.model.*
@ -129,7 +129,7 @@ internal abstract class WebtoonsParser(
Manga(
id = generateUid(titleNo),
title = jo.getString("title"),
altTitle = null,
altTitles = emptySet(),
url = "$titleNo",
publicUrl = "https://$domain/$languageCode/originals/a/list?title_no=${titleNo}",
rating = jo.getFloatOrDefault("starScoreAverage", -10f) / 10f,
@ -169,7 +169,7 @@ internal abstract class WebtoonsParser(
publicUrl = "https://$domain/$languageCode/originals/a/list?title_no=$titleNo",
title = jo.getString("title"),
coverUrl = jo.getString("thumbnail").toAbsoluteUrl(staticDomain),
altTitle = null,
altTitles = emptySet(),
authors = author?.let { setOf(it) } ?: emptySet(),
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
rating = jo.getFloatOrDefault("starScoreAverage", -10f) / 10f,
@ -205,7 +205,7 @@ internal abstract class WebtoonsParser(
Manga(
id = generateUid(titleNo),
title = jo.getString("title"),
altTitle = null,
altTitles = emptySet(),
url = titleNo.toString(),
publicUrl = "https://$domain/$languageCode/originals/a/list?title_no=$titleNo",
rating = RATING_UNKNOWN,

@ -5,8 +5,8 @@ import kotlinx.coroutines.coroutineScope
import org.json.JSONArray
import org.jsoup.nodes.Document
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.util.*
@ -107,7 +107,7 @@ internal abstract class AnimeBootstrapParser(
coverUrl = div.selectFirstOrThrow("div.product__item__pic")
.attrAsAbsoluteUrlOrNull("data-setbg"),
title = div.selectFirstOrThrow("div.product__item__text").text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),

@ -69,7 +69,7 @@ internal class PapScan(context: MangaLoaderContext) :
coverUrl = div.selectFirstOrThrow("div.product__item__pic")
.attrAsAbsoluteUrlOrNull("data-setbg"),
title = div.selectFirstOrThrow("div.product__item__text h5").text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),

@ -7,8 +7,8 @@ import org.json.JSONObject
import org.koitharu.kotatsu.parsers.Broken
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.json.mapJSON
@ -109,7 +109,7 @@ internal class FlixScans(context: MangaLoaderContext) :
Manga(
id = generateUid(href),
title = j.getString("title"),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,

@ -3,8 +3,8 @@ package org.koitharu.kotatsu.parsers.site.ar
import org.koitharu.kotatsu.parsers.Broken
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.network.UserAgents
import org.koitharu.kotatsu.parsers.util.*
@ -71,7 +71,7 @@ internal class MangaStorm(context: MangaLoaderContext) :
Manga(
id = generateUid(href),
title = div.select(".manga-ct-title").text(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,

@ -6,8 +6,8 @@ import kotlinx.coroutines.coroutineScope
import org.jsoup.nodes.Element
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.text.SimpleDateFormat
@ -105,7 +105,7 @@ internal class TeamXNovel(context: MangaLoaderContext) :
Manga(
id = generateUid(href),
title = div.select(".tt, h3").text(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,

@ -4,10 +4,10 @@ import androidx.collection.ArraySet
import org.json.JSONArray
import org.json.JSONObject
import org.koitharu.kotatsu.parsers.Broken
import org.koitharu.kotatsu.parsers.core.LegacyMangaParser
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.generateUid
import org.koitharu.kotatsu.parsers.util.getDomain
@ -92,7 +92,7 @@ internal class AnibelParser(context: MangaLoaderContext) : LegacyMangaParser(con
title = title.getString("be"),
coverUrl = jo.getString("poster").removePrefix("/cdn")
.toAbsoluteUrl(getDomain("cdn")) + "?width=200&height=280",
altTitle = title.optJSONArray("alt")?.optString(0)?.nullIfEmpty(),
altTitles = setOfNotNull(title.optJSONArray("alt")?.optString(0)?.nullIfEmpty()),
authors = emptySet(),
contentRating = null,
rating = jo.getDouble("rating").toFloat() / 10f,
@ -144,7 +144,7 @@ internal class AnibelParser(context: MangaLoaderContext) : LegacyMangaParser(con
).getJSONObject("chapters").getJSONArray("docs")
return manga.copy(
title = title.getString("be"),
altTitle = title.optJSONArray("alt")?.optString(0)?.nullIfEmpty(),
altTitles = setOfNotNull(title.optJSONArray("alt")?.optString(0)?.nullIfEmpty()),
coverUrl = "$poster?width=200&height=280",
largeCoverUrl = poster,
description = details.getJSONObject("description").getString("be"),
@ -239,7 +239,7 @@ internal class AnibelParser(context: MangaLoaderContext) : LegacyMangaParser(con
title = title.getString("be"),
coverUrl = jo.getString("poster").removePrefix("/cdn")
.toAbsoluteUrl(getDomain("cdn")) + "?width=200&height=280",
altTitle = title.getString("en").nullIfEmpty(),
altTitles = setOfNotNull(title.getString("en").nullIfEmpty()),
authors = emptySet(),
contentRating = null,
rating = RATING_UNKNOWN,

@ -2,8 +2,8 @@ package org.koitharu.kotatsu.parsers.site.cupfox
import org.jsoup.nodes.Document
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.util.*
@ -95,7 +95,7 @@ internal abstract class CupFoxParser(
Manga(
id = generateUid(href),
title = li.selectFirst("h3, h4, p.dm-bn")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,
@ -124,7 +124,9 @@ internal abstract class CupFoxParser(
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
val author = doc.selectFirst(selectMangaDetailsAuthor)?.text()?.substringAfter("")?.nullIfEmpty()
return manga.copy(
altTitle = doc.selectFirst(selectMangaDetailsAltTitle)?.text()?.substringAfter("")?.nullIfEmpty(),
altTitles = setOfNotNull(
doc.selectFirst(selectMangaDetailsAltTitle)?.text()?.substringAfter("")?.nullIfEmpty(),
),
tags = doc.select(selectMangaDetailsTags).mapToSet { a ->
MangaTag(
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),
@ -161,7 +163,7 @@ internal abstract class CupFoxParser(
Manga(
id = generateUid(href),
title = li.selectFirst("h3, h4, p.dm-bn")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,

@ -6,8 +6,8 @@ import kotlinx.coroutines.sync.withLock
import org.json.JSONObject
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.json.asTypedList
@ -113,7 +113,7 @@ internal class AsuraScansParser(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(domain),
coverUrl = a.selectFirst("img")?.src(),
title = a.selectFirst("div.block > span.block")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = a.selectFirst("div.block label.ml-1")?.text()?.toFloatOrNull()?.div(10f) ?: RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),

@ -2,8 +2,8 @@ package org.koitharu.kotatsu.parsers.site.en
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.text.SimpleDateFormat
@ -75,7 +75,7 @@ internal class BeeToon(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(domain),
coverUrl = div.selectFirst("img")?.src(),
title = div.selectFirst(".name")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = div.selectFirst(".counter")?.text()?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),

@ -2,8 +2,8 @@ package org.koitharu.kotatsu.parsers.site.en
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacySinglePageMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacySinglePageMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.util.*
@ -38,7 +38,7 @@ internal class CloneMangaParser(context: MangaLoaderContext) :
id = generateUid(href),
title = item.selectFirst("h3")?.text() ?: return@mapNotNull null,
coverUrl = "https://$domain/$cover",
altTitle = null,
altTitles = emptySet(),
authors = setOf("Dan Kim"),
rating = RATING_UNKNOWN,
url = href,

@ -2,8 +2,8 @@ package org.koitharu.kotatsu.parsers.site.en
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.network.UserAgents
import org.koitharu.kotatsu.parsers.util.*
@ -71,7 +71,7 @@ internal class ComicExtra(context: MangaLoaderContext) :
Manga(
id = generateUid(href),
title = div.selectFirstOrThrow("a.egb-serie").text(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,
@ -106,7 +106,7 @@ internal class ComicExtra(context: MangaLoaderContext) :
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
val author = doc.selectFirst("table.full-table tr:contains(Author:) td:nth-child(2)")?.textOrNull()
return manga.copy(
altTitle = doc.selectFirstOrThrow("div.anime-top h1.title").textOrNull(),
altTitles = setOfNotNull(doc.selectFirstOrThrow("div.anime-top h1.title").textOrNull()),
state = when (doc.selectFirstOrThrow("ul.anime-genres li.status a").text()) {
"Ongoing" -> MangaState.ONGOING
"Completed" -> MangaState.FINISHED

@ -9,8 +9,8 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.network.UserAgents
import org.koitharu.kotatsu.parsers.util.*
@ -86,7 +86,7 @@ internal class DynastyScans(context: MangaLoaderContext) :
Manga(
id = generateUid(href),
title = div.selectFirstOrThrow("div.caption").text(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,
@ -107,7 +107,7 @@ internal class DynastyScans(context: MangaLoaderContext) :
Manga(
id = generateUid(href),
title = div.selectFirstOrThrow("a").text(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,

@ -6,8 +6,8 @@ import org.json.JSONArray
import org.json.JSONObject
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacySinglePageMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacySinglePageMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.json.*
@ -132,9 +132,9 @@ internal class FlameComics(context: MangaLoaderContext) :
return Manga(
id = generateUid(seriesId),
title = jo.getString("title"),
altTitle = jo.getStringOrNull("altTitles")?.let {
JSONArray(it).optString(0)
},
altTitles = jo.getStringOrNull("altTitles")?.let {
JSONArray(it).toStringSet()
}.orEmpty(),
url = seriesId.toString(),
publicUrl = "https://${domain}/series/$seriesId",
rating = RATING_UNKNOWN,

@ -4,7 +4,10 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import org.json.JSONArray
import org.json.JSONObject
import org.koitharu.kotatsu.parsers.*
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.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
@ -88,7 +91,7 @@ internal class FlixScansOrg(context: MangaLoaderContext) :
Manga(
id = generateUid(href),
title = j.getString("title"),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,

@ -4,8 +4,8 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.text.SimpleDateFormat
@ -82,7 +82,7 @@ internal class MangaGeko(context: MangaLoaderContext) :
Manga(
id = generateUid(href),
title = div.selectFirstOrThrow("h4").text(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,
@ -112,7 +112,7 @@ internal class MangaGeko(context: MangaLoaderContext) :
val chaptersDeferred = async { loadChapters(manga.url) }
val author = doc.selectFirstOrThrow(".author").textOrNull()
manga.copy(
altTitle = doc.selectFirstOrThrow(".alternative-title").textOrNull(),
altTitles = setOfNotNull(doc.selectFirstOrThrow(".alternative-title").textOrNull()),
state = when (doc.selectFirstOrThrow(".header-stats span:contains(Status) strong").text()) {
"Ongoing" -> MangaState.ONGOING
"Completed" -> MangaState.FINISHED

@ -5,8 +5,8 @@ import kotlinx.coroutines.coroutineScope
import okhttp3.Headers
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.util.*
@ -83,7 +83,7 @@ internal class MangaKawaiiEn(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src() ?: a.attrAsAbsoluteUrlOrNull("data-bg"),
title = div.selectFirstOrThrow("h4, .media-thumbnail__name").text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),
@ -102,7 +102,9 @@ internal class MangaKawaiiEn(context: MangaLoaderContext) :
val author = doc.select("a[href*=author]").textOrNull()
manga.copy(
description = doc.selectFirst("dd.text-justify.text-break")?.html(),
altTitle = doc.select("span[itemprop*=alternativeHeadline]").joinToString { ", " }.nullIfEmpty(),
altTitles = doc.select("span[itemprop*=alternativeHeadline]").mapNotNullToSet {
it.textOrNull()
},
authors = author?.let { setOf(it) } ?: emptySet(),
state = when (doc.selectFirst("span.badge.bg-success.text-uppercase")?.text()) {
"Ongoing" -> MangaState.ONGOING

@ -2,8 +2,8 @@ package org.koitharu.kotatsu.parsers.site.en
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.text.DateFormat
@ -118,7 +118,7 @@ internal class MangaTownParser(context: MangaLoaderContext) :
title = a.attr("title"),
coverUrl = a.selectFirst("img")?.attrAsAbsoluteUrlOrNull("src"),
source = MangaParserSource.MANGATOWN,
altTitle = null,
altTitles = emptySet(),
rating = li.selectFirst("p.score")?.selectFirst("b")
?.ownText()?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
authors = author?.let { setOf(it) } ?: emptySet(),

@ -5,8 +5,8 @@ import org.jsoup.nodes.Document
import org.koitharu.kotatsu.parsers.Broken
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.network.UserAgents
import org.koitharu.kotatsu.parsers.util.*
@ -106,7 +106,7 @@ internal class Mangaowl(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src(),
title = div.selectFirst("a.one-line")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = div.select("span").last()?.text()?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),

@ -3,8 +3,8 @@ package org.koitharu.kotatsu.parsers.site.en
import androidx.collection.ArrayMap
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.suspendlazy.suspendLazy
@ -125,7 +125,7 @@ internal class Manhwa18Com(context: MangaLoaderContext) :
Manga(
id = generateUid(absUrl.toRelativeUrl(domain)),
title = titleElement.text(),
altTitle = null,
altTitles = emptySet(),
url = absUrl.toRelativeUrl(domain),
publicUrl = absUrl,
rating = RATING_UNKNOWN,
@ -164,8 +164,10 @@ internal class Manhwa18Com(context: MangaLoaderContext) :
}
return manga.copy(
altTitle = cardInfoElement?.selectFirst("b:contains(Other names)")?.parent()?.ownTextOrNull()
?.removePrefix(": "),
altTitles = setOfNotNull(
cardInfoElement?.selectFirst("b:contains(Other names)")?.parent()?.ownTextOrNull()
?.removePrefix(": "),
),
authors = author?.let { setOf(it) } ?: emptySet(),
description = docs.selectFirst(".series-summary .summary-content")?.html(),
tags = tags.orEmpty(),

@ -3,8 +3,8 @@ package org.koitharu.kotatsu.parsers.site.en
import androidx.collection.ArrayMap
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.suspendlazy.suspendLazy
@ -125,7 +125,7 @@ internal class Manhwa18Parser(context: MangaLoaderContext) :
Manga(
id = generateUid(absUrl.toRelativeUrl(domain)),
title = titleElement.text(),
altTitle = null,
altTitles = emptySet(),
url = absUrl.toRelativeUrl(domain),
publicUrl = absUrl,
rating = RATING_UNKNOWN,
@ -164,8 +164,10 @@ internal class Manhwa18Parser(context: MangaLoaderContext) :
}
return manga.copy(
altTitle = cardInfoElement?.selectFirst("b:contains(Other names)")?.parent()?.ownTextOrNull()
?.removePrefix(": "),
altTitles = setOfNotNull(
cardInfoElement?.selectFirst("b:contains(Other names)")?.parent()?.ownTextOrNull()
?.removePrefix(": "),
),
authors = author?.let { setOf(it) } ?: emptySet(),
description = docs.selectFirst(".series-summary .summary-content")?.html(),
tags = tags.orEmpty(),

@ -2,8 +2,8 @@ package org.koitharu.kotatsu.parsers.site.en
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.text.DateFormat
@ -85,7 +85,7 @@ internal class ManhwasMen(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(domain),
coverUrl = li.selectFirst("img")?.src(),
title = li.selectFirst(".title")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),

@ -2,8 +2,8 @@ package org.koitharu.kotatsu.parsers.site.en
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.util.*
@ -74,7 +74,7 @@ internal class MyComicList(context: MangaLoaderContext) :
url = href,
publicUrl = href.toAbsoluteUrl(domain),
title = div.selectFirst("h3 a")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
authors = emptySet(),
tags = emptySet(),
rating = RATING_UNKNOWN,

@ -3,8 +3,8 @@ package org.koitharu.kotatsu.parsers.site.en
import org.koitharu.kotatsu.parsers.Broken
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacySinglePageMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacySinglePageMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.text.SimpleDateFormat
@ -46,7 +46,7 @@ internal class Po2Scans(context: MangaLoaderContext) :
Manga(
id = generateUid(href),
title = div.selectFirstOrThrow("h2").text(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,

@ -8,8 +8,8 @@ import org.jsoup.nodes.Element
import org.koitharu.kotatsu.parsers.Broken
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.util.*
@ -96,7 +96,7 @@ internal class Pururin(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(domain),
coverUrl = a.selectFirst("img.card-img-top")?.src(),
title = a.selectFirst(".title")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),
@ -173,7 +173,7 @@ internal class Pururin(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(domain),
coverUrl = a.selectFirst("img.card-img-top")?.src(),
title = a.selectFirst(".title")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),

@ -2,8 +2,8 @@ package org.koitharu.kotatsu.parsers.site.en
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.text.DateFormat
@ -107,7 +107,7 @@ internal class VyManga(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(domain),
coverUrl = div.selectFirst(".comic-image img")?.src(),
title = div.selectFirst(".comic-title")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),

@ -7,7 +7,6 @@ import okhttp3.HttpUrl.Companion.toHttpUrl
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaParser
import org.koitharu.kotatsu.parsers.MangaParserAuthProvider
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
@ -186,7 +185,7 @@ internal class WeebCentral(context: MangaLoaderContext) : LegacyMangaParser(cont
url = mangaId,
publicUrl = "https://$domain/series/$mangaId",
title = element.selectFirstOrThrow("abbr[title] > a").text(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
contentRating = if (element.selectFirst("svg:has(style:containsData(ff0000))") == null) {
SAFE
@ -233,8 +232,8 @@ internal class WeebCentral(context: MangaLoaderContext) : LegacyMangaParser(cont
manga.copy(
title = sectionRight.selectFirstOrThrow("h1").text(),
altTitle = sectionRight.select("li:has(strong:contains(Associated Name)) li")
.eachText().joinToString(),
altTitles = sectionRight.select("li:has(strong:contains(Associated Name)) li")
.eachText().toSet(),
publicUrl = "https://$domain/series/${manga.url}",
rating = RATING_UNKNOWN,
contentRating = if (sectionLeft.selectFirst("ul > li > strong:contains(Official Translation) + a:contains(Yes)") != null) {

@ -3,8 +3,8 @@ package org.koitharu.kotatsu.parsers.site.es
import kotlinx.coroutines.coroutineScope
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacySinglePageMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacySinglePageMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.network.UserAgents
import org.koitharu.kotatsu.parsers.util.*
@ -44,7 +44,7 @@ internal class TempleScanEsp(context: MangaLoaderContext) :
publicUrl = href,
coverUrl = it.getString("urlImg"),
title = it.getString("name").orEmpty(),
altTitle = it.getStringOrNull("alternativeName"),
altTitles = setOfNotNull(it.getStringOrNull("alternativeName")),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),

@ -6,8 +6,8 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.text.SimpleDateFormat
@ -158,7 +158,7 @@ internal class TuMangaOnlineParser(context: MangaLoaderContext) : LegacyPagedMan
id = generateUid(href),
title = item.selectFirst("h4.text-truncate")?.text() ?: return@mapNotNull null,
coverUrl = item.select("style").toString().substringAfter("('").substringBeforeLast("')"),
altTitle = null,
altTitles = emptySet(),
authors = emptySet(),
rating = item.selectFirst("span.score")?.text()?.toFloatOrNull()?.div(10F) ?: RATING_UNKNOWN,
url = href,

@ -4,8 +4,8 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import org.jsoup.nodes.Document
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.text.DateFormat
@ -144,7 +144,7 @@ internal abstract class FmreaderParser(
?: div.selectFirst("div.img-in-ratio")?.attr("style")?.substringAfter("(")
?.substringBefore(")"))?.toAbsoluteUrl(domain),
title = div.selectFirst("div.series-title")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),
@ -200,8 +200,8 @@ internal abstract class FmreaderParser(
)
},
description = desc,
altTitle = alt,
authors = author?.let { setOf(it) } ?: emptySet(),
altTitles = setOfNotNull(alt),
authors = setOfNotNull(author),
state = state,
chapters = chaptersDeferred.await(),
)

@ -32,7 +32,7 @@ internal class Klz9(context: MangaLoaderContext) :
coverUrl = div.selectFirstOrThrow("div.img-in-ratio").attr("style").substringAfter("('")
.substringBeforeLast("')"),
title = div.selectFirstOrThrow("div.series-title").text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),

@ -4,8 +4,8 @@ import kotlinx.coroutines.coroutineScope
import org.json.JSONArray
import org.jsoup.nodes.Document
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.text.SimpleDateFormat
@ -90,7 +90,7 @@ internal abstract class FoolSlideParser(
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src(),// in search no img
title = div.selectFirst(".title a")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),

@ -8,8 +8,8 @@ import org.jsoup.nodes.Element
import org.koitharu.kotatsu.parsers.Broken
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.exception.ParseException
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
@ -115,7 +115,7 @@ internal class BentomangaParser(context: MangaLoaderContext) :
Manga(
id = generateUid(href),
title = div.selectFirst("h1")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = div.getElementsByAttributeValue("data-icon", "avg_rate")
@ -150,7 +150,7 @@ internal class BentomangaParser(context: MangaLoaderContext) :
.requireElementById("container_manga_show")
val author = root.selectFirst(".datas_more-authors-people")?.textOrNull()
return manga.copy(
altTitle = root.selectFirst(".component-manga-title_alt")?.textOrNull(),
altTitles = setOfNotNull(root.selectFirst(".component-manga-title_alt")?.textOrNull()),
description = root.selectFirst(".datas_synopsis")?.html().assertNotNull("description")
?: manga.description,
state = when (root.selectFirst(".datas_more-status-data")?.textOrNull().assertNotNull("status")) {

@ -5,8 +5,8 @@ import org.jsoup.nodes.Document
import org.koitharu.kotatsu.parsers.ErrorMessages
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacySinglePageMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacySinglePageMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.network.UserAgents
import org.koitharu.kotatsu.parsers.util.*
@ -71,7 +71,7 @@ internal class FuryoSociety(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src(),
title = (div.selectFirst("div.media-body") ?: div.selectFirst("a"))?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),

@ -4,8 +4,8 @@ import org.json.JSONArray
import org.json.JSONObject
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.json.mapJSON
@ -132,7 +132,7 @@ internal class LegacyScansParser(context: MangaLoaderContext) :
Manga(
id = generateUid(urlManga),
title = j.getString("title"),
altTitle = null,
altTitles = emptySet(),
url = urlManga,
publicUrl = urlManga,
rating = RATING_UNKNOWN,
@ -153,7 +153,7 @@ internal class LegacyScansParser(context: MangaLoaderContext) :
Manga(
id = generateUid(urlManga),
title = j.getString("title"),
altTitle = null,
altTitles = emptySet(),
url = urlManga,
publicUrl = urlManga,
rating = RATING_UNKNOWN,

@ -3,8 +3,8 @@ package org.koitharu.kotatsu.parsers.site.fr
import org.koitharu.kotatsu.parsers.Broken
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.text.SimpleDateFormat
@ -68,7 +68,7 @@ internal class LireScan(context: MangaLoaderContext) : LegacyPagedMangaParser(co
Manga(
id = generateUid(href),
title = div.select(".item-poster__title").text(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = div.selectFirstOrThrow(".item__rating").ownText().toFloatOrNull()?.div(10f) ?: RATING_UNKNOWN,
@ -89,8 +89,10 @@ internal class LireScan(context: MangaLoaderContext) : LegacyPagedMangaParser(co
.replace("Artist(s):", "")
.nullIfEmpty()
return manga.copy(
altTitle = root.select("ul.pmovie__list li:contains(Nom Alternatif:)").text()
.replace("Nom Alternatif:", "").nullIfEmpty(),
altTitles = setOfNotNull(
root.select("ul.pmovie__list li:contains(Nom Alternatif:)").text()
.replace("Nom Alternatif:", "").nullIfEmpty(),
),
state = when (root.select("ul.pmovie__list li:contains(Status:)").text()) {
"Status: OnGoing", "Status: En cours" -> MangaState.ONGOING
"Status: Fini" -> MangaState.FINISHED

@ -4,8 +4,8 @@ import org.json.JSONArray
import org.koitharu.kotatsu.parsers.ErrorMessages
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.network.UserAgents
import org.koitharu.kotatsu.parsers.util.*
@ -107,7 +107,7 @@ internal class LugnicaScans(context: MangaLoaderContext) :
Manga(
id = generateUid(urlManga),
title = j.getString("manga_title"),
altTitle = null,
altTitles = emptySet(),
url = urlManga.toRelativeUrl(domain),
publicUrl = urlManga.toAbsoluteUrl(domain),
rating = j.getFloatOrDefault("manga_rate", RATING_UNKNOWN).div(5f),
@ -128,7 +128,7 @@ internal class LugnicaScans(context: MangaLoaderContext) :
Manga(
id = generateUid(urlManga),
title = j.getString("title"),
altTitle = null,
altTitles = emptySet(),
url = urlManga.toRelativeUrl(domain),
publicUrl = urlManga.toAbsoluteUrl(domain),
rating = j.getString("rate").toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,

@ -5,8 +5,8 @@ import kotlinx.coroutines.coroutineScope
import okhttp3.Headers
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.util.*
@ -83,7 +83,7 @@ internal class MangaKawaii(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src() ?: a.attrAsAbsoluteUrlOrNull("data-bg"),
title = div.selectFirst("h4, .media-thumbnail__name")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),
@ -99,11 +99,14 @@ internal class MangaKawaii(context: MangaLoaderContext) :
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
val firstChapter = doc.selectFirst("tr[class*='volume-'] a")?.attr("href")
val chaptersDeferred = async { loadChapters(firstChapter) }
val author = doc.select("a[href*=author]").text()
val author = doc.select("a[href*=author]").textOrNull()
manga.copy(
description = doc.selectFirst("dd.text-justify.text-break")?.html(),
altTitle = doc.select("span[itemprop*=alternativeHeadline]").joinToString { ", " }.nullIfEmpty(),
authors = author?.let { setOf(it) } ?: emptySet(),
altTitles = setOfNotNull(
doc.select("span[itemprop*=alternativeHeadline]").joinToString { ", " }
.nullIfEmpty(),
),
authors = setOfNotNull(author),
state = when (doc.selectFirst("span.badge.bg-success.text-uppercase")?.text()) {
"En Cours" -> MangaState.ONGOING
"Terminé" -> MangaState.FINISHED

@ -11,12 +11,13 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.exception.ParseException
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.json.getIntOrDefault
import org.koitharu.kotatsu.parsers.util.json.getStringOrNull
import org.koitharu.kotatsu.parsers.util.json.mapJSON
import java.text.SimpleDateFormat
import java.util.*
@ -78,7 +79,7 @@ internal class MangaMana(context: MangaLoaderContext) :
id = generateUid(url),
title = jo.getString("name").orEmpty(),
coverUrl = img,
altTitle = jo.getString("otherNames").orEmpty(),
altTitles = setOfNotNull(jo.getStringOrNull("otherNames")),
authors = emptySet(),
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
rating = RATING_UNKNOWN,
@ -109,7 +110,8 @@ internal class MangaMana(context: MangaLoaderContext) :
val doc = webClient.httpGet("https://$domain/?page=$page").parseHtml()
return doc.select("div.row div.col_home").map { div ->
val href = div.selectFirstOrThrow("h4 a").attrAsRelativeUrl("href")
val isNsfwSource = div.selectFirst("img[data-adult]")?.attr("data-adult")?.isNotEmpty() == true
val isNsfwSource =
div.selectFirst("img[data-adult]")?.attr("data-adult")?.isNotEmpty() == true
val img = if (isNsfwSource) {
div.selectFirst("img")?.attr("data-adult")
} else {
@ -118,7 +120,7 @@ internal class MangaMana(context: MangaLoaderContext) :
Manga(
id = generateUid(href),
title = div.select("h4").text(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,
@ -181,7 +183,7 @@ internal class MangaMana(context: MangaLoaderContext) :
Manga(
id = generateUid(href),
title = div.select("h2.fs-6").text(),
altTitle = doc.selectFirst(".mangalist_item_othernames")?.text().orEmpty(),
altTitles = setOfNotNull(doc.selectFirst(".mangalist_item_othernames")?.textOrNull()),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = div.getElementById("avgrating")?.ownText()?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,

@ -6,8 +6,8 @@ import org.jsoup.nodes.Document
import org.koitharu.kotatsu.parsers.Broken
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacySinglePageMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacySinglePageMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.network.UserAgents
import org.koitharu.kotatsu.parsers.util.*
@ -83,7 +83,7 @@ internal class ScansMangasMe(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src(),
title = div.selectFirstOrThrow("div.bigor div.tt").text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = div.selectFirstOrThrow("div.rating i").ownText().toFloatOrNull()?.div(10f)
?: RATING_UNKNOWN,
tags = emptySet(),
@ -124,8 +124,8 @@ internal class ScansMangasMe(context: MangaLoaderContext) :
)
},
description = desc,
altTitle = alt,
authors = author?.let { setOf(it) } ?: emptySet(),
altTitles = setOfNotNull(alt),
authors = setOfNotNull(author),
state = when (doc.selectFirstOrThrow("div.spe span:contains(Statut:)").textOrNull()
?.substringAfterLast(':')) {
" En cours" -> MangaState.ONGOING

@ -2,8 +2,8 @@ package org.koitharu.kotatsu.parsers.site.fr
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.exception.ParseException
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.network.UserAgents
@ -84,7 +84,7 @@ internal class ScantradUnion(context: MangaLoaderContext) :
Manga(
id = generateUid(href),
title = article.select(".carteinfos a").text(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,
@ -104,7 +104,7 @@ internal class ScantradUnion(context: MangaLoaderContext) :
Manga(
id = generateUid(href),
title = article.select(".index-post-header a").text(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,
@ -125,7 +125,7 @@ internal class ScantradUnion(context: MangaLoaderContext) :
val author = root.select("div.project-details a[href*=auteur]").textOrNull()
return manga.copy(
altTitle = root.select(".divider2:contains(Noms associés :)").firstOrNull()?.textOrNull(),
altTitles = setOfNotNull(root.select(".divider2:contains(Noms associés :)").firstOrNull()?.textOrNull()),
state = when (root.select(".label.label-primary")[2].text()) {
"En cours" -> MangaState.ONGOING
"Terminé", "Abondonné", "One Shot" -> MangaState.FINISHED

@ -7,8 +7,8 @@ import kotlinx.coroutines.coroutineScope
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.text.DateFormat
@ -149,7 +149,7 @@ internal abstract class FuzzyDoodleParser(
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src(),
title = div.selectFirst("h2")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),
@ -184,7 +184,7 @@ internal abstract class FuzzyDoodleParser(
val author = doc.selectFirst(selectAuthor)?.textOrNull()
manga.copy(
altTitle = doc.selectLast(selectAltTitle)?.textOrNull(),
altTitles = setOfNotNull(doc.selectLast(selectAltTitle)?.textOrNull()),
state = when (doc.selectFirst(selectState)?.text()?.lowercase().orEmpty()) {
in ongoing -> MangaState.ONGOING
in finished -> MangaState.FINISHED

@ -8,8 +8,8 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.koitharu.kotatsu.parsers.ErrorMessages
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.util.*
@ -109,7 +109,7 @@ internal abstract class GalleryAdultsParser(
Manga(
id = generateUid(href),
title = div.select(selectGalleryTitle).text().cleanupTitle(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,

@ -39,7 +39,7 @@ internal class DoujinDesuUk(context: MangaLoaderContext) :
title = div.select(selectGalleryTitle).text().replace(regexBrackets, "")
.replace(regexSpaces, " ")
.trim(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,

@ -90,7 +90,7 @@ internal class NHentaiParser(context: MangaLoaderContext) :
Manga(
id = generateUid(href),
title = div.select(selectGalleryTitle).text().cleanupTitle(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,

@ -80,7 +80,7 @@ internal class NHentaiToParser(context: MangaLoaderContext) :
Manga(
id = generateUid(href),
title = div.select(selectGalleryTitle).text().cleanupTitle(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,

@ -93,7 +93,7 @@ internal class NHentaiXxxParser(context: MangaLoaderContext) :
Manga(
id = generateUid(href),
title = div.select(selectGalleryTitle).text().cleanupTitle(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,

@ -3,8 +3,8 @@ package org.koitharu.kotatsu.parsers.site.gattsu
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.util.*
@ -79,7 +79,7 @@ internal abstract class GattsuParser(
publicUrl = href,
title = li.selectLast(".thumb-titulo, .video-titulo")?.text().orEmpty(),
coverUrl = li.selectFirst("img")?.src(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
description = null,

@ -5,7 +5,10 @@ import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.site.gattsu.GattsuParser
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.attrAsAbsoluteUrl
import org.koitharu.kotatsu.parsers.util.generateUid
import org.koitharu.kotatsu.parsers.util.selectLastOrThrow
import org.koitharu.kotatsu.parsers.util.src
@MangaSourceParser("MUNDOHENTAIOFICIAL", "MundoHentaiOficial", "pt", ContentType.HENTAI)
internal class MundoHentaiOficial(context: MangaLoaderContext) :
@ -27,7 +30,7 @@ internal class MundoHentaiOficial(context: MangaLoaderContext) :
publicUrl = href,
title = li.selectLastOrThrow(".thumb-titulo, .video-titulo").text(),
coverUrl = li.selectFirst("img")?.src(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
description = null,

@ -2,10 +2,13 @@ package org.koitharu.kotatsu.parsers.site.guya
import org.json.JSONObject
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.core.LegacySinglePageMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacySinglePageMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.generateUid
import org.koitharu.kotatsu.parsers.util.parseJson
import org.koitharu.kotatsu.parsers.util.removeSuffix
import org.koitharu.kotatsu.parsers.util.toAbsoluteUrl
import java.util.*
internal abstract class GuyaParser(
@ -67,7 +70,7 @@ internal abstract class GuyaParser(
publicUrl = url,
title = name,
coverUrl = j.getString("cover").toAbsoluteUrl(domain),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
description = j.getString("description"),

@ -3,8 +3,8 @@ package org.koitharu.kotatsu.parsers.site.heancms
import org.json.JSONArray
import org.json.JSONObject
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.json.asTypedList
@ -125,7 +125,7 @@ internal abstract class HeanCms(
id = id,
url = url,
title = title,
altTitle = it.getString("alternative_names").takeIf { it.isNotBlank() },
altTitles = setOfNotNull(it.getString("alternative_names").takeIf { it.isNotBlank() }),
publicUrl = publicUrl.toAbsoluteUrl(domain),
description = it.getString("description"),
rating = it.getFloatOrDefault("rating", RATING_UNKNOWN) / 5f,

@ -2,8 +2,8 @@ package org.koitharu.kotatsu.parsers.site.heancmsalt
import org.koitharu.kotatsu.parsers.ErrorMessages
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.text.DateFormat
@ -67,7 +67,7 @@ internal abstract class HeanCmsAlt(
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src(),
title = div.selectFirst(selectMangaTitle)?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),
@ -89,7 +89,7 @@ internal abstract class HeanCmsAlt(
val doc = webClient.httpGet(fullUrl).parseHtml()
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
return manga.copy(
altTitle = doc.selectFirst(selectAlt)?.textOrNull(),
altTitles = setOfNotNull(doc.selectFirst(selectAlt)?.textOrNull()),
description = doc.selectFirst(selectDesc)?.html(),
chapters = doc.select(selectChapter)
.mapChapters(reversed = true) { i, a ->

@ -25,7 +25,7 @@ internal class Brakeout(context: MangaLoaderContext) :
val doc = webClient.httpGet(fullUrl).parseHtml()
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
return manga.copy(
altTitle = doc.selectFirst(selectAlt)?.textOrNull(),
altTitles = setOfNotNull(doc.selectFirst(selectAlt)?.textOrNull()),
description = doc.selectFirstOrThrow(selectDesc).html(),
chapters = doc.select(selectChapter)
.mapChapters(reversed = true) { i, div ->

@ -7,8 +7,8 @@ import kotlinx.coroutines.sync.withLock
import okhttp3.Headers
import org.jsoup.nodes.Document
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.network.UserAgents
import org.koitharu.kotatsu.parsers.util.*
@ -109,7 +109,7 @@ internal abstract class HotComicsParser(
publicUrl = url.toAbsoluteUrl(domain),
coverUrl = li.selectFirst("img")?.src(),
title = li.selectFirst(".title")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
description = li.selectFirst("p[itemprop*=description]")?.text().orEmpty(),
tags = tags,

@ -3,8 +3,8 @@ package org.koitharu.kotatsu.parsers.site.id
import okhttp3.Headers
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.text.SimpleDateFormat
@ -116,7 +116,7 @@ internal class DoujinDesuParser(context: MangaLoaderContext) :
Manga(
id = generateUid(href),
title = it.selectFirst(".metadata > a")?.attr("title").orEmpty(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,

@ -2,8 +2,8 @@ package org.koitharu.kotatsu.parsers.site.id
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.util.*
@ -68,7 +68,7 @@ internal class HentaiCrot(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src()?.replace("-200x285", ""),
title = div.selectFirst("h2")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),
@ -98,7 +98,9 @@ internal class HentaiCrot(context: MangaLoaderContext) :
val author = doc.selectFirst("div.entry-content ul li:contains(Artists :) em")?.textOrNull()
return manga.copy(
description = doc.selectFirst("div.entry-content p")?.html(),
altTitle = doc.selectFirst("div.entry-content ul li:contains(Alternative Name(s) :) em")?.textOrNull(),
altTitles = setOfNotNull(
doc.selectFirst("div.entry-content ul li:contains(Alternative Name(s) :) em")?.textOrNull(),
),
authors = author?.let { setOf(it) } ?: emptySet(),
state = null,
chapters = listOf(

@ -2,8 +2,8 @@ package org.koitharu.kotatsu.parsers.site.id
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.util.*
@ -68,7 +68,7 @@ internal class PixHentai(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src()?.replace("-200x285", ""),
title = div.selectFirst("h2")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),
@ -98,7 +98,9 @@ internal class PixHentai(context: MangaLoaderContext) :
val author = doc.selectFirst("div.entry-content ul li:contains(Artists :) em")?.textOrNull()
return manga.copy(
description = doc.selectFirst("div.entry-content p")?.html(),
altTitle = doc.selectFirst("div.entry-content ul li:contains(Alternative Name(s) :) em")?.textOrNull(),
altTitles = setOfNotNull(
doc.selectFirst("div.entry-content ul li:contains(Alternative Name(s) :) em")?.textOrNull(),
),
authors = author?.let { setOf(it) } ?: emptySet(),
state = null,
chapters = listOf(

@ -2,8 +2,8 @@ package org.koitharu.kotatsu.parsers.site.iken
import org.json.JSONObject
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.json.asTypedList
@ -109,7 +109,7 @@ internal abstract class IkenParser(
publicUrl = url.toAbsoluteUrl(domain),
coverUrl = it.getString("featuredImage"),
title = it.getString("postTitle"),
altTitle = it.getString("alternativeTitles"),
altTitles = setOfNotNull(it.getStringOrNull("alternativeTitles")),
description = it.getString("postContent"),
rating = RATING_UNKNOWN,
tags = emptySet(),

@ -1,10 +1,10 @@
package org.koitharu.kotatsu.parsers.site.ja
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.core.LegacyMangaParser
import org.koitharu.kotatsu.parsers.MangaParserAuthProvider
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyMangaParser
import org.koitharu.kotatsu.parsers.exception.AuthRequiredException
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.network.UserAgents
@ -89,7 +89,7 @@ internal class NicovideoSeigaParser(context: MangaLoaderContext) :
id = generateUid(href),
title = item.selectFirst(".mg_body > .title > a")?.text() ?: return@mapNotNull null,
coverUrl = item.selectFirst(".comic_icon > div > a > img")?.attrAsAbsoluteUrl("src"),
altTitle = null,
altTitles = emptySet(),
authors = author?.let { setOf(it) } ?: emptySet(),
rating = RATING_UNKNOWN,
url = href,
@ -193,7 +193,7 @@ internal class NicovideoSeigaParser(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(item.host ?: domain),
title = item.selectFirst(".search_result__item__info > .search_result__item__info--title > a")
?.textOrNull() ?: return@mapNotNull null,
altTitle = null,
altTitles = emptySet(),
authors = emptySet(),
tags = emptySet(),
rating = RATING_UNKNOWN,

@ -5,8 +5,8 @@ import kotlinx.coroutines.coroutineScope
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.core.LegacySinglePageMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacySinglePageMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.text.DateFormat
@ -129,7 +129,7 @@ internal abstract class KeyoappParser(
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = cover?.styleValueOrNull("background-image")?.cssUrl(),
title = div.selectFirstOrThrow("h3").text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = div.select("div.gap-1 a").mapToSet { a ->
MangaTag(

@ -7,8 +7,8 @@ import okhttp3.HttpUrl.Companion.toHttpUrl
import org.json.JSONObject
import org.jsoup.nodes.Element
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.text.DateFormat
@ -111,7 +111,7 @@ internal abstract class LikeMangaParser(
Manga(
id = generateUid(href),
title = div.selectFirstOrThrow("p.title-manga").text(),
altTitle = null,
altTitles = emptySet(),
url = href,
publicUrl = href.toAbsoluteUrl(domain),
rating = RATING_UNKNOWN,
@ -151,7 +151,7 @@ internal abstract class LikeMangaParser(
}
val author = doc.selectLast("li.author p")?.textOrNull()
return manga.copy(
altTitle = doc.selectFirst(".list-info li.othername h2")?.textOrNull(),
altTitles = setOfNotNull(doc.selectFirst(".list-info li.othername h2")?.textOrNull()),
tags = doc.select("li.kind a").mapToSet { a ->
MangaTag(
key = a.attr("href").removeSuffix('/').substringAfterLast('/'),

@ -5,8 +5,8 @@ import kotlinx.coroutines.coroutineScope
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.json.getBooleanOrDefault
@ -116,7 +116,7 @@ internal abstract class LilianaParser(
publicUrl = href.toAbsoluteUrl(domain),
coverUrl = element.selectFirst("img")?.src(),
title = element.selectFirst(".text-center a")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = RATING_UNKNOWN,
tags = emptySet(),
authors = emptySet(),

@ -8,8 +8,8 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaParserAuthProvider
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser
import org.koitharu.kotatsu.parsers.exception.AuthRequiredException
import org.koitharu.kotatsu.parsers.exception.ParseException
import org.koitharu.kotatsu.parsers.model.*
@ -468,7 +468,7 @@ internal abstract class MadaraParser(
coverUrl = div.selectFirst("img")?.src(),
title = (summary?.selectFirst("h3, h4") ?: div.selectFirst(".manga-name, .post-title"))?.text()
.orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a ->
MangaTag(
@ -575,7 +575,7 @@ internal abstract class MadaraParser(
)
},
description = desc,
altTitle = alt,
altTitles = setOfNotNull(alt),
state = state,
chapters = chaptersDeferred.await(),
contentRating = if (doc.selectFirst(".adult-confirm") != null) {
@ -659,7 +659,7 @@ internal abstract class MadaraParser(
id = generateUid(href),
url = href,
publicUrl = href.toAbsoluteUrl(a.host ?: domain),
altTitle = null,
altTitles = emptySet(),
title = div.selectFirstOrThrow(".widget-title").text(),
authors = emptySet(),
coverUrl = div.selectFirst("img")?.src(),

@ -71,7 +71,7 @@ internal class Manga18Fx(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src(),
title = div.selectFirstOrThrow("h3").text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = div.selectFirst("div.item-rate span")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
tags = emptySet(),
authors = emptySet(),

@ -77,7 +77,7 @@ internal class Manhwa18Cc(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src(),
title = div.selectFirstOrThrow("h3").text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = div.selectFirst(".item-rate span")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
tags = emptySet(),
authors = emptySet(),

@ -118,7 +118,7 @@ internal class AdultWebtoon(context: MangaLoaderContext) :
)
},
description = desc,
altTitle = alt,
altTitles = setOfNotNull(alt),
state = state,
chapters = chaptersDeferred.await(),
)

@ -25,7 +25,7 @@ internal class FireScans(context: MangaLoaderContext) :
coverUrl = div.selectFirst("img")?.src(),
title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4")
?: div.selectFirst(".manga-name"))?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a ->
MangaTag(

@ -110,7 +110,7 @@ internal class Hentai4Free(context: MangaLoaderContext) :
coverUrl = div.selectFirst("img")?.src(),
title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4")
?: div.selectFirst(".manga-name"))?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a ->
MangaTag(

@ -112,7 +112,7 @@ internal class HentaiManga(context: MangaLoaderContext) :
)
},
description = desc,
altTitle = alt,
altTitles = setOfNotNull(alt),
state = state,
chapters = chaptersDeferred.await(),
)

@ -112,7 +112,7 @@ internal class HentaiWebtoon(context: MangaLoaderContext) :
)
},
description = desc,
altTitle = alt,
altTitles = setOfNotNull(alt),
state = state,
chapters = chaptersDeferred.await(),
)

@ -84,7 +84,7 @@ internal class IsekaiScan(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src(),
title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4"))?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a ->
MangaTag(

@ -107,7 +107,7 @@ internal class IsekaiScanEuParser(context: MangaLoaderContext) :
coverUrl = div.selectFirst("img")?.src(),
title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4")
?: summary?.selectFirst("div.post-title p.juduldepan"))?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a ->
MangaTag(

@ -82,7 +82,7 @@ internal class MangaDass(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src(),
title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4"))?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a ->
MangaTag(
@ -138,7 +138,7 @@ internal class MangaDass(context: MangaLoaderContext) :
)
},
description = desc,
altTitle = alt,
altTitles = setOfNotNull(alt),
state = state,
chapters = chaptersDeferred.await(),
)

@ -75,7 +75,7 @@ internal class MangaDna(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src(),
title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4"))?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = div.selectFirst("div.hitem-rate span")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a ->
MangaTag(
@ -131,7 +131,7 @@ internal class MangaDna(context: MangaLoaderContext) :
)
},
description = desc,
altTitle = alt,
altTitles = setOfNotNull(alt),
state = state,
chapters = chaptersDeferred.await(),
)

@ -89,7 +89,7 @@ internal class MangaPure(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src(),
title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4"))?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a ->
MangaTag(

@ -68,7 +68,7 @@ internal class ManhwaHentai(context: MangaLoaderContext) :
)
},
description = desc,
altTitle = alt,
altTitles = setOfNotNull(alt),
state = state,
chapters = chaptersDeferred.await(),
)

@ -78,7 +78,7 @@ internal class Manhwaz(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src(),
title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4"))?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a ->
MangaTag(

@ -115,7 +115,7 @@ internal class ManyToon(context: MangaLoaderContext) :
)
},
description = desc,
altTitle = alt,
altTitles = setOfNotNull(alt),
state = state,
chapters = chaptersDeferred.await(),
)

@ -26,7 +26,7 @@ internal class ShibaManga(context: MangaLoaderContext) :
coverUrl = div.selectFirst("img")?.src(),
title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4")
?: div.selectFirst("div.post-title a"))?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a ->
MangaTag(

@ -61,7 +61,7 @@ internal class DragonTranslationParser(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img.thumb-img")?.src(),
title = div.selectFirst("div.series-box h5")?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
tags = emptySet(),
authors = emptySet(),

@ -31,8 +31,10 @@ internal class MangasNoSekai(context: MangaLoaderContext) :
},
authors = author?.let { setOf(it) } ?: emptySet(),
description = body.selectFirst("#section-sinopsis p")?.text().orEmpty(),
altTitle = doc.selectFirst("section#section-sinopsis div.d-flex:has(div:contains(Otros nombres)) p")
?.textOrNull(),
altTitles = setOfNotNull(
doc.selectFirst("section#section-sinopsis div.d-flex:has(div:contains(Otros nombres)) p")
?.textOrNull(),
),
state = body.selectFirst("section#section-sinopsis div.d-flex:has(div:contains(Estado)) p")
?.let {
when (it.text()) {

@ -72,7 +72,7 @@ internal class TmoManga(context: MangaLoaderContext) :
publicUrl = href.toAbsoluteUrl(div.host ?: domain),
coverUrl = div.selectFirst("img")?.src(),
title = div.selectFirstOrThrow("h3").text(),
altTitle = null,
altTitles = emptySet(),
rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
tags = emptySet(),
authors = emptySet(),

@ -74,7 +74,7 @@ internal class ManhwaHub(context: MangaLoaderContext) :
coverUrl = div.selectFirst("img")?.src(),
title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4")
?: div.selectFirst("h5.series-title"))?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a ->
MangaTag(

@ -30,7 +30,7 @@ internal class MangaFenxi(context: MangaLoaderContext) :
coverUrl = div.selectFirst("img")?.attr("src")?.replace("-193x278", ""),
title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4")
?: div.selectFirst(".manga-name") ?: div.selectFirst(".post-title"))?.text().orEmpty(),
altTitle = null,
altTitles = emptySet(),
rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a ->
MangaTag(

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save