[ComicK] Fixes and status filter support

pull/400/head
Koitharu 2 years ago
parent 7dee865c8a
commit cecba7623e
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -2,10 +2,11 @@ package org.koitharu.kotatsu.parsers.site.all
import androidx.collection.ArraySet import androidx.collection.ArraySet
import androidx.collection.SparseArrayCompat import androidx.collection.SparseArrayCompat
import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaParser
import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.PagedMangaParser
import org.koitharu.kotatsu.parsers.config.ConfigKey import org.koitharu.kotatsu.parsers.config.ConfigKey
import org.koitharu.kotatsu.parsers.model.* import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.* import org.koitharu.kotatsu.parsers.util.*
@ -17,11 +18,10 @@ import java.util.*
* https://api.comick.fun/docs/static/index.html * https://api.comick.fun/docs/static/index.html
*/ */
private const val PAGE_SIZE = 20
private const val CHAPTERS_LIMIT = 99999 private const val CHAPTERS_LIMIT = 99999
@MangaSourceParser("COMICK_FUN", "ComicK") @MangaSourceParser("COMICK_FUN", "ComicK")
internal class ComickFunParser(context: MangaLoaderContext) : MangaParser(context, MangaSource.COMICK_FUN) { internal class ComickFunParser(context: MangaLoaderContext) : PagedMangaParser(context, MangaSource.COMICK_FUN, 20) {
override val configKeyDomain = ConfigKey.Domain("comick.app") override val configKeyDomain = ConfigKey.Domain("comick.app")
@ -31,46 +31,56 @@ internal class ComickFunParser(context: MangaLoaderContext) : MangaParser(contex
SortOrder.RATING, SortOrder.RATING,
) )
override val availableStates: Set<MangaState> = EnumSet.allOf(MangaState::class.java)
@Volatile @Volatile
private var cachedTags: SparseArrayCompat<MangaTag>? = null private var cachedTags: SparseArrayCompat<MangaTag>? = null
override suspend fun getList( override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {
offset: Int,
query: String?,
tags: Set<MangaTag>?,
sortOrder: SortOrder,
): List<Manga> {
val domain = domain val domain = domain
val url = buildString { val url = urlBuilder()
append("https://api.") .host("api.$domain")
append(domain) .addPathSegment("v1.0")
append("/v1.0/search?tachiyomi=true") .addPathSegment("search")
if (!query.isNullOrEmpty()) { .addQueryParameter("type", "comic")
if (offset > 0) { .addQueryParameter("tachiyomi", "true")
return emptyList() .addQueryParameter("limit", pageSize.toString())
} .addQueryParameter("page", page.toString())
append("&q=") when (filter) {
append(query.urlEncoded()) is MangaListFilter.Search -> {
} else { url.addQueryParameter("q", filter.query)
append("&limit=") }
append(PAGE_SIZE)
append("&page=") null -> {
append((offset / PAGE_SIZE) + 1) url.addQueryParameter("sort", "view")
if (!tags.isNullOrEmpty()) { }
append("&genres=")
appendAll(tags, "&genres=", MangaTag::key) is MangaListFilter.Advanced -> {
} filter.tags.forEach { tag ->
append("&sort=") // view, uploaded, rating, follow, user_follow_count url.addQueryParameter("genres", tag.key)
append( }
when (sortOrder) { url.addQueryParameter(
"sort",
when (filter.sortOrder) {
SortOrder.POPULARITY -> "view" SortOrder.POPULARITY -> "view"
SortOrder.RATING -> "rating" SortOrder.RATING -> "rating"
else -> "uploaded" else -> "uploaded"
}, },
) )
filter.states.forEach {
url.addQueryParameter(
"status",
when (it) {
MangaState.ONGOING -> "1"
MangaState.FINISHED -> "2"
MangaState.ABANDONED -> "3"
MangaState.PAUSED -> "4"
},
)
}
} }
} }
val ja = webClient.httpGet(url).parseJsonArray() val ja = webClient.httpGet(url.build()).parseJsonArray()
val tagsMap = cachedTags ?: loadTags() val tagsMap = cachedTags ?: loadTags()
return ja.mapJSON { jo -> return ja.mapJSON { jo ->
val slug = jo.getString("slug") val slug = jo.getString("slug")
@ -108,7 +118,7 @@ internal class ComickFunParser(context: MangaLoaderContext) : MangaParser(contex
title = comic.getString("title"), title = comic.getString("title"),
altTitle = null, // TODO altTitle = null, // TODO
isNsfw = jo.getBoolean("matureContent") || comic.getBoolean("hentai"), isNsfw = jo.getBoolean("matureContent") || comic.getBoolean("hentai"),
description = comic.getStringOrNull("parsed") ?: comic.getString("desc"), description = comic.getStringOrNull("parsed") ?: comic.getStringOrNull("desc"),
tags = manga.tags + comic.getJSONArray("md_comic_md_genres").mapJSONToSet { tags = manga.tags + comic.getJSONArray("md_comic_md_genres").mapJSONToSet {
val g = it.getJSONObject("md_genres") val g = it.getJSONObject("md_genres")
MangaTag( MangaTag(
@ -168,9 +178,32 @@ internal class ComickFunParser(context: MangaLoaderContext) : MangaParser(contex
url = "https://api.${domain}/comic/$hid/chapters?limit=$CHAPTERS_LIMIT", url = "https://api.${domain}/comic/$hid/chapters?limit=$CHAPTERS_LIMIT",
).parseJson().getJSONArray("chapters") ).parseJson().getJSONArray("chapters")
val dateFormat = SimpleDateFormat("yyyy-MM-dd") val dateFormat = SimpleDateFormat("yyyy-MM-dd")
val list = ja.toJSONList().reversed() val counters = HashMap<String?, Int>()
return ja.toJSONList().reversed().mapChapters { _, jo ->
val vol = jo.getStringOrNull("vol")
val chap = jo.getStringOrNull("chap")
val locale = Locale.forLanguageTag(jo.getString("lang"))
val group = jo.optJSONArray("group_name")?.joinToString(", ")
val branch = locale.getDisplayName(locale).toTitleCase(locale) + group
MangaChapter(
id = generateUid(jo.getLong("id")),
name = buildString {
vol?.let { append("Vol ").append(it).append(' ') }
chap?.let { append("Chap ").append(it) }
jo.getStringOrNull("title")?.let { append(": ").append(it) }
},
number = counters.incrementAndGet(branch),
url = jo.getString("hid"),
scanlator = jo.optJSONArray("group_name")?.asIterable<String>()?.joinToString()
?.takeUnless { it.isBlank() },
uploadDate = dateFormat.tryParse(jo.getString("created_at").substringBefore('T')),
branch = branch,
source = source,
)
}
val chaptersBuilder = ChaptersListBuilder(list.size)
/*val chaptersBuilder = ChaptersListBuilder(list.size)
val branchedChapters = HashMap<String?, HashMap<Pair<String?, String?>, MangaChapter>>() val branchedChapters = HashMap<String?, HashMap<Pair<String?, String?>, MangaChapter>>()
for (jo in list) { for (jo in list) {
val vol = jo.getStringOrNull("vol") val vol = jo.getStringOrNull("vol")
@ -201,7 +234,7 @@ internal class ComickFunParser(context: MangaLoaderContext) : MangaParser(contex
branchedChapters.getOrPut(branch, ::HashMap)[volChap] = chapter branchedChapters.getOrPut(branch, ::HashMap)[volChap] = chapter
} }
} }
return chaptersBuilder.toList() return chaptersBuilder.toList()*/
} }
private fun JSONObject.selectGenres(tags: SparseArrayCompat<MangaTag>): Set<MangaTag> { private fun JSONObject.selectGenres(tags: SparseArrayCompat<MangaTag>): Set<MangaTag> {
@ -209,9 +242,13 @@ internal class ComickFunParser(context: MangaLoaderContext) : MangaParser(contex
val res = ArraySet<MangaTag>(array.length()) val res = ArraySet<MangaTag>(array.length())
for (i in 0 until array.length()) { for (i in 0 until array.length()) {
val id = array.getInt(i) val id = array.getInt(i)
val tag = tags.get(id) ?: continue val tag = tags[id] ?: continue
res.add(tag) res.add(tag)
} }
return res return res
} }
private fun JSONArray.joinToString(separator: String): String {
return (0 until length()).joinToString(separator) { i -> getString(i) }
}
} }

@ -73,3 +73,10 @@ inline fun <T, K, V> Collection<T>.associateGrouping(transform: (T) -> Pair<K, V
} }
return result return result
} }
fun <K> MutableMap<K, Int>.incrementAndGet(key: K): Int {
var value = get(key) ?: 0
value++
put(key, value)
return value
}

Loading…
Cancel
Save