diff --git a/.github/summary.yaml b/.github/summary.yaml index f7706fbc..da87f700 100644 --- a/.github/summary.yaml +++ b/.github/summary.yaml @@ -1 +1 @@ -total: 1173 \ No newline at end of file +total: 1174 \ No newline at end of file diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Fecomicc.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Fecomicc.kt index aedcdbce..6d71c4ba 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Fecomicc.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/Fecomicc.kt @@ -5,7 +5,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.MangaParserSource import org.koitharu.kotatsu.parsers.site.madara.MadaraParser -@MangaSourceParser("FECOMICC", "Fecomicc", "vi") +@MangaSourceParser("FECOMICC", "Fecomic", "vi") internal class Fecomicc(context: MangaLoaderContext) : MadaraParser(context, MangaParserSource.FECOMICC, "fftruyen.net", 9) { override val listUrl = "comic/" diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/HentaiCube.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/HentaiCube.kt index 1922b636..8a49e2cd 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/HentaiCube.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/HentaiCube.kt @@ -11,7 +11,7 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.parsers.util.* -@MangaSourceParser("HENTAICUBE", "HentaiCube", "vi", ContentType.HENTAI) +@MangaSourceParser("HENTAICUBE", "CBHentai", "vi", ContentType.HENTAI) internal class HentaiCube(context: MangaLoaderContext) : MadaraParser(context, MangaParserSource.HENTAICUBE, "hentaicb.pro") { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/HentaiVnPlus.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/HentaiVnPlus.kt index 9baa6e8d..cb7a276d 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/HentaiVnPlus.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/HentaiVnPlus.kt @@ -6,9 +6,9 @@ import org.koitharu.kotatsu.parsers.model.ContentType import org.koitharu.kotatsu.parsers.model.MangaParserSource import org.koitharu.kotatsu.parsers.site.madara.MadaraParser -@MangaSourceParser("HENTAIVNPLUS", "HentaiVnPlus", "vi", ContentType.HENTAI) +@MangaSourceParser("HENTAIVNPLUS", "HentaiVN.plus", "vi", ContentType.HENTAI) internal class HentaiVnPlus(context: MangaLoaderContext) : - MadaraParser(context, MangaParserSource.HENTAIVNPLUS, "hentaivn.now", 24) { + MadaraParser(context, MangaParserSource.HENTAIVNPLUS, "hentaivn.li", 24) { override val listUrl = "truyen-hentai/" override val tagPrefix = "the-loai/" override val datePattern = "dd/MM/yyyy" 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 8a150fe8..078e3042 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 @@ -9,7 +9,7 @@ import org.koitharu.kotatsu.parsers.model.MangaParserSource import org.koitharu.kotatsu.parsers.site.madara.MadaraParser import org.koitharu.kotatsu.parsers.util.* -@MangaSourceParser("QUAANHDAOCUTEO", "Quaanhdaocuteo", "vi", ContentType.HENTAI) +@MangaSourceParser("QUAANHDAOCUTEO", "Quả Anh Đào Cuteo", "vi", ContentType.HENTAI) internal class Quaanhdaocuteo(context: MangaLoaderContext) : MadaraParser(context, MangaParserSource.QUAANHDAOCUTEO, "quaanhdaocuteo.xyz") { override val datePattern = "dd/MM/yyyy" diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/RuaHapChanhDay.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/RuaHapChanhDay.kt index 0010f7f3..a55f8ecf 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/RuaHapChanhDay.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/RuaHapChanhDay.kt @@ -5,7 +5,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.MangaParserSource import org.koitharu.kotatsu.parsers.site.madara.MadaraParser -@MangaSourceParser("RUAHAPCHANHDAY", "RuaHapChanhDay", "vi") +@MangaSourceParser("RUAHAPCHANHDAY", "Rùa Hấp Chanh Dây", "vi") internal class RuaHapChanhDay(context: MangaLoaderContext) : MadaraParser(context, MangaParserSource.RUAHAPCHANHDAY, "ruahapchanhday.com", 30) { override val datePattern = "dd/MM/yyyy" 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 9e487b40..fe6aea30 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 @@ -8,7 +8,7 @@ import org.koitharu.kotatsu.parsers.model.MangaParserSource import org.koitharu.kotatsu.parsers.site.madara.MadaraParser import org.koitharu.kotatsu.parsers.util.* -@MangaSourceParser("TRUYENTRANHDAMMYY", "TruyenTranhDamMyy", "vi") +@MangaSourceParser("TRUYENTRANHDAMMYY", "Truyện Tranh Đam Mỹ", "vi") internal class TruyenTranhDamMyy(context: MangaLoaderContext) : MadaraParser(context, MangaParserSource.TRUYENTRANHDAMMYY, "truyentranhdammyy.site") { override val postReq = true diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/TruyenVn.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/TruyenVn.kt index 58642e92..09bba1cc 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/TruyenVn.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/madara/vi/TruyenVn.kt @@ -8,7 +8,7 @@ import org.koitharu.kotatsu.parsers.site.madara.MadaraParser @MangaSourceParser("TRUYENVN", "TruyenVn", "vi", ContentType.HENTAI) internal class TruyenVn(context: MangaLoaderContext) : - MadaraParser(context, MangaParserSource.TRUYENVN, "truyenvn.vin", 20) { + MadaraParser(context, MangaParserSource.TRUYENVN, "truyenvn.live", 20) { override val listUrl = "truyen-tranh/" override val tagPrefix = "the-loai/" override val datePattern = "dd/MM/yyyy" diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/otakusanctuary/en/OtakusanEn.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/otakusanctuary/en/OtakusanEn.kt index ba73dd7b..b7279250 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/otakusanctuary/en/OtakusanEn.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/otakusanctuary/en/OtakusanEn.kt @@ -5,7 +5,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.MangaParserSource import org.koitharu.kotatsu.parsers.site.otakusanctuary.OtakuSanctuaryParser -@MangaSourceParser("OTAKUSAN_EN", "OtakuSan-En", "en") +@MangaSourceParser("OTAKUSAN_EN", "Otaku Sanctuary (EN)", "en") internal class OtakusanEn(context: MangaLoaderContext) : OtakuSanctuaryParser(context, MangaParserSource.OTAKUSAN_EN, "otakusan.me") { override val lang = "us" diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/otakusanctuary/vi/OtakusanVi.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/otakusanctuary/vi/OtakusanVi.kt index a7576354..ab019870 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/otakusanctuary/vi/OtakusanVi.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/otakusanctuary/vi/OtakusanVi.kt @@ -5,7 +5,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.MangaParserSource import org.koitharu.kotatsu.parsers.site.otakusanctuary.OtakuSanctuaryParser -@MangaSourceParser("OTAKUSAN_VI", "OtakuSan-Vi", "vi") +@MangaSourceParser("OTAKUSAN_VI", "Otaku Sanctuary (VN)", "vi") internal class OtakusanVi(context: MangaLoaderContext) : OtakuSanctuaryParser(context, MangaParserSource.OTAKUSAN_VI, "otakusan.me") { override val selectState = ".table-info tr:contains(Status) td" 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 7582fcdc..1e4e18ac 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 @@ -15,7 +15,7 @@ import java.util.* import org.koitharu.kotatsu.parsers.Broken @Broken -@MangaSourceParser("BLOGTRUYEN", "BlogTruyen", "vi") +@MangaSourceParser("BLOGTRUYEN", "Blog Truyện", "vi") internal class BlogTruyenParser(context: MangaLoaderContext) : PagedMangaParser(context, MangaParserSource.BLOGTRUYEN, pageSize = 20) { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/BlogTruyenVN.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/BlogTruyenVN.kt index 87fb7ce7..dc98f7d2 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/BlogTruyenVN.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/BlogTruyenVN.kt @@ -18,7 +18,7 @@ import java.text.SimpleDateFormat import java.util.* @Broken -@MangaSourceParser("BLOGTRUYENVN", "BlogTruyenVN", "vi") +@MangaSourceParser("BLOGTRUYENVN", "BlogTruyen.vn (Unofficial)", "vi") internal class BlogTruyenVN(context: MangaLoaderContext) : PagedMangaParser(context, MangaParserSource.BLOGTRUYENVN, pageSize = 20) { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/CuuTruyenParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/CuuTruyenParser.kt index 38add73c..0b134bfd 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/CuuTruyenParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/CuuTruyenParser.kt @@ -22,7 +22,7 @@ import java.net.HttpURLConnection import java.text.SimpleDateFormat import java.util.* -@MangaSourceParser("CUUTRUYEN", "CuuTruyen", "vi") +@MangaSourceParser("CUUTRUYEN", "Cứu Truyện", "vi") internal class CuuTruyenParser(context: MangaLoaderContext) : PagedMangaParser(context, MangaParserSource.CUUTRUYEN, 20), Interceptor { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/DuaLeoTruyen.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/DuaLeoTruyen.kt index f5894e82..a1ee6389 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/DuaLeoTruyen.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/DuaLeoTruyen.kt @@ -10,7 +10,7 @@ import org.koitharu.kotatsu.parsers.util.* import java.text.SimpleDateFormat import java.util.* -@MangaSourceParser("DUALEOTRUYEN", "DuaLeoTruyen", "vi", type = ContentType.HENTAI) +@MangaSourceParser("DUALEOTRUYEN", "Dưa Leo Truyện", "vi", type = ContentType.HENTAI) internal class DuaLeoTruyen(context: MangaLoaderContext) : PagedMangaParser(context, MangaParserSource.DUALEOTRUYEN, 60) { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/LxManga.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/LxManga.kt index 9308c5c2..9cca6b09 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/LxManga.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/LxManga.kt @@ -9,10 +9,10 @@ import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.util.* import java.util.* -@MangaSourceParser("LXMANGA", "LxManga", "vi", type = ContentType.HENTAI) +@MangaSourceParser("LXMANGA", "LXManga", "vi", type = ContentType.HENTAI) internal class LxManga(context: MangaLoaderContext) : PagedMangaParser(context, MangaParserSource.LXMANGA, 60) { - override val configKeyDomain = ConfigKey.Domain("lxmanga.store") + override val configKeyDomain = ConfigKey.Domain("lxmanga.live") override fun onCreateConfig(keys: MutableCollection>) { super.onCreateConfig(keys) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/SayHentai.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/SayHentai.kt index a18a985f..bb718e63 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/SayHentai.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/SayHentai.kt @@ -11,7 +11,7 @@ import java.util.* @MangaSourceParser("SAYHENTAI", "SayHentai", "vi", ContentType.HENTAI) internal class SayHentai(context: MangaLoaderContext) : PagedMangaParser(context, MangaParserSource.SAYHENTAI, 20) { - override val configKeyDomain = ConfigKey.Domain("sayhentai.one") + override val configKeyDomain = ConfigKey.Domain("sayhentai.art") override fun onCreateConfig(keys: MutableCollection>) { super.onCreateConfig(keys) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/WpComicsParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/WpComicsParser.kt index f843df58..bfa53748 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/WpComicsParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/WpComicsParser.kt @@ -232,7 +232,6 @@ internal abstract class WpComicsParser( ) } - protected open val selectDate = "div.col-xs-4" protected open val selectChapter = "div.list-chapter li.row:not(.heading)" diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/MeHentaiVN.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/MeHentaiVN.kt new file mode 100644 index 00000000..74116179 --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/MeHentaiVN.kt @@ -0,0 +1,74 @@ +package org.koitharu.kotatsu.parsers.site.wpcomics.vi + +import kotlinx.coroutines.async +import androidx.collection.ArraySet +import kotlinx.coroutines.coroutineScope +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.config.ConfigKey +import org.koitharu.kotatsu.parsers.model.MangaParserSource +import org.koitharu.kotatsu.parsers.site.wpcomics.WpComicsParser +import org.koitharu.kotatsu.parsers.model.* +import org.koitharu.kotatsu.parsers.util.* +import java.util.* + +@MangaSourceParser("MEHENTAIVN", "MeHentaiVN", "vi", ContentType.HENTAI) +internal class MeHentaiVN(context: MangaLoaderContext) : + WpComicsParser(context, MangaParserSource.MEHENTAIVN, "www.mehentaivn.xyz", 44) { + + override val configKeyDomain: ConfigKey.Domain = ConfigKey.Domain("www.mehentaivn.xyz", "www.hentaivnx.autos") + + override suspend fun getFilterOptions() = MangaListFilterOptions( + availableTags = fetchTags(), + availableStates = EnumSet.of(MangaState.ONGOING, MangaState.FINISHED), + ) + + override suspend fun getDetails(manga: Manga): Manga = coroutineScope { + val fullUrl = manga.url.toAbsoluteUrl(domain) + val doc = webClient.httpGet(fullUrl).parseHtml() + val chaptersDeferred = async { getChapters(doc) } + val tagMap = getOrCreateTagMap() + val tagsElement = doc.select("li.kind p.col-xs-8 a") + val mangaTags = tagsElement.mapNotNullToSet { + val tagTitle = it.text() + if (tagTitle.isNotEmpty()) + MangaTag( + title = tagTitle, + key = tagsElement.attr("href").substringAfterLast('/').trim(), + source = source + ) + else null + } + + manga.copy( + description = doc.selectFirst(selectDesc)?.html().orEmpty(), + altTitle = doc.selectFirst("h2.other-name")?.text().orEmpty(), + author = doc.body().select(selectAut).text(), + state = doc.selectFirst(selectState)?.let { + when (it.text()) { + in ongoing -> MangaState.ONGOING + in finished -> MangaState.FINISHED + else -> null + } + }, + tags = mangaTags, + rating = doc.selectFirst("div.star input")?.attr("value")?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN, + chapters = chaptersDeferred.await(), + isNsfw = true + ) + } + + private suspend fun fetchTags(): Set { + val doc = webClient.httpGet("https://$domain/").parseHtml() + val tagItems = doc.select("ul.dropdown-menu.megamenu li a") + val tagSet = ArraySet(tagItems.size) + for (item in tagItems) { + val title = item.attr("data-title").trim() + val key = item.attr("href").substringAfterLast('/').trim() + if (key.isNotEmpty() && title.isNotEmpty()) { + tagSet.add(MangaTag(title = title, key = key, source = source)) + } + } + return tagSet + } +} \ No newline at end of file diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyen.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyen.kt index a6295dd6..2877f852 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyen.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyen.kt @@ -1,15 +1,51 @@ package org.koitharu.kotatsu.parsers.site.wpcomics.vi +import androidx.collection.ArrayMap +import androidx.collection.ArraySet +import kotlinx.coroutines.async +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import org.jsoup.nodes.Document +import org.jsoup.nodes.Element import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.parsers.model.MangaParserSource import org.koitharu.kotatsu.parsers.site.wpcomics.WpComicsParser +import org.koitharu.kotatsu.parsers.model.* +import org.koitharu.kotatsu.parsers.util.* +import java.text.DateFormat +import java.text.SimpleDateFormat +import java.util.* @MangaSourceParser("NETTRUYEN", "NetTruyen", "vi") internal class NetTruyen(context: MangaLoaderContext) : WpComicsParser(context, MangaParserSource.NETTRUYEN, "nettruyenww.com", 44) { - override val configKeyDomain: ConfigKey.Domain = ConfigKey.Domain( - "nettruyenww.com", "nettruyenx.com", - ) + + override val configKeyDomain: ConfigKey.Domain = ConfigKey.Domain("nettruyenww.com", "nettruyenx.com") + + override suspend fun getDetails(manga: Manga): Manga = coroutineScope { + val fullUrl = manga.url.toAbsoluteUrl(domain) + val doc = webClient.httpGet(fullUrl).parseHtml() + val chaptersDeferred = async { getChapters(doc) } + val tagMap = getOrCreateTagMap() + val tagsElement = doc.select("li.kind p.col-xs-8 a") + val mangaTags = tagsElement.mapNotNullToSet { tagMap[it.text()] } + manga.copy( + description = doc.selectFirst(selectDesc)?.html().orEmpty(), + altTitle = doc.selectFirst("h2.other-name")?.text().orEmpty(), + author = doc.body().select(selectAut).text(), + state = doc.selectFirst(selectState)?.let { + when (it.text()) { + in ongoing -> MangaState.ONGOING + in finished -> MangaState.FINISHED + else -> null + } + }, + tags = mangaTags, + rating = doc.selectFirst("div.star input")?.attr("value")?.toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN, + chapters = chaptersDeferred.await().reversed(), + ) + } }