Use ContentType instead of Type
This commit is contained in:
@@ -5,7 +5,11 @@ 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_MULTIPLE_CONTENT_RATING_NOT_SUPPORTED =
|
||||
"Multiple Content Rating are not supported by this source"
|
||||
"Multiple Content ratings are not supported by this source"
|
||||
const val FILTER_MULTIPLE_CONTENT_TYPES_NOT_SUPPORTED =
|
||||
"Multiple Content types are not supported by this source"
|
||||
const val FILTER_MULTIPLE_DEMOGRAPHICS_NOT_SUPPORTED =
|
||||
"Multiple Demographics 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 =
|
||||
|
||||
@@ -43,11 +43,11 @@ abstract class MangaParser @InternalParsersApi constructor(
|
||||
get() = emptySet()
|
||||
|
||||
/**
|
||||
* Supported [Type] variants for filtering. May be empty.
|
||||
* Supported [ContentType] variants for filtering. May be empty.
|
||||
*
|
||||
* For better performance use [EnumSet] for more than one item.
|
||||
*/
|
||||
open val availableTypes: Set<Type>
|
||||
open val availableContentTypes: Set<ContentType>
|
||||
get() = emptySet()
|
||||
|
||||
/**
|
||||
@@ -184,8 +184,8 @@ abstract class MangaParser @InternalParsersApi constructor(
|
||||
locale = null,
|
||||
states = emptySet(),
|
||||
contentRating = emptySet(),
|
||||
type = emptySet(),
|
||||
demographic = emptySet(),
|
||||
types = emptySet(),
|
||||
demographics = emptySet(),
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,10 @@ enum class ContentType {
|
||||
*/
|
||||
MANGA,
|
||||
|
||||
MANHWA,
|
||||
|
||||
MANHUA,
|
||||
|
||||
/**
|
||||
* Use this if the source provides mostly nsfw content.
|
||||
*/
|
||||
@@ -17,6 +21,8 @@ enum class ContentType {
|
||||
*/
|
||||
COMICS,
|
||||
|
||||
NOVEL,
|
||||
|
||||
/**
|
||||
* Use this type if no other suits your needs. For example, for an indie manga
|
||||
*/
|
||||
|
||||
@@ -14,9 +14,9 @@ sealed interface MangaListFilter {
|
||||
(tags.size <= 1 || parser.isMultipleTagsSupported) &&
|
||||
(tagsExclude.isEmpty() || parser.isTagsExclusionSupported) &&
|
||||
(contentRating.isEmpty() || parser.availableContentRating.containsAll(contentRating)) &&
|
||||
(states.isEmpty() || parser.availableStates.containsAll(states) &&
|
||||
(type.isEmpty() || parser.availableType.containsAll(type)) &&
|
||||
(demographic.isEmpty() || parser.availableDemographic.containsAll(demographic)))
|
||||
(states.isEmpty() || parser.availableStates.containsAll(states)) &&
|
||||
(types.isEmpty() || parser.availableContentTypes.containsAll(types)) &&
|
||||
(demographics.isEmpty() || parser.availableDemographics.containsAll(demographics))
|
||||
|
||||
is Search -> parser.isSearchSupported
|
||||
}
|
||||
@@ -37,12 +37,12 @@ sealed interface MangaListFilter {
|
||||
@JvmField val locale: Locale?,
|
||||
@JvmField val states: Set<MangaState>,
|
||||
@JvmField val contentRating: Set<ContentRating>,
|
||||
@JvmField val type: Set<Type>,
|
||||
@JvmField val demographic: Set<Demographic>,
|
||||
@JvmField val types: Set<ContentType>,
|
||||
@JvmField val demographics: Set<Demographic>,
|
||||
) : MangaListFilter {
|
||||
|
||||
override fun isEmpty(): Boolean =
|
||||
tags.isEmpty() && tagsExclude.isEmpty() && locale == null && states.isEmpty() && contentRating.isEmpty() && type.isEmpty() && demographic.isEmpty()
|
||||
tags.isEmpty() && tagsExclude.isEmpty() && locale == null && states.isEmpty() && contentRating.isEmpty() && types.isEmpty() && demographics.isEmpty()
|
||||
|
||||
fun newBuilder() = Builder(sortOrder)
|
||||
.tags(tags)
|
||||
@@ -50,8 +50,8 @@ sealed interface MangaListFilter {
|
||||
.locale(locale)
|
||||
.states(states)
|
||||
.contentRatings(contentRating)
|
||||
.type(type)
|
||||
.demographic(demographic)
|
||||
.type(types)
|
||||
.demographic(demographics)
|
||||
|
||||
class Builder(sortOrder: SortOrder) {
|
||||
|
||||
@@ -61,7 +61,7 @@ sealed interface MangaListFilter {
|
||||
private var _locale: Locale? = null
|
||||
private var _states: Set<MangaState>? = null
|
||||
private var _contentRating: Set<ContentRating>? = null
|
||||
private var _type: Set<Type>? = null
|
||||
private var _types: Set<ContentType>? = null
|
||||
private var _demographic: Set<Demographic>? = null
|
||||
|
||||
fun sortOrder(order: SortOrder) = apply {
|
||||
@@ -88,8 +88,8 @@ sealed interface MangaListFilter {
|
||||
_contentRating = rating
|
||||
}
|
||||
|
||||
fun type(type: Set<Type>?) = apply {
|
||||
_type = type
|
||||
fun type(type: Set<ContentType>?) = apply {
|
||||
_types = type
|
||||
}
|
||||
|
||||
fun demographic(demographic: Set<Demographic>?) = apply {
|
||||
@@ -103,8 +103,8 @@ sealed interface MangaListFilter {
|
||||
locale = _locale,
|
||||
states = _states.orEmpty(),
|
||||
contentRating = _contentRating.orEmpty(),
|
||||
type = _type.orEmpty(),
|
||||
demographic = _demographic.orEmpty()
|
||||
types = _types.orEmpty(),
|
||||
demographics = _demographic.orEmpty(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.model
|
||||
|
||||
enum class Type {
|
||||
MANGA,
|
||||
MANHWA,
|
||||
MANHUA,
|
||||
COMIC,
|
||||
NOVEL,
|
||||
OTHERS,
|
||||
}
|
||||
@@ -36,14 +36,14 @@ internal class ComickFunParser(context: MangaLoaderContext) :
|
||||
SortOrder.NEWEST,
|
||||
)
|
||||
|
||||
override val availableType: Set<Type> = EnumSet.of(
|
||||
Type.MANGA,
|
||||
Type.MANHWA,
|
||||
Type.MANHUA,
|
||||
Type.OTHERS,
|
||||
override val availableContentTypes: Set<ContentType> = EnumSet.of(
|
||||
ContentType.MANGA,
|
||||
ContentType.MANHWA,
|
||||
ContentType.MANHUA,
|
||||
ContentType.OTHER,
|
||||
)
|
||||
|
||||
override val availableDemographic: Set<Demographic> = EnumSet.allOf(Demographic::class.java)
|
||||
override val availableDemographics: Set<Demographic> = EnumSet.allOf(Demographic::class.java)
|
||||
|
||||
override val availableStates: Set<MangaState> =
|
||||
EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.PAUSED, MangaState.ABANDONED)
|
||||
@@ -99,20 +99,20 @@ internal class ComickFunParser(context: MangaLoaderContext) :
|
||||
)
|
||||
}
|
||||
|
||||
filter.type.forEach {
|
||||
filter.types.forEach {
|
||||
url.addQueryParameter(
|
||||
"country",
|
||||
when (it) {
|
||||
Type.MANGA -> "jp"
|
||||
Type.MANHWA -> "kr"
|
||||
Type.MANHUA -> "cn"
|
||||
Type.OTHERS -> "others"
|
||||
ContentType.MANGA -> "jp"
|
||||
ContentType.MANHWA -> "kr"
|
||||
ContentType.MANHUA -> "cn"
|
||||
ContentType.OTHER -> "others"
|
||||
else -> ""
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
filter.demographic.forEach {
|
||||
filter.demographics.forEach {
|
||||
url.addQueryParameter(
|
||||
"demographic",
|
||||
when (it) {
|
||||
|
||||
@@ -37,7 +37,7 @@ internal class MangaDexParser(context: MangaLoaderContext) : MangaParser(context
|
||||
|
||||
override val availableContentRating: Set<ContentRating> = EnumSet.allOf(ContentRating::class.java)
|
||||
|
||||
override val availableDemographic: Set<Demographic> = EnumSet.allOf(Demographic::class.java)
|
||||
override val availableDemographics: Set<Demographic> = EnumSet.allOf(Demographic::class.java)
|
||||
|
||||
override val availableStates: Set<MangaState> =
|
||||
EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.PAUSED, MangaState.ABANDONED)
|
||||
@@ -110,7 +110,7 @@ internal class MangaDexParser(context: MangaLoaderContext) : MangaParser(context
|
||||
}
|
||||
}
|
||||
|
||||
filter.demographic.forEach {
|
||||
filter.demographics.forEach {
|
||||
append("&publicationDemographic[]=")
|
||||
append(
|
||||
when (it) {
|
||||
|
||||
@@ -46,8 +46,14 @@ internal abstract class MangaReaderParser(
|
||||
override val availableStates: Set<MangaState>
|
||||
get() = EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.PAUSED)
|
||||
|
||||
override val availableType: Set<Type>
|
||||
get() = EnumSet.of(Type.MANGA, Type.MANHWA, Type.MANHUA, Type.COMIC, Type.NOVEL)
|
||||
override val availableContentTypes: Set<ContentType>
|
||||
get() = EnumSet.of(
|
||||
ContentType.MANGA,
|
||||
ContentType.MANHWA,
|
||||
ContentType.MANHUA,
|
||||
ContentType.COMICS,
|
||||
ContentType.NOVEL,
|
||||
)
|
||||
|
||||
|
||||
override val isTagsExclusionSupported = true
|
||||
@@ -114,15 +120,15 @@ internal abstract class MangaReaderParser(
|
||||
}
|
||||
}
|
||||
|
||||
filter.type.oneOrThrowIfMany()?.let {
|
||||
filter.types.oneOrThrowIfMany()?.let {
|
||||
append("&type=")
|
||||
append(
|
||||
when (it) {
|
||||
Type.MANGA -> "manga"
|
||||
Type.MANHWA -> "manhwa"
|
||||
Type.MANHUA -> "manhua"
|
||||
Type.COMIC -> "comic"
|
||||
Type.NOVEL -> "novel"
|
||||
ContentType.MANGA -> "manga"
|
||||
ContentType.MANHWA -> "manhwa"
|
||||
ContentType.MANHUA -> "manhua"
|
||||
ContentType.COMICS -> "comic"
|
||||
ContentType.NOVEL -> "novel"
|
||||
else -> ""
|
||||
},
|
||||
)
|
||||
@@ -241,18 +247,18 @@ internal abstract class MangaReaderParser(
|
||||
"En cours de publication", "Đang tiến hành", "Em lançamento", "em lançamento", "Em Lançamento", "Онгоінг", "Publishing",
|
||||
"Devam Ediyor", "Em Andamento", "In Corso", "Güncel", "Berjalan", "Продолжается", "Updating", "Lançando", "In Arrivo", "Emision",
|
||||
"En emision", "مستمر", "Curso", "En marcha", "Publicandose", "Publicando", "连载中", "Devam ediyor", "Devam Etmekte",
|
||||
-> MangaState.ONGOING
|
||||
-> MangaState.ONGOING
|
||||
|
||||
"Completed", "Completo", "Complété", "Fini", "Achevé", "Terminé", "Terminé ⚫", "Tamamlandı", "Đã hoàn thành", "Hoàn Thành",
|
||||
"مكتملة", "Завершено", "Finished", "Finalizado", "Completata", "One-Shot", "Bitti", "Tamat", "Completado", "Concluído",
|
||||
"Concluido", "已完结", "Bitmiş",
|
||||
-> MangaState.FINISHED
|
||||
-> MangaState.FINISHED
|
||||
|
||||
"Canceled", "Cancelled", "Cancelado", "cancellato", "Cancelados", "Dropped", "Discontinued", "abandonné", "Abandonné",
|
||||
-> MangaState.ABANDONED
|
||||
-> MangaState.ABANDONED
|
||||
|
||||
"Hiatus", "On Hold", "Pausado", "En espera", "En pause", "En Pause", "En attente",
|
||||
-> MangaState.PAUSED
|
||||
-> MangaState.PAUSED
|
||||
|
||||
else -> null
|
||||
}
|
||||
|
||||
@@ -51,48 +51,34 @@ fun Element.parseFailed(message: String? = null): Nothing {
|
||||
}
|
||||
|
||||
@InternalParsersApi
|
||||
fun Set<MangaTag>?.oneOrThrowIfMany(): MangaTag? {
|
||||
return when {
|
||||
isNullOrEmpty() -> null
|
||||
size == 1 -> first()
|
||||
else -> throw IllegalArgumentException(ErrorMessages.FILTER_MULTIPLE_GENRES_NOT_SUPPORTED)
|
||||
}
|
||||
}
|
||||
fun Set<MangaTag>?.oneOrThrowIfMany(): MangaTag? = oneOrThrowIfMany(
|
||||
ErrorMessages.FILTER_MULTIPLE_GENRES_NOT_SUPPORTED,
|
||||
)
|
||||
|
||||
@InternalParsersApi
|
||||
fun Set<MangaState>?.oneOrThrowIfMany(): MangaState? {
|
||||
return when {
|
||||
isNullOrEmpty() -> null
|
||||
size == 1 -> first()
|
||||
else -> throw IllegalArgumentException(ErrorMessages.FILTER_MULTIPLE_STATES_NOT_SUPPORTED)
|
||||
}
|
||||
}
|
||||
fun Set<MangaState>?.oneOrThrowIfMany(): MangaState? = oneOrThrowIfMany(
|
||||
ErrorMessages.FILTER_MULTIPLE_STATES_NOT_SUPPORTED,
|
||||
)
|
||||
|
||||
@InternalParsersApi
|
||||
fun Set<Type>?.oneOrThrowIfMany(): Type? {
|
||||
return when {
|
||||
isNullOrEmpty() -> null
|
||||
size == 1 -> first()
|
||||
else -> throw IllegalArgumentException(ErrorMessages.FILTER_MULTIPLE_STATES_NOT_SUPPORTED)
|
||||
}
|
||||
}
|
||||
fun Set<ContentType>?.oneOrThrowIfMany(): ContentType? = oneOrThrowIfMany(
|
||||
ErrorMessages.FILTER_MULTIPLE_CONTENT_TYPES_NOT_SUPPORTED,
|
||||
)
|
||||
|
||||
@InternalParsersApi
|
||||
fun Set<Demographic>?.oneOrThrowIfMany(): Demographic? {
|
||||
return when {
|
||||
isNullOrEmpty() -> null
|
||||
size == 1 -> first()
|
||||
else -> throw IllegalArgumentException(ErrorMessages.FILTER_MULTIPLE_STATES_NOT_SUPPORTED)
|
||||
}
|
||||
}
|
||||
fun Set<Demographic>?.oneOrThrowIfMany(): Demographic? = oneOrThrowIfMany(
|
||||
ErrorMessages.FILTER_MULTIPLE_DEMOGRAPHICS_NOT_SUPPORTED,
|
||||
)
|
||||
|
||||
@InternalParsersApi
|
||||
fun Set<ContentRating>?.oneOrThrowIfMany(): ContentRating? {
|
||||
return when {
|
||||
isNullOrEmpty() -> null
|
||||
size == 1 -> first()
|
||||
else -> throw IllegalArgumentException(ErrorMessages.FILTER_MULTIPLE_CONTENT_RATING_NOT_SUPPORTED)
|
||||
}
|
||||
fun Set<ContentRating>?.oneOrThrowIfMany(): ContentRating? = oneOrThrowIfMany(
|
||||
ErrorMessages.FILTER_MULTIPLE_CONTENT_RATING_NOT_SUPPORTED,
|
||||
)
|
||||
|
||||
private fun <T> Set<T>?.oneOrThrowIfMany(msg: String): T? = when {
|
||||
isNullOrEmpty() -> null
|
||||
size == 1 -> first()
|
||||
else -> throw IllegalArgumentException(msg)
|
||||
}
|
||||
|
||||
val MangaParser.domain: String
|
||||
|
||||
@@ -19,7 +19,7 @@ internal class MangaParserTest {
|
||||
|
||||
@ParameterizedTest(name = "{index}|list|{0}")
|
||||
@MangaSources
|
||||
fun list(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
fun list(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
val parser = context.newParserInstance(source)
|
||||
val list = parser.getList(0, null)
|
||||
checkMangaList(list, "list")
|
||||
@@ -28,7 +28,7 @@ internal class MangaParserTest {
|
||||
|
||||
@ParameterizedTest(name = "{index}|pagination|{0}")
|
||||
@MangaSources
|
||||
fun pagination(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
fun pagination(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
val parser = context.newParserInstance(source)
|
||||
val page1 = parser.getList(0, filter = null)
|
||||
val page2 = parser.getList(page1.size, filter = null)
|
||||
@@ -48,7 +48,7 @@ internal class MangaParserTest {
|
||||
|
||||
@ParameterizedTest(name = "{index}|search|{0}")
|
||||
@MangaSources
|
||||
fun search(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
fun search(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
val parser = context.newParserInstance(source)
|
||||
val subject = parser.getList(
|
||||
offset = 0,
|
||||
@@ -59,8 +59,8 @@ internal class MangaParserTest {
|
||||
states = emptySet(),
|
||||
tagsExclude = emptySet(),
|
||||
contentRating = emptySet(),
|
||||
type = emptySet(),
|
||||
demographic = emptySet(),
|
||||
types = emptySet(),
|
||||
demographics = emptySet(),
|
||||
),
|
||||
).minByOrNull {
|
||||
it.title.length
|
||||
@@ -78,7 +78,7 @@ internal class MangaParserTest {
|
||||
|
||||
@ParameterizedTest(name = "{index}|tags|{0}")
|
||||
@MangaSources
|
||||
fun tags(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
fun tags(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
val parser = context.newParserInstance(source)
|
||||
val tags = parser.getAvailableTags()
|
||||
assert(tags.isNotEmpty()) { "No tags found" }
|
||||
@@ -107,7 +107,7 @@ internal class MangaParserTest {
|
||||
|
||||
@ParameterizedTest(name = "{index}|tags_multiple|{0}")
|
||||
@MangaSources
|
||||
fun tagsMultiple(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
fun tagsMultiple(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
val parser = context.newParserInstance(source)
|
||||
if (!parser.isMultipleTagsSupported) return@runTest
|
||||
val tags = parser.getAvailableTags().shuffled().take(2).toSet()
|
||||
@@ -122,7 +122,7 @@ internal class MangaParserTest {
|
||||
|
||||
@ParameterizedTest(name = "{index}|locale|{0}")
|
||||
@MangaSources
|
||||
fun locale(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
fun locale(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
val parser = context.newParserInstance(source)
|
||||
val locales = parser.getAvailableLocales()
|
||||
if (locales.isEmpty()) {
|
||||
@@ -135,8 +135,8 @@ internal class MangaParserTest {
|
||||
locale = locales.random(),
|
||||
states = setOf(),
|
||||
contentRating = setOf(),
|
||||
type = emptySet(),
|
||||
demographic = emptySet(),
|
||||
types = emptySet(),
|
||||
demographics = emptySet(),
|
||||
)
|
||||
val list = parser.getList(offset = 0, filter)
|
||||
checkMangaList(list, filter.locale.toString())
|
||||
@@ -146,7 +146,7 @@ internal class MangaParserTest {
|
||||
|
||||
@ParameterizedTest(name = "{index}|details|{0}")
|
||||
@MangaSources
|
||||
fun details(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
fun details(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
val parser = context.newParserInstance(source)
|
||||
val list = parser.getList(0, null)
|
||||
val manga = list[3]
|
||||
@@ -176,7 +176,7 @@ internal class MangaParserTest {
|
||||
|
||||
@ParameterizedTest(name = "{index}|pages|{0}")
|
||||
@MangaSources
|
||||
fun pages(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
fun pages(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
val parser = context.newParserInstance(source)
|
||||
val list = parser.getList(0, null)
|
||||
val manga = list.first()
|
||||
@@ -200,7 +200,7 @@ internal class MangaParserTest {
|
||||
|
||||
@ParameterizedTest(name = "{index}|favicon|{0}")
|
||||
@MangaSources
|
||||
fun favicon(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
fun favicon(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
val parser = context.newParserInstance(source)
|
||||
val favicons = parser.getFavicons()
|
||||
val types = setOf("png", "svg", "ico", "gif", "jpg", "jpeg")
|
||||
@@ -216,7 +216,7 @@ internal class MangaParserTest {
|
||||
|
||||
@ParameterizedTest(name = "{index}|domain|{0}")
|
||||
@MangaSources
|
||||
fun domain(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
fun domain(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
val parser = context.newParserInstance(source)
|
||||
val defaultDomain = parser.domain
|
||||
val url = HttpUrl.Builder().host(defaultDomain).scheme("https").toString()
|
||||
@@ -232,7 +232,7 @@ internal class MangaParserTest {
|
||||
@ParameterizedTest(name = "{index}|authorization|{0}")
|
||||
@MangaSources
|
||||
@Disabled
|
||||
fun authorization(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
fun authorization(source: MangaParserSource) = runTest(timeout = timeout) {
|
||||
val parser = context.newParserInstance(source)
|
||||
if (parser is MangaParserAuthProvider) {
|
||||
val username = parser.getUsername()
|
||||
|
||||
Reference in New Issue
Block a user