|
|
|
@ -31,6 +31,24 @@ internal abstract class FuzzyDoodleParser(
|
|
|
|
|
|
|
|
|
|
|
|
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.NEWEST)
|
|
|
|
override val availableSortOrders: Set<SortOrder> = EnumSet.of(SortOrder.NEWEST)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
override val filterCapabilities: MangaListFilterCapabilities
|
|
|
|
|
|
|
|
get() = MangaListFilterCapabilities(
|
|
|
|
|
|
|
|
isMultipleTagsSupported = true,
|
|
|
|
|
|
|
|
isSearchSupported = true,
|
|
|
|
|
|
|
|
isSearchWithFiltersSupported = true,
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
override suspend fun getFilterOptions() = MangaListFilterOptions(
|
|
|
|
|
|
|
|
availableTags = fetchAvailableTags(),
|
|
|
|
|
|
|
|
availableStates = EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.PAUSED, MangaState.ABANDONED),
|
|
|
|
|
|
|
|
availableContentTypes = EnumSet.of(
|
|
|
|
|
|
|
|
ContentType.MANGA,
|
|
|
|
|
|
|
|
ContentType.MANHWA,
|
|
|
|
|
|
|
|
ContentType.MANHUA,
|
|
|
|
|
|
|
|
ContentType.COMICS,
|
|
|
|
|
|
|
|
),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
@JvmField
|
|
|
|
@JvmField
|
|
|
|
protected val ongoing = scatterSetOf(
|
|
|
|
protected val ongoing = scatterSetOf(
|
|
|
|
"en cours",
|
|
|
|
"en cours",
|
|
|
|
@ -67,54 +85,53 @@ internal abstract class FuzzyDoodleParser(
|
|
|
|
protected open val pausedValue = "haitus"
|
|
|
|
protected open val pausedValue = "haitus"
|
|
|
|
protected open val abandonedValue = "dropped"
|
|
|
|
protected open val abandonedValue = "dropped"
|
|
|
|
|
|
|
|
|
|
|
|
override val filterCapabilities: MangaListFilterCapabilities
|
|
|
|
protected open val mangaValue = "manga"
|
|
|
|
get() = MangaListFilterCapabilities(
|
|
|
|
protected open val manhwaValue = "manhwa"
|
|
|
|
isMultipleTagsSupported = true,
|
|
|
|
protected open val manhuaValue = "manhua"
|
|
|
|
isSearchSupported = true,
|
|
|
|
protected open val comicsValue = "bande-dessinee"
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
override suspend fun getFilterOptions() = MangaListFilterOptions(
|
|
|
|
|
|
|
|
availableTags = fetchAvailableTags(),
|
|
|
|
|
|
|
|
availableStates = EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.PAUSED, MangaState.ABANDONED),
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
override suspend fun getListPage(page: Int, order: SortOrder, filter: MangaListFilter): List<Manga> {
|
|
|
|
override suspend fun getListPage(page: Int, order: SortOrder, filter: MangaListFilter): List<Manga> {
|
|
|
|
val url = buildString {
|
|
|
|
val url = buildString {
|
|
|
|
append("https://")
|
|
|
|
append("https://")
|
|
|
|
append(domain)
|
|
|
|
append(domain)
|
|
|
|
append("/manga?page=")
|
|
|
|
append("/manga?page=")
|
|
|
|
append(page)
|
|
|
|
append(page.toString())
|
|
|
|
|
|
|
|
|
|
|
|
when {
|
|
|
|
append("&type=")
|
|
|
|
|
|
|
|
filter.types.oneOrThrowIfMany().let {
|
|
|
|
!filter.query.isNullOrEmpty() -> {
|
|
|
|
append(
|
|
|
|
append("&title=")
|
|
|
|
when (it) {
|
|
|
|
append(filter.query.urlEncoded())
|
|
|
|
ContentType.MANGA -> mangaValue
|
|
|
|
}
|
|
|
|
ContentType.MANHWA -> manhwaValue
|
|
|
|
|
|
|
|
ContentType.MANHUA -> manhuaValue
|
|
|
|
|
|
|
|
ContentType.COMICS -> comicsValue
|
|
|
|
|
|
|
|
else -> ""
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
else -> {
|
|
|
|
filter.query?.let {
|
|
|
|
append("&type=")
|
|
|
|
append("&title=")
|
|
|
|
|
|
|
|
append(filter.query.urlEncoded())
|
|
|
|
append("&status=")
|
|
|
|
}
|
|
|
|
filter.states.oneOrThrowIfMany()?.let {
|
|
|
|
append("&status=")
|
|
|
|
append(
|
|
|
|
filter.states.oneOrThrowIfMany()?.let {
|
|
|
|
when (it) {
|
|
|
|
append(
|
|
|
|
MangaState.ONGOING -> ongoingValue
|
|
|
|
when (it) {
|
|
|
|
MangaState.FINISHED -> finishedValue
|
|
|
|
MangaState.ONGOING -> ongoingValue
|
|
|
|
MangaState.PAUSED -> pausedValue
|
|
|
|
MangaState.FINISHED -> finishedValue
|
|
|
|
MangaState.ABANDONED -> abandonedValue
|
|
|
|
MangaState.PAUSED -> pausedValue
|
|
|
|
else -> ""
|
|
|
|
MangaState.ABANDONED -> abandonedValue
|
|
|
|
},
|
|
|
|
else -> ""
|
|
|
|
)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
filter.tags.forEach {
|
|
|
|
filter.tags.forEach {
|
|
|
|
append("&")
|
|
|
|
append("&")
|
|
|
|
append("genre[]".urlEncoded())
|
|
|
|
append("genre[]".urlEncoded())
|
|
|
|
append("=")
|
|
|
|
append("=")
|
|
|
|
append(it.key)
|
|
|
|
append(it.key)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@ -270,17 +287,14 @@ internal abstract class FuzzyDoodleParser(
|
|
|
|
private fun parseChapterDate(dateFormat: DateFormat, date: String?): Long {
|
|
|
|
private fun parseChapterDate(dateFormat: DateFormat, date: String?): Long {
|
|
|
|
val d = date?.lowercase() ?: return 0
|
|
|
|
val d = date?.lowercase() ?: return 0
|
|
|
|
return when {
|
|
|
|
return when {
|
|
|
|
d.endsWith(" ago") ||
|
|
|
|
|
|
|
|
d.endsWith("مضت") || d.startsWith("منذ") ||
|
|
|
|
|
|
|
|
d.startsWith("il y a") -> parseRelativeDate(date)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
date.contains(Regex("""\d(st|nd|rd|th)""")) -> date.split(" ").map {
|
|
|
|
WordSet(" ago", "مضت").endsWith(d) -> {
|
|
|
|
if (it.contains(Regex("""\d\D\D"""))) {
|
|
|
|
parseRelativeDate(d)
|
|
|
|
it.replace(Regex("""\D"""), "")
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
|
|
|
|
it
|
|
|
|
WordSet("il y a", "منذ").startsWith(d) -> {
|
|
|
|
}
|
|
|
|
parseRelativeDate(d)
|
|
|
|
}.let { dateFormat.tryParse(it.joinToString(" ")) }
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
else -> dateFormat.tryParse(date)
|
|
|
|
else -> dateFormat.tryParse(date)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|