From 2292c392e9c5d4591d37441a96cdef12ea45c3bc Mon Sep 17 00:00:00 2001 From: Naga <94557604+NagaYZ@users.noreply.github.com> Date: Sun, 26 May 2024 00:56:50 +0200 Subject: [PATCH] fix filters, added search support (#775) --- .../parsers/site/mangareader/en/RizzComic.kt | 152 ++++++++++++++---- 1 file changed, 123 insertions(+), 29 deletions(-) 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 aefbfd8f..2cd98675 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,58 +1,152 @@ package org.koitharu.kotatsu.parsers.site.mangareader.en -import org.koitharu.kotatsu.parsers.ErrorMessages +import okhttp3.FormBody +import okhttp3.Request import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaSourceParser 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 org.koitharu.kotatsu.parsers.util.* +import org.koitharu.kotatsu.parsers.util.json.getFloatOrDefault +import org.koitharu.kotatsu.parsers.util.json.getStringOrNull +import org.koitharu.kotatsu.parsers.util.json.mapJSON import java.util.* @MangaSourceParser("RIZZCOMIC", "RizzComic", "en") internal class RizzComic(context: MangaLoaderContext) : - MangaReaderParser(context, MangaSource.RIZZCOMIC, "rizzfables.com", pageSize = 50, searchPageSize = 20) { + MangaReaderParser(context, MangaSource.RIZZCOMIC, "rizzfables.com", pageSize = 50, searchPageSize = 20){ override val datePattern = "dd MMM yyyy" override val listUrl = "/series" - - override val availableSortOrders: Set = EnumSet.of(SortOrder.ALPHABETICAL) - override val availableStates: Set = emptySet() - override val isMultipleTagsSupported = false + override val availableSortOrders: Set = EnumSet.of(SortOrder.ALPHABETICAL, SortOrder.UPDATED, SortOrder.NEWEST, SortOrder.POPULARITY, SortOrder.ALPHABETICAL_DESC) + override val availableStates: Set = EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.PAUSED) + override val isMultipleTagsSupported = true override val isSearchSupported = true override val isTagsExclusionSupported = false - // TODO Query created in json + private val filterUrl = "/Index/filter_series" + private val searchUrl = "/Index/live_search" + private val seriesCode = "r2311170" + private val slugRegex = Regex("""[^a-z0-9]+""") + override suspend fun getListPage(page: Int, filter: MangaListFilter?): List { if (page > 1) { return emptyList() } - val url = buildString { - append("https://") - append(domain) - when (filter) { + var url = "https://$domain$filterUrl" - is MangaListFilter.Search -> { - throw IllegalArgumentException(ErrorMessages.SEARCH_NOT_SUPPORTED) + val payload = when (filter) { + is MangaListFilter.Search -> { + url = "https://$domain$searchUrl" + if (filter.query != "") { + FormBody.Builder() + .add("search_value", filter.query.trim()) + .build() + } else { + null } + } + is MangaListFilter.Advanced ->{ + val state = if (filter.states.isEmpty()) "all" + else filter.states.oneOrThrowIfMany()!!.toPayloadValue() - is MangaListFilter.Advanced -> { + val genres = filter.tags.map { it.key } - if (filter.tags.isNotEmpty()) { - append("/genre/") - filter.tags.oneOrThrowIfMany()?.let { - append(it.key) - } - } else { - append(listUrl) - } - } + val formBuilder = FormBody.Builder() + .add("StatusValue", state) + .add("TypeValue", "all") + .add("OrderValue", filter.sortOrder.toPayloadValue()) - null -> { - append(listUrl) + genres.forEach { genre -> + formBuilder.add("genres_checked[]", genre) } + formBuilder.build() + } + else -> { + FormBody.Builder() + .add("StatusValue", "all") + .add("TypeValue", "all") + .add("OrderValue", "all") + .build() + } + } + val request = Request.Builder() + .url(url) + .apply { + if (payload != null) { + post(payload) + } else { + get() + } + } + .build() + val response = context.httpClient.newCall(request).execute().parseJsonArray() + return response.mapJSON { j -> + val title = j.getString("title") + val urlManga = "https://$domain$listUrl/$seriesCode-" + title.trim().lowercase() + .replace(slugRegex, "-") + .replace("-s-", "s-") + .replace("-ll-", "ll-") + + val manga = Manga( + id = j.getLong("id"), + title = title, + altTitle = j.getString("description"), + url = urlManga.toRelativeUrl(domain), + publicUrl = urlManga, + rating = j.getFloatOrDefault("rating", RATING_UNKNOWN) / 10f, + isNsfw = false, + coverUrl = "https://$domain/assets/images/"+ j.getString("image_url"), + tags = setOf(), + state = when (j.getString("status")) { + "ongoing" -> MangaState.ONGOING + "completed" -> MangaState.FINISHED + "hiatus" -> MangaState.PAUSED + else -> null + }, + author = j.getStringOrNull("author"), + source = source, + description = j.getString("long_description"), + ) + manga + + } + + } + + private fun SortOrder.toPayloadValue(): String = when (this) { + SortOrder.ALPHABETICAL -> "title" + SortOrder.POPULARITY -> "popular" + SortOrder.UPDATED -> "update" + SortOrder.NEWEST -> "latest" + SortOrder.ALPHABETICAL_DESC -> "titlereverse" + else -> "all" + } + + private fun MangaState.toPayloadValue(): String = when (this) { + MangaState.ONGOING -> "ongoing" + MangaState.FINISHED -> "completed" + MangaState.PAUSED -> "hiatus" + else -> "all" + } + override suspend fun getAvailableTags(): Set { + val url = "https://$domain/series" + val doc = webClient.httpGet(url).parseHtml() + + val genreElements = doc.select("input.genre-item") + + return genreElements.mapNotNullTo(mutableSetOf()) { element -> + val id = element.attr("value") + val name = element.nextElementSibling()?.text() + + if (id.isNotEmpty() && name != null) { + MangaTag( + key = id, + title = name.toTitleCase(sourceLocale), + source = source, + ) + } else { + null } } - return parseMangaList(webClient.httpGet(url).parseHtml()) } }