Add multi tag some sources

Add SortOrder.POPULARITY some sources
Add all language on GalleryAdultsParser
fix YugenMangas (pt)
devi 2 years ago
parent 3ea088371b
commit 410c73a74f

@ -149,6 +149,9 @@ internal abstract class GalleryAdultsParser(
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
val urlChapters = doc.selectFirstOrThrow(selectUrlChapter).attr("href")
val tag = doc.selectFirst(selectTag)?.parseTags()
val branch = doc.select(selectLanguageChapter).joinToString(separator = " / ") {
it.html().substringBefore("<")
}
return manga.copy(
tags = tag.orEmpty(),
author = doc.selectFirst(selectAuthor)?.html()?.substringBefore("<span"),
@ -160,7 +163,7 @@ internal abstract class GalleryAdultsParser(
url = urlChapters,
scanlator = null,
uploadDate = 0,
branch = doc.selectFirst(selectLanguageChapter)?.html()?.substringBefore("<"),
branch = branch,
source = source,
),
),

@ -5,6 +5,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.site.galleryadults.GalleryAdultsParser
import org.koitharu.kotatsu.parsers.util.*
import java.util.EnumSet
@MangaSourceParser("HENTAI3", "3Hentai", type = ContentType.HENTAI)
internal class Hentai3(context: MangaLoaderContext) :
@ -14,10 +15,10 @@ internal class Hentai3(context: MangaLoaderContext) :
override val selectGalleryLink = "a"
override val selectGalleryTitle = ".title"
override val pathTagUrl = "/tags-popular/"
override val selectTags = "span.filter-elem"
override val selectTag = "div.tag-container:contains(Tags :) .filter-elem"
override val selectAuthor = "div.tag-container:contains(Artistes :) .filter-elem"
override val selectLanguageChapter = "div.tag-container:contains(Langues :) .filter-elem"
override val selectTags = "div.tag-listing-container"
override val selectTag = "div.tag-container:contains(Tags)"
override val selectAuthor = "div.tag-container:contains(Artists) .filter-elem a"
override val selectLanguageChapter = "div.tag-container:contains(Languages) a"
override val selectUrlChapter = "#main-cover a"
override val idImg = ".js-main-img"
override val listLanguage = arrayOf(
@ -30,31 +31,40 @@ internal class Hentai3(context: MangaLoaderContext) :
"/japanese",
)
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY)
override suspend fun getListPage(
page: Int,
query: String?,
tags: Set<MangaTag>?,
sortOrder: SortOrder,
): List<Manga> {
val tag = tags.oneOrThrowIfMany()
if (query.isNullOrEmpty() && tags != null && tags.size > 1) {
return getListPage(page, buildQuery(tags), emptySet(), sortOrder)
}
val url = buildString {
append("https://")
append(domain)
if (!tags.isNullOrEmpty()) {
if (tag?.key == "languageKey") {
val tag = tags.single()
if (tag.key == "languageKey") {
append("/language")
append(tag.title)
append("/")
append(page)
} else {
append("/tags/")
append(tag?.key.orEmpty())
append("/")
append(page)
append(tag.key)
}
append("/")
append(page)
if (sortOrder == SortOrder.POPULARITY) {
append("?sort=popular")
}
} else if (!query.isNullOrEmpty()) {
append("/search/?q=")
append("/search?q=")
append(query.urlEncoded())
if (sortOrder == SortOrder.POPULARITY) {
append("&sort=popular")
}
append("&page=")
append(page)
} else {
@ -69,4 +79,13 @@ internal class Hentai3(context: MangaLoaderContext) :
val doc = webClient.httpGet(page.url.toAbsoluteUrl(domain)).parseHtml()
return doc.selectFirstOrThrow(idImg).src() ?: doc.parseFailed("Image src not found")
}
private fun buildQuery(tags: Collection<MangaTag>) =
tags.joinToString(separator = " ") { tag ->
if (tag.key == "languageKey") {
"language:\"${tag.title.removePrefix("/")}\""
} else {
"tag:\"${tag.title}\""
}
}
}

@ -8,6 +8,7 @@ import org.koitharu.kotatsu.parsers.util.domain
import org.koitharu.kotatsu.parsers.util.oneOrThrowIfMany
import org.koitharu.kotatsu.parsers.util.parseHtml
import org.koitharu.kotatsu.parsers.util.urlEncoded
import java.util.EnumSet
@MangaSourceParser("HENTAIENVY", "HentaiEnvy", type = ContentType.HENTAI)
internal class HentaiEnvy(context: MangaLoaderContext) :
@ -31,6 +32,8 @@ internal class HentaiEnvy(context: MangaLoaderContext) :
"/portuguese",
)
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY)
override suspend fun getListPage(
page: Int,
query: String?,
@ -49,6 +52,9 @@ internal class HentaiEnvy(context: MangaLoaderContext) :
} else {
append("/tag/")
append(tag?.key.orEmpty())
if (sortOrder == SortOrder.POPULARITY) {
append("/popular")
}
append("/?")
}
} else if (!query.isNullOrEmpty()) {

@ -6,6 +6,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.site.galleryadults.GalleryAdultsParser
import org.koitharu.kotatsu.parsers.util.*
import java.util.EnumSet
@MangaSourceParser("HENTAIERA", "HentaiEra", type = ContentType.HENTAI)
internal class HentaiEra(context: MangaLoaderContext) :
@ -24,6 +25,8 @@ internal class HentaiEra(context: MangaLoaderContext) :
"/russian",
)
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY)
override fun Element.parseTags() = select("a.tag, .gallery_title a").mapToSet {
val key = it.attr("href").removeSuffix('/').substringAfterLast('/')
val name = it.selectFirst(".item_name")?.text() ?: it.text()
@ -40,23 +43,33 @@ internal class HentaiEra(context: MangaLoaderContext) :
tags: Set<MangaTag>?,
sortOrder: SortOrder,
): List<Manga> {
val tag = tags.oneOrThrowIfMany()
if (query.isNullOrEmpty() && tags != null && tags.size > 1) {
return getListPage(page, buildQuery(tags), emptySet(), sortOrder)
}
val url = buildString {
append("https://")
append(domain)
if (!tags.isNullOrEmpty()) {
if (tag?.key == "languageKey") {
val tag = tags.single()
if (tag.key == "languageKey") {
append("/language")
append(tag.title)
append("/?")
} else {
append("/tag/")
append(tag?.key.orEmpty())
append("/?")
append(tag.key)
}
append("/")
if (sortOrder == SortOrder.POPULARITY) {
append("popular/")
}
append("?")
} else if (!query.isNullOrEmpty()) {
append("/search/?key=")
append(query.urlEncoded())
if (sortOrder == SortOrder.POPULARITY) {
append(query.replace("&lt=1&dl=0&pp=0&tr=0", "&lt=0&dl=0&pp=1&tr=0"))
} else {
append(query)
}
append("&")
} else {
append("/?")
@ -67,10 +80,51 @@ internal class HentaiEra(context: MangaLoaderContext) :
return parseMangaList(webClient.httpGet(url).parseHtml())
}
private fun buildQuery(tags: Collection<MangaTag>): String {
val queryDefault =
"&search=&mg=1&dj=1&ws=1&is=1&ac=1&gc=1&en=0&jp=0&es=0&fr=0&kr=0&de=0&ru=0&lt=1&dl=0&pp=0&tr=0"
var tag = ""
var queryMod = ""
tags.map {
if (it.key == "languageKey" && it.title == "/english") {
queryMod = queryDefault.replace("en=0", "en=1")
}
if (it.key == "languageKey" && it.title == "/japanese") {
queryMod = queryDefault.replace("jp=0", "jp=1")
}
if (it.key == "languageKey" && it.title == "/spanish") {
queryMod = queryDefault.replace("es=0", "es=1")
}
if (it.key == "languageKey" && it.title == "/french") {
queryMod = queryDefault.replace("fr=0", "fr=1")
}
if (it.key == "languageKey" && it.title == "/korean") {
queryMod = queryDefault.replace("kr=0", "kr=1")
}
if (it.key == "languageKey" && it.title == "/russian") {
queryMod = queryDefault.replace("ru=0", "ru=1")
}
if (it.key == "languageKey" && it.title == "/german") {
queryMod = queryDefault.replace("de=0", "de=1")
}
if (it.key != "languageKey") {
tag += it.key + " "
}
}
if (queryMod.isEmpty()) {
queryMod = "&search=&mg=1&dj=1&ws=1&is=1&ac=1&gc=1&en=1&jp=1&es=1&fr=1&kr=1&de=1&ru=1&lt=1&dl=0&pp=0&tr=0"
}
return tag + queryMod
}
override suspend fun getDetails(manga: Manga): Manga {
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
val urlChapters = doc.selectFirstOrThrow("#cover a, .cover a, .left_cover a").attr("href")
val tag = doc.selectFirst(selectTag)?.parseTags()
val branch = doc.select(selectLanguageChapter).joinToString(separator = " / ") {
it.text()
}
return manga.copy(
tags = tag.orEmpty(),
author = doc.selectFirst(selectAuthor)?.text(),
@ -82,7 +136,7 @@ internal class HentaiEra(context: MangaLoaderContext) :
url = urlChapters,
scanlator = null,
uploadDate = 0,
branch = doc.selectFirst(selectLanguageChapter)?.text(),
branch = branch,
source = source,
),
),

@ -5,6 +5,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.site.galleryadults.GalleryAdultsParser
import org.koitharu.kotatsu.parsers.util.*
import java.util.EnumSet
@MangaSourceParser("HENTAIFORCE", "HentaiForce", type = ContentType.HENTAI)
internal class HentaiForce(context: MangaLoaderContext) :
@ -34,6 +35,8 @@ internal class HentaiForce(context: MangaLoaderContext) :
"/vietnamese",
)
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY)
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")
@ -45,23 +48,31 @@ internal class HentaiForce(context: MangaLoaderContext) :
tags: Set<MangaTag>?,
sortOrder: SortOrder,
): List<Manga> {
val tag = tags.oneOrThrowIfMany()
if (query.isNullOrEmpty() && tags != null && tags.size > 1) {
return getListPage(page, buildQuery(tags), emptySet(), sortOrder)
}
val url = buildString {
append("https://")
append(domain)
if (!tags.isNullOrEmpty()) {
if (tag?.key == "languageKey") {
val tag = tags.single()
if (tag.key == "languageKey") {
append("/language")
append(tag.title)
append("/")
} else {
append("/tag/")
append(tag?.key.orEmpty())
append("/")
append(tag.key)
}
if (sortOrder == SortOrder.POPULARITY) {
append("/popular")
}
append("/")
} else if (!query.isNullOrEmpty()) {
append("search?q=")
append("/search?q=")
append(query.urlEncoded())
if (sortOrder == SortOrder.POPULARITY) {
append("&sort=popular")
}
append("&page=")
} else {
append("/page/")
@ -70,4 +81,13 @@ internal class HentaiForce(context: MangaLoaderContext) :
}
return parseMangaList(webClient.httpGet(url).parseHtml())
}
private fun buildQuery(tags: Collection<MangaTag>) =
tags.joinToString(separator = " ") { tag ->
if (tag.key == "languageKey") {
"language:${tag.title.removePrefix("/")}"
} else {
"tag:${tag.title}"
}
}
}

@ -1,10 +1,12 @@
package org.koitharu.kotatsu.parsers.site.galleryadults.all
import org.jsoup.nodes.Element
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.site.galleryadults.GalleryAdultsParser
import org.koitharu.kotatsu.parsers.util.*
import java.util.EnumSet
@MangaSourceParser("HENTAIFOX", "HentaiFox", type = ContentType.HENTAI)
internal class HentaiFox(context: MangaLoaderContext) :
@ -30,33 +32,43 @@ internal class HentaiFox(context: MangaLoaderContext) :
"/vietnamese",
)
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY)
override suspend fun getListPage(
page: Int,
query: String?,
tags: Set<MangaTag>?,
sortOrder: SortOrder,
): List<Manga> {
val tag = tags.oneOrThrowIfMany()
if (query.isNullOrEmpty() && tags != null && tags.size > 1) {
return getListPage(page, buildQuery(tags), emptySet(), sortOrder)
}
val url = buildString {
append("https://")
append(domain)
if (!tags.isNullOrEmpty()) {
if (tag?.key == "languageKey") {
val tag = tags.single()
if (tag.key == "languageKey") {
append("/language")
append(tag.title)
} else {
append("/tag/")
append(tag?.key.orEmpty())
append(tag.key)
}
if (sortOrder == SortOrder.POPULARITY) {
append("/popular")
}
if (page > 1) {
append("/pag/")
append(page)
append("/")
}
} else if (!query.isNullOrEmpty()) {
append("/search/?q=")
append(query.urlEncoded())
if (sortOrder == SortOrder.POPULARITY) {
append("&sort=popular")
}
if (page > 1) {
append("&page=")
append(page)
@ -75,4 +87,23 @@ internal class HentaiFox(context: MangaLoaderContext) :
}
return parseMangaList(webClient.httpGet(url).parseHtml())
}
override fun Element.parseTags() = select("a").mapToSet {
val key = it.attr("href").removeSuffix('/').substringAfterLast('/')
val name = it.selectFirst(".list_tag")?.text() ?: it.html().substringBefore("<")
MangaTag(
key = key,
title = name,
source = source,
)
}
private fun buildQuery(tags: Collection<MangaTag>) =
tags.joinToString(separator = " ") { tag ->
if (tag.key == "languageKey") {
tag.title.removePrefix("/")
} else {
tag.key
}
}
}

@ -6,6 +6,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.site.galleryadults.GalleryAdultsParser
import org.koitharu.kotatsu.parsers.util.*
import java.util.EnumSet
@MangaSourceParser("NHENTAI", "NHentai.net", type = ContentType.HENTAI)
internal class NHentaiParser(context: MangaLoaderContext) :
@ -14,7 +15,7 @@ internal class NHentaiParser(context: MangaLoaderContext) :
override val selectGalleryLink = "a"
override val selectGalleryTitle = ".caption"
override val pathTagUrl = "/tags/popular?page="
override val selectTags = "#tag-container a"
override val selectTags = "#tag-container"
override val selectTag = ".tag-container:contains(Tags:) span.tags"
override val selectAuthor = "#tags div.tag-container:contains(Artists:) span.name"
override val selectLanguageChapter =
@ -26,6 +27,8 @@ internal class NHentaiParser(context: MangaLoaderContext) :
"/chinese",
)
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY)
override suspend fun getListPage(
page: Int,
query: String?,
@ -43,18 +46,28 @@ internal class NHentaiParser(context: MangaLoaderContext) :
if (tag.key == "languageKey") {
append("/language")
append(tag.title)
append("/?")
} else {
append("/tag/")
append(tag.key)
append("/?")
}
append("/")
if (sortOrder == SortOrder.POPULARITY) {
append("popular")
}
append("?")
} else if (!query.isNullOrEmpty()) {
append("/search/?q=")
append(query.urlEncoded())
if (sortOrder == SortOrder.POPULARITY) {
append("&sort=popular")
}
append("&")
} else {
append("/?")
if (sortOrder == SortOrder.POPULARITY) {
append("/?sort=popular&")
} else {
append("/?")
}
}
append("page=")
append(page)
@ -78,7 +91,12 @@ internal class NHentaiParser(context: MangaLoaderContext) :
)
}
private fun buildQuery(tags: Collection<MangaTag>) = tags.joinToString(separator = " ") { tag ->
"tag:\"${tag.key}\""
}
private fun buildQuery(tags: Collection<MangaTag>) =
tags.joinToString(separator = " ") { tag ->
if (tag.key == "languageKey") {
"language:\"${tag.title.removePrefix("/")}\""
} else {
"tag:\"${tag.key}\""
}
}
}

@ -1,5 +1,6 @@
package org.koitharu.kotatsu.parsers.site.pt
import org.json.JSONObject
import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.PagedMangaParser
@ -7,14 +8,16 @@ import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import org.koitharu.kotatsu.parsers.util.json.mapJSON
import org.koitharu.kotatsu.parsers.util.json.mapJSONIndexed
import java.text.DateFormat
import java.text.SimpleDateFormat
import java.util.*
@MangaSourceParser("YUGENMANGAS", "YugenMangas.org", "pt")
@MangaSourceParser("YUGENMANGAS", "YugenMangas.net.br", "pt")
class YugenMangas(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.YUGENMANGAS, 28) {
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL, SortOrder.UPDATED)
override val configKeyDomain = ConfigKey.Domain("yugenmangas.org")
override val sortOrders: Set<SortOrder> = EnumSet.of(SortOrder.ALPHABETICAL)
override val configKeyDomain = ConfigKey.Domain("yugenmangas.net.br")
override suspend fun getListPage(
page: Int,
@ -22,114 +25,114 @@ class YugenMangas(context: MangaLoaderContext) : PagedMangaParser(context, Manga
tags: Set<MangaTag>?,
sortOrder: SortOrder,
): List<Manga> {
if (!query.isNullOrEmpty()) {
if (page > 1) {
return emptyList()
}
val url = buildString {
append("https://")
append(domain)
append("/api/series/list/?query=")
append(query.urlEncoded())
}
val json = webClient.httpGet(url).parseJsonArray()
return json.mapJSON { j ->
val urlManga = "https://$domain/series/${j.getString("slug")}/"
Manga(
id = generateUid(urlManga),
url = urlManga,
publicUrl = urlManga,
title = j.getString("name"),
coverUrl = "",
altTitle = null,
rating = RATING_UNKNOWN,
tags = emptySet(),
description = null,
state = null,
author = null,
isNsfw = false,
source = source,
)
}
} else {
val url = buildString {
append("https://")
append(domain)
when (sortOrder) {
SortOrder.ALPHABETICAL -> append("/series")
SortOrder.UPDATED -> append("/updates")
else -> append("/updates")
val json =
if (!query.isNullOrEmpty()) {
if (page > 1) {
return emptyList()
}
val url = buildString {
append("https://api.")
append(domain)
append("/api/series/list/?query=")
append(query.urlEncoded())
}
webClient.httpGet(url).parseJsonArray()
} else {
if (page > 1) {
append("?page=")
append(page)
return emptyList()
}
val url = buildString {
append("https://api.")
append(domain)
append("/api/all_series/?page=1")
}
webClient.httpGet(url).parseJson().getJSONArray("series")
}
val doc = webClient.httpGet(url).parseHtml()
return doc.select(".gallery .mangas-gallery, .container-update-series .card-series-updates").map { div ->
val a = div.selectFirstOrThrow("a")
val href = a.attrAsRelativeUrl("href")
Manga(
id = generateUid(href),
url = href,
publicUrl = a.attrAsAbsoluteUrl("href"),
title = div.selectLastOrThrow(".title-serie, .name-manga").text(),
coverUrl = div.selectFirst("img")?.src().orEmpty(),
altTitle = null,
rating = RATING_UNKNOWN,
tags = emptySet(),
description = null,
state = null,
author = null,
isNsfw = false,
source = source,
)
}
return json.mapJSON { j ->
val slug = j.getString("slug")
Manga(
id = generateUid(slug),
url = slug,
publicUrl = slug,
title = j.getString("name"),
coverUrl = j.getString("cover"),
altTitle = null,
rating = RATING_UNKNOWN,
tags = emptySet(),
description = null,
state = null,
author = null,
isNsfw = isNsfwSource,
source = source,
)
}
}
override suspend fun getDetails(manga: Manga): Manga {
val doc = webClient.httpGet(manga.url.toAbsoluteUrl(domain)).parseHtml()
val dateFormat = SimpleDateFormat("dd.MM.yyyy", Locale.ROOT)
val chapters = doc.requireElementById("listadecapitulos")
val detailManga =
webClient.httpPost("https://api.$domain/api/serie_details/${manga.url}", emptyMap()).parseJson()
val body = JSONObject()
body.put("serie_slug", manga.url)
val chapterManga = webClient.httpPost("https://api.$domain/api/get_chapters_by_serie/", body).parseJson()
.getJSONArray("chapters")
val dateFormat = SimpleDateFormat("dd/MM/yyyy", sourceLocale)
return manga.copy(
description = doc.selectFirst(".sinopse .sinopse")?.html(),
author = doc.selectFirst(".author")?.text(),
coverUrl = doc.selectFirst(".side img")?.src().orEmpty(),
state = doc.selectFirst(".lancamento p")?.let {
when (it.text().lowercase()) {
description = detailManga.getString("synopsis"),
coverUrl = detailManga.getString("cover"),
altTitle = detailManga.getString("alternative_names"),
author = detailManga.getString("author"),
state = detailManga.getString("status")?.let {
when (it) {
"ongoing" -> MangaState.ONGOING
"completed", "finished" -> MangaState.FINISHED
"completed" -> MangaState.FINISHED
//"hiatus" -> MangaState.PAUSED
else -> null
}
},
chapters = chapters.select(".chapter").mapChapters(reversed = true) { i, div ->
val a = div.selectFirstOrThrow("a")
val href = a.attrAsRelativeUrl("href")
val title = div.selectFirstOrThrow(".chapter-title").text()
val dateText = div.selectFirstOrThrow(".chapter-lancado").text()
chapters = chapterManga.mapJSONIndexed { i, j ->
val url = "https://api.$domain/api/serie/${manga.url}/chapter/${j.getString("slug")}/images/imgs/"
MangaChapter(
id = generateUid(href),
name = title,
number = i + 1,
url = href,
id = generateUid(url),
name = j.getString("name"),
number = j.getString("name").removePrefix("Capítulo ").toInt(),
url = url,
scanlator = null,
uploadDate = dateFormat.tryParse(dateText),
uploadDate = parseChapterDate(
dateFormat,
j.getString("upload_date"),
),
branch = null,
source = source,
)
},
}.sortedBy { it.name },
)
}
private fun parseChapterDate(dateFormat: DateFormat, date: String?): Long {
val d = date?.lowercase() ?: return 0
return when {
d.endsWith(" atrás") -> parseRelativeDate(date)
else -> dateFormat.tryParse(date)
}
}
private fun parseRelativeDate(date: String): Long {
val number = Regex("""(\d+)""").find(date)?.value?.toIntOrNull() ?: return 0
val cal = Calendar.getInstance()
return when {
WordSet("dia", "dias").anyWordIn(date) -> cal.apply { add(Calendar.DAY_OF_MONTH, -number) }.timeInMillis
WordSet("hora", "horas").anyWordIn(date) -> cal.apply { add(Calendar.HOUR, -number) }.timeInMillis
else -> 0
}
}
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
val fullUrl = chapter.url.toAbsoluteUrl(domain)
val apiUrl = webClient.httpGet(fullUrl).parseHtml().selectFirstOrThrow("script:containsData(imageUrls)").data()
.substringAfter("apiUrl = \"").substringBefore("\";")
val json = webClient.httpGet(apiUrl.toAbsoluteUrl(domain)).parseJson().getJSONArray("chapter_images")
val pages = ArrayList<MangaPage>(json.length())
for (i in 0 until json.length()) {
val img = "https://media.$domain/${json.getString(i)}"
val jsonPages = webClient.httpPost(chapter.url, emptyMap()).parseJson().getJSONArray("chapter_images")
val pages = ArrayList<MangaPage>(jsonPages.length())
for (i in 0 until jsonPages.length()) {
val img = "https://$domain/${jsonPages.getString(i)}"
pages.add(
MangaPage(
id = generateUid(img),

Loading…
Cancel
Save