[AsuraComic] Fix pages parsing
This commit is contained in:
@@ -235,6 +235,6 @@ internal class ImHentai(context: MangaLoaderContext) :
|
||||
override suspend fun getPageUrl(page: MangaPage): String {
|
||||
val doc = webClient.httpGet(page.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val img = doc.body().requireElementById("gimg")
|
||||
return img.src() ?: doc.parseFailed("Cannot find image src")
|
||||
return img.requireSrc()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ internal class MangaStorm(context: MangaLoaderContext) : PagedMangaParser(contex
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml().requireElementById("content")
|
||||
return doc.select("div.text-center .img-fluid").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -212,7 +212,7 @@ internal class TeamXNovel(context: MangaLoaderContext) : PagedMangaParser(contex
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(".image_list img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -183,7 +183,7 @@ internal abstract class CupFoxParser(
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(selectPages).map { img ->
|
||||
val url = img.src() ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc()
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -115,7 +115,7 @@ internal class AsuraScansParser(context: MangaLoaderContext) :
|
||||
rating = a.selectFirst("div.block label.ml-1")?.text()?.toFloatOrNull()?.div(10f) ?: RATING_UNKNOWN,
|
||||
tags = emptySet(),
|
||||
author = null,
|
||||
state = when (a.selectLast("span.status")?.text().orEmpty()) {
|
||||
state = when (a.selectLast("span.status")?.text()) {
|
||||
"Ongoing" -> MangaState.ONGOING
|
||||
"Completed" -> MangaState.FINISHED
|
||||
"Hiatus" -> MangaState.PAUSED
|
||||
@@ -147,7 +147,7 @@ internal class AsuraScansParser(context: MangaLoaderContext) :
|
||||
)
|
||||
}
|
||||
tagCache = tagMap
|
||||
return@withLock tagMap
|
||||
tagMap
|
||||
}
|
||||
|
||||
private val regexDate = """(\d+)(st|nd|rd|th)""".toRegex()
|
||||
@@ -185,8 +185,8 @@ internal class AsuraScansParser(context: MangaLoaderContext) :
|
||||
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val doc = webClient.httpGet(chapter.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
return doc.select("div > img[alt*=chapter]").map { img ->
|
||||
val urlPage = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
return doc.selectOrThrow("div.w-full > img.object-cover").map { img ->
|
||||
val urlPage = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(urlPage),
|
||||
url = urlPage,
|
||||
|
||||
@@ -135,7 +135,7 @@ internal class BeeToon(context: MangaLoaderContext) :
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val doc = webClient.httpGet(chapter.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
return doc.select(".chapter-content-inner center img").map { img ->
|
||||
val urlPage = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val urlPage = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(urlPage),
|
||||
url = urlPage,
|
||||
|
||||
@@ -167,7 +167,7 @@ internal class ComicExtra(context: MangaLoaderContext) : PagedMangaParser(contex
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(".chapter-container img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -158,7 +158,7 @@ internal class MangaGeko(context: MangaLoaderContext) : PagedMangaParser(context
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
|
||||
return doc.requireElementById("chapter-reader").select("img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -171,7 +171,7 @@ internal class ManhwasMen(context: MangaLoaderContext) :
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val doc = webClient.httpGet(chapter.url.toAbsoluteUrl(domain)).parseHtml().requireElementById("chapter_imgs")
|
||||
return doc.select("img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -187,7 +187,7 @@ internal class Pururin(context: MangaLoaderContext) :
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(".gallery-preview img").map { url ->
|
||||
val img = url.src()?.toRelativeUrl(domain) ?: url.parseFailed("Image src not found")
|
||||
val img = url.requireSrc().toRelativeUrl(domain)
|
||||
val urlImage = img.replace("t.", ".")
|
||||
MangaPage(
|
||||
id = generateUid(urlImage),
|
||||
|
||||
@@ -194,7 +194,7 @@ internal class VyManga(context: MangaLoaderContext) :
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val doc = webClient.httpGet(chapter.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
return doc.select("img.d-block").map { img ->
|
||||
val url = img.src() ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc()
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -85,7 +85,7 @@ internal class TempleScanEsp(context: MangaLoaderContext) :
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select("main.contenedor img.readChapter_image__450v_").map { url ->
|
||||
val img = url.src()?.toRelativeUrl(domain) ?: url.parseFailed("Image src not found")
|
||||
val img = url.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(img),
|
||||
url = img,
|
||||
|
||||
@@ -239,7 +239,7 @@ internal abstract class FmreaderParser(
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(selectPage).map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -19,7 +19,7 @@ internal class OlimpoScans(context: MangaLoaderContext) :
|
||||
val fullUrl = ("/" + chapter.url).toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(selectPage).map { img ->
|
||||
val url = ("/proxy.php?link=" + img.src()).toRelativeUrl(domain)
|
||||
val url = ("/proxy.php?link=" + img.requireSrc()).toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -85,7 +85,7 @@ internal class Klz9(context: MangaLoaderContext) :
|
||||
val cid = doc.selectFirstOrThrow("#chapter").attr("value")
|
||||
val docLoad = webClient.httpGet("https://$domain/app/manga/controllers/cont.listImg.php?cid=$cid").parseHtml()
|
||||
return docLoad.select(selectPage).map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -45,7 +45,7 @@ internal class WeLoveManga(context: MangaLoaderContext) :
|
||||
val cid = doc.selectFirstOrThrow("#chapter").attr("value")
|
||||
val docLoad = webClient.httpGet("https://$domain/app/manga/controllers/cont.listImg.php?cid=$cid").parseHtml()
|
||||
return docLoad.select("img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
|
||||
@@ -120,7 +120,7 @@ internal class FuryoSociety(context: MangaLoaderContext) :
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select("div.main-img img").map { url ->
|
||||
val img = url.src()?.toRelativeUrl(domain) ?: url.parseFailed("Image src not found")
|
||||
val img = url.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(img),
|
||||
url = img,
|
||||
|
||||
@@ -206,7 +206,7 @@ internal class LegacyScansParser(context: MangaLoaderContext) :
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select("div.readerComics img").map { img ->
|
||||
val url = img.src() ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc()
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -260,7 +260,7 @@ internal abstract class FuzzyDoodleParser(
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(selectPages).map { img ->
|
||||
val url = img.src() ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc()
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -209,7 +209,7 @@ internal abstract class GalleryAdultsParser(
|
||||
|
||||
override suspend fun getPageUrl(page: MangaPage): String {
|
||||
val doc = webClient.httpGet(page.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
return doc.requireElementById(idImg).src() ?: doc.parseFailed("Image src not found")
|
||||
return doc.requireElementById(idImg).requireSrc()
|
||||
}
|
||||
|
||||
protected fun String.cleanupTitle() = replace(regexBrackets, "")
|
||||
|
||||
@@ -58,7 +58,7 @@ internal class DoujinDesuUk(context: MangaLoaderContext) :
|
||||
override suspend fun getPageUrl(page: MangaPage): String {
|
||||
val doc = webClient.httpGet(page.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val root = doc.body()
|
||||
return root.requireElementById(idImg).selectFirstOrThrow("img").src() ?: root.parseFailed("Image src not found")
|
||||
return root.requireElementById(idImg).selectFirstOrThrow("img").requireSrc()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ internal class Hentai3(context: MangaLoaderContext) :
|
||||
|
||||
override suspend fun getPageUrl(page: MangaPage): String {
|
||||
val doc = webClient.httpGet(page.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
return doc.selectFirstOrThrow(idImg).src() ?: doc.parseFailed("Image src not found")
|
||||
return doc.selectFirstOrThrow(idImg).requireSrc()
|
||||
}
|
||||
|
||||
private fun buildQuery(tags: Collection<MangaTag>, language: Locale?): String {
|
||||
|
||||
@@ -50,7 +50,7 @@ internal class HentaiForce(context: MangaLoaderContext) :
|
||||
|
||||
override suspend fun getPageUrl(page: MangaPage): String {
|
||||
val doc = webClient.httpGet(page.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
return doc.selectFirstOrThrow(idImg).src() ?: doc.parseFailed("Image src not found")
|
||||
return doc.selectFirstOrThrow(idImg).requireSrc()
|
||||
}
|
||||
|
||||
override suspend fun getListPage(page: Int, order: SortOrder, filter: MangaListFilter): List<Manga> {
|
||||
|
||||
@@ -107,7 +107,7 @@ internal class NHentaiParser(context: MangaLoaderContext) :
|
||||
override suspend fun getPageUrl(page: MangaPage): String {
|
||||
val doc = webClient.httpGet(page.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val root = doc.body()
|
||||
return root.requireElementById(idImg).selectFirstOrThrow("img").src() ?: root.parseFailed("Image src not found")
|
||||
return root.requireElementById(idImg).selectFirstOrThrow("img").requireSrc()
|
||||
}
|
||||
|
||||
override fun Element.parseTags() = select("a").mapToSet {
|
||||
|
||||
@@ -152,6 +152,6 @@ internal abstract class GattsuParser(
|
||||
|
||||
override suspend fun getPageUrl(page: MangaPage): String {
|
||||
val doc = webClient.httpGet(page.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
return doc.selectFirstOrThrow("div.galeria-foto img").src() ?: doc.parseFailed("Image src not found")
|
||||
return doc.selectFirstOrThrow("div.galeria-foto img").requireSrc()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ internal class UniversoHentai(context: MangaLoaderContext) :
|
||||
val images = webClient.httpGet(chapter.url.toAbsoluteUrl(domain)).parseHtml().requireElementById("galeria")
|
||||
.select(".galeria-foto img")
|
||||
return images.map { img ->
|
||||
val urlImages = img.src() ?: img.parseFailed("Image src not found")
|
||||
val urlImages = img.requireSrc()
|
||||
MangaPage(
|
||||
id = generateUid(urlImages),
|
||||
url = urlImages,
|
||||
|
||||
@@ -178,7 +178,7 @@ internal abstract class HeanCms(
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(selectPages).map { img ->
|
||||
val url = img.src() ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc()
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -119,7 +119,7 @@ internal abstract class HeanCmsAlt(
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(selectPage).map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -167,7 +167,7 @@ internal abstract class HotComicsParser(
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(selectPages).map { img ->
|
||||
val url = img.src() ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc()
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -120,7 +120,7 @@ internal class HentaiCrot(context: MangaLoaderContext) :
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(".thumbnail img, figure.gallery-item img").map { img ->
|
||||
val url = img.src() ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc()
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -120,7 +120,7 @@ internal class PixHentai(context: MangaLoaderContext) :
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(".thumbnail img, figure.gallery-item img").map { img ->
|
||||
val url = img.src() ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc()
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -164,7 +164,7 @@ internal abstract class IkenParser(
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(selectPages).map { img ->
|
||||
val url = img.src() ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc()
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -233,7 +233,7 @@ internal abstract class KeyoappParser(
|
||||
?.also { return it }
|
||||
|
||||
return doc.select(selectPage).map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -116,7 +116,7 @@ internal abstract class LikeMangaParser(
|
||||
publicUrl = href.toAbsoluteUrl(domain),
|
||||
rating = RATING_UNKNOWN,
|
||||
isNsfw = false,
|
||||
coverUrl = div.selectFirstOrThrow("img").src()?.toAbsoluteUrl(domain).orEmpty(),
|
||||
coverUrl = div.selectFirstOrThrow("img").src().orEmpty(),
|
||||
tags = emptySet(),
|
||||
state = null,
|
||||
author = null,
|
||||
@@ -269,7 +269,7 @@ internal abstract class LikeMangaParser(
|
||||
|
||||
} else {
|
||||
return doc.select(".reading-detail img").map { img ->
|
||||
val url = img.src() ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc()
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -684,7 +684,7 @@ internal abstract class MadaraParser(
|
||||
)
|
||||
return root.select(selectPage).flatMap { div ->
|
||||
div.selectOrThrow("img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: div.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -113,7 +113,7 @@ internal class Manhwa18Cc(context: MangaLoaderContext) :
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val root = doc.body().selectFirstOrThrow(selectBodyPage)
|
||||
return root.select("img").map { img ->
|
||||
val url = img.src() ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc()
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -168,7 +168,7 @@ internal class AdultWebtoon(context: MangaLoaderContext) :
|
||||
)
|
||||
return root.select(selectPage).map { div ->
|
||||
val img = div.selectFirstOrThrow("img")
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: div.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url.replace("http:", "https:"),
|
||||
|
||||
@@ -9,16 +9,8 @@ import org.koitharu.kotatsu.parsers.model.MangaChapter
|
||||
import org.koitharu.kotatsu.parsers.model.MangaPage
|
||||
import org.koitharu.kotatsu.parsers.model.MangaParserSource
|
||||
import org.koitharu.kotatsu.parsers.site.madara.MadaraParser
|
||||
import org.koitharu.kotatsu.parsers.util.CryptoAES
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.generateUid
|
||||
import org.koitharu.kotatsu.parsers.util.parseFailed
|
||||
import org.koitharu.kotatsu.parsers.util.parseHtml
|
||||
import org.koitharu.kotatsu.parsers.util.selectFirstOrThrow
|
||||
import org.koitharu.kotatsu.parsers.util.src
|
||||
import org.koitharu.kotatsu.parsers.util.toAbsoluteUrl
|
||||
import org.koitharu.kotatsu.parsers.util.toRelativeUrl
|
||||
import java.util.Base64
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("DARK_SCANS", "DarkScans", "en")
|
||||
internal class DarkScans(context: MangaLoaderContext) :
|
||||
@@ -40,7 +32,7 @@ internal class DarkScans(context: MangaLoaderContext) :
|
||||
)
|
||||
return root.select(selectPage).map { div ->
|
||||
val img = div.selectFirstOrThrow("img")
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: div.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url.replace("http:", "https:"),
|
||||
|
||||
@@ -174,7 +174,7 @@ internal class MangaDass(context: MangaLoaderContext) :
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val root = doc.body().selectFirstOrThrow("div.read-manga").selectFirstOrThrow("div.read-content")
|
||||
return root.select("img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -167,7 +167,7 @@ internal class MangaDna(context: MangaLoaderContext) :
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val root = doc.body().selectFirstOrThrow("div.read-manga").selectFirstOrThrow("div.read-content")
|
||||
return root.select("img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -19,7 +19,7 @@ internal class Manhuaplus(context: MangaLoaderContext) :
|
||||
val root = doc.body().selectFirst("div.main-col-inner")?.selectFirst("div.reading-content")
|
||||
?: throw ParseException("Root not found", fullUrl)
|
||||
return root.select("img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -20,7 +20,7 @@ internal class Manhwaden(context: MangaLoaderContext) :
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val root = doc.body().selectFirstOrThrow(selectBodyPage)
|
||||
return root.select(selectPage).map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -27,7 +27,7 @@ internal class DoujinHentaiNet(context: MangaLoaderContext) :
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(selectPage).map { div ->
|
||||
val img = div.selectFirstOrThrow("img")
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: div.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -81,7 +81,7 @@ internal class MangasNoSekai(context: MangaLoaderContext) :
|
||||
?: throw ParseException("No image found, try to log in", fullUrl)
|
||||
return root.select(selectPage).map { div ->
|
||||
val img = div.selectFirstOrThrow("img")
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: div.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -108,7 +108,7 @@ internal class TmoManga(context: MangaLoaderContext) :
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val root = doc.body().requireElementById("images_chapter")
|
||||
return root.select("img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain).orEmpty()
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -33,7 +33,7 @@ internal class FrScan(context: MangaLoaderContext) :
|
||||
} else {
|
||||
return doc.body().selectFirstOrThrow(selectBodyPage).select(selectPage).map { div ->
|
||||
val img = div.selectFirstOrThrow("img")
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: div.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -19,7 +19,7 @@ internal class RhPlusManga(context: MangaLoaderContext) :
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val root = doc.body().selectFirstOrThrow("div.main-col-inner").selectFirstOrThrow("div.reading-content")
|
||||
return root.select("img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -27,7 +27,7 @@ internal class HentaiCube(context: MangaLoaderContext) :
|
||||
val root = doc.body().selectFirst("div.main-col-inner")?.selectFirst("div.reading-content")
|
||||
?: throw ParseException("Root not found", fullUrl)
|
||||
return root.select("img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -20,7 +20,7 @@ internal class Quaanhdaocuteo(context: MangaLoaderContext) :
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val root = doc.body().selectFirstOrThrow(selectBodyPage)
|
||||
return root.select(selectPage).map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -233,7 +233,7 @@ internal abstract class MadthemeParser(
|
||||
val result = ArrayList<MangaPage>()
|
||||
// html parisng
|
||||
doc.select(selectPage).forEach { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
if (known.add(url)) {
|
||||
result += MangaPage(
|
||||
id = generateUid(url),
|
||||
|
||||
@@ -233,7 +233,7 @@ internal abstract class MangaboxParser(
|
||||
val doc2 = webClient.httpGet(fullUrl2).parseHtml()
|
||||
|
||||
return doc2.select(selectPage).map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
@@ -244,7 +244,7 @@ internal abstract class MangaboxParser(
|
||||
}
|
||||
} else {
|
||||
return doc.select(selectPage).map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
|
||||
@@ -297,7 +297,7 @@ internal abstract class MangaReaderParser(
|
||||
val test = docs.select(selectTestScript)
|
||||
if (test.isNullOrEmpty() and !encodedSrc) {
|
||||
return docs.select(selectPage).map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -30,7 +30,7 @@ internal class CatharsisFantasy(context: MangaLoaderContext) :
|
||||
val test = docs.select(selectTestScript)
|
||||
if (test.isNullOrEmpty() and !encodedSrc) {
|
||||
return docs.select(selectPage).map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -20,7 +20,7 @@ internal class LelManga(context: MangaLoaderContext) :
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val root = doc.body().selectFirstOrThrow("div.maincontent").requireElementById("readerarea")
|
||||
return root.select("img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -158,7 +158,7 @@ internal class Komikcast(context: MangaLoaderContext) :
|
||||
val test = docs.select("script:containsData(ts_reader)")
|
||||
if (test.isNullOrEmpty()) {
|
||||
return docs.select("div#chapter_body img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -217,7 +217,7 @@ internal abstract class MangaWorldParser(
|
||||
val selectMangaPages = "img.img-fluid"
|
||||
val imgSelector = if (doc.select(selectWebtoonPages).isNotEmpty()) selectWebtoonPages else selectMangaPages
|
||||
return doc.select(imgSelector).map { img ->
|
||||
val urlPage = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val urlPage = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(urlPage),
|
||||
url = urlPage,
|
||||
|
||||
@@ -242,7 +242,7 @@ internal abstract class MmrcmsParser(
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(selectPage).map { url ->
|
||||
val img = url.src()?.toRelativeUrl(domain) ?: url.parseFailed("Image src not found")
|
||||
val img = url.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(img),
|
||||
url = img,
|
||||
|
||||
@@ -79,7 +79,7 @@ internal abstract class OneMangaParser(
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select("div.elementor-widget-container img").map { img ->
|
||||
val url = img.src() ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc()
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -228,7 +228,7 @@ internal abstract class OtakuSanctuaryParser(
|
||||
}
|
||||
} else {
|
||||
return doc.select(selectPage).map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -140,7 +140,7 @@ internal class LerMangaOnline(context: MangaLoaderContext) :
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(".images img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -152,7 +152,7 @@ internal class MangaOnline(context: MangaLoaderContext) : PagedMangaParser(conte
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(".content p img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -177,6 +177,6 @@ internal class AComics(context: MangaLoaderContext) :
|
||||
|
||||
override suspend fun getPageUrl(page: MangaPage): String {
|
||||
val doc = webClient.httpGet(page.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
return doc.requireElementById("mainImage").src() ?: doc.parseFailed("Image src not found")
|
||||
return doc.requireElementById("mainImage").requireSrc()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ internal class MangaAy(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select("div.mt-2 img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -96,7 +96,7 @@ internal class SadScans(context: MangaLoaderContext) : SinglePageMangaParser(con
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(".swiper-slide img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -227,7 +227,7 @@ internal class TrWebtoon(context: MangaLoaderContext) :
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val doc = webClient.httpGet(chapter.url.toAbsoluteUrl(domain)).parseHtml().requireElementById("images")
|
||||
return doc.select("img").map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -136,7 +136,7 @@ internal class HentaiVNParser(context: MangaLoaderContext) : MangaParser(context
|
||||
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
|
||||
val docs = webClient.httpGet(chapter.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
return docs.select("#image > img").map {
|
||||
val pageUrl = it.src() ?: it.parseFailed("Image src not found")
|
||||
val pageUrl = it.requireSrc()
|
||||
MangaPage(
|
||||
id = generateUid(pageUrl),
|
||||
url = pageUrl,
|
||||
|
||||
@@ -14,11 +14,11 @@ import java.util.*
|
||||
@MangaSourceParser("TRUYENGG", "TruyenGG", "vi")
|
||||
internal class TruyenGG(context: MangaLoaderContext) : PagedMangaParser(context, MangaParserSource.TRUYENGG, 42) {
|
||||
|
||||
override val configKeyDomain = ConfigKey.Domain("truyengg.com")
|
||||
override val configKeyDomain = ConfigKey.Domain("truyengg.com")
|
||||
|
||||
override fun onCreateConfig(keys: MutableCollection<ConfigKey<*>>) {
|
||||
super.onCreateConfig(keys)
|
||||
keys.add(userAgentKey)
|
||||
super.onCreateConfig(keys)
|
||||
keys.add(userAgentKey)
|
||||
}
|
||||
|
||||
override val userAgentKey = ConfigKey.UserAgent(UserAgents.CHROME_DESKTOP)
|
||||
@@ -62,6 +62,7 @@ internal class TruyenGG(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
append(filter.query.urlEncoded())
|
||||
}
|
||||
}
|
||||
|
||||
else -> {
|
||||
buildString {
|
||||
append("https://")
|
||||
@@ -147,11 +148,11 @@ internal class TruyenGG(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
override suspend fun getDetails(manga: Manga): Manga {
|
||||
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
|
||||
val dateFormat = SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH)
|
||||
|
||||
|
||||
return manga.copy(
|
||||
altTitle = doc.selectFirst("h2.other-name")?.text(),
|
||||
author = doc.select("p:contains(Tác Giả) + p").joinToString { it.text() }.takeUnless { it.isEmpty() },
|
||||
tags = doc.select("a.clblue").mapToSet {
|
||||
tags = doc.select("a.clblue").mapToSet {
|
||||
MangaTag(
|
||||
key = it.attr("href").substringAfterLast('-').substringBeforeLast('.'),
|
||||
title = it.text(),
|
||||
@@ -188,7 +189,7 @@ internal class TruyenGG(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(".content_detail img").map { img ->
|
||||
val url = img.src() ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc()
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
@@ -198,14 +199,14 @@ internal class TruyenGG(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/tim-kiem-nang-cao.html").parseHtml()
|
||||
return doc.select(".advsearch-form div.genre-item").mapToSet {
|
||||
MangaTag(
|
||||
key = it.selectFirstOrThrow("span").attr("data-id"),
|
||||
title = it.text(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
private suspend fun fetchAvailableTags(): Set<MangaTag> {
|
||||
val doc = webClient.httpGet("https://$domain/tim-kiem-nang-cao.html").parseHtml()
|
||||
return doc.select(".advsearch-form div.genre-item").mapToSet {
|
||||
MangaTag(
|
||||
key = it.selectFirstOrThrow("span").attr("data-id"),
|
||||
title = it.text(),
|
||||
source = source,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +201,7 @@ internal class TruyenQQ(context: MangaLoaderContext) : PagedMangaParser(context,
|
||||
val root = doc.body().selectFirstOrThrow(".chapter_content")
|
||||
return root.select("div.page-chapter").map { div ->
|
||||
val img = div.selectFirstOrThrow("img")
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: div.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -144,7 +144,7 @@ internal abstract class VmpParser(
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select("div.wp-content img").map { div ->
|
||||
val img = div.selectFirstOrThrow("img")
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: div.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -268,7 +268,7 @@ internal abstract class WpComicsParser(
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select(selectPage).map { url ->
|
||||
val img = url.src()?.toRelativeUrl(domain) ?: url.parseFailed("Image src not found")
|
||||
val img = url.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(img),
|
||||
url = img,
|
||||
|
||||
@@ -341,7 +341,7 @@ internal abstract class ZeistMangaParser(
|
||||
|
||||
} else {
|
||||
doc.select(selectPage).map { img ->
|
||||
val url = img.src() ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc()
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -275,7 +275,7 @@ internal abstract class ZMangaParser(
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
|
||||
return doc.select(selectPage).map { img ->
|
||||
val url = img.src()?.toRelativeUrl(domain) ?: img.parseFailed("Image src not found")
|
||||
val url = img.requireSrc().toRelativeUrl(domain)
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.jsoup.select.QueryParser
|
||||
import org.jsoup.select.Selector
|
||||
import org.koitharu.kotatsu.parsers.InternalParsersApi
|
||||
import org.koitharu.kotatsu.parsers.exception.ParseException
|
||||
import kotlin.contracts.contract
|
||||
|
||||
public val Element.host: String?
|
||||
get() {
|
||||
@@ -24,8 +25,7 @@ public val Element.host: String?
|
||||
* Return an attribute value or null if it is missing or empty
|
||||
* @see [Element.attr] which returns empty string instead of null
|
||||
*/
|
||||
public fun Element.attrOrNull(attributeKey: String) = attr(attributeKey).takeUnless { it.isBlank() }?.trim()
|
||||
|
||||
public fun Element.attrOrNull(attributeKey: String): String? = attr(attributeKey).takeUnless { it.isBlank() }?.trim()
|
||||
|
||||
/**
|
||||
* Return an attribute value or throw an exception if it is missing
|
||||
@@ -48,7 +48,7 @@ public fun Element.attrAsRelativeUrlOrNull(attributeKey: String): String? {
|
||||
if (attr.isEmpty() || attr.startsWith("data:")) {
|
||||
return null
|
||||
}
|
||||
if (attr.startsWith("/")) {
|
||||
if (attr.startsWith('/')) {
|
||||
return attr
|
||||
}
|
||||
val host = baseUri().toHttpUrlOrNull()?.host ?: return null
|
||||
@@ -90,7 +90,7 @@ public fun Element.attrAsAbsoluteUrlOrNull(attributeKey: String): String? {
|
||||
* @see attrAsRelativeUrlOrNull
|
||||
*/
|
||||
public fun Element.attrAsAbsoluteUrl(attributeKey: String): String {
|
||||
return requireNotNull(attrAsAbsoluteUrlOrNull(attributeKey)) {
|
||||
return parseNotNull(attrAsAbsoluteUrlOrNull(attributeKey)) {
|
||||
"Cannot get absolute url for $attributeKey: \"${attr(attributeKey)}\""
|
||||
}
|
||||
}
|
||||
@@ -107,8 +107,8 @@ public fun Element.styleValueOrNull(property: String): String? {
|
||||
/**
|
||||
* Like a `expectFirst` but with detailed error message
|
||||
*/
|
||||
public fun Element.selectFirstOrThrow(cssQuery: String): Element {
|
||||
return Selector.selectFirst(cssQuery, this) ?: throw ParseException("Cannot find \"$cssQuery\"", baseUri())
|
||||
public fun Element.selectFirstOrThrow(cssQuery: String): Element = parseNotNull(Selector.selectFirst(cssQuery, this)) {
|
||||
"Cannot find \"$cssQuery\""
|
||||
}
|
||||
|
||||
public fun Element.selectOrThrow(cssQuery: String): Elements {
|
||||
@@ -117,16 +117,14 @@ public fun Element.selectOrThrow(cssQuery: String): Elements {
|
||||
}
|
||||
}
|
||||
|
||||
public fun Element.requireElementById(id: String): Element {
|
||||
return getElementById(id) ?: throw ParseException("Cannot find \"#$id\"", baseUri())
|
||||
public fun Element.requireElementById(id: String): Element = parseNotNull(getElementById(id)) {
|
||||
"Cannot find \"#$id\""
|
||||
}
|
||||
|
||||
public fun Element.selectLast(cssQuery: String): Element? {
|
||||
return select(cssQuery).lastOrNull()
|
||||
}
|
||||
public fun Element.selectLast(cssQuery: String): Element? = select(cssQuery).lastOrNull()
|
||||
|
||||
public fun Element.selectLastOrThrow(cssQuery: String): Element {
|
||||
return selectLast(cssQuery) ?: throw ParseException("Cannot find \"$cssQuery\"", baseUri())
|
||||
public fun Element.selectLastOrThrow(cssQuery: String): Element = parseNotNull(selectLast(cssQuery)) {
|
||||
"Cannot find \"$cssQuery\""
|
||||
}
|
||||
|
||||
public fun Element.textOrNull(): String? = text().takeUnless { it.isEmpty() }
|
||||
@@ -142,8 +140,9 @@ public fun Element.selectFirstParent(query: String): Element? {
|
||||
}
|
||||
}
|
||||
|
||||
public fun Element.selectFirstParentOrThrow(query: String): Element =
|
||||
selectFirstParent(query) ?: throw ParseException("Cannot find parent \"$query\"", baseUri())
|
||||
public fun Element.selectFirstParentOrThrow(query: String): Element = parseNotNull(selectFirstParent(query)) {
|
||||
"Cannot find parent \"$query\""
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a first non-empty attribute value of [names] or null if it is missing or empty
|
||||
@@ -183,6 +182,11 @@ public fun Element.src(
|
||||
return null
|
||||
}
|
||||
|
||||
@InternalParsersApi
|
||||
public fun Element.requireSrc(): String = parseNotNull(src()) {
|
||||
"Image src not found"
|
||||
}
|
||||
|
||||
public fun Element.metaValue(itemprop: String): String? = getElementsByAttributeValue("itemprop", itemprop)
|
||||
.firstNotNullOfOrNull { element ->
|
||||
element.attrOrNull("content")
|
||||
@@ -200,3 +204,16 @@ public fun String.cssUrl(): String? {
|
||||
substring(fromIndex + 4, toIndex).trim()
|
||||
}
|
||||
}
|
||||
|
||||
internal inline fun <T : Any> Element.parseNotNull(value: T?, lazyMessage: () -> String): T {
|
||||
contract {
|
||||
returns() implies (value != null)
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
val message = lazyMessage()
|
||||
throw ParseException(message, baseUri())
|
||||
} else {
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ internal class MangaParserTest {
|
||||
fun favicon(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
val parser = context.newParserInstance(source)
|
||||
val favicons = parser.getFavicons()
|
||||
val types = setOf("png", "svg", "ico", "gif", "jpg", "jpeg")
|
||||
val types = setOf("png", "svg", "ico", "gif", "jpg", "jpeg", "webp", "avif")
|
||||
assert(favicons.isNotEmpty())
|
||||
favicons.forEach {
|
||||
assert(it.url.isUrlAbsolute()) { "Favicon url is not absolute: ${it.url}" }
|
||||
|
||||
Reference in New Issue
Block a user