Refactor json utilities
This commit is contained in:
@@ -202,7 +202,7 @@ internal class ComickFunParser(context: MangaLoaderContext) :
|
||||
url = "https://api.${domain}/comic/$hid/chapters?limit=$CHAPTERS_LIMIT",
|
||||
).parseJson().getJSONArray("chapters")
|
||||
val dateFormat = SimpleDateFormat("yyyy-MM-dd")
|
||||
return ja.toJSONList().reversed().mapChapters { _, jo ->
|
||||
return ja.asTypedList<JSONObject>().reversed().mapChapters { _, jo ->
|
||||
val vol = jo.getIntOrDefault("vol", 0)
|
||||
val chap = jo.getFloatOrDefault("chap", 0f)
|
||||
val locale = Locale.forLanguageTag(jo.getString("lang"))
|
||||
@@ -227,7 +227,7 @@ internal class ComickFunParser(context: MangaLoaderContext) :
|
||||
number = chap,
|
||||
volume = vol,
|
||||
url = jo.getString("hid"),
|
||||
scanlator = jo.optJSONArray("group_name")?.asIterable<String>()?.joinToString()
|
||||
scanlator = jo.optJSONArray("group_name")?.asTypedList<String>()?.joinToString()
|
||||
?.takeUnless { it.isBlank() },
|
||||
uploadDate = dateFormat.tryParse(jo.getString("created_at").substringBefore('T')),
|
||||
branch = branch,
|
||||
@@ -270,7 +270,7 @@ internal class ComickFunParser(context: MangaLoaderContext) :
|
||||
private suspend fun loadTags(): SparseArrayCompat<MangaTag> {
|
||||
val ja = webClient.httpGet("https://api.${domain}/genre").parseJsonArray()
|
||||
val tags = SparseArrayCompat<MangaTag>(ja.length())
|
||||
for (jo in ja.JSONIterator()) {
|
||||
for (jo in ja.asTypedList<JSONObject>()) {
|
||||
tags.append(
|
||||
jo.getInt("id"),
|
||||
MangaTag(
|
||||
|
||||
@@ -86,7 +86,7 @@ internal abstract class LineWebtoonsParser(
|
||||
val episodes = firstResult
|
||||
.getJSONObject("episodeList")
|
||||
.getJSONArray("episode")
|
||||
.toJSONList()
|
||||
.asTypedList<JSONObject>()
|
||||
.toMutableList()
|
||||
|
||||
while (episodes.count() < totalEpisodeCount) {
|
||||
@@ -94,7 +94,7 @@ internal abstract class LineWebtoonsParser(
|
||||
url = "/lineWebtoon/webtoon/challengeEpisodeList.json?v=2&titleNo=$titleNo&startIndex=${episodes.count()}&pageSize=30",
|
||||
).getJSONObject("episodeList")
|
||||
.getJSONArray("episode")
|
||||
.toJSONList()
|
||||
.asTypedList<JSONObject>()
|
||||
|
||||
episodes.addAll(page)
|
||||
}
|
||||
|
||||
@@ -320,7 +320,7 @@ internal class MangaDexParser(context: MangaLoaderContext) : MangaParser(context
|
||||
)
|
||||
}
|
||||
|
||||
private fun JSONObject.firstStringValue() = values().next() as String
|
||||
private fun JSONObject.firstStringValue() = entries<String>().first().value
|
||||
|
||||
private fun JSONObject.selectByLocale(): String? {
|
||||
val preferredLocales = context.getPreferredLocales()
|
||||
@@ -328,7 +328,7 @@ internal class MangaDexParser(context: MangaLoaderContext) : MangaParser(context
|
||||
getStringOrNull(locale.language)?.let { return it }
|
||||
getStringOrNull(locale.toLanguageTag())?.let { return it }
|
||||
}
|
||||
return getStringOrNull(LOCALE_FALLBACK) ?: values().nextOrNull() as? String
|
||||
return getStringOrNull(LOCALE_FALLBACK) ?: entries<String>().firstOrNull()?.value
|
||||
}
|
||||
|
||||
private fun JSONArray.flatten(): JSONObject {
|
||||
@@ -387,7 +387,7 @@ internal class MangaDexParser(context: MangaLoaderContext) : MangaParser(context
|
||||
val json = webClient.httpGet(url).parseJson()
|
||||
if (json.getString("result") == "ok") {
|
||||
return Chapters(
|
||||
data = json.optJSONArray("data")?.toJSONList().orEmpty(),
|
||||
data = json.optJSONArray("data")?.asTypedList<JSONObject>().orEmpty(),
|
||||
total = json.getInt("total"),
|
||||
)
|
||||
} else {
|
||||
@@ -443,6 +443,16 @@ internal class MangaDexParser(context: MangaLoaderContext) : MangaParser(context
|
||||
return chaptersBuilder.toList()
|
||||
}
|
||||
|
||||
private fun JSONArray.associateByKey(key: String): Map<String, JSONObject> {
|
||||
val destination = LinkedHashMap<String, JSONObject>(length())
|
||||
repeat(length()) { i ->
|
||||
val item = getJSONObject(i)
|
||||
val keyValue = item.getString(key)
|
||||
destination[keyValue] = item
|
||||
}
|
||||
return destination
|
||||
}
|
||||
|
||||
private class Chapters(
|
||||
val data: List<JSONObject>,
|
||||
val total: Int,
|
||||
|
||||
@@ -14,10 +14,10 @@ import org.koitharu.kotatsu.parsers.SinglePageMangaParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.asTypedList
|
||||
import org.koitharu.kotatsu.parsers.util.json.getStringOrNull
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSON
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSONNotNull
|
||||
import org.koitharu.kotatsu.parsers.util.json.toJSONList
|
||||
import java.util.*
|
||||
|
||||
internal abstract class MangaPlusParser(
|
||||
@@ -68,7 +68,7 @@ internal abstract class MangaPlusParser(
|
||||
|
||||
return json.getJSONObject("titleRankingView")
|
||||
.getJSONArray("titles")
|
||||
.toJSONList()
|
||||
.asTypedList<JSONObject>()
|
||||
.toMangaList()
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ internal abstract class MangaPlusParser(
|
||||
apiCall("/title_list/allV2")
|
||||
.getJSONObject("allTitlesViewV2")
|
||||
.getJSONArray("AllTitlesGroup")
|
||||
.mapJSON { it.getJSONArray("titles").toJSONList() }
|
||||
.mapJSON { it.getJSONArray("titles").asTypedList<JSONObject>() }
|
||||
.flatten()
|
||||
}
|
||||
|
||||
@@ -169,10 +169,10 @@ internal abstract class MangaPlusParser(
|
||||
|
||||
private fun parseChapters(chapterListGroup: JSONArray, language: String): List<MangaChapter> {
|
||||
val chapterList = chapterListGroup
|
||||
.toJSONList()
|
||||
.asTypedList<JSONObject>()
|
||||
.flatMap {
|
||||
it.optJSONArray("firstChapterList")?.toJSONList().orEmpty() +
|
||||
it.optJSONArray("lastChapterList")?.toJSONList().orEmpty()
|
||||
it.optJSONArray("firstChapterList")?.asTypedList<JSONObject>().orEmpty() +
|
||||
it.optJSONArray("lastChapterList")?.asTypedList<JSONObject>().orEmpty()
|
||||
}
|
||||
|
||||
return chapterList.mapChapters { _, chapter ->
|
||||
@@ -254,7 +254,7 @@ internal abstract class MangaPlusParser(
|
||||
return checkNotNull(success) {
|
||||
val error = response.getJSONObject("error")
|
||||
val reason = error.getJSONArray("popups")
|
||||
.toJSONList()
|
||||
.asTypedList<JSONObject>()
|
||||
.firstOrNull { it.getStringOrNull("language") == null }
|
||||
|
||||
if (reason?.getStringOrNull("subject") == "Not Found" && url.contains("manga_viewer")) {
|
||||
|
||||
@@ -11,10 +11,10 @@ import org.koitharu.kotatsu.parsers.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.asTypedList
|
||||
import org.koitharu.kotatsu.parsers.util.json.getStringOrNull
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSON
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSONToSet
|
||||
import org.koitharu.kotatsu.parsers.util.json.toJSONList
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@@ -364,8 +364,8 @@ internal class NineNineNineHentaiParser(context: MangaLoaderContext) :
|
||||
}
|
||||
}
|
||||
|
||||
val pics = pages.getJSONArray("pics").toJSONList()
|
||||
val picsS = pages.getJSONArray("picsS").toJSONList()
|
||||
val pics = pages.getJSONArray("pics").asTypedList<JSONObject>()
|
||||
val picsS = pages.getJSONArray("picsS").asTypedList<JSONObject>()
|
||||
|
||||
return pics.zip(picsS).map {
|
||||
val img = it.first.getString("url")
|
||||
|
||||
@@ -12,10 +12,10 @@ import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.domain
|
||||
import org.koitharu.kotatsu.parsers.util.generateUid
|
||||
import org.koitharu.kotatsu.parsers.util.getDomain
|
||||
import org.koitharu.kotatsu.parsers.util.json.asTypedList
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSON
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSONIndexed
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSONNotNull
|
||||
import org.koitharu.kotatsu.parsers.util.json.stringIterator
|
||||
import org.koitharu.kotatsu.parsers.util.toAbsoluteUrl
|
||||
import java.util.*
|
||||
|
||||
@@ -281,7 +281,7 @@ internal class AnibelParser(context: MangaLoaderContext) : MangaParser(context,
|
||||
}
|
||||
|
||||
val result = ArraySet<MangaTag>(length())
|
||||
stringIterator().forEach {
|
||||
asTypedList<String>().forEach {
|
||||
result.add(
|
||||
MangaTag(
|
||||
title = toTitle(it),
|
||||
|
||||
@@ -3,13 +3,14 @@ package org.koitharu.kotatsu.parsers.site.en
|
||||
import androidx.collection.ArrayMap
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import org.json.JSONObject
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.toJSONList
|
||||
import org.koitharu.kotatsu.parsers.util.json.asTypedList
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@@ -135,7 +136,8 @@ internal class AsuraScansParser(context: MangaLoaderContext) :
|
||||
tagCache?.let { return@withLock it }
|
||||
val tagMap = ArrayMap<String, MangaTag>()
|
||||
val json =
|
||||
webClient.httpGet("https://gg.$domain/api/series/filters").parseJson().getJSONArray("genres").toJSONList()
|
||||
webClient.httpGet("https://gg.$domain/api/series/filters").parseJson().getJSONArray("genres")
|
||||
.asTypedList<JSONObject>()
|
||||
for (el in json) {
|
||||
if (el.getString("name").isEmpty()) continue
|
||||
tagMap[el.getString("name")] = MangaTag(
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.koitharu.kotatsu.parsers.site.en
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import org.koitharu.kotatsu.parsers.Broken
|
||||
import org.koitharu.kotatsu.parsers.ErrorMessages
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
@@ -11,8 +12,8 @@ import org.koitharu.kotatsu.parsers.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.asTypedList
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSON
|
||||
import org.koitharu.kotatsu.parsers.util.json.toJSONList
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@@ -167,7 +168,7 @@ internal class FlixScansOrg(context: MangaLoaderContext) :
|
||||
val seriesKey = baseUrl.substringAfterLast("/").substringBefore("-")
|
||||
val json = JSONArray(
|
||||
webClient.httpGet("https://api.$domain/api/v1/webtoon/chapters/$key-desc").parseRaw(),
|
||||
).toJSONList().reversed()
|
||||
).asTypedList<JSONObject>().reversed()
|
||||
return json.mapChapters { i, j ->
|
||||
val url = "https://$domain/read/webtoon/$seriesKey-${j.getString("id")}-${j.getString("slug")}"
|
||||
val date = j.getString("createdAt").substringBeforeLast("T")
|
||||
|
||||
@@ -7,9 +7,9 @@ import org.koitharu.kotatsu.parsers.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.asTypedList
|
||||
import org.koitharu.kotatsu.parsers.util.json.getFloatOrDefault
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSON
|
||||
import org.koitharu.kotatsu.parsers.util.json.toJSONList
|
||||
import org.koitharu.kotatsu.parsers.util.json.unescapeJson
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
@@ -151,7 +151,7 @@ internal abstract class HeanCms(
|
||||
val seriesId = manga.id
|
||||
val url = "https://$apiPath/chapter/query?page=1&perPage=9999&series_id=$seriesId"
|
||||
val response = webClient.httpGet(url).parseJson()
|
||||
val data = response.getJSONArray("data").toJSONList()
|
||||
val data = response.getJSONArray("data").asTypedList<JSONObject>()
|
||||
val dateFormat = SimpleDateFormat(datePattern, Locale.ENGLISH)
|
||||
return manga.copy(
|
||||
chapters = data.mapChapters(reversed = true) { i, it ->
|
||||
|
||||
@@ -6,9 +6,9 @@ import org.koitharu.kotatsu.parsers.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.asTypedList
|
||||
import org.koitharu.kotatsu.parsers.util.json.getBooleanOrDefault
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSON
|
||||
import org.koitharu.kotatsu.parsers.util.json.toJSONList
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@@ -132,7 +132,7 @@ internal abstract class IkenParser(
|
||||
val url = "https://$domain/api/chapters?postId=$seriesId&skip=0&take=1000&order=desc&userid="
|
||||
val json = webClient.httpGet(url).parseJson().getJSONObject("post")
|
||||
val slug = json.getString("slug")
|
||||
val data = json.getJSONArray("chapters").toJSONList()
|
||||
val data = json.getJSONArray("chapters").asTypedList<JSONObject>()
|
||||
val dateFormat = SimpleDateFormat(datePattern, Locale.ENGLISH)
|
||||
return manga.copy(
|
||||
chapters = data.mapChapters(reversed = true) { i, it ->
|
||||
|
||||
@@ -131,7 +131,7 @@ internal abstract class MangAdventureParser(
|
||||
"hiatus" -> MangaState.PAUSED
|
||||
else -> null
|
||||
},
|
||||
chapters = chapters?.optJSONArray("results")?.toJSONList()?.mapChapters { _, it ->
|
||||
chapters = chapters?.optJSONArray("results")?.asTypedList<JSONObject>()?.mapChapters { _, it ->
|
||||
MangaChapter(
|
||||
id = generateUid(it.getLong("id")),
|
||||
name = it.getString("full_title"),
|
||||
|
||||
@@ -8,9 +8,9 @@ import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.network.UserAgents
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.asTypedList
|
||||
import org.koitharu.kotatsu.parsers.util.json.getStringOrNull
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSONIndexed
|
||||
import org.koitharu.kotatsu.parsers.util.json.toJSONList
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@@ -177,7 +177,7 @@ internal abstract class NepnepParser(
|
||||
doc.selectFirstOrThrow("script:containsData(MainFunction)").data()
|
||||
.substringAfter("vm.Chapters = ")
|
||||
.substringBefore(';'),
|
||||
).toJSONList().reversed(),
|
||||
).asTypedList<JSONObject>().reversed(),
|
||||
)
|
||||
|
||||
val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:SS", sourceLocale)
|
||||
|
||||
@@ -8,9 +8,10 @@ import org.koitharu.kotatsu.parsers.SinglePageMangaParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.asTypedList
|
||||
import org.koitharu.kotatsu.parsers.util.json.getStringOrNull
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSONIndexed
|
||||
import org.koitharu.kotatsu.parsers.util.json.toJSONList
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSONToSet
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@@ -209,10 +210,10 @@ internal abstract class PizzaReaderParser(
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val json = webClient.httpGet(fullUrl).parseJson().getJSONObject("comic")
|
||||
val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US)
|
||||
val chapters = JSONArray(json.getJSONArray("chapters").toJSONList().reversed())
|
||||
val chapters = JSONArray(json.getJSONArray("chapters").asTypedList<JSONObject>().reversed())
|
||||
|
||||
manga.copy(
|
||||
tags = json.getJSONArray("genres").toJSONList().mapNotNullToSet {
|
||||
tags = json.getJSONArray("genres").mapJSONToSet {
|
||||
MangaTag(
|
||||
key = it.getString("slug"),
|
||||
title = it.getString("name"),
|
||||
|
||||
@@ -137,13 +137,13 @@ internal class MangaWtfParser(
|
||||
tags = jo.getJSONArray("labels").mapJSONToSet { it.toMangaTag() },
|
||||
state = jo.getStringOrNull("status")?.toMangaState(),
|
||||
author =
|
||||
jo.getJSONArray("relations").toJSONList().firstNotNullOfOrNull {
|
||||
if (it.getStringOrNull("type") == "AUTHOR") {
|
||||
it.getJSONObject("publisher").getStringOrNull("name")
|
||||
} else {
|
||||
null
|
||||
}
|
||||
},
|
||||
jo.getJSONArray("relations").asTypedList<JSONObject>().firstNotNullOfOrNull {
|
||||
if (it.getStringOrNull("type") == "AUTHOR") {
|
||||
it.getJSONObject("publisher").getStringOrNull("name")
|
||||
} else {
|
||||
null
|
||||
}
|
||||
},
|
||||
source = source,
|
||||
largeCoverUrl = null,
|
||||
description = jo.getString("description").nl2br(),
|
||||
@@ -209,10 +209,10 @@ internal class MangaWtfParser(
|
||||
MangaChapter(
|
||||
id = generateUid(jo.getString("id")),
|
||||
name =
|
||||
jo.getStringOrNull("name") ?: buildString {
|
||||
if (volume > 0) append("Том ").append(volume).append(' ')
|
||||
if (number > 0) append("Глава ").append(number) else append("Без имени")
|
||||
},
|
||||
jo.getStringOrNull("name") ?: buildString {
|
||||
if (volume > 0) append("Том ").append(volume).append(' ')
|
||||
if (number > 0) append("Глава ").append(number) else append("Без имени")
|
||||
},
|
||||
number = number,
|
||||
volume = volume,
|
||||
url = jo.getString("id"),
|
||||
|
||||
@@ -13,9 +13,9 @@ import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.asTypedList
|
||||
import org.koitharu.kotatsu.parsers.util.json.getStringOrNull
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSON
|
||||
import org.koitharu.kotatsu.parsers.util.json.toJSONList
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@@ -36,7 +36,7 @@ internal class HentaiUkrParser(context: MangaLoaderContext) : MangaParser(contex
|
||||
webClient.httpGet("https://$domain/search/objects2.json").parseJson()
|
||||
}.recoverCatchingCancellable {
|
||||
webClient.httpGet("https://$domain/search/objects69.json").parseJson()
|
||||
}.getOrThrow().getJSONArray("manga").toJSONList()
|
||||
}.getOrThrow().getJSONArray("manga").asTypedList<JSONObject>()
|
||||
}
|
||||
|
||||
override val configKeyDomain: ConfigKey.Domain = ConfigKey.Domain("hentaiukr.com")
|
||||
|
||||
@@ -7,7 +7,10 @@ import org.koitharu.kotatsu.parsers.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.asTypedList
|
||||
import org.koitharu.kotatsu.parsers.util.json.getStringOrNull
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSON
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSONToSet
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@@ -93,7 +96,7 @@ internal class YurinekoParser(context: MangaLoaderContext) : PagedMangaParser(co
|
||||
val df = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US)
|
||||
return manga.copy(
|
||||
chapters = response.getJSONArray("chapters")
|
||||
.toJSONList()
|
||||
.asTypedList<JSONObject>()
|
||||
.mapChapters(true) { i, jo ->
|
||||
val mangaId = jo.getInt("mangaID")
|
||||
val chapterId = jo.getInt("id")
|
||||
@@ -120,7 +123,7 @@ internal class YurinekoParser(context: MangaLoaderContext) : PagedMangaParser(co
|
||||
.getJSONObject("pageProps")
|
||||
.getJSONObject("chapterData")
|
||||
.getJSONArray("url")
|
||||
.asIterable<String>()
|
||||
.asTypedList<String>()
|
||||
.map { url ->
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
|
||||
@@ -3,6 +3,7 @@ package org.koitharu.kotatsu.parsers.site.zeistmanga
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
import org.jsoup.Jsoup
|
||||
import org.jsoup.nodes.Document
|
||||
import org.koitharu.kotatsu.parsers.ErrorMessages
|
||||
@@ -11,8 +12,9 @@ import org.koitharu.kotatsu.parsers.PagedMangaParser
|
||||
import org.koitharu.kotatsu.parsers.config.ConfigKey
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.asTypedList
|
||||
import org.koitharu.kotatsu.parsers.util.json.getStringOrNull
|
||||
import org.koitharu.kotatsu.parsers.util.json.toJSONList
|
||||
import org.koitharu.kotatsu.parsers.util.json.mapJSON
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@@ -150,10 +152,11 @@ internal abstract class ZeistMangaParser(
|
||||
}
|
||||
|
||||
protected open fun parseMangaList(json: JSONArray): List<Manga> {
|
||||
return json.toJSONList().map { j ->
|
||||
return json.mapJSON { j ->
|
||||
val name = j.getJSONObject("title").getString("\$t")
|
||||
val href =
|
||||
j.getJSONArray("link").toJSONList().first { it.getString("rel") == "alternate" }.getString("href")
|
||||
j.getJSONArray("link").asTypedList<JSONObject>().first { it.getString("rel") == "alternate" }
|
||||
.getString("href")
|
||||
val urlImg = if (j.toString().contains("media\$thumbnail")) {
|
||||
j.getJSONObject("media\$thumbnail").getStringOrNull("url")
|
||||
?.replace("""/s.+?-c/""".toRegex(), "/w600/")
|
||||
@@ -274,12 +277,14 @@ internal abstract class ZeistMangaParser(
|
||||
append("?alt=json&orderby=published&max-results=9999")
|
||||
}
|
||||
val json =
|
||||
webClient.httpGet(url).parseJson().getJSONObject("feed").getJSONArray("entry").toJSONList().reversed()
|
||||
webClient.httpGet(url).parseJson().getJSONObject("feed").getJSONArray("entry").asTypedList<JSONObject>()
|
||||
.reversed()
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
return json.mapIndexedNotNull { i, j ->
|
||||
val name = j.getJSONObject("title").getString("\$t")
|
||||
val href =
|
||||
j.getJSONArray("link").toJSONList().first { it.getString("rel") == "alternate" }.getString("href")
|
||||
j.getJSONArray("link").asTypedList<JSONObject>().first { it.getString("rel") == "alternate" }
|
||||
.getString("href")
|
||||
val dateText = j.getJSONObject("published").getString("\$t").substringBefore("T")
|
||||
val slug = mangaUrl.substringAfterLast('/')
|
||||
val slugChapter = href.substringAfterLast('/')
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.koitharu.kotatsu.parsers.site.zeistmanga.id
|
||||
|
||||
import org.json.JSONObject
|
||||
import org.jsoup.nodes.Document
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
@@ -8,7 +9,7 @@ import org.koitharu.kotatsu.parsers.model.MangaPage
|
||||
import org.koitharu.kotatsu.parsers.model.MangaParserSource
|
||||
import org.koitharu.kotatsu.parsers.site.zeistmanga.ZeistMangaParser
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.util.json.toJSONList
|
||||
import org.koitharu.kotatsu.parsers.util.json.asTypedList
|
||||
import java.text.SimpleDateFormat
|
||||
|
||||
@MangaSourceParser("KOMIKGES", "KomikGes", "id")
|
||||
@@ -25,12 +26,14 @@ internal class KomikGes(context: MangaLoaderContext) :
|
||||
append("?alt=json&orderby=published&max-results=9999")
|
||||
}
|
||||
val json =
|
||||
webClient.httpGet(url).parseJson().getJSONObject("feed").getJSONArray("entry").toJSONList().reversed()
|
||||
webClient.httpGet(url).parseJson().getJSONObject("feed").getJSONArray("entry").asTypedList<JSONObject>()
|
||||
.reversed()
|
||||
val dateFormat = SimpleDateFormat(datePattern, sourceLocale)
|
||||
return json.mapIndexedNotNull { i, j ->
|
||||
val name = j.getJSONObject("title").getString("\$t")
|
||||
val href =
|
||||
j.getJSONArray("link").toJSONList().first { it.getString("rel") == "alternate" }.getString("href")
|
||||
j.getJSONArray("link").asTypedList<JSONObject>().first { it.getString("rel") == "alternate" }
|
||||
.getString("href")
|
||||
val dateText = j.getJSONObject("published").getString("\$t").substringBefore("T")
|
||||
val slug = mangaUrl.substringAfterLast('/')
|
||||
val slugChapter = href.substringAfterLast('/')
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package org.koitharu.kotatsu.parsers.util.json
|
||||
|
||||
import org.json.JSONArray
|
||||
|
||||
internal class JSONArrayTypedIterator<T : Any>(
|
||||
private val array: JSONArray,
|
||||
private val typeClass: Class<T>,
|
||||
startIndex: Int,
|
||||
) : ListIterator<T> {
|
||||
|
||||
private val total = array.length()
|
||||
private var index = startIndex
|
||||
|
||||
override fun hasNext() = index < total
|
||||
|
||||
override fun next(): T = typeClass.cast(array[index++])
|
||||
|
||||
override fun hasPrevious(): Boolean = index > 0
|
||||
|
||||
override fun nextIndex(): Int = index + 1
|
||||
|
||||
override fun previous(): T = typeClass.cast(array[index--])
|
||||
|
||||
override fun previousIndex(): Int = index - 1
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package org.koitharu.kotatsu.parsers.util.json
|
||||
|
||||
import org.json.JSONArray
|
||||
|
||||
internal class JSONArrayTypedListWrapper<T : Any>(
|
||||
private val jsonArray: JSONArray,
|
||||
private val typeClass: Class<T>,
|
||||
) : List<T> {
|
||||
|
||||
override fun contains(element: T): Boolean = indexOf(element) != -1
|
||||
|
||||
override fun containsAll(elements: Collection<T>): Boolean = elements.all { contains(it) }
|
||||
|
||||
override fun get(index: Int): T = typeClass.cast(jsonArray[index])
|
||||
|
||||
override fun indexOf(element: T): Int {
|
||||
repeat(jsonArray.length()) { i ->
|
||||
if (jsonArray[i] == element) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
override fun isEmpty(): Boolean = jsonArray.length() == 0
|
||||
|
||||
override fun iterator(): Iterator<T> = listIterator(0)
|
||||
|
||||
override fun lastIndexOf(element: T): Int {
|
||||
val total = jsonArray.length()
|
||||
repeat(total) { i ->
|
||||
if (jsonArray[total - i - 1] == element) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
override fun listIterator(): ListIterator<T> = listIterator(0)
|
||||
|
||||
override fun listIterator(index: Int): ListIterator<T> = JSONArrayTypedIterator(jsonArray, typeClass, index)
|
||||
|
||||
override fun subList(fromIndex: Int, toIndex: Int): List<T> {
|
||||
val result = ArrayList<T>(toIndex - fromIndex + 1)
|
||||
for (i in fromIndex..toIndex) {
|
||||
result.add(get(i))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
override val size: Int
|
||||
get() = jsonArray.length()
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.util.json
|
||||
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
|
||||
class JSONIterator(private val array: JSONArray) : Iterator<JSONObject> {
|
||||
|
||||
private val total = array.length()
|
||||
private var index = 0
|
||||
|
||||
override fun hasNext() = index < total
|
||||
|
||||
override fun next(): JSONObject = array.getJSONObject(index++)
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
package org.koitharu.kotatsu.parsers.util.json
|
||||
|
||||
import org.json.JSONObject
|
||||
|
||||
internal class JSONObjectTypedIterableWrapper<T : Any>(
|
||||
private val json: JSONObject,
|
||||
private val typeClass: Class<T>,
|
||||
) : Iterable<Map.Entry<String, T>> {
|
||||
|
||||
override fun iterator(): Iterator<Map.Entry<String, T>> = IteratorImpl()
|
||||
|
||||
private inner class IteratorImpl : Iterator<Map.Entry<String, T>> {
|
||||
|
||||
private val keyIterator = json.keys().iterator()
|
||||
|
||||
override fun hasNext(): Boolean = keyIterator.hasNext()
|
||||
|
||||
override fun next(): Map.Entry<String, T> = keyIterator.next().let { key ->
|
||||
JSONEntry(key, typeClass.cast(json.get(key)))
|
||||
}
|
||||
}
|
||||
|
||||
private class JSONEntry<T : Any>(override val key: String, override val value: T) : Map.Entry<String, T>
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.util.json
|
||||
|
||||
import org.json.JSONArray
|
||||
|
||||
class JSONStringIterator(private val array: JSONArray) : Iterator<String> {
|
||||
|
||||
private val total = array.length()
|
||||
private var index = 0
|
||||
|
||||
override fun hasNext() = index < total
|
||||
|
||||
override fun next(): String = array.getString(index++)
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.util.json
|
||||
|
||||
import org.json.JSONArray
|
||||
|
||||
class JSONTypedIterator<T>(
|
||||
private val array: JSONArray,
|
||||
private val cls: Class<T>,
|
||||
) : Iterator<T> {
|
||||
|
||||
private val total = array.length()
|
||||
private var index = 0
|
||||
|
||||
override fun hasNext() = index < total
|
||||
|
||||
override fun next(): T {
|
||||
return cls.cast(array.get(index++))
|
||||
}
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package org.koitharu.kotatsu.parsers.util.json
|
||||
|
||||
import org.json.JSONObject
|
||||
|
||||
class JSONValuesIterator(
|
||||
private val jo: JSONObject,
|
||||
) : Iterator<Any> {
|
||||
|
||||
private val keyIterator = jo.keys()
|
||||
|
||||
override fun hasNext(): Boolean = keyIterator.hasNext()
|
||||
|
||||
override fun next(): Any {
|
||||
val key = keyIterator.next()
|
||||
return jo.get(key)
|
||||
}
|
||||
}
|
||||
@@ -38,6 +38,10 @@ public inline fun <T> JSONArray.mapJSONNotNull(block: (JSONObject) -> T?): List<
|
||||
return mapJSONNotNullTo(ArrayList(length()), block)
|
||||
}
|
||||
|
||||
public inline fun <T> JSONArray.mapJSONToSet(mapper: (JSONObject) -> T): Set<T> {
|
||||
return mapJSONTo(ArraySet<T>(length()), mapper)
|
||||
}
|
||||
|
||||
public fun <T> JSONArray.mapJSONIndexed(block: (Int, JSONObject) -> T): List<T> {
|
||||
val len = length()
|
||||
val result = ArrayList<T>(len)
|
||||
@@ -104,30 +108,6 @@ public fun JSONObject.getFloatOrDefault(name: String, defaultValue: Float): Floa
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated("")
|
||||
public fun JSONArray.JSONIterator(): Iterator<JSONObject> = JSONIterator(this)
|
||||
|
||||
@Deprecated("")
|
||||
public fun JSONArray.stringIterator(): Iterator<String> = JSONStringIterator(this)
|
||||
|
||||
public inline fun <T> JSONArray.mapJSONToSet(mapper: (JSONObject) -> T): Set<T> {
|
||||
return mapJSONTo(ArraySet<T>(length()), mapper)
|
||||
}
|
||||
|
||||
@Deprecated("")
|
||||
public fun JSONObject.values(): Iterator<Any> = JSONValuesIterator(this)
|
||||
|
||||
@Deprecated("")
|
||||
public fun JSONArray.associateByKey(key: String): Map<String, JSONObject> {
|
||||
val destination = LinkedHashMap<String, JSONObject>(length())
|
||||
repeat(length()) { i ->
|
||||
val item = getJSONObject(i)
|
||||
val keyValue = item.getString(key)
|
||||
destination[keyValue] = item
|
||||
}
|
||||
return destination
|
||||
}
|
||||
|
||||
public fun JSONArray?.isNullOrEmpty(): Boolean {
|
||||
contract {
|
||||
returns(false) implies (this@isNullOrEmpty != null)
|
||||
@@ -136,12 +116,14 @@ public fun JSONArray?.isNullOrEmpty(): Boolean {
|
||||
return this == null || this.length() == 0
|
||||
}
|
||||
|
||||
@Deprecated("")
|
||||
public fun JSONArray.toJSONList(): List<JSONObject> {
|
||||
return List(length()) { i -> getJSONObject(i) }
|
||||
public fun <T : Any> JSONArray.asTypedList(typeClass: Class<T>): List<T> {
|
||||
return JSONArrayTypedListWrapper(this, typeClass)
|
||||
}
|
||||
|
||||
@Deprecated("")
|
||||
public inline fun <reified T> JSONArray.asIterable(): Iterable<T> = Iterable {
|
||||
JSONTypedIterator(this, T::class.java)
|
||||
public inline fun <reified T : Any> JSONArray.asTypedList(): List<T> = asTypedList(T::class.java)
|
||||
|
||||
public fun <T : Any> JSONObject.entries(typeClass: Class<T>): Iterable<Map.Entry<String, T>> {
|
||||
return JSONObjectTypedIterableWrapper(this, typeClass)
|
||||
}
|
||||
|
||||
public inline fun <reified T : Any> JSONObject.entries(): Iterable<Map.Entry<String, T>> = entries(T::class.java)
|
||||
|
||||
Reference in New Issue
Block a user