From 019b8cc0875a8fedca86945c72f1a3718a340837 Mon Sep 17 00:00:00 2001 From: devi Date: Fri, 1 Dec 2023 18:49:30 +0100 Subject: [PATCH] fix getlist some source mangaeader, MmrcmsParser add filter on NepnepParser --- .../parsers/site/mangareader/ar/SwaTeam.kt | 90 ++++----- .../site/mangareader/en/ManhwaFreak.kt | 94 +++++----- .../parsers/site/mangareader/en/RizzComic.kt | 52 +++--- .../parsers/site/mangareader/en/Zahard.kt | 65 +++---- .../parsers/site/mangareader/es/TuManhwas.kt | 44 ++--- .../site/mangareader/fr/ManhwaFreakFr.kt | 95 +++++----- .../site/mangareader/id/CosmicScans.kt | 87 +++++---- .../parsers/site/mangareader/id/KomikSan.kt | 97 +++++----- .../parsers/site/mangareader/id/Komikcast.kt | 95 ++++++---- .../parsers/site/mmrcms/MmrcmsParser.kt | 171 ++++++++++-------- .../kotatsu/parsers/site/mmrcms/ar/Onma.kt | 96 ++-------- .../kotatsu/parsers/site/mmrcms/id/Mangaid.kt | 4 - .../parsers/site/nepnep/NepnepParser.kt | 65 +++++-- 13 files changed, 529 insertions(+), 526 deletions(-) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/ar/SwaTeam.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/ar/SwaTeam.kt index eb82d9f9..f672d1c5 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/ar/SwaTeam.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/ar/SwaTeam.kt @@ -17,52 +17,58 @@ internal class SwaTeam(context: MangaLoaderContext) : override val selectMangaListImg = "img" override val isNetShieldProtected = true - override suspend fun getListPage( - page: Int, - query: String?, - tags: Set?, - sortOrder: SortOrder, - ): List { - if (!query.isNullOrEmpty()) { - if (page > lastSearchPage) { - return emptyList() - } - - val url = buildString { - append("https://") - append(domain) - append("/?s=") - append(query.urlEncoded()) - append("&page=") - append(page) - } - - val docs = webClient.httpGet(url).parseHtml() - lastSearchPage = docs.selectFirst(".pagination .next") - ?.previousElementSibling() - ?.text()?.toIntOrNull() ?: 1 - return parseMangaList(docs) - } - - val sortQuery = when (sortOrder) { - SortOrder.ALPHABETICAL -> "a-z" - SortOrder.NEWEST -> "added" - SortOrder.POPULARITY -> "popular" - SortOrder.UPDATED -> "update" - else -> "" - } - val tagKey = "genre[]".urlEncoded() - val tagQuery = - if (tags.isNullOrEmpty()) "" else tags.joinToString(separator = "&", prefix = "&") { "$tagKey=${it.key}" } + override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { val url = buildString { append("https://") append(domain) - append(listUrl) - append("/?order=") - append(sortQuery) - append(tagQuery) + + when (filter) { + + is MangaListFilter.Search -> { + append("/?s=") + append(filter.query.urlEncoded()) + } + + is MangaListFilter.Advanced -> { + append(listUrl) + + append("/?order=") + append( + when (filter.sortOrder) { + SortOrder.ALPHABETICAL -> "a-z" + SortOrder.NEWEST -> "added" + SortOrder.POPULARITY -> "popular" + SortOrder.UPDATED -> "update" + else -> "" + }, + ) + + val tagKey = "genre[]".urlEncoded() + val tagQuery = + if (filter.tags.isEmpty()) "" + else filter.tags.joinToString(separator = "&", prefix = "&") { "$tagKey=${it.key}" } + append(tagQuery) + + if (filter.states.isNotEmpty()) { + filter.states.oneOrThrowIfMany()?.let { + append("&status=") + when (it) { + MangaState.ONGOING -> append("ongoing") + MangaState.FINISHED -> append("completed") + MangaState.PAUSED -> append("hiatus") + else -> append("") + } + } + } + } + + null -> { + append(listUrl) + append("/?order=update") + } + } append("&page=") - append(page) + append(page.toString()) } return parseMangaList(webClient.httpGet(url).parseHtml()) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/ManhwaFreak.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/ManhwaFreak.kt index ae686339..6ffc0851 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/ManhwaFreak.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/ManhwaFreak.kt @@ -17,60 +17,54 @@ internal class ManhwaFreak(context: MangaLoaderContext) : override val selectMangaList = ".listupd .lastest-serie" override val selectMangaListImg = "img" + override val availableStates: Set = emptySet() + override val isMultipleTagsSupported = false - override suspend fun getListPage( - page: Int, - query: String?, - tags: Set?, - sortOrder: SortOrder, - ): List { - if (!query.isNullOrEmpty()) { - if (page > lastSearchPage) { - return emptyList() - } - val url = buildString { - append("https://") - append(domain) - append("/page/") - append(page) - append("/?s=") - append(query.urlEncoded()) - } - val docs = webClient.httpGet(url).parseHtml() - lastSearchPage = docs.selectFirst(".pagination .next") - ?.previousElementSibling() - ?.text()?.toIntOrNull() ?: 1 - return parseMangaList(docs) - } - if (!tags.isNullOrEmpty()) { - if (page > 1) { - return emptyList() - } - val tag = tags.oneOrThrowIfMany() - val url = buildString { - append("https://") - append(domain) - append("/genres/?genre=") - append(tag?.key.orEmpty()) - } - return parseMangaList(webClient.httpGet(url).parseHtml()) - } - if (page > 1) { - return emptyList() - } - val sortQuery = when (sortOrder) { - SortOrder.ALPHABETICAL -> "az" - SortOrder.NEWEST -> "new" - SortOrder.POPULARITY -> "views" - SortOrder.UPDATED -> "" - else -> "" - } + override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { val url = buildString { append("https://") append(domain) - append(listUrl) - append("/?order=") - append(sortQuery) + + when (filter) { + + is MangaListFilter.Search -> { + append("/page/") + append(page.toString()) + append("/?s=") + append(filter.query.urlEncoded()) + } + + is MangaListFilter.Advanced -> { + if (page > 1) { + return emptyList() + } + + if (filter.tags.isNotEmpty()) { + append("/genres/?genre=") + append( + filter.tags.oneOrThrowIfMany()?.let { + it.key + }, + ) + } else { + append(listUrl) + append("/?order=") + append( + when (filter.sortOrder) { + SortOrder.ALPHABETICAL -> "az" + SortOrder.NEWEST -> "new" + SortOrder.POPULARITY -> "views" + SortOrder.UPDATED -> "" + else -> "" + }, + ) + } + } + + null -> { + append(listUrl) + } + } } return parseMangaList(webClient.httpGet(url).parseHtml()) } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/RizzComic.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/RizzComic.kt index c1eb518d..48ffe06c 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/RizzComic.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/RizzComic.kt @@ -3,8 +3,9 @@ package org.koitharu.kotatsu.parsers.site.mangareader.en import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaListFilter import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.parsers.model.MangaTag +import org.koitharu.kotatsu.parsers.model.MangaState import org.koitharu.kotatsu.parsers.model.SortOrder import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser import org.koitharu.kotatsu.parsers.util.domain @@ -19,31 +20,40 @@ internal class RizzComic(context: MangaLoaderContext) : override val datePattern = "dd MMM yyyy" override val listUrl = "/series" - override val availableSortOrders: Set - get() = EnumSet.of(SortOrder.ALPHABETICAL) + override val availableSortOrders: Set = EnumSet.of(SortOrder.ALPHABETICAL) + override val availableStates: Set = emptySet() + override val isMultipleTagsSupported = false - override suspend fun getListPage( - page: Int, - query: String?, - tags: Set?, - sortOrder: SortOrder, - ): List { - val tag = tags.oneOrThrowIfMany() + // TODO Query created in json + override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { if (page > 1) { return emptyList() } - if (!query.isNullOrEmpty()) { - throw IllegalArgumentException("Search is not supported by this source") - } - val url = if (!tags.isNullOrEmpty()) { - buildString { - append("https://") - append(domain) - append("/genre/") - append(tag?.key.orEmpty()) + val url = buildString { + append("https://") + append(domain) + when (filter) { + + is MangaListFilter.Search -> { + throw IllegalArgumentException("Search is not supported by this source") + } + + is MangaListFilter.Advanced -> { + + if (filter.tags.isNotEmpty()) { + append("/genre/") + filter.tags.oneOrThrowIfMany()?.let { + append(it.key) + } + } else { + append(listUrl) + } + } + + null -> { + append(listUrl) + } } - } else { - "https://$domain$listUrl" } return parseMangaList(webClient.httpGet(url).parseHtml()) } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/Zahard.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/Zahard.kt index ef1064ce..7d57f9a9 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/Zahard.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/en/Zahard.kt @@ -3,11 +3,13 @@ package org.koitharu.kotatsu.parsers.site.mangareader.en import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaListFilter import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.parsers.model.MangaTag +import org.koitharu.kotatsu.parsers.model.MangaState import org.koitharu.kotatsu.parsers.model.SortOrder import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser 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.* @@ -19,53 +21,34 @@ internal class Zahard(context: MangaLoaderContext) : override val listUrl = "/library" override val selectChapter = "#chapterlist > ul > a" override val selectPage = "div#chapter_imgs img" + override val availableSortOrders: Set = EnumSet.of(SortOrder.NEWEST) + override val availableStates: Set = emptySet() + override val isMultipleTagsSupported = false - - override val availableSortOrders: Set - get() = EnumSet.of(SortOrder.NEWEST) - - - override suspend fun getListPage( - page: Int, - query: String?, - tags: Set?, - sortOrder: SortOrder, - ): List { - if (!query.isNullOrEmpty()) { - if (page > lastSearchPage) { - return emptyList() - } - - val url = buildString { - append("https://") - append(domain) - append(listUrl) - append("?search=") - append(query.urlEncoded()) - append("&page=") - append(page) - } - - val docs = webClient.httpGet(url).parseHtml() - lastSearchPage = docs.selectFirst("a[rel=next]") - ?.previousElementSibling() - ?.text()?.toIntOrNull() ?: 1 - return parseMangaList(docs) - } - - val tagKey = "tag".urlEncoded() - val tagQuery = - if (tags.isNullOrEmpty()) "" else tags.joinToString(separator = "&", prefix = "&") { "$tagKey=${it.key}" } + override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { val url = buildString { append("https://") append(domain) append(listUrl) append("?page=") - append(page) - append(tagQuery) - + append(page.toString()) + when (filter) { + + is MangaListFilter.Search -> { + append("&search=") + append(filter.query.urlEncoded()) + } + + is MangaListFilter.Advanced -> { + filter.tags.oneOrThrowIfMany()?.let { + append("tag=") + append(it.key) + } + } + + null -> {} + } } - return parseMangaList(webClient.httpGet(url).parseHtml()) } } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/es/TuManhwas.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/es/TuManhwas.kt index 06afc82b..d8e2af53 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/es/TuManhwas.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/es/TuManhwas.kt @@ -12,41 +12,41 @@ import java.util.ArrayList import java.util.Calendar import java.util.EnumSet -@MangaSourceParser("TU_MANHWAS", "TuManhwas", "es") +@MangaSourceParser("TU_MANHWAS", "TuManhwas.com", "es") internal class TuManhwas(context: MangaLoaderContext) : MangaReaderParser(context, MangaSource.TU_MANHWAS, "tumanhwas.com", 20, 20) { override val listUrl = "/biblioteca" override val selectPage = "div#readerarea img" - - - override val availableSortOrders: Set - get() = EnumSet.of(SortOrder.NEWEST) + override val availableSortOrders: Set = EnumSet.of(SortOrder.NEWEST) + override val availableStates: Set = emptySet() + override val isMultipleTagsSupported = false override suspend fun getAvailableTags(): Set = emptySet() - override suspend fun getListPage( - page: Int, - query: String?, - tags: Set?, - sortOrder: SortOrder, - ): List { - val tag = tags.oneOrThrowIfMany() + + override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { val url = buildString { append("https://") append(domain) append(listUrl) append("?page=") - append(page) - if (!tags.isNullOrEmpty()) { - append("&genero=") - append(tag?.key.orEmpty()) + append(page.toString()) + when (filter) { + + is MangaListFilter.Search -> { + append("&search=") + append(filter.query.urlEncoded()) + } + + is MangaListFilter.Advanced -> { + filter.tags.oneOrThrowIfMany()?.let { + append("&genero=") + append(it.key) + } + } + + null -> {} } - if (!query.isNullOrEmpty()) { - append("&search=") - append(query.urlEncoded()) - } - } - return parseMangaList(webClient.httpGet(url).parseHtml()) } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/fr/ManhwaFreakFr.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/fr/ManhwaFreakFr.kt index ac5a6929..26991985 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/fr/ManhwaFreakFr.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/fr/ManhwaFreakFr.kt @@ -18,61 +18,54 @@ internal class ManhwaFreakFr(context: MangaLoaderContext) : override val selectMangaList = ".listupd .lastest-serie" override val selectMangaListImg = "img" override val sourceLocale: Locale = Locale.ENGLISH + override val availableStates: Set = emptySet() + override val isMultipleTagsSupported = false - override suspend fun getListPage( - page: Int, - query: String?, - tags: Set?, - sortOrder: SortOrder, - ): List { - if (!query.isNullOrEmpty()) { - if (page > lastSearchPage) { - return emptyList() - } - val url = buildString { - append("https://") - append(domain) - append("/page/") - append(page) - append("/?s=") - append(query.urlEncoded()) - } - val docs = webClient.httpGet(url).parseHtml() - lastSearchPage = docs.selectFirst(".pagination .next") - ?.previousElementSibling() - ?.text()?.toIntOrNull() ?: 1 - return parseMangaList(docs) - } - if (!tags.isNullOrEmpty()) { - - if (page > 1) { - return emptyList() - } - val tag = tags.oneOrThrowIfMany() - val url = buildString { - append("https://") - append(domain) - append("/genres/?genre=") - append(tag?.key.orEmpty()) - } - return parseMangaList(webClient.httpGet(url).parseHtml()) - } - if (page > 1) { - return emptyList() - } - val sortQuery = when (sortOrder) { - SortOrder.ALPHABETICAL -> "az" - SortOrder.NEWEST -> "new" - SortOrder.POPULARITY -> "views" - SortOrder.UPDATED -> "" - else -> "" - } + override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { val url = buildString { append("https://") append(domain) - append(listUrl) - append("/?order=") - append(sortQuery) + + when (filter) { + + is MangaListFilter.Search -> { + append("/page/") + append(page.toString()) + append("/?s=") + append(filter.query.urlEncoded()) + } + + is MangaListFilter.Advanced -> { + if (page > 1) { + return emptyList() + } + + if (filter.tags.isNotEmpty()) { + append("/genres/?genre=") + append( + filter.tags.oneOrThrowIfMany()?.let { + it.key + }, + ) + } else { + append(listUrl) + append("/?order=") + append( + when (filter.sortOrder) { + SortOrder.ALPHABETICAL -> "az" + SortOrder.NEWEST -> "new" + SortOrder.POPULARITY -> "views" + SortOrder.UPDATED -> "" + else -> "" + }, + ) + } + } + + null -> { + append(listUrl) + } + } } return parseMangaList(webClient.httpGet(url).parseHtml()) } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/CosmicScans.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/CosmicScans.kt index 52526dc1..f979bece 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/CosmicScans.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/CosmicScans.kt @@ -3,13 +3,16 @@ package org.koitharu.kotatsu.parsers.site.mangareader.id import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaListFilter import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.parsers.model.MangaTag +import org.koitharu.kotatsu.parsers.model.MangaState import org.koitharu.kotatsu.parsers.model.SortOrder import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser 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 import java.util.Locale @MangaSourceParser("COSMIC_SCANS", "CosmicScans.id", "id") @@ -17,54 +20,50 @@ internal class CosmicScans(context: MangaLoaderContext) : MangaReaderParser(context, MangaSource.COSMIC_SCANS, "cosmicscans.id", pageSize = 30, searchPageSize = 30) { override val sourceLocale: Locale = Locale.ENGLISH + override val availableSortOrders: Set = EnumSet.of(SortOrder.UPDATED) + override val availableStates: Set = emptySet() + override val isMultipleTagsSupported = false override val listUrl = "/semua-komik" - override suspend fun getListPage( - page: Int, - query: String?, - tags: Set?, - sortOrder: SortOrder, - ): List { - if (!query.isNullOrEmpty()) { - if (page > lastSearchPage) { - return emptyList() - } - val url = buildString { - append("https://") - append(domain) - append("/page/") - append(page) - append("/?s=") - append(query.urlEncoded()) - } - val docs = webClient.httpGet(url).parseHtml() - lastSearchPage = docs.selectFirst(".pagination .next") - ?.previousElementSibling() - ?.text()?.toIntOrNull() ?: 1 - return parseMangaList(docs) - } - if (page > 1) { - return emptyList() - } - val sortQuery = when (sortOrder) { - SortOrder.ALPHABETICAL -> "title" - SortOrder.NEWEST -> "latest" - SortOrder.POPULARITY -> "popular" - SortOrder.UPDATED -> "update" - else -> "" - } - val tagKey = "genre[]".urlEncoded() - val tagQuery = - if (tags.isNullOrEmpty()) "" else tags.joinToString(separator = "&", prefix = "&") { "$tagKey=${it.key}" } + override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { val url = buildString { append("https://") append(domain) - append(listUrl) - append("/?order=") - append(sortQuery) - append(tagQuery) - append("&page=") - append(page) + + when (filter) { + + is MangaListFilter.Search -> { + append("/page/") + append(page.toString()) + append("/?s=") + append(filter.query.urlEncoded()) + } + + is MangaListFilter.Advanced -> { + if (filter.tags.isNotEmpty()) { + filter.tags.oneOrThrowIfMany()?.let { + append("/genres/") + append(it.key) + append("/page/") + append(page.toString()) + append('/') + } + } else { + if (page > 1) { + return emptyList() + } + append(listUrl) + } + + } + + null -> { + if (page > 1) { + return emptyList() + } + append(listUrl) + } + } } return parseMangaList(webClient.httpGet(url).parseHtml()) } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/KomikSan.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/KomikSan.kt index 10efd3fa..9074f62c 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/KomikSan.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/KomikSan.kt @@ -3,11 +3,13 @@ package org.koitharu.kotatsu.parsers.site.mangareader.id import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.Manga +import org.koitharu.kotatsu.parsers.model.MangaListFilter import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.parsers.model.MangaTag +import org.koitharu.kotatsu.parsers.model.MangaState import org.koitharu.kotatsu.parsers.model.SortOrder import org.koitharu.kotatsu.parsers.site.mangareader.MangaReaderParser 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 @@ -19,50 +21,61 @@ internal class KomikSan(context: MangaLoaderContext) : override val listUrl = "/list" override val datePattern = "MMM d, yyyy" - override suspend fun getListPage( - page: Int, - query: String?, - tags: Set?, - sortOrder: SortOrder, - ): List { - if (!query.isNullOrEmpty()) { - if (page > lastSearchPage) { - return emptyList() - } - - val url = buildString { - append("https://") - append(domain) - append("/search?search=") - append(query.urlEncoded()) - append("&page=") - append(page) - } - val docs = webClient.httpGet(url).parseHtml() - lastSearchPage = docs.selectFirst(".pagination .next") - ?.previousElementSibling() - ?.text()?.toIntOrNull() ?: 1 - return parseMangaList(docs) - } - val sortQuery = when (sortOrder) { - SortOrder.ALPHABETICAL -> "title" - SortOrder.NEWEST -> "latest" - SortOrder.POPULARITY -> "popular" - SortOrder.UPDATED -> "update" - else -> "" - } - val tagKey = "genre[]".urlEncoded() - val tagQuery = - if (tags.isNullOrEmpty()) "" else tags.joinToString(separator = "&", prefix = "&") { "$tagKey=${it.key}" } + override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { val url = buildString { append("https://") append(domain) - append(listUrl) - append("/?order=") - append(sortQuery) - append(tagQuery) - append("&page=") - append(page) + when (filter) { + + is MangaListFilter.Search -> { + append("/search?search=") + append(filter.query.urlEncoded()) + append("&page=") + append(page.toString()) + } + + is MangaListFilter.Advanced -> { + append(listUrl) + + append("/?order=") + append( + when (filter.sortOrder) { + SortOrder.ALPHABETICAL -> "title" + SortOrder.NEWEST -> "latest" + SortOrder.POPULARITY -> "popular" + SortOrder.UPDATED -> "update" + else -> "" + }, + ) + + val tagKey = "genre[]".urlEncoded() + val tagQuery = + if (filter.tags.isEmpty()) "" + else filter.tags.joinToString(separator = "&", prefix = "&") { "$tagKey=${it.key}" } + append(tagQuery) + + if (filter.states.isNotEmpty()) { + filter.states.oneOrThrowIfMany()?.let { + append("&status=") + when (it) { + MangaState.ONGOING -> append("ongoing") + MangaState.FINISHED -> append("completed") + MangaState.PAUSED -> append("hiatus") + else -> append("") + } + } + } + + append("&page=") + append(page.toString()) + } + + null -> { + append(listUrl) + append("/?order=update&page=") + append(page.toString()) + } + } } return parseMangaList(webClient.httpGet(url).parseHtml()) } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/Komikcast.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/Komikcast.kt index 63fd834f..989284df 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/Komikcast.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mangareader/id/Komikcast.kt @@ -13,55 +13,70 @@ import java.util.* @MangaSourceParser("KOMIKCAST", "KomikCast", "id") internal class Komikcast(context: MangaLoaderContext) : - MangaReaderParser(context, MangaSource.KOMIKCAST, "komikcast.ch", pageSize = 60, searchPageSize = 28) { + MangaReaderParser(context, MangaSource.KOMIKCAST, "komikcast.lol", pageSize = 60, searchPageSize = 28) { override val listUrl = "/daftar-komik" override val datePattern = "MMM d, yyyy" override val sourceLocale: Locale = Locale.ENGLISH - override val availableSortOrders: Set - get() = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.ALPHABETICAL) - - override suspend fun getListPage( - page: Int, - query: String?, - tags: Set?, - sortOrder: SortOrder, - ): List { - if (!query.isNullOrEmpty()) { - if (page > lastSearchPage) { - return emptyList() - } - val url = buildString { - append("https://") - append(domain) - append("/page/") - append(page) - append("/?s=") - append(query.urlEncoded()) - } - val docs = webClient.httpGet(url).parseHtml() - lastSearchPage = docs.selectFirst(".pagination .next") - ?.previousElementSibling() - ?.text()?.toIntOrNull() ?: 1 - return parseMangaList(docs) - } - val tagKey = "genre[]".urlEncoded() - val tagQuery = - if (tags.isNullOrEmpty()) "" else tags.joinToString(separator = "&", prefix = "&") { "$tagKey=${it.key}" } + override val availableSortOrders: Set = + EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.ALPHABETICAL) + override val availableStates: Set = EnumSet.of(MangaState.ONGOING, MangaState.FINISHED) + + override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { val url = buildString { append("https://") append(domain) - append(listUrl) - append("/page/") - append(page) - when (sortOrder) { - SortOrder.ALPHABETICAL -> append("/?orderby=titleasc") - SortOrder.POPULARITY -> append("/?orderby=popular") - SortOrder.UPDATED -> append("/?sortby=update") - else -> append("/?sortby=update") + + when (filter) { + + is MangaListFilter.Search -> { + append("/page/") + append(page.toString()) + append("/?s=") + append(filter.query.urlEncoded()) + } + + is MangaListFilter.Advanced -> { + append(listUrl) + append("/page/") + append(page.toString()) + + append("/?orderby=") + append( + when (filter.sortOrder) { + SortOrder.ALPHABETICAL -> append("titleasc") + SortOrder.POPULARITY -> append("popular") + SortOrder.UPDATED -> append("update") + else -> append("update") + }, + ) + + val tagKey = "genre[]".urlEncoded() + val tagQuery = + if (filter.tags.isEmpty()) "" + else filter.tags.joinToString(separator = "&", prefix = "&") { "$tagKey=${it.key}" } + append(tagQuery) + + if (filter.states.isNotEmpty()) { + filter.states.oneOrThrowIfMany()?.let { + append("&status=") + when (it) { + MangaState.ONGOING -> append("Ongoing") + MangaState.FINISHED -> append("Completed") + else -> append("") + } + } + } + } + + null -> { + append(listUrl) + append("/?orderby=update&page=") + append(page.toString()) + } } - append(tagQuery) } + return parseMangaList(webClient.httpGet(url).parseHtml()) } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mmrcms/MmrcmsParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mmrcms/MmrcmsParser.kt index 86385d29..9d025b62 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mmrcms/MmrcmsParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mmrcms/MmrcmsParser.kt @@ -55,87 +55,114 @@ internal abstract class MmrcmsParser( "مكتملة", ) + override val isMultipleTagsSupported = false + protected open val imgUpdated = "/cover/cover_250x350.jpg" - override suspend fun getListPage( - page: Int, - query: String?, - tags: Set?, - sortOrder: SortOrder, - ): List { - val tag = tags.oneOrThrowIfMany() - val url = if (!query.isNullOrEmpty() || !tags.isNullOrEmpty() || sortOrder != SortOrder.UPDATED) { - buildString { - append("https://") - append(domain) - append("/$listUrl/") - append("?page=") - append(page.toString()) - append("&asc=true&author=&tag=") - append("&alpha=") - if (!query.isNullOrEmpty()) { - append(query.urlEncoded()) - } - append("&cat=") - if (!tags.isNullOrEmpty()) { - append(tag?.key.orEmpty()) + override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { + + when (filter) { + + is MangaListFilter.Search -> { + val url = buildString { + append("https://") + append(domain) + append('/') + append(listUrl) + append("/?page=") + append(page.toString()) + append("&asc=true&author=&tag=&alpha=") + append(filter.query.urlEncoded()) + append("&cat=&sortBy=views") } - append("&sortBy=") - when (sortOrder) { - SortOrder.POPULARITY -> append("views") - SortOrder.ALPHABETICAL -> append("name") - else -> append("name") + return parseMangaList(webClient.httpGet(url).parseHtml()) + } + + is MangaListFilter.Advanced -> { + + if (filter.sortOrder == SortOrder.UPDATED) { + val url = buildString { + append("https://") + append(domain) + append("/latest-release?page=") + append(page.toString()) + } + return parseMangaListUpdated(webClient.httpGet(url).parseHtml()) + + } else { + val url = buildString { + append("https://") + append(domain) + append('/') + append(listUrl) + append("/?page=") + append(page.toString()) + append("&asc=true&author=&tag=&alpha=&cat=") + filter.tags.oneOrThrowIfMany()?.let { + append(it.key) + } + append("&sortBy=") + when (filter.sortOrder) { + SortOrder.POPULARITY -> append("views") + SortOrder.ALPHABETICAL -> append("name") + else -> append("name") + } + } + return parseMangaList(webClient.httpGet(url).parseHtml()) } } - } else { - buildString { - append("https://") - append(domain) - append("/latest-release") - append("?page=") - append(page.toString()) + + null -> { + val url = buildString { + append("https://") + append(domain) + append("/latest-release?page=") + append(page.toString()) + } + return parseMangaList(webClient.httpGet(url).parseHtml()) } } - val doc = webClient.httpGet(url).parseHtml() - if (!query.isNullOrEmpty() || !tags.isNullOrEmpty() || sortOrder != SortOrder.UPDATED) { - return doc.select("div.media").map { div -> - val href = div.selectFirstOrThrow("a").attrAsRelativeUrl("href") - Manga( - id = generateUid(href), - url = href, - publicUrl = href.toAbsoluteUrl(div.host ?: domain), - coverUrl = div.selectFirst("img")?.src().orEmpty(), - title = div.selectFirstOrThrow("div.media-body h5").text().orEmpty(), - altTitle = null, - rating = div.selectFirstOrThrow("span").ownText().toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN, - tags = emptySet(), - author = null, - state = null, - source = source, - isNsfw = isNsfwSource, - ) - } - } else { - return doc.select("div.manga-item").map { div -> - val href = div.selectFirstOrThrow("a").attrAsRelativeUrl("href") - val deeplink = href.substringAfterLast("/") - Manga( - id = generateUid(href), - url = href, - publicUrl = href.toAbsoluteUrl(div.host ?: domain), - coverUrl = "https://$domain/uploads/manga/$deeplink$imgUpdated", - title = div.selectFirstOrThrow("h3 a").text().orEmpty(), - altTitle = null, - rating = RATING_UNKNOWN, - tags = emptySet(), - author = null, - state = null, - source = source, - isNsfw = isNsfwSource, - ) - } + } + + protected open fun parseMangaList(doc: Document): List { + return doc.select("div.media").map { div -> + val href = div.selectFirstOrThrow("a").attrAsRelativeUrl("href") + Manga( + id = generateUid(href), + url = href, + publicUrl = href.toAbsoluteUrl(div.host ?: domain), + coverUrl = div.selectFirst("img")?.src().orEmpty(), + title = div.selectFirstOrThrow("div.media-body h5").text().orEmpty(), + altTitle = null, + rating = div.selectFirstOrThrow("span").ownText().toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN, + tags = emptySet(), + author = null, + state = null, + source = source, + isNsfw = isNsfwSource, + ) } + } + protected open fun parseMangaListUpdated(doc: Document): List { + return doc.select("div.manga-item").map { div -> + val href = div.selectFirstOrThrow("a").attrAsRelativeUrl("href") + val deeplink = href.substringAfterLast("/") + Manga( + id = generateUid(href), + url = href, + publicUrl = href.toAbsoluteUrl(div.host ?: domain), + coverUrl = "https://$domain/uploads/manga/$deeplink$imgUpdated", + title = div.selectFirstOrThrow("h3 a").text().orEmpty(), + altTitle = null, + rating = RATING_UNKNOWN, + tags = emptySet(), + author = null, + state = null, + source = source, + isNsfw = isNsfwSource, + ) + } } override suspend fun getAvailableTags(): Set { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mmrcms/ar/Onma.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mmrcms/ar/Onma.kt index 5101e05a..787f2bcb 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mmrcms/ar/Onma.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mmrcms/ar/Onma.kt @@ -2,6 +2,7 @@ package org.koitharu.kotatsu.parsers.site.mmrcms.ar import kotlinx.coroutines.async import kotlinx.coroutines.coroutineScope +import org.jsoup.nodes.Document import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.* @@ -19,83 +20,24 @@ internal class Onma(context: MangaLoaderContext) : override val selectAut = "h3:contains(المؤلف) .text" override val selectTag = "h3:contains(التصنيفات) .text" - override suspend fun getListPage( - page: Int, - query: String?, - tags: Set?, - sortOrder: SortOrder, - ): List { - val tag = tags.oneOrThrowIfMany() - val url = if (sortOrder == SortOrder.UPDATED) { - buildString { - append("https://") - append(domain) - append("/latest-release") - append("?page=") - append(page.toString()) - } - } else { - buildString { - append("https://") - append(domain) - append("/$listUrl/") - append("?page=") - append(page.toString()) - append("&asc=true&author=&tag=") - append("&alpha=") - if (!query.isNullOrEmpty()) { - append(query.urlEncoded()) - } - append("&cat=") - if (!tags.isNullOrEmpty()) { - append(tag?.key.orEmpty()) - } - append("&sortBy=") - when (sortOrder) { - SortOrder.POPULARITY -> append("views") - SortOrder.ALPHABETICAL -> append("name") - else -> append("views") - } - } - } - val doc = webClient.httpGet(url).parseHtml() - if (sortOrder == SortOrder.UPDATED) { - return doc.select("div.manga-item").map { div -> - val href = div.selectFirstOrThrow("a").attrAsRelativeUrl("href") - val deeplink = href.substringAfterLast('/') - Manga( - id = generateUid(href), - url = href, - publicUrl = href.toAbsoluteUrl(div.host ?: domain), - coverUrl = "https://$domain/uploads/manga/$deeplink$imgUpdated", - title = div.selectFirstOrThrow("div.content-left a").text().orEmpty(), - altTitle = null, - rating = RATING_UNKNOWN, - tags = emptySet(), - author = null, - state = null, - source = source, - isNsfw = isNsfwSource, - ) - } - } else { - return doc.select("div.chapter-container").map { div -> - val href = div.selectFirstOrThrow("a").attrAsRelativeUrl("href") - Manga( - id = generateUid(href), - url = href, - publicUrl = href.toAbsoluteUrl(div.host ?: domain), - coverUrl = div.selectFirst("img")?.src().orEmpty(), - title = div.selectFirstOrThrow("h5.media-heading").text().orEmpty(), - altTitle = null, - rating = div.selectFirstOrThrow("span").ownText().toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN, - tags = emptySet(), - author = null, - state = null, - source = source, - isNsfw = isNsfwSource, - ) - } + + override fun parseMangaList(doc: Document): List { + return doc.select("div.chapter-container").map { div -> + val href = div.selectFirstOrThrow("a").attrAsRelativeUrl("href") + Manga( + id = generateUid(href), + url = href, + publicUrl = href.toAbsoluteUrl(div.host ?: domain), + coverUrl = div.selectFirst("img")?.src().orEmpty(), + title = div.selectFirstOrThrow("h5.media-heading").text().orEmpty(), + altTitle = null, + rating = div.selectFirstOrThrow("span").ownText().toFloatOrNull()?.div(5f) ?: RATING_UNKNOWN, + tags = emptySet(), + author = null, + state = null, + source = source, + isNsfw = isNsfwSource, + ) } } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mmrcms/id/Mangaid.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mmrcms/id/Mangaid.kt index dff1955a..f0a0bfa7 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mmrcms/id/Mangaid.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/mmrcms/id/Mangaid.kt @@ -1,18 +1,14 @@ package org.koitharu.kotatsu.parsers.site.mmrcms.id - import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.site.mmrcms.MmrcmsParser import java.util.Locale - @MangaSourceParser("MANGAID", "MangaId", "id") internal class Mangaid(context: MangaLoaderContext) : MmrcmsParser(context, MangaSource.MANGAID, "mangaid.click") { - - override val selectState = "dt:contains(Status)" override val selectAlt = "dt:contains(Other names)" override val selectAut = "dt:contains(Author(s))" diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/nepnep/NepnepParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/nepnep/NepnepParser.kt index 2845daec..f175cbe1 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/nepnep/NepnepParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/nepnep/NepnepParser.kt @@ -24,15 +24,20 @@ internal abstract class NepnepParser( override val configKeyDomain = ConfigKey.Domain(domain) override val availableSortOrders: Set = EnumSet.of(SortOrder.ALPHABETICAL) + override val availableStates: Set = EnumSet.allOf(MangaState::class.java) override val headers: Headers = Headers.Builder() .add("User-Agent", UserAgents.CHROME_DESKTOP) .build() - override suspend fun getList(offset: Int, query: String?, tags: Set?, sortOrder: SortOrder): List { + override suspend fun getList(offset: Int, filter: MangaListFilter?): List { if (offset > 0) { return emptyList() } + + var foundTag = true + var foundState = true + val doc = webClient.httpGet("https://$domain/search/").parseHtml() val json = JSONArray( doc.selectFirstOrThrow("script:containsData(MainFunction)").data() @@ -41,18 +46,18 @@ internal abstract class NepnepParser( .trim() .replace(';', ' '), ) - - val manga = ArrayList(json.length()) + for (i in 0 until json.length()) { val m = json.getJSONObject(i) val href = "/manga/" + m.getString("i") val imgUrl = "https://temp.compsci88.com/cover/" + m.getString("i") + ".jpg" - when { - !query.isNullOrEmpty() -> { - if (m.getString("s").contains(query, ignoreCase = true) || m.getString("al") - .contains(query, ignoreCase = true) + when (filter) { + + is MangaListFilter.Search -> { + if (m.getString("s").contains(filter.query, ignoreCase = true) || m.getString("al") + .contains(filter.query, ignoreCase = true) ) { manga.add( addManga(href, imgUrl, m), @@ -60,29 +65,49 @@ internal abstract class NepnepParser( } } - !tags.isNullOrEmpty() -> { - val a = m.getJSONArray("g").toString() - var found = true - tags.forEach { - if (!a.contains(it.key, ignoreCase = true)) { - found = false + is MangaListFilter.Advanced -> { + + if (filter.tags.isNotEmpty()) { + val tagsJon = m.getJSONArray("g").toString() + filter.tags.forEach { + foundTag = false + if (tagsJon.contains(it.key, ignoreCase = true)) { + foundTag = true + } } } - if (found) { - manga.add( - addManga(href, imgUrl, m), - ) + + if (filter.states.isNotEmpty()) { + val stateJson = m.getString("ps") + filter.states.oneOrThrowIfMany().let { + foundState = false + if (stateJson.contains( + when (it) { + MangaState.ONGOING -> "Ongoing" + MangaState.FINISHED -> "Complete" + MangaState.ABANDONED -> "Cancelled" + MangaState.PAUSED -> "Hiatus" + else -> "" + }, + ignoreCase = true, + ) + ) { + foundState = true + } + } + } + + if (foundTag && foundState) { + manga.add(addManga(href, imgUrl, m)) } } - else -> { + null -> { manga.add( addManga(href, imgUrl, m), ) } } - - } return manga }