Migrates nepnep multisrc to kotlinx.serialization (#8494)
* Fix chapter number issue * Migration to kotlinx.serialization
This commit is contained in:
parent
76ff5c9090
commit
b98ede3e0a
|
@ -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")
|
||||
)
|
||||
}
|
||||
}
|
|
@ -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),
|
||||
|
|
Loading…
Reference in New Issue