From 6ce8a225149967ac6518ba776c24b04fd14588f0 Mon Sep 17 00:00:00 2001 From: Draken <131387159+dragonx943@users.noreply.github.com> Date: Wed, 31 Jul 2024 01:48:51 +0700 Subject: [PATCH 1/8] Update BlogTruyenParser.kt --- .../org/koitharu/kotatsu/parsers/site/vi/BlogTruyenParser.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/BlogTruyenParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/BlogTruyenParser.kt index da074f2e..bd087e72 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/BlogTruyenParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/BlogTruyenParser.kt @@ -20,7 +20,7 @@ class BlogTruyenParser(context: MangaLoaderContext) : PagedMangaParser(context, MangaParserSource.BLOGTRUYEN, pageSize = 20) { override val configKeyDomain: ConfigKey.Domain - get() = ConfigKey.Domain("blogtruyenmoi.com") + get() = ConfigKey.Domain("blogtruyenmoi.com", "blogtruyen.vn") override val availableSortOrders: Set get() = EnumSet.of(SortOrder.UPDATED) From 99b57e12976cb6689f83d2cc55f99146eafe58e3 Mon Sep 17 00:00:00 2001 From: Draken <131387159+dragonx943@users.noreply.github.com> Date: Wed, 31 Jul 2024 01:54:57 +0700 Subject: [PATCH 2/8] Update TruyenTranhDamMyy.kt --- .../kotatsu/parsers/site/madara/vi/TruyenTranhDamMyy.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/TruyenTranhDamMyy.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/TruyenTranhDamMyy.kt index 32b1cedc..09dc014c 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/TruyenTranhDamMyy.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/TruyenTranhDamMyy.kt @@ -12,7 +12,7 @@ import org.koitharu.kotatsu.parsers.util.* @Broken @MangaSourceParser("TRUYENTRANHDAMMYY", "TruyenTranhDamMyy", "vi") internal class TruyenTranhDamMyy(context: MangaLoaderContext) : - MadaraParser(context, MangaParserSource.TRUYENTRANHDAMMYY, "truyentranhdammyy.net") { + MadaraParser(context, MangaParserSource.TRUYENTRANHDAMMYY, "truyennhameo.com") { override val postReq = true override suspend fun loadChapters(mangaUrl: String, document: Document): List { val mangaId = document.select("div#manga-chapters-holder").attr("data-id") From da041df054e901b532067ec967b3705be924b0ce Mon Sep 17 00:00:00 2001 From: Draken <131387159+dragonx943@users.noreply.github.com> Date: Wed, 31 Jul 2024 02:05:13 +0700 Subject: [PATCH 3/8] Delete src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Saytruyenhay.kt --- .../parsers/site/madara/vi/Saytruyenhay.kt | 165 ------------------ 1 file changed, 165 deletions(-) delete mode 100644 src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Saytruyenhay.kt diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Saytruyenhay.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Saytruyenhay.kt deleted file mode 100644 index e661e64d..00000000 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Saytruyenhay.kt +++ /dev/null @@ -1,165 +0,0 @@ -package org.koitharu.kotatsu.parsers.site.madara.vi - -import kotlinx.coroutines.async -import kotlinx.coroutines.coroutineScope -import org.koitharu.kotatsu.parsers.MangaLoaderContext -import org.koitharu.kotatsu.parsers.MangaSourceParser -import org.koitharu.kotatsu.parsers.model.* -import org.koitharu.kotatsu.parsers.site.madara.MadaraParser -import org.koitharu.kotatsu.parsers.util.* -import java.util.* - -@MangaSourceParser("SAYTRUYENHAY", "PheTruyen", "vi") -internal class Saytruyenhay(context: MangaLoaderContext) : - MadaraParser(context, MangaParserSource.SAYTRUYENHAY, "phetruyen.vip", 40) { - - override val tagPrefix = "genre/" - override val withoutAjax = true - override val listUrl = "public/genre/manga/" - override val availableStates: Set = emptySet() - override val availableContentRating: Set = emptySet() - override val availableSortOrders: Set = - EnumSet.of(SortOrder.POPULARITY, SortOrder.UPDATED, SortOrder.RATING, SortOrder.NEWEST) - - init { - paginator.firstPage = 1 - searchPaginator.firstPage = 1 - } - - override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { - val url = buildString { - append("https://") - append(domain) - when (filter) { - is MangaListFilter.Search -> { - append("/search?s=") - append(filter.query.urlEncoded()) - append("&page=") - append(page.toString()) - } - - is MangaListFilter.Advanced -> { - - val tag = filter.tags.oneOrThrowIfMany() - if (filter.tags.isNotEmpty()) { - append("/$tagPrefix") - append(tag?.key.orEmpty()) - } else { - append("/$listUrl") - - } - append("?page=") - append(page.toString()) - append("&m_orderby=") - when (filter.sortOrder) { - SortOrder.UPDATED -> append("latest") - SortOrder.RATING -> append("rating") - SortOrder.POPULARITY -> append("views") - SortOrder.NEWEST -> append("new") - else -> append("latest") - } - } - - null -> { - append("/$listUrl") - append("?page=") - append(page.toString()) - } - } - } - - val doc = webClient.httpGet(url).parseHtml() - - - return doc.select("div.row.c-tabs-item__content").ifEmpty { - doc.select("div.page-item-detail") - }.map { div -> - val href = div.selectFirst("a")?.attrAsRelativeUrlOrNull("href") ?: div.parseFailed("Link not found") - val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".item-summary") - Manga( - id = generateUid(href), - url = href, - publicUrl = href.toAbsoluteUrl(div.host ?: domain), - coverUrl = div.selectFirst("img")?.src().orEmpty(), - title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4"))?.text().orEmpty(), - altTitle = null, - rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f, - tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a -> - MangaTag( - key = a.attr("href").removeSuffix('/').substringAfterLast('/'), - title = a.text().ifEmpty { return@mapNotNullToSet null }.toTitleCase(), - source = source, - ) - }.orEmpty(), - author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(), - state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText() - ?.lowercase().orEmpty()) { - in ongoing -> MangaState.ONGOING - in finished -> MangaState.FINISHED - else -> null - }, - source = source, - isNsfw = isNsfwSource, - ) - } - } - - override suspend fun getDetails(manga: Manga): Manga = coroutineScope { - val fullUrl = manga.url.toAbsoluteUrl(domain) - val doc = webClient.httpGet(fullUrl).parseHtml() - val body = doc.body() - - val chaptersDeferred = async { getChapters(manga, doc) } - - val desc = body.select(selectDesc).let { - if (it.select("p").text().isNotEmpty()) { - it.select("p").joinToString(separator = "\n\n") { p -> - p.text().replace("
", "\n") - } - } else { - it.text() - } - } - - val stateDiv = (body.selectFirst("div.post-content_item:contains(Status)") - ?: body.selectFirst("div.post-content_item:contains(Statut)") - ?: body.selectFirst("div.post-content_item:contains(État)") - ?: body.selectFirst("div.post-content_item:contains(حالة العمل)") - ?: body.selectFirst("div.post-content_item:contains(Estado)") - ?: body.selectFirst("div.post-content_item:contains(สถานะ)") - ?: body.selectFirst("div.post-content_item:contains(Stato)") - ?: body.selectFirst("div.post-content_item:contains(Durum)") - ?: body.selectFirst("div.post-content_item:contains(Statüsü)") - ?: body.selectFirst("div.post-content_item:contains(Статус)") - ?: body.selectFirst("div.post-content_item:contains(状态)") - ?: body.selectFirst("div.post-content_item:contains(الحالة)"))?.selectLast("div.summary-content") - - val state = stateDiv?.let { - when (it.text()) { - in ongoing -> MangaState.ONGOING - in finished -> MangaState.FINISHED - else -> null - } - } - - val alt = - doc.body().select(".post-content_item:contains(Alt) .summary-content").firstOrNull()?.tableValue()?.text() - ?.trim() ?: doc.body().select(".post-content_item:contains(Nomes alternativos: ) .summary-content") - .firstOrNull()?.tableValue()?.text()?.trim() - - manga.copy( - tags = doc.body().select(selectGenre).mapNotNullToSet { a -> - MangaTag( - key = a.attr("href").removeSuffix("/").substringAfterLast('/'), - title = a.text().toTitleCase(), - source = source, - ) - }, - description = desc, - altTitle = alt, - state = state, - chapters = chaptersDeferred.await(), - ) - } - -} From e33c57f51b16c42d56335c22f1d0a1c8e3f21563 Mon Sep 17 00:00:00 2001 From: Draken <131387159+dragonx943@users.noreply.github.com> Date: Wed, 31 Jul 2024 02:06:55 +0700 Subject: [PATCH 4/8] Update Quaanhdaocuteo.kt --- .../koitharu/kotatsu/parsers/site/madara/vi/Quaanhdaocuteo.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Quaanhdaocuteo.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Quaanhdaocuteo.kt index e07e439f..6787e9ab 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Quaanhdaocuteo.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Quaanhdaocuteo.kt @@ -11,7 +11,7 @@ import org.koitharu.kotatsu.parsers.util.* @MangaSourceParser("QUAANHDAOCUTEO", "Quaanhdaocuteo", "vi", ContentType.HENTAI) internal class Quaanhdaocuteo(context: MangaLoaderContext) : - MadaraParser(context, MangaParserSource.QUAANHDAOCUTEO, "quaanhdaocuteo.com") { + MadaraParser(context, MangaParserSource.QUAANHDAOCUTEO, "qadc.top") { override val datePattern = "dd/MM/yyyy" override val selectPage = "p img" From 017a9a58a36c43e5ad958ef1129d63c7cea84018 Mon Sep 17 00:00:00 2001 From: Draken <131387159+dragonx943@users.noreply.github.com> Date: Thu, 1 Aug 2024 00:36:19 +0700 Subject: [PATCH 5/8] Update TruyenTranhDamMyy.kt --- .../koitharu/kotatsu/parsers/site/madara/vi/TruyenTranhDamMyy.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/TruyenTranhDamMyy.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/TruyenTranhDamMyy.kt index 09dc014c..c8b42c3d 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/TruyenTranhDamMyy.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/TruyenTranhDamMyy.kt @@ -9,7 +9,6 @@ import org.koitharu.kotatsu.parsers.model.MangaParserSource import org.koitharu.kotatsu.parsers.site.madara.MadaraParser import org.koitharu.kotatsu.parsers.util.* -@Broken @MangaSourceParser("TRUYENTRANHDAMMYY", "TruyenTranhDamMyy", "vi") internal class TruyenTranhDamMyy(context: MangaLoaderContext) : MadaraParser(context, MangaParserSource.TRUYENTRANHDAMMYY, "truyennhameo.com") { From d1a12df18f49aa4a3d0833c5bfaca592e51ca42a Mon Sep 17 00:00:00 2001 From: Draken <131387159+dragonx943@users.noreply.github.com> Date: Thu, 1 Aug 2024 00:42:27 +0700 Subject: [PATCH 6/8] Create Saytruyenhay.kt --- .../parsers/site/madara/vi/Saytruyenhay.kt | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) create mode 100644 src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Saytruyenhay.kt diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Saytruyenhay.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Saytruyenhay.kt new file mode 100644 index 00000000..f8f23d0e --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Saytruyenhay.kt @@ -0,0 +1,166 @@ +package org.koitharu.kotatsu.parsers.site.madara.vi + +import kotlinx.coroutines.async +import kotlinx.coroutines.coroutineScope +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.model.* +import org.koitharu.kotatsu.parsers.site.madara.MadaraParser +import org.koitharu.kotatsu.parsers.util.* +import java.util.* + +@Broken +@MangaSourceParser("SAYTRUYENHAY", "PheTruyen", "vi") +internal class Saytruyenhay(context: MangaLoaderContext) : + MadaraParser(context, MangaParserSource.SAYTRUYENHAY, "phetruyen.vip", 40) { + + override val tagPrefix = "genre/" + override val withoutAjax = true + override val listUrl = "public/genre/manga/" + override val availableStates: Set = emptySet() + override val availableContentRating: Set = emptySet() + override val availableSortOrders: Set = + EnumSet.of(SortOrder.POPULARITY, SortOrder.UPDATED, SortOrder.RATING, SortOrder.NEWEST) + + init { + paginator.firstPage = 1 + searchPaginator.firstPage = 1 + } + + override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { + val url = buildString { + append("https://") + append(domain) + when (filter) { + is MangaListFilter.Search -> { + append("/search?s=") + append(filter.query.urlEncoded()) + append("&page=") + append(page.toString()) + } + + is MangaListFilter.Advanced -> { + + val tag = filter.tags.oneOrThrowIfMany() + if (filter.tags.isNotEmpty()) { + append("/$tagPrefix") + append(tag?.key.orEmpty()) + } else { + append("/$listUrl") + + } + append("?page=") + append(page.toString()) + append("&m_orderby=") + when (filter.sortOrder) { + SortOrder.UPDATED -> append("latest") + SortOrder.RATING -> append("rating") + SortOrder.POPULARITY -> append("views") + SortOrder.NEWEST -> append("new") + else -> append("latest") + } + } + + null -> { + append("/$listUrl") + append("?page=") + append(page.toString()) + } + } + } + + val doc = webClient.httpGet(url).parseHtml() + + + return doc.select("div.row.c-tabs-item__content").ifEmpty { + doc.select("div.page-item-detail") + }.map { div -> + val href = div.selectFirst("a")?.attrAsRelativeUrlOrNull("href") ?: div.parseFailed("Link not found") + val summary = div.selectFirst(".tab-summary") ?: div.selectFirst(".item-summary") + Manga( + id = generateUid(href), + url = href, + publicUrl = href.toAbsoluteUrl(div.host ?: domain), + coverUrl = div.selectFirst("img")?.src().orEmpty(), + title = (summary?.selectFirst("h3") ?: summary?.selectFirst("h4"))?.text().orEmpty(), + altTitle = null, + rating = div.selectFirst("span.total_votes")?.ownText()?.toFloatOrNull()?.div(5f) ?: -1f, + tags = summary?.selectFirst(".mg_genres")?.select("a")?.mapNotNullToSet { a -> + MangaTag( + key = a.attr("href").removeSuffix('/').substringAfterLast('/'), + title = a.text().ifEmpty { return@mapNotNullToSet null }.toTitleCase(), + source = source, + ) + }.orEmpty(), + author = summary?.selectFirst(".mg_author")?.selectFirst("a")?.ownText(), + state = when (summary?.selectFirst(".mg_status")?.selectFirst(".summary-content")?.ownText() + ?.lowercase().orEmpty()) { + in ongoing -> MangaState.ONGOING + in finished -> MangaState.FINISHED + else -> null + }, + source = source, + isNsfw = isNsfwSource, + ) + } + } + + override suspend fun getDetails(manga: Manga): Manga = coroutineScope { + val fullUrl = manga.url.toAbsoluteUrl(domain) + val doc = webClient.httpGet(fullUrl).parseHtml() + val body = doc.body() + + val chaptersDeferred = async { getChapters(manga, doc) } + + val desc = body.select(selectDesc).let { + if (it.select("p").text().isNotEmpty()) { + it.select("p").joinToString(separator = "\n\n") { p -> + p.text().replace("
", "\n") + } + } else { + it.text() + } + } + + val stateDiv = (body.selectFirst("div.post-content_item:contains(Status)") + ?: body.selectFirst("div.post-content_item:contains(Statut)") + ?: body.selectFirst("div.post-content_item:contains(État)") + ?: body.selectFirst("div.post-content_item:contains(حالة العمل)") + ?: body.selectFirst("div.post-content_item:contains(Estado)") + ?: body.selectFirst("div.post-content_item:contains(สถานะ)") + ?: body.selectFirst("div.post-content_item:contains(Stato)") + ?: body.selectFirst("div.post-content_item:contains(Durum)") + ?: body.selectFirst("div.post-content_item:contains(Statüsü)") + ?: body.selectFirst("div.post-content_item:contains(Статус)") + ?: body.selectFirst("div.post-content_item:contains(状态)") + ?: body.selectFirst("div.post-content_item:contains(الحالة)"))?.selectLast("div.summary-content") + + val state = stateDiv?.let { + when (it.text()) { + in ongoing -> MangaState.ONGOING + in finished -> MangaState.FINISHED + else -> null + } + } + + val alt = + doc.body().select(".post-content_item:contains(Alt) .summary-content").firstOrNull()?.tableValue()?.text() + ?.trim() ?: doc.body().select(".post-content_item:contains(Nomes alternativos: ) .summary-content") + .firstOrNull()?.tableValue()?.text()?.trim() + + manga.copy( + tags = doc.body().select(selectGenre).mapNotNullToSet { a -> + MangaTag( + key = a.attr("href").removeSuffix("/").substringAfterLast('/'), + title = a.text().toTitleCase(), + source = source, + ) + }, + description = desc, + altTitle = alt, + state = state, + chapters = chaptersDeferred.await(), + ) + } + +} From 2d274f37ee0270283082c495b089198f6c6e7980 Mon Sep 17 00:00:00 2001 From: Draken <131387159+dragonx943@users.noreply.github.com> Date: Thu, 1 Aug 2024 00:48:49 +0700 Subject: [PATCH 7/8] Update TruyenTranhDamMyy.kt --- .../koitharu/kotatsu/parsers/site/madara/vi/TruyenTranhDamMyy.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/TruyenTranhDamMyy.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/TruyenTranhDamMyy.kt index c8b42c3d..17f40e95 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/TruyenTranhDamMyy.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/TruyenTranhDamMyy.kt @@ -1,7 +1,6 @@ package org.koitharu.kotatsu.parsers.site.madara.vi 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.MangaChapter From fd3dc389df2716f36726c8757484d8569715890c Mon Sep 17 00:00:00 2001 From: Draken <131387159+dragonx943@users.noreply.github.com> Date: Thu, 1 Aug 2024 00:48:54 +0700 Subject: [PATCH 8/8] Update Saytruyenhay.kt --- .../org/koitharu/kotatsu/parsers/site/madara/vi/Saytruyenhay.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Saytruyenhay.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Saytruyenhay.kt index f8f23d0e..13f9b16f 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Saytruyenhay.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Saytruyenhay.kt @@ -2,6 +2,7 @@ package org.koitharu.kotatsu.parsers.site.madara.vi import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope +import org.koitharu.kotatsu.parsers.Broken import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.*