From 3ed960254d02af108d49d0a1865d267094439a20 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Tue, 5 Dec 2023 13:05:11 +0200 Subject: [PATCH] [GalleryAdults] Language filter support #357 --- .../koitharu/kotatsu/parsers/ErrorMessages.kt | 12 +++ .../kotatsu/parsers/site/en/ComicExtra.kt | 4 +- .../kotatsu/parsers/site/es/TempleScanEsp.kt | 4 +- .../kotatsu/parsers/site/fr/FuryoSociety.kt | 4 +- .../kotatsu/parsers/site/fr/LugnicaScans.kt | 4 +- .../site/galleryadults/GalleryAdultsParser.kt | 78 ++++++++-------- .../site/galleryadults/all/AsmHentai.kt | 16 ++-- .../site/galleryadults/all/DoujinDesuUk.kt | 12 ++- .../parsers/site/galleryadults/all/Hentai3.kt | 66 +++++++------ .../site/galleryadults/all/HentaiEnvy.kt | 51 +++++----- .../site/galleryadults/all/HentaiEra.kt | 93 ++++++++----------- .../site/galleryadults/all/HentaiForce.kt | 78 +++++++++------- .../site/galleryadults/all/HentaiFox.kt | 60 ++++++------ .../site/galleryadults/all/HentaiRox.kt | 22 +++-- .../site/galleryadults/all/NHentaiParser.kt | 56 ++++++----- .../site/galleryadults/all/NHentaiUk.kt | 59 +++++++----- .../parsers/site/heancmsalt/HeanCmsAlt.kt | 4 +- .../parsers/site/mangareader/en/RizzComic.kt | 12 +-- .../parsers/site/uk/MangaInUaParser.kt | 5 +- .../kotatsu/parsers/util/MangaParserEnv.kt | 5 +- 20 files changed, 348 insertions(+), 297 deletions(-) create mode 100644 src/main/kotlin/org/koitharu/kotatsu/parsers/ErrorMessages.kt diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/ErrorMessages.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/ErrorMessages.kt new file mode 100644 index 00000000..ade47d3b --- /dev/null +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/ErrorMessages.kt @@ -0,0 +1,12 @@ +package org.koitharu.kotatsu.parsers + +object ErrorMessages { + + const val FILTER_MULTIPLE_STATES_NOT_SUPPORTED = "Multiple states are not supported by this source" + const val FILTER_MULTIPLE_GENRES_NOT_SUPPORTED = "Multiple genres are not supported by this source" + const val FILTER_BOTH_LOCALE_GENRES_NOT_SUPPORTED = + "Filtering by both genres and locale is not supported by this source" + const val FILTER_BOTH_STATES_GENRES_NOT_SUPPORTED = + "Filtering by both genres and states is not supported by this source" + const val SEARCH_NOT_SUPPORTED = "Search is not supported by this source" +} diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/ComicExtra.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/ComicExtra.kt index 042beaef..ab795fd9 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/ComicExtra.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/ComicExtra.kt @@ -1,6 +1,7 @@ package org.koitharu.kotatsu.parsers.site.en import okhttp3.Headers +import org.koitharu.kotatsu.parsers.ErrorMessages import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.PagedMangaParser @@ -8,7 +9,6 @@ import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.network.UserAgents import org.koitharu.kotatsu.parsers.util.* -import java.lang.IllegalArgumentException import java.text.SimpleDateFormat import java.util.* @@ -60,7 +60,7 @@ internal class ComicExtra(context: MangaLoaderContext) : PagedMangaParser(contex } } else if (filter.tags.isNotEmpty() && filter.states.isNotEmpty()) { - throw IllegalArgumentException("Source does not support tag + states filters") + throw IllegalArgumentException(ErrorMessages.FILTER_BOTH_STATES_GENRES_NOT_SUPPORTED) } else { when (filter.sortOrder) { SortOrder.POPULARITY -> append("popular-comic") diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/es/TempleScanEsp.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/es/TempleScanEsp.kt index ec17b58d..47ae240c 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/es/TempleScanEsp.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/es/TempleScanEsp.kt @@ -3,6 +3,7 @@ package org.koitharu.kotatsu.parsers.site.es import kotlinx.coroutines.coroutineScope import okhttp3.Headers import org.jsoup.nodes.Document +import org.koitharu.kotatsu.parsers.ErrorMessages import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.PagedMangaParser @@ -10,7 +11,6 @@ import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.network.UserAgents import org.koitharu.kotatsu.parsers.util.* -import java.lang.IllegalArgumentException import java.util.* @MangaSourceParser("TEMPLESCANESP", "TempleScanEsp", "es", ContentType.HENTAI) @@ -31,7 +31,7 @@ internal class TempleScanEsp(context: MangaLoaderContext) : append(domain) when (filter) { is MangaListFilter.Search -> { - throw IllegalArgumentException("Search is not supported by this source") + throw IllegalArgumentException(ErrorMessages.SEARCH_NOT_SUPPORTED) } is MangaListFilter.Advanced -> { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/fr/FuryoSociety.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/fr/FuryoSociety.kt index 047e2eaa..7fbc5038 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/fr/FuryoSociety.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/fr/FuryoSociety.kt @@ -3,6 +3,7 @@ package org.koitharu.kotatsu.parsers.site.fr import kotlinx.coroutines.coroutineScope import okhttp3.Headers import org.jsoup.nodes.Document +import org.koitharu.kotatsu.parsers.ErrorMessages import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.PagedMangaParser @@ -10,7 +11,6 @@ import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.network.UserAgents import org.koitharu.kotatsu.parsers.util.* -import java.lang.IllegalArgumentException import java.text.DateFormat import java.text.SimpleDateFormat import java.util.* @@ -46,7 +46,7 @@ internal class FuryoSociety(context: MangaLoaderContext) : append(domain) when (filter) { is MangaListFilter.Search -> { - throw IllegalArgumentException("Search is not supported by this source") + throw IllegalArgumentException(ErrorMessages.SEARCH_NOT_SUPPORTED) } is MangaListFilter.Advanced -> { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/fr/LugnicaScans.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/fr/LugnicaScans.kt index 3545a377..0af98d46 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/fr/LugnicaScans.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/fr/LugnicaScans.kt @@ -2,6 +2,7 @@ package org.koitharu.kotatsu.parsers.site.fr import okhttp3.Headers import org.json.JSONArray +import org.koitharu.kotatsu.parsers.ErrorMessages import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.PagedMangaParser @@ -10,7 +11,6 @@ import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.network.UserAgents import org.koitharu.kotatsu.parsers.util.* import org.koitharu.kotatsu.parsers.util.json.mapJSON -import java.lang.IllegalArgumentException import java.text.SimpleDateFormat import java.util.* @@ -49,7 +49,7 @@ internal class LugnicaScans(context: MangaLoaderContext) : PagedMangaParser(cont override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { when (filter) { is MangaListFilter.Search -> { - throw IllegalArgumentException("Search is not supported by this source") + throw IllegalArgumentException(ErrorMessages.SEARCH_NOT_SUPPORTED) } is MangaListFilter.Advanced -> { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/GalleryAdultsParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/GalleryAdultsParser.kt index 5b69fd57..e4b70d0b 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/GalleryAdultsParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/GalleryAdultsParser.kt @@ -6,6 +6,7 @@ import kotlinx.coroutines.awaitAll import kotlinx.coroutines.coroutineScope import org.jsoup.nodes.Document import org.jsoup.nodes.Element +import org.koitharu.kotatsu.parsers.ErrorMessages import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.PagedMangaParser import org.koitharu.kotatsu.parsers.config.ConfigKey @@ -25,7 +26,6 @@ internal abstract class GalleryAdultsParser( override val isMultipleTagsSupported = false override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { - val url = buildString { append("https://") append(domain) @@ -37,18 +37,19 @@ internal abstract class GalleryAdultsParser( } is MangaListFilter.Advanced -> { - if (filter.tags.isNotEmpty()) { - filter.tags.oneOrThrowIfMany()?.let { - if (it.key == "languageKey") { - append("/language") - append(it.title) - append("/?") - } else { - append("/tag/") - append(it.key) - append("/?") - } - } + val tag = filter.tags.oneOrThrowIfMany() + val lang = filter.locale + if (tag != null && lang != null) { + throw IllegalArgumentException(ErrorMessages.FILTER_BOTH_LOCALE_GENRES_NOT_SUPPORTED) + } + if (tag != null) { + append("/tag/") + append(tag.key) + append("/?") + } else if (filter.locale != null) { + append("/language/") + append(filter.locale.toLanguagePath()) + append("/?") } else { append("/?") } @@ -102,39 +103,30 @@ internal abstract class GalleryAdultsParser( }.awaitAll().flattenTo(ArraySet(360)) } + override suspend fun getAvailableLocales(): Set = setOf( + Locale.ENGLISH, + Locale.FRENCH, + Locale.JAPANESE, + Locale.CHINESE, + Locale("es"), + Locale("ru"), + Locale("ko"), + Locale.GERMAN, + Locale("id"), + Locale.ITALIAN, + Locale("pt"), + Locale("tr"), + Locale("th"), + Locale("vi"), + ) + protected open val pathTagUrl = "/tags/popular/?page=" protected open val selectTags = ".tags_page ul.tags li" - protected open val listLanguage = arrayOf( - "/english", - "/french", - "/japanese", - "/chinese", - "/spanish", - "/russian", - "/korean", - "/german", - "/indonesian", - "/italian", - "/portuguese", - "/turkish", - "/thai", - "/vietnamese", - ) // The "/" is used to move them up in the tag list and therefore also in the url. private suspend fun getTags(page: Int): Set { val url = "https://$domain$pathTagUrl$page" val root = webClient.httpGet(url).parseHtml().selectFirstOrThrow(selectTags) - val tagLanguage = ArrayList(listLanguage.size) - for (language in listLanguage) { - tagLanguage.add( - MangaTag( - key = "languageKey", - title = language, - source = source, - ), - ) - } - return root.parseTags() + tagLanguage + return root.parseTags() } protected open fun Element.parseTags() = select("a").mapToSet { @@ -142,7 +134,7 @@ internal abstract class GalleryAdultsParser( val name = it.html().substringBefore("<") MangaTag( key = key, - title = name, + title = name.toTitleCase(), source = source, ) } @@ -204,4 +196,8 @@ internal abstract class GalleryAdultsParser( val doc = webClient.httpGet(page.url.toAbsoluteUrl(domain)).parseHtml() return doc.requireElementById(idImg).src() ?: doc.parseFailed("Image src not found") } + + protected open fun Locale.toLanguagePath() = when (language) { + else -> getDisplayLanguage(Locale.ENGLISH).lowercase() + } } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/AsmHentai.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/AsmHentai.kt index 539fac03..b4e4b771 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/AsmHentai.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/AsmHentai.kt @@ -3,10 +3,13 @@ package org.koitharu.kotatsu.parsers.site.galleryadults.all import org.jsoup.nodes.Element import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser -import org.koitharu.kotatsu.parsers.model.* +import org.koitharu.kotatsu.parsers.model.ContentType +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.site.galleryadults.GalleryAdultsParser import org.koitharu.kotatsu.parsers.util.mapToSet import org.koitharu.kotatsu.parsers.util.removeSuffix +import java.util.* @MangaSourceParser("ASMHENTAI", "AsmHentai", type = ContentType.HENTAI) internal class AsmHentai(context: MangaLoaderContext) : @@ -17,11 +20,12 @@ internal class AsmHentai(context: MangaLoaderContext) : override val pathTagUrl = "/tags/?page=" override val selectAuthor = "div.tags:contains(Artists:) .tag_list a span.tag" override val idImg = "fimg" - override val listLanguage = arrayOf( - "/english", - "/japanese", - "/chinese", - "/turkish", + + override suspend fun getAvailableLocales(): Set = setOf( + Locale.ENGLISH, + Locale.JAPANESE, + Locale.CHINESE, + Locale("tr"), ) override fun Element.parseTags() = select("a").mapToSet { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/DoujinDesuUk.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/DoujinDesuUk.kt index cd406c74..cc06c554 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/DoujinDesuUk.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/DoujinDesuUk.kt @@ -6,10 +6,11 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.site.galleryadults.GalleryAdultsParser import org.koitharu.kotatsu.parsers.util.* +import java.util.* @MangaSourceParser("DOUJINDESUUK", "DoujinDesu.uk", type = ContentType.HENTAI) internal class DoujinDesuUk(context: MangaLoaderContext) : - GalleryAdultsParser(context, MangaSource.DOUJINDESUUK, "doujindesu.uk", 50) { + GalleryAdultsParser(context, MangaSource.DOUJINDESUUK, "doujindesu.uk", 25) { override val selectGallery = ".gallery" override val selectGalleryLink = "a" override val selectGalleryTitle = ".caption" @@ -19,10 +20,11 @@ internal class DoujinDesuUk(context: MangaLoaderContext) : override val selectAuthor = "div.tag-container:contains(Artists) a" override val selectLanguageChapter = "div.tag-container:contains(Languages) a" override val idImg = "image-container" - override val listLanguage = arrayOf( - "/english", - "/japanese", - "/chinese", + + override suspend fun getAvailableLocales(): Set = setOf( + Locale.ENGLISH, + Locale.JAPANESE, + Locale.CHINESE, ) override fun parseMangaList(doc: Document): List { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/Hentai3.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/Hentai3.kt index ed39facf..832a689b 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/Hentai3.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/Hentai3.kt @@ -1,15 +1,16 @@ package org.koitharu.kotatsu.parsers.site.galleryadults.all +import org.jsoup.internal.StringUtil import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.site.galleryadults.GalleryAdultsParser import org.koitharu.kotatsu.parsers.util.* -import java.util.EnumSet +import java.util.* @MangaSourceParser("HENTAI3", "3Hentai", type = ContentType.HENTAI) internal class Hentai3(context: MangaLoaderContext) : - GalleryAdultsParser(context, MangaSource.HENTAI3, "3hentai.net") { + GalleryAdultsParser(context, MangaSource.HENTAI3, "3hentai.net", pageSize = 30) { override val selectGallery = ".doujin " override val selectGalleryLink = "a" @@ -21,20 +22,21 @@ internal class Hentai3(context: MangaLoaderContext) : override val selectLanguageChapter = "div.tag-container:contains(Languages) a" override val selectUrlChapter = "#main-cover a" override val idImg = ".js-main-img" - override val listLanguage = arrayOf( - "/english", - "/spanish", - "/french", - "/italian", - "/portuguese", - "/russian", - "/japanese", - ) override val isMultipleTagsSupported = true override val availableSortOrders: Set = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY) + override suspend fun getAvailableLocales(): Set = setOf( + Locale.ENGLISH, + Locale.FRENCH, + Locale.JAPANESE, + Locale("es"), + Locale("ru"), + Locale.ITALIAN, + Locale("pt"), + ) + override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { val url = buildString { append("https://") @@ -49,24 +51,26 @@ internal class Hentai3(context: MangaLoaderContext) : } is MangaListFilter.Advanced -> { - - if (filter.tags.isNotEmpty() && filter.tags.size > 1) { + if (filter.tags.size > 1 || (filter.tags.isNotEmpty() && filter.locale != null)) { append("/search?q=") - append(buildQuery(filter.tags)) + append(buildQuery(filter.tags, filter.locale)) if (filter.sortOrder == SortOrder.POPULARITY) { append("&sort=popular") } append("&page=") append(page.toString()) + } else if (filter.locale != null) { + append("/language/") + append(filter.locale.toLanguagePath()) + append("/") + append(page.toString()) + if (filter.sortOrder == SortOrder.POPULARITY) { + append("?sort=popular") + } } else if (filter.tags.isNotEmpty()) { filter.tags.oneOrThrowIfMany()?.let { - if (it.key == "languageKey") { - append("/language") - append(it.title) - } else { - append("/tags/") - append(it.key) - } + append("/tags/") + append(it.key) } append("/") append(page.toString()) @@ -93,12 +97,18 @@ internal class Hentai3(context: MangaLoaderContext) : return doc.selectFirstOrThrow(idImg).src() ?: doc.parseFailed("Image src not found") } - private fun buildQuery(tags: Collection) = - tags.joinToString(separator = " ") { tag -> - if (tag.key == "languageKey") { - "language:\"${tag.title.removePrefix("/")}\"" - } else { - "tag:\"${tag.title}\"" - } + private fun buildQuery(tags: Collection, language: Locale?): String { + val joiner = StringUtil.StringJoiner(" ") + tags.forEach { tag -> + joiner.add("tag:\"") + joiner.append(tag.key) + joiner.append("\"") + } + language?.let { lc -> + joiner.add("language:\"") + joiner.append(lc.toLanguagePath()) + joiner.append("\"") } + return joiner.complete() + } } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiEnvy.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiEnvy.kt index 95407f77..ef469c05 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiEnvy.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiEnvy.kt @@ -1,5 +1,6 @@ package org.koitharu.kotatsu.parsers.site.galleryadults.all +import org.koitharu.kotatsu.parsers.ErrorMessages import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.* @@ -8,11 +9,11 @@ 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.* @MangaSourceParser("HENTAIENVY", "HentaiEnvy", type = ContentType.HENTAI) internal class HentaiEnvy(context: MangaLoaderContext) : - GalleryAdultsParser(context, MangaSource.HENTAIENVY, "hentaienvy.com") { + GalleryAdultsParser(context, MangaSource.HENTAIENVY, "hentaienvy.com", pageSize = 24) { override val selectGalleryLink = "a" override val selectGalleryTitle = "div.title" override val selectTags = ".tags_items" @@ -20,17 +21,6 @@ internal class HentaiEnvy(context: MangaLoaderContext) : override val selectAuthor = ".gt_right_tags ul:contains(Artists:) a" override val selectLanguageChapter = ".gt_right_tags ul:contains(Languages:) a" override val idImg = "fimg" - override val listLanguage = arrayOf( - "/english", - "/french", - "/japanese", - "/chinese", - "/spanish", - "/russian", - "/korean", - "/german", - "/portuguese", - ) override val availableSortOrders: Set = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY) @@ -47,20 +37,21 @@ internal class HentaiEnvy(context: MangaLoaderContext) : is MangaListFilter.Advanced -> { if (filter.tags.isNotEmpty()) { + if (filter.locale != null) { + throw IllegalArgumentException(ErrorMessages.FILTER_BOTH_LOCALE_GENRES_NOT_SUPPORTED) + } filter.tags.oneOrThrowIfMany()?.let { - if (it.key == "languageKey") { - append("/language") - append(it.title) - append("/?") - } else { - append("/tag/") - append(it.key) - if (filter.sortOrder == SortOrder.POPULARITY) { - append("/popular") - } - append("/?") + append("/tag/") + append(it.key) + if (filter.sortOrder == SortOrder.POPULARITY) { + append("/popular") } + append("/?") } + } else if (filter.locale != null) { + append("/language/") + append(filter.locale.toLanguagePath()) + append("/?") } else { append("/?") } @@ -74,4 +65,16 @@ internal class HentaiEnvy(context: MangaLoaderContext) : } return parseMangaList(webClient.httpGet(url).parseHtml()) } + + override suspend fun getAvailableLocales(): Set = setOf( + Locale.ENGLISH, + Locale.FRENCH, + Locale.JAPANESE, + Locale.CHINESE, + Locale("es"), + Locale("ru"), + Locale("ko"), + Locale.GERMAN, + Locale("pt"), + ) } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiEra.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiEra.kt index 0b83be26..dccc423c 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiEra.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiEra.kt @@ -6,7 +6,7 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.site.galleryadults.GalleryAdultsParser import org.koitharu.kotatsu.parsers.util.* -import java.util.EnumSet +import java.util.* @MangaSourceParser("HENTAIERA", "HentaiEra", type = ContentType.HENTAI) internal class HentaiEra(context: MangaLoaderContext) : @@ -15,20 +15,22 @@ internal class HentaiEra(context: MangaLoaderContext) : override val selectTag = ".galleries_info li:contains(Tags) div.info_tags" override val selectAuthor = ".galleries_info li:contains(Artists) span.item_name" override val selectLanguageChapter = ".galleries_info li:contains(Languages) div.info_tags .item_name" - override val listLanguage = arrayOf( - "/english", - "/japanese", - "/spanish", - "/french", - "/korean", - "/german", - "/russian", - ) override val availableSortOrders: Set = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY) override val isMultipleTagsSupported = true + + override suspend fun getAvailableLocales(): Set = setOf( + Locale.ENGLISH, + Locale.FRENCH, + Locale.JAPANESE, + Locale("es"), + Locale("ru"), + Locale("ko"), + Locale.GERMAN, + ) + override fun Element.parseTags() = select("a.tag, .gallery_title a").mapToSet { val key = it.attr("href").removeSuffix('/').substringAfterLast('/') val name = it.selectFirst(".item_name")?.text() ?: it.text() @@ -52,24 +54,31 @@ internal class HentaiEra(context: MangaLoaderContext) : } is MangaListFilter.Advanced -> { - if (filter.tags.isNotEmpty() && filter.tags.size > 1) { + if (filter.tags.size > 1 || (filter.tags.isNotEmpty() && filter.locale != null)) { append("/search/?key=") if (filter.sortOrder == SortOrder.POPULARITY) { - append(buildQuery(filter.tags).replace("<=1&dl=0&pp=0&tr=0", "<=0&dl=0&pp=1&tr=0")) + append( + buildQuery(filter.tags, filter.locale) + .replace("<=1&dl=0&pp=0&tr=0", "<=0&dl=0&pp=1&tr=0"), + ) } else { - append(buildQuery(filter.tags)) + append(buildQuery(filter.tags, filter.locale)) } append("&") } else if (filter.tags.isNotEmpty()) { filter.tags.oneOrThrowIfMany()?.let { - if (it.key == "languageKey") { - append("/language") - append(it.title) - } else { - append("/tag/") - append(it.key) - } + append("/tag/") + append(it.key) + } + append("/") + + if (filter.sortOrder == SortOrder.POPULARITY) { + append("popular/") } + append("?") + } else if (filter.locale != null) { + append("/language/") + append(filter.locale.toLanguagePath()) append("/") if (filter.sortOrder == SortOrder.POPULARITY) { @@ -90,40 +99,20 @@ internal class HentaiEra(context: MangaLoaderContext) : return parseMangaList(webClient.httpGet(url).parseHtml()) } - private fun buildQuery(tags: Collection): String { + private fun buildQuery(tags: Collection, locale: Locale?): String { val queryDefault = "&search=&mg=1&dj=1&ws=1&is=1&ac=1&gc=1&en=0&jp=0&es=0&fr=0&kr=0&de=0&ru=0<=1&dl=0&pp=0&tr=0" - var tag = "" - var queryMod = "" - tags.map { - if (it.key == "languageKey" && it.title == "/english") { - queryMod = queryDefault.replace("en=0", "en=1") - } - if (it.key == "languageKey" && it.title == "/japanese") { - queryMod = queryDefault.replace("jp=0", "jp=1") - } - if (it.key == "languageKey" && it.title == "/spanish") { - queryMod = queryDefault.replace("es=0", "es=1") - } - if (it.key == "languageKey" && it.title == "/french") { - queryMod = queryDefault.replace("fr=0", "fr=1") - } - if (it.key == "languageKey" && it.title == "/korean") { - queryMod = queryDefault.replace("kr=0", "kr=1") - } - if (it.key == "languageKey" && it.title == "/russian") { - queryMod = queryDefault.replace("ru=0", "ru=1") - } - if (it.key == "languageKey" && it.title == "/german") { - queryMod = queryDefault.replace("de=0", "de=1") - } - if (it.key != "languageKey") { - tag += it.key + " " - } - } - - if (queryMod.isEmpty()) { - queryMod = "&search=&mg=1&dj=1&ws=1&is=1&ac=1&gc=1&en=1&jp=1&es=1&fr=1&kr=1&de=1&ru=1<=1&dl=0&pp=0&tr=0" + val tag = tags.joinToString(" ", postfix = " ") { it.key } + val queryMod = when (val lp = locale?.toLanguagePath()) { + "english" -> queryDefault.replace("en=0", "en=1") + "japanese" -> queryDefault.replace("jp=0", "jp=1") + "spanish" -> queryDefault.replace("es=0", "es=1") + "french" -> queryDefault.replace("fr=0", "fr=1") + "korean" -> queryDefault.replace("kr=0", "kr=1") + "russian" -> queryDefault.replace("ru=0", "ru=1") + "german" -> queryDefault.replace("de=0", "de=1") + null -> "&search=&mg=1&dj=1&ws=1&is=1&ac=1&gc=1&en=1&jp=1&es=1&fr=1&kr=1&de=1&ru=1<=1&dl=0&pp=0&tr=0" + else -> throw IllegalArgumentException("Unsupported locale: $lp") } return tag + queryMod } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiForce.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiForce.kt index ed97854f..5fec4f3e 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiForce.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiForce.kt @@ -1,15 +1,16 @@ package org.koitharu.kotatsu.parsers.site.galleryadults.all +import org.jsoup.internal.StringUtil import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.site.galleryadults.GalleryAdultsParser import org.koitharu.kotatsu.parsers.util.* -import java.util.EnumSet +import java.util.* @MangaSourceParser("HENTAIFORCE", "HentaiForce", type = ContentType.HENTAI) internal class HentaiForce(context: MangaLoaderContext) : - GalleryAdultsParser(context, MangaSource.HENTAIFORCE, "hentaiforce.net") { + GalleryAdultsParser(context, MangaSource.HENTAIFORCE, "hentaiforce.net", pageSize = 30) { override val selectGallery = ".gallery" override val selectGalleryLink = "a.gallery-thumb" override val pathTagUrl = "/tags/popular/" @@ -19,26 +20,27 @@ internal class HentaiForce(context: MangaLoaderContext) : override val selectAuthor = "div.tag-container:contains(Artists:) a" override val selectLanguageChapter = "div.tag-container:contains(Languages:) a" override val idImg = ".gallery-reader-img-wrapper img" - override val listLanguage = arrayOf( - "/english", - "/french", - "/japanese", - "/chinese", - "/spanish", - "/russian", - "/korean", - "/german", - "/indonesian", - "/italian", - "/portuguese", - "/thai", - "/vietnamese", - ) override val isMultipleTagsSupported = true override val availableSortOrders: Set = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY) + override suspend fun getAvailableLocales(): Set = setOf( + Locale.ENGLISH, + Locale.FRENCH, + Locale.JAPANESE, + Locale.CHINESE, + Locale("es"), + Locale("ru"), + Locale("ko"), + Locale.GERMAN, + Locale("id"), + Locale.ITALIAN, + Locale("pt"), + Locale("th"), + Locale("vi"), + ) + override suspend fun getPageUrl(page: MangaPage): String { val doc = webClient.httpGet(page.url.toAbsoluteUrl(domain)).parseHtml() return doc.selectFirstOrThrow(idImg).src() ?: doc.parseFailed("Image src not found") @@ -56,23 +58,27 @@ internal class HentaiForce(context: MangaLoaderContext) : } is MangaListFilter.Advanced -> { - if (filter.tags.isNotEmpty() && filter.tags.size > 1) { + if (filter.tags.size > 1 || (filter.tags.isNotEmpty() && filter.locale != null)) { append("/search?q=") - append(buildQuery(filter.tags)) + append(buildQuery(filter.tags, filter.locale)) if (filter.sortOrder == SortOrder.POPULARITY) { append("&sort=popular") } append("&page=") } else if (filter.tags.isNotEmpty()) { filter.tags.oneOrThrowIfMany()?.let { - if (it.key == "languageKey") { - append("/language") - append(it.title) - } else { - append("/tag/") - append(it.key) - } + append("/tag/") + append(it.key) + } + append("/") + + if (filter.sortOrder == SortOrder.POPULARITY) { + append("popular/") } + append("?") + } else if (filter.locale != null) { + append("/language/") + append(filter.locale.toLanguagePath()) append("/") if (filter.sortOrder == SortOrder.POPULARITY) { @@ -92,12 +98,18 @@ internal class HentaiForce(context: MangaLoaderContext) : return parseMangaList(webClient.httpGet(url).parseHtml()) } - private fun buildQuery(tags: Collection) = - tags.joinToString(separator = " ") { tag -> - if (tag.key == "languageKey") { - "language:${tag.title.removePrefix("/")}" - } else { - "tag:${tag.title}" - } + private fun buildQuery(tags: Collection, language: Locale?): String { + val joiner = StringUtil.StringJoiner(" ") + tags.forEach { tag -> + joiner.add("tag:\"") + joiner.append(tag.key) + joiner.append("\"") + } + language?.let { lc -> + joiner.add("language:\"") + joiner.append(lc.toLanguagePath()) + joiner.append("\"") } + return joiner.complete() + } } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiFox.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiFox.kt index 02c108c0..45972561 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiFox.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiFox.kt @@ -1,12 +1,13 @@ package org.koitharu.kotatsu.parsers.site.galleryadults.all +import org.jsoup.internal.StringUtil import org.jsoup.nodes.Element import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.site.galleryadults.GalleryAdultsParser import org.koitharu.kotatsu.parsers.util.* -import java.util.EnumSet +import java.util.* @MangaSourceParser("HENTAIFOX", "HentaiFox", type = ContentType.HENTAI) internal class HentaiFox(context: MangaLoaderContext) : @@ -16,21 +17,6 @@ internal class HentaiFox(context: MangaLoaderContext) : override val selectTags = ".list_tags" override val selectTag = "ul.tags" override val selectLanguageChapter = "ul.languages a.tag_btn" - override val listLanguage = arrayOf( - "/english", - "/french", - "/japanese", - "/chinese", - "/spanish", - "/russian", - "/korean", - "/indonesian", - "/italian", - "/portuguese", - "/turkish", - "/thai", - "/vietnamese", - ) override val isMultipleTagsSupported = true @@ -51,9 +37,9 @@ internal class HentaiFox(context: MangaLoaderContext) : } is MangaListFilter.Advanced -> { - if (filter.tags.isNotEmpty() && filter.tags.size > 1) { + if (filter.tags.size > 1 || (filter.tags.isNotEmpty() && filter.locale != null)) { append("/search/?q=") - append(buildQuery(filter.tags)) + append(buildQuery(filter.tags, filter.locale)) if (page > 1) { append("&page=") append(page.toString()) @@ -64,19 +50,27 @@ internal class HentaiFox(context: MangaLoaderContext) : } } else if (filter.tags.isNotEmpty()) { filter.tags.oneOrThrowIfMany()?.let { - if (it.key == "languageKey") { - append("/language") - append(it.title) - } else { - append("/tag/") - append(it.key) - } + append("/tag/") + append(it.key) } append("/") if (filter.sortOrder == SortOrder.POPULARITY) { append("popular/") } + if (page > 1) { + append("/pag/") + append(page.toString()) + append("/") + } + } else if (filter.locale != null) { + append("/language/") + append(filter.locale.toLanguagePath()) + append("/") + if (filter.sortOrder == SortOrder.POPULARITY) { + append("popular/") + } + if (page > 1) { append("/pag/") append(page.toString()) @@ -122,12 +116,14 @@ internal class HentaiFox(context: MangaLoaderContext) : ) } - private fun buildQuery(tags: Collection) = - tags.joinToString(separator = " ") { tag -> - if (tag.key == "languageKey") { - tag.title.removePrefix("/") - } else { - tag.key - } + private fun buildQuery(tags: Collection, language: Locale?): String { + val joiner = StringUtil.StringJoiner(" ") + tags.forEach { tag -> + joiner.add(tag.key) + } + language?.let { lc -> + joiner.add(lc.toLanguagePath()) } + return joiner.complete() + } } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiRox.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiRox.kt index fe510247..16d5864a 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiRox.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/HentaiRox.kt @@ -3,10 +3,13 @@ package org.koitharu.kotatsu.parsers.site.galleryadults.all import org.jsoup.nodes.Element import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser -import org.koitharu.kotatsu.parsers.model.* +import org.koitharu.kotatsu.parsers.model.ContentType +import org.koitharu.kotatsu.parsers.model.MangaSource +import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.site.galleryadults.GalleryAdultsParser import org.koitharu.kotatsu.parsers.util.mapToSet import org.koitharu.kotatsu.parsers.util.removeSuffix +import java.util.* @MangaSourceParser("HENTAIROX", "HentaiRox", type = ContentType.HENTAI) internal class HentaiRox(context: MangaLoaderContext) : @@ -16,14 +19,15 @@ internal class HentaiRox(context: MangaLoaderContext) : override val selectTag = "li:contains(Tags:)" override val selectAuthor = "li:contains(Artists:) span.item_name" override val selectLanguageChapter = "li:contains(Languages:) .item_name" - override val listLanguage = arrayOf( - "/english", - "/french", - "/japanese", - "/spanish", - "/russian", - "/korean", - "/german", + + override suspend fun getAvailableLocales(): Set = setOf( + Locale.ENGLISH, + Locale.FRENCH, + Locale.JAPANESE, + Locale("es"), + Locale("ru"), + Locale("ko"), + Locale.GERMAN, ) override fun Element.parseTags() = select("a.tag, .gallery_title a").mapToSet { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/NHentaiParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/NHentaiParser.kt index c7ecb9ab..c56e9145 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/NHentaiParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/NHentaiParser.kt @@ -1,12 +1,13 @@ package org.koitharu.kotatsu.parsers.site.galleryadults.all +import org.jsoup.internal.StringUtil import org.jsoup.nodes.Element import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.site.galleryadults.GalleryAdultsParser import org.koitharu.kotatsu.parsers.util.* -import java.util.EnumSet +import java.util.* @MangaSourceParser("NHENTAI", "NHentai.net", type = ContentType.HENTAI) internal class NHentaiParser(context: MangaLoaderContext) : @@ -21,11 +22,6 @@ internal class NHentaiParser(context: MangaLoaderContext) : override val selectLanguageChapter = ".tag-container:contains(Languages:) span.tags a:not(.tag-17249) span.name" // tag-17249 = translated override val idImg = "image-container" - override val listLanguage = arrayOf( - "/english", - "/japanese", - "/chinese", - ) override val availableSortOrders: Set = EnumSet.of(SortOrder.UPDATED, SortOrder.POPULARITY) @@ -45,23 +41,27 @@ internal class NHentaiParser(context: MangaLoaderContext) : } is MangaListFilter.Advanced -> { - if (filter.tags.isNotEmpty() && filter.tags.size > 1) { + if (filter.tags.size > 1 || (filter.tags.isNotEmpty() && filter.locale != null)) { append("/search/?q=") - append(buildQuery(filter.tags)) + append(buildQuery(filter.tags, filter.locale).urlEncoded()) if (filter.sortOrder == SortOrder.POPULARITY) { append("&sort=popular") } append("&") } else if (filter.tags.isNotEmpty()) { filter.tags.oneOrThrowIfMany()?.let { - if (it.key == "languageKey") { - append("/language") - append(it.title) - } else { - append("/tag/") - append(it.key) - } + append("/tag/") + append(it.key) + } + append("/") + if (filter.sortOrder == SortOrder.POPULARITY) { + append("popular/") } + + append("?") + } else if (filter.locale != null) { + append("/language/") + append(filter.locale.toLanguagePath()) append("/") if (filter.sortOrder == SortOrder.POPULARITY) { append("popular/") @@ -101,12 +101,24 @@ internal class NHentaiParser(context: MangaLoaderContext) : ) } - private fun buildQuery(tags: Collection) = - tags.joinToString(separator = " ") { tag -> - if (tag.key == "languageKey") { - "language:\"${tag.title.removePrefix("/")}\"" - } else { - "tag:\"${tag.key}\"" - } + override suspend fun getAvailableLocales(): Set = setOf( + Locale.ENGLISH, + Locale.JAPANESE, + Locale.CHINESE, + ) + + private fun buildQuery(tags: Collection, language: Locale?): String { + val joiner = StringUtil.StringJoiner(" ") + tags.forEach { tag -> + joiner.add("tag:\"") + joiner.append(tag.key) + joiner.append("\"") + } + language?.let { lc -> + joiner.add("language:\"") + joiner.append(lc.toLanguagePath()) + joiner.append("\"") } + return joiner.complete() + } } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/NHentaiUk.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/NHentaiUk.kt index cc434d16..643eeec7 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/NHentaiUk.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/galleryadults/all/NHentaiUk.kt @@ -1,15 +1,16 @@ package org.koitharu.kotatsu.parsers.site.galleryadults.all +import org.koitharu.kotatsu.parsers.ErrorMessages import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.site.galleryadults.GalleryAdultsParser import org.koitharu.kotatsu.parsers.util.* -import java.lang.IllegalArgumentException +import java.util.* @MangaSourceParser("NHENTAIUK", "NHentai.uk", type = ContentType.HENTAI) internal class NHentaiUk(context: MangaLoaderContext) : - GalleryAdultsParser(context, MangaSource.NHENTAIUK, "nhentai.uk", 50) { + GalleryAdultsParser(context, MangaSource.NHENTAIUK, "nhentai.uk", pageSize = 50) { override val selectGallery = ".gallery" override val selectGalleryLink = "a" override val selectGalleryTitle = ".caption" @@ -19,18 +20,19 @@ internal class NHentaiUk(context: MangaLoaderContext) : override val selectAuthor = "div.tag-container:contains(Artists:) a" override val selectLanguageChapter = "div.tag-container:contains(Languages:) a" override val idImg = "image-container" - override val listLanguage = arrayOf( - "/english", - "/french", - "/japanese", - "/chinese", - "/spanish", - "/russian", - "/korean", - "/german", - "/italian", - "/portuguese", - "/turkish", + + override suspend fun getAvailableLocales(): Set = setOf( + Locale.ENGLISH, + Locale.FRENCH, + Locale.JAPANESE, + Locale.CHINESE, + Locale("es"), + Locale("ru"), + Locale("ko"), + Locale.GERMAN, + Locale("pt"), + Locale.ITALIAN, + Locale("tr"), ) override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { @@ -41,23 +43,32 @@ internal class NHentaiUk(context: MangaLoaderContext) : when (filter) { is MangaListFilter.Search -> { - throw IllegalArgumentException("Search is not supported by this source") + throw IllegalArgumentException(ErrorMessages.SEARCH_NOT_SUPPORTED) } is MangaListFilter.Advanced -> { - if (filter.tags.isNotEmpty()) { - filter.tags.oneOrThrowIfMany()?.let { - if (it.key == "languageKey") { - append("/language") - append(it.title) - } else { + when { + filter.locale != null && filter.tags.isNotEmpty() -> { + throw IllegalArgumentException(ErrorMessages.FILTER_BOTH_LOCALE_GENRES_NOT_SUPPORTED) + } + + filter.locale != null -> { + append("/language") + append(filter.locale.toLanguagePath()) + append("/?p=") + } + + filter.tags.isNotEmpty() -> { + filter.tags.oneOrThrowIfMany()?.let { append("/tag/") append(it.key) } + append("/?p=") + } + + else -> { + append("/home?p=") } - append("/?p=") - } else { - append("/home?p=") } } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/heancmsalt/HeanCmsAlt.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/heancmsalt/HeanCmsAlt.kt index 588e23f3..d3f86602 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/heancmsalt/HeanCmsAlt.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/heancmsalt/HeanCmsAlt.kt @@ -1,11 +1,11 @@ package org.koitharu.kotatsu.parsers.site.heancmsalt +import org.koitharu.kotatsu.parsers.ErrorMessages import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.PagedMangaParser import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.util.* -import java.lang.IllegalArgumentException import java.text.DateFormat import java.text.SimpleDateFormat import java.util.* @@ -41,7 +41,7 @@ internal abstract class HeanCmsAlt( append(listUrl) when (filter) { is MangaListFilter.Search -> { - throw IllegalArgumentException("Search is not supported by this source") + throw IllegalArgumentException(ErrorMessages.SEARCH_NOT_SUPPORTED) } is MangaListFilter.Advanced -> { 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 48ffe06c..ce364b48 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 @@ -1,18 +1,14 @@ package org.koitharu.kotatsu.parsers.site.mangareader.en +import org.koitharu.kotatsu.parsers.ErrorMessages 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.MangaState -import org.koitharu.kotatsu.parsers.model.SortOrder +import org.koitharu.kotatsu.parsers.model.* 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 java.lang.IllegalArgumentException -import java.util.EnumSet +import java.util.* @MangaSourceParser("RIZZCOMIC", "RizzComic", "en") internal class RizzComic(context: MangaLoaderContext) : @@ -35,7 +31,7 @@ internal class RizzComic(context: MangaLoaderContext) : when (filter) { is MangaListFilter.Search -> { - throw IllegalArgumentException("Search is not supported by this source") + throw IllegalArgumentException(ErrorMessages.SEARCH_NOT_SUPPORTED) } is MangaListFilter.Advanced -> { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/uk/MangaInUaParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/uk/MangaInUaParser.kt index 29b21668..f169fe26 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/uk/MangaInUaParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/uk/MangaInUaParser.kt @@ -1,5 +1,6 @@ package org.koitharu.kotatsu.parsers.site.uk +import org.koitharu.kotatsu.parsers.ErrorMessages import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.PagedMangaParser @@ -23,6 +24,8 @@ class MangaInUaParser(context: MangaLoaderContext) : PagedMangaParser( override val configKeyDomain: ConfigKey.Domain = ConfigKey.Domain("manga.in.ua") + override val isMultipleTagsSupported: Boolean = false + private val userHashRegex by lazy { Regex("site_login_hash\\s*=\\s*\'([^\']+)\'", RegexOption.IGNORE_CASE) } @@ -40,7 +43,7 @@ class MangaInUaParser(context: MangaLoaderContext) : PagedMangaParser( tags.isNullOrEmpty() -> "/mangas/page/$page".toAbsoluteUrl(domain) tags.size == 1 -> "${tags.first().key}/page/$page" - tags.size > 1 -> throw IllegalArgumentException("This source supports only 1 genre") + tags.size > 1 -> throw IllegalArgumentException(ErrorMessages.FILTER_MULTIPLE_GENRES_NOT_SUPPORTED) else -> "/mangas/page/$page".toAbsoluteUrl(domain) } val doc = webClient.httpGet(url).parseHtml() diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/MangaParserEnv.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/MangaParserEnv.kt index 95dc2954..8d2045b6 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/MangaParserEnv.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/MangaParserEnv.kt @@ -2,6 +2,7 @@ package org.koitharu.kotatsu.parsers.util import okhttp3.HttpUrl import org.jsoup.nodes.Element +import org.koitharu.kotatsu.parsers.ErrorMessages import org.koitharu.kotatsu.parsers.InternalParsersApi import org.koitharu.kotatsu.parsers.MangaParser import org.koitharu.kotatsu.parsers.exception.ParseException @@ -54,7 +55,7 @@ fun Set?.oneOrThrowIfMany(): MangaTag? { return when { isNullOrEmpty() -> null size == 1 -> first() - else -> throw IllegalArgumentException("Multiple genres are not supported by this source") + else -> throw IllegalArgumentException(ErrorMessages.FILTER_MULTIPLE_GENRES_NOT_SUPPORTED) } } @@ -63,7 +64,7 @@ fun Set?.oneOrThrowIfMany(): MangaState? { return when { isNullOrEmpty() -> null size == 1 -> first() - else -> throw IllegalArgumentException("Multiple states are not supported by this source") + else -> throw IllegalArgumentException(ErrorMessages.FILTER_MULTIPLE_STATES_NOT_SUPPORTED) } }