Replace org.json with kotlinx.serialization in some sources (#9569)
* Replace org.json in MeDocTruyenTranh. * Replace org.json in Kuaikanmanhua. * Replace org.json in QiXiManhua. * Replace org.json in Desu.
This commit is contained in:
parent
d0e8f185ab
commit
fd927c254d
|
@ -1,11 +1,12 @@
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
|
apply plugin: 'kotlinx-serialization'
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
extName = 'Desu'
|
extName = 'Desu'
|
||||||
pkgNameSuffix = 'ru.desu'
|
pkgNameSuffix = 'ru.desu'
|
||||||
extClass = '.Desu'
|
extClass = '.Desu'
|
||||||
extVersionCode = 12
|
extVersionCode = 13
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
apply from: "$rootDir/common.gradle"
|
||||||
|
|
|
@ -9,12 +9,20 @@ import eu.kanade.tachiyomi.source.model.Page
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.JsonObject
|
||||||
|
import kotlinx.serialization.json.float
|
||||||
|
import kotlinx.serialization.json.floatOrNull
|
||||||
|
import kotlinx.serialization.json.int
|
||||||
|
import kotlinx.serialization.json.jsonArray
|
||||||
|
import kotlinx.serialization.json.jsonObject
|
||||||
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
|
import kotlinx.serialization.json.long
|
||||||
import okhttp3.Headers
|
import okhttp3.Headers
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import org.json.JSONArray
|
|
||||||
import org.json.JSONObject
|
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
|
||||||
class Desu : HttpSource() {
|
class Desu : HttpSource() {
|
||||||
|
@ -26,31 +34,34 @@ class Desu : HttpSource() {
|
||||||
|
|
||||||
override val supportsLatest = true
|
override val supportsLatest = true
|
||||||
|
|
||||||
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
override fun headersBuilder() = Headers.Builder().apply {
|
override fun headersBuilder() = Headers.Builder().apply {
|
||||||
add("User-Agent", "Tachiyomi")
|
add("User-Agent", "Tachiyomi")
|
||||||
add("Referer", baseUrl)
|
add("Referer", baseUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun mangaPageFromJSON(json: String, next: Boolean): MangasPage {
|
private fun mangaPageFromJSON(jsonStr: String, next: Boolean): MangasPage {
|
||||||
val arr = JSONArray(json)
|
val mangaList = json.parseToJsonElement(jsonStr).jsonArray
|
||||||
val ret = ArrayList<SManga>(arr.length())
|
.map {
|
||||||
for (i in 0 until arr.length()) {
|
|
||||||
val obj = arr.getJSONObject(i)
|
|
||||||
ret.add(
|
|
||||||
SManga.create().apply {
|
SManga.create().apply {
|
||||||
mangaFromJSON(obj, false)
|
mangaFromJSON(it.jsonObject, false)
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
}
|
|
||||||
return MangasPage(ret, next)
|
return MangasPage(mangaList, next)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun SManga.mangaFromJSON(obj: JSONObject, chapter: Boolean) {
|
private fun SManga.mangaFromJSON(obj: JsonObject, chapter: Boolean) {
|
||||||
val id = obj.getInt("id")
|
val id = obj["id"]!!.jsonPrimitive.int
|
||||||
|
|
||||||
url = "/$id"
|
url = "/$id"
|
||||||
title = obj.getString("name").split(" / ").first()
|
title = obj["name"]!!.jsonPrimitive.content
|
||||||
thumbnail_url = obj.getJSONObject("image").getString("original")
|
.split(" / ")
|
||||||
val ratingValue = obj.getString("score").toFloat()
|
.first()
|
||||||
|
thumbnail_url = obj["image"]!!.jsonObject["original"]!!.jsonPrimitive.content
|
||||||
|
|
||||||
|
val ratingValue = obj["score"]!!.jsonPrimitive.floatOrNull ?: 0F
|
||||||
val ratingStar = when {
|
val ratingStar = when {
|
||||||
ratingValue > 9.5 -> "★★★★★"
|
ratingValue > 9.5 -> "★★★★★"
|
||||||
ratingValue > 8.5 -> "★★★★✬"
|
ratingValue > 8.5 -> "★★★★✬"
|
||||||
|
@ -64,14 +75,13 @@ class Desu : HttpSource() {
|
||||||
ratingValue > 0.5 -> "✬☆☆☆☆"
|
ratingValue > 0.5 -> "✬☆☆☆☆"
|
||||||
else -> "☆☆☆☆☆"
|
else -> "☆☆☆☆☆"
|
||||||
}
|
}
|
||||||
val rawAgeValue = obj.getString("adult")
|
|
||||||
val rawAgeStop = when (rawAgeValue) {
|
val rawAgeStop = when (obj["adult"]!!.jsonPrimitive.int) {
|
||||||
"1" -> "18+"
|
1 -> "18+"
|
||||||
else -> "0+"
|
else -> "0+"
|
||||||
}
|
}
|
||||||
|
|
||||||
val rawTypeValue = obj.getString("kind")
|
val rawTypeStr = when (obj["kind"]!!.jsonPrimitive.content) {
|
||||||
val rawTypeStr = when (rawTypeValue) {
|
|
||||||
"manga" -> "Манга"
|
"manga" -> "Манга"
|
||||||
"manhwa" -> "Манхва"
|
"manhwa" -> "Манхва"
|
||||||
"manhua" -> "Маньхуа"
|
"manhua" -> "Маньхуа"
|
||||||
|
@ -81,21 +91,32 @@ class Desu : HttpSource() {
|
||||||
}
|
}
|
||||||
|
|
||||||
var altName = ""
|
var altName = ""
|
||||||
if (obj.getString("synonyms").isNotEmpty() && obj.getString("synonyms") != "null") {
|
|
||||||
altName = "Альтернативные названия:\n" + obj.getString("synonyms").replace("|", " / ") + "\n\n"
|
if (obj["synonyms"]?.jsonPrimitive?.content.orEmpty().isNotEmpty()) {
|
||||||
|
altName = "Альтернативные названия:\n" +
|
||||||
|
obj["synonyms"]!!.jsonPrimitive.content
|
||||||
|
.replace("|", " / ") +
|
||||||
|
"\n\n"
|
||||||
}
|
}
|
||||||
description = obj.getString("russian") + "\n" + ratingStar + " " + ratingValue + " (голосов: " + obj.getString("score_users") + ")\n" + altName + obj.getString("description")
|
|
||||||
|
description = obj["russian"]!!.jsonPrimitive.content + "\n" +
|
||||||
|
ratingStar + " " + ratingValue +
|
||||||
|
" (голосов: " +
|
||||||
|
obj["score_users"]!!.jsonPrimitive.int +
|
||||||
|
")\n" + altName +
|
||||||
|
obj["description"]!!.jsonPrimitive.content
|
||||||
|
|
||||||
genre = if (chapter) {
|
genre = if (chapter) {
|
||||||
val jsonArray = obj.getJSONArray("genres")
|
obj["genres"]!!.jsonArray
|
||||||
val genreList = mutableListOf<String>()
|
.map { it.jsonObject["russian"]!!.jsonPrimitive.content }
|
||||||
for (i in 0 until jsonArray.length()) {
|
.plusElement(rawTypeStr)
|
||||||
genreList.add(jsonArray.getJSONObject(i).getString("russian"))
|
.plusElement(rawAgeStop)
|
||||||
}
|
.joinToString()
|
||||||
genreList.plusElement(rawTypeStr).plusElement(rawAgeStop).joinToString()
|
|
||||||
} else {
|
} else {
|
||||||
obj.getString("genres") + ", " + rawTypeStr + ", " + rawAgeStop
|
obj["genres"]!!.jsonPrimitive.content + ", " + rawTypeStr + ", " + rawAgeStop
|
||||||
}
|
}
|
||||||
status = when (obj.getString("status")) {
|
|
||||||
|
status = when (obj["status"]!!.jsonPrimitive.content) {
|
||||||
"ongoing" -> SManga.ONGOING
|
"ongoing" -> SManga.ONGOING
|
||||||
"released" -> SManga.COMPLETED
|
"released" -> SManga.COMPLETED
|
||||||
"copyright" -> SManga.LICENSED
|
"copyright" -> SManga.LICENSED
|
||||||
|
@ -103,11 +124,13 @@ class Desu : HttpSource() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int) = GET("$baseUrl$API_URL/?limit=50&order=popular&page=$page")
|
override fun popularMangaRequest(page: Int) =
|
||||||
|
GET("$baseUrl$API_URL/?limit=50&order=popular&page=$page")
|
||||||
|
|
||||||
override fun popularMangaParse(response: Response) = searchMangaParse(response)
|
override fun popularMangaParse(response: Response) = searchMangaParse(response)
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl$API_URL/?limit=50&order=updated&page=$page")
|
override fun latestUpdatesRequest(page: Int) =
|
||||||
|
GET("$baseUrl$API_URL/?limit=50&order=updated&page=$page")
|
||||||
|
|
||||||
override fun latestUpdatesParse(response: Response): MangasPage = searchMangaParse(response)
|
override fun latestUpdatesParse(response: Response): MangasPage = searchMangaParse(response)
|
||||||
|
|
||||||
|
@ -136,12 +159,13 @@ class Desu : HttpSource() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun searchMangaParse(response: Response): MangasPage {
|
override fun searchMangaParse(response: Response): MangasPage {
|
||||||
val res = response.body!!.string()
|
val res = json.parseToJsonElement(response.body!!.string()).jsonObject
|
||||||
val obj = JSONObject(res).getJSONArray("response")
|
val obj = res["response"]!!.jsonArray
|
||||||
val nav = JSONObject(res).getJSONObject("pageNavParams")
|
val nav = res["pageNavParams"]!!.jsonObject
|
||||||
val count = nav.getInt("count")
|
val count = nav["count"]!!.jsonPrimitive.int
|
||||||
val limit = nav.getInt("limit")
|
val limit = nav["limit"]!!.jsonPrimitive.int
|
||||||
val page = nav.getInt("page")
|
val page = nav["page"]!!.jsonPrimitive.int
|
||||||
|
|
||||||
return mangaPageFromJSON(obj.toString(), count > page * limit)
|
return mangaPageFromJSON(obj.toString(), count > page * limit)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,53 +186,56 @@ class Desu : HttpSource() {
|
||||||
return GET(baseUrl + "/manga" + manga.url, headers)
|
return GET(baseUrl + "/manga" + manga.url, headers)
|
||||||
}
|
}
|
||||||
override fun mangaDetailsParse(response: Response) = SManga.create().apply {
|
override fun mangaDetailsParse(response: Response) = SManga.create().apply {
|
||||||
val obj = JSONObject(response.body!!.string()).getJSONObject("response")
|
val obj = json.parseToJsonElement(response.body!!.string())
|
||||||
|
.jsonObject["response"]!!
|
||||||
|
.jsonObject
|
||||||
|
|
||||||
mangaFromJSON(obj, true)
|
mangaFromJSON(obj, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
override fun chapterListParse(response: Response): List<SChapter> {
|
||||||
val obj = JSONObject(response.body!!.string()).getJSONObject("response")
|
val obj = json.parseToJsonElement(response.body!!.string())
|
||||||
val ret = ArrayList<SChapter>()
|
.jsonObject["response"]!!
|
||||||
|
.jsonObject
|
||||||
|
|
||||||
val cid = obj.getInt("id")
|
val cid = obj["id"]!!.jsonPrimitive.int
|
||||||
|
|
||||||
val arr = obj.getJSONObject("chapters").getJSONArray("list")
|
return obj["chapters"]!!.jsonObject["list"]!!.jsonArray.map {
|
||||||
for (i in 0 until arr.length()) {
|
val chapterObj = it.jsonObject
|
||||||
val obj2 = arr.getJSONObject(i)
|
val ch = chapterObj["ch"]!!.jsonPrimitive.float
|
||||||
ret.add(
|
val fullNumStr = "${chapterObj["vol"]!!.jsonPrimitive.int} . Глава $ch"
|
||||||
SChapter.create().apply {
|
val title = chapterObj["title"]?.jsonPrimitive?.content.orEmpty()
|
||||||
val ch = obj2.getString("ch")
|
|
||||||
val fullnumstr = obj2.getString("vol") + ". " + "Глава " + ch
|
SChapter.create().apply {
|
||||||
val title = if (obj2.getString("title") == "null") "" else obj2.getString("title")
|
name = if (title.isEmpty()) {
|
||||||
name = if (title.isEmpty()) {
|
fullNumStr
|
||||||
fullnumstr
|
} else {
|
||||||
} else {
|
"$fullNumStr: $title"
|
||||||
"$fullnumstr: $title"
|
|
||||||
}
|
|
||||||
val id = obj2.getString("id")
|
|
||||||
url = "/$cid/chapter/$id"
|
|
||||||
chapter_number = ch.toFloat()
|
|
||||||
date_upload = obj2.getLong("date") * 1000
|
|
||||||
}
|
}
|
||||||
)
|
url = "/$cid/chapter/${chapterObj["id"]!!.jsonPrimitive.int}"
|
||||||
|
chapter_number = ch
|
||||||
|
date_upload = chapterObj["date"]!!.jsonPrimitive.long * 1000L
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun chapterListRequest(manga: SManga): Request {
|
override fun chapterListRequest(manga: SManga): Request {
|
||||||
return GET(baseUrl + API_URL + manga.url, headers)
|
return GET(baseUrl + API_URL + manga.url, headers)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pageListRequest(chapter: SChapter): Request {
|
override fun pageListRequest(chapter: SChapter): Request {
|
||||||
return GET(baseUrl + API_URL + chapter.url, headers)
|
return GET(baseUrl + API_URL + chapter.url, headers)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pageListParse(response: Response): List<Page> {
|
override fun pageListParse(response: Response): List<Page> {
|
||||||
val obj = JSONObject(response.body!!.string()).getJSONObject("response")
|
val obj = json.parseToJsonElement(response.body!!.string())
|
||||||
val pages = obj.getJSONObject("pages")
|
.jsonObject["response"]!!
|
||||||
val list = pages.getJSONArray("list")
|
.jsonObject
|
||||||
val ret = ArrayList<Page>(list.length())
|
|
||||||
for (i in 0 until list.length()) {
|
return obj["pages"]!!.jsonObject["list"]!!.jsonArray
|
||||||
ret.add(Page(i, "", list.getJSONObject(i).getString("img")))
|
.mapIndexed { i, jsonEl ->
|
||||||
}
|
Page(i, "", jsonEl.jsonObject["img"]!!.jsonPrimitive.content)
|
||||||
return ret
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(response: Response) =
|
override fun imageUrlParse(response: Response) =
|
||||||
|
@ -236,10 +263,6 @@ class Desu : HttpSource() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
companion object {
|
|
||||||
const val PREFIX_SLUG_SEARCH = "slug:"
|
|
||||||
private const val API_URL = "/manga/api"
|
|
||||||
}
|
|
||||||
|
|
||||||
private class OrderBy : Filter.Select<String>(
|
private class OrderBy : Filter.Select<String>(
|
||||||
"Сортировка",
|
"Сортировка",
|
||||||
|
@ -247,10 +270,13 @@ class Desu : HttpSource() {
|
||||||
)
|
)
|
||||||
|
|
||||||
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Жанр", genres)
|
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Жанр", genres)
|
||||||
|
|
||||||
private class TypeList(types: List<Type>) : Filter.Group<Type>("Тип", types)
|
private class TypeList(types: List<Type>) : Filter.Group<Type>("Тип", types)
|
||||||
|
|
||||||
private class Type(name: String, val id: String) : Filter.CheckBox(name)
|
private class Type(name: String, val id: String) : Filter.CheckBox(name)
|
||||||
|
|
||||||
private class Genre(name: String, val id: String) : Filter.CheckBox(name)
|
private class Genre(name: String, val id: String) : Filter.CheckBox(name)
|
||||||
|
|
||||||
override fun getFilterList() = FilterList(
|
override fun getFilterList() = FilterList(
|
||||||
OrderBy(),
|
OrderBy(),
|
||||||
TypeList(getTypeList()),
|
TypeList(getTypeList()),
|
||||||
|
@ -312,4 +338,10 @@ class Desu : HttpSource() {
|
||||||
Genre("Юри", "Yuri"),
|
Genre("Юри", "Yuri"),
|
||||||
Genre("Яой", "Yaoi")
|
Genre("Яой", "Yaoi")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val PREFIX_SLUG_SEARCH = "slug:"
|
||||||
|
|
||||||
|
private const val API_URL = "/manga/api"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
|
apply plugin: 'kotlinx-serialization'
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
extName = 'MeDocTruyenTranh'
|
extName = 'MeDocTruyenTranh'
|
||||||
pkgNameSuffix = 'vi.medoctruyentranh'
|
pkgNameSuffix = 'vi.medoctruyentranh'
|
||||||
extClass = '.MeDocTruyenTranh'
|
extClass = '.MeDocTruyenTranh'
|
||||||
extVersionCode = 4
|
extVersionCode = 5
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
apply from: "$rootDir/common.gradle"
|
||||||
|
|
|
@ -8,12 +8,15 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.jsonArray
|
||||||
|
import kotlinx.serialization.json.jsonObject
|
||||||
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import org.json.JSONArray
|
|
||||||
import org.json.JSONObject
|
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
|
@ -29,6 +32,8 @@ class MeDocTruyenTranh : ParsedHttpSource() {
|
||||||
|
|
||||||
override val client = network.cloudflareClient
|
override val client = network.cloudflareClient
|
||||||
|
|
||||||
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
override fun popularMangaSelector() = "div.classifyList a"
|
override fun popularMangaSelector() = "div.classifyList a"
|
||||||
|
|
||||||
override fun searchMangaSelector() = ".listCon a"
|
override fun searchMangaSelector() = ".listCon a"
|
||||||
|
@ -37,37 +42,24 @@ class MeDocTruyenTranh : ParsedHttpSource() {
|
||||||
return GET("$baseUrl/tim-truyen/toan-bo" + if (page > 1) "/$page" else "", headers)
|
return GET("$baseUrl/tim-truyen/toan-bo" + if (page > 1) "/$page" else "", headers)
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <reified T, R> JSONArray.mapJSONArray(transform: (Int, T) -> R): List<R> {
|
|
||||||
val list = mutableListOf<R>()
|
|
||||||
for (i in 0 until this.length()) {
|
|
||||||
list.add(transform(i, this[i] as T))
|
|
||||||
}
|
|
||||||
return list
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun JSONArray.flatten(): JSONArray {
|
|
||||||
val list = mutableListOf<Any>()
|
|
||||||
for (i in 0 until this.length()) {
|
|
||||||
val childArray = this[i] as JSONArray
|
|
||||||
for (j in 0 until childArray.length()) {
|
|
||||||
list.add(childArray[j])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return JSONArray(list)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun popularMangaParse(response: Response): MangasPage {
|
override fun popularMangaParse(response: Response): MangasPage {
|
||||||
val document = response.asJsoup()
|
val document = response.asJsoup()
|
||||||
|
|
||||||
// trying to build URLs from this JSONObject could cause issues but we need it to get thumbnails
|
// trying to build URLs from this JSONObject could cause issues but we need it to get thumbnails
|
||||||
val titleCoverMap = JSONObject(document.select("script#__NEXT_DATA__").first().data())
|
val nextData = document.select("script#__NEXT_DATA__").first()
|
||||||
.getJSONObject("props")
|
.let { json.parseToJsonElement(it.data()).jsonObject }
|
||||||
.getJSONObject("pageProps")
|
|
||||||
.getJSONObject("initialState")
|
val titleCoverMap = nextData["props"]!!
|
||||||
.getJSONObject("classify")
|
.jsonObject["pageProps"]!!
|
||||||
.getJSONArray("comics")
|
.jsonObject["initialState"]!!
|
||||||
.mapJSONArray { _, jsonObject: JSONObject ->
|
.jsonObject["classify"]!!
|
||||||
Pair(jsonObject.getString("title"), jsonObject.getString("coverimg"))
|
.jsonObject["comics"]!!
|
||||||
|
.jsonArray
|
||||||
|
.map {
|
||||||
|
Pair(
|
||||||
|
it.jsonObject["title"]!!.jsonPrimitive.content,
|
||||||
|
it.jsonObject["coverimg"]!!.jsonPrimitive.content
|
||||||
|
)
|
||||||
}
|
}
|
||||||
.toMap()
|
.toMap()
|
||||||
|
|
||||||
|
@ -79,6 +71,7 @@ class MeDocTruyenTranh : ParsedHttpSource() {
|
||||||
|
|
||||||
return MangasPage(mangas, document.select(popularMangaNextPageSelector()) != null)
|
return MangasPage(mangas, document.select(popularMangaNextPageSelector()) != null)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||||
return GET("$baseUrl/search/$query", headers)
|
return GET("$baseUrl/search/$query", headers)
|
||||||
}
|
}
|
||||||
|
@ -108,26 +101,24 @@ class MeDocTruyenTranh : ParsedHttpSource() {
|
||||||
|
|
||||||
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
|
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
|
||||||
|
|
||||||
override fun mangaDetailsParse(document: Document): SManga {
|
override fun mangaDetailsParse(document: Document): SManga = SManga.create().apply {
|
||||||
val manga = SManga.create()
|
|
||||||
val jsonData = JSONObject(document.select("#__NEXT_DATA__").first()!!.data())
|
val nextData = document.select("script#__NEXT_DATA__").first()
|
||||||
val mangaDetail = jsonData
|
.let { json.parseToJsonElement(it.data()).jsonObject }
|
||||||
.getJSONObject("props")
|
|
||||||
.getJSONObject("pageProps")
|
val mangaDetail = nextData["props"]!!
|
||||||
.getJSONObject("initialState")
|
.jsonObject["pageProps"]!!
|
||||||
.getJSONObject("detail")
|
.jsonObject["initialState"]!!
|
||||||
.getJSONObject("story_item")
|
.jsonObject["detail"]!!
|
||||||
manga.title = mangaDetail.getString("title")
|
.jsonObject["story_item"]!!
|
||||||
manga.author = mangaDetail.getJSONArray("author_list").getString(0)
|
.jsonObject
|
||||||
val genres = mutableListOf<String>()
|
|
||||||
for (i in 0 until mangaDetail.getJSONArray("category_list").length()) {
|
title = mangaDetail["title"]!!.jsonPrimitive.content
|
||||||
genres.add(mangaDetail.getJSONArray("category_list").getString(i))
|
author = mangaDetail["author_list"]!!.jsonArray.joinToString { it.jsonPrimitive.content }
|
||||||
}
|
genre = mangaDetail["category_list"]!!.jsonArray.joinToString { it.jsonPrimitive.content }
|
||||||
manga.genre = genres.joinToString(", ")
|
description = mangaDetail["summary"]!!.jsonPrimitive.content
|
||||||
manga.description = mangaDetail.getString("summary")
|
status = parseStatus(mangaDetail["is_updating"]!!.jsonPrimitive.content)
|
||||||
manga.status = parseStatus(mangaDetail.getString("is_updating"))
|
thumbnail_url = mangaDetail["coverimg"]!!.jsonPrimitive.content
|
||||||
manga.thumbnail_url = mangaDetail.getString("coverimg")
|
|
||||||
return manga
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseStatus(status: String) = when {
|
private fun parseStatus(status: String) = when {
|
||||||
|
@ -139,18 +130,23 @@ class MeDocTruyenTranh : ParsedHttpSource() {
|
||||||
override fun chapterListSelector() = "div.chapters a"
|
override fun chapterListSelector() = "div.chapters a"
|
||||||
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
override fun chapterListParse(response: Response): List<SChapter> {
|
||||||
return JSONObject(response.asJsoup().select("script#__NEXT_DATA__").first().data())
|
val nextData = response.asJsoup().select("script#__NEXT_DATA__").first()
|
||||||
.getJSONObject("props")
|
.let { json.parseToJsonElement(it.data()).jsonObject }
|
||||||
.getJSONObject("pageProps")
|
|
||||||
.getJSONObject("initialState")
|
return nextData["props"]!!
|
||||||
.getJSONObject("detail")
|
.jsonObject["pageProps"]!!
|
||||||
.getJSONArray("story_chapters")
|
.jsonObject["initialState"]!!
|
||||||
.flatten()
|
.jsonObject["detail"]!!
|
||||||
.mapJSONArray { _, jsonObject: JSONObject ->
|
.jsonObject["story_chapters"]!!
|
||||||
|
.jsonArray
|
||||||
|
.flatMap { it.jsonArray }
|
||||||
|
.map {
|
||||||
|
val chapterObj = it.jsonObject
|
||||||
|
|
||||||
SChapter.create().apply {
|
SChapter.create().apply {
|
||||||
name = jsonObject.getString("title")
|
name = chapterObj["title"]!!.jsonPrimitive.content
|
||||||
setUrlWithoutDomain("${response.request.url}/${jsonObject.getString("chapter_index")}")
|
date_upload = parseChapterDate(chapterObj["time"]!!.jsonPrimitive.content)
|
||||||
date_upload = parseChapterDate(jsonObject.getString("time"))
|
setUrlWithoutDomain("${response.request.url}/${chapterObj["chapter_index"]!!.jsonPrimitive.content}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.reversed()
|
.reversed()
|
||||||
|
@ -166,15 +162,19 @@ class MeDocTruyenTranh : ParsedHttpSource() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pageListParse(document: Document): List<Page> {
|
override fun pageListParse(document: Document): List<Page> {
|
||||||
return JSONObject(document.select("#__NEXT_DATA__").first()?.data() ?: "{}")
|
val nextData = document.select("script#__NEXT_DATA__").firstOrNull()
|
||||||
.getJSONObject("props")
|
?.let { json.parseToJsonElement(it.data()).jsonObject }
|
||||||
.getJSONObject("pageProps")
|
?: return emptyList()
|
||||||
.getJSONObject("initialState")
|
|
||||||
.getJSONObject("read")
|
return nextData["props"]!!
|
||||||
.getJSONObject("detail_item")
|
.jsonObject["pageProps"]!!
|
||||||
.getJSONArray("elements")
|
.jsonObject["initialState"]!!
|
||||||
.mapJSONArray { i, jsonObject: JSONObject ->
|
.jsonObject["read"]!!
|
||||||
Page(i, "", jsonObject.getString("content"))
|
.jsonObject["detail_item"]!!
|
||||||
|
.jsonObject["elements"]!!
|
||||||
|
.jsonArray
|
||||||
|
.mapIndexed { i, jsonEl ->
|
||||||
|
Page(i, "", jsonEl.jsonObject["content"]!!.jsonPrimitive.content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
|
apply plugin: 'kotlinx-serialization'
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
extName = 'Kuaikanmanhua'
|
extName = 'Kuaikanmanhua'
|
||||||
pkgNameSuffix = 'zh.kuaikanmanhua'
|
pkgNameSuffix = 'zh.kuaikanmanhua'
|
||||||
extClass = '.Kuaikanmanhua'
|
extClass = '.Kuaikanmanhua'
|
||||||
extVersionCode = 5
|
extVersionCode = 6
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
apply from: "$rootDir/common.gradle"
|
||||||
|
|
|
@ -10,14 +10,20 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.JsonArray
|
||||||
|
import kotlinx.serialization.json.int
|
||||||
|
import kotlinx.serialization.json.jsonArray
|
||||||
|
import kotlinx.serialization.json.jsonObject
|
||||||
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import org.json.JSONArray
|
|
||||||
import org.json.JSONObject
|
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.Calendar
|
import java.util.Calendar
|
||||||
|
import java.util.Locale
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
class Kuaikanmanhua : HttpSource() {
|
class Kuaikanmanhua : HttpSource() {
|
||||||
|
@ -34,6 +40,8 @@ class Kuaikanmanhua : HttpSource() {
|
||||||
|
|
||||||
private val apiUrl = "https://api.kkmh.com"
|
private val apiUrl = "https://api.kkmh.com"
|
||||||
|
|
||||||
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
// Popular
|
// Popular
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int): Request {
|
override fun popularMangaRequest(page: Int): Request {
|
||||||
|
@ -42,25 +50,25 @@ class Kuaikanmanhua : HttpSource() {
|
||||||
|
|
||||||
override fun popularMangaParse(response: Response): MangasPage {
|
override fun popularMangaParse(response: Response): MangasPage {
|
||||||
val body = response.body!!.string()
|
val body = response.body!!.string()
|
||||||
val jsonList = JSONObject(body).getJSONObject("data").getJSONArray("topics")
|
val jsonList = json.parseToJsonElement(body).jsonObject["data"]!!
|
||||||
|
.jsonObject["topics"]!!
|
||||||
|
.jsonArray
|
||||||
return parseMangaJsonArray(jsonList)
|
return parseMangaJsonArray(jsonList)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseMangaJsonArray(jsonList: JSONArray, isSearch: Boolean = false): MangasPage {
|
private fun parseMangaJsonArray(jsonList: JsonArray, isSearch: Boolean = false): MangasPage {
|
||||||
val mangaList = mutableListOf<SManga>()
|
val mangaList = jsonList.map {
|
||||||
|
val mangaObj = it.jsonObject
|
||||||
|
|
||||||
for (i in 0 until jsonList.length()) {
|
SManga.create().apply {
|
||||||
val obj = jsonList.getJSONObject(i)
|
title = mangaObj["title"]!!.jsonPrimitive.content
|
||||||
mangaList.add(
|
thumbnail_url = mangaObj["vertical_image_url"]!!.jsonPrimitive.content
|
||||||
SManga.create().apply {
|
url = "/web/topic/" + mangaObj["id"]!!.jsonPrimitive.int
|
||||||
title = obj.getString("title")
|
}
|
||||||
thumbnail_url = obj.getString("vertical_image_url")
|
|
||||||
url = "/web/topic/" + obj.getInt("id")
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// KKMH does not have pages when you search
|
// KKMH does not have pages when you search
|
||||||
return MangasPage(mangaList, mangaList.size > 9 && !isSearch)
|
return MangasPage(mangaList, hasNextPage = mangaList.size > 9 && !isSearch)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Latest
|
// Latest
|
||||||
|
@ -110,12 +118,12 @@ class Kuaikanmanhua : HttpSource() {
|
||||||
|
|
||||||
override fun searchMangaParse(response: Response): MangasPage {
|
override fun searchMangaParse(response: Response): MangasPage {
|
||||||
val body = response.body!!.string()
|
val body = response.body!!.string()
|
||||||
val jsonObj = JSONObject(body).getJSONObject("data")
|
val jsonObj = json.parseToJsonElement(body).jsonObject["data"]!!.jsonObject
|
||||||
if (jsonObj.has("hit")) {
|
if (jsonObj["hit"] != null) {
|
||||||
return parseMangaJsonArray(jsonObj.getJSONArray("hit"), true)
|
return parseMangaJsonArray(jsonObj["hit"]!!.jsonArray, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
return parseMangaJsonArray(jsonObj.getJSONArray("topics"), false)
|
return parseMangaJsonArray(jsonObj["topics"]!!.jsonArray, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Details
|
// Details
|
||||||
|
@ -128,32 +136,37 @@ class Kuaikanmanhua : HttpSource() {
|
||||||
return Observable.just(sManga)
|
return Observable.just(sManga)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mangaDetailsParse(response: Response): SManga {
|
override fun mangaDetailsParse(response: Response): SManga = SManga.create().apply {
|
||||||
val data = JSONObject(response.body!!.string()).getJSONObject("data")
|
val data = json.parseToJsonElement(response.body!!.string())
|
||||||
val manga = SManga.create()
|
.jsonObject["data"]!!
|
||||||
manga.title = data.getString("title")
|
.jsonObject
|
||||||
manga.thumbnail_url = data.getString("vertical_image_url")
|
|
||||||
manga.author = data.getJSONObject("user").getString("nickname")
|
|
||||||
manga.description = data.getString("description")
|
|
||||||
manga.status = data.getInt("update_status_code")
|
|
||||||
|
|
||||||
return manga
|
title = data["title"]!!.jsonPrimitive.content
|
||||||
|
thumbnail_url = data["vertical_image_url"]!!.jsonPrimitive.content
|
||||||
|
author = data["user"]!!.jsonObject["nickname"]!!.jsonPrimitive.content
|
||||||
|
description = data["description"]!!.jsonPrimitive.content
|
||||||
|
status = data["update_status_code"]!!.jsonPrimitive.int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chapters & Pages
|
// Chapters & Pages
|
||||||
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
override fun chapterListParse(response: Response): List<SChapter> {
|
||||||
val document = response.asJsoup()
|
val document = response.asJsoup()
|
||||||
val chapters = mutableListOf<SChapter>()
|
|
||||||
val script = document.select("script:containsData(comics)").first().data()
|
val script = document.select("script:containsData(comics)").first().data()
|
||||||
val comics = JSONArray(script.substringAfter("comics:").substringBefore(",first_comic_id"))
|
val comics = script.substringAfter("comics:")
|
||||||
val variable = script.substringAfter("(function(").substringBefore("){").split(",")
|
.substringBefore(",first_comic_id")
|
||||||
val value = script.substringAfterLast("}}(").substringBefore("));").split(",")
|
.let { json.parseToJsonElement(it).jsonArray }
|
||||||
|
val variable = script.substringAfter("(function(")
|
||||||
|
.substringBefore("){")
|
||||||
|
.split(",")
|
||||||
|
val value = script.substringAfterLast("}}(")
|
||||||
|
.substringBefore("));")
|
||||||
|
.split(",")
|
||||||
|
|
||||||
document.select("div.TopicItem").forEachIndexed { index, element ->
|
return document.select("div.TopicItem")
|
||||||
chapters.add(
|
.mapIndexed { index, element ->
|
||||||
SChapter.create().apply {
|
SChapter.create().apply {
|
||||||
val idVar = comics.getJSONObject(index).getString("id")
|
val idVar = comics[index].jsonObject["id"]!!.jsonPrimitive.content
|
||||||
val id = value[variable.indexOf(idVar)]
|
val id = value[variable.indexOf(idVar)]
|
||||||
url = "/web/comic/$id"
|
url = "/web/comic/$id"
|
||||||
name = element.select("div.title > a").text()
|
name = element.select("div.title > a").text()
|
||||||
|
@ -167,11 +180,10 @@ class Kuaikanmanhua : HttpSource() {
|
||||||
} else {
|
} else {
|
||||||
"20$dateStr"
|
"20$dateStr"
|
||||||
}
|
}
|
||||||
date_upload = SimpleDateFormat("yyyy-MM-dd").parse(dateStr).time
|
date_upload = runCatching { DATE_FORMAT.parse(dateStr)?.time }
|
||||||
|
.getOrNull() ?: 0L
|
||||||
}
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
return chapters
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
|
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
|
||||||
|
@ -187,18 +199,26 @@ class Kuaikanmanhua : HttpSource() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pageListParse(response: Response): List<Page> {
|
override fun pageListParse(response: Response): List<Page> {
|
||||||
val pages = ArrayList<Page>()
|
|
||||||
val document = response.asJsoup()
|
val document = response.asJsoup()
|
||||||
val script = document.selectFirst("script:containsData(comicImages)").data()
|
val script = document.selectFirst("script:containsData(comicImages)").data()
|
||||||
val images = JSONArray(script.substringAfter("comicImages:").substringBefore("},nextComicInfo"))
|
val images = script.substringAfter("comicImages:")
|
||||||
val variable = script.substringAfter("(function(").substringBefore("){").split(",")
|
.substringBefore("},nextComicInfo")
|
||||||
val value = script.substringAfterLast("}}(").substringBefore("));").split(",")
|
.let { json.parseToJsonElement(it).jsonArray }
|
||||||
for (i in 0 until images.length()) {
|
val variable = script.substringAfter("(function(")
|
||||||
val urlVar = images.getJSONObject(i).getString("url")
|
.substringBefore("){")
|
||||||
val url = value[variable.indexOf(urlVar)].replace("\\u002F", "/").replace("\"", "")
|
.split(",")
|
||||||
pages.add(Page(i, "", url))
|
val value = script.substringAfterLast("}}(")
|
||||||
|
.substringBefore("));")
|
||||||
|
.split(",")
|
||||||
|
|
||||||
|
return images.mapIndexed { index, jsonEl ->
|
||||||
|
val urlVar = jsonEl.jsonObject["url"]!!.jsonPrimitive.content
|
||||||
|
val imageUrl = value[variable.indexOf(urlVar)]
|
||||||
|
.replace("\\u002F", "/")
|
||||||
|
.replace("\"", "")
|
||||||
|
|
||||||
|
Page(index, "", imageUrl)
|
||||||
}
|
}
|
||||||
return pages
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filters
|
// Filters
|
||||||
|
@ -256,5 +276,9 @@ class Kuaikanmanhua : HttpSource() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TOPIC_ID_SEARCH_PREFIX = "topic:"
|
const val TOPIC_ID_SEARCH_PREFIX = "topic:"
|
||||||
|
|
||||||
|
private val DATE_FORMAT by lazy {
|
||||||
|
SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
|
apply plugin: 'kotlinx-serialization'
|
||||||
|
|
||||||
ext {
|
ext {
|
||||||
extName = 'QiXiManhua'
|
extName = 'QiXiManhua'
|
||||||
pkgNameSuffix = 'zh.qiximh'
|
pkgNameSuffix = 'zh.qiximh'
|
||||||
extClass = '.Qiximh'
|
extClass = '.Qiximh'
|
||||||
extVersionCode = 2
|
extVersionCode = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
apply from: "$rootDir/common.gradle"
|
||||||
|
|
|
@ -11,19 +11,30 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.int
|
||||||
|
import kotlinx.serialization.json.jsonArray
|
||||||
|
import kotlinx.serialization.json.jsonObject
|
||||||
|
import kotlinx.serialization.json.jsonPrimitive
|
||||||
import okhttp3.FormBody
|
import okhttp3.FormBody
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import org.json.JSONArray
|
import uy.kohesive.injekt.injectLazy
|
||||||
import org.json.JSONObject
|
|
||||||
|
|
||||||
class Qiximh : HttpSource() {
|
class Qiximh : HttpSource() {
|
||||||
|
|
||||||
override val lang = "zh"
|
override val lang = "zh"
|
||||||
|
|
||||||
override val supportsLatest = true
|
override val supportsLatest = true
|
||||||
|
|
||||||
override val name = "七夕漫画"
|
override val name = "七夕漫画"
|
||||||
|
|
||||||
override val baseUrl = "http://qiximh1.com"
|
override val baseUrl = "http://qiximh1.com"
|
||||||
|
|
||||||
// This is hard limit by API
|
// This is hard limit by API
|
||||||
val maxPage = 5
|
private val maxPage = 5
|
||||||
|
|
||||||
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
// Used in Rank API
|
// Used in Rank API
|
||||||
private enum class RANKTYPE(val rankVal: Int) {
|
private enum class RANKTYPE(val rankVal: Int) {
|
||||||
|
@ -84,20 +95,19 @@ class Qiximh : HttpSource() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun commonDataProcess(origRequest: Request, responseBody: String): MangasPage {
|
private fun commonDataProcess(origRequest: Request, responseBody: String): MangasPage {
|
||||||
val jsonData = JSONArray(responseBody)
|
val jsonData = json.parseToJsonElement(responseBody).jsonArray
|
||||||
|
|
||||||
val mangaArr = mutableListOf<SManga>()
|
val mangaArr = jsonData.map {
|
||||||
|
val targetObj = it.jsonObject
|
||||||
|
|
||||||
for (i in 0 until jsonData.length()) {
|
SManga.create().apply {
|
||||||
val targetObj = jsonData.getJSONObject(i)
|
title = targetObj["name"]!!.jsonPrimitive.content
|
||||||
mangaArr.add(
|
status = SManga.UNKNOWN
|
||||||
SManga.create().apply {
|
thumbnail_url = targetObj["imgurl"]!!.jsonPrimitive.content
|
||||||
title = targetObj.get("name") as String
|
// Extension is wrongly adding the baseURL to the SManga.
|
||||||
status = SManga.UNKNOWN
|
// I kept it as it is to avoid user migrations.
|
||||||
thumbnail_url = targetObj.get("imgurl") as String
|
url = "$baseUrl/${targetObj["id"]!!.jsonPrimitive.int}"
|
||||||
url = "$baseUrl/${targetObj.get("id")}/"
|
}
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val requestBody = origRequest.body as FormBody
|
val requestBody = origRequest.body as FormBody
|
||||||
|
@ -153,36 +163,37 @@ class Qiximh : HttpSource() {
|
||||||
}
|
}
|
||||||
override fun searchMangaParse(response: Response): MangasPage {
|
override fun searchMangaParse(response: Response): MangasPage {
|
||||||
val responseBody = response.body
|
val responseBody = response.body
|
||||||
val mangaArr = mutableListOf<SManga>()
|
?: return MangasPage(emptyList(), false)
|
||||||
|
|
||||||
if (responseBody != null) {
|
val responseString = responseBody.string()
|
||||||
val responseString = responseBody.string()
|
|
||||||
if (!responseString.isNullOrEmpty()) {
|
|
||||||
if (responseString.startsWith("[")) {
|
|
||||||
// This is to process filter
|
|
||||||
return commonDataProcess(response.request, responseString)
|
|
||||||
} else {
|
|
||||||
val jsonData = JSONObject(responseString)
|
|
||||||
if (jsonData.get("msg") == "success") {
|
|
||||||
val jsonArr = jsonData.getJSONArray("search_data")
|
|
||||||
|
|
||||||
for (i in 0 until jsonArr.length()) {
|
if (responseString.isNotEmpty()) {
|
||||||
val targetObj = jsonArr.getJSONObject(i)
|
if (responseString.startsWith("[")) {
|
||||||
mangaArr.add(
|
// This is to process filter
|
||||||
SManga.create().apply {
|
return commonDataProcess(response.request, responseString)
|
||||||
title = targetObj.get("name") as String
|
} else {
|
||||||
thumbnail_url = targetObj.get("imgs") as String
|
val jsonData = json.parseToJsonElement(responseString).jsonObject
|
||||||
url = "$baseUrl/${targetObj.get("id")}/"
|
|
||||||
}
|
if (jsonData["msg"]!!.jsonPrimitive.content == "success") {
|
||||||
)
|
val mangaArr = jsonData["search_data"]!!.jsonArray.map {
|
||||||
|
val targetObj = it.jsonObject
|
||||||
|
|
||||||
|
SManga.create().apply {
|
||||||
|
title = targetObj["name"]!!.jsonPrimitive.content
|
||||||
|
thumbnail_url = targetObj["imgs"]!!.jsonPrimitive.content
|
||||||
|
// Extension is wrongly adding the baseURL to the SManga.
|
||||||
|
// I kept it as it is to avoid user migrations.
|
||||||
|
url = "$baseUrl/${targetObj["id"]!!.jsonPrimitive.int}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return MangasPage(mangaArr, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search does not have pagination
|
// Search does not have pagination
|
||||||
return MangasPage(mangaArr, false)
|
return MangasPage(emptyList(), false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter
|
// Filter
|
||||||
|
@ -247,13 +258,16 @@ class Qiximh : HttpSource() {
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
override fun chapterListParse(response: Response): List<SChapter> {
|
||||||
val document = response.asJsoup()
|
val document = response.asJsoup()
|
||||||
|
|
||||||
// API does not allow retrieve full chapter list, hence the need to parse the chapters from both HTML and API
|
// API does not allow retrieve full chapter list, hence the need to parse
|
||||||
val htmlChapters = document.select(".catalog_list.row_catalog_list a").map {
|
// the chapters from both HTML and API
|
||||||
SChapter.create().apply {
|
val chapterList = document.select(".catalog_list.row_catalog_list a")
|
||||||
name = it.text()
|
.map {
|
||||||
url = "$baseUrl${it.attr("href")}"
|
SChapter.create().apply {
|
||||||
|
name = it.text()
|
||||||
|
url = "$baseUrl${it.attr("href")}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
.toMutableList()
|
||||||
|
|
||||||
val mangaUrl = response.request.url.toString()
|
val mangaUrl = response.request.url.toString()
|
||||||
|
|
||||||
|
@ -267,22 +281,18 @@ class Qiximh : HttpSource() {
|
||||||
)
|
)
|
||||||
|
|
||||||
val inlineResponse = client.newCall(request).execute()
|
val inlineResponse = client.newCall(request).execute()
|
||||||
val jsonData = JSONArray(inlineResponse.body!!.string())
|
val jsonData = json.parseToJsonElement(inlineResponse.body!!.string()).jsonArray
|
||||||
|
|
||||||
val chapterArr = mutableListOf<SChapter>()
|
chapterList += jsonData.map {
|
||||||
chapterArr.addAll(htmlChapters)
|
val targetObj = it.jsonObject
|
||||||
|
|
||||||
for (i in 0 until jsonData.length()) {
|
SChapter.create().apply {
|
||||||
val targetObj = jsonData.getJSONObject(i)
|
name = targetObj["chaptername"]!!.jsonPrimitive.content
|
||||||
chapterArr.add(
|
url = "$mangaUrl${targetObj["chapterid"]!!.jsonPrimitive.int}.html"
|
||||||
SChapter.create().apply {
|
}
|
||||||
name = targetObj.get("chaptername") as String
|
|
||||||
url = "$mangaUrl${targetObj.get("chapterid")}.html"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return chapterArr
|
return chapterList
|
||||||
}
|
}
|
||||||
|
|
||||||
// Page
|
// Page
|
||||||
|
|
Loading…
Reference in New Issue