diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/WebtoonsParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/WebtoonsParser.kt index eb51e1dfb..f75e9ce8e 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/WebtoonsParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/all/WebtoonsParser.kt @@ -231,21 +231,19 @@ internal abstract class WebtoonsParser( val genre = filter.tags.oneOrThrowIfMany()?.key ?: "ALL" val genres = getAllGenreList() - val result = getAllTitleList() + var result = getAllTitleList() - val sortedResult = when (filter.sortOrder) { - SortOrder.UPDATED -> result.sortedBy { it.date } + if (genre != "ALL") { + result = result.filter { it.manga.tags.contains(genres[genre]) } + } + + when (filter.sortOrder) { + SortOrder.UPDATED -> result.sortedByDescending { it.date } SortOrder.POPULARITY -> result.sortedByDescending { it.readCount } SortOrder.RATING -> result.sortedByDescending { it.manga.rating } //SortOrder.LIKE -> result.sortedBy { it.likeitCount } else -> throw IllegalArgumentException("Unsupported sort order: ${filter.sortOrder}") } - - if (genre != "ALL") { - sortedResult.filter { it.manga.tags.contains(genres[genre]) } - } else { - sortedResult - } } else -> getAllTitleList() diff --git a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/nepnep/NepnepParser.kt b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/nepnep/NepnepParser.kt index ccc6f2700..610f3b0ca 100644 --- a/src/main/kotlin/org/koitharu/kotatsu/parsers/site/nepnep/NepnepParser.kt +++ b/src/main/kotlin/org/koitharu/kotatsu/parsers/site/nepnep/NepnepParser.kt @@ -3,6 +3,7 @@ package org.koitharu.kotatsu.parsers.site.nepnep import okhttp3.Headers import org.json.JSONArray import org.json.JSONObject +import org.jsoup.nodes.Document import org.koitharu.kotatsu.parsers.MangaLoaderContext import org.koitharu.kotatsu.parsers.MangaParser import org.koitharu.kotatsu.parsers.config.ConfigKey @@ -12,9 +13,12 @@ import org.koitharu.kotatsu.parsers.util.* 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.SoftSuspendLazy +import org.koitharu.kotatsu.parsers.util.SuspendLazy import java.text.SimpleDateFormat import java.util.* + internal abstract class NepnepParser( context: MangaLoaderContext, source: MangaSource, @@ -23,7 +27,7 @@ internal abstract class NepnepParser( override val configKeyDomain = ConfigKey.Domain(domain) - override val availableSortOrders: Set = EnumSet.of(SortOrder.ALPHABETICAL) + override val availableSortOrders: Set = EnumSet.of(SortOrder.ALPHABETICAL, SortOrder.POPULARITY, SortOrder.UPDATED) override val availableStates: Set = EnumSet.allOf(MangaState::class.java) override val isTagsExclusionSupported = true @@ -31,97 +35,95 @@ internal abstract class NepnepParser( .add("User-Agent", UserAgents.CHROME_DESKTOP) .build() + private lateinit var docCache: Document + private var mangaListCache: List = emptyList() + + data class MangaWithLastUpdate( + val manga: Manga, + val lastUpdate: Long, + val views: String + ) override suspend fun getList(offset: Int, filter: MangaListFilter?): List { - if (offset > 0) { - return emptyList() + val doc = if (::docCache.isInitialized) { + docCache + }else{ + webClient.httpGet("https://$domain/search/").parseHtml() } - var foundTag = true - var foundTagExclude = true - var foundState = true - - val doc = webClient.httpGet("https://$domain/search/").parseHtml() - val json = JSONArray( - doc.selectFirstOrThrow("script:containsData(MainFunction)").data() + val json = JSONArray(doc.selectFirstOrThrow("script:containsData(MainFunction)").data() .substringAfter("vm.Directory = ") .substringBefore("vm.GetIntValue") .trim() .replace(';', ' '), ) - val manga = ArrayList(json.length()) - + val mangaWithLastUpdateList = ArrayList(json.length()) + var sort = false for (i in 0 until json.length()) { val m = json.getJSONObject(i) val href = "/manga/" + m.getString("i") val imgUrl = "https://temp.compsci88.com/cover/" + m.getString("i") + ".jpg" + val lastUpdate = m.getLong("lt") + val views = m.getString("v") + val viewMonth = m.getString("vm") + when (filter) { is MangaListFilter.Search -> { - if (m.getString("s").contains(filter.query, ignoreCase = true) || m.getString("al") - .contains(filter.query, ignoreCase = true) + if (m.getString("s").contains(filter.query, ignoreCase = true) || (m.getJSONArray("al").length() > 0 && m.getJSONArray("al").getString(0).contains(filter.query, ignoreCase = true)) ) { - manga.add( - addManga(href, imgUrl, m), + mangaWithLastUpdateList.add( + MangaWithLastUpdate(addManga(href, imgUrl, m), lastUpdate, views) ) } } is MangaListFilter.Advanced -> { - - if (filter.tags.isNotEmpty()) { - val tagsJon = m.getJSONArray("g").toString() - filter.tags.forEach { - foundTag = false - if (tagsJon.contains(it.key, ignoreCase = true)) { - foundTag = true - } - } - } - - if (filter.tagsExclude.isNotEmpty()) { - val tagsJon = m.getJSONArray("g").toString() - filter.tagsExclude.forEach { - foundTagExclude = false - if (!tagsJon.contains(it.key, ignoreCase = true)) { - foundTagExclude = true - } - } - } - - if (filter.states.isNotEmpty()) { - val stateJson = m.getString("ps") - filter.states.oneOrThrowIfMany().let { - foundState = false - if (stateJson.contains( - when (it) { - MangaState.ONGOING -> "Ongoing" - MangaState.FINISHED -> "Complete" - MangaState.ABANDONED -> "Cancelled" - MangaState.PAUSED -> "Hiatus" - else -> "" - }, - ignoreCase = true, - ) - ) { - foundState = true - } - } + val tags = filter.tags + val tagsExcluded = filter.tagsExclude + val tagsJson = m.getJSONArray("g").toString() + + val tagsMatched = tags.isEmpty() || tags.all { tag -> tagsJson.contains(tag.key, ignoreCase = true) } + val tagsExcludeMatched = tagsExcluded.isEmpty() || tagsExcluded.none { tag -> tagsJson.contains(tag.key, ignoreCase = true) } + val statesMatched = filter.states.isEmpty() || filter.states.any { state -> + m.getString("ps").contains( + when (state) { + MangaState.ONGOING -> "Ongoing" + MangaState.FINISHED -> "Complete" + MangaState.ABANDONED -> "Cancelled" + MangaState.PAUSED -> "Hiatus" + else -> "" + }, + ignoreCase = true, + ) } + if (tagsMatched && tagsExcludeMatched && statesMatched) { + mangaWithLastUpdateList.add( + MangaWithLastUpdate(addManga(href, imgUrl, m), lastUpdate, views) + ) - if (foundTag && foundState && foundTagExclude) { - manga.add(addManga(href, imgUrl, m)) } + sort = true } null -> { - manga.add( - addManga(href, imgUrl, m), + mangaWithLastUpdateList.add( + MangaWithLastUpdate(addManga(href, imgUrl, m), lastUpdate, views) ) } } } - return manga + if(sort){ + when(filter?.sortOrder){ + SortOrder.POPULARITY -> mangaWithLastUpdateList.sortByDescending { it.views } + SortOrder.UPDATED -> mangaWithLastUpdateList.sortByDescending { it.lastUpdate } + SortOrder.ALPHABETICAL -> {} + else -> if (filter != null) { + throw IllegalArgumentException("Unsupported sort order: ${filter.sortOrder}") + } + } + } + return mangaWithLastUpdateList.map { it.manga }.subList(offset, (offset + 30).coerceAtMost(mangaWithLastUpdateList.size)) } private fun addManga(href: String, imgUrl: String, m: JSONObject): Manga { @@ -141,8 +143,13 @@ internal abstract class NepnepParser( ) } + override suspend fun getAvailableTags(): Set { - val doc = webClient.httpGet("https://$domain/search/").parseHtml() + val doc = if (::docCache.isInitialized) { + docCache + }else{ + webClient.httpGet("https://$domain/search/").parseHtml() + } val tags = doc.selectFirstOrThrow("script:containsData(vm.AvailableFilters)").data() .substringAfter("\"Genre\"") .substringAfter('[')