From 6b95a8c55e4e3b9a42d55834f120b6d1b09378cf Mon Sep 17 00:00:00 2001 From: Koitharu Date: Mon, 15 May 2023 10:56:09 +0300 Subject: [PATCH] [MangaDex] Fix branching ##172 --- .../kotatsu/parsers/site/MangaDexParser.kt | 74 ++++++++++++------- .../kotatsu/parsers/util/Collection.kt | 6 +- .../org/koitharu/kotatsu/test_util/Util.kt | 10 +-- 3 files changed, 56 insertions(+), 34 deletions(-) diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/MangaDexParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/MangaDexParser.kt index db033c80..a19b58e6 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/MangaDexParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/MangaDexParser.kt @@ -134,35 +134,10 @@ internal class MangaDexParser(context: MangaLoaderContext) : MangaParser(context val feedDeferred = async { loadChapters(mangaId) } val mangaAttrs = attrsDeferred.await() val feed = feedDeferred.await() - // 2022-01-02T00:27:11+00:00 - val dateFormat = SimpleDateFormat( - "yyyy-MM-dd'T'HH:mm:ss'+00:00'", - Locale.ROOT, - ) manga.copy( description = mangaAttrs.optJSONObject("description")?.selectByLocale() ?: manga.description, - chapters = feed.mapChapters { _, jo -> - val id = jo.getString("id") - val attrs = jo.getJSONObject("attributes") - if (!attrs.isNull("externalUrl")) { - return@mapChapters null - } - val locale = attrs.getStringOrNull("translatedLanguage")?.let { Locale.forLanguageTag(it) } - val relations = jo.getJSONArray("relationships").associateByKey("type") - val number = attrs.getFloatOrDefault("chapter", 0f) - MangaChapter( - id = generateUid(id), - name = attrs.getStringOrNull("title")?.takeUnless(String::isEmpty) - ?: "Chapter #$number", - number = number.toInt(), - url = id, - scanlator = relations["scanlation_group"]?.getStringOrNull("name"), - uploadDate = dateFormat.tryParse(attrs.getString("publishAt")), - branch = locale?.getDisplayName(locale)?.toTitleCase(locale), - source = source, - ) - }, + chapters = mapChapters(feed), ) } @@ -262,6 +237,53 @@ internal class MangaDexParser(context: MangaLoaderContext) : MangaParser(context } } + private fun mapChapters(list: List): List { + // 2022-01-02T00:27:11+00:00 + val dateFormat = SimpleDateFormat( + "yyyy-MM-dd'T'HH:mm:ss'+00:00'", + Locale.ROOT, + ) + val branches = list.associateGrouping { jo -> + jo.getJSONObject("attributes").getStringOrNull("translatedLanguage") to + jo.getJSONArray("relationships").associateByKey("type")["scanlation_group"] + ?.getJSONObject("attributes")?.getStringOrNull("name") + } + val dc = list.groupBy { jo -> jo.getJSONObject("attributes").getFloatOrDefault("chapter", 0f) } + val chaptersBuilder = ChaptersListBuilder(list.size) + var index = 0 + for ((number, value) in dc) { + for (jo in value) { + val id = jo.getString("id") + val attrs = jo.getJSONObject("attributes") + if (!attrs.isNull("externalUrl")) { + continue + } + val lang = attrs.getStringOrNull("translatedLanguage") + val locale = lang?.let { Locale.forLanguageTag(it) } + val relations = jo.getJSONArray("relationships").associateByKey("type") + val team = relations["scanlation_group"]?.getJSONObject("attributes")?.getStringOrNull("name") + ?.takeUnless { it.isBlank() } + var branch = locale?.getDisplayName(locale)?.toTitleCase(locale) + if (branches[lang].orEmpty().size > 1 && team != null) { + branch += " ($team)" + } + chaptersBuilder += MangaChapter( + id = generateUid(id), + name = attrs.getStringOrNull("title")?.takeUnless(String::isEmpty) + ?: "Chapter #$number", + number = if (number <= 0f) (index + 1) else number.toInt(), + url = id, + scanlator = team, + uploadDate = dateFormat.tryParse(attrs.getString("publishAt")), + branch = branch, + source = source, + ) + } + index++ + } + return chaptersBuilder.toList() + } + private class Chapters( val data: List, val total: Int, diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Collection.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Collection.kt index 039ed1b4..3cfcfbfc 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Collection.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/util/Collection.kt @@ -66,11 +66,11 @@ inline fun List.areItemsEquals(other: List, equals: (T, T) -> Boolean) fun Iterator.nextOrNull(): T? = if (hasNext()) next() else null -inline fun Collection.associateGrouping(transform: (T) -> Pair): Map> { - val result = LinkedHashMap>(size) +inline fun Collection.associateGrouping(transform: (T) -> Pair): Map> { + val result = LinkedHashMap>(size) for (item in this) { val (k, v) = transform(item) - result.getOrPut(k) { LinkedList() }.add(v) + result.getOrPut(k) { LinkedHashSet() }.add(v) } return result } diff --git a/src/test/kotlin/org/koitharu/kotatsu/test_util/Util.kt b/src/test/kotlin/org/koitharu/kotatsu/test_util/Util.kt index 8e41abdd..af2c4d5d 100644 --- a/src/test/kotlin/org/koitharu/kotatsu/test_util/Util.kt +++ b/src/test/kotlin/org/koitharu/kotatsu/test_util/Util.kt @@ -1,7 +1,7 @@ package org.koitharu.kotatsu.test_util import androidx.collection.ArraySet -import okhttp3.HttpUrl.Companion.toHttpUrl +import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import org.koitharu.kotatsu.parsers.model.Manga import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.parsers.model.RATING_UNKNOWN @@ -44,15 +44,15 @@ inline operator fun List.component6(): T = get(5) inline operator fun List.component7(): T = get(6) fun mangaOf(source: MangaSource, url: String): Manga { - val httpUrl = url.toHttpUrl() + val httpUrl = url.toHttpUrlOrNull() var id = 1125899906842597L source.name.forEach { c -> id = 31 * id + c.code } url.forEach { c -> id = 31 * id + c.code } return Manga( id = id, - title = httpUrl.pathSegments.last(), + title = httpUrl?.pathSegments?.last() ?: url, altTitle = null, - url = url.toRelativeUrl(httpUrl.host), + url = httpUrl?.let { url.toRelativeUrl(it.host) } ?: url, publicUrl = url, rating = RATING_UNKNOWN, isNsfw = false, @@ -65,4 +65,4 @@ fun mangaOf(source: MangaSource, url: String): Manga { chapters = null, source = source, ) -} \ No newline at end of file +}