diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/MangaParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/MangaParser.kt index b608fe75..8de5048c 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/MangaParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/MangaParser.kt @@ -47,6 +47,11 @@ abstract class MangaParser @InternalParsersApi constructor( */ open val isTagsExclusionSupported: Boolean = false + /** + * Whether parser supports searching by string query using [MangaListFilter.Search] + */ + open val isSearchSupported: Boolean = true + @Deprecated( message = "Use availableSortOrders instead", replaceWith = ReplaceWith("availableSortOrders"), @@ -149,21 +154,42 @@ abstract class MangaParser @InternalParsersApi constructor( return getList( offset, MangaListFilter.Advanced( - sortOrder ?: defaultSortOrder, - tags.orEmpty(), - tagsExclude.orEmpty(), - null, - emptySet(), - emptySet(), + sortOrder = sortOrder ?: defaultSortOrder, + tags = tags.orEmpty(), + tagsExclude = tagsExclude.orEmpty(), + locale = null, + states = emptySet(), + contentRating = emptySet(), ), ) } + @Suppress("DEPRECATION") open suspend fun getList(offset: Int, filter: MangaListFilter?): List { return when (filter) { - is MangaListFilter.Advanced -> getList(offset, null, filter.tags, filter.tagsExclude, filter.sortOrder) - is MangaListFilter.Search -> getList(offset, filter.query, null, null, defaultSortOrder) - null -> getList(offset, null, null, null, defaultSortOrder) + is MangaListFilter.Advanced -> getList( + offset = offset, + query = null, + tags = filter.tags, + tagsExclude = filter.tagsExclude, + sortOrder = filter.sortOrder, + ) + + is MangaListFilter.Search -> getList( + offset = offset, + query = filter.query, + tags = null, + tagsExclude = null, + sortOrder = defaultSortOrder, + ) + + null -> getList( + offset = offset, + query = null, + tags = null, + tagsExclude = null, + sortOrder = defaultSortOrder, + ) } } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/PagedMangaParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/PagedMangaParser.kt index 1017b88e..6d638a2a 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/PagedMangaParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/PagedMangaParser.kt @@ -50,9 +50,29 @@ abstract class PagedMangaParser( open suspend fun getListPage(page: Int, filter: MangaListFilter?): List { return when (filter) { - is MangaListFilter.Advanced -> getListPage(page, null, filter.tags, filter.tagsExclude, filter.sortOrder) - is MangaListFilter.Search -> getListPage(page, filter.query, null, null, defaultSortOrder) - null -> getListPage(page, null, null, null, defaultSortOrder) + is MangaListFilter.Advanced -> getListPage( + page = page, + query = null, + tags = filter.tags, + tagsExclude = filter.tagsExclude, + sortOrder = filter.sortOrder, + ) + + is MangaListFilter.Search -> getListPage( + page = page, + query = filter.query, + tags = null, + tagsExclude = null, + sortOrder = defaultSortOrder, + ) + + null -> getListPage( + page = page, + query = null, + tags = null, + tagsExclude = null, + sortOrder = defaultSortOrder, + ) } } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/model/MangaListFilter.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/model/MangaListFilter.kt index 9688801b..2abe61f6 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/model/MangaListFilter.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/model/MangaListFilter.kt @@ -1,5 +1,6 @@ package org.koitharu.kotatsu.parsers.model +import org.koitharu.kotatsu.parsers.MangaParser import java.util.* sealed interface MangaListFilter { @@ -8,6 +9,16 @@ sealed interface MangaListFilter { val sortOrder: SortOrder? + fun isValid(parser: MangaParser): Boolean = when (this) { + is Advanced -> (sortOrder in parser.availableSortOrders) && + (tags.size <= 1 || parser.isMultipleTagsSupported) && + (tagsExclude.isEmpty() || parser.isTagsExclusionSupported) && + (contentRating.isEmpty() || parser.availableContentRating.containsAll(contentRating)) && + (states.isEmpty() || parser.availableStates.containsAll(states)) + + is Search -> parser.isSearchSupported + } + data class Search( @JvmField val query: String, ) : MangaListFilter { @@ -26,6 +37,57 @@ sealed interface MangaListFilter { @JvmField val contentRating: Set, ) : MangaListFilter { - override fun isEmpty(): Boolean = tags.isEmpty() && tagsExclude.isEmpty() && locale == null && states.isEmpty() && contentRating.isEmpty() + override fun isEmpty(): Boolean = + tags.isEmpty() && tagsExclude.isEmpty() && locale == null && states.isEmpty() && contentRating.isEmpty() + + fun newBuilder() = Builder(sortOrder) + .tags(tags) + .tagsExclude(tagsExclude) + .locale(locale) + .states(states) + .contentRatings(contentRating) + + class Builder(sortOrder: SortOrder) { + + private var _sortOrder: SortOrder = sortOrder + private var _tags: Set? = null + private var _tagsExclude: Set? = null + private var _locale: Locale? = null + private var _states: Set? = null + private var _contentRating: Set? = null + + fun sortOrder(order: SortOrder) = apply { + _sortOrder = order + } + + fun tags(tags: Set?) = apply { + _tags = tags + } + + fun tagsExclude(tags: Set?) = apply { + _tagsExclude = tags + } + + fun locale(locale: Locale?) = apply { + _locale = locale + } + + fun states(states: Set?) = apply { + _states = states + } + + fun contentRatings(rating: Set?) = apply { + _contentRating = rating + } + + fun build() = Advanced( + sortOrder = _sortOrder, + tags = _tags.orEmpty(), + tagsExclude = _tagsExclude.orEmpty(), + locale = _locale, + states = _states.orEmpty(), + contentRating = _contentRating.orEmpty(), + ) + } } } diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/NineNineNineHentaiParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/NineNineNineHentaiParser.kt index 8145040e..c985e8f9 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/NineNineNineHentaiParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/NineNineNineHentaiParser.kt @@ -9,30 +9,14 @@ import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.PagedMangaParser import org.koitharu.kotatsu.parsers.config.ConfigKey -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.MangaListFilter -import org.koitharu.kotatsu.parsers.model.MangaPage -import org.koitharu.kotatsu.parsers.model.MangaSource -import org.koitharu.kotatsu.parsers.model.MangaTag -import org.koitharu.kotatsu.parsers.model.RATING_UNKNOWN -import org.koitharu.kotatsu.parsers.model.SortOrder -import org.koitharu.kotatsu.parsers.util.SuspendLazy -import org.koitharu.kotatsu.parsers.util.domain -import org.koitharu.kotatsu.parsers.util.generateUid +import org.koitharu.kotatsu.parsers.model.* +import org.koitharu.kotatsu.parsers.util.* import org.koitharu.kotatsu.parsers.util.json.getStringOrNull import org.koitharu.kotatsu.parsers.util.json.mapJSON import org.koitharu.kotatsu.parsers.util.json.mapJSONToSet import org.koitharu.kotatsu.parsers.util.json.toJSONList -import org.koitharu.kotatsu.parsers.util.mapToSet -import org.koitharu.kotatsu.parsers.util.oneOrThrowIfMany -import org.koitharu.kotatsu.parsers.util.parseHtml -import org.koitharu.kotatsu.parsers.util.toAbsoluteUrl -import org.koitharu.kotatsu.parsers.util.toCamelCase import java.text.SimpleDateFormat -import java.util.EnumSet -import java.util.Locale +import java.util.* @MangaSourceParser("NINENINENINEHENTAI", "999Hentai", type = ContentType.HENTAI) internal class NineNineNineHentaiParser(context: MangaLoaderContext) : diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/FlixScansOrg.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/FlixScansOrg.kt index f8b42850..40da667a 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/FlixScansOrg.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/FlixScansOrg.kt @@ -19,6 +19,7 @@ internal class FlixScansOrg(context: MangaLoaderContext) : PagedMangaParser(cont override val availableSortOrders: Set = EnumSet.of(SortOrder.UPDATED) override val availableStates: Set = EnumSet.allOf(MangaState::class.java) override val configKeyDomain = ConfigKey.Domain("flixscans.org") + override val isSearchSupported = false override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/ReaperComics.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/ReaperComics.kt index cdc972bd..73b7e760 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/ReaperComics.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/en/ReaperComics.kt @@ -22,6 +22,8 @@ internal class ReaperComics(context: MangaLoaderContext) : override val configKeyDomain = ConfigKey.Domain("reaperscans.com") + override val isSearchSupported = false + override val headers: Headers = Headers.Builder() .add("User-Agent", UserAgents.CHROME_DESKTOP) .build() 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 47ae240c..d7478d2e 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 @@ -21,6 +21,8 @@ internal class TempleScanEsp(context: MangaLoaderContext) : override val configKeyDomain = ConfigKey.Domain("templescanesp.net") + override val isSearchSupported = false + override val headers: Headers = Headers.Builder() .add("User-Agent", UserAgents.CHROME_DESKTOP) .build() 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 7fbc5038..910add0e 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 @@ -23,6 +23,8 @@ internal class FuryoSociety(context: MangaLoaderContext) : override val configKeyDomain = ConfigKey.Domain("furyosociety.com") + override val isSearchSupported = false + override val headers: Headers = Headers.Builder() .add("User-Agent", UserAgents.CHROME_DESKTOP) .build() 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 a2553816..ee92fe93 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 @@ -25,6 +25,8 @@ internal class LugnicaScans(context: MangaLoaderContext) : PagedMangaParser(cont override val availableStates: Set = EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.PAUSED, MangaState.ABANDONED) + override val isSearchSupported = false + override val configKeyDomain = ConfigKey.Domain("lugnica-scans.com") override val headers: Headers = Headers.Builder() 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 ecd00892..89dace41 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 @@ -23,6 +23,8 @@ internal abstract class HeanCmsAlt( override val availableSortOrders: Set = EnumSet.of(SortOrder.UPDATED) + override val isSearchSupported = false + protected open val listUrl = "/comics" protected open val datePattern = "MMMM d, yyyy" 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 ce364b48..3c675e90 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 @@ -19,6 +19,7 @@ internal class RizzComic(context: MangaLoaderContext) : override val availableSortOrders: Set = EnumSet.of(SortOrder.ALPHABETICAL) override val availableStates: Set = emptySet() override val isMultipleTagsSupported = false + override val isSearchSupported = false // TODO Query created in json override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/pt/LerManga.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/pt/LerManga.kt index 21011b81..cd5dc7cb 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/pt/LerManga.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/pt/LerManga.kt @@ -25,6 +25,7 @@ class LerManga(context: MangaLoaderContext) : PagedMangaParser(context, MangaSou override val configKeyDomain = ConfigKey.Domain("lermanga.org") override val isMultipleTagsSupported = false + override val isSearchSupported = false override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/scan/ScanParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/scan/ScanParser.kt index 915825a4..6142f05a 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/scan/ScanParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/scan/ScanParser.kt @@ -21,7 +21,7 @@ internal abstract class ScanParser( override val availableSortOrders: Set = EnumSet.of(SortOrder.ALPHABETICAL, SortOrder.UPDATED, SortOrder.POPULARITY, SortOrder.RATING) - + override val isSearchSupported = false override val configKeyDomain = ConfigKey.Domain(domain) override suspend fun getListPage(page: Int, filter: MangaListFilter?): List {