From bb7ac26c0c752040eda09efd866f16823f852c0a Mon Sep 17 00:00:00 2001 From: Draken <131387159+dragonx943@users.noreply.github.com> Date: Thu, 5 Jun 2025 09:03:45 +0700 Subject: [PATCH] [MimiHentai] Small fixes (#1860) --- .../kotatsu/parsers/site/vi/MimiHentai.kt | 136 +++++++++++++----- 1 file changed, 97 insertions(+), 39 deletions(-) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/MimiHentai.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/MimiHentai.kt index ad94a78c..35623cc1 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/MimiHentai.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/vi/MimiHentai.kt @@ -10,9 +10,7 @@ import org.koitharu.kotatsu.parsers.util.* import org.koitharu.kotatsu.parsers.util.json.* import java.text.SimpleDateFormat import java.util.* -import org.koitharu.kotatsu.parsers.Broken -@Broken("Changed API entities + paths") @MangaSourceParser("MIMIHENTAI", "MimiHentai", "vi", type = ContentType.HENTAI) internal class MimiHentai(context: MangaLoaderContext) : LegacyPagedMangaParser(context, MangaParserSource.MIMIHENTAI, 18) { @@ -36,7 +34,15 @@ internal class MimiHentai(context: MangaLoaderContext) : keys.add(preferredServerKey) } - override val availableSortOrders: Set = EnumSet.of(SortOrder.UPDATED) + override val availableSortOrders: Set = EnumSet.of( + SortOrder.UPDATED, + SortOrder.ALPHABETICAL, + SortOrder.POPULARITY, + SortOrder.POPULARITY_TODAY, + SortOrder.POPULARITY_WEEK, + SortOrder.POPULARITY_MONTH, + SortOrder.RATING, + ) override val filterCapabilities: MangaListFilterCapabilities get() = MangaListFilterCapabilities( @@ -53,31 +59,64 @@ internal class MimiHentai(context: MangaLoaderContext) : override suspend fun getFilterOptions() = MangaListFilterOptions(availableTags = fetchTags()) override suspend fun getListPage(page: Int, order: SortOrder, filter: MangaListFilter): List { - val url = buildString { - append("https://") - append(domain) - append("/$apiSuffix/advance-search?page=") - append(page) - append("&max=18") // page size, avoid rate limit - when { - !filter.query.isNullOrEmpty() -> { - append("&name=") - append(filter.query.urlEncoded()) - } - - !filter.author.isNullOrEmpty() -> { - append("&author=") - append(filter.author.urlEncoded()) - } - - filter.tags.isNotEmpty() -> { - append("&genre=") - append(filter.tags.joinToString(",") { it.key }) - } - } - } - - val json = webClient.httpGet(url).parseJson() + val url = buildString { + append("https://") + append(domain + "/" + apiSuffix) + + if (!filter.query.isNullOrEmpty() || !filter.author.isNullOrEmpty() || filter.tags.isNotEmpty()) { + append("/advance-search?page=") + append(page) + append("&max=18") // page size, avoid rate limit + + when { + !filter.query.isNullOrEmpty() -> { + append("&name=") + append(filter.query.urlEncoded()) + } + + !filter.author.isNullOrEmpty() -> { + append("&author=") + append(filter.author.urlEncoded()) + } + + filter.tags.isNotEmpty() -> { + append("&genre=") + append(filter.tags.joinToString(",") { it.key }) + } + } + + append("&sort=") + append( + when (order) { + SortOrder.UPDATED -> "updated_at" + SortOrder.ALPHABETICAL -> "title" + SortOrder.POPULARITY, + SortOrder.POPULARITY_TODAY, + SortOrder.POPULARITY_WEEK, + SortOrder.POPULARITY_MONTH -> "views" + SortOrder.RATING -> "likes" + else -> "" + } + ) + } + + else { + append( + when (order) { + SortOrder.UPDATED -> "/tatcatruyen?page=$page&sort=updated_at" + SortOrder.ALPHABETICAL -> "/tatcatruyen?page=$page&sort=title" + SortOrder.POPULARITY -> "/tatcatruyen?page=$page&sort=views" + SortOrder.POPULARITY_TODAY -> "/top-manga?page=$page&timeType=1&limit=18" + SortOrder.POPULARITY_WEEK -> "/top-manga?page=$page&timeType=2&limit=18" + SortOrder.POPULARITY_MONTH -> "/top-manga?page=$page&timeType=3&limit=18" + SortOrder.RATING -> "/tatcatruyen?page=$page&sort=likes" + else -> "/tatcatruyen?page=$page&sort=updated_at" // default + } + ) + } + } + + val json = webClient.httpGet(url).parseJson() val data = json.getJSONArray("data") return parseMangaList(data) } @@ -85,16 +124,37 @@ internal class MimiHentai(context: MangaLoaderContext) : private fun parseMangaList(data: JSONArray): List { return data.mapJSON { jo -> val id = jo.getLong("id") - val title = jo.getString("title") + val title = jo.getString("title").takeIf { it.isNotEmpty() } ?: "Web chưa đặt tên" val description = jo.getStringOrNull("description") - val authors = jo.getJSONArray("authors").asTypedList().toSet() - val differentNames = jo.getJSONArray("differentNames").asTypedList().toSet() - val state = when (description) { + + val differentNames = mutableSetOf().apply { + jo.optJSONArray("differentNames")?.let { namesArray -> + for (i in 0 until namesArray.length()) { + namesArray.optString(i)?.takeIf { it.isNotEmpty() }?.let { name -> + add(name) + } + } + } + } + + val state = when (description) { "Đang Tiến Hành" -> MangaState.ONGOING "Hoàn Thành" -> MangaState.FINISHED else -> null } + val authors = jo.getJSONArray("authors").mapJSON { + it.getString("name") + }.toSet() + + val tags = jo.getJSONArray("genres").mapJSON { genre -> + MangaTag( + key = genre.getLong("id").toString(), + title = genre.getString("name"), + source = source + ) + }.toSet() + Manga( id = generateUid(id), title = title, @@ -104,7 +164,7 @@ internal class MimiHentai(context: MangaLoaderContext) : rating = RATING_UNKNOWN, contentRating = ContentRating.ADULT, coverUrl = jo.getString("coverUrl"), - tags = emptySet(), + tags = tags, state = state, authors = authors, source = source, @@ -115,9 +175,11 @@ internal class MimiHentai(context: MangaLoaderContext) : override suspend fun getDetails(manga: Manga): Manga { val url = manga.url.toAbsoluteUrl(domain) val json = webClient.httpGet(url).parseJson() + val id = json.getLong("id") + val description = json.getStringOrNull("description") + val uploaderName = json.getJSONObject("uploader").getString("displayName") - val relationInfo = json.getJSONObject("relationInfo") - val tags = relationInfo.getJSONArray("genres").mapJSONToSet { jo -> + val tags = json.getJSONArray("genres").mapJSONToSet { jo -> MangaTag( title = jo.getString("name").toTitleCase(sourceLocale), key = jo.getLong("id").toString(), @@ -125,10 +187,6 @@ internal class MimiHentai(context: MangaLoaderContext) : ) } - val basicInfo = json.getJSONObject("basicInfo") - val id = basicInfo.getLong("id") - val description = basicInfo.getStringOrNull("description") - val uploaderName = json.getStringOrNull("uploaderName") val urlChaps = "https://$domain/$apiSuffix/gallery/$id" val parsedChapters = webClient.httpGet(urlChaps).parseJsonArray() val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSSSS", Locale.US)