From b98ede3e0aea7d61c3e5d3486828a55346a1da0d Mon Sep 17 00:00:00 2001 From: Arraiment <76941874+Arraiment@users.noreply.github.com> Date: Tue, 10 Aug 2021 00:44:19 +0800 Subject: [PATCH] Migrates nepnep multisrc to kotlinx.serialization (#8494) * Fix chapter number issue * Migration to kotlinx.serialization --- .../tachiyomi/multisrc/nepnep/NepNep.kt | 126 +++++++++++------- .../multisrc/nepnep/NepNepGenerator.kt | 2 +- 2 files changed, 79 insertions(+), 49 deletions(-) diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/nepnep/NepNep.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/nepnep/NepNep.kt index b7adad7e9..30c79f430 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/nepnep/NepNep.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/nepnep/NepNep.kt @@ -1,12 +1,5 @@ package eu.kanade.tachiyomi.multisrc.nepnep -import com.github.salomonbrys.kotson.fromJson -import com.github.salomonbrys.kotson.get -import com.github.salomonbrys.kotson.nullString -import com.github.salomonbrys.kotson.string -import com.google.gson.GsonBuilder -import com.google.gson.JsonArray -import com.google.gson.JsonElement import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.source.model.Filter @@ -17,10 +10,18 @@ import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.util.asJsoup +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.contentOrNull +import kotlinx.serialization.json.jsonArray +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive import okhttp3.Headers import okhttp3.Request import okhttp3.Response import rx.Observable +import uy.kohesive.injekt.injectLazy import java.text.SimpleDateFormat import java.util.Locale @@ -40,10 +41,20 @@ abstract class NepNep( .add("Referer", "$baseUrl/") .add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/77.0") - private val gson = GsonBuilder().setLenient().create() + private val json: Json by injectLazy() private lateinit var directory: List + // Convenience functions to shorten later code + /** Returns value corresponding to given key as a string, or null */ + private fun JsonElement.getString(key: String): String? { + return this.jsonObject[key]!!.jsonPrimitive.contentOrNull + } + /** Returns value corresponding to given key as a JsonArray */ + private fun JsonElement.getArray(key: String): JsonArray { + return this.jsonObject[key]!!.jsonArray + } + // Popular override fun fetchPopularManga(page: Int): Observable { @@ -63,15 +74,15 @@ abstract class NepNep( } // don't use ";" for substringBefore() ! - private fun directoryFromResponse(response: Response): String { - return response.asJsoup().select("script:containsData(MainFunction)").first().data() + private fun directoryFromResponse(response: Response): JsonArray { + val str = response.asJsoup().select("script:containsData(MainFunction)").first().data() .substringAfter("vm.Directory = ").substringBefore("vm.GetIntValue").trim() .replace(";", " ") + return json.parseToJsonElement(str).jsonArray } override fun popularMangaParse(response: Response): MangasPage { - directory = gson.fromJson(directoryFromResponse(response)) - .sortedByDescending { it["v"].string } + directory = directoryFromResponse(response).sortedByDescending { it.getString("v") } return parseDirectory(1) } @@ -82,9 +93,9 @@ abstract class NepNep( for (i in (((page - 1) * 24)..endRange)) { mangas.add( SManga.create().apply { - title = directory[i]["s"].string - url = "/manga/${directory[i]["i"].string}" - thumbnail_url = "https://cover.nep.li/cover/${directory[i]["i"].string}.jpg" + title = directory[i].getString("s")!! + url = "/manga/${directory[i].getString("i")}" + thumbnail_url = "https://cover.nep.li/cover/${directory[i].getString("i")}.jpg" } ) } @@ -108,8 +119,7 @@ abstract class NepNep( override fun latestUpdatesRequest(page: Int): Request = popularMangaRequest(1) override fun latestUpdatesParse(response: Response): MangasPage { - directory = gson.fromJson(directoryFromResponse(response)) - .sortedByDescending { it["lt"].string } + directory = directoryFromResponse(response).sortedByDescending { it.getString("lt") } return parseDirectory(1) } @@ -131,10 +141,14 @@ abstract class NepNep( private fun searchMangaParse(response: Response, query: String, filters: FilterList): MangasPage { val trimmedQuery = query.trim() - directory = gson.fromJson(directoryFromResponse(response)) + directory = directoryFromResponse(response) .filter { - it["s"].string.contains(trimmedQuery, ignoreCase = true) or - it["al"].asJsonArray.any { altName -> altName.string.contains(trimmedQuery, ignoreCase = true) } + // Comparing query with display name + it.getString("s")!!.contains(trimmedQuery, ignoreCase = true) or + // Comparing query with list of alternate names + it.getArray("al").any { altName -> + altName.jsonPrimitive.content.contains(trimmedQuery, ignoreCase = true) + } } val genres = mutableListOf() @@ -149,20 +163,24 @@ abstract class NepNep( else -> "s" } directory = if (filter.state?.ascending != true) { - directory.sortedByDescending { it[sortBy].string } + directory.sortedByDescending { it.getString(sortBy) } } else { - directory.sortedByDescending { it[sortBy].string }.reversed() + directory.sortedByDescending { it.getString(sortBy) }.reversed() } } is SelectField -> if (filter.state != 0) directory = when (filter.name) { - "Scan Status" -> directory.filter { it["ss"].string.contains(filter.values[filter.state], ignoreCase = true) } - "Publish Status" -> directory.filter { it["ps"].string.contains(filter.values[filter.state], ignoreCase = true) } - "Type" -> directory.filter { it["t"].string.contains(filter.values[filter.state], ignoreCase = true) } - "Translation" -> directory.filter { it["o"].string.contains("yes", ignoreCase = true) } + "Scan Status" -> directory.filter { it.getString("ss")!!.contains(filter.values[filter.state], ignoreCase = true) } + "Publish Status" -> directory.filter { it.getString("ps")!!.contains(filter.values[filter.state], ignoreCase = true) } + "Type" -> directory.filter { it.getString("t")!!.contains(filter.values[filter.state], ignoreCase = true) } + "Translation" -> directory.filter { it.getString("o")!!.contains("yes", ignoreCase = true) } else -> directory } - is YearField -> if (filter.state.isNotEmpty()) directory = directory.filter { it["y"].string.contains(filter.state) } - is AuthorField -> if (filter.state.isNotEmpty()) directory = directory.filter { e -> e["a"].asJsonArray.any { it.string.contains(filter.state, ignoreCase = true) } } + is YearField -> if (filter.state.isNotEmpty()) directory = directory.filter { it.getString("y")!!.contains(filter.state) } + is AuthorField -> if (filter.state.isNotEmpty()) directory = directory.filter { e -> + e.getArray("a").any { + it.jsonPrimitive.content.contains(filter.state, ignoreCase = true) + } + } is GenreList -> filter.state.forEach { genre -> when (genre.state) { Filter.TriState.STATE_INCLUDE -> genres.add(genre.name) @@ -171,8 +189,16 @@ abstract class NepNep( } } } - if (genres.isNotEmpty()) genres.map { genre -> directory = directory.filter { e -> e["g"].asJsonArray.any { it.string.contains(genre, ignoreCase = true) } } } - if (genresNo.isNotEmpty()) genresNo.map { genre -> directory = directory.filterNot { e -> e["g"].asJsonArray.any { it.string.contains(genre, ignoreCase = true) } } } + if (genres.isNotEmpty()) genres.map { genre -> + directory = directory.filter { e -> + e.getArray("g").any { it.jsonPrimitive.content.contains(genre, ignoreCase = true) } + } + } + if (genresNo.isNotEmpty()) genresNo.map { genre -> + directory = directory.filterNot { e -> + e.getArray("g").any { it.jsonPrimitive.content.contains(genre, ignoreCase = true) } + } + } return parseDirectory(1) } @@ -206,7 +232,7 @@ abstract class NepNep( // add alternative name to manga description val altName = "Alternative Name: " info.select("li.list-group-item:has(span:contains(Alter))").firstOrNull()?.ownText()?.let { - if (it.isEmpty().not() && it !="N/A") { + if (it.isEmpty().not() && it != "N/A") { description += when { description!!.isEmpty() -> altName + it else -> "\n\n$altName" + it @@ -242,10 +268,14 @@ abstract class NepNep( private val chapterImageRegex = Regex("""^0+""") private fun chapterImage(e: String, cleanString: Boolean = false): String { + // cleanString will result in an empty string if chapter number is 0, hence the else if below val a = e.substring(1, e.length - 1).let { if (cleanString) it.replace(chapterImageRegex, "") else it } + // If b is not zero, indicates chapter has decimal numbering val b = e.substring(e.length - 1).toInt() - return if (b == 0) { + return if (b == 0 && a.isNotEmpty()) { a + } else if (b == 0 && a.isEmpty()) { + "0" } else { "$a.$b" } @@ -255,13 +285,13 @@ abstract class NepNep( val vmChapters = response.asJsoup().select("script:containsData(MainFunction)").first().data() .substringAfter("vm.Chapters = ").substringBefore(";") - return gson.fromJson(vmChapters).map { json -> - val indexChapter = json["Chapter"].string + return json.parseToJsonElement(vmChapters).jsonArray.map { json -> + val indexChapter = json.getString("Chapter")!! SChapter.create().apply { - name = json["ChapterName"].nullString.let { if (it.isNullOrEmpty()) "${json["Type"].string} ${chapterImage(indexChapter, true)}" else it } + name = json.getString("ChapterName").let { if (it.isNullOrEmpty()) "${json.getString("Type")} ${chapterImage(indexChapter, true)}" else it } url = "/read-online/" + response.request.url.toString().substringAfter("/manga/") + chapterURLEncode(indexChapter) date_upload = try { - json["Date"].nullString?.let { dateFormat.parse("$it +0600")?.time } ?: 0 + json.getString("Date").let { dateFormat.parse("$it +0600")?.time } ?: 0 } catch (_: Exception) { 0L } @@ -274,24 +304,24 @@ abstract class NepNep( override fun pageListParse(response: Response): List { val document = response.asJsoup() val script = document.select("script:containsData(MainFunction)").first().data() - val curChapter = gson.fromJson(script.substringAfter("vm.CurChapter = ").substringBefore(";")) + val curChapter = json.parseToJsonElement(script.substringAfter("vm.CurChapter = ").substringBefore(";")).jsonObject - val pageTotal = curChapter["Page"].string.toInt() + val pageTotal = curChapter.getString("Page")!!.toInt() val host = "https://" + - script - .substringAfter("vm.CurPathName = \"", "") - .substringBefore("\"") - .also { - if (it.isEmpty()) - throw Exception("$name is overloaded and blocking Tachiyomi right now. Wait for unblock.") - } + script + .substringAfter("vm.CurPathName = \"", "") + .substringBefore("\"") + .also { + if (it.isEmpty()) + throw Exception("$name is overloaded and blocking Tachiyomi right now. Wait for unblock.") + } val titleURI = script.substringAfter("vm.IndexName = \"").substringBefore("\"") - val seasonURI = curChapter["Directory"].string + val seasonURI = curChapter.getString("Directory")!! .let { if (it.isEmpty()) "" else "$it/" } val path = "$host/manga/$titleURI/$seasonURI" - val chNum = chapterImage(curChapter["Chapter"].string) + val chNum = chapterImage(curChapter.getString("Chapter")!!) return IntRange(1, pageTotal).mapIndexed { i, _ -> val imageNum = (i + 1).toString().let { "000$it" }.let { it.substring(it.length - 3) } @@ -362,4 +392,4 @@ abstract class NepNep( Genre("Yaoi"), Genre("Yuri") ) -} +} \ No newline at end of file diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/nepnep/NepNepGenerator.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/nepnep/NepNepGenerator.kt index ff45fcf79..f074dba5b 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/nepnep/NepNepGenerator.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/nepnep/NepNepGenerator.kt @@ -9,7 +9,7 @@ class NepNepGenerator : ThemeSourceGenerator { override val themeClass = "NepNep" - override val baseVersionCode: Int = 4 + override val baseVersionCode: Int = 5 override val sources = listOf( SingleLang("MangaSee", "https://mangasee123.com", "en", overrideVersionCode = 20),