Remove deprecated Manga constructor and introduce authors field
This commit is contained in:
@@ -2,6 +2,7 @@ package org.koitharu.kotatsu.parsers.model
|
||||
|
||||
import androidx.collection.ArrayMap
|
||||
import org.koitharu.kotatsu.parsers.util.findById
|
||||
import org.koitharu.kotatsu.parsers.util.mapToSet
|
||||
import org.koitharu.kotatsu.parsers.util.nullIfEmpty
|
||||
|
||||
public data class Manga constructor(
|
||||
@@ -49,9 +50,9 @@ public data class Manga constructor(
|
||||
*/
|
||||
@JvmField public val state: MangaState?,
|
||||
/**
|
||||
* Author of the manga, may be null
|
||||
* Authors of the manga
|
||||
*/
|
||||
@JvmField public val author: String?,
|
||||
@JvmField public val authors: Set<String>,
|
||||
/**
|
||||
* Large cover url (absolute), null if is no large cover
|
||||
* @see coverUrl
|
||||
@@ -70,41 +71,12 @@ public data class Manga constructor(
|
||||
*/
|
||||
@JvmField public val source: MangaSource,
|
||||
) {
|
||||
|
||||
@Deprecated("Prefer constructor with contentRating instead of isNsfw")
|
||||
public constructor(
|
||||
id: Long,
|
||||
title: String,
|
||||
altTitle: String?,
|
||||
url: String,
|
||||
publicUrl: String,
|
||||
rating: Float,
|
||||
isNsfw: Boolean,
|
||||
coverUrl: String?,
|
||||
tags: Set<MangaTag>,
|
||||
state: MangaState?,
|
||||
author: String?,
|
||||
largeCoverUrl: String? = null,
|
||||
description: String? = null,
|
||||
chapters: List<MangaChapter>? = null,
|
||||
source: MangaSource,
|
||||
) : this(
|
||||
id = id,
|
||||
title = title,
|
||||
altTitle = altTitle?.nullIfEmpty(),
|
||||
url = url,
|
||||
publicUrl = publicUrl,
|
||||
rating = rating,
|
||||
contentRating = if (isNsfw) ContentRating.ADULT else null,
|
||||
coverUrl = coverUrl?.nullIfEmpty(),
|
||||
tags = tags,
|
||||
state = state,
|
||||
author = author?.nullIfEmpty(),
|
||||
largeCoverUrl = largeCoverUrl?.nullIfEmpty(),
|
||||
description = description?.nullIfEmpty(),
|
||||
chapters = chapters,
|
||||
source = source,
|
||||
)
|
||||
/**
|
||||
* Author of the manga, may be null
|
||||
*/
|
||||
@Deprecated("Please use authors")
|
||||
public val author: String?
|
||||
get() = authors.firstOrNull()
|
||||
|
||||
/**
|
||||
* Return if manga has a specified rating
|
||||
|
||||
@@ -214,6 +214,7 @@ internal class BatoToParser(context: MangaLoaderContext) : PagedMangaParser(
|
||||
val attrs = details.selectFirst(".attr-main")?.select(".attr-item")?.associate {
|
||||
it.child(0).text() to it.child(1)
|
||||
}.orEmpty()
|
||||
val author = attrs["Authors:"]?.textOrNull()
|
||||
return manga.copy(
|
||||
title = root.selectFirst("h3.item-title")?.text() ?: manga.title,
|
||||
contentRating = if (root.selectFirst("alert")?.getElementsContainingOwnText("NSFW").isNullOrEmpty()) {
|
||||
@@ -233,7 +234,7 @@ internal class BatoToParser(context: MangaLoaderContext) : PagedMangaParser(
|
||||
"Hiatus" -> MangaState.PAUSED
|
||||
else -> manga.state
|
||||
},
|
||||
author = attrs["Authors:"]?.textOrNull() ?: manga.author,
|
||||
authors = author?.let { setOf(it) } ?: manga.authors,
|
||||
chapters = root.selectFirst(".episode-list")
|
||||
?.selectFirst(".main")
|
||||
?.children()
|
||||
@@ -337,13 +338,13 @@ internal class BatoToParser(context: MangaLoaderContext) : PagedMangaParser(
|
||||
url = href,
|
||||
publicUrl = a.absUrl("href"),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = div.selectFirst("img[src]")?.absUrl("src"),
|
||||
largeCoverUrl = null,
|
||||
description = null,
|
||||
tags = div.selectFirst(".item-genre")?.parseTags().orEmpty(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ internal class ComickFunParser(context: MangaLoaderContext) :
|
||||
4 -> MangaState.PAUSED
|
||||
else -> null
|
||||
},
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -182,6 +182,7 @@ internal class ComickFunParser(context: MangaLoaderContext) :
|
||||
val alt = comic.getJSONArray("md_titles").asTypedList<JSONObject>().joinToString("\n") {
|
||||
it.getStringOrNull("title").orEmpty()
|
||||
}
|
||||
val author = jo.getJSONArray("artists").optJSONObject(0)?.getStringOrNull("name")
|
||||
return manga.copy(
|
||||
altTitle = alt.nullIfEmpty(),
|
||||
contentRating = if (jo.getBooleanOrDefault("matureContent", false)
|
||||
@@ -200,7 +201,7 @@ internal class ComickFunParser(context: MangaLoaderContext) :
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
author = jo.getJSONArray("artists").optJSONObject(0)?.getStringOrNull("name"),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
chapters = getChapters(comic.getString("hid")),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -168,6 +168,8 @@ internal class ExHentaiParser(
|
||||
val href = a.attrAsRelativeUrl("href")
|
||||
val tagsDiv = gLink.nextElementSibling() ?: gLink.parseFailed("tags div not found")
|
||||
val rawTitle = gLink.text()
|
||||
val author = tagsDiv.getElementsContainingOwnText("artist:").first()
|
||||
?.nextElementSibling()?.textOrNull()
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
title = rawTitle.cleanupTitle(),
|
||||
@@ -182,8 +184,7 @@ internal class ExHentaiParser(
|
||||
rawTitle.contains("(ongoing)", ignoreCase = true) -> MangaState.ONGOING
|
||||
else -> null
|
||||
},
|
||||
author = tagsDiv.getElementsContainingOwnText("artist:").first()
|
||||
?.nextElementSibling()?.textOrNull(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -524,9 +524,9 @@ internal class HitomiLaParser(context: MangaLoaderContext) : MangaParser(context
|
||||
doc.selectFirstOrThrow("h1 > a")
|
||||
.attrAsRelativeUrl("href")
|
||||
.toAbsoluteUrl(domain),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
tags = emptySet(),
|
||||
isNsfw = true,
|
||||
contentRating = ContentRating.ADULT,
|
||||
rating = RATING_UNKNOWN,
|
||||
altTitle = null,
|
||||
state = null,
|
||||
@@ -542,6 +542,10 @@ internal class HitomiLaParser(context: MangaLoaderContext) : MangaParser(context
|
||||
.parseRaw()
|
||||
.substringAfter("var galleryinfo = ")
|
||||
.let(::JSONObject)
|
||||
val author =
|
||||
json.optJSONArray("artists")
|
||||
?.mapJSON { it.getString("artist").toCamelCase() }
|
||||
?.joinToString()
|
||||
|
||||
return manga.copy(
|
||||
title = json.getString("title"),
|
||||
@@ -554,10 +558,7 @@ internal class HitomiLaParser(context: MangaLoaderContext) : MangaParser(context
|
||||
|
||||
"https://${getDomain("${subDomain}a")}/webp/$commonId$imageId/$hash.webp"
|
||||
},
|
||||
author =
|
||||
json.optJSONArray("artists")
|
||||
?.mapJSON { it.getString("artist").toCamelCase() }
|
||||
?.joinToString(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
publicUrl = json.getString("galleryurl").toAbsoluteUrl(domain),
|
||||
tags =
|
||||
buildSet {
|
||||
|
||||
@@ -125,10 +125,10 @@ internal class ImHentai(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -161,6 +161,7 @@ internal class ImHentai(context: MangaLoaderContext) :
|
||||
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val author = doc.selectFirst("li:contains(Artists) a.tag")?.ownTextOrNull()
|
||||
manga.copy(
|
||||
tags = doc.body().select("li:contains(Tags) a.tag").mapNotNullToSet {
|
||||
val href = it.attr("href").substringAfterLast("tag/").substringBeforeLast('/')
|
||||
@@ -170,7 +171,7 @@ internal class ImHentai(context: MangaLoaderContext) :
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
author = doc.selectFirst("li:contains(Artists) a.tag")?.ownTextOrNull(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
chapters = listOf(
|
||||
MangaChapter(
|
||||
id = manga.id,
|
||||
@@ -202,10 +203,10 @@ internal class ImHentai(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,6 +121,8 @@ internal abstract class LineWebtoonsParser(
|
||||
makeRequest("/lineWebtoon/webtoon/challengeTitleInfo.json?v=2&titleNo=${titleNo}")
|
||||
.getJSONObject("titleInfo")
|
||||
.let { jo ->
|
||||
val isNsfwSource = jo.getBooleanOrDefault("ageGradeNotice", isNsfwSource)
|
||||
val author = jo.getStringOrNull("writingAuthorName")
|
||||
Manga(
|
||||
id = generateUid(titleNo),
|
||||
title = jo.getString("title"),
|
||||
@@ -128,11 +130,11 @@ internal abstract class LineWebtoonsParser(
|
||||
url = "$titleNo",
|
||||
publicUrl = "https://$domain/$languageCode/canvas/a/list?title_no=${titleNo}",
|
||||
rating = jo.getFloatOrDefault("starScoreAverage", -10f) / 10f,
|
||||
isNsfw = jo.getBooleanOrDefault("ageGradeNotice", isNsfwSource),
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
coverUrl = jo.getString("thumbnail").toAbsoluteUrl(staticDomain),
|
||||
largeCoverUrl = jo.getStringOrNull("thumbnailVertical")?.toAbsoluteUrl(staticDomain),
|
||||
tags = setOf(parseTag(jo.getJSONObject("genreInfo"))),
|
||||
author = jo.getStringOrNull("writingAuthorName"),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = jo.getString("synopsis"),
|
||||
// I don't think the API provides this info
|
||||
state = null,
|
||||
@@ -150,6 +152,7 @@ internal abstract class LineWebtoonsParser(
|
||||
.getJSONArray("titleList")
|
||||
.mapJSON { jo ->
|
||||
val titleNo = jo.getLong("titleNo")
|
||||
val author = jo.getStringOrNull("writingAuthorName")
|
||||
|
||||
Manga(
|
||||
id = generateUid(titleNo),
|
||||
@@ -158,11 +161,11 @@ internal abstract class LineWebtoonsParser(
|
||||
url = titleNo.toString(),
|
||||
publicUrl = "https://$domain/$languageCode/canvas/a/list?title_no=$titleNo",
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
coverUrl = jo.getString("thumbnail").toAbsoluteUrl(staticDomain),
|
||||
largeCoverUrl = null,
|
||||
tags = emptySet(),
|
||||
author = jo.getStringOrNull("writingAuthorName"),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = null,
|
||||
state = null,
|
||||
source = source,
|
||||
@@ -194,6 +197,8 @@ internal abstract class LineWebtoonsParser(
|
||||
.getJSONArray("titles")
|
||||
.mapJSON { jo ->
|
||||
val titleNo = jo.getLong("titleNo")
|
||||
val isNsfwSource = jo.getBooleanOrDefault("ageGradeNotice", isNsfwSource)
|
||||
val author = jo.getStringOrNull("writingAuthorName")
|
||||
|
||||
Manga(
|
||||
id = generateUid(titleNo),
|
||||
@@ -202,11 +207,11 @@ internal abstract class LineWebtoonsParser(
|
||||
url = titleNo.toString(),
|
||||
publicUrl = "https://$domain/$languageCode/canvas/a/list?title_no=$titleNo",
|
||||
rating = jo.getFloatOrDefault("starScoreAverage", -10f) / 10f,
|
||||
isNsfw = jo.getBooleanOrDefault("ageGradeNotice", isNsfwSource),
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
coverUrl = jo.getString("thumbnail").toAbsoluteUrl(staticDomain),
|
||||
largeCoverUrl = jo.getStringOrNull("thumbnailVertical")?.toAbsoluteUrl(staticDomain),
|
||||
tags = setOfNotNull(genres[jo.getString("representGenre")]),
|
||||
author = jo.getStringOrNull("writingAuthorName"),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = jo.getString("synopsis"),
|
||||
// I don't think the API provides this info
|
||||
state = null,
|
||||
|
||||
@@ -287,6 +287,9 @@ internal class MangaDexParser(context: MangaLoaderContext) : MangaParser(context
|
||||
?.let {
|
||||
"https://uploads.$domain/covers/$id/$it"
|
||||
}
|
||||
val author = (relations["author"] ?: relations["artist"])
|
||||
?.getJSONObject("attributes")
|
||||
?.getStringOrNull("name")
|
||||
return Manga(
|
||||
id = generateUid(id),
|
||||
title = requireNotNull(attrs.getJSONObject("title").selectByLocale()) {
|
||||
@@ -322,9 +325,7 @@ internal class MangaDexParser(context: MangaLoaderContext) : MangaParser(context
|
||||
"cancelled" -> MangaState.ABANDONED
|
||||
else -> null
|
||||
},
|
||||
author = (relations["author"] ?: relations["artist"])
|
||||
?.getJSONObject("attributes")
|
||||
?.getStringOrNull("name"),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
chapters = chapters,
|
||||
source = source,
|
||||
)
|
||||
|
||||
@@ -165,7 +165,7 @@ internal abstract class MangaFireParser(
|
||||
source = source,
|
||||
altTitle = null,
|
||||
largeCoverUrl = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
contentRating = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
state = null,
|
||||
@@ -179,6 +179,8 @@ internal abstract class MangaFireParser(
|
||||
val availableTags = tags.get()
|
||||
var isAdult = false
|
||||
var isSuggestive = false
|
||||
val author = document.select("div.meta a[href*=/author/]")
|
||||
.joinToString { it.ownText() }.nullIfEmpty()
|
||||
|
||||
return manga.copy(
|
||||
title = document.selectFirstOrThrow(".info > h1").ownText(),
|
||||
@@ -211,8 +213,7 @@ internal abstract class MangaFireParser(
|
||||
else -> null
|
||||
}
|
||||
},
|
||||
author = document.select("div.meta a[href*=/author/]")
|
||||
.joinToString { it.ownText() }.nullIfEmpty(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = document.selectFirstOrThrow("#synopsis div.modal-content").html(),
|
||||
chapters = getChapters(manga.url, document),
|
||||
)
|
||||
@@ -332,7 +333,7 @@ internal abstract class MangaFireParser(
|
||||
source = source,
|
||||
altTitle = null,
|
||||
largeCoverUrl = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
contentRating = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
state = null,
|
||||
@@ -355,7 +356,7 @@ internal abstract class MangaFireParser(
|
||||
source = source,
|
||||
altTitle = null,
|
||||
largeCoverUrl = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
contentRating = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
state = null,
|
||||
|
||||
@@ -160,10 +160,10 @@ internal class MangaPark(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = div.selectFirst("span.text-yellow-500")?.text()?.toFloatOrNull()?.div(10F) ?: RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -193,9 +193,10 @@ internal class MangaPark(context: MangaLoaderContext) :
|
||||
val tags = selectTag.mapNotNullToSet { tagMap[it.text()] }
|
||||
val nsfw = tags.any { t -> t.key == "hentai" || t.key == "adult" }
|
||||
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(),
|
||||
author = doc.selectFirst("div[q:key=tz_4]")?.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()) {
|
||||
"ongoing" -> MangaState.ONGOING
|
||||
|
||||
@@ -122,8 +122,8 @@ internal abstract class MangaPlusParser(
|
||||
title = name,
|
||||
coverUrl = it.getString("portraitImageUrl"),
|
||||
altTitle = null,
|
||||
author = author,
|
||||
isNsfw = false,
|
||||
authors = setOf(author),
|
||||
contentRating = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
state = null,
|
||||
source = source,
|
||||
@@ -143,13 +143,14 @@ internal abstract class MangaPlusParser(
|
||||
}
|
||||
|
||||
val hiatus = json.getStringOrNull("nonAppearanceInfo")?.contains("on a hiatus") == true
|
||||
val author = title.getString("author")
|
||||
.split("/").joinToString(transform = String::trim)
|
||||
|
||||
return manga.copy(
|
||||
title = title.getString("name"),
|
||||
publicUrl = "/titles/${title.getInt("titleId")}".toAbsoluteUrl(domain),
|
||||
coverUrl = title.getString("portraitImageUrl"),
|
||||
author = title.getString("author")
|
||||
.split("/").joinToString(transform = String::trim),
|
||||
authors = setOf(author),
|
||||
description = buildString {
|
||||
json.getString("overview").let(::append)
|
||||
json.getStringOrNull("viewingPeriodDescription")
|
||||
|
||||
@@ -132,8 +132,8 @@ internal class MangaReaderToParser(context: MangaLoaderContext) :
|
||||
coverUrl = thumb.attr("src"),
|
||||
source = source,
|
||||
altTitle = null,
|
||||
author = null,
|
||||
isNsfw = false,
|
||||
authors = emptySet(),
|
||||
contentRating = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
state = null,
|
||||
tags = emptySet(),
|
||||
@@ -155,7 +155,7 @@ internal class MangaReaderToParser(context: MangaLoaderContext) :
|
||||
coverUrl = thumb.attrAsAbsoluteUrlOrNull("src"),
|
||||
source = source,
|
||||
altTitle = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
contentRating = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
state = null,
|
||||
@@ -169,6 +169,8 @@ internal class MangaReaderToParser(context: MangaLoaderContext) :
|
||||
val availableTags = tags.get()
|
||||
var isAdult = false
|
||||
var isSuggestive = false
|
||||
val author = document.select("div.anisc-info a[href*=/author/]")
|
||||
.joinToString { it.ownText().replace(", ", " ") }.nullIfEmpty()
|
||||
|
||||
return manga.copy(
|
||||
title = document.selectFirst("h2.manga-name")!!.ownText(),
|
||||
@@ -201,8 +203,7 @@ internal class MangaReaderToParser(context: MangaLoaderContext) :
|
||||
else -> null
|
||||
}
|
||||
},
|
||||
author = document.select("div.anisc-info a[href*=/author/]")
|
||||
.joinToString { it.ownText().replace(", ", " ") }.nullIfEmpty(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = document.select("div.description").html(),
|
||||
chapters = parseChapters(document),
|
||||
source = source,
|
||||
|
||||
@@ -116,8 +116,8 @@ internal abstract class NineMangaParser(
|
||||
altTitle = null,
|
||||
coverUrl = node.selectFirst("img")?.src(),
|
||||
rating = RATING_UNKNOWN,
|
||||
author = null,
|
||||
isNsfw = false,
|
||||
authors = emptySet(),
|
||||
contentRating = null,
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
@@ -135,11 +135,12 @@ internal abstract class NineMangaParser(
|
||||
val tagMap = getOrCreateTagMap()
|
||||
val selectTag = infoRoot.getElementsByAttributeValue("itemprop", "genre").first()?.select("a")
|
||||
val tags = selectTag?.mapNotNullToSet { tagMap[it.text()] }
|
||||
val author = infoRoot.getElementsByAttributeValue("itemprop", "author").first()?.textOrNull()
|
||||
return manga.copy(
|
||||
title = root.selectFirst("h1[itemprop=name]")?.textOrNull()?.removeSuffix("Manga")?.trimEnd()
|
||||
?: manga.title,
|
||||
tags = tags.orEmpty(),
|
||||
author = infoRoot.getElementsByAttributeValue("itemprop", "author").first()?.textOrNull(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = parseStatus(infoRoot.select("li a.red").text()),
|
||||
description = infoRoot.getElementsByAttributeValue("itemprop", "description").first()?.html()
|
||||
?.substringAfter("</b>"),
|
||||
|
||||
@@ -206,7 +206,7 @@ internal class NineNineNineHentaiParser(context: MangaLoaderContext) :
|
||||
cover == null -> null
|
||||
else -> "https://${cdnHost.get()}/$cover"
|
||||
},
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
contentRating = ContentRating.ADULT,
|
||||
url = id,
|
||||
publicUrl = "/hchapter/$id".toAbsoluteUrl(domain),
|
||||
@@ -264,12 +264,13 @@ internal class NineNineNineHentaiParser(context: MangaLoaderContext) :
|
||||
type = it.getStringOrNull("tagType"),
|
||||
)
|
||||
}
|
||||
val author = tags?.filter { it.type == "artist" }?.joinToString { it.name.toCamelCase() }?.nullIfEmpty()
|
||||
return manga.copy(
|
||||
title = name.replace(shortenTitleRegex, "").trim(),
|
||||
altTitle = name,
|
||||
coverUrl = cover.first,
|
||||
largeCoverUrl = cover.second,
|
||||
author = tags?.filter { it.type == "artist" }?.joinToString { it.name.toCamelCase() }?.nullIfEmpty(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
contentRating = ContentRating.ADULT,
|
||||
tags = tags?.mapToSet {
|
||||
MangaTag(
|
||||
|
||||
@@ -123,6 +123,8 @@ internal abstract class WebtoonsParser(
|
||||
val chapters = chaptersDeferred.await()
|
||||
makeRequest("/lineWebtoon/webtoon/titleInfo.json?titleNo=${titleNo}&anyServiceStatus=false").getJSONObject("titleInfo")
|
||||
.let { jo ->
|
||||
val isNsfwSource = jo.getBooleanOrDefault("ageGradeNotice", isNsfwSource)
|
||||
val author = jo.getStringOrNull("writingAuthorName")
|
||||
MangaWebtoon(
|
||||
Manga(
|
||||
id = generateUid(titleNo),
|
||||
@@ -131,11 +133,11 @@ internal abstract class WebtoonsParser(
|
||||
url = "$titleNo",
|
||||
publicUrl = "https://$domain/$languageCode/originals/a/list?title_no=${titleNo}",
|
||||
rating = jo.getFloatOrDefault("starScoreAverage", -10f) / 10f,
|
||||
isNsfw = jo.getBooleanOrDefault("ageGradeNotice", isNsfwSource),
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
coverUrl = jo.getString("thumbnail").toAbsoluteUrl(staticDomain),
|
||||
largeCoverUrl = jo.getStringOrNull("thumbnailVertical")?.toAbsoluteUrl(staticDomain),
|
||||
tags = setOf(parseTag(jo.getJSONObject("genreInfo"))),
|
||||
author = jo.getStringOrNull("writingAuthorName"),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = jo.getString("synopsis"),
|
||||
// I don't think the API provides this info,
|
||||
state = null,
|
||||
@@ -158,6 +160,8 @@ internal abstract class WebtoonsParser(
|
||||
makeRequest("/lineWebtoon/webtoon/titleList.json?").getJSONObject("titleList").getJSONArray("titles")
|
||||
.mapJSON { jo ->
|
||||
val titleNo = jo.getLong("titleNo")
|
||||
val isNsfwSource = jo.getBooleanOrDefault("ageGradeNotice", isNsfwSource)
|
||||
val author = jo.getStringOrNull("writingAuthorName")
|
||||
MangaWebtoon(
|
||||
Manga(
|
||||
id = generateUid(titleNo),
|
||||
@@ -166,8 +170,8 @@ internal abstract class WebtoonsParser(
|
||||
title = jo.getString("title"),
|
||||
coverUrl = jo.getString("thumbnail").toAbsoluteUrl(staticDomain),
|
||||
altTitle = null,
|
||||
author = jo.getStringOrNull("writingAuthorName"),
|
||||
isNsfw = jo.getBooleanOrDefault("ageGradeNotice", isNsfwSource),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
rating = jo.getFloatOrDefault("starScoreAverage", -10f) / 10f,
|
||||
tags = setOfNotNull(allGenreCache.get()[jo.getString("representGenre")]),
|
||||
description = jo.getString("synopsis"),
|
||||
@@ -196,6 +200,7 @@ internal abstract class WebtoonsParser(
|
||||
makeRequest("/lineWebtoon/webtoon/searchWebtoon?query=${filter.query.urlEncoded()}").getJSONObject("webtoonSearch")
|
||||
.getJSONArray("titleList").mapJSON { jo ->
|
||||
val titleNo = jo.getLong("titleNo")
|
||||
val author = jo.getStringOrNull("writingAuthorName")
|
||||
MangaWebtoon(
|
||||
Manga(
|
||||
id = generateUid(titleNo),
|
||||
@@ -204,11 +209,11 @@ internal abstract class WebtoonsParser(
|
||||
url = titleNo.toString(),
|
||||
publicUrl = "https://$domain/$languageCode/originals/a/list?title_no=$titleNo",
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
coverUrl = jo.getString("thumbnail").toAbsoluteUrl(staticDomain),
|
||||
largeCoverUrl = null,
|
||||
tags = emptySet(),
|
||||
author = jo.getStringOrNull("writingAuthorName"),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = null,
|
||||
state = null,
|
||||
source = source,
|
||||
|
||||
@@ -110,10 +110,10 @@ internal abstract class AnimeBootstrapParser(
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,10 +72,10 @@ internal class PapScan(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ internal class FlixScans(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = cover,
|
||||
tags = emptySet(),
|
||||
state = when (j.getString("status")) {
|
||||
@@ -122,7 +122,7 @@ internal class FlixScans(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
"droped" -> MangaState.ABANDONED
|
||||
else -> null
|
||||
},
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -74,11 +74,11 @@ internal class MangaStorm(context: MangaLoaderContext) : PagedMangaParser(contex
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = div.selectFirstOrThrow("img").src(),
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -108,7 +108,7 @@ internal class TeamXNovel(context: MangaLoaderContext) : PagedMangaParser(contex
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = div.selectFirstOrThrow("img").src()?.replace("thumbnail_", ""),
|
||||
tags = emptySet(),
|
||||
state = when (div.selectFirst(".status")?.text()) {
|
||||
@@ -117,7 +117,7 @@ internal class TeamXNovel(context: MangaLoaderContext) : PagedMangaParser(contex
|
||||
"متوقف" -> MangaState.ABANDONED
|
||||
else -> null
|
||||
},
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -90,8 +90,8 @@ internal class AnibelParser(context: MangaLoaderContext) : MangaParser(context,
|
||||
coverUrl = jo.getString("poster").removePrefix("/cdn")
|
||||
.toAbsoluteUrl(getDomain("cdn")) + "?width=200&height=280",
|
||||
altTitle = title.optJSONArray("alt")?.optString(0)?.nullIfEmpty(),
|
||||
author = null,
|
||||
isNsfw = false,
|
||||
authors = emptySet(),
|
||||
contentRating = null,
|
||||
rating = jo.getDouble("rating").toFloat() / 10f,
|
||||
url = href,
|
||||
publicUrl = "https://${domain}/$href",
|
||||
@@ -237,8 +237,8 @@ internal class AnibelParser(context: MangaLoaderContext) : MangaParser(context,
|
||||
coverUrl = jo.getString("poster").removePrefix("/cdn")
|
||||
.toAbsoluteUrl(getDomain("cdn")) + "?width=200&height=280",
|
||||
altTitle = title.getString("en").nullIfEmpty(),
|
||||
author = null,
|
||||
isNsfw = false,
|
||||
authors = emptySet(),
|
||||
contentRating = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
url = href,
|
||||
publicUrl = "https://${domain}/$href",
|
||||
|
||||
@@ -99,11 +99,11 @@ internal abstract class CupFoxParser(
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = li.selectFirst(selectMangasCover)?.src(),
|
||||
tags = setOf(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -122,6 +122,7 @@ internal abstract class CupFoxParser(
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
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(),
|
||||
tags = doc.select(selectMangaDetailsTags).mapToSet { a ->
|
||||
@@ -131,7 +132,7 @@ internal abstract class CupFoxParser(
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
author = doc.selectFirst(selectMangaDetailsAuthor)?.text()?.substringAfter(":")?.nullIfEmpty(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = doc.selectFirst(selectMangaDescription)?.html(),
|
||||
chapters = doc.select(selectMangaChapters)
|
||||
.mapChapters { i, li ->
|
||||
@@ -164,11 +165,11 @@ internal abstract class CupFoxParser(
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = li.selectFirst(selectMangasCover)?.src(),
|
||||
tags = setOf(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ internal class AsuraScansParser(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = a.selectFirst("div.block label.ml-1")?.text()?.toFloatOrNull()?.div(10f) ?: RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = when (a.selectLast("span.status")?.text()) {
|
||||
"Ongoing" -> MangaState.ONGOING
|
||||
"Completed" -> MangaState.FINISHED
|
||||
@@ -126,7 +126,7 @@ internal class AsuraScansParser(context: MangaLoaderContext) :
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -159,10 +159,11 @@ internal class AsuraScansParser(context: MangaLoaderContext) :
|
||||
val tagMap = getOrCreateTagMap()
|
||||
val selectTag = doc.select("div[class^=space] > div.flex > button.text-white")
|
||||
val tags = selectTag.mapNotNullToSet { tagMap[it.text()] }
|
||||
val author = doc.selectFirst("div.grid > div:has(h3:eq(0):containsOwn(Author)) > h3:eq(1)")?.text().orEmpty()
|
||||
return manga.copy(
|
||||
description = doc.selectFirst("span.font-medium.text-sm")?.text().orEmpty(),
|
||||
tags = tags,
|
||||
author = doc.selectFirst("div.grid > div:has(h3:eq(0):containsOwn(Author)) > h3:eq(1)")?.text().orEmpty(),
|
||||
authors = setOf(author),
|
||||
chapters = doc.select("div.scrollbar-thumb-themecolor > div.group").mapChapters(reversed = true) { i, div ->
|
||||
val a = div.selectLastOrThrow("a")
|
||||
val urlRelative = "/series/" + a.attrAsRelativeUrl("href")
|
||||
|
||||
@@ -78,14 +78,14 @@ internal class BeeToon(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = div.selectFirst(".counter")?.text()?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = when (div.selectLastOrThrow(".status span").text()) {
|
||||
"Ongoing" -> MangaState.ONGOING
|
||||
"Completed" -> MangaState.FINISHED
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -103,6 +103,7 @@ internal class BeeToon(context: MangaLoaderContext) :
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val author = doc.selectFirst(".info .author a")?.text()
|
||||
return manga.copy(
|
||||
description = doc.getElementById("desc")?.text().orEmpty(),
|
||||
rating = doc.selectFirst(".counter")?.text()?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
|
||||
@@ -113,7 +114,7 @@ internal class BeeToon(context: MangaLoaderContext) :
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
author = doc.selectFirst(".info .author a")?.text(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
chapters = doc.select(".items-chapters a").mapChapters(reversed = true) { i, a ->
|
||||
val url = a.attrAsRelativeUrl("href").toAbsoluteUrl(domain)
|
||||
MangaChapter(
|
||||
|
||||
@@ -39,10 +39,10 @@ internal class CloneMangaParser(context: MangaLoaderContext) :
|
||||
title = item.selectFirst("h3")?.text() ?: return@mapNotNull null,
|
||||
coverUrl = "https://$domain/$cover",
|
||||
altTitle = null,
|
||||
author = "Dan Kim",
|
||||
authors = setOf("Dan Kim"),
|
||||
rating = RATING_UNKNOWN,
|
||||
url = href,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
|
||||
@@ -74,7 +74,7 @@ internal class ComicExtra(context: MangaLoaderContext) : PagedMangaParser(contex
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = div.selectFirstOrThrow("img").attrAsAbsoluteUrl("src"),
|
||||
tags = div.select("div.egb-details a").mapToSet { a ->
|
||||
MangaTag(
|
||||
@@ -84,7 +84,7 @@ internal class ComicExtra(context: MangaLoaderContext) : PagedMangaParser(contex
|
||||
)
|
||||
},
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -103,6 +103,7 @@ internal class ComicExtra(context: MangaLoaderContext) : PagedMangaParser(contex
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
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(),
|
||||
state = when (doc.selectFirstOrThrow("ul.anime-genres li.status a").text()) {
|
||||
@@ -117,7 +118,7 @@ internal class ComicExtra(context: MangaLoaderContext) : PagedMangaParser(contex
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
author = doc.selectFirst("table.full-table tr:contains(Author:) td:nth-child(2)")?.textOrNull(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = doc.selectFirstOrThrow("div.detail-desc-content p").html(),
|
||||
chapters = doc.select("ul.basic-list li").let { elements ->
|
||||
elements.mapChapters { i, li ->
|
||||
|
||||
@@ -90,11 +90,11 @@ internal class DynastyScans(context: MangaLoaderContext) :
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = div.selectFirstOrThrow("img").attrAsAbsoluteUrl("src"),
|
||||
tags = setOf(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -111,7 +111,7 @@ internal class DynastyScans(context: MangaLoaderContext) :
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = null,
|
||||
tags = div.select("span.tags a").mapToSet { a ->
|
||||
MangaTag(
|
||||
@@ -121,7 +121,7 @@ internal class DynastyScans(context: MangaLoaderContext) :
|
||||
)
|
||||
},
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -128,6 +128,7 @@ internal class FlameComics(context: MangaLoaderContext) :
|
||||
private fun parseManga(jo: JSONObject): Manga {
|
||||
val seriesId = jo.getLong("series_id")
|
||||
val cover = jo.getStringOrNull("cover")
|
||||
val author = jo.getStringOrNull("author")
|
||||
return Manga(
|
||||
id = generateUid(seriesId),
|
||||
title = jo.getString("title"),
|
||||
@@ -137,7 +138,7 @@ internal class FlameComics(context: MangaLoaderContext) :
|
||||
url = seriesId.toString(),
|
||||
publicUrl = "https://${domain}/series/$seriesId",
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = if (cover != null) {
|
||||
imageUrl(seriesId, cover, 256)
|
||||
} else {
|
||||
@@ -153,7 +154,7 @@ internal class FlameComics(context: MangaLoaderContext) :
|
||||
"Ongoing" -> MangaState.ONGOING
|
||||
else -> null
|
||||
},
|
||||
author = jo.getStringOrNull("author"),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
largeCoverUrl = if (cover != null) {
|
||||
imageUrl(seriesId, cover, 640)
|
||||
} else {
|
||||
|
||||
@@ -91,7 +91,7 @@ internal class FlixScansOrg(context: MangaLoaderContext) :
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
coverUrl = cover,
|
||||
tags = emptySet(),
|
||||
state = when (j.getString("status")) {
|
||||
@@ -101,7 +101,7 @@ internal class FlixScansOrg(context: MangaLoaderContext) :
|
||||
"droped" -> MangaState.ABANDONED
|
||||
else -> null
|
||||
},
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ internal class MangaGeko(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
val doc = webClient.httpGet(url).parseHtml()
|
||||
return doc.select("li.novel-item").map { div ->
|
||||
val href = div.selectFirstOrThrow("a").attrAsRelativeUrl("href")
|
||||
val author = div.selectFirstOrThrow("h6").text().removePrefix("Author(S): ").nullIfEmpty()
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
title = div.selectFirstOrThrow("h4").text(),
|
||||
@@ -84,11 +85,11 @@ internal class MangaGeko(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = div.selectFirstOrThrow("img").src(),
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
author = div.selectFirstOrThrow("h6").text().removePrefix("Author(S): ").nullIfEmpty(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -108,6 +109,7 @@ internal class MangaGeko(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val chaptersDeferred = async { loadChapters(manga.url) }
|
||||
val author = doc.selectFirstOrThrow(".author").textOrNull()
|
||||
manga.copy(
|
||||
altTitle = doc.selectFirstOrThrow(".alternative-title").textOrNull(),
|
||||
state = when (doc.selectFirstOrThrow(".header-stats span:contains(Status) strong").text()) {
|
||||
@@ -122,7 +124,7 @@ internal class MangaGeko(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
author = doc.selectFirstOrThrow(".author").textOrNull(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = doc.selectFirstOrThrow(".description").html(),
|
||||
chapters = chaptersDeferred.await(),
|
||||
)
|
||||
|
||||
@@ -86,10 +86,10 @@ internal class MangaKawaiiEn(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -99,10 +99,11 @@ internal class MangaKawaiiEn(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]").textOrNull()
|
||||
manga.copy(
|
||||
description = doc.selectFirst("dd.text-justify.text-break")?.html(),
|
||||
altTitle = doc.select("span[itemprop*=alternativeHeadline]").joinToString { ", " }.nullIfEmpty(),
|
||||
author = doc.select("a[href*=author]").textOrNull(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (doc.selectFirst("span.badge.bg-success.text-uppercase")?.text()) {
|
||||
"Ongoing" -> MangaState.ONGOING
|
||||
"" -> MangaState.FINISHED
|
||||
|
||||
@@ -110,6 +110,9 @@ internal class MangaTownParser(context: MangaLoaderContext) :
|
||||
val views = li.select("p.view")
|
||||
val status = views.firstNotNullOfOrNull { it.ownText().takeIf { x -> x.startsWith("Status:") } }
|
||||
?.substringAfter(':')?.trim()?.lowercase(Locale.ROOT)
|
||||
val author = views.firstNotNullOfOrNull { it.text().takeIf { x -> x.startsWith("Author:") } }
|
||||
?.substringAfter(':')
|
||||
?.trim()
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
title = a.attr("title"),
|
||||
@@ -118,9 +121,7 @@ internal class MangaTownParser(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = li.selectFirst("p.score")?.selectFirst("b")
|
||||
?.ownText()?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
|
||||
author = views.firstNotNullOfOrNull { it.text().takeIf { x -> x.startsWith("Author:") } }
|
||||
?.substringAfter(':')
|
||||
?.trim(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (status) {
|
||||
"ongoing" -> MangaState.ONGOING
|
||||
"completed" -> MangaState.FINISHED
|
||||
@@ -134,7 +135,7 @@ internal class MangaTownParser(context: MangaLoaderContext) :
|
||||
)
|
||||
}.orEmpty(),
|
||||
url = href,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
publicUrl = href.toAbsoluteUrl(a.host ?: domain),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -109,10 +109,10 @@ internal class Mangaowl(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = div.select("span").last()?.text()?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,11 +129,11 @@ internal class Manhwa18Com(context: MangaLoaderContext) :
|
||||
url = absUrl.toRelativeUrl(domain),
|
||||
publicUrl = absUrl,
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = true,
|
||||
contentRating = ContentRating.ADULT,
|
||||
coverUrl = it.selectFirst("div.img-in-ratio")?.attrAsAbsoluteUrl("data-bg"),
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
largeCoverUrl = null,
|
||||
description = null,
|
||||
source = MangaParserSource.MANHWA18,
|
||||
@@ -166,7 +166,7 @@ internal class Manhwa18Com(context: MangaLoaderContext) :
|
||||
return manga.copy(
|
||||
altTitle = cardInfoElement?.selectFirst("b:contains(Other names)")?.parent()?.ownTextOrNull()
|
||||
?.removePrefix(": "),
|
||||
author = author,
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = docs.selectFirst(".series-summary .summary-content")?.html(),
|
||||
tags = tags.orEmpty(),
|
||||
state = state,
|
||||
|
||||
@@ -129,11 +129,11 @@ internal class Manhwa18Parser(context: MangaLoaderContext) :
|
||||
url = absUrl.toRelativeUrl(domain),
|
||||
publicUrl = absUrl,
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = true,
|
||||
contentRating = ContentRating.ADULT,
|
||||
coverUrl = it.selectFirst("div.img-in-ratio")?.attrAsAbsoluteUrl("data-bg"),
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
largeCoverUrl = null,
|
||||
description = null,
|
||||
source = MangaParserSource.MANHWA18,
|
||||
@@ -166,7 +166,7 @@ internal class Manhwa18Parser(context: MangaLoaderContext) :
|
||||
return manga.copy(
|
||||
altTitle = cardInfoElement?.selectFirst("b:contains(Other names)")?.parent()?.ownTextOrNull()
|
||||
?.removePrefix(": "),
|
||||
author = author,
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = docs.selectFirst(".series-summary .summary-content")?.html(),
|
||||
tags = tags.orEmpty(),
|
||||
state = state,
|
||||
|
||||
@@ -88,10 +88,10 @@ internal class ManhwasMen(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,10 +74,10 @@ internal class MyComicList(context: MangaLoaderContext) : PagedMangaParser(conte
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
title = div.selectFirst("h3 a")?.text().orEmpty(),
|
||||
altTitle = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
tags = emptySet(),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
coverUrl = img?.attrAsAbsoluteUrlOrNull("data-src"),
|
||||
state = null,
|
||||
source = source,
|
||||
@@ -87,6 +87,7 @@ internal class MyComicList(context: MangaLoaderContext) : PagedMangaParser(conte
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val author = doc.selectFirst("td:contains(Author:) + td")?.textOrNull()
|
||||
return manga.copy(
|
||||
tags = doc.select("td:contains(Genres:) + td a").mapToSet { a ->
|
||||
MangaTag(
|
||||
@@ -95,7 +96,7 @@ internal class MyComicList(context: MangaLoaderContext) : PagedMangaParser(conte
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
author = doc.selectFirst("td:contains(Author:) + td")?.textOrNull(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (doc.selectFirst("td:contains(Status:) + td a")?.text()?.lowercase()) {
|
||||
"ongoing" -> MangaState.ONGOING
|
||||
"completed" -> MangaState.FINISHED
|
||||
|
||||
@@ -49,11 +49,11 @@ internal class Po2Scans(context: MangaLoaderContext) : SinglePageMangaParser(con
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = div.selectFirstOrThrow("img").src(),
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -62,6 +62,7 @@ internal class Po2Scans(context: MangaLoaderContext) : SinglePageMangaParser(con
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val dateFormat = SimpleDateFormat("dd MMM, yy", Locale.ENGLISH)
|
||||
val author = doc.selectLast(".author span")?.textOrNull()
|
||||
return manga.copy(
|
||||
state = when (doc.select(".status span").last()?.text()) {
|
||||
"Ongoing" -> MangaState.ONGOING
|
||||
@@ -69,7 +70,7 @@ internal class Po2Scans(context: MangaLoaderContext) : SinglePageMangaParser(con
|
||||
else -> null
|
||||
},
|
||||
tags = emptySet(),
|
||||
author = doc.selectLast(".author span")?.textOrNull(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = doc.selectFirstOrThrow(".summary").html(),
|
||||
chapters = doc.select(".chap-section .chap")
|
||||
.mapChapters(reversed = true) { i, div ->
|
||||
|
||||
@@ -99,10 +99,10 @@ internal class Pururin(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -133,6 +133,7 @@ internal class Pururin(context: MangaLoaderContext) :
|
||||
override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val author = doc.selectFirst("a[itemprop=author]")?.text()
|
||||
manga.copy(
|
||||
description = doc.selectFirst("p.mb-2")?.text().orEmpty(),
|
||||
rating = doc.selectFirst("td span.rating")?.attr("content")?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
|
||||
@@ -144,7 +145,7 @@ internal class Pururin(context: MangaLoaderContext) :
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
author = doc.selectFirst("a[itemprop=author]")?.text(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
chapters = listOf(
|
||||
MangaChapter(
|
||||
id = manga.id,
|
||||
@@ -175,10 +176,10 @@ internal class Pururin(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,10 +110,10 @@ internal class VyManga(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -179,6 +179,7 @@ internal class WeebCentral(context: MangaLoaderContext) : MangaParser(context, M
|
||||
.attrAsAbsoluteUrl("href")
|
||||
.toHttpUrl()
|
||||
.pathSegments[1]
|
||||
val author = document.select("div:contains(author) a").eachText().joinToString().nullIfEmpty()
|
||||
Manga(
|
||||
id = generateUid(mangaId),
|
||||
url = mangaId,
|
||||
@@ -210,7 +211,7 @@ internal class WeebCentral(context: MangaLoaderContext) : MangaParser(context, M
|
||||
"Hiatus" -> PAUSED
|
||||
else -> null
|
||||
},
|
||||
author = document.select("div:contains(author) a").eachText().joinToString().nullIfEmpty(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
largeCoverUrl = null,
|
||||
chapters = null,
|
||||
source = source,
|
||||
@@ -226,6 +227,8 @@ internal class WeebCentral(context: MangaLoaderContext) : MangaParser(context, M
|
||||
|
||||
val sectionLeft = document.select("section[x-data] > section")[0]
|
||||
val sectionRight = document.select("section[x-data] > section")[1]
|
||||
val author = sectionLeft.select("ul > li:has(strong:contains(Author)) > span > a")
|
||||
.eachText().joinToString()
|
||||
|
||||
manga.copy(
|
||||
title = sectionRight.selectFirstOrThrow("h1").text(),
|
||||
@@ -253,8 +256,7 @@ internal class WeebCentral(context: MangaLoaderContext) : MangaParser(context, M
|
||||
"Hiatus" -> PAUSED
|
||||
else -> null
|
||||
},
|
||||
author = sectionLeft.select("ul > li:has(strong:contains(Author)) > span > a")
|
||||
.eachText().joinToString(),
|
||||
authors = setOf(author),
|
||||
description = Element("div").also { desc ->
|
||||
sectionRight.selectFirst("li:has(strong:contains(Description)) > p")?.let {
|
||||
desc.appendChild(it)
|
||||
|
||||
@@ -47,10 +47,10 @@ internal class TempleScanEsp(context: MangaLoaderContext) :
|
||||
altTitle = it.getStringOrNull("alternativeName"),
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -151,6 +151,7 @@ internal class TuMangaOnlineParser(context: MangaLoaderContext) : PagedMangaPars
|
||||
val doc = webClient.httpGet(url, getRequestHeaders()).parseHtml()
|
||||
val items = doc.body().select("div.element")
|
||||
return items.mapNotNull { item ->
|
||||
val isNsfwSource = item.select("i").hasClass("fas fa-heartbeat fa-2x")
|
||||
val href =
|
||||
item.selectFirst("a")?.attrAsRelativeUrlOrNull("href")?.substringAfter(' ') ?: return@mapNotNull null
|
||||
Manga(
|
||||
@@ -158,10 +159,10 @@ internal class TuMangaOnlineParser(context: MangaLoaderContext) : PagedMangaPars
|
||||
title = item.selectFirst("h4.text-truncate")?.text() ?: return@mapNotNull null,
|
||||
coverUrl = item.select("style").toString().substringAfter("('").substringBeforeLast("')"),
|
||||
altTitle = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
rating = item.selectFirst("span.score")?.text()?.toFloatOrNull()?.div(10F) ?: RATING_UNKNOWN,
|
||||
url = href,
|
||||
isNsfw = item.select("i").hasClass("fas fa-heartbeat fa-2x"),
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
publicUrl = href.toAbsoluteUrl(doc.host ?: domain),
|
||||
@@ -174,6 +175,7 @@ internal class TuMangaOnlineParser(context: MangaLoaderContext) : PagedMangaPars
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val contents = doc.body().selectFirstOrThrow("section.element-header-content")
|
||||
val author = contents.selectFirst("h5.card-title")?.attr("title")?.substringAfter(", ")
|
||||
return manga.copy(
|
||||
description = contents.selectFirst("p.element-description")?.html(),
|
||||
tags = contents.select("h6 a").mapToSet { a ->
|
||||
@@ -185,7 +187,7 @@ internal class TuMangaOnlineParser(context: MangaLoaderContext) : PagedMangaPars
|
||||
},
|
||||
largeCoverUrl = contents.selectFirst(".book-thumbnail")?.attrAsAbsoluteUrlOrNull("src"),
|
||||
state = parseStatus(contents.select("span.book-status").text().orEmpty()),
|
||||
author = contents.selectFirst("h5.card-title")?.attr("title")?.substringAfter(", "),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
chapters = if (doc.select("div.chapters").isEmpty()) {
|
||||
doc.select(oneShotChapterListSelector).mapChapters(reversed = true) { _, item ->
|
||||
oneShotChapterFromElement(item)
|
||||
|
||||
@@ -147,10 +147,10 @@ internal abstract class FmreaderParser(
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -190,7 +190,7 @@ internal abstract class FmreaderParser(
|
||||
}
|
||||
}
|
||||
val alt = doc.body().selectFirst(selectAlt)?.text()?.replace("Other names", "")?.nullIfEmpty()
|
||||
val auth = doc.body().selectFirst(selectAut)?.textOrNull()
|
||||
val author = doc.body().selectFirst(selectAut)?.textOrNull()
|
||||
manga.copy(
|
||||
tags = doc.body().select(selectTag).mapToSet { a ->
|
||||
MangaTag(
|
||||
@@ -201,7 +201,7 @@ internal abstract class FmreaderParser(
|
||||
},
|
||||
description = desc,
|
||||
altTitle = alt,
|
||||
author = auth,
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = state,
|
||||
chapters = chaptersDeferred.await(),
|
||||
)
|
||||
|
||||
@@ -35,10 +35,10 @@ internal class Klz9(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,10 +93,10 @@ internal abstract class FoolSlideParser(
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ internal abstract class FoolSlideParser(
|
||||
manga.copy(
|
||||
coverUrl = doc.selectFirst(".thumbnail img")?.src() ?: manga.coverUrl,
|
||||
description = desc?.nullIfEmpty(),
|
||||
author = author?.nullIfEmpty(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
chapters = chapters,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ internal class Seinagi(context: MangaLoaderContext) :
|
||||
manga.copy(
|
||||
coverUrl = doc.selectFirst(".thumbnail img")?.src() ?: manga.coverUrl,
|
||||
description = desc?.nullIfEmpty(),
|
||||
author = author?.nullIfEmpty(),
|
||||
authors = author?.nullIfEmpty()?.let { setOf(it) } ?: emptySet(),
|
||||
chapters = chapters,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ internal class Pzykosis666hFansub(context: MangaLoaderContext) :
|
||||
manga.copy(
|
||||
coverUrl = doc.selectFirst(".thumbnail img")?.src() ?: manga.coverUrl,
|
||||
description = desc?.nullIfEmpty(),
|
||||
author = author?.nullIfEmpty(),
|
||||
authors = author?.nullIfEmpty()?.let { setOf(it) } ?: emptySet(),
|
||||
chapters = chapters,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ internal class SeinagiAdulto(context: MangaLoaderContext) :
|
||||
manga.copy(
|
||||
coverUrl = doc.selectFirst(".thumbnail img")?.src(),// for manga result on search
|
||||
description = desc?.nullIfEmpty(),
|
||||
author = author?.nullIfEmpty(),
|
||||
authors = author?.nullIfEmpty()?.let { setOf(it) } ?: emptySet(),
|
||||
chapters = chapters,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -111,6 +111,7 @@ internal class BentomangaParser(context: MangaLoaderContext) :
|
||||
return root.select(".manga[data-manga]").map { div ->
|
||||
val header = div.selectFirstOrThrow(".manga_header")
|
||||
val href = header.selectFirstOrThrow("a").attrAsRelativeUrl("href")
|
||||
val isNsfwSource = div.selectFirst(".badge-adult_content") != null
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
title = div.selectFirst("h1")?.text().orEmpty(),
|
||||
@@ -123,7 +124,7 @@ internal class BentomangaParser(context: MangaLoaderContext) :
|
||||
?.toFloatOrNull()
|
||||
?.div(10f)
|
||||
?: RATING_UNKNOWN,
|
||||
isNsfw = div.selectFirst(".badge-adult_content") != null,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
coverUrl = div.selectFirst("img")?.src().assertNotNull("src"),
|
||||
tags = div.selectFirst(".component-manga-categories")
|
||||
.assertNotNull("tags")
|
||||
@@ -136,7 +137,7 @@ internal class BentomangaParser(context: MangaLoaderContext) :
|
||||
)
|
||||
}.orEmpty(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
description = div.selectFirst(".manga_synopsis")?.html().assertNotNull("description"),
|
||||
source = source,
|
||||
)
|
||||
@@ -147,6 +148,7 @@ internal class BentomangaParser(context: MangaLoaderContext) :
|
||||
val mangaUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val root = webClient.httpGet(mangaUrl).parseHtml()
|
||||
.requireElementById("container_manga_show")
|
||||
val author = root.selectFirst(".datas_more-authors-people")?.textOrNull()
|
||||
return manga.copy(
|
||||
altTitle = root.selectFirst(".component-manga-title_alt")?.textOrNull(),
|
||||
description = root.selectFirst(".datas_synopsis")?.html().assertNotNull("description")
|
||||
@@ -158,7 +160,7 @@ internal class BentomangaParser(context: MangaLoaderContext) :
|
||||
"En pause" -> MangaState.PAUSED
|
||||
else -> null
|
||||
},
|
||||
author = root.selectFirst(".datas_more-authors-people")?.textOrNull(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
chapters = run {
|
||||
val input = root.selectFirst("input[name=\"limit\"]") ?: return@run parseChapters(root)
|
||||
val max = input.attr("max").toInt()
|
||||
|
||||
@@ -74,10 +74,10 @@ internal class FuryoSociety(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -136,11 +136,11 @@ internal class LegacyScansParser(context: MangaLoaderContext) :
|
||||
url = urlManga,
|
||||
publicUrl = urlManga,
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = "https://api.$domain/" + j.getString("cover"),
|
||||
tags = setOf(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -157,11 +157,11 @@ internal class LegacyScansParser(context: MangaLoaderContext) :
|
||||
url = urlManga,
|
||||
publicUrl = urlManga,
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = null,
|
||||
tags = setOf(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -170,6 +170,7 @@ internal class LegacyScansParser(context: MangaLoaderContext) :
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val root = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val dateFormat = SimpleDateFormat("dd/MM/yyyy", Locale.FRENCH)
|
||||
val author = root.select("div.serieAdd p:contains(Auteur:) strong").textOrNull()
|
||||
return manga.copy(
|
||||
tags = root.select("div.serieGenre span").mapToSet { span ->
|
||||
MangaTag(
|
||||
@@ -179,7 +180,7 @@ internal class LegacyScansParser(context: MangaLoaderContext) :
|
||||
)
|
||||
},
|
||||
coverUrl = root.selectFirst("div.serieImg img")?.attrAsAbsoluteUrlOrNull("src"),
|
||||
author = root.select("div.serieAdd p:contains(Auteur:) strong").textOrNull(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = root.selectFirst("div.serieDescription div")?.html(),
|
||||
chapters = root.select("div.chapterList a")
|
||||
.mapChapters(reversed = true) { i, a ->
|
||||
|
||||
@@ -72,11 +72,11 @@ internal class LireScan(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = div.selectFirstOrThrow(".item__rating").ownText().toFloatOrNull()?.div(10f) ?: RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = div.selectFirstOrThrow("img").attrAsAbsoluteUrl("src"),
|
||||
tags = setOf(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -85,6 +85,9 @@ internal class LireScan(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val root = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val dateFormat = SimpleDateFormat("dd-MM-yyyy", Locale.FRANCE)
|
||||
val author = root.select("ul.pmovie__list li:contains(Artist(s):)").text()
|
||||
.replace("Artist(s):", "")
|
||||
.nullIfEmpty()
|
||||
return manga.copy(
|
||||
altTitle = root.select("ul.pmovie__list li:contains(Nom Alternatif:)").text()
|
||||
.replace("Nom Alternatif:", "").nullIfEmpty(),
|
||||
@@ -101,9 +104,7 @@ internal class LireScan(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
author = root.select("ul.pmovie__list li:contains(Artist(s):)").text()
|
||||
.replace("Artist(s):", "")
|
||||
.nullIfEmpty(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = root.selectFirst("div.pmovie__text")?.html(),
|
||||
chapters = root.select("ul li div.chapter")
|
||||
.mapChapters(reversed = true) { i, div ->
|
||||
|
||||
@@ -111,11 +111,11 @@ internal class LugnicaScans(context: MangaLoaderContext) :
|
||||
url = urlManga.toRelativeUrl(domain),
|
||||
publicUrl = urlManga.toAbsoluteUrl(domain),
|
||||
rating = j.getFloatOrDefault("manga_rate", RATING_UNKNOWN).div(5f),
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = img,
|
||||
tags = setOf(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -132,7 +132,7 @@ internal class LugnicaScans(context: MangaLoaderContext) :
|
||||
url = urlManga.toRelativeUrl(domain),
|
||||
publicUrl = urlManga.toAbsoluteUrl(domain),
|
||||
rating = j.getString("rate").toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = img,
|
||||
tags = setOf(),
|
||||
state = when (j.getString("status")) {
|
||||
@@ -141,7 +141,7 @@ internal class LugnicaScans(context: MangaLoaderContext) :
|
||||
"3" -> MangaState.ABANDONED
|
||||
else -> null
|
||||
},
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -161,6 +161,7 @@ internal class LugnicaScans(context: MangaLoaderContext) :
|
||||
}
|
||||
val slug = manga.url.substringAfterLast("/")
|
||||
val dateFormat = SimpleDateFormat("dd-MM-yyyy", Locale.FRANCE)
|
||||
val author = jsonManga.getStringOrNull("author")
|
||||
return manga.copy(
|
||||
state = when (jsonManga.getString("status")) {
|
||||
"0" -> MangaState.ONGOING
|
||||
@@ -168,7 +169,7 @@ internal class LugnicaScans(context: MangaLoaderContext) :
|
||||
"3" -> MangaState.ABANDONED
|
||||
else -> null
|
||||
},
|
||||
author = jsonManga.getStringOrNull("author"),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = jsonManga.getStringOrNull("description"),
|
||||
chapters = chapters.mapChapters { i, it ->
|
||||
val id = it.substringAfter("\"chapter\":").substringBefore(",")
|
||||
|
||||
@@ -85,10 +85,10 @@ internal class MangaKawaii(context: MangaLoaderContext) : PagedMangaParser(conte
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -98,10 +98,11 @@ internal class MangaKawaii(context: MangaLoaderContext) : PagedMangaParser(conte
|
||||
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()
|
||||
manga.copy(
|
||||
description = doc.selectFirst("dd.text-justify.text-break")?.html(),
|
||||
altTitle = doc.select("span[itemprop*=alternativeHeadline]").joinToString { ", " }.nullIfEmpty(),
|
||||
author = doc.select("a[href*=author]").text(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (doc.selectFirst("span.badge.bg-success.text-uppercase")?.text()) {
|
||||
"En Cours" -> MangaState.ONGOING
|
||||
"Terminé" -> MangaState.FINISHED
|
||||
|
||||
@@ -68,17 +68,18 @@ internal class MangaMana(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
val slug = jo.getString("slug") ?: throw ParseException("Missing Slug", url)
|
||||
val url = "https://$domain/m/$slug"
|
||||
val img = "https://$domainCdn/uploads/manga/$slug/cover/cover_thumb.jpg"
|
||||
val isNsfwSource = when (jo.getIntOrDefault("caution", 0)) {
|
||||
0 -> false
|
||||
2 -> true
|
||||
else -> false
|
||||
}
|
||||
Manga(
|
||||
id = generateUid(url),
|
||||
title = jo.getString("name").orEmpty(),
|
||||
coverUrl = img,
|
||||
altTitle = jo.getString("otherNames").orEmpty(),
|
||||
author = null,
|
||||
isNsfw = when (jo.getIntOrDefault("caution", 0)) {
|
||||
0 -> false
|
||||
2 -> true
|
||||
else -> false
|
||||
},
|
||||
authors = emptySet(),
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
rating = RATING_UNKNOWN,
|
||||
url = url,
|
||||
description = jo.getString("summary_old").orEmpty(),
|
||||
@@ -107,8 +108,8 @@ internal class MangaMana(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
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 isNsfw = div.selectFirst("img[data-adult]")?.attr("data-adult")?.isNotEmpty() == true
|
||||
val img = if (isNsfw) {
|
||||
val isNsfwSource = div.selectFirst("img[data-adult]")?.attr("data-adult")?.isNotEmpty() == true
|
||||
val img = if (isNsfwSource) {
|
||||
div.selectFirst("img")?.attr("data-adult")
|
||||
} else {
|
||||
div.selectFirst("img")?.attr("data-src")?.replace(" ", "")
|
||||
@@ -120,12 +121,12 @@ internal class MangaMana(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = isNsfw,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
coverUrl = img,
|
||||
description = null,
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -170,8 +171,8 @@ internal class MangaMana(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
|
||||
return doc.select("div.p-2 div.col").map { div ->
|
||||
val href = div.selectFirstOrThrow("a").attrAsRelativeUrl("href")
|
||||
val isNsfw = div.selectFirst("img[data-adult]")?.attr("data-adult")?.isNotEmpty() == true
|
||||
val img = if (isNsfw) {
|
||||
val isNsfwSource = div.selectFirst("img[data-adult]")?.attr("data-adult")?.isNotEmpty() == true
|
||||
val img = if (isNsfwSource) {
|
||||
div.selectFirst("img")?.attr("data-adult")
|
||||
} else {
|
||||
div.selectFirst("img")?.attr("data-src")?.replace(" ", "")
|
||||
@@ -183,7 +184,7 @@ internal class MangaMana(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = div.getElementById("avgrating")?.ownText()?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN,
|
||||
isNsfw = isNsfw,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
coverUrl = img,
|
||||
description = div.selectFirst(".mangalist_item_description")?.text().orEmpty(),
|
||||
tags = div.select("div.mb-1 a").mapToSet {
|
||||
@@ -195,7 +196,7 @@ internal class MangaMana(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
)
|
||||
},
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -228,6 +229,7 @@ internal class MangaMana(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
val doc = webClient.httpGet(mangaUrl).parseHtml()
|
||||
val maxPageChapterSelect = doc.select("ul.pagination a.page-link")
|
||||
var maxPageChapter = 1
|
||||
val author = doc.selectFirst("div.show_details span[itemprop=author]")?.text().orEmpty()
|
||||
if (!maxPageChapterSelect.isNullOrEmpty()) {
|
||||
maxPageChapterSelect.map {
|
||||
val i = it.attr("href").substringAfterLast("=").toInt()
|
||||
@@ -243,7 +245,7 @@ internal class MangaMana(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
"Abandonné" -> MangaState.ABANDONED
|
||||
else -> null
|
||||
},
|
||||
author = doc.selectFirst("div.show_details span[itemprop=author]")?.text().orEmpty(),
|
||||
authors = setOf(author),
|
||||
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").mapToSet {
|
||||
|
||||
@@ -87,10 +87,10 @@ internal class ScansMangasMe(context: MangaLoaderContext) :
|
||||
rating = div.selectFirstOrThrow("div.rating i").ownText().toFloatOrNull()?.div(10f)
|
||||
?: RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -114,7 +114,7 @@ internal class ScansMangasMe(context: MangaLoaderContext) :
|
||||
val chaptersDeferred = getChapters(doc)
|
||||
val desc = doc.selectFirstOrThrow("div.desc").html().nullIfEmpty()
|
||||
val alt = doc.body().select("div.infox span.alter").textOrNull()
|
||||
val aut = doc.select("div.spe span")[2].text().replace("Auteur:", "").nullIfEmpty()
|
||||
val author = doc.select("div.spe span")[2].text().replace("Auteur:", "").nullIfEmpty()
|
||||
manga.copy(
|
||||
tags = doc.select("div.spe span:contains(Genres) a").mapToSet { a ->
|
||||
MangaTag(
|
||||
@@ -125,7 +125,7 @@ internal class ScansMangasMe(context: MangaLoaderContext) :
|
||||
},
|
||||
description = desc,
|
||||
altTitle = alt,
|
||||
author = aut,
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (doc.selectFirstOrThrow("div.spe span:contains(Statut:)").textOrNull()
|
||||
?.substringAfterLast(':')) {
|
||||
" En cours" -> MangaState.ONGOING
|
||||
|
||||
@@ -88,11 +88,11 @@ internal class ScantradUnion(context: MangaLoaderContext) :
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = article.selectFirst("img.attachment-thumbnail")?.attrAsAbsoluteUrl("src"),
|
||||
tags = setOf(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -108,11 +108,11 @@ internal class ScantradUnion(context: MangaLoaderContext) :
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = article.selectFirst("img")?.attrAsAbsoluteUrl("src"),
|
||||
tags = setOf(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -122,6 +122,7 @@ internal class ScantradUnion(context: MangaLoaderContext) :
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val root = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml().requireElementById("main")
|
||||
val dateFormat = SimpleDateFormat("dd-MM-yyyy", Locale.FRANCE)
|
||||
val author = root.select("div.project-details a[href*=auteur]").textOrNull()
|
||||
|
||||
return manga.copy(
|
||||
altTitle = root.select(".divider2:contains(Noms associés :)").firstOrNull()?.textOrNull(),
|
||||
@@ -137,7 +138,7 @@ internal class ScantradUnion(context: MangaLoaderContext) :
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
author = root.select("div.project-details a[href*=auteur]").textOrNull(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = root.selectFirst("p.sContent")?.html(),
|
||||
chapters = root.select("div.chapter-list li")
|
||||
.mapChapters(reversed = true) { i, li ->
|
||||
|
||||
@@ -152,10 +152,10 @@ internal abstract class FuzzyDoodleParser(
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -181,6 +181,7 @@ internal abstract class FuzzyDoodleParser(
|
||||
}
|
||||
}
|
||||
}
|
||||
val author = doc.selectFirst(selectAuthor)?.textOrNull()
|
||||
|
||||
manga.copy(
|
||||
altTitle = doc.selectLast(selectAltTitle)?.textOrNull(),
|
||||
@@ -191,7 +192,7 @@ internal abstract class FuzzyDoodleParser(
|
||||
in paused -> MangaState.PAUSED
|
||||
else -> null
|
||||
},
|
||||
author = doc.selectFirst(selectAuthor)?.textOrNull(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = doc.select(selectDescription).html(),
|
||||
tags = doc.select(selectTagManga).mapToSet {
|
||||
val key = it.attr("href").substringAfterLast('=')
|
||||
|
||||
@@ -113,11 +113,11 @@ internal abstract class GalleryAdultsParser(
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
coverUrl = div.selectFirst(selectGalleryImg)?.src(),
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -165,10 +165,11 @@ internal abstract class GalleryAdultsParser(
|
||||
val branch = doc.select(selectLanguageChapter).joinToString(separator = " / ") {
|
||||
it.html().substringBefore("<")
|
||||
}
|
||||
val author = doc.selectFirst(selectAuthor)?.html()?.substringBefore("<span")
|
||||
return manga.copy(
|
||||
tags = tag.orEmpty(),
|
||||
title = doc.selectFirst(selectTitle)?.textOrNull()?.cleanupTitle() ?: manga.title,
|
||||
author = doc.selectFirst(selectAuthor)?.html()?.substringBefore("<span"),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
chapters = listOf(
|
||||
MangaChapter(
|
||||
id = manga.id,
|
||||
|
||||
@@ -43,11 +43,11 @@ internal class DoujinDesuUk(context: MangaLoaderContext) :
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
coverUrl = div.selectLastOrThrow(selectGalleryImg).src(),
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -126,9 +126,10 @@ internal class HentaiEra(context: MangaLoaderContext) :
|
||||
val branch = doc.select(selectLanguageChapter).joinToString(separator = " / ") {
|
||||
it.text()
|
||||
}
|
||||
val author = doc.selectFirst(selectAuthor)?.text()
|
||||
return manga.copy(
|
||||
tags = tag.orEmpty(),
|
||||
author = doc.selectFirst(selectAuthor)?.text(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
chapters = listOf(
|
||||
MangaChapter(
|
||||
id = manga.id,
|
||||
|
||||
@@ -94,11 +94,11 @@ internal class NHentaiParser(context: MangaLoaderContext) :
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
coverUrl = div.selectFirstOrThrow(selectGalleryImg).src(),
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ internal class NHentaiToParser(context: MangaLoaderContext) :
|
||||
coverUrl = div.selectFirstOrThrow(selectGalleryImg).src(),
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
largeCoverUrl = null,
|
||||
description = null,
|
||||
chapters = null,
|
||||
|
||||
@@ -101,7 +101,7 @@ internal class NHentaiXxxParser(context: MangaLoaderContext) :
|
||||
coverUrl = div.selectFirstOrThrow(selectGalleryImg).src(),
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
largeCoverUrl = null,
|
||||
description = null,
|
||||
chapters = null,
|
||||
|
||||
@@ -84,8 +84,8 @@ internal abstract class GattsuParser(
|
||||
tags = emptySet(),
|
||||
description = null,
|
||||
state = null,
|
||||
author = null,
|
||||
isNsfw = isNsfwSource,
|
||||
authors = emptySet(),
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -111,12 +111,12 @@ internal abstract class GattsuParser(
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val urlChapter = doc.selectFirstOrThrow("ul.post-fotos li a, ul.paginaPostBotoes a").attrAsAbsoluteUrl("href")
|
||||
val author = doc.selectFirst(".post-itens li:contains(Autor) a, .paginaPostInfo li:contains(Artista) a")?.text()
|
||||
return manga.copy(
|
||||
description = doc.selectFirst("div.post-texto")?.html(),
|
||||
tags = doc.selectFirst(".post-itens li:contains(Tags), .paginaPostInfo li:contains(Categorias)")
|
||||
?.parseTags().orEmpty(),
|
||||
author = doc.selectFirst(".post-itens li:contains(Autor) a, .paginaPostInfo li:contains(Artista) a")
|
||||
?.text(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
chapters = listOf(
|
||||
MangaChapter(
|
||||
id = manga.id,
|
||||
|
||||
@@ -3,10 +3,7 @@ package org.koitharu.kotatsu.parsers.site.gattsu.pt
|
||||
import org.jsoup.nodes.Document
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.ContentType
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaParserSource
|
||||
import org.koitharu.kotatsu.parsers.model.RATING_UNKNOWN
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.site.gattsu.GattsuParser
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
|
||||
@@ -35,8 +32,8 @@ internal class MundoHentaiOficial(context: MangaLoaderContext) :
|
||||
tags = emptySet(),
|
||||
description = null,
|
||||
state = null,
|
||||
author = null,
|
||||
isNsfw = isNsfwSource,
|
||||
authors = emptySet(),
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ internal abstract class GuyaParser(
|
||||
private fun addManga(j: JSONObject, name: String): Manga {
|
||||
val url = "https://$domain/read/manga/" + j.getString("slug")
|
||||
val apiUrl = "https://$domain/api/series/" + j.getString("slug")
|
||||
val author = j.getString("author")
|
||||
return Manga(
|
||||
id = generateUid(apiUrl),
|
||||
url = apiUrl,
|
||||
@@ -71,8 +72,8 @@ internal abstract class GuyaParser(
|
||||
tags = emptySet(),
|
||||
description = j.getString("description"),
|
||||
state = null,
|
||||
author = j.getString("author"),
|
||||
isNsfw = isNsfwSource,
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ internal abstract class HeanCms(
|
||||
publicUrl = publicUrl.toAbsoluteUrl(domain),
|
||||
description = it.getString("description"),
|
||||
rating = it.getFloatOrDefault("rating", RATING_UNKNOWN) / 5f,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
coverUrl = cover,
|
||||
tags = emptySet(),
|
||||
state = when (it.getString("status")) {
|
||||
@@ -139,7 +139,7 @@ internal abstract class HeanCms(
|
||||
"Hiatus" -> MangaState.PAUSED
|
||||
else -> null
|
||||
},
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -70,10 +70,10 @@ internal abstract class HeanCmsAlt(
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,6 +100,8 @@ internal abstract class HotComicsParser(
|
||||
}
|
||||
|
||||
val tags = li.select(".etc span").mapNotNullToSet { tagMap[it.text()] }
|
||||
val isNsfwSource = a.selectFirst(".ico-18plus") != null
|
||||
val author = li.selectFirst(".writer")?.text().orEmpty()
|
||||
|
||||
Manga(
|
||||
id = generateUid(url),
|
||||
@@ -111,14 +113,14 @@ internal abstract class HotComicsParser(
|
||||
rating = RATING_UNKNOWN,
|
||||
description = li.selectFirst("p[itemprop*=description]")?.text().orEmpty(),
|
||||
tags = tags,
|
||||
author = li.selectFirst(".writer")?.text().orEmpty(),
|
||||
authors = setOf(author),
|
||||
state = if (doc.selectFirst(".ico_fin") != null) {
|
||||
MangaState.FINISHED
|
||||
} else {
|
||||
MangaState.ONGOING
|
||||
},
|
||||
source = source,
|
||||
isNsfw = a.selectFirst(".ico-18plus") != null,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,11 +120,11 @@ internal class DoujinDesuParser(context: MangaLoaderContext) :
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = true,
|
||||
contentRating = ContentRating.ADULT,
|
||||
coverUrl = it.selectFirst(".thumbnail > img")?.src(),
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
largeCoverUrl = null,
|
||||
description = null,
|
||||
source = source,
|
||||
@@ -141,8 +141,9 @@ internal class DoujinDesuParser(context: MangaLoaderContext) :
|
||||
"Publishing" -> MangaState.ONGOING
|
||||
else -> null
|
||||
}
|
||||
val author = metadataEl?.selectFirst("tr:contains(Author)")?.selectLast("td")?.text()
|
||||
return manga.copy(
|
||||
author = metadataEl?.selectFirst("tr:contains(Author)")?.selectLast("td")?.text(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = docs.selectFirst(".wrapper > .metadata > .pb-2")?.selectFirst("p")?.html(),
|
||||
state = state,
|
||||
rating = metadataEl?.selectFirst(".rating-prc")?.ownText()?.toFloatOrNull()?.div(10f) ?: RATING_UNKNOWN,
|
||||
|
||||
@@ -71,10 +71,10 @@ internal class HentaiCrot(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -95,10 +95,11 @@ internal class HentaiCrot(context: MangaLoaderContext) :
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
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(),
|
||||
author = doc.selectFirst("div.entry-content ul li:contains(Artists :) em")?.textOrNull(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = null,
|
||||
chapters = listOf(
|
||||
MangaChapter(
|
||||
|
||||
@@ -71,10 +71,10 @@ internal class PixHentai(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -95,10 +95,11 @@ internal class PixHentai(context: MangaLoaderContext) :
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
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(),
|
||||
author = doc.selectFirst("div.entry-content ul li:contains(Artists :) em")?.textOrNull(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = null,
|
||||
chapters = listOf(
|
||||
MangaChapter(
|
||||
|
||||
@@ -101,6 +101,8 @@ internal abstract class IkenParser(
|
||||
protected open fun parseMangaList(json: JSONObject): List<Manga> {
|
||||
return json.getJSONArray("posts").mapJSON {
|
||||
val url = "/series/${it.getString("slug")}"
|
||||
val isNsfwSource = it.getBooleanOrDefault("hot", false)
|
||||
val author = it.getString("author")
|
||||
Manga(
|
||||
id = it.getLong("id"),
|
||||
url = url,
|
||||
@@ -111,7 +113,7 @@ internal abstract class IkenParser(
|
||||
description = it.getString("postContent"),
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = it.getString("author"),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (it.getString("seriesStatus")) {
|
||||
"ONGOING" -> MangaState.ONGOING
|
||||
"COMPLETED" -> MangaState.FINISHED
|
||||
@@ -120,7 +122,7 @@ internal abstract class IkenParser(
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
isNsfw = it.getBooleanOrDefault("hot", false),
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,15 +84,16 @@ internal class NicovideoSeigaParser(context: MangaLoaderContext) :
|
||||
val href =
|
||||
item.selectFirst(".comic_icon > div > a")?.attrAsRelativeUrlOrNull("href") ?: return@mapNotNull null
|
||||
val statusText = item.selectFirst(".mg_description_header > .mg_icon > .content_status > span")?.text()
|
||||
val author = item.selectFirst(".mg_description_header > .mg_author > a")?.text()
|
||||
Manga(
|
||||
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,
|
||||
author = item.selectFirst(".mg_description_header > .mg_author > a")?.text(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
rating = RATING_UNKNOWN,
|
||||
url = href,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
tags = item.getElementsByAttributeValueContaining("href", "?category=").mapToSet { a ->
|
||||
MangaTag(
|
||||
key = a.attr("href").substringAfterLast('='),
|
||||
@@ -193,11 +194,11 @@ internal class NicovideoSeigaParser(context: MangaLoaderContext) :
|
||||
title = item.selectFirst(".search_result__item__info > .search_result__item__info--title > a")
|
||||
?.textOrNull() ?: return@mapNotNull null,
|
||||
altTitle = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
tags = emptySet(),
|
||||
rating = RATING_UNKNOWN,
|
||||
state = null,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
source = source,
|
||||
coverUrl = item.selectFirst(".search_result__item__thumbnail > a > img")
|
||||
?.attrAsAbsoluteUrl("data-original"),
|
||||
|
||||
@@ -138,10 +138,10 @@ internal abstract class KeyoappParser(
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -115,11 +115,11 @@ internal abstract class LikeMangaParser(
|
||||
url = href,
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
contentRating = null,
|
||||
coverUrl = div.selectFirstOrThrow("img").src(),
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
@@ -149,6 +149,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(),
|
||||
tags = doc.select("li.kind a").mapToSet { a ->
|
||||
@@ -158,7 +159,7 @@ internal abstract class LikeMangaParser(
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
author = doc.selectLast("li.author p")?.textOrNull(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
description = doc.requireElementById("summary_shortened").html(),
|
||||
chapters = run {
|
||||
if (maxPageChapter == 1) {
|
||||
|
||||
@@ -119,10 +119,10 @@ internal abstract class LilianaParser(
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -148,6 +148,9 @@ internal abstract class LilianaParser(
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val author = doc.selectFirst("div.y6x11p i.fas.fa-user + span.dt")?.textOrNull()?.takeUnless {
|
||||
it.equals("updating", true)
|
||||
}
|
||||
return manga.copy(
|
||||
description = doc.selectFirst("div#syn-target")?.html(),
|
||||
largeCoverUrl = doc.selectFirst(".a1 > figure img")?.src(),
|
||||
@@ -158,9 +161,7 @@ internal abstract class LilianaParser(
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
author = doc.selectFirst("div.y6x11p i.fas.fa-user + span.dt")?.textOrNull()?.takeUnless {
|
||||
it.equals("updating", true)
|
||||
},
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (doc.selectFirst("div.y6x11p i.fas.fa-rss + span.dt")?.text()?.lowercase().orEmpty()) {
|
||||
in ongoing -> MangaState.ONGOING
|
||||
in finished -> MangaState.FINISHED
|
||||
|
||||
@@ -460,6 +460,7 @@ internal abstract class MadaraParser(
|
||||
}.map { div ->
|
||||
val href = div.selectFirstOrThrow("a").attrAsRelativeUrl("href")
|
||||
val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".item-summary")
|
||||
val author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText()
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
@@ -476,7 +477,7 @@ internal abstract class MadaraParser(
|
||||
source = source,
|
||||
)
|
||||
}.orEmpty(),
|
||||
author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (
|
||||
summary?.selectFirst(".mg_status")
|
||||
?.selectFirst(".summary-content")
|
||||
@@ -491,7 +492,7 @@ internal abstract class MadaraParser(
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -660,12 +661,12 @@ internal abstract class MadaraParser(
|
||||
publicUrl = href.toAbsoluteUrl(a.host ?: domain),
|
||||
altTitle = null,
|
||||
title = div.selectFirstOrThrow(".widget-title").text(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
coverUrl = div.selectFirst("img")?.src(),
|
||||
tags = emptySet(),
|
||||
rating = RATING_UNKNOWN,
|
||||
state = null,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -74,10 +74,10 @@ internal class Manga18Fx(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = div.selectFirst("div.item-rate span")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,10 +80,10 @@ internal class Manhwa18Cc(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = div.selectFirst(".item-rate span")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,7 @@ package org.koitharu.kotatsu.parsers.site.madara.en
|
||||
import org.jsoup.nodes.Document
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.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.*
|
||||
|
||||
@@ -20,6 +17,7 @@ internal class FireScans(context: MangaLoaderContext) :
|
||||
}.map { div ->
|
||||
val href = div.selectFirst("h3 a")?.attrAsRelativeUrlOrNull("href") ?: div.parseFailed("Link not found")
|
||||
val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".item-summary")
|
||||
val author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText()
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
@@ -36,7 +34,7 @@ internal class FireScans(context: MangaLoaderContext) :
|
||||
source = source,
|
||||
)
|
||||
}.orEmpty(),
|
||||
author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (
|
||||
summary?.selectFirst(".mg_status")
|
||||
?.selectFirst(".summary-content")
|
||||
@@ -50,7 +48,7 @@ internal class FireScans(context: MangaLoaderContext) :
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,6 +102,7 @@ internal class Hentai4Free(context: MangaLoaderContext) :
|
||||
}.map { div ->
|
||||
val href = div.selectFirst("a")?.attrAsRelativeUrlOrNull("href") ?: div.parseFailed("Link not found")
|
||||
val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".item-summary")
|
||||
val author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText()
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
@@ -118,7 +119,7 @@ internal class Hentai4Free(context: MangaLoaderContext) :
|
||||
source = source,
|
||||
)
|
||||
}.orEmpty(),
|
||||
author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText()
|
||||
?.lowercase().orEmpty()) {
|
||||
in ongoing -> MangaState.ONGOING
|
||||
@@ -126,7 +127,7 @@ internal class Hentai4Free(context: MangaLoaderContext) :
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ internal class IsekaiScan(context: MangaLoaderContext) :
|
||||
}.map { div ->
|
||||
val href = div.selectFirstOrThrow("a").attrAsRelativeUrl("href")
|
||||
val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".item-summary")
|
||||
val author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText()
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
@@ -92,7 +93,7 @@ internal class IsekaiScan(context: MangaLoaderContext) :
|
||||
source = source,
|
||||
)
|
||||
}.orEmpty(),
|
||||
author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText()
|
||||
?.lowercase()) {
|
||||
"ongoing" -> MangaState.ONGOING
|
||||
@@ -100,7 +101,7 @@ internal class IsekaiScan(context: MangaLoaderContext) :
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,6 +99,7 @@ internal class IsekaiScanEuParser(context: MangaLoaderContext) :
|
||||
}.map { div ->
|
||||
val href = div.selectFirst("a")?.attrAsRelativeUrlOrNull("href") ?: div.parseFailed("Link not found")
|
||||
val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".item-summary")
|
||||
val author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText()
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
@@ -115,7 +116,7 @@ internal class IsekaiScanEuParser(context: MangaLoaderContext) :
|
||||
source = source,
|
||||
)
|
||||
}.orEmpty(),
|
||||
author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText()
|
||||
?.lowercase().orEmpty()) {
|
||||
in ongoing -> MangaState.ONGOING
|
||||
@@ -123,7 +124,7 @@ internal class IsekaiScanEuParser(context: MangaLoaderContext) :
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ internal class MangaDass(context: MangaLoaderContext) :
|
||||
}.map { div ->
|
||||
val href = div.selectFirst("a")?.attrAsRelativeUrlOrNull("href") ?: div.parseFailed("Link not found")
|
||||
val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".item-summary")
|
||||
val author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText()
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
@@ -90,7 +91,7 @@ internal class MangaDass(context: MangaLoaderContext) :
|
||||
source = source,
|
||||
)
|
||||
}.orEmpty(),
|
||||
author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText()
|
||||
?.lowercase().orEmpty()) {
|
||||
in ongoing -> MangaState.ONGOING
|
||||
@@ -98,7 +99,7 @@ internal class MangaDass(context: MangaLoaderContext) :
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ internal class MangaDna(context: MangaLoaderContext) :
|
||||
return doc.select("div.home-item").map { div ->
|
||||
val href = div.selectFirst("a")?.attrAsRelativeUrlOrNull("href") ?: div.parseFailed("Link not found")
|
||||
val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".hcontent")
|
||||
val author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText()
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
@@ -83,7 +84,7 @@ internal class MangaDna(context: MangaLoaderContext) :
|
||||
source = source,
|
||||
)
|
||||
}.orEmpty(),
|
||||
author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText()
|
||||
?.lowercase().orEmpty()) {
|
||||
in ongoing -> MangaState.ONGOING
|
||||
@@ -91,7 +92,7 @@ internal class MangaDna(context: MangaLoaderContext) :
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,6 +82,7 @@ internal class MangaPure(context: MangaLoaderContext) :
|
||||
}.map { div ->
|
||||
val href = div.selectFirstOrThrow("a").attrAsRelativeUrl("href")
|
||||
val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".item-summary")
|
||||
val author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText()
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
@@ -97,7 +98,7 @@ internal class MangaPure(context: MangaLoaderContext) :
|
||||
source = source,
|
||||
)
|
||||
}.orEmpty(),
|
||||
author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText()
|
||||
?.lowercase()) {
|
||||
"ongoing" -> MangaState.ONGOING
|
||||
@@ -105,7 +106,7 @@ internal class MangaPure(context: MangaLoaderContext) :
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ internal class Manhwaz(context: MangaLoaderContext) :
|
||||
}.map { div ->
|
||||
val href = div.selectFirst("a")?.attrAsRelativeUrlOrNull("href") ?: div.parseFailed("Link not found")
|
||||
val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".item-summary")
|
||||
val author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText()
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
@@ -86,7 +87,7 @@ internal class Manhwaz(context: MangaLoaderContext) :
|
||||
source = source,
|
||||
)
|
||||
}.orEmpty(),
|
||||
author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText()
|
||||
?.lowercase().orEmpty()) {
|
||||
in ongoing -> MangaState.ONGOING
|
||||
@@ -94,7 +95,7 @@ internal class Manhwaz(context: MangaLoaderContext) :
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,7 @@ package org.koitharu.kotatsu.parsers.site.madara.en
|
||||
import org.jsoup.nodes.Document
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.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.*
|
||||
|
||||
@@ -21,6 +18,7 @@ internal class ShibaManga(context: MangaLoaderContext) :
|
||||
}.map { div ->
|
||||
val href = div.selectFirst("a")?.attrAsRelativeUrlOrNull("href") ?: div.parseFailed("Link not found")
|
||||
val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".item-summary")
|
||||
val author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText()
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
@@ -37,7 +35,7 @@ internal class ShibaManga(context: MangaLoaderContext) :
|
||||
source = source,
|
||||
)
|
||||
}.orEmpty(),
|
||||
author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (
|
||||
summary?.selectFirst(".mg_status")
|
||||
?.selectFirst(".summary-content")
|
||||
@@ -52,7 +50,7 @@ internal class ShibaManga(context: MangaLoaderContext) :
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,10 +2,7 @@ package org.koitharu.kotatsu.parsers.site.madara.es
|
||||
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaListFilter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaParserSource
|
||||
import org.koitharu.kotatsu.parsers.model.SortOrder
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.util.*
|
||||
@@ -67,10 +64,10 @@ internal class DragonTranslationParser(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ internal class MangasNoSekai(context: MangaLoaderContext) :
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val body = doc.body()
|
||||
val chaptersDeferred = async { loadChapters(manga.url, doc) }
|
||||
val author = doc.selectFirst("section#section-sinopsis div.d-flex:has(div:contains(Autor)) p a")?.textOrNull()
|
||||
manga.copy(
|
||||
tags = doc.body().select("#section-sinopsis a[href*=genre]").mapToSet { a ->
|
||||
MangaTag(
|
||||
@@ -28,8 +29,7 @@ internal class MangasNoSekai(context: MangaLoaderContext) :
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
author = doc.selectFirst("section#section-sinopsis div.d-flex:has(div:contains(Autor)) p a")
|
||||
?.textOrNull(),
|
||||
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(),
|
||||
|
||||
@@ -75,10 +75,10 @@ internal class TmoManga(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ internal class ManhwaHub(context: MangaLoaderContext) :
|
||||
}.map { div ->
|
||||
val href = div.selectFirstOrThrow("a").attrAsRelativeUrl("href")
|
||||
val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".item-summary")
|
||||
val author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText()
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
@@ -82,7 +83,7 @@ internal class ManhwaHub(context: MangaLoaderContext) :
|
||||
source = source,
|
||||
)
|
||||
}.orEmpty(),
|
||||
author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText()
|
||||
?.lowercase().orEmpty()) {
|
||||
in ongoing -> MangaState.ONGOING
|
||||
@@ -90,7 +91,7 @@ internal class ManhwaHub(context: MangaLoaderContext) :
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,7 @@ 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.model.Manga
|
||||
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.util.*
|
||||
@@ -25,6 +22,7 @@ internal class MangaFenxi(context: MangaLoaderContext) :
|
||||
}.map { div ->
|
||||
val href = div.selectFirst("a")?.attrAsRelativeUrlOrNull("href") ?: div.parseFailed("Link not found")
|
||||
val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".item-summary")
|
||||
val author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText()
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
@@ -41,7 +39,7 @@ internal class MangaFenxi(context: MangaLoaderContext) :
|
||||
source = source,
|
||||
)
|
||||
}.orEmpty(),
|
||||
author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (
|
||||
summary?.selectFirst(".mg_status")
|
||||
?.selectFirst(".summary-content")
|
||||
@@ -56,7 +54,7 @@ internal class MangaFenxi(context: MangaLoaderContext) :
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ internal class Saytruyenhay(context: MangaLoaderContext) :
|
||||
}.map { div ->
|
||||
val href = div.selectFirst("a")?.attrAsRelativeUrlOrNull("href") ?: div.parseFailed("Link not found")
|
||||
val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".item-summary")
|
||||
val author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText()
|
||||
Manga(
|
||||
id = generateUid(href),
|
||||
url = href,
|
||||
@@ -87,7 +88,7 @@ internal class Saytruyenhay(context: MangaLoaderContext) :
|
||||
source = source,
|
||||
)
|
||||
}.orEmpty(),
|
||||
author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(),
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText()
|
||||
?.lowercase().orEmpty()) {
|
||||
in ongoing -> MangaState.ONGOING
|
||||
@@ -95,7 +96,7 @@ internal class Saytruyenhay(context: MangaLoaderContext) :
|
||||
else -> null
|
||||
},
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,10 +130,10 @@ internal abstract class MadthemeParser(
|
||||
source = source,
|
||||
)
|
||||
},
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,10 +112,10 @@ internal abstract class Manga18Parser(
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -166,7 +166,7 @@ internal abstract class Manga18Parser(
|
||||
},
|
||||
description = desc?.nullIfEmpty(),
|
||||
altTitle = alt,
|
||||
author = author,
|
||||
authors = author?.let { setOf(it) } ?: emptySet(),
|
||||
state = state,
|
||||
chapters = chaptersDeferred.await(),
|
||||
)
|
||||
|
||||
@@ -3,10 +3,7 @@ package org.koitharu.kotatsu.parsers.site.manga18.en
|
||||
import org.jsoup.nodes.Document
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.model.ContentType
|
||||
import org.koitharu.kotatsu.parsers.model.Manga
|
||||
import org.koitharu.kotatsu.parsers.model.MangaParserSource
|
||||
import org.koitharu.kotatsu.parsers.model.RATING_UNKNOWN
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.site.manga18.Manga18Parser
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
|
||||
@@ -28,10 +25,10 @@ internal class Hentai3zCc(context: MangaLoaderContext) :
|
||||
altTitle = null,
|
||||
rating = RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
isNsfw = isNsfwSource,
|
||||
contentRating = if (isNsfwSource) ContentRating.ADULT else null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user