[DesuMe] Genres in list

Koitharu 3 years ago
parent 454b24ec88
commit f3b731114e
No known key found for this signature in database
GPG Key ID: 8E861F8CE6E7CE27

@ -1,5 +1,6 @@
package org.koitharu.kotatsu.parsers.site package org.koitharu.kotatsu.parsers.site
import androidx.collection.ArrayMap
import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaLoaderContext
import org.koitharu.kotatsu.parsers.MangaSourceParser import org.koitharu.kotatsu.parsers.MangaSourceParser
import org.koitharu.kotatsu.parsers.PagedMangaParser import org.koitharu.kotatsu.parsers.PagedMangaParser
@ -24,6 +25,8 @@ internal class DesuMeParser(context: MangaLoaderContext) : PagedMangaParser(cont
SortOrder.ALPHABETICAL, SortOrder.ALPHABETICAL,
) )
private val tagsCache = SuspendLazy(::fetchTags)
override suspend fun getListPage( override suspend fun getListPage(
page: Int, page: Int,
query: String?, query: String?,
@ -54,10 +57,12 @@ internal class DesuMeParser(context: MangaLoaderContext) : PagedMangaParser(cont
?: throw ParseException("Invalid response", url) ?: throw ParseException("Invalid response", url)
val total = json.length() val total = json.length()
val list = ArrayList<Manga>(total) val list = ArrayList<Manga>(total)
val tagsMap = tagsCache.tryGet().getOrNull()
for (i in 0 until total) { for (i in 0 until total) {
val jo = json.getJSONObject(i) val jo = json.getJSONObject(i)
val cover = jo.getJSONObject("image") val cover = jo.getJSONObject("image")
val id = jo.getLong("id") val id = jo.getLong("id")
val genres = jo.getString("genres").split(',')
list += Manga( list += Manga(
url = "/manga/api/$id", url = "/manga/api/$id",
publicUrl = jo.getString("url"), publicUrl = jo.getString("url"),
@ -73,7 +78,13 @@ internal class DesuMeParser(context: MangaLoaderContext) : PagedMangaParser(cont
rating = jo.getDouble("score").toFloat().coerceIn(0f, 1f), rating = jo.getDouble("score").toFloat().coerceIn(0f, 1f),
id = generateUid(id), id = generateUid(id),
isNsfw = false, isNsfw = false,
tags = emptySet(), tags = if (!tagsMap.isNullOrEmpty()) {
genres.mapNotNullToSet { g ->
tagsMap[g.trim().toTitleCase()]
}
} else {
emptySet()
},
author = null, author = null,
description = jo.getString("description"), description = jo.getString("description"),
) )
@ -133,12 +144,27 @@ internal class DesuMeParser(context: MangaLoaderContext) : PagedMangaParser(cont
} }
override suspend fun getTags(): Set<MangaTag> { override suspend fun getTags(): Set<MangaTag> {
return tagsCache.get().values.toSet()
}
private fun getSortKey(sortOrder: SortOrder) =
when (sortOrder) {
SortOrder.ALPHABETICAL -> "name"
SortOrder.POPULARITY -> "popular"
SortOrder.UPDATED -> "updated"
SortOrder.NEWEST -> "id"
else -> "updated"
}
private suspend fun fetchTags(): Map<String, MangaTag> {
val doc = webClient.httpGet("https://${domain}/manga/").parseHtml() val doc = webClient.httpGet("https://${domain}/manga/").parseHtml()
val root = doc.body().requireElementById("animeFilter") val root = doc.body().requireElementById("animeFilter")
.selectFirstOrThrow(".catalog-genres") .selectFirstOrThrow(".catalog-genres")
return root.select("li").mapToSet { val li = root.select("li")
val result = ArrayMap<String, MangaTag>(li.size)
li.forEach {
val input = it.selectFirstOrThrow("input") val input = it.selectFirstOrThrow("input")
MangaTag( val tag = MangaTag(
source = source, source = source,
key = input.attr("data-genre-slug").ifEmpty { key = input.attr("data-genre-slug").ifEmpty {
it.parseFailed("data-genre-slug is empty") it.parseFailed("data-genre-slug is empty")
@ -147,15 +173,8 @@ internal class DesuMeParser(context: MangaLoaderContext) : PagedMangaParser(cont
it.parseFailed("data-genre-name is empty") it.parseFailed("data-genre-name is empty")
}, },
) )
result[tag.title] = tag
} }
} return result
private fun getSortKey(sortOrder: SortOrder) =
when (sortOrder) {
SortOrder.ALPHABETICAL -> "name"
SortOrder.POPULARITY -> "popular"
SortOrder.UPDATED -> "updated"
SortOrder.NEWEST -> "id"
else -> "updated"
} }
} }

@ -0,0 +1,36 @@
package org.koitharu.kotatsu.parsers.util
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
class SuspendLazy<T>(
private val initializer: suspend () -> T,
) {
private val mutex = Mutex()
private var cachedValue: Any? = Uninitialized
@Suppress("UNCHECKED_CAST")
suspend fun get(): T {
// fast way
cachedValue.let {
if (it !== Uninitialized) {
return it as T
}
}
return mutex.withLock {
cachedValue.let {
if (it !== Uninitialized) {
return it as T
}
}
val result = initializer()
cachedValue = result
result
}
}
suspend fun tryGet() = runCatchingCancellable { get() }
private object Uninitialized
}
Loading…
Cancel
Save