Replace usages of Gson (#10080)
This commit is contained in:
parent
1f6027dd67
commit
fa6be0f1c9
|
@ -123,25 +123,26 @@ dependencies {
|
|||
|
||||
#### Additional dependencies
|
||||
|
||||
You may find yourself needing additional functionality and wanting to add more dependencies to your `build.gradle` file. Since extensions are run within the main Tachiyomi app, you can make use of [its dependencies](https://github.com/tachiyomiorg/tachiyomi/blob/master/app/build.gradle).
|
||||
You may find yourself needing additional functionality and wanting to add more dependencies to your `build.gradle` file. Since extensions are run within the main Tachiyomi app, you can make use of [its dependencies](https://github.com/tachiyomiorg/tachiyomi/blob/master/app/build.gradle.kts).
|
||||
|
||||
For example, an extension that needs Gson could add the following:
|
||||
For example, an extension that needs coroutines, it could add the following:
|
||||
|
||||
```gradle
|
||||
dependencies {
|
||||
compileOnly 'com.google.code.gson:gson:2.8.2'
|
||||
compileOnly 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.2'
|
||||
compileOnly 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.5.2'
|
||||
}
|
||||
```
|
||||
|
||||
(Note that Gson, and several other dependencies, are already exposed to all extensions via `common.gradle`.)
|
||||
(Note that several dependencies are already exposed to all extensions via `common-dependencies.gradle`.)
|
||||
|
||||
Notice that we're using `compileOnly` instead of `implementation`, since the app already contains it. You could use `implementation` instead for a new dependency, or you prefer not to rely on whatever the main app has at the expense of app size.
|
||||
|
||||
Note that using `compileOnly` restricts you to versions that must be compatible with those used in [Tachiyomi v0.8.5+](https://github.com/tachiyomiorg/tachiyomi/blob/82141cec6e612885fef4fa70092e29e99d60adbb/app/build.gradle#L104) for proper backwards compatibility.
|
||||
Note that using `compileOnly` restricts you to versions that must be compatible with those used in [Tachiyomi v0.10.12+](https://github.com/tachiyomiorg/tachiyomi/blob/v0.10.12/app/build.gradle.kts) for proper backwards compatibility.
|
||||
|
||||
### Extension main class
|
||||
|
||||
The class which is refrenced and defined by `extClass` in `build.gradle`. This class should implement either `SourceFactory` or extend one of the `Source` implementations: `HttpSource` or `ParsedHttpSource`.
|
||||
The class which is referenced and defined by `extClass` in `build.gradle`. This class should implement either `SourceFactory` or extend one of the `Source` implementations: `HttpSource` or `ParsedHttpSource`.
|
||||
|
||||
| Class | Description |
|
||||
| ----- | ----------- |
|
||||
|
|
|
@ -5,13 +5,6 @@ import android.content.SharedPreferences
|
|||
import androidx.preference.CheckBoxPreference
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import com.github.salomonbrys.kotson.addProperty
|
||||
import com.github.salomonbrys.kotson.fromJson
|
||||
import com.github.salomonbrys.kotson.get
|
||||
import com.github.salomonbrys.kotson.set
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
|
@ -22,6 +15,20 @@ import eu.kanade.tachiyomi.source.model.Page
|
|||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.JsonPrimitive
|
||||
import kotlinx.serialization.json.boolean
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
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 kotlinx.serialization.json.put
|
||||
import kotlinx.serialization.json.putJsonArray
|
||||
import kotlinx.serialization.json.putJsonObject
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
|
@ -29,6 +36,7 @@ import okhttp3.Response
|
|||
import rx.Observable
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.util.Calendar
|
||||
|
||||
abstract class Luscious(
|
||||
|
@ -44,7 +52,7 @@ abstract class Luscious(
|
|||
|
||||
private val apiBaseUrl: String = "$baseUrl/graphql/nobatch/"
|
||||
|
||||
private val gson = Gson()
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
override val client: OkHttpClient = network.cloudflareClient
|
||||
|
||||
|
@ -86,90 +94,91 @@ abstract class Luscious(
|
|||
val contentTypeFilter = filters.findInstance<ContentTypeSelectFilter>()!!
|
||||
val albumSizeFilter = filters.findInstance<AlbumSizeSelectFilter>()!!
|
||||
val restrictGenresFilter = filters.findInstance<RestrictGenresSelectFilter>()!!
|
||||
return JsonObject().apply {
|
||||
add(
|
||||
"input",
|
||||
JsonObject().apply {
|
||||
addProperty("display", sortByFilter.selected)
|
||||
addProperty("page", page)
|
||||
add(
|
||||
"filters",
|
||||
JsonArray().apply {
|
||||
return buildJsonObject {
|
||||
putJsonObject("input") {
|
||||
put("display", sortByFilter.selected)
|
||||
put("page", page)
|
||||
putJsonArray("filters") {
|
||||
if (contentTypeFilter.selected != FILTER_VALUE_IGNORE)
|
||||
add(contentTypeFilter.toJsonObject("content_id"))
|
||||
|
||||
if (contentTypeFilter.selected != FILTER_VALUE_IGNORE)
|
||||
add(contentTypeFilter.toJsonObject("content_id"))
|
||||
if (albumTypeFilter.selected != FILTER_VALUE_IGNORE)
|
||||
add(albumTypeFilter.toJsonObject("album_type"))
|
||||
|
||||
if (albumTypeFilter.selected != FILTER_VALUE_IGNORE)
|
||||
add(albumTypeFilter.toJsonObject("album_type"))
|
||||
if (selectionFilter.selected != FILTER_VALUE_IGNORE)
|
||||
add(selectionFilter.toJsonObject("selection"))
|
||||
|
||||
if (selectionFilter.selected != FILTER_VALUE_IGNORE)
|
||||
add(selectionFilter.toJsonObject("selection"))
|
||||
if (albumSizeFilter.selected != FILTER_VALUE_IGNORE)
|
||||
add(albumSizeFilter.toJsonObject("picture_count_rank"))
|
||||
|
||||
if (albumSizeFilter.selected != FILTER_VALUE_IGNORE)
|
||||
add(albumSizeFilter.toJsonObject("picture_count_rank"))
|
||||
if (restrictGenresFilter.selected != FILTER_VALUE_IGNORE)
|
||||
add(restrictGenresFilter.toJsonObject("restrict_genres"))
|
||||
|
||||
if (restrictGenresFilter.selected != FILTER_VALUE_IGNORE)
|
||||
add(restrictGenresFilter.toJsonObject("restrict_genres"))
|
||||
|
||||
with(interestsFilter) {
|
||||
if (this.selected.isEmpty()) {
|
||||
throw Exception("Please select an Interest")
|
||||
}
|
||||
add(this.toJsonObject("audience_ids"))
|
||||
}
|
||||
|
||||
if (lusLang != FILTER_VALUE_IGNORE) {
|
||||
add(
|
||||
languagesFilter.toJsonObject("language_ids").apply {
|
||||
set("value", "+$lusLang${get("value").asString}")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (tagsFilter.state.isNotEmpty()) {
|
||||
val tags = "+${tagsFilter.state.toLowerCase()}".replace(" ", "_").replace("_,", "+").replace(",_", "+").replace(",", "+").replace("+-", "-").replace("-_", "-").trim()
|
||||
add(
|
||||
JsonObject().apply {
|
||||
addProperty("name", "tagged")
|
||||
addProperty("value", tags)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (creatorFilter.state.isNotEmpty()) {
|
||||
add(
|
||||
JsonObject().apply {
|
||||
addProperty("name", "created_by_id")
|
||||
addProperty("value", creatorFilter.state)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (favoriteFilter.state.isNotEmpty()) {
|
||||
add(
|
||||
JsonObject().apply {
|
||||
addProperty("name", "favorite_by_user_id")
|
||||
addProperty("value", favoriteFilter.state)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (genreFilter.anyNotIgnored()) {
|
||||
add(genreFilter.toJsonObject("genre_ids"))
|
||||
}
|
||||
|
||||
if (query != "") {
|
||||
add(
|
||||
JsonObject().apply {
|
||||
addProperty("name", "search_query")
|
||||
addProperty("value", query)
|
||||
}
|
||||
)
|
||||
}
|
||||
with(interestsFilter) {
|
||||
if (this.selected.isEmpty()) {
|
||||
throw Exception("Please select an Interest")
|
||||
}
|
||||
)
|
||||
add(this.toJsonObject("audience_ids"))
|
||||
}
|
||||
|
||||
if (lusLang != FILTER_VALUE_IGNORE) {
|
||||
val languageIds = languagesFilter.toJsonObject("language_ids")
|
||||
add(
|
||||
JsonObject(
|
||||
languageIds.toMutableMap().apply {
|
||||
put(
|
||||
"value",
|
||||
JsonPrimitive ("+$lusLang${languageIds["value"]!!.jsonPrimitive.content}")
|
||||
)
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
if (tagsFilter.state.isNotEmpty()) {
|
||||
val tags = "+${tagsFilter.state.toLowerCase()}".replace(" ", "_")
|
||||
.replace("_,", "+").replace(",_", "+").replace(",", "+")
|
||||
.replace("+-", "-").replace("-_", "-").trim()
|
||||
add(
|
||||
buildJsonObject {
|
||||
put("name", "tagged")
|
||||
put("value", tags)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (creatorFilter.state.isNotEmpty()) {
|
||||
add(
|
||||
buildJsonObject {
|
||||
put("name", "created_by_id")
|
||||
put("value", creatorFilter.state)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (favoriteFilter.state.isNotEmpty()) {
|
||||
add(
|
||||
buildJsonObject {
|
||||
put("name", "favorite_by_user_id")
|
||||
put("value", favoriteFilter.state)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
if (genreFilter.anyNotIgnored()) {
|
||||
add(genreFilter.toJsonObject("genre_ids"))
|
||||
}
|
||||
|
||||
if (query != "") {
|
||||
add(
|
||||
buildJsonObject {
|
||||
put("name", "search_query")
|
||||
put("value", query)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,24 +193,24 @@ abstract class Luscious(
|
|||
}
|
||||
|
||||
private fun parseAlbumListResponse(response: Response): MangasPage {
|
||||
val data = gson.fromJson<JsonObject>(response.body!!.string())
|
||||
with(data["data"]["album"]["list"]) {
|
||||
val data = json.decodeFromString<JsonObject>(response.body!!.string())
|
||||
with(data["data"]!!.jsonObject["album"]!!.jsonObject["list"]) {
|
||||
return MangasPage(
|
||||
this["items"].asJsonArray.map {
|
||||
this!!.jsonObject["items"]!!.jsonArray.map {
|
||||
SManga.create().apply {
|
||||
url = it["url"].asString
|
||||
title = it["title"].asString
|
||||
thumbnail_url = it["cover"]["url"].asString
|
||||
url = it.jsonObject["url"]!!.jsonPrimitive.content
|
||||
title = it.jsonObject["title"]!!.jsonPrimitive.content
|
||||
thumbnail_url = it.jsonObject["cover"]!!.jsonObject["url"]!!.jsonPrimitive.content
|
||||
}
|
||||
},
|
||||
this["info"]["has_next_page"].asBoolean
|
||||
this.jsonObject["info"]!!.jsonObject["has_next_page"]!!.jsonPrimitive.boolean
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildAlbumInfoRequestInput(id: String): JsonObject {
|
||||
return JsonObject().apply {
|
||||
addProperty("id", id)
|
||||
return buildJsonObject {
|
||||
put("id", id)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,34 +255,34 @@ abstract class Luscious(
|
|||
var nextPage = true
|
||||
var page = 2
|
||||
val id = response.request.url.queryParameter("variables").toString()
|
||||
.let { gson.fromJson<JsonObject>(it)["input"]["filters"].asJsonArray }
|
||||
.let { it.first { f -> f["name"].asString == "album_id" } }
|
||||
.let { it["value"].asString }
|
||||
.let { json.decodeFromString<JsonObject>(it)["input"]!!.jsonObject["filters"]!!.jsonArray }
|
||||
.let { it.first { f -> f.jsonObject["name"]!!.jsonPrimitive.content == "album_id" } }
|
||||
.let { it.jsonObject["value"]!!.jsonPrimitive.content }
|
||||
|
||||
var data = gson.fromJson<JsonObject>(response.body!!.string())
|
||||
.let { it["data"]["picture"]["list"].asJsonObject }
|
||||
var data = json.decodeFromString<JsonObject>(response.body!!.string())
|
||||
.let { it.jsonObject["data"]!!.jsonObject["picture"]!!.jsonObject["list"]!!.jsonObject }
|
||||
|
||||
while (nextPage) {
|
||||
nextPage = data["info"]["has_next_page"].asBoolean
|
||||
data["items"].asJsonArray.map {
|
||||
nextPage = data["info"]!!.jsonObject["has_next_page"]!!.jsonPrimitive.boolean
|
||||
data["items"]!!.jsonArray.map {
|
||||
val chapter = SChapter.create()
|
||||
val url = when (getResolutionPref()) {
|
||||
"-1" -> it["url_to_original"].asString
|
||||
else -> it["thumbnails"][getResolutionPref()?.toInt()!!]["url"].asString
|
||||
"-1" -> it.jsonObject["url_to_original"]!!.jsonPrimitive.content
|
||||
else -> it.jsonObject["thumbnails"]!!.jsonObject[getResolutionPref()?.toInt()!!]!!.jsonObject["url"]!!.jsonPrimitive.content
|
||||
}
|
||||
when {
|
||||
url.startsWith("//") -> chapter.url = "https:$url"
|
||||
else -> chapter.url = url
|
||||
}
|
||||
chapter.chapter_number = it["position"].asInt.toFloat()
|
||||
chapter.name = chapter.chapter_number.toInt().toString() + " - " + it["title"].asString
|
||||
chapter.date_upload = "${it["created"].asLong}000".toLong()
|
||||
chapter.chapter_number = it.jsonObject["position"]!!.jsonPrimitive.int.toFloat()
|
||||
chapter.name = chapter.chapter_number.toInt().toString() + " - " + it.jsonObject["title"]!!.jsonPrimitive.content
|
||||
chapter.date_upload = "${it.jsonObject["created"]!!.jsonPrimitive.long}000".toLong()
|
||||
chapters.add(chapter)
|
||||
}
|
||||
if (nextPage) {
|
||||
val newPage = client.newCall(GET(buildAlbumPicturesPageUrl(id, page))).execute()
|
||||
data = gson.fromJson<JsonObject>(newPage.body!!.string())
|
||||
.let { it["data"]["picture"]["list"].asJsonObject }
|
||||
data = json.decodeFromString<JsonObject>(newPage.body!!.string())
|
||||
.let { it["data"]!!.jsonObject["picture"]!!.jsonObject["list"]!!.jsonObject }
|
||||
}
|
||||
page++
|
||||
}
|
||||
|
@ -288,25 +297,17 @@ abstract class Luscious(
|
|||
// Pages
|
||||
|
||||
private fun buildAlbumPicturesRequestInput(id: String, page: Int): JsonObject {
|
||||
return JsonObject().apply {
|
||||
addProperty(
|
||||
"input",
|
||||
JsonObject().apply {
|
||||
addProperty(
|
||||
"filters",
|
||||
JsonArray().apply {
|
||||
add(
|
||||
JsonObject().apply {
|
||||
addProperty("name", "album_id")
|
||||
addProperty("value", id)
|
||||
}
|
||||
)
|
||||
}
|
||||
)
|
||||
addProperty("display", getSortPref())
|
||||
addProperty("page", page)
|
||||
return buildJsonObject {
|
||||
putJsonObject("input") {
|
||||
putJsonArray("filters") {
|
||||
add(buildJsonObject {
|
||||
put("name", "album_id")
|
||||
put("value", id)
|
||||
})
|
||||
}
|
||||
)
|
||||
put("display", getSortPref())
|
||||
put("page", page)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -324,20 +325,20 @@ abstract class Luscious(
|
|||
var nextPage = true
|
||||
var page = 2
|
||||
val id = response.request.url.queryParameter("variables").toString()
|
||||
.let { gson.fromJson<JsonObject>(it)["input"]["filters"].asJsonArray }
|
||||
.let { it.first { f -> f["name"].asString == "album_id" } }
|
||||
.let { it["value"].asString }
|
||||
.let { json.decodeFromString<JsonObject>(it)["input"]!!.jsonObject["filters"]!!.jsonArray }
|
||||
.let { it.first { f -> f.jsonObject["name"]!!.jsonPrimitive.content == "album_id" } }
|
||||
.let { it.jsonObject["value"]!!.jsonPrimitive.content }
|
||||
|
||||
var data = gson.fromJson<JsonObject>(response.body!!.string())
|
||||
.let { it["data"]["picture"]["list"].asJsonObject }
|
||||
var data = json.decodeFromString<JsonObject>(response.body!!.string())
|
||||
.let { it["data"]!!.jsonObject["picture"]!!.jsonObject["list"]!!.jsonObject }
|
||||
|
||||
while (nextPage) {
|
||||
nextPage = data["info"]["has_next_page"].asBoolean
|
||||
data["items"].asJsonArray.map {
|
||||
val index = it["position"].asInt
|
||||
nextPage = data["info"]!!.jsonObject["has_next_page"]!!.jsonPrimitive.boolean
|
||||
data["items"]!!.jsonArray.map {
|
||||
val index = it.jsonObject["position"]!!.jsonPrimitive.int
|
||||
val url = when (getResolutionPref()) {
|
||||
"-1" -> it["url_to_original"].asString
|
||||
else -> it["thumbnails"][getResolutionPref()?.toInt()!!]["url"].asString
|
||||
"-1" -> it.jsonObject["url_to_original"]!!.jsonPrimitive.content
|
||||
else -> it.jsonObject["thumbnails"]!!.jsonObject[getResolutionPref()?.toInt()!!]!!.jsonObject["url"]!!.jsonPrimitive.content
|
||||
}
|
||||
when {
|
||||
url.startsWith("//") -> pages.add(Page(index, "https:$url", "https:$url"))
|
||||
|
@ -346,8 +347,8 @@ abstract class Luscious(
|
|||
}
|
||||
if (nextPage) {
|
||||
val newPage = client.newCall(GET(buildAlbumPicturesPageUrl(id, page))).execute()
|
||||
data = gson.fromJson<JsonObject>(newPage.body!!.string())
|
||||
.let { it["data"]["picture"]["list"].asJsonObject }
|
||||
data = json.decodeFromString<JsonObject>(newPage.body!!.string())
|
||||
.let { it["data"]!!.jsonObject["picture"]!!.jsonObject["list"]!!.jsonObject }
|
||||
}
|
||||
page++
|
||||
}
|
||||
|
@ -381,12 +382,12 @@ abstract class Luscious(
|
|||
return client.newCall(GET(page.url, headers))
|
||||
.asObservableSuccess()
|
||||
.map {
|
||||
val data = gson.fromJson<JsonObject>(it.body!!.string()).let { data ->
|
||||
data["data"]["picture"]["list"].asJsonObject
|
||||
val data = json.decodeFromString<JsonObject>(it.body!!.string()).let { data ->
|
||||
data["data"]!!.jsonObject["picture"]!!.jsonObject["list"]!!.jsonObject
|
||||
}
|
||||
when (getResolutionPref()) {
|
||||
"-1" -> data["items"].asJsonArray[page.index % 50].asJsonObject["url_to_original"].asString
|
||||
else -> data["items"].asJsonArray[page.index % 50].asJsonObject["thumbnails"][getResolutionPref()?.toInt()!!]["url"].asString
|
||||
"-1" -> data["items"]!!.jsonArray[page.index % 50].jsonObject["url_to_original"]!!.jsonPrimitive.content
|
||||
else -> data["items"]!!.jsonArray[page.index % 50].jsonObject["thumbnails"]!!.jsonObject[getResolutionPref()?.toInt()!!]!!.jsonObject["url"]!!.jsonPrimitive.content
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -405,32 +406,32 @@ abstract class Luscious(
|
|||
}
|
||||
|
||||
private fun detailsParse(response: Response): SManga {
|
||||
val data = gson.fromJson<JsonObject>(response.body!!.string())
|
||||
with(data["data"]["album"]["get"]) {
|
||||
val data = json.decodeFromString<JsonObject>(response.body!!.string())
|
||||
with(data["data"]!!.jsonObject["album"]!!.jsonObject["get"]!!.jsonObject) {
|
||||
val manga = SManga.create()
|
||||
manga.url = this["url"].asString
|
||||
manga.title = this["title"].asString
|
||||
manga.thumbnail_url = this["cover"]["url"].asString
|
||||
manga.url = this["url"]!!.jsonPrimitive.content
|
||||
manga.title = this["title"]!!.jsonPrimitive.content
|
||||
manga.thumbnail_url = this["cover"]!!.jsonObject["url"]!!.jsonPrimitive.content
|
||||
manga.status = 0
|
||||
manga.description = "${this["description"].asString}\n\nPictures: ${this["number_of_pictures"].asString}\nAnimated Pictures: ${this["number_of_animated_pictures"].asString}"
|
||||
var genreList = this["language"]["title"].asString
|
||||
for ((i, _) in this["labels"].asJsonArray.withIndex()) {
|
||||
genreList = "$genreList, ${this["labels"][i].asString}"
|
||||
manga.description = "${this["description"]!!.jsonPrimitive.content}\n\nPictures: ${this["number_of_pictures"]!!.jsonPrimitive.content}\nAnimated Pictures: ${this["number_of_animated_pictures"]!!.jsonPrimitive.content}"
|
||||
var genreList = this["language"]!!.jsonObject["title"]!!.jsonPrimitive.content
|
||||
for ((i, _) in this["labels"]!!.jsonArray.withIndex()) {
|
||||
genreList = "$genreList, ${this["labels"]!!.jsonArray[i].jsonPrimitive.content}"
|
||||
}
|
||||
for ((i, _) in this["genres"].asJsonArray.withIndex()) {
|
||||
genreList = "$genreList, ${this["genres"][i]["title"].asString}"
|
||||
for ((i, _) in this["genres"]!!.jsonArray.withIndex()) {
|
||||
genreList = "$genreList, ${this["genres"]!!.jsonArray[i].jsonObject["title"]!!.jsonPrimitive.content}"
|
||||
}
|
||||
for ((i, _) in this["audiences"].asJsonArray.withIndex()) {
|
||||
genreList = "$genreList, ${this["audiences"][i]["title"].asString}"
|
||||
for ((i, _) in this["audiences"]!!.jsonArray.withIndex()) {
|
||||
genreList = "$genreList, ${this["audiences"]!!.jsonArray[i].jsonObject["title"]!!.jsonPrimitive.content}"
|
||||
}
|
||||
for ((i, _) in this["tags"].asJsonArray.withIndex()) {
|
||||
genreList = "$genreList, ${this["tags"][i]["text"].asString}"
|
||||
if (this["tags"][i]["text"].asString.contains("Artist:")) {
|
||||
manga.artist = this["tags"][i]["text"].asString.substringAfter(":").trim()
|
||||
for ((i, _) in this["tags"]!!.jsonArray.withIndex()) {
|
||||
genreList = "$genreList, ${this["tags"]!!.jsonArray[i].jsonObject["text"]!!.jsonPrimitive.content}"
|
||||
if (this["tags"]!!.jsonArray[i].jsonObject["text"]!!.jsonPrimitive.content.contains("Artist:")) {
|
||||
manga.artist = this["tags"]!!.jsonArray[i].jsonObject["text"]!!.jsonPrimitive.content.substringAfter(":").trim()
|
||||
manga.author = manga.artist
|
||||
}
|
||||
}
|
||||
genreList = "$genreList, ${this["content"]["title"].asString}"
|
||||
genreList = "$genreList, ${this["content"]!!.jsonObject["title"]!!.jsonPrimitive.content}"
|
||||
manga.genre = genreList
|
||||
|
||||
return manga
|
||||
|
@ -483,9 +484,9 @@ abstract class Luscious(
|
|||
|
||||
private fun Filter<*>.toJsonObject(key: String): JsonObject {
|
||||
val value = this.toString()
|
||||
return JsonObject().apply {
|
||||
addProperty("name", key)
|
||||
addProperty("value", value)
|
||||
return buildJsonObject {
|
||||
put("name", key)
|
||||
put("value", value)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,13 +2,6 @@ package eu.kanade.tachiyomi.multisrc.mmrcms
|
|||
|
||||
import android.annotation.SuppressLint
|
||||
import android.net.Uri
|
||||
import com.github.salomonbrys.kotson.array
|
||||
import com.github.salomonbrys.kotson.bool
|
||||
import com.github.salomonbrys.kotson.get
|
||||
import com.github.salomonbrys.kotson.string
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParser
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.source.model.Filter
|
||||
|
@ -19,11 +12,20 @@ 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.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.boolean
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
@ -33,7 +35,7 @@ abstract class MMRCMS(
|
|||
override val name: String,
|
||||
override val baseUrl: String,
|
||||
override val lang: String,
|
||||
private val sourceInfo: String = "",
|
||||
sourceInfo: String = "",
|
||||
) : HttpSource() {
|
||||
open val jsonData = if (sourceInfo == "") {
|
||||
SourceData.giveMetaData(baseUrl)
|
||||
|
@ -72,14 +74,15 @@ abstract class MMRCMS(
|
|||
*
|
||||
*
|
||||
*/
|
||||
open val jsonObject = JsonParser.parseString(jsonData) as JsonObject
|
||||
override val supportsLatest = jsonObject["supports_latest"].bool
|
||||
open val itemUrl = jsonObject["item_url"].string
|
||||
open val categoryMappings = mapToPairs(jsonObject["categories"].array)
|
||||
open var tagMappings = if (jsonObject["tags"].isJsonArray) {
|
||||
mapToPairs(jsonObject["tags"].asJsonArray)
|
||||
private val json: Json by injectLazy()
|
||||
val jsonObject = json.decodeFromString<JsonObject>(jsonData)
|
||||
override val supportsLatest = jsonObject["supports_latest"]!!.jsonPrimitive.boolean
|
||||
open val itemUrl = jsonObject["item_url"]!!.jsonPrimitive.content
|
||||
open val categoryMappings = mapToPairs(jsonObject["categories"]!!.jsonArray)
|
||||
open var tagMappings = if (jsonObject["tags"] is JsonArray) {
|
||||
mapToPairs(jsonObject["tags"]!!.jsonArray)
|
||||
} else {
|
||||
emptyList<Pair<String, String>>()
|
||||
emptyList()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -95,7 +98,7 @@ abstract class MMRCMS(
|
|||
open fun mapToPairs(array: JsonArray): List<Pair<String, String>> = array.map {
|
||||
it as JsonObject
|
||||
|
||||
it["id"].string to it["name"].string
|
||||
it["id"]!!.jsonPrimitive.content to it["name"]!!.jsonPrimitive.content
|
||||
}
|
||||
|
||||
private val itemUrlPath = Uri.parse(itemUrl).pathSegments.firstOrNull()
|
||||
|
@ -153,16 +156,16 @@ abstract class MMRCMS(
|
|||
override fun searchMangaParse(response: Response): MangasPage {
|
||||
return if (listOf("query", "q").any { it in response.request.url.queryParameterNames }) {
|
||||
// If a search query was specified, use search instead!
|
||||
val jsonArray = JsonParser.parseString(response.body!!.string()).let {
|
||||
it["suggestions"].array
|
||||
val jsonArray = json.decodeFromString<JsonObject>(response.body!!.string()).let {
|
||||
it["suggestions"]!!.jsonArray
|
||||
}
|
||||
MangasPage(
|
||||
jsonArray
|
||||
.map {
|
||||
SManga.create().apply {
|
||||
val segment = it["data"].string
|
||||
val segment = it.jsonObject["data"]!!.jsonPrimitive.content
|
||||
url = getUrlWithoutBaseUrl(itemUrl + segment)
|
||||
title = it["value"].string
|
||||
title = it.jsonObject["value"]!!.jsonPrimitive.content
|
||||
|
||||
// Guess thumbnails
|
||||
// thumbnail_url = "$baseUrl/uploads/manga/$segment/cover/cover_250x350.jpg"
|
||||
|
|
|
@ -10,7 +10,7 @@ import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
|||
import okhttp3.Headers
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
|
@ -73,7 +73,7 @@ abstract class ToomicsGlobal(
|
|||
.add("Content-Type", "application/x-www-form-urlencoded")
|
||||
.build()
|
||||
|
||||
val rbody = RequestBody.create(null, "toonData=$query&offset=0&limit=20")
|
||||
val rbody = "toonData=$query&offset=0&limit=20".toRequestBody(null)
|
||||
|
||||
return POST("$baseUrl/$siteLang/webtoon/ajax_search", newHeaders, rbody)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlinx-serialization'
|
||||
|
||||
ext {
|
||||
extName = 'GMANGA'
|
||||
|
|
|
@ -1,13 +1,6 @@
|
|||
package eu.kanade.tachiyomi.extension.ar.gmanga
|
||||
|
||||
import androidx.preference.PreferenceScreen
|
||||
import com.github.salomonbrys.kotson.fromJson
|
||||
import com.github.salomonbrys.kotson.get
|
||||
import com.github.salomonbrys.kotson.nullString
|
||||
import com.github.salomonbrys.kotson.toJsonArray
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import eu.kanade.tachiyomi.extension.ar.gmanga.GmangaPreferences.Companion.PREF_CHAPTER_LISTING
|
||||
import eu.kanade.tachiyomi.extension.ar.gmanga.GmangaPreferences.Companion.PREF_CHAPTER_LISTING_SHOW_POPULAR
|
||||
import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
|
||||
|
@ -21,12 +14,24 @@ 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.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.contentOrNull
|
||||
import kotlinx.serialization.json.float
|
||||
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.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.Response
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
|
||||
class Gmanga : ConfigurableSource, HttpSource() {
|
||||
|
||||
|
@ -40,7 +45,7 @@ class Gmanga : ConfigurableSource, HttpSource() {
|
|||
|
||||
override val supportsLatest: Boolean = true
|
||||
|
||||
private val gson = Gson()
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
private val preferences = GmangaPreferences(id)
|
||||
|
||||
|
@ -67,18 +72,18 @@ class Gmanga : ConfigurableSource, HttpSource() {
|
|||
|
||||
val chapters: List<JsonArray> = buildList {
|
||||
val allChapters: ArrayList<JsonArray> = ArrayList()
|
||||
data["rows"][0]["rows"].asJsonArray.forEach { release ->
|
||||
val chapter = data["rows"][2]["rows"].asJsonArray.filter { it[0] == release[4] }.toJsonArray()
|
||||
chapter.asJsonArray.forEach { release.asJsonArray.addAll(it.asJsonArray) }
|
||||
val team = data["rows"][1]["rows"].asJsonArray.filter { it[0] == release[5] }.toJsonArray()
|
||||
team.asJsonArray.forEach { release.asJsonArray.addAll(it.asJsonArray) }
|
||||
allChapters.add(release.asJsonArray)
|
||||
data["rows"]!!.jsonArray[0].jsonObject["rows"]!!.jsonArray.forEach { release ->
|
||||
val chapter = data["rows"]!!.jsonArray[2].jsonObject["rows"]!!.jsonArray.filter { it.jsonArray[0] == release.jsonArray[4] }
|
||||
allChapters.addAll(chapter.map { it.jsonArray })
|
||||
val team = data["rows"]!!.jsonArray[1].jsonObject["rows"]!!.jsonArray.filter { it.jsonArray[0] == release.jsonArray[5] }
|
||||
allChapters.addAll(team.map { it.jsonArray })
|
||||
allChapters.add(release.jsonArray)
|
||||
}
|
||||
|
||||
when (preferences.getString(PREF_CHAPTER_LISTING)) {
|
||||
PREF_CHAPTER_LISTING_SHOW_POPULAR -> addAll(
|
||||
allChapters.groupBy { it.asJsonArray[4].asFloat }
|
||||
.map { (_: Float, versions: List<JsonArray>) -> versions.maxByOrNull { it[5].asLong }!! }
|
||||
allChapters.groupBy { it.jsonArray[4].jsonPrimitive.float }
|
||||
.map { (_: Float, versions: List<JsonArray>) -> versions.maxByOrNull { it[5].jsonPrimitive.float }!! }
|
||||
)
|
||||
else -> addAll(allChapters)
|
||||
}
|
||||
|
@ -86,14 +91,14 @@ class Gmanga : ConfigurableSource, HttpSource() {
|
|||
|
||||
return chapters.map {
|
||||
SChapter.create().apply {
|
||||
chapter_number = it[8].asFloat
|
||||
chapter_number = it[8].jsonPrimitive.float
|
||||
|
||||
val chapterName = it[10].asString.let { if (it.trim() != "") " - $it" else "" }
|
||||
val chapterName = it[10].jsonPrimitive.content.let { if (it.trim() != "") " - $it" else "" }
|
||||
|
||||
url = "/r/${it[0]}"
|
||||
name = "${chapter_number.let { if (it % 1 > 0) it else it.toInt() }}$chapterName"
|
||||
date_upload = it[2].asLong * 1000
|
||||
scanlator = it[13].asString
|
||||
date_upload = it[2].jsonPrimitive.long * 1000
|
||||
scanlator = it[13].jsonPrimitive.content
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -101,16 +106,16 @@ class Gmanga : ConfigurableSource, HttpSource() {
|
|||
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Not used")
|
||||
|
||||
override fun latestUpdatesParse(response: Response): MangasPage {
|
||||
val data = gson.fromJson<JsonObject>(response.asJsoup().select(".js-react-on-rails-component").html())
|
||||
val data = json.decodeFromString<JsonObject>(response.asJsoup().select(".js-react-on-rails-component").html())
|
||||
return MangasPage(
|
||||
data["mangaDataAction"]["newMangas"].asJsonArray.map {
|
||||
data["mangaDataAction"]!!.jsonObject["newMangas"]!!.jsonArray.map {
|
||||
SManga.create().apply {
|
||||
url = "/mangas/${it["id"].asString}"
|
||||
title = it["title"].asString
|
||||
url = "/mangas/${it.jsonObject["id"]!!.jsonPrimitive.content}"
|
||||
title = it.jsonObject["title"]!!.jsonPrimitive.content
|
||||
|
||||
thumbnail_url = it["cover"].nullString?.let { coverFileName ->
|
||||
thumbnail_url = it.jsonObject["cover"]!!.jsonPrimitive.contentOrNull?.let { coverFileName ->
|
||||
val thumbnail = "medium_${coverFileName.substringBeforeLast(".")}.webp"
|
||||
"https://media.$domain/uploads/manga/cover/${it["id"].asString}/$thumbnail"
|
||||
"https://media.$domain/uploads/manga/cover/${it.jsonObject["id"]!!.jsonPrimitive.content}/$thumbnail"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -123,27 +128,27 @@ class Gmanga : ConfigurableSource, HttpSource() {
|
|||
}
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga {
|
||||
val data = gson.fromJson<JsonObject>(response.asJsoup().select(".js-react-on-rails-component").html())
|
||||
val mangaData = data["mangaDataAction"]["mangaData"].asJsonObject
|
||||
val data = json.decodeFromString<JsonObject>(response.asJsoup().select(".js-react-on-rails-component").html())
|
||||
val mangaData = data["mangaDataAction"]!!.jsonObject["mangaData"]!!.jsonObject
|
||||
return SManga.create().apply {
|
||||
description = mangaData["summary"].nullString ?: ""
|
||||
artist = mangaData["artists"].asJsonArray.joinToString(", ") { it.asJsonObject["name"].asString }
|
||||
author = mangaData["authors"].asJsonArray.joinToString(", ") { it.asJsonObject["name"].asString }
|
||||
genre = mangaData["categories"].asJsonArray.joinToString(", ") { it.asJsonObject["name"].asString }
|
||||
description = mangaData["summary"]!!.jsonPrimitive.contentOrNull ?: ""
|
||||
artist = mangaData["artists"]!!.jsonArray.joinToString(", ") { it.jsonObject["name"]!!.jsonPrimitive.content }
|
||||
author = mangaData["authors"]!!.jsonArray.joinToString(", ") { it.jsonObject["name"]!!.jsonPrimitive.content }
|
||||
genre = mangaData["categories"]!!.jsonArray.joinToString(", ") { it.jsonObject["name"]!!.jsonPrimitive.content }
|
||||
}
|
||||
}
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> {
|
||||
val url = response.request.url.toString()
|
||||
val data = gson.fromJson<JsonObject>(response.asJsoup().select(".js-react-on-rails-component").html())
|
||||
val releaseData = data["readerDataAction"]["readerData"]["release"].asJsonObject
|
||||
val data = json.decodeFromString<JsonObject>(response.asJsoup().select(".js-react-on-rails-component").html())
|
||||
val releaseData = data["readerDataAction"]!!.jsonObject["readerData"]!!.jsonObject["release"]!!.jsonObject
|
||||
|
||||
val hasWebP = releaseData["webp_pages"].asJsonArray.size() > 0
|
||||
return releaseData[if (hasWebP) "webp_pages" else "pages"].asJsonArray.map { it.asString }.mapIndexed { index, pageUri ->
|
||||
val hasWebP = releaseData["webp_pages"]!!.jsonArray.size > 0
|
||||
return releaseData[if (hasWebP) "webp_pages" else "pages"]!!.jsonArray.map { it.jsonPrimitive.content }.mapIndexed { index, pageUri ->
|
||||
Page(
|
||||
index,
|
||||
"$url#page_$index",
|
||||
"https://media.$domain/uploads/releases/${releaseData["storage_key"].asString}/hq${if (hasWebP) "_webp" else ""}/$pageUri"
|
||||
"https://media.$domain/uploads/releases/${releaseData["storage_key"]!!.jsonPrimitive.content}/hq${if (hasWebP) "_webp" else ""}/$pageUri"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -154,29 +159,29 @@ class Gmanga : ConfigurableSource, HttpSource() {
|
|||
|
||||
override fun searchMangaParse(response: Response): MangasPage {
|
||||
val data = decryptResponse(response)
|
||||
val mangas = data["mangas"].asJsonArray
|
||||
val mangas = data["mangas"]!!.jsonArray
|
||||
return MangasPage(
|
||||
mangas.asJsonArray.map {
|
||||
mangas.jsonArray.map {
|
||||
SManga.create().apply {
|
||||
url = "/mangas/${it["id"].asString}"
|
||||
title = it["title"].asString
|
||||
val thumbnail = "medium_${it["cover"].asString.substringBeforeLast(".")}.webp"
|
||||
thumbnail_url = "https://media.$domain/uploads/manga/cover/${it["id"].asString}/$thumbnail"
|
||||
url = "/mangas/${it.jsonObject["id"]!!.jsonPrimitive.content}"
|
||||
title = it.jsonObject["title"]!!.jsonPrimitive.content
|
||||
val thumbnail = "medium_${it.jsonObject["cover"]!!.jsonPrimitive.content.substringBeforeLast(".")}.webp"
|
||||
thumbnail_url = "https://media.$domain/uploads/manga/cover/${it.jsonObject["id"]!!.jsonPrimitive.content}/$thumbnail"
|
||||
}
|
||||
},
|
||||
mangas.size() == 50
|
||||
mangas.size == 50
|
||||
)
|
||||
}
|
||||
|
||||
private fun decryptResponse(response: Response): JsonObject {
|
||||
val encryptedData = gson.fromJson<JsonObject>(response.body!!.string())["data"].asString
|
||||
val encryptedData = json.decodeFromString<JsonObject>(response.body!!.string())["data"]!!.jsonPrimitive.content
|
||||
val decryptedData = decrypt(encryptedData)
|
||||
return gson.fromJson(decryptedData)
|
||||
return json.decodeFromString(decryptedData)
|
||||
}
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
return GmangaFilters.buildSearchPayload(page, query, if (filters.isEmpty()) getFilterList() else filters).let {
|
||||
val body = RequestBody.create(MEDIA_TYPE, it.toString())
|
||||
val body = it.toString().toRequestBody(MEDIA_TYPE)
|
||||
POST("$baseUrl/api/mangas/search", headers, body)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
package eu.kanade.tachiyomi.extension.ar.gmanga
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import com.github.salomonbrys.kotson.addAll
|
||||
import com.github.salomonbrys.kotson.addProperty
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonNull
|
||||
import com.google.gson.JsonObject
|
||||
import eu.kanade.tachiyomi.source.model.Filter
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import java.lang.Exception
|
||||
import kotlinx.serialization.json.JsonNull
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.JsonObjectBuilder
|
||||
import kotlinx.serialization.json.add
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
import kotlinx.serialization.json.put
|
||||
import kotlinx.serialization.json.putJsonArray
|
||||
import kotlinx.serialization.json.putJsonObject
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
|
||||
|
@ -35,139 +37,90 @@ class GmangaFilters() {
|
|||
val dateRangeFilter = filters.findInstance<DateRangeFilter>()!!
|
||||
val categoryFilter = filters.findInstance<CategoryFilter>()!!
|
||||
|
||||
return JsonObject().apply {
|
||||
|
||||
return buildJsonObject {
|
||||
oneShotFilter.state.first().let {
|
||||
when {
|
||||
it.isIncluded() -> addProperty("oneshot", true)
|
||||
it.isExcluded() -> addProperty("oneshot", false)
|
||||
else -> addProperty("oneshot", JsonNull.INSTANCE)
|
||||
it.isIncluded() -> put("oneshot", true)
|
||||
it.isExcluded() -> put("oneshot", false)
|
||||
else -> put("oneshot", JsonNull)
|
||||
}
|
||||
}
|
||||
|
||||
addProperty("title", query)
|
||||
addProperty("page", page)
|
||||
addProperty(
|
||||
"manga_types",
|
||||
JsonObject().apply {
|
||||
|
||||
addProperty(
|
||||
"include",
|
||||
JsonArray().apply {
|
||||
addAll(mangaTypeFilter.state.filter { it.isIncluded() }.map { it.id })
|
||||
}
|
||||
)
|
||||
|
||||
addProperty(
|
||||
"exclude",
|
||||
JsonArray().apply {
|
||||
addAll(mangaTypeFilter.state.filter { it.isExcluded() }.map { it.id })
|
||||
}
|
||||
)
|
||||
put("title", query)
|
||||
put("page", page)
|
||||
putJsonObject("manga_types") {
|
||||
putJsonArray("include") {
|
||||
mangaTypeFilter.state.filter { it.isIncluded() }.map { it.id }.forEach { add(it) }
|
||||
}
|
||||
)
|
||||
addProperty(
|
||||
"story_status",
|
||||
JsonObject().apply {
|
||||
|
||||
addProperty(
|
||||
"include",
|
||||
JsonArray().apply {
|
||||
addAll(storyStatusFilter.state.filter { it.isIncluded() }.map { it.id })
|
||||
}
|
||||
)
|
||||
|
||||
addProperty(
|
||||
"exclude",
|
||||
JsonArray().apply {
|
||||
addAll(storyStatusFilter.state.filter { it.isExcluded() }.map { it.id })
|
||||
}
|
||||
)
|
||||
putJsonArray("exclude") {
|
||||
mangaTypeFilter.state.filter { it.isExcluded() }.map { it.id }.forEach { add(it) }
|
||||
}
|
||||
)
|
||||
addProperty(
|
||||
"translation_status",
|
||||
JsonObject().apply {
|
||||
|
||||
addProperty(
|
||||
"include",
|
||||
JsonArray().apply {
|
||||
addAll(translationStatusFilter.state.filter { it.isIncluded() }.map { it.id })
|
||||
}
|
||||
)
|
||||
|
||||
addProperty(
|
||||
"exclude",
|
||||
JsonArray().apply {
|
||||
addAll(translationStatusFilter.state.filter { it.isExcluded() }.map { it.id })
|
||||
}
|
||||
)
|
||||
}
|
||||
putJsonObject("story_status") {
|
||||
putJsonArray("include") {
|
||||
storyStatusFilter.state.filter { it.isIncluded() }.map { it.id }.forEach { add(it) }
|
||||
}
|
||||
)
|
||||
addProperty(
|
||||
"categories",
|
||||
JsonObject().apply {
|
||||
|
||||
addProperty(
|
||||
"include",
|
||||
JsonArray().apply {
|
||||
add(JsonNull.INSTANCE) // always included, maybe to avoid shifting index in the backend
|
||||
addAll(categoryFilter.state.filter { it.isIncluded() }.map { it.id })
|
||||
}
|
||||
)
|
||||
|
||||
addProperty(
|
||||
"exclude",
|
||||
JsonArray().apply {
|
||||
addAll(categoryFilter.state.filter { it.isExcluded() }.map { it.id })
|
||||
}
|
||||
)
|
||||
putJsonArray("exclude") {
|
||||
storyStatusFilter.state.filter { it.isExcluded() }.map { it.id }.forEach { add(it) }
|
||||
}
|
||||
)
|
||||
addProperty(
|
||||
"chapters",
|
||||
JsonObject().apply {
|
||||
|
||||
addPropertyFromValidatingTextFilter(
|
||||
chapterCountFilter.state.first {
|
||||
it.id == FILTER_ID_MIN_CHAPTER_COUNT
|
||||
},
|
||||
"min",
|
||||
ERROR_INVALID_MIN_CHAPTER_COUNT,
|
||||
""
|
||||
)
|
||||
|
||||
addPropertyFromValidatingTextFilter(
|
||||
chapterCountFilter.state.first {
|
||||
it.id == FILTER_ID_MAX_CHAPTER_COUNT
|
||||
},
|
||||
"max",
|
||||
ERROR_INVALID_MAX_CHAPTER_COUNT,
|
||||
""
|
||||
)
|
||||
}
|
||||
putJsonObject("translation_status") {
|
||||
putJsonArray("include") {
|
||||
translationStatusFilter.state.filter { it.isIncluded() }.map { it.id }.forEach { add(it) }
|
||||
}
|
||||
)
|
||||
addProperty(
|
||||
"dates",
|
||||
JsonObject().apply {
|
||||
|
||||
addPropertyFromValidatingTextFilter(
|
||||
dateRangeFilter.state.first {
|
||||
it.id == FILTER_ID_START_DATE
|
||||
},
|
||||
"start",
|
||||
ERROR_INVALID_START_DATE
|
||||
)
|
||||
|
||||
addPropertyFromValidatingTextFilter(
|
||||
dateRangeFilter.state.first {
|
||||
it.id == FILTER_ID_END_DATE
|
||||
},
|
||||
"end",
|
||||
ERROR_INVALID_END_DATE
|
||||
)
|
||||
putJsonArray("exclude") {
|
||||
translationStatusFilter.state.filter { it.isExcluded() }.map { it.id }.forEach { add(it) }
|
||||
}
|
||||
)
|
||||
}
|
||||
putJsonObject("categories") {
|
||||
putJsonArray("include") {
|
||||
add(JsonNull) // always included, maybe to avoid shifting index in the backend
|
||||
categoryFilter.state.filter { it.isIncluded() }.map { it.id }.forEach { add(it) }
|
||||
}
|
||||
|
||||
putJsonArray("exclude") {
|
||||
categoryFilter.state.filter { it.isExcluded() }.map { it.id }.forEach { add(it) }
|
||||
}
|
||||
}
|
||||
putJsonObject("chapters") {
|
||||
putFromValidatingTextFilter(
|
||||
chapterCountFilter.state.first {
|
||||
it.id == FILTER_ID_MIN_CHAPTER_COUNT
|
||||
},
|
||||
"min",
|
||||
ERROR_INVALID_MIN_CHAPTER_COUNT,
|
||||
""
|
||||
)
|
||||
|
||||
putFromValidatingTextFilter(
|
||||
chapterCountFilter.state.first {
|
||||
it.id == FILTER_ID_MAX_CHAPTER_COUNT
|
||||
},
|
||||
"max",
|
||||
ERROR_INVALID_MAX_CHAPTER_COUNT,
|
||||
""
|
||||
)
|
||||
}
|
||||
putJsonObject("dates") {
|
||||
putFromValidatingTextFilter(
|
||||
dateRangeFilter.state.first {
|
||||
it.id == FILTER_ID_START_DATE
|
||||
},
|
||||
"start",
|
||||
ERROR_INVALID_START_DATE
|
||||
)
|
||||
|
||||
putFromValidatingTextFilter(
|
||||
dateRangeFilter.state.first {
|
||||
it.id == FILTER_ID_END_DATE
|
||||
},
|
||||
"end",
|
||||
ERROR_INVALID_END_DATE
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -298,7 +251,7 @@ class GmangaFilters() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun JsonObject.addPropertyFromValidatingTextFilter(
|
||||
private fun JsonObjectBuilder.putFromValidatingTextFilter(
|
||||
filter: ValidatingTextFilter,
|
||||
property: String,
|
||||
invalidErrorMessage: String,
|
||||
|
@ -307,9 +260,9 @@ class GmangaFilters() {
|
|||
filter.let {
|
||||
when {
|
||||
it.state == "" -> if (default == null) {
|
||||
addProperty(property, JsonNull.INSTANCE)
|
||||
} else addProperty(property, default)
|
||||
it.isValid() -> addProperty(property, it.state)
|
||||
put(property, JsonNull)
|
||||
} else put(property, default)
|
||||
it.isValid() -> put(property, it.state)
|
||||
else -> throw Exception(invalidErrorMessage)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlinx-serialization'
|
||||
|
||||
ext {
|
||||
extName = 'Manga Tube'
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
package eu.kanade.tachiyomi.extension.de.mangatube
|
||||
|
||||
import com.github.salomonbrys.kotson.fromJson
|
||||
import com.github.salomonbrys.kotson.get
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
|
@ -14,14 +9,22 @@ import eu.kanade.tachiyomi.source.model.Page
|
|||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import okhttp3.Headers
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import rx.Observable
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
@ -45,7 +48,7 @@ class MangaTube : ParsedHttpSource() {
|
|||
|
||||
private val xhrHeaders: Headers = headersBuilder().add("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8").build()
|
||||
|
||||
private val gson by lazy { Gson() }
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
// Popular
|
||||
|
||||
|
@ -59,21 +62,21 @@ class MangaTube : ParsedHttpSource() {
|
|||
|
||||
override fun popularMangaRequest(page: Int): Request {
|
||||
val rbodyContent = "action=load_series_list_entries¶meter%5Bpage%5D=$page¶meter%5Bletter%5D=¶meter%5Bsortby%5D=popularity¶meter%5Border%5D=asc"
|
||||
return POST("$baseUrl/ajax", xhrHeaders, RequestBody.create(null, rbodyContent))
|
||||
return POST("$baseUrl/ajax", xhrHeaders, rbodyContent.toRequestBody(null))
|
||||
}
|
||||
|
||||
// popular uses "success" as a key, search uses "suggestions"
|
||||
// for future reference: if adding filters, advanced search might use a different key
|
||||
private fun parseMangaFromJson(response: Response, hasNextPage: Boolean): MangasPage {
|
||||
var titleKey = "manga_title"
|
||||
val mangas = gson.fromJson<JsonObject>(response.body!!.string())
|
||||
.let { it["success"] ?: it["suggestions"].also { titleKey = "value" } }
|
||||
.asJsonArray
|
||||
val mangas = json.decodeFromString<JsonObject>(response.body!!.string())
|
||||
.let { it["success"] ?: it["suggestions"].also { titleKey = "value" } }!!
|
||||
.jsonArray
|
||||
.map { json ->
|
||||
SManga.create().apply {
|
||||
title = json[titleKey].asString
|
||||
url = "/series/${json["manga_slug"].asString}"
|
||||
thumbnail_url = json["covers"][0]["img_name"].asString
|
||||
title = json.jsonObject[titleKey]!!.jsonPrimitive.content
|
||||
url = "/series/${json.jsonObject["manga_slug"]!!.jsonPrimitive.content}"
|
||||
thumbnail_url = json.jsonObject["covers"]!!.jsonArray[0].jsonObject["img_name"]!!.jsonPrimitive.content
|
||||
}
|
||||
}
|
||||
return MangasPage(mangas, hasNextPage)
|
||||
|
@ -109,7 +112,7 @@ class MangaTube : ParsedHttpSource() {
|
|||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
val rbodyContent = "action=search_query¶meter%5Bquery%5D=$query"
|
||||
return POST("$baseUrl/ajax", xhrHeaders, RequestBody.create(null, rbodyContent))
|
||||
return POST("$baseUrl/ajax", xhrHeaders, rbodyContent.toRequestBody(null))
|
||||
}
|
||||
|
||||
override fun searchMangaParse(response: Response): MangasPage {
|
||||
|
@ -173,8 +176,8 @@ class MangaTube : ParsedHttpSource() {
|
|||
val jsonArray = Regex("""pages: (\[.*]),""").find(script)?.groupValues?.get(1)
|
||||
?: throw Exception("Couldn't find JSON array")
|
||||
|
||||
return gson.fromJson<JsonArray>(jsonArray).mapIndexed { i, json ->
|
||||
Page(i, "", imagePath + json.asJsonObject["file_name"].asString)
|
||||
return json.decodeFromString<JsonArray>(jsonArray).mapIndexed { i, json ->
|
||||
Page(i, "", imagePath + json.jsonObject["file_name"]!!.jsonPrimitive.content)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlinx-serialization'
|
||||
|
||||
ext {
|
||||
extName = 'Mangahub'
|
||||
|
|
|
@ -1,11 +1,5 @@
|
|||
package eu.kanade.tachiyomi.extension.en.mangahub
|
||||
|
||||
import com.github.salomonbrys.kotson.fromJson
|
||||
import com.github.salomonbrys.kotson.get
|
||||
import com.github.salomonbrys.kotson.keys
|
||||
import com.github.salomonbrys.kotson.string
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonObject
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.source.model.Filter
|
||||
|
@ -14,12 +8,18 @@ import eu.kanade.tachiyomi.source.model.Page
|
|||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.net.URL
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
|
@ -156,21 +156,26 @@ class Mangahub : ParsedHttpSource() {
|
|||
|
||||
val slug = chapter.url.substringAfter("chapter/").substringBefore("/")
|
||||
val number = chapter.url.substringAfter("chapter-").removeSuffix("/")
|
||||
val body = RequestBody.create(null, "{\"query\":\"{chapter(x:m01,slug:\\\"$slug\\\",number:$number){id,title,mangaID,number,slug,date,pages,noAd,manga{id,title,slug,mainSlug,author,isWebtoon,isYaoi,isPorn,isSoftPorn,unauthFile,isLicensed}}}\"}")
|
||||
val body =
|
||||
"{\"query\":\"{chapter(x:m01,slug:\\\"$slug\\\",number:$number){id,title,mangaID,number,slug,date,pages,noAd,manga{id,title,slug,mainSlug,author,isWebtoon,isYaoi,isPorn,isSoftPorn,unauthFile,isLicensed}}}\"}".toRequestBody(
|
||||
null
|
||||
)
|
||||
|
||||
return POST("https://api.mghubcdn.com/graphql", jsonHeaders, body)
|
||||
}
|
||||
|
||||
private val gson = Gson()
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> {
|
||||
val cdn = "https://img.mghubcdn.com/file/imghub"
|
||||
|
||||
return gson.fromJson<JsonObject>(response.body!!.string())["data"]["chapter"]["pages"].string
|
||||
return json.decodeFromString<JsonObject>(response.body!!.string())["data"]!!
|
||||
.jsonObject["chapter"]!!
|
||||
.jsonObject["pages"]!!.jsonPrimitive.content
|
||||
.removeSurrounding("\"").replace("\\", "")
|
||||
.let { cleaned ->
|
||||
val jsonObject = gson.fromJson<JsonObject>(cleaned)
|
||||
jsonObject.keys().map { key -> jsonObject[key].string }
|
||||
val jsonObject = json.decodeFromString<JsonObject>(cleaned)
|
||||
jsonObject.keys.map { key -> jsonObject[key]!!.jsonPrimitive.content }
|
||||
}
|
||||
.mapIndexed { i, tail -> Page(i, "", "$cdn/$tail") }
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlinx-serialization'
|
||||
|
||||
ext {
|
||||
extName = 'MangaRock.es'
|
||||
|
|
|
@ -1,8 +1,5 @@
|
|||
package eu.kanade.tachiyomi.extension.en.mangarockes
|
||||
|
||||
import com.github.salomonbrys.kotson.fromJson
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonArray
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.source.model.Filter
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
|
@ -10,6 +7,11 @@ import eu.kanade.tachiyomi.source.model.Page
|
|||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.OkHttpClient
|
||||
|
@ -18,6 +20,7 @@ import okhttp3.Response
|
|||
import okhttp3.ResponseBody.Companion.toResponseBody
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
|
@ -160,13 +163,13 @@ class MangaRockEs : ParsedHttpSource() {
|
|||
|
||||
// Pages
|
||||
|
||||
private val gson by lazy { Gson() }
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> {
|
||||
val responseString = response.body!!.string()
|
||||
return Regex("""mangaData = (\[.*]);""", RegexOption.IGNORE_CASE).find(responseString)?.groupValues?.get(1)?.let { array ->
|
||||
gson.fromJson<JsonArray>(array)
|
||||
.mapIndexed { i, jsonElement -> Page(i, "", jsonElement.asJsonObject["url"].asString) }
|
||||
json.decodeFromString<JsonArray>(array)
|
||||
.mapIndexed { i, jsonElement -> Page(i, "", jsonElement.jsonObject["url"]!!.jsonPrimitive.content) }
|
||||
}
|
||||
?: Regex("""getManga\(\d+, '(http.*)',""").findAll(responseString).toList()
|
||||
.mapIndexed { i, mr -> Page(i, "", mr.groupValues[1]) }
|
||||
|
|
|
@ -11,7 +11,7 @@ import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
|||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
|
@ -69,7 +69,7 @@ class ManhuaManga : ParsedHttpSource() {
|
|||
protected fun getXhrChapters(mangaId: String): Document {
|
||||
val xhrHeaders = headersBuilder().add("Content-Type: application/x-www-form-urlencoded; charset=UTF-8")
|
||||
.build()
|
||||
val body = RequestBody.create(null, "action=tw_ajax&type=list_chap&id=$mangaId")
|
||||
val body = "action=tw_ajax&type=list_chap&id=$mangaId".toRequestBody(null)
|
||||
return client.newCall(POST("$baseUrl/wp-admin/admin-ajax.php", xhrHeaders, body)).execute().asJsoup()
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
|||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
|
@ -69,7 +69,7 @@ class ManhwaManga : ParsedHttpSource() {
|
|||
protected fun getXhrChapters(mangaId: String): Document {
|
||||
val xhrHeaders = headersBuilder().add("Content-Type: application/x-www-form-urlencoded; charset=UTF-8")
|
||||
.build()
|
||||
val body = RequestBody.create(null, "action=tw_ajax&type=list_chap&id=$mangaId")
|
||||
val body = "action=tw_ajax&type=list_chap&id=$mangaId".toRequestBody(null)
|
||||
return client.newCall(POST("$baseUrl/wp-admin/admin-ajax.php", xhrHeaders, body)).execute().asJsoup()
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlinx-serialization'
|
||||
|
||||
ext {
|
||||
extName = 'ReadManhwa'
|
||||
|
|
|
@ -2,14 +2,6 @@ package eu.kanade.tachiyomi.extension.en.readmanhwa
|
|||
|
||||
import android.app.Application
|
||||
import android.content.SharedPreferences
|
||||
import com.github.salomonbrys.kotson.fromJson
|
||||
import com.github.salomonbrys.kotson.get
|
||||
import com.github.salomonbrys.kotson.int
|
||||
import com.github.salomonbrys.kotson.nullString
|
||||
import com.github.salomonbrys.kotson.string
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
|
@ -20,6 +12,15 @@ import eu.kanade.tachiyomi.source.model.Page
|
|||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.contentOrNull
|
||||
import kotlinx.serialization.json.int
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import okhttp3.OkHttpClient
|
||||
|
@ -28,6 +29,7 @@ import okhttp3.Response
|
|||
import rx.Observable
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
|
@ -54,20 +56,20 @@ class ReadManhwa : ConfigurableSource, HttpSource() {
|
|||
|
||||
override val client: OkHttpClient = network.cloudflareClient
|
||||
|
||||
private val gson = Gson()
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
private fun parseMangaFromJson(response: Response): MangasPage {
|
||||
val jsonObject = gson.fromJson<JsonObject>(response.body!!.string())
|
||||
val jsonObject = json.decodeFromString<JsonObject>(response.body!!.string())
|
||||
|
||||
val mangas = jsonObject["data"].asJsonArray.map { json ->
|
||||
val mangas = jsonObject["data"]!!.jsonArray.map { json ->
|
||||
SManga.create().apply {
|
||||
title = json["title"].string
|
||||
thumbnail_url = json["image_url"].string
|
||||
url = json["slug"].string
|
||||
title = json.jsonObject["title"]!!.jsonPrimitive.content
|
||||
thumbnail_url = json.jsonObject["image_url"]!!.jsonPrimitive.content
|
||||
url = json.jsonObject["slug"]!!.jsonPrimitive.content
|
||||
}
|
||||
}
|
||||
|
||||
return MangasPage(mangas, jsonObject["current_page"].int < jsonObject["last_page"].int)
|
||||
return MangasPage(mangas, jsonObject["current_page"]!!.jsonPrimitive.int < jsonObject["last_page"]!!.jsonPrimitive.int)
|
||||
}
|
||||
private fun getMangaUrl(url: String): String {
|
||||
return url.toHttpUrlOrNull()!!.newBuilder()
|
||||
|
@ -159,15 +161,15 @@ class ReadManhwa : ConfigurableSource, HttpSource() {
|
|||
}
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga {
|
||||
val jsonObject = gson.fromJson<JsonObject>(response.body!!.string())
|
||||
val jsonObject = json.decodeFromString<JsonObject>(response.body!!.string())
|
||||
|
||||
return SManga.create().apply {
|
||||
description = jsonObject["description"].nullString
|
||||
status = jsonObject["status"].nullString.toStatus()
|
||||
thumbnail_url = jsonObject["image_url"].nullString
|
||||
genre = try { jsonObject["tags"].asJsonArray.joinToString { it["name"].string } } catch (_: Exception) { null }
|
||||
artist = try { jsonObject["artists"].asJsonArray.joinToString { it["name"].string } } catch (_: Exception) { null }
|
||||
author = try { jsonObject["authors"].asJsonArray.joinToString { it["name"].string } } catch (_: Exception) { null }
|
||||
description = jsonObject["description"]!!.jsonPrimitive.contentOrNull
|
||||
status = jsonObject["status"]!!.jsonPrimitive.contentOrNull.toStatus()
|
||||
thumbnail_url = jsonObject["image_url"]!!.jsonPrimitive.contentOrNull
|
||||
genre = try { jsonObject["tags"]!!.jsonArray.joinToString { it.jsonObject["name"]!!.jsonPrimitive.content } } catch (_: Exception) { null }
|
||||
artist = try { jsonObject["artists"]!!.jsonArray.joinToString { it.jsonObject["name"]!!.jsonPrimitive.content } } catch (_: Exception) { null }
|
||||
author = try { jsonObject["authors"]!!.jsonArray.joinToString { it.jsonObject["name"]!!.jsonPrimitive.content } } catch (_: Exception) { null }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -193,11 +195,11 @@ class ReadManhwa : ConfigurableSource, HttpSource() {
|
|||
}
|
||||
|
||||
private fun chapterListParse(response: Response, titleSlug: String): List<SChapter> {
|
||||
return gson.fromJson<JsonArray>(response.body!!.string()).map { json ->
|
||||
return json.decodeFromString<JsonArray>(response.body!!.string()).map { json ->
|
||||
SChapter.create().apply {
|
||||
name = json["name"].string
|
||||
url = "$titleSlug/${json["slug"].string}"
|
||||
date_upload = json["added_at"].string.let { dateString ->
|
||||
name = json.jsonObject["name"]!!.jsonPrimitive.content
|
||||
url = "$titleSlug/${json.jsonObject["slug"]!!.jsonPrimitive.content}"
|
||||
date_upload = json.jsonObject["added_at"]!!.jsonPrimitive.content.let { dateString ->
|
||||
if (dateString.contains("ago")) {
|
||||
val trimmedDate = dateString.substringBefore(" ago").removeSuffix("s").split(" ")
|
||||
val calendar = Calendar.getInstance()
|
||||
|
@ -225,8 +227,8 @@ class ReadManhwa : ConfigurableSource, HttpSource() {
|
|||
}
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> {
|
||||
return gson.fromJson<JsonObject>(response.body!!.string())["images"].asJsonArray.mapIndexed { i, json ->
|
||||
Page(i, "", json["source_url"].string)
|
||||
return json.decodeFromString<JsonObject>(response.body!!.string())["images"]!!.jsonArray.mapIndexed { i, json ->
|
||||
Page(i, "", json.jsonObject["source_url"]!!.jsonPrimitive.content)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import eu.kanade.tachiyomi.source.model.SManga
|
|||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
|
@ -131,7 +131,7 @@ class DoujinYang : ParsedHttpSource() {
|
|||
return POST(
|
||||
baseUrl + chapter.url,
|
||||
headersBuilder().add("Content-Type", "application/x-www-form-urlencoded").build(),
|
||||
RequestBody.create(null, "info")
|
||||
"info".toRequestBody(null)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package eu.kanade.tachiyomi.extension.es.kumanga
|
||||
|
||||
import android.util.Base64
|
||||
import com.github.salomonbrys.kotson.jsonObject
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.source.model.Filter
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlinx-serialization'
|
||||
|
||||
ext {
|
||||
extName = 'ComX'
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
package eu.kanade.tachiyomi.extension.ru.comx
|
||||
|
||||
import com.github.salomonbrys.kotson.get
|
||||
import com.github.salomonbrys.kotson.nullArray
|
||||
import com.github.salomonbrys.kotson.obj
|
||||
import com.google.gson.JsonParser
|
||||
import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
|
@ -15,6 +11,12 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
|||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
|
@ -23,12 +25,16 @@ import okhttp3.Request
|
|||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class ComX : ParsedHttpSource() {
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
override val name = "Com-x"
|
||||
|
||||
override val baseUrl = "https://com-x.life"
|
||||
|
@ -186,13 +192,13 @@ class ComX : ParsedHttpSource() {
|
|||
.substringBefore("</script>")
|
||||
.substringBeforeLast(";")
|
||||
|
||||
val data = JsonParser.parseString(dataStr).obj
|
||||
val chaptersList = data["chapters"].nullArray
|
||||
val data = json.decodeFromString<JsonObject>(dataStr)
|
||||
val chaptersList = data["chapters"]?.jsonArray
|
||||
val chapters: List<SChapter>? = chaptersList?.map {
|
||||
val chapter = SChapter.create()
|
||||
chapter.name = it["title"].asString
|
||||
chapter.date_upload = parseDate(it["date"].asString)
|
||||
chapter.setUrlWithoutDomain("/readcomix/" + data["news_id"] + "/" + it["id"] + ".html")
|
||||
chapter.name = it.jsonObject["title"]!!.jsonPrimitive.content
|
||||
chapter.date_upload = parseDate(it.jsonObject["date"]!!.jsonPrimitive.content)
|
||||
chapter.setUrlWithoutDomain("/readcomix/" + data["news_id"] + "/" + it.jsonObject["id"]!!.jsonPrimitive.content + ".html")
|
||||
chapter
|
||||
}
|
||||
return chapters ?: emptyList()
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlinx-serialization'
|
||||
|
||||
ext {
|
||||
extName = 'MangaLib'
|
||||
|
|
|
@ -5,18 +5,6 @@ import android.content.SharedPreferences
|
|||
import android.widget.Toast
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import com.github.salomonbrys.kotson.array
|
||||
import com.github.salomonbrys.kotson.get
|
||||
import com.github.salomonbrys.kotson.int
|
||||
import com.github.salomonbrys.kotson.nullArray
|
||||
import com.github.salomonbrys.kotson.nullInt
|
||||
import com.github.salomonbrys.kotson.nullString
|
||||
import com.github.salomonbrys.kotson.obj
|
||||
import com.github.salomonbrys.kotson.string
|
||||
import com.github.salomonbrys.kotson.toMap
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonParser
|
||||
import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
|
@ -30,6 +18,17 @@ 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.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.contentOrNull
|
||||
import kotlinx.serialization.json.int
|
||||
import kotlinx.serialization.json.intOrNull
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||
import okhttp3.OkHttpClient
|
||||
|
@ -39,12 +38,15 @@ import org.jsoup.nodes.Element
|
|||
import rx.Observable
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class LibManga : ConfigurableSource, HttpSource() {
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
private val preferences: SharedPreferences by lazy {
|
||||
Injekt.get<Application>().getSharedPreferences("source_${id}_2", 0x0000)
|
||||
}
|
||||
|
@ -72,8 +74,6 @@ class LibManga : ConfigurableSource, HttpSource() {
|
|||
add("Referer", baseUrl)
|
||||
}
|
||||
|
||||
private val jsonParser = JsonParser()
|
||||
|
||||
override fun latestUpdatesRequest(page: Int) = GET(baseUrl, headers)
|
||||
|
||||
private val latestUpdatesSelector = "div.updates__item"
|
||||
|
@ -135,21 +135,21 @@ class LibManga : ConfigurableSource, HttpSource() {
|
|||
|
||||
override fun popularMangaParse(response: Response): MangasPage {
|
||||
val resBody = response.body!!.string()
|
||||
val result = jsonParser.parse(resBody).obj
|
||||
val items = result["items"]
|
||||
val popularMangas = items["data"].nullArray?.map { popularMangaFromElement(it) }
|
||||
val result = json.decodeFromString<JsonObject>(resBody)
|
||||
val items = result["items"]!!.jsonObject
|
||||
val popularMangas = items["data"]?.jsonArray?.map { popularMangaFromElement(it) }
|
||||
|
||||
if (popularMangas != null) {
|
||||
val hasNextPage = items["next_page_url"].nullString != null
|
||||
val hasNextPage = items["next_page_url"]?.jsonPrimitive?.contentOrNull != null
|
||||
return MangasPage(popularMangas, hasNextPage)
|
||||
}
|
||||
return MangasPage(emptyList(), false)
|
||||
}
|
||||
|
||||
private fun popularMangaFromElement(el: JsonElement) = SManga.create().apply {
|
||||
val slug = el["slug"].string
|
||||
val cover = el["cover"].string
|
||||
title = if (titleLanguage.equals("rus")) el["rus_name"].string else el["name"].string
|
||||
val slug = el.jsonObject["slug"]!!.jsonPrimitive.content
|
||||
val cover = el.jsonObject["cover"]!!.jsonPrimitive.content
|
||||
title = if (titleLanguage.equals("rus")) el.jsonObject["rus_name"]!!.jsonPrimitive.content else el.jsonObject["name"]!!.jsonPrimitive.content
|
||||
thumbnail_url = "$COVER_URL/uploads/cover/$slug/cover/${cover}_250x350.jpg"
|
||||
url = "/$slug"
|
||||
}
|
||||
|
@ -232,17 +232,17 @@ class LibManga : ConfigurableSource, HttpSource() {
|
|||
.substringBefore("window._SITE_COLOR_")
|
||||
.substringBeforeLast(";")
|
||||
|
||||
val data = jsonParser.parse(dataStr).obj
|
||||
val chaptersList = data["chapters"]["list"].nullArray
|
||||
val slug = data["manga"]["slug"].string
|
||||
val branches = data["chapters"]["branches"].array.reversed()
|
||||
val data = json.decodeFromString<JsonObject>(dataStr)
|
||||
val chaptersList = data["chapters"]!!.jsonObject["list"]?.jsonArray
|
||||
val slug = data["manga"]!!.jsonObject["slug"]!!.jsonPrimitive.content
|
||||
val branches = data["chapters"]!!.jsonObject["branches"]!!.jsonArray.reversed()
|
||||
val sortingList = preferences.getString(SORTING_PREF, "ms_mixing")
|
||||
|
||||
val chapters: List<SChapter>? = if (branches.isNotEmpty() && !sortingList.equals("ms_mixing")) {
|
||||
sortChaptersByTranslator(sortingList, chaptersList, slug, branches)
|
||||
} else {
|
||||
chaptersList
|
||||
?.filter { it["status"].nullInt != 2 }
|
||||
?.filter { it.jsonObject["status"]?.jsonPrimitive?.intOrNull != 2 }
|
||||
?.map { chapterFromElement(it, sortingList, slug) }
|
||||
}
|
||||
|
||||
|
@ -256,9 +256,9 @@ class LibManga : ConfigurableSource, HttpSource() {
|
|||
"ms_combining" -> {
|
||||
val tempChaptersList = mutableListOf<SChapter>()
|
||||
for (currentBranch in branches.withIndex()) {
|
||||
val teamId = branches[currentBranch.index]["id"].int
|
||||
val teamId = branches[currentBranch.index].jsonObject["id"]!!.jsonPrimitive.int
|
||||
chapters = chaptersList
|
||||
?.filter { it["branch_id"].nullInt == teamId && it["status"].nullInt != 2 }
|
||||
?.filter { it.jsonObject["branch_id"]?.jsonPrimitive?.intOrNull == teamId && it.jsonObject["status"]?.jsonPrimitive?.intOrNull != 2 }
|
||||
?.map { chapterFromElement(it, sortingList, slug, teamId, branches) }
|
||||
chapters?.let { tempChaptersList.addAll(it) }
|
||||
}
|
||||
|
@ -267,26 +267,26 @@ class LibManga : ConfigurableSource, HttpSource() {
|
|||
"ms_largest" -> {
|
||||
val sizesChaptersLists = mutableListOf<Int>()
|
||||
for (currentBranch in branches.withIndex()) {
|
||||
val teamId = branches[currentBranch.index]["id"].int
|
||||
val teamId = branches[currentBranch.index].jsonObject["id"]!!.jsonPrimitive.int
|
||||
val chapterSize = chaptersList
|
||||
?.filter { it["branch_id"].nullInt == teamId }!!.size
|
||||
?.filter { it.jsonObject["branch_id"]?.jsonPrimitive?.intOrNull == teamId }!!.size
|
||||
sizesChaptersLists.add(chapterSize)
|
||||
}
|
||||
val max = sizesChaptersLists.indexOfFirst { it == sizesChaptersLists.maxOrNull() ?: 0 }
|
||||
val teamId = branches[max]["id"].int
|
||||
val teamId = branches[max].jsonObject["id"]!!.jsonPrimitive.int
|
||||
|
||||
chapters = chaptersList
|
||||
?.filter { it["branch_id"].nullInt == teamId && it["status"].nullInt != 2 }
|
||||
?.filter { it.jsonObject["branch_id"]?.jsonPrimitive?.intOrNull == teamId && it.jsonObject["status"]?.jsonPrimitive?.intOrNull != 2 }
|
||||
?.map { chapterFromElement(it, sortingList, slug, teamId, branches) }
|
||||
}
|
||||
"ms_active" -> {
|
||||
for (currentBranch in branches.withIndex()) {
|
||||
val teams = branches[currentBranch.index]["teams"].array
|
||||
val teams = branches[currentBranch.index].jsonObject["teams"]!!.jsonArray
|
||||
for (currentTeam in teams.withIndex()) {
|
||||
if (teams[currentTeam.index]["is_active"].int == 1) {
|
||||
val teamId = branches[currentBranch.index]["id"].int
|
||||
if (teams[currentTeam.index].jsonObject["is_active"]!!.jsonPrimitive.int == 1) {
|
||||
val teamId = branches[currentBranch.index].jsonObject["id"]!!.jsonPrimitive.int
|
||||
chapters = chaptersList
|
||||
?.filter { it["branch_id"].nullInt == teamId && it["status"].nullInt != 2 }
|
||||
?.filter { it.jsonObject["branch_id"]?.jsonPrimitive?.intOrNull == teamId && it.jsonObject["status"]?.jsonPrimitive?.intOrNull != 2 }
|
||||
?.map { chapterFromElement(it, sortingList, slug, teamId, branches) }
|
||||
break
|
||||
}
|
||||
|
@ -303,23 +303,23 @@ class LibManga : ConfigurableSource, HttpSource() {
|
|||
(chapterItem: JsonElement, sortingList: String?, slug: String, teamIdParam: Int? = null, branches: List<JsonElement>? = null): SChapter {
|
||||
val chapter = SChapter.create()
|
||||
|
||||
val volume = chapterItem["chapter_volume"].int
|
||||
val number = chapterItem["chapter_number"].string
|
||||
val volume = chapterItem.jsonObject["chapter_volume"]!!.jsonPrimitive.int
|
||||
val number = chapterItem.jsonObject["chapter_number"]!!.jsonPrimitive.content
|
||||
val teamId = if (teamIdParam != null) "?bid=$teamIdParam" else ""
|
||||
|
||||
val url = "$baseUrl/$slug/v$volume/c$number$teamId"
|
||||
|
||||
chapter.setUrlWithoutDomain(url)
|
||||
|
||||
val nameChapter = chapterItem["chapter_name"].nullString
|
||||
val nameChapter = chapterItem.jsonObject["chapter_name"]?.jsonPrimitive?.contentOrNull
|
||||
val fullNameChapter = "Том $volume. Глава $number"
|
||||
|
||||
if (!sortingList.equals("ms_mixing")) {
|
||||
chapter.scanlator = branches?.let { getScanlatorTeamName(it, chapterItem) } ?: chapterItem["username"].string
|
||||
chapter.scanlator = branches?.let { getScanlatorTeamName(it, chapterItem) } ?: chapterItem.jsonObject["username"]!!.jsonPrimitive.content
|
||||
}
|
||||
chapter.name = if (nameChapter.isNullOrBlank()) fullNameChapter else "$fullNameChapter - $nameChapter"
|
||||
chapter.date_upload = SimpleDateFormat("yyyy-MM-dd", Locale.US)
|
||||
.parse(chapterItem["chapter_created_at"].string.substringBefore(" "))?.time ?: 0L
|
||||
.parse(chapterItem.jsonObject["chapter_created_at"]!!.jsonPrimitive.content.substringBefore(" "))?.time ?: 0L
|
||||
|
||||
return chapter
|
||||
}
|
||||
|
@ -327,15 +327,15 @@ class LibManga : ConfigurableSource, HttpSource() {
|
|||
private fun getScanlatorTeamName(branches: List<JsonElement>, chapterItem: JsonElement): String? {
|
||||
var scanlatorData: String? = null
|
||||
for (currentBranch in branches.withIndex()) {
|
||||
val branch = branches[currentBranch.index]
|
||||
val teams = branch["teams"].array
|
||||
if (chapterItem["branch_id"].int == branch["id"].int) {
|
||||
val branch = branches[currentBranch.index].jsonObject
|
||||
val teams = branch["teams"]!!.jsonArray
|
||||
if (chapterItem.jsonObject["branch_id"]!!.jsonPrimitive.int == branch["id"]!!.jsonPrimitive.int) {
|
||||
for (currentTeam in teams.withIndex()) {
|
||||
val team = teams[currentTeam.index]
|
||||
val scanlatorId = chapterItem["chapter_scanlator_id"].int
|
||||
scanlatorData = if ((scanlatorId == team["id"].int) ||
|
||||
(scanlatorId == 0 && team["is_active"].int == 1)
|
||||
) team["name"].string else branch["teams"][0]["name"].string
|
||||
val team = teams[currentTeam.index].jsonObject
|
||||
val scanlatorId = chapterItem.jsonObject["chapter_scanlator_id"]!!.jsonPrimitive.int
|
||||
scanlatorData = if ((scanlatorId == team.jsonObject["id"]!!.jsonPrimitive.int) ||
|
||||
(scanlatorId == 0 && team["is_active"]!!.jsonPrimitive.int == 1)
|
||||
) team["name"]!!.jsonPrimitive.content else branch["teams"]!!.jsonArray[0].jsonObject["name"]!!.jsonPrimitive.content
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -371,11 +371,11 @@ class LibManga : ConfigurableSource, HttpSource() {
|
|||
.split(";")
|
||||
.first()
|
||||
|
||||
val chapInfoJson = jsonParser.parse(chapInfo).obj
|
||||
val servers = chapInfoJson["servers"].asJsonObject.toMap()
|
||||
val defaultServer: String = chapInfoJson["img"]["server"].string
|
||||
val chapInfoJson = json.decodeFromString<JsonObject>(chapInfo)
|
||||
val servers = chapInfoJson["servers"]!!.jsonObject.toMap()
|
||||
val defaultServer: String = chapInfoJson["img"]!!.jsonObject["server"]!!.jsonPrimitive.content
|
||||
val autoServer = setOf("secondary", "fourth", defaultServer, "compress")
|
||||
val imgUrl: String = chapInfoJson["img"]["url"].string
|
||||
val imgUrl: String = chapInfoJson["img"]!!.jsonObject["url"]!!.jsonPrimitive.content
|
||||
|
||||
val serverToUse = when (this.server) {
|
||||
null -> autoServer
|
||||
|
@ -392,15 +392,15 @@ class LibManga : ConfigurableSource, HttpSource() {
|
|||
.removePrefix("window.__pg = ")
|
||||
.removeSuffix(";")
|
||||
|
||||
val pagesJson = jsonParser.parse(pagesArr).array
|
||||
val pagesJson = json.decodeFromString<JsonArray>(pagesArr)
|
||||
val pages = mutableListOf<Page>()
|
||||
|
||||
pagesJson.forEach { page ->
|
||||
val keys = servers.keys.filter { serverToUse.indexOf(it) >= 0 }.sortedBy { serverToUse.indexOf(it) }
|
||||
val serversUrls = keys.map {
|
||||
servers[it]?.string + imgUrl + page["u"].string
|
||||
servers[it]?.jsonPrimitive?.contentOrNull + imgUrl + page.jsonObject["u"]!!.jsonPrimitive.content
|
||||
}.joinToString(separator = ",,") { it }
|
||||
pages.add(Page(page["p"].int, serversUrls))
|
||||
pages.add(Page(page.jsonObject["p"]!!.jsonPrimitive.int, serversUrls))
|
||||
}
|
||||
|
||||
return pages
|
||||
|
@ -523,7 +523,7 @@ class LibManga : ConfigurableSource, HttpSource() {
|
|||
)
|
||||
.execute().body!!.string()
|
||||
|
||||
val jsonList = jsonParser.parse(popup).array
|
||||
val jsonList = json.decodeFromString<JsonArray>(popup)
|
||||
jsonList.forEach {
|
||||
mangas.add(popularMangaFromElement(it))
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlinx-serialization'
|
||||
|
||||
ext {
|
||||
extName = 'Mangaonlinebiz'
|
||||
|
|
|
@ -1,10 +1,5 @@
|
|||
package eu.kanade.tachiyomi.extension.ru.mangaonlinebiz
|
||||
|
||||
import com.github.salomonbrys.kotson.float
|
||||
import com.github.salomonbrys.kotson.forEach
|
||||
import com.github.salomonbrys.kotson.string
|
||||
import com.google.gson.JsonObject
|
||||
import com.google.gson.JsonParser
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.source.model.Filter
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
|
@ -13,15 +8,27 @@ import eu.kanade.tachiyomi.source.model.Page
|
|||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.float
|
||||
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 org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class MangaOnlineBiz : ParsedHttpSource() {
|
||||
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
override val name = "MangaOnlineBiz"
|
||||
|
||||
override val baseUrl = "https://manga-online.biz"
|
||||
|
@ -68,15 +75,14 @@ class MangaOnlineBiz : ParsedHttpSource() {
|
|||
return popularMangaParse(response)
|
||||
}
|
||||
val jsonData = response.body!!.string()
|
||||
val json = JsonParser().parse(jsonData).asJsonObject
|
||||
val results = json.getAsJsonArray("results")
|
||||
val results = json.decodeFromString<JsonObject>(jsonData)["results"]!!.jsonArray
|
||||
val mangas = mutableListOf<SManga>()
|
||||
results.forEach {
|
||||
val element = it.asJsonObject
|
||||
val element = it.jsonObject
|
||||
val manga = SManga.create()
|
||||
manga.setUrlWithoutDomain(element.get("url").string)
|
||||
manga.title = element.get("title").string.split("/").first()
|
||||
val image = element.get("image").string
|
||||
manga.setUrlWithoutDomain(element["url"]!!.jsonPrimitive.content)
|
||||
manga.title = element["title"]!!.jsonPrimitive.content.split("/").first()
|
||||
val image = element["image"]!!.jsonPrimitive.content
|
||||
if (image.startsWith("http")) {
|
||||
manga.thumbnail_url = image
|
||||
} else {
|
||||
|
@ -130,10 +136,9 @@ class MangaOnlineBiz : ParsedHttpSource() {
|
|||
|
||||
val jsonData = html.split("App.Collection.MangaChapter(").last().split("]);").first() + "]"
|
||||
val mangaName = html.split("mangaName: '").last().split("' });").first()
|
||||
val json = JsonParser().parse(jsonData).asJsonArray
|
||||
val chapterList = mutableListOf<SChapter>()
|
||||
json.forEach {
|
||||
chapterList.add(chapterFromElement(mangaName, it.asJsonObject))
|
||||
json.decodeFromString<JsonArray>(jsonData).forEach {
|
||||
chapterList.add(chapterFromElement(mangaName, it.jsonObject))
|
||||
}
|
||||
return chapterList
|
||||
}
|
||||
|
@ -142,22 +147,22 @@ class MangaOnlineBiz : ParsedHttpSource() {
|
|||
|
||||
private fun chapterFromElement(mangaName: String, element: JsonObject): SChapter {
|
||||
val chapter = SChapter.create()
|
||||
chapter.setUrlWithoutDomain("/$mangaName/${element.get("volume").string}/${element.get("number").string})/1")
|
||||
chapter.name = "Том ${element.get("volume").string} - Глава ${element.get("number").string} ${element.get("title").string}"
|
||||
chapter.chapter_number = element.get("number").float
|
||||
chapter.date_upload = SimpleDateFormat("yyyy-MM-dd", Locale.US).parse(element.get("date").string)?.time ?: 0L
|
||||
chapter.setUrlWithoutDomain("/$mangaName/${element["volume"]!!.jsonPrimitive.content}/${element["number"]!!.jsonPrimitive.content})/1")
|
||||
chapter.name = "Том ${element["volume"]!!.jsonPrimitive.content} - Глава ${element["number"]!!.jsonPrimitive.content} ${element["title"]!!.jsonPrimitive.content}"
|
||||
chapter.chapter_number = element["number"]!!.jsonPrimitive.float
|
||||
chapter.date_upload = SimpleDateFormat("yyyy-MM-dd", Locale.US).parse(element["date"]!!.jsonPrimitive.content)?.time ?: 0L
|
||||
return chapter
|
||||
}
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> {
|
||||
val html = response.body!!.string()
|
||||
val jsonData = html.split("new App.Router.Chapter(").last().split("});").first() + "}"
|
||||
val json = JsonParser().parse(jsonData).asJsonObject
|
||||
val cdnUrl = json.get("srcBaseUrl").string
|
||||
val pages = json.get("pages").asJsonObject
|
||||
val jsonObj = json.decodeFromString<JsonObject>(jsonData)
|
||||
val cdnUrl = jsonObj["srcBaseUrl"]!!.jsonPrimitive.content
|
||||
val pages = jsonObj["pages"]!!.jsonObject
|
||||
val resPages = mutableListOf<Page>()
|
||||
pages.forEach { page, jsonElement ->
|
||||
resPages.add(Page(page.toInt(), imageUrl = "$cdnUrl/${jsonElement.asJsonObject.get("src").string}"))
|
||||
pages.entries.forEach { (page, jsonElement) ->
|
||||
resPages.add(Page(page.toInt(), imageUrl = "$cdnUrl/${jsonElement.jsonObject["src"]!!.jsonPrimitive.content}"))
|
||||
}
|
||||
return resPages
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
apply plugin: 'kotlinx-serialization'
|
||||
|
||||
ext {
|
||||
extName = 'Risens Team'
|
||||
|
|
|
@ -1,14 +1,5 @@
|
|||
package eu.kanade.tachiyomi.extension.ru.risensteam
|
||||
|
||||
import com.github.salomonbrys.kotson.fromJson
|
||||
import com.github.salomonbrys.kotson.get
|
||||
import com.github.salomonbrys.kotson.int
|
||||
import com.github.salomonbrys.kotson.nullString
|
||||
import com.github.salomonbrys.kotson.string
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
|
@ -18,11 +9,22 @@ import eu.kanade.tachiyomi.source.model.Page
|
|||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.contentOrNull
|
||||
import kotlinx.serialization.json.int
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.Response
|
||||
import rx.Observable
|
||||
import uy.kohesive.injekt.injectLazy
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
@ -39,7 +41,7 @@ class RisensTeam : HttpSource() {
|
|||
|
||||
override val versionId: Int = 2
|
||||
|
||||
private val gson by lazy { Gson() }
|
||||
private val json: Json by injectLazy()
|
||||
|
||||
// Popular (source only returns manga sorted by latest)
|
||||
|
||||
|
@ -49,16 +51,16 @@ class RisensTeam : HttpSource() {
|
|||
|
||||
private fun mangaFromJson(json: JsonElement): SManga {
|
||||
return SManga.create().apply {
|
||||
url = "${json["id"].int}/${json["furl"].string}"
|
||||
title = json["title"].string
|
||||
thumbnail_url = baseUrl + json["poster"].string
|
||||
description = json["description"].nullString
|
||||
status = try { if (json["active"].int == 1) SManga.ONGOING else SManga.UNKNOWN } catch (_: Exception) { SManga.UNKNOWN }
|
||||
url = "${json.jsonObject["id"]!!.jsonPrimitive.int}/${json.jsonObject["furl"]!!.jsonPrimitive.content}"
|
||||
title = json.jsonObject["title"]!!.jsonPrimitive.content
|
||||
thumbnail_url = baseUrl + json.jsonObject["poster"]!!.jsonPrimitive.content
|
||||
description = json.jsonObject["description"]!!.jsonPrimitive.contentOrNull
|
||||
status = try { if (json.jsonObject["active"]!!.jsonPrimitive.int == 1) SManga.ONGOING else SManga.UNKNOWN } catch (_: Exception) { SManga.UNKNOWN }
|
||||
}
|
||||
}
|
||||
|
||||
override fun popularMangaParse(response: Response): MangasPage {
|
||||
val mangas = gson.fromJson<JsonArray>(response.body!!.string())
|
||||
val mangas = json.decodeFromString<JsonArray>(response.body!!.string())
|
||||
.map { json -> mangaFromJson(json) }
|
||||
|
||||
return MangasPage(mangas, false)
|
||||
|
@ -98,7 +100,7 @@ class RisensTeam : HttpSource() {
|
|||
}
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga {
|
||||
return mangaFromJson(gson.fromJson<JsonObject>(response.body!!.string()))
|
||||
return mangaFromJson(json.decodeFromString<JsonObject>(response.body!!.string()))
|
||||
}
|
||||
|
||||
// Chapters
|
||||
|
@ -106,11 +108,11 @@ class RisensTeam : HttpSource() {
|
|||
override fun chapterListRequest(manga: SManga): Request = apiMangaDetailsRequest(manga)
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
return gson.fromJson<JsonObject>(response.body!!.string())["entities"].asJsonArray.map { json ->
|
||||
return json.decodeFromString<JsonObject>(response.body!!.string())["entities"]!!.jsonArray.map { json ->
|
||||
SChapter.create().apply {
|
||||
url = json["id"].int.toString()
|
||||
name = listOfNotNull(json["label"].nullString, json["name"].nullString).joinToString(" - ")
|
||||
date_upload = json["updated_at"].toDate()
|
||||
url = json.jsonObject["id"]!!.jsonPrimitive.int.toString()
|
||||
name = listOfNotNull(json.jsonObject["label"]!!.jsonPrimitive.contentOrNull, json.jsonObject["name"]!!.jsonPrimitive.contentOrNull).joinToString(" - ")
|
||||
date_upload = json.jsonObject["updated_at"]!!.toDate()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -120,7 +122,7 @@ class RisensTeam : HttpSource() {
|
|||
}
|
||||
|
||||
private fun JsonElement.toDate(): Long {
|
||||
val date = this.nullString ?: return 0
|
||||
val date = this.jsonPrimitive.contentOrNull ?: return 0
|
||||
return try {
|
||||
simpleDateFormat.parse(date)?.time ?: 0
|
||||
} catch (e: ParseException) {
|
||||
|
@ -135,8 +137,8 @@ class RisensTeam : HttpSource() {
|
|||
}
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> {
|
||||
return gson.fromJson<JsonArray>(response.body!!.string())
|
||||
.mapIndexed { i, json -> Page(i, "", json.string) }
|
||||
return json.decodeFromString<JsonArray>(response.body!!.string())
|
||||
.mapIndexed { i, json -> Page(i, "", json.jsonPrimitive.content) }
|
||||
}
|
||||
|
||||
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException("Not used")
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
package eu.kanade.tachiyomi.extension.th.nekopost.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class RawProjectChapter(
|
||||
@SerializedName("cu_displayname")
|
||||
@SerialName("cu_displayname")
|
||||
val cuDisplayname: String,
|
||||
@SerializedName("nc_chapter_id")
|
||||
@SerialName("nc_chapter_id")
|
||||
val ncChapterId: String,
|
||||
@SerializedName("nc_chapter_name")
|
||||
@SerialName("nc_chapter_name")
|
||||
val ncChapterName: String,
|
||||
@SerializedName("nc_chapter_no")
|
||||
@SerialName("nc_chapter_no")
|
||||
val ncChapterNo: String,
|
||||
@SerializedName("nc_created_date")
|
||||
@SerialName("nc_created_date")
|
||||
val ncCreatedDate: String,
|
||||
@SerializedName("nc_data_file")
|
||||
@SerialName("nc_data_file")
|
||||
val ncDataFile: String,
|
||||
@SerializedName("nc_owner_id")
|
||||
@SerialName("nc_owner_id")
|
||||
val ncOwnerId: String,
|
||||
@SerializedName("nc_provider")
|
||||
@SerialName("nc_provider")
|
||||
val ncProvider: String
|
||||
)
|
||||
|
|
|
@ -1,38 +1,38 @@
|
|||
package eu.kanade.tachiyomi.extension.th.nekopost.model
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
data class RawProjectInfoData(
|
||||
@SerializedName("artist_name")
|
||||
@SerialName("artist_name")
|
||||
val artistName: String,
|
||||
@SerializedName("author_name")
|
||||
@SerialName("author_name")
|
||||
val authorName: String,
|
||||
@SerializedName("np_comment")
|
||||
@SerialName("np_comment")
|
||||
val npComment: String,
|
||||
@SerializedName("np_created_date")
|
||||
@SerialName("np_created_date")
|
||||
val npCreatedDate: String,
|
||||
@SerializedName("np_flag_mature")
|
||||
@SerialName("np_flag_mature")
|
||||
val npFlagMature: String,
|
||||
@SerializedName("np_info")
|
||||
@SerialName("np_info")
|
||||
val npInfo: String,
|
||||
@SerializedName("np_licenced_by")
|
||||
@SerialName("np_licenced_by")
|
||||
val npLicencedBy: String,
|
||||
@SerializedName("np_name")
|
||||
@SerialName("np_name")
|
||||
val npName: String,
|
||||
@SerializedName("np_name_link")
|
||||
@SerialName("np_name_link")
|
||||
val npNameLink: String,
|
||||
@SerializedName("np_project_id")
|
||||
@SerialName("np_project_id")
|
||||
val npProjectId: String,
|
||||
@SerializedName("np_status")
|
||||
@SerialName("np_status")
|
||||
val npStatus: String,
|
||||
@SerializedName("np_type")
|
||||
@SerialName("np_type")
|
||||
val npType: String,
|
||||
@SerializedName("np_updated_date")
|
||||
@SerialName("np_updated_date")
|
||||
val npUpdatedDate: String,
|
||||
@SerializedName("np_view")
|
||||
@SerialName("np_view")
|
||||
val npView: String,
|
||||
@SerializedName("np_web")
|
||||
@SerialName("np_web")
|
||||
val npWeb: String
|
||||
)
|
||||
|
|
Loading…
Reference in New Issue