Skip to content
465 changes: 465 additions & 0 deletions src/main/kotlin/tsuki/parsers/KeyoApp.kt

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion src/main/kotlin/tsuki/site/all/Mangadotnet.kt
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ internal class Mangadotnet(context: MangaLoaderContext) :
ContentType.MANGA,
ContentType.MANHWA,
ContentType.MANHUA,
ContentType.ONE_SHOT,
ContentType.OTHER,
),
availableDemographics = EnumSet.of(
Expand Down Expand Up @@ -201,7 +202,8 @@ internal class Mangadotnet(context: MangaLoaderContext) :
ContentType.MANGA -> addQueryParameter("origin", "JP")
ContentType.MANHWA -> addQueryParameter("origin", "KR")
ContentType.MANHUA -> addQueryParameter("origin", "CN")
ContentType.OTHER -> addQueryParameter("origin", "ONESHOT")
ContentType.ONE_SHOT -> addQueryParameter("origin", "ONESHOT")
ContentType.OTHER -> addQueryParameter("origin", "EN")
else -> {}
}
}
Expand Down
51 changes: 40 additions & 11 deletions src/main/kotlin/tsuki/site/en/Chikari.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import tsuki.util.parseJson
import tsuki.util.oneOrThrowIfMany

import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
import okhttp3.HttpUrl.Companion.toHttpUrl
import org.json.JSONArray
Expand Down Expand Up @@ -258,16 +259,44 @@ class Chikari(context: MangaLoaderContext) :

private suspend fun fetchChapters(slug: String, detailsJson: JSONObject? = null): List<MangaChapter> {
try {
val url = "https://$domain/api/series/$slug/chapters".toHttpUrl().newBuilder()
.addQueryParameter("order", "desc")
.addQueryParameter("limit", "9999")
.addQueryParameter("offset", "0")
.build()
.toString()

val response = webClient.httpGet(url).parseJson()
response.optJSONArray("items")?.let { items ->
return parseChapterArray(items, slug)
val limit = 200 // server-enforced max page size

fun buildUrl(offset: Int) =
"https://$domain/api/series/$slug/chapters".toHttpUrl().newBuilder()
.addQueryParameter("order", "desc")
.addQueryParameter("limit", limit.toString())
.addQueryParameter("offset", offset.toString())
.build()
.toString()

val firstResponse = webClient.httpGet(buildUrl(0)).parseJson()
val total = firstResponse.optInt("total", 0)
val allChapters = mutableListOf<MangaChapter>()

firstResponse.optJSONArray("items")?.let { items ->
allChapters.addAll(parseChapterArray(items, slug))
}

val remainingOffsets = (allChapters.size until total step limit).toList()

if (remainingOffsets.isNotEmpty()) {
val pages = coroutineScope {
remainingOffsets.map { offset ->
async {
runCatching {
val response = webClient.httpGet(buildUrl(offset)).parseJson()
response.optJSONArray("items")
?.let { parseChapterArray(it, slug) }
?: emptyList()
}.getOrDefault(emptyList())
}
}.awaitAll()
}
pages.forEach { allChapters.addAll(it) }
}

if (allChapters.isNotEmpty()) {
return allChapters.distinctBy { it.number }.sortedBy { it.number }
}
} catch (_: Exception) {
}
Expand Down Expand Up @@ -300,7 +329,7 @@ class Chikari(context: MangaLoaderContext) :
branch = null,
source = source,
)
}.sortedBy { it.number }
}
}

private fun parseDate(dateStr: String): Long =
Expand Down
Loading