From 2175e91db7e76f98182fd0b8ecb8af7bcd9e4e60 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Fri, 21 Mar 2025 18:44:59 +0200 Subject: [PATCH] [DamCoNuong] Fixes --- .../kotatsu/parsers/site/vi/DamCoNuong.kt | 123 +++++++++--------- 1 file changed, 62 insertions(+), 61 deletions(-) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/DamCoNuong.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/DamCoNuong.kt index b63b6548..a07859d3 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/DamCoNuong.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/DamCoNuong.kt @@ -4,18 +4,23 @@ import org.jsoup.nodes.Document import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.config.ConfigKey -import org.koitharu.kotatsu.parsers.exception.ParseException import org.koitharu.kotatsu.parsers.core.LegacyPagedMangaParser +import org.koitharu.kotatsu.parsers.exception.ParseException import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.util.* +import org.koitharu.kotatsu.parsers.util.suspendlazy.getOrNull +import org.koitharu.kotatsu.parsers.util.suspendlazy.suspendLazy import java.text.SimpleDateFormat import java.util.* @MangaSourceParser("DAMCONUONG", "Dâm Cô Nương", "vi", type = ContentType.HENTAI) -internal class DamCoNuong(context: MangaLoaderContext) : LegacyPagedMangaParser(context, MangaParserSource.DAMCONUONG, 30) { +internal class DamCoNuong(context: MangaLoaderContext) : + LegacyPagedMangaParser(context, MangaParserSource.DAMCONUONG, 30) { override val configKeyDomain = ConfigKey.Domain("damconuong.fit") + private val availableTags = suspendLazy(initializer = ::fetchTags) + override fun onCreateConfig(keys: MutableCollection>) { super.onCreateConfig(keys) keys.add(userAgentKey) @@ -38,7 +43,7 @@ internal class DamCoNuong(context: MangaLoaderContext) : LegacyPagedMangaParser( ) override suspend fun getFilterOptions() = MangaListFilterOptions( - availableTags = fetchTags(), + availableTags = availableTags.get(), availableStates = EnumSet.of(MangaState.ONGOING, MangaState.FINISHED), ) @@ -57,10 +62,10 @@ internal class DamCoNuong(context: MangaLoaderContext) : LegacyPagedMangaParser( SortOrder.ALPHABETICAL -> "name" SortOrder.ALPHABETICAL_DESC -> "-name" else -> "-updated_at" - } + }, ) - if (filter.states.isNotEmpty()) { + if (filter.states.isNotEmpty()) { append("&filter[status]=") filter.states.forEach { append( @@ -91,41 +96,40 @@ internal class DamCoNuong(context: MangaLoaderContext) : LegacyPagedMangaParser( } private suspend fun parseMangaList(doc: Document): List { - return doc.select("div.border.rounded-lg.border-gray-300.dark\\:border-dark-blue.bg-white.dark\\:bg-fire-blue.manga-vertical").map { element -> - val mainA = element.selectFirst("div.relative a") - val href = mainA?.attr("href") ?: "" - val title = element.selectFirst("div.latest-chapter a.text-white.capitalize").text() ?: "No name" - val coverUrl = element.selectFirst("img.rounded-t-lg.cover.lazyload")?.attr("data-src") ?: "" - - Manga( - id = generateUid(href), - title = title, - altTitles = emptySet(), - url = href, - publicUrl = href.toAbsoluteUrl(domain), - rating = RATING_UNKNOWN, - contentRating = ContentRating.ADULT, - coverUrl = coverUrl, - tags = emptySet(), - state = null, - authors = emptySet(), - source = source, - ) - } + return doc.select("div.border.rounded-lg.border-gray-300.dark\\:border-dark-blue.bg-white.dark\\:bg-fire-blue.manga-vertical") + .map { element -> + val mainA = element.selectFirstOrThrow("div.relative a") + val href = mainA.attrAsRelativeUrl("href") + val title = element.selectFirst("div.latest-chapter a.text-white.capitalize")?.textOrNull() ?: "No name" + val coverUrl = element.selectFirst("img.rounded-t-lg.cover.lazyload")?.src() + + Manga( + id = generateUid(href), + title = title, + altTitles = emptySet(), + url = href, + publicUrl = href.toAbsoluteUrl(domain), + rating = RATING_UNKNOWN, + contentRating = ContentRating.ADULT, + coverUrl = coverUrl, + tags = emptySet(), + state = null, + authors = emptySet(), + source = source, + ) + } } override suspend fun getDetails(manga: Manga): Manga { val url = manga.url.toAbsoluteUrl(domain) val doc = webClient.httpGet(url).parseHtml() - val altTitles = doc.select("div.mt-2:contains(Tên khác:) span").map { it.text() }.toSet().orEmpty() - val tags = doc.select("div.mt-2:contains(Thể loại:) a").map { a -> - MangaTag( - key = "", // Auto-detected by title, idk - title = a.text(), - source = source, - ) - }.toSet() + val altTitles = doc.select("div.mt-2:contains(Tên khác:) span").mapNotNullToSet { it.textOrNull() } + val allTags = availableTags.getOrNull().orEmpty() + val tags = doc.select("div.mt-2:contains(Thể loại:) a").mapToSet { a -> + val title = a.text().toTitleCase() + allTags.find { x -> x.title == title } + } val stateText = doc.selectFirst("div.mt-2:contains(Tình trạng:) span")?.text() val state = when (stateText) { @@ -133,19 +137,20 @@ internal class DamCoNuong(context: MangaLoaderContext) : LegacyPagedMangaParser( else -> MangaState.FINISHED } - val chapterListDiv = doc.selectFirst("div#chapterList.justify-between.border-2.border-gray-100.dark\\:border-dark-blue.p-3.bg-white.dark\\:bg-fire-blue.shadow-md.rounded.dark\\:shadow-gray-900.mb-4") - ?: throw ParseException("Chapters list not found!", url) + val chapterListDiv = + doc.selectFirst("div#chapterList.justify-between.border-2.border-gray-100.dark\\:border-dark-blue.p-3.bg-white.dark\\:bg-fire-blue.shadow-md.rounded.dark\\:shadow-gray-900.mb-4") + ?: throw ParseException("Chapters list not found!", url) val chapterLinks = chapterListDiv.select("a.block") - val chapters = chapterLinks.mapIndexed { index, a -> - val title = a.selectFirst("span.text-ellipsis")?.text().orEmpty() - val href = a.attr("href") - val uploadDate = a.selectFirst("span.ml-2.whitespace-nowrap")?.text().orEmpty() + val chapters = chapterLinks.mapChapters(reversed = true) { index, a -> + val title = a.selectFirst("span.text-ellipsis")?.textOrNull() + val href = a.attrAsRelativeUrl("href") + val uploadDate = a.selectFirst("span.ml-2.whitespace-nowrap")?.text() MangaChapter( id = generateUid(href), title = title, - number = (chapterLinks.size - index).toFloat(), + number = index + 1f, volume = 0, url = href, scanlator = null, @@ -153,7 +158,7 @@ internal class DamCoNuong(context: MangaLoaderContext) : LegacyPagedMangaParser( branch = null, source = source, ) - }.reversed() + } return manga.copy( altTitles = altTitles, @@ -163,9 +168,9 @@ internal class DamCoNuong(context: MangaLoaderContext) : LegacyPagedMangaParser( ) } - override suspend fun getPages(chapter: MangaChapter): List { + override suspend fun getPages(chapter: MangaChapter): List { val doc = webClient.httpGet(chapter.url.toAbsoluteUrl(domain)).parseHtml() - return doc.select("div.text-center img.max-w-full.my-0.mx-auto").mapNotNull { img -> + return doc.select("div.text-center img.max-w-full.my-0.mx-auto").map { img -> val url = img.requireSrc() MangaPage( id = generateUid(url), @@ -176,7 +181,7 @@ internal class DamCoNuong(context: MangaLoaderContext) : LegacyPagedMangaParser( } } - private fun parseChapterDate(date: String?): Long { + private fun parseChapterDate(date: String?): Long { if (date == null) return 0 return when { date.contains("giây trước") -> System.currentTimeMillis() - date.removeSuffix(" giây trước").toLong() * 1000 @@ -204,21 +209,17 @@ internal class DamCoNuong(context: MangaLoaderContext) : LegacyPagedMangaParser( private suspend fun fetchTags(): Set { val doc = webClient.httpGet("https://$domain/tim-kiem").parseHtml() - return doc.select("label.ml-3.inline-flex.items-center.cursor-pointer.select-none").map { label -> - val key = label.attr("@click").substringAfter("toggleGenre('").substringBefore("')").trim() - // val key = getKeyTags(rawKey) - val title = label.selectFirst("span.ml-2.text-sm.font-semibold.text-blueGray-600.text-ellipsis")?.text() ?: "" - MangaTag( - key = key, - title = title, - source = source, - ) - }.toSet() + val regex = Regex("toggleGenre\\('([0-9]+)'\\)") + return doc.body().getElementsByAttribute("@click") + .mapNotNullToSet { label -> + // @click="toggleGenre('1')" + val attr = label.attr("@click") + val number = attr.findGroupValue(regex) ?: return@mapNotNullToSet null + MangaTag( + key = number, + title = label.textOrNull()?.toTitleCase(sourceLocale) ?: return@mapNotNullToSet null, + source = source, + ) + } } - - // Fix tags, if its necessary! - // private fun getKeyTags(rawKey: String): String { - // val number = rawKey.trim().replace(Regex("[^0-9]"), "") - // return (number.toIntOrNull()?.plus(1) ?: 0).toString() - // } }