diff --git a/.github/summary.yaml b/.github/summary.yaml index 5c72cec38..0d6501027 100644 --- a/.github/summary.yaml +++ b/.github/summary.yaml @@ -1 +1 @@ -total: 1241 \ No newline at end of file +total: 1242 \ No newline at end of file diff --git a/.gitignore b/.gitignore index d5c1728f5..79beefc69 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ # When using Gradle or Maven with auto-import, you should exclude module files, # since they will be recreated, and may cause churn. Uncomment if using # auto-import. +.idea/deviceManager.xml .idea/.name .idea/artifacts .idea/compiler.xml diff --git a/.idea/.gitignore b/.idea/.gitignore index 3a7297b83..541d1b3c3 100644 --- a/.idea/.gitignore +++ b/.idea/.gitignore @@ -5,3 +5,4 @@ /copilot/chatSessions .name +deviceManager.xml diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/CMangaParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/CMangaParser.kt index 4b13e0c52..3c9e8e963 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/CMangaParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/CMangaParser.kt @@ -230,10 +230,10 @@ internal class CMangaParser(context: MangaLoaderContext) : private fun JSONObject.isLocked() = opt("lock") != null private fun containsAdsUrl(url: String): Boolean { - val ADS_URL = "https://img.cmangapi.com/data-image/index.php" + val adsUrl = "https://img.cmangapi.com/data-image/index.php" val cleanUrl = url.replace("\\", "") return when { - cleanUrl.startsWith(ADS_URL) -> true + cleanUrl.startsWith(adsUrl) -> true cleanUrl.contains("?v=12&data=") -> true else -> false } 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 3c7d0a201..8dc6df44e 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 @@ -100,7 +100,7 @@ internal class DamCoNuong(context: MangaLoaderContext) : return parseMangaList(doc) } - private suspend fun parseMangaList(doc: Document): List { + private 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.selectFirstOrThrow("div.relative a") 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 19533048c..eb616fc38 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 @@ -144,7 +144,7 @@ internal class DuaLeoTruyen(context: MangaLoaderContext) : ).closeQuietly() } - return doc.select(".content_view_chap img").mapIndexed { i, img -> + return doc.select(".content_view_chap img").mapIndexed { _, img -> val url = img.absUrl("data-original") MangaPage( id = generateUid(url), diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/LangGeekParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/LangGeekParser.kt new file mode 100644 index 000000000..e77b7cbca --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/LangGeekParser.kt @@ -0,0 +1,209 @@ +package org.koitharu.kotatsu.parsers.site.vi + +import okhttp3.HttpUrl.Companion.toHttpUrl +import org.json.JSONObject +import org.jsoup.nodes.Document +import org.jsoup.parser.Parser +import org.koitharu.kotatsu.parsers.MangaLoaderContext +import org.koitharu.kotatsu.parsers.MangaSourceParser +import org.koitharu.kotatsu.parsers.config.ConfigKey +import org.koitharu.kotatsu.parsers.core.PagedMangaParser +import org.koitharu.kotatsu.parsers.exception.ParseException +import org.koitharu.kotatsu.parsers.model.ContentType +import org.koitharu.kotatsu.parsers.model.Manga +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.model.MangaTag +import org.koitharu.kotatsu.parsers.model.SortOrder +import org.koitharu.kotatsu.parsers.model.MangaListFilter +import org.koitharu.kotatsu.parsers.model.MangaListFilterCapabilities +import org.koitharu.kotatsu.parsers.model.MangaListFilterOptions +import org.koitharu.kotatsu.parsers.model.RATING_UNKNOWN +import org.koitharu.kotatsu.parsers.util.generateUid +import org.koitharu.kotatsu.parsers.util.parseHtml +import org.koitharu.kotatsu.parsers.util.parseJson +import org.koitharu.kotatsu.parsers.util.parseSafe +import org.koitharu.kotatsu.parsers.util.requireSrc +import org.koitharu.kotatsu.parsers.util.textOrNull +import org.koitharu.kotatsu.parsers.util.urlEncoded +import org.koitharu.kotatsu.parsers.util.attrAsRelativeUrl +import org.koitharu.kotatsu.parsers.util.mapToSet +import org.koitharu.kotatsu.parsers.util.toAbsoluteUrl +import java.text.SimpleDateFormat +import java.util.EnumSet +import java.util.Locale + +@MangaSourceParser("LANGGEEK", "Làng Geek", "vi", ContentType.COMICS) +internal class LangGeekParser(context: MangaLoaderContext): + PagedMangaParser(context, MangaParserSource.LANGGEEK, 20, 100) { + + override val configKeyDomain = ConfigKey.Domain("langgeek.net") + + override fun onCreateConfig(keys: MutableCollection>) { + super.onCreateConfig(keys) + keys.add(userAgentKey) + } + + override val availableSortOrders: Set = EnumSet.of(SortOrder.POPULARITY) + + override val filterCapabilities: MangaListFilterCapabilities + get() = MangaListFilterCapabilities( + isSearchSupported = true, + ) + + override suspend fun getFilterOptions() = MangaListFilterOptions() + + override suspend fun getListPage(page: Int, order: SortOrder, filter: MangaListFilter): List { + return when { + !filter.query.isNullOrEmpty() -> { + if (page > 1) { + return emptyList() + } + + val keyword = filter.query.urlEncoded() + val url = "https://$domain/wp-admin/admin-ajax.php?action=flatsome_ajax_search_products&query=${keyword}" + val response = webClient.httpGet(url.toHttpUrl()).parseJson() + parseMangaSearch(response) + } + + filter.tags.isNotEmpty() -> { + val tag = filter.tags.first() + val url = buildString { + append("https://") + append(domain) + append("/the-loai/") + append(tag.key) + if (page > 1) { + append("/page/") + append(page) + } + } + val response = webClient.httpGet(url).parseHtml() + parseMangaList(response) + } + + else -> { + val url = buildString { + append("https://") + append(domain) + // SortOrder.POPULARITY, only has 1 page + append("/top-truyen/") + } + + val response = webClient.httpGet(url).parseHtml() + parseMangaList(response) + } + } + } + + private fun parseMangaSearch(json: JSONObject): List { + val suggestions = json.getJSONArray("suggestions") + + return (0 until suggestions.length()).map { index -> + val item = suggestions.getJSONObject(index) + val href = item.getString("url") + Manga( + id = generateUid(href), + url = href, + publicUrl = href, + title = Parser.unescapeEntities(item.getString("value"), false), + altTitles = emptySet(), + authors = emptySet(), + tags = emptySet(), + rating = RATING_UNKNOWN, + state = null, + coverUrl = item.getString("img"), + contentRating = null, + source = source, + ) + } + } + + private fun parseMangaList(doc: Document): List { + return doc.select("div.col.post-item").mapNotNull { div -> + val a = div.selectFirst("a.plain") ?: return@mapNotNull null + val img = div.selectFirst("img.wp-post-image")?.requireSrc() + val titleElement = div.selectFirst("h5.post-title") + val mangaUrl = a.attr("href") + val title = titleElement?.text().orEmpty() + + Manga( + id = generateUid(mangaUrl), + publicUrl = mangaUrl, + url = mangaUrl, + title = title, + altTitles = emptySet(), + authors = emptySet(), + tags = emptySet(), + rating = RATING_UNKNOWN, + state = null, + coverUrl = img, + contentRating = null, + source = source, + ) + } + } + + override suspend fun getDetails(manga: Manga): Manga { + val root = webClient.httpGet(manga.url).parseHtml() + val chapterDateFormat = SimpleDateFormat("dd/MM/yyyy", Locale.ROOT) + + val author = root.selectFirst("li:has(span:contains(Tác giả)) a")?.textOrNull() + val scanlator = root.selectFirst("li:has(span:contains(Nhóm dịch)) a")?.textOrNull() + + val description = root.selectFirst("li:has(strong:contains(Giới thiệu)) p")?.textOrNull() + + val tags = root.select("li:has(span:contains(Thể Loại)) a").mapToSet { a -> + val href = a.attr("href") + val key = href.substringAfter("/the-loai/").removeSuffix("/") + MangaTag( + key = key, + title = a.text(), + source = source, + ) + } + + val rows = root.select("div.list_issues > div.row-issue:not(.row-header)") + val total = rows.size + val chapters = root.select("div.list_issues > div.row-issue:not(.row-header)") + .mapIndexed { i, row -> + val a = row.selectFirst("div.col:first-child a") + ?: throw ParseException("Cant fetch chapter list", manga.url) + val href = a.attrAsRelativeUrl("href") + val dateText = row.selectFirst("div.col:last-child")?.text().orEmpty() + + MangaChapter( + id = generateUid(href), + title = a.text(), + number = (total - i).toFloat(), + volume = 0, + url = href, + scanlator = scanlator, + uploadDate = chapterDateFormat.parseSafe(dateText), + branch = null, + source = source, + ) + }.reversed() + + return manga.copy( + tags = tags, + authors = setOfNotNull(author), + description = description, + chapters = chapters, + ) + } + + override suspend fun getPages(chapter: MangaChapter): List { + val doc = webClient.httpGet(chapter.url.toAbsoluteUrl(domain)).parseHtml() + return doc.select("div.list-images img.lazy").mapNotNull { img -> + val url = img.attr("src") + MangaPage( + id = generateUid(url), + url = url, + preview = null, + source = source, + ) + } + } +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/MimiHentai.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/MimiHentai.kt index 0498d02b3..faa665b1a 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/MimiHentai.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/MimiHentai.kt @@ -74,7 +74,7 @@ internal class MimiHentai(context: MangaLoaderContext) : override suspend fun getListPage(page: Int, order: SortOrder, filter: MangaListFilter): List { val url = buildString { append("https://") - append(domain + "/" + apiSuffix) + append("$domain/$apiSuffix") if (!filter.query.isNullOrEmpty() || !filter.author.isNullOrEmpty() || filter.tags.isNotEmpty()) { append("/advance-search?page=") 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 6adede323..ce3c10f70 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 @@ -125,7 +125,7 @@ internal class SayHentai(context: MangaLoaderContext) : override suspend fun getPages(chapter: MangaChapter): List { val fullUrl = chapter.url.toAbsoluteUrl(domain) val doc = webClient.httpGet(fullUrl).parseHtml() - return doc.selectOrThrow("div.page-break img").mapIndexed { i, img -> + return doc.selectOrThrow("div.page-break img").mapIndexed { _, img -> val url = img.src().orEmpty() MangaPage( id = generateUid(url), diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/TruyenHentai18.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/TruyenHentai18.kt index f68db43c3..5d5857d10 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/TruyenHentai18.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/TruyenHentai18.kt @@ -55,7 +55,7 @@ internal class TruyenHentai18(context: MangaLoaderContext): else -> { buildString { - append(apiSuffix + "/posts") + append("$apiSuffix/posts") append("?language=vi") append("&order=") @@ -140,7 +140,7 @@ internal class TruyenHentai18(context: MangaLoaderContext): if (responseStart == -1) throw Exception("Không tìm thấy object 'response' trong script") val jsonStr = extractJsonString(cleanedScript, responseStart) - val responseObj = org.json.JSONObject(jsonStr) + val responseObj = JSONObject(jsonStr) val dataArray = responseObj.getJSONObject("response").optJSONArray("data") ?: throw Exception("Không tìm thấy trường 'data' trong object 'response'") @@ -283,4 +283,4 @@ internal class TruyenHentai18(context: MangaLoaderContext): }.toSet() } ?: emptySet() } -} \ No newline at end of file +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/yurigarden/YuriGarden.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/yurigarden/YuriGarden.kt index ac9975cfc..865b0b755 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/yurigarden/YuriGarden.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/yurigarden/YuriGarden.kt @@ -3,7 +3,6 @@ package org.koitharu.kotatsu.parsers.site.vi.yurigarden import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.MangaParserSource -import org.koitharu.kotatsu.parsers.site.vi.yurigarden.YuriGardenParser @MangaSourceParser("YURIGARDEN", "Yuri Garden", "vi") internal class YuriGarden(context: MangaLoaderContext) : @@ -12,4 +11,4 @@ internal class YuriGarden(context: MangaLoaderContext) : source = MangaParserSource.YURIGARDEN, domain = "yurigarden.com", isR18Enable = false - ) \ No newline at end of file + ) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/yurigarden/YuriGardenParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/yurigarden/YuriGardenParser.kt index cdd40906d..f944b1863 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/yurigarden/YuriGardenParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/yurigarden/YuriGardenParser.kt @@ -174,7 +174,7 @@ internal abstract class YuriGardenParser( manga.copy( altTitles = altTitles, authors = authors, - chapters = chaptersDeferred.await().mapChapters() { _, jo -> + chapters = chaptersDeferred.await().mapChapters { _, jo -> val chapId = jo.getLong("id") MangaChapter( id = generateUid(chapId), diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/yurigarden/YuriGardenR18.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/yurigarden/YuriGardenR18.kt index 2b76ceaa0..a93d43e6c 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/yurigarden/YuriGardenR18.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/yurigarden/YuriGardenR18.kt @@ -4,7 +4,6 @@ import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.ContentType import org.koitharu.kotatsu.parsers.model.MangaParserSource -import org.koitharu.kotatsu.parsers.site.vi.yurigarden.YuriGardenParser @MangaSourceParser("YURIGARDEN_R18", "Yuri Garden (18+)", "vi", type = ContentType.HENTAI) internal class YuriGardenR18(context: MangaLoaderContext) : @@ -13,4 +12,4 @@ internal class YuriGardenR18(context: MangaLoaderContext) : source = MangaParserSource.YURIGARDEN_R18, domain = "yurigarden.com", isR18Enable = true - ) \ No newline at end of file + ) 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 06a0df9de..7cc8ee9b3 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 @@ -27,7 +27,7 @@ internal abstract class WpComicsParser( ) : PagedMangaParser(context, source, pageSize) { companion object { - const val netDomain = "nettruyen1905.com" + const val GLOBAL_NETTRUYEN_DOMAIN = "nettruyen1905.com" } override val configKeyDomain = ConfigKey.Domain(domain) 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 index 3cf0d501a..a99a7b314 100644 --- 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 @@ -8,12 +8,10 @@ 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.network.UserAgents import org.koitharu.kotatsu.parsers.site.wpcomics.WpComicsParser import org.koitharu.kotatsu.parsers.exception.NotFoundException import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.util.* -import java.lang.NullPointerException import java.net.URL import java.util.* diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyenFE.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyenFE.kt index 86376c98e..c590fa9f2 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyenFE.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyenFE.kt @@ -16,7 +16,7 @@ import java.util.EnumSet @MangaSourceParser("NETTRUYENFE", "NetTruyenFE", "vi") internal class NetTruyenFE(context: MangaLoaderContext) : - WpComicsParser(context, MangaParserSource.NETTRUYENFE, WpComicsParser.netDomain, 20) { + WpComicsParser(context, MangaParserSource.NETTRUYENFE, GLOBAL_NETTRUYEN_DOMAIN, 20) { override val listUrl = "/tim-kiem-nang-cao" @@ -161,4 +161,4 @@ internal class NetTruyenFE(context: MangaLoaderContext) : } } }.getOrNull() -} \ No newline at end of file +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyenLL.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyenLL.kt index 90961691a..f34569aff 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyenLL.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyenLL.kt @@ -16,7 +16,7 @@ import java.util.EnumSet @MangaSourceParser("NETTRUYENLL", "NetTruyenLL", "vi") internal class NetTruyenLL(context: MangaLoaderContext) : - WpComicsParser(context, MangaParserSource.NETTRUYENLL, WpComicsParser.netDomain, 20) { + WpComicsParser(context, MangaParserSource.NETTRUYENLL, GLOBAL_NETTRUYEN_DOMAIN, 20) { override val listUrl = "/tim-kiem-nang-cao" @@ -161,4 +161,4 @@ internal class NetTruyenLL(context: MangaLoaderContext) : } } }.getOrNull() -} \ No newline at end of file +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyenSSR.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyenSSR.kt index be097fd39..35dce2270 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyenSSR.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyenSSR.kt @@ -16,7 +16,7 @@ import java.util.EnumSet @MangaSourceParser("NETTRUYENSSR", "NetTruyenSSR", "vi") internal class NetTruyenSSR(context: MangaLoaderContext) : - WpComicsParser(context, MangaParserSource.NETTRUYENSSR, WpComicsParser.netDomain, 20) { + WpComicsParser(context, MangaParserSource.NETTRUYENSSR, GLOBAL_NETTRUYEN_DOMAIN, 20) { override val listUrl = "/tim-kiem-nang-cao" @@ -161,4 +161,4 @@ internal class NetTruyenSSR(context: MangaLoaderContext) : } } }.getOrNull() -} \ No newline at end of file +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyenUU.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyenUU.kt index f96b6b7de..15f46d64c 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyenUU.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NetTruyenUU.kt @@ -16,7 +16,7 @@ import java.util.* @MangaSourceParser("NETTRUYENUU", "NetTruyenUU", "vi") internal class NetTruyenUU(context: MangaLoaderContext) : - WpComicsParser(context, MangaParserSource.NETTRUYENUU, WpComicsParser.netDomain, 20) { + WpComicsParser(context, MangaParserSource.NETTRUYENUU, GLOBAL_NETTRUYEN_DOMAIN, 20) { override val listUrl = "/tim-kiem-nang-cao" @@ -161,4 +161,4 @@ internal class NetTruyenUU(context: MangaLoaderContext) : } } }.getOrNull() -} \ No newline at end of file +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NhatTruyenVN.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NhatTruyenVN.kt index acc135fdf..203ce415d 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NhatTruyenVN.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/wpcomics/vi/NhatTruyenVN.kt @@ -9,7 +9,6 @@ import org.koitharu.kotatsu.parsers.site.wpcomics.WpComicsParser import org.koitharu.kotatsu.parsers.util.* import org.koitharu.kotatsu.parsers.util.json.getStringOrNull import java.text.SimpleDateFormat -import java.util.* @MangaSourceParser("NHATTRUYENVN", "NhatTruyenVN", "vi") internal class NhatTruyenVN(context: MangaLoaderContext) : @@ -50,7 +49,7 @@ internal class NhatTruyenVN(context: MangaLoaderContext) : val jo = data.getJSONObject(data.length() - 1 - i) val chapterSlug = jo.getString("chapter_slug") val chapterUrl = "/truyen-tranh/$slug/$chapterSlug" - val chapterNum = jo.getString("chapter_num").toFloat() ?: 0f + val chapterNum = jo.getString("chapter_num").toFloatOrNull() ?: 0f MangaChapter( id = generateUid(chapterUrl), @@ -65,55 +64,4 @@ internal class NhatTruyenVN(context: MangaLoaderContext) : ) } } - - private fun parseChapterDate(dateText: String?): Long { - if (dateText == null) return 0 - - val relativeTimePattern = Regex("(\\d+)\\s*(phút|giờ|ngày|tháng|năm) trước") - val absoluteTimePattern = Regex("(\\d{2}/\\d{2}/\\d{4})") - - return when { - dateText.contains("phút trước") -> { - val match = relativeTimePattern.find(dateText) - val minutes = match?.groups?.get(1)?.value?.toIntOrNull() ?: 0 - System.currentTimeMillis() - minutes * 60 * 1000 - } - - dateText.contains("giờ trước") -> { - val match = relativeTimePattern.find(dateText) - val hours = match?.groups?.get(1)?.value?.toIntOrNull() ?: 0 - System.currentTimeMillis() - hours * 3600 * 1000 - } - - dateText.contains("ngày trước") -> { - val match = relativeTimePattern.find(dateText) - val days = match?.groups?.get(1)?.value?.toIntOrNull() ?: 0 - System.currentTimeMillis() - days * 86400 * 1000 - } - - dateText.contains("tháng trước") -> { - val match = relativeTimePattern.find(dateText) - val months = match?.groups?.get(1)?.value?.toIntOrNull() ?: 0 - System.currentTimeMillis() - months * 30 * 86400 * 1000 - } - - dateText.contains("năm trước") -> { - val match = relativeTimePattern.find(dateText) - val years = match?.groups?.get(1)?.value?.toIntOrNull() ?: 0 - System.currentTimeMillis() - years * 365 * 86400 * 1000 - } - - absoluteTimePattern.matches(dateText) -> { - val formatter = SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()) - try { - val parsedDate = formatter.parse(dateText) - parsedDate?.time ?: 0L - } catch (e: Exception) { - 0L - } - } - - else -> 0L - } - } }