Migrates nepnep multisrc to kotlinx.serialization (#8494)

* Fix chapter number issue

* Migration to kotlinx.serialization
This commit is contained in:
Arraiment 2021-08-10 00:44:19 +08:00 committed by GitHub
parent 76ff5c9090
commit b98ede3e0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 79 additions and 49 deletions

View File

@ -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<JsonElement>
// 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<MangasPage> {
@ -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<JsonArray>(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<JsonArray>(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<JsonArray>(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<String>()
@ -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<JsonArray>(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<Page> {
val document = response.asJsoup()
val script = document.select("script:containsData(MainFunction)").first().data()
val curChapter = gson.fromJson<JsonElement>(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")
)
}
}

View File

@ -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),