Convert SY specific usages of Gson to Kotlin Serialization

Cleanup saved searches a bit
Cleanup json parsing
This commit is contained in:
Jobobby04 2020-10-12 14:20:54 -04:00
parent bbfce97125
commit f3365cef67
46 changed files with 490 additions and 366 deletions

View File

@ -2,20 +2,16 @@ package eu.kanade.tachiyomi.data.backup
import android.content.Context
import android.net.Uri
import com.github.salomonbrys.kotson.array
import com.github.salomonbrys.kotson.fromJson
import com.github.salomonbrys.kotson.jsonObject
import com.github.salomonbrys.kotson.obj
import com.github.salomonbrys.kotson.registerTypeAdapter
import com.github.salomonbrys.kotson.registerTypeHierarchyAdapter
import com.github.salomonbrys.kotson.set
import com.github.salomonbrys.kotson.string
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonArray
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.backup.BackupCreateService.Companion.BACKUP_CATEGORY
@ -62,13 +58,16 @@ import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.online.all.EHentai
import eu.kanade.tachiyomi.source.online.all.MergedSource
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
import exh.EXHSavedSearch
import exh.MERGED_SOURCE_ID
import exh.eh.EHentaiThrottleManager
import exh.merged.sql.models.MergedMangaReference
import exh.savedsearches.EXHSavedSearch
import exh.savedsearches.JsonSavedSearch
import exh.util.asObservable
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import rx.Observable
import timber.log.Timber
import uy.kohesive.injekt.Injekt
@ -553,17 +552,17 @@ class BackupManager(val context: Context, version: Int = CURRENT_VERSION) {
val newSavedSearches = backupSavedSearches.mapNotNull {
try {
val id = it.substringBefore(':').toLong()
val content = JsonParser.parseString(it.substringAfter(':')).obj
val content = Json.decodeFromString<JsonSavedSearch>(it.substringAfter(':'))
val source = sourceManager.getOrStub(id)
if (source !is CatalogueSource) return@mapNotNull null
val originalFilters = source.getFilterList()
filterSerializer.deserialize(originalFilters, content["filters"].array)
filterSerializer.deserialize(originalFilters, content.filters)
Pair(
id,
EXHSavedSearch(
content["name"].string,
content["query"].string,
content.name,
content.query,
originalFilters
)
)
@ -580,18 +579,18 @@ class BackupManager(val context: Context, version: Int = CURRENT_VERSION) {
newSavedSearches += preferences.eh_savedSearches().get().mapNotNull {
try {
val id = it.substringBefore(':').toLong()
val content = JsonParser.parseString(it.substringAfter(':')).obj
val content = Json.decodeFromString<JsonSavedSearch>(it.substringAfter(':'))
if (id !in currentSources) return@mapNotNull null
val source = sourceManager.getOrStub(id)
if (source !is CatalogueSource) return@mapNotNull null
val originalFilters = source.getFilterList()
filterSerializer.deserialize(originalFilters, content["filters"].array)
filterSerializer.deserialize(originalFilters, content.filters)
Pair(
id,
EXHSavedSearch(
content["name"].string,
content["query"].string,
content.name,
content.query,
originalFilters
)
)

View File

@ -1,14 +1,19 @@
package eu.kanade.tachiyomi.data.library
import android.content.Context
import com.github.salomonbrys.kotson.nullLong
import com.github.salomonbrys.kotson.nullString
import com.github.salomonbrys.kotson.set
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import com.google.gson.JsonObject
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaImpl
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.encodeToJsonElement
import kotlinx.serialization.json.jsonPrimitive
import kotlinx.serialization.json.longOrNull
import java.io.File
import java.util.Scanner
@ -28,25 +33,24 @@ class CustomMangaManager(val context: Context) {
if (!editJson.exists() || !editJson.isFile) return
val json = try {
Gson().fromJson(
Scanner(editJson).useDelimiter("\\Z").next(),
JsonObject::class.java
Json.decodeFromString<JsonObject>(
Scanner(editJson).useDelimiter("\\Z").next()
)
} catch (e: Exception) {
null
} ?: return
val mangasJson = json.get("mangas").asJsonArray ?: return
val mangasJson = json["mangas"] as? JsonArray ?: return
customMangaMap = mangasJson.mapNotNull { element ->
val mangaObject = element.asJsonObject ?: return@mapNotNull null
val id = mangaObject["id"]?.nullLong ?: return@mapNotNull null
val mangaObject = element as? JsonObject ?: return@mapNotNull null
val id = mangaObject["id"]?.jsonPrimitive?.longOrNull ?: return@mapNotNull null
val manga = MangaImpl().apply {
this.id = id
title = mangaObject["title"]?.nullString ?: ""
author = mangaObject["author"]?.nullString
artist = mangaObject["artist"]?.nullString
description = mangaObject["description"]?.nullString
genre = mangaObject["genre"]?.asJsonArray?.mapNotNull { it.nullString }
title = mangaObject["title"]?.jsonPrimitive?.contentOrNull ?: ""
author = mangaObject["author"]?.jsonPrimitive?.contentOrNull
artist = mangaObject["artist"]?.jsonPrimitive?.contentOrNull
description = mangaObject["description"]?.jsonPrimitive?.contentOrNull
genre = (mangaObject["genre"] as? JsonArray)?.mapNotNull { it.jsonPrimitive.contentOrNull }
?.joinToString(", ")
}
id to manga
@ -72,17 +76,16 @@ class CustomMangaManager(val context: Context) {
private fun saveCustomInfo() {
val jsonElements = customMangaMap.values.map { it.toJson() }
if (jsonElements.isNotEmpty()) {
val gson = GsonBuilder().create()
val root = JsonObject()
val mangaEntries = gson.toJsonTree(jsonElements)
root["mangas"] = mangaEntries
val mangaEntries = Json.encodeToJsonElement(jsonElements)
val root = buildJsonObject {
put("mangas", mangaEntries)
}
editJson.delete()
editJson.writeText(gson.toJson(root))
editJson.writeText(Json.encodeToString(root))
}
}
fun Manga.toJson(): MangaJson {
private fun Manga.toJson(): MangaJson {
return MangaJson(
id!!,
title,
@ -93,6 +96,7 @@ class CustomMangaManager(val context: Context) {
)
}
@Serializable
data class MangaJson(
val id: Long,
val title: String? = null,

View File

@ -1,8 +1,6 @@
package eu.kanade.tachiyomi.extension.api
import android.content.Context
import com.github.salomonbrys.kotson.get
import com.github.salomonbrys.kotson.int
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.extension.model.Extension
import eu.kanade.tachiyomi.extension.model.LoadResult

View File

@ -1,7 +1,6 @@
package eu.kanade.tachiyomi.source
import android.content.Context
import com.google.gson.GsonBuilder
import com.google.gson.JsonParser
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@ -18,6 +17,9 @@ import eu.kanade.tachiyomi.util.storage.EpubFile
import eu.kanade.tachiyomi.util.system.ImageUtil
import junrar.Archive
import junrar.rarfile.FileHeader
import kotlinx.serialization.Serializable
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import rx.Observable
import timber.log.Timber
import uy.kohesive.injekt.Injekt
@ -154,16 +156,19 @@ class LocalSource(private val context: Context) : CatalogueSource {
val directory = getBaseDirectories(context).mapNotNull { File(it, manga.url) }.find {
it.exists()
} ?: return
val gson = GsonBuilder().setPrettyPrinting().create()
val json = Json {
prettyPrint = true
}
val existingFileName = directory.listFiles()?.find { it.extension == "json" }?.name
val file = File(directory, existingFileName ?: "info.json")
file.writeText(gson.toJson(manga.toJson()))
file.writeText(json.encodeToString(manga.toJson()))
}
fun SManga.toJson(): MangaJson {
private fun SManga.toJson(): MangaJson {
return MangaJson(title, author, artist, description, genre?.split(", ")?.toTypedArray())
}
@Serializable
data class MangaJson(
val title: String,
val author: String?,

View File

@ -3,15 +3,6 @@ package eu.kanade.tachiyomi.source.online.all
import android.content.Context
import android.net.Uri
import com.elvishew.xlog.XLog
import com.github.salomonbrys.kotson.array
import com.github.salomonbrys.kotson.get
import com.github.salomonbrys.kotson.int
import com.github.salomonbrys.kotson.obj
import com.github.salomonbrys.kotson.set
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.annoations.Nsfw
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
@ -57,6 +48,17 @@ import exh.util.trimAll
import exh.util.trimOrNull
import exh.util.urlImportFetchSearchManga
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.add
import kotlinx.serialization.json.buildJsonArray
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.put
import okhttp3.CacheControl
import okhttp3.CookieJar
import okhttp3.Headers
@ -938,29 +940,33 @@ class EHentai(
val gallery = lastSplit.first()
val pageToken = uri.pathSegments.elementAt(1)
val json = JsonObject()
json["method"] = "gtoken"
json["pagelist"] = JsonArray().apply {
add(
JsonArray().apply {
add(gallery.toInt())
add(pageToken)
add(pageNum.toInt())
val json = buildJsonObject {
put("method", "gtoken")
put(
"pagelist",
buildJsonArray {
add(
buildJsonArray {
add(gallery.toInt())
add(pageToken)
add(pageNum.toInt())
}
)
}
)
}
val outJson = JsonParser.parseString(
val outJson = Json.decodeFromString<JsonObject>(
client.newCall(
Request.Builder()
.url(EH_API_BASE)
.post(json.toString().toRequestBody(JSON))
.build()
).execute().body!!.string()
).obj
)
val obj = outJson["tokenlist"].array.first()
return "${uri.scheme}://${uri.host}/g/${obj["gid"].int}/${obj["token"].string}/"
val obj = outJson["tokenlist"]!!.jsonArray.first().jsonObject
return "${uri.scheme}://${uri.host}/g/${obj["gid"]!!.jsonPrimitive.int}/${obj["token"]!!.jsonPrimitive.content}/"
}
override fun getDescriptionAdapter(controller: MangaController): EHentaiDescriptionAdapter {

View File

@ -68,8 +68,8 @@ class Hitomi(delegate: HttpSource, val context: Context) :
tags += RaisedTag("group", group!!, RaisedSearchMetadata.TAG_TYPE_VIRTUAL)
}
"type" -> {
type = content.text()
tags += RaisedTag("type", type!!, RaisedSearchMetadata.TAG_TYPE_VIRTUAL)
genre = content.text()
tags += RaisedTag("type", genre!!, RaisedSearchMetadata.TAG_TYPE_VIRTUAL)
}
"series" -> {
series = content.select("a").map { it.text() }

View File

@ -2,12 +2,7 @@ package eu.kanade.tachiyomi.source.online.all
import android.content.Context
import android.net.Uri
import com.github.salomonbrys.kotson.get
import com.github.salomonbrys.kotson.nullArray
import com.github.salomonbrys.kotson.nullLong
import com.github.salomonbrys.kotson.nullObj
import com.github.salomonbrys.kotson.nullString
import com.google.gson.JsonParser
import com.elvishew.xlog.XLog
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
@ -23,6 +18,10 @@ import exh.metadata.metadata.base.RaisedTag
import exh.source.DelegatedHttpSource
import exh.ui.metadata.adapters.NHentaiDescriptionAdapter
import exh.util.urlImportFetchSearchManga
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import okhttp3.Response
import rx.Observable
@ -58,41 +57,40 @@ class NHentai(delegate: HttpSource, val context: Context) :
val json = GALLERY_JSON_REGEX.find(input.body!!.string())!!.groupValues[1].replace(
UNICODE_ESCAPE_REGEX
) { it.groupValues[1].toInt(radix = 16).toChar().toString() }
val obj = JsonParser.parseString(json).asJsonObject
val jsonResponse = jsonParser.decodeFromString<JsonResponse>(json)
with(metadata) {
nhId = obj["id"].asLong
nhId = jsonResponse.id
uploadDate = obj["upload_date"].nullLong
uploadDate = jsonResponse.uploadDate
favoritesCount = obj["num_favorites"].nullLong
favoritesCount = jsonResponse.numFavorites
mediaId = obj["media_id"].nullString
mediaId = jsonResponse.mediaId
obj["title"].nullObj?.let { title ->
japaneseTitle = title["japanese"].nullString
shortTitle = title["pretty"].nullString
englishTitle = title["english"].nullString
jsonResponse.title?.let { title ->
japaneseTitle = title.japanese
shortTitle = title.pretty
englishTitle = title.english
}
obj["images"].nullObj?.let { images ->
coverImageType = images["cover"]?.get("t").nullString
images["pages"].nullArray?.mapNotNull {
it?.asJsonObject?.get("t").nullString
}?.let {
jsonResponse.images?.let { images ->
coverImageType = images.cover?.type
images.pages.mapNotNull {
it.type
}.let {
pageImageTypes = it
}
thumbnailImageType = images["thumbnail"]?.get("t").nullString
thumbnailImageType = images.thumbnail?.type
}
scanlator = obj["scanlator"].nullString
scanlator = jsonResponse.scanlator
obj["tags"]?.asJsonArray?.map {
val asObj = it.asJsonObject
Pair(asObj["type"].nullString, asObj["name"].nullString)
}?.apply {
jsonResponse.tags.map {
it.type to it.name
}.apply {
tags.clear()
}?.forEach {
}.forEach {
if (it.first != null && it.second != null) {
tags.add(RaisedTag(it.first!!, it.second!!, if (it.first == "category") RaisedSearchMetadata.TAG_TYPE_VIRTUAL else NHentaiSearchMetadata.TAG_TYPE_DEFAULT))
}
@ -100,6 +98,49 @@ class NHentai(delegate: HttpSource, val context: Context) :
}
}
@Serializable
data class JsonResponse(
val id: Long,
@SerialName("media_id") val mediaId: String? = null,
val title: JsonTitle? = null,
val images: JsonImages? = null,
val scanlator: String? = null,
@SerialName("upload_date") val uploadDate: Long? = null,
val tags: List<JsonTag> = emptyList(),
@SerialName("num_pages") val numPages: Int? = null,
@SerialName("num_favorites") val numFavorites: Long? = null
)
@Serializable
data class JsonTitle(
val english: String? = null,
val japanese: String? = null,
val pretty: String? = null
)
@Serializable
data class JsonImages(
val pages: List<JsonPage> = emptyList(),
val cover: JsonPage? = null,
val thumbnail: JsonPage? = null
)
@Serializable
data class JsonPage(
@SerialName("t") val type: String? = null,
@SerialName("w") val width: String? = null,
@SerialName("h") val height: String? = null
)
@Serializable
data class JsonTag(
val id: Long? = null,
val type: String? = null,
val name: String? = null,
val url: String? = null,
val count: Long? = null
)
override fun toString() = "$name (${lang.toUpperCase()})"
override fun ensureDelegateCompatible() {
@ -127,6 +168,10 @@ class NHentai(delegate: HttpSource, val context: Context) :
companion object {
const val otherId = 7309872737163460316L
private val jsonParser = Json {
ignoreUnknownKeys = true
}
private val GALLERY_JSON_REGEX = Regex(".parse\\(\"(.*)\"\\);")
private val UNICODE_ESCAPE_REGEX = Regex("\\\\u([0-9a-fA-F]{4})")
}

View File

@ -96,7 +96,7 @@ class PervEden(delegate: HttpSource, val context: Context) :
if (it is TextNode) {
val text = it.text().trim()
if (!text.isBlank()) {
type = text
genre = text
}
}
}

View File

@ -53,8 +53,8 @@ import eu.kanade.tachiyomi.util.view.shrinkOnScroll
import eu.kanade.tachiyomi.util.view.snack
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
import eu.kanade.tachiyomi.widget.EmptyView
import exh.EXHSavedSearch
import exh.isEhBasedSource
import exh.savedsearches.EXHSavedSearch
import exh.source.EnhancedHttpSource.Companion.getMainSource
import kotlinx.android.parcel.Parcelize
import kotlinx.android.synthetic.main.main_activity.root_coordinator

View File

@ -1,11 +1,6 @@
package eu.kanade.tachiyomi.ui.browse.source.browse
import android.os.Bundle
import com.github.salomonbrys.kotson.array
import com.github.salomonbrys.kotson.jsonObject
import com.github.salomonbrys.kotson.obj
import com.github.salomonbrys.kotson.string
import com.google.gson.JsonParser
import eu.davidea.flexibleadapter.items.IFlexible
import eu.davidea.flexibleadapter.items.ISectionable
import eu.kanade.tachiyomi.data.cache.CoverCache
@ -38,7 +33,14 @@ import eu.kanade.tachiyomi.ui.browse.source.filter.TriStateItem
import eu.kanade.tachiyomi.ui.browse.source.filter.TriStateSectionItem
import eu.kanade.tachiyomi.util.chapter.ChapterSettingsHelper
import eu.kanade.tachiyomi.util.removeCovers
import exh.EXHSavedSearch
import exh.savedsearches.EXHSavedSearch
import exh.savedsearches.JsonSavedSearch
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.put
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
@ -134,8 +136,8 @@ open class BrowseSourcePresenter(
// SY -->
if (filters != null) {
val filters = JsonParser.parseString(filters).obj
filterSerializer.deserialize(sourceFilters, filters["filters"].array)
val filters = Json.decodeFromString<JsonObject>(filters)
filterSerializer.deserialize(sourceFilters, filters["filters"]!!.jsonArray)
}
val allDefault = sourceFilters == source.getFilterList()
// SY <--
@ -446,11 +448,11 @@ open class BrowseSourcePresenter(
!it.startsWith("${source.id}:")
}
val newSerialized = searches.map {
"${source.id}:" + jsonObject(
"name" to it.name,
"query" to it.query,
"filters" to filterSerializer.serialize(it.filterList)
).toString()
"${source.id}:" + buildJsonObject {
put("name", it.name)
put("query", it.query)
put("filters", filterSerializer.serialize(it.filterList))
}.toString()
}
prefs.eh_savedSearches().set((otherSerialized + newSerialized).toSet())
}
@ -461,12 +463,12 @@ open class BrowseSourcePresenter(
try {
val id = it.substringBefore(':').toLong()
if (id != source.id) return@map null
val content = JsonParser.parseString(it.substringAfter(':')).obj
val content = Json.decodeFromString<JsonSavedSearch>(it.substringAfter(':'))
val originalFilters = source.getFilterList()
filterSerializer.deserialize(originalFilters, content["filters"].array)
filterSerializer.deserialize(originalFilters, content.filters)
EXHSavedSearch(
content["name"].string,
content["query"].string,
content.name,
content.query,
originalFilters
)
} catch (t: RuntimeException) {

View File

@ -1,16 +1,5 @@
package eu.kanade.tachiyomi.ui.browse.source.browse
import com.github.salomonbrys.kotson.array
import com.github.salomonbrys.kotson.get
import com.github.salomonbrys.kotson.jsonObject
import com.github.salomonbrys.kotson.nullArray
import com.github.salomonbrys.kotson.nullObj
import com.github.salomonbrys.kotson.nullString
import com.github.salomonbrys.kotson.obj
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.data.database.models.Manga
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.model.MangasPage
@ -22,6 +11,15 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import kotlinx.serialization.json.put
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.OkHttpClient
@ -73,17 +71,18 @@ class MyAnimeList() : API("https://api.jikan.moe/v3/") {
if (body.isEmpty()) {
throw Exception("Null Response")
}
val data = JsonParser.parseString(body).obj
val recommendations = data["recommendations"].nullArray
val data = Json.decodeFromString<JsonObject>(body)
val recommendations = data["recommendations"] as? JsonArray
?: throw Exception("Unexpected response")
val recs = recommendations.map { rec ->
rec as? JsonObject ?: throw Exception("Invalid json")
Timber.tag("RECOMMENDATIONS")
.d("MYANIMELIST > FOUND RECOMMENDATION > %s", rec["title"].string)
.d("MYANIMELIST > FOUND RECOMMENDATION > %s", rec["title"]!!.jsonPrimitive.content)
SMangaImpl().apply {
this.title = rec["title"].string
this.thumbnail_url = rec["image_url"].string
this.title = rec["title"]!!.jsonPrimitive.content
this.thumbnail_url = rec["image_url"]!!.jsonPrimitive.content
this.initialized = true
this.url = rec["url"].string
this.url = rec["url"]!!.jsonPrimitive.content
}
}
callback.invoke(recs, null)
@ -121,15 +120,15 @@ class MyAnimeList() : API("https://api.jikan.moe/v3/") {
if (body.isEmpty()) {
throw Exception("Null Response")
}
val data = JsonParser.parseString(body).obj
val results = data["results"].nullArray ?: throw Exception("Unexpected response")
if (results.size() <= 0) {
val data = Json.decodeFromString<JsonObject>(body)
val results = data["results"] as? JsonArray ?: throw Exception("Unexpected response")
if (results.size <= 0) {
throw Exception("'$search' not found")
}
val result = results.first().obj
val result = results.first().jsonObject
Timber.tag("RECOMMENDATIONS")
.d("MYANIMELIST > FOUND TITLE > %s", result["title"].string)
val id = result["mal_id"].string
.d("MYANIMELIST > FOUND TITLE > %s", result["title"]!!.jsonPrimitive.content)
val id = result["mal_id"]!!.jsonPrimitive.content
getRecsById(id, callback)
}
}
@ -138,19 +137,21 @@ class MyAnimeList() : API("https://api.jikan.moe/v3/") {
class Anilist() : API("https://graphql.anilist.co/") {
private fun countOccurrence(arr: JsonArray, search: String): Int {
return arr.count {
val synonym = it.string
val synonym = it.jsonPrimitive.content
synonym.contains(search, true)
}
}
private fun languageContains(obj: JsonObject, language: String, search: String): Boolean {
return obj["title"].obj[language].nullString?.contains(search, true) == true
return obj["title"]?.jsonObject?.get(language)?.jsonPrimitive?.content?.contains(search, true) == true
}
private fun getTitle(obj: JsonObject): String {
return obj["title"].obj["romaji"].nullString
?: obj["title"].obj["english"].nullString
?: obj["title"].obj["native"].string
return obj["title"]!!.jsonObject.let {
it["romaji"]?.jsonPrimitive?.content
?: it["english"]?.jsonPrimitive?.content
?: it["native"]!!.jsonPrimitive.content
}
}
override fun getRecsBySearch(
@ -189,11 +190,13 @@ class Anilist() : API("https://graphql.anilist.co/") {
|}
|}
|""".trimMargin()
val variables = jsonObject("search" to search)
val payload = jsonObject(
"query" to query,
"variables" to variables
)
val variables = buildJsonObject {
put("search", search)
}
val payload = buildJsonObject {
put("query", query)
put("variables", variables)
}
val payloadBody =
payload.toString().toRequestBody("application/json; charset=utf-8".toMediaTypeOrNull())
val request = Request.Builder()
@ -211,33 +214,33 @@ class Anilist() : API("https://graphql.anilist.co/") {
if (body.isEmpty()) {
throw Exception("Null Response")
}
val data = JsonParser.parseString(body).obj["data"].nullObj
val data = Json.decodeFromString<JsonObject>(body)["data"] as? JsonObject
?: throw Exception("Unexpected response")
val page = data["Page"].obj
val media = page["media"].array
if (media.size() <= 0) {
val page = data["Page"]!!.jsonObject
val media = page["media"]!!.jsonArray
if (media.size <= 0) {
throw Exception("'$search' not found")
}
val result = media.sortedWith(
compareBy(
{ languageContains(it.obj, "romaji", search) },
{ languageContains(it.obj, "english", search) },
{ languageContains(it.obj, "native", search) },
{ countOccurrence(it.obj["synonyms"].array, search) > 0 }
{ languageContains(it.jsonObject, "romaji", search) },
{ languageContains(it.jsonObject, "english", search) },
{ languageContains(it.jsonObject, "native", search) },
{ countOccurrence(it.jsonObject["synonyms"]!!.jsonArray, search) > 0 }
)
).last().obj
).last().jsonObject
Timber.tag("RECOMMENDATIONS")
.d("ANILIST > FOUND TITLE > %s", getTitle(result))
val recommendations = result["recommendations"].obj["edges"].array
val recommendations = result["recommendations"]!!.jsonObject["edges"]!!.jsonArray
val recs = recommendations.map {
val rec = it["node"]["mediaRecommendation"].obj
val rec = it.jsonObject["node"]!!.jsonObject["mediaRecommendation"]!!.jsonObject
Timber.tag("RECOMMENDATIONS")
.d("ANILIST: FOUND RECOMMENDATION: %s", getTitle(rec))
SMangaImpl().apply {
this.title = getTitle(rec)
this.thumbnail_url = rec["coverImage"].obj["large"].string
this.thumbnail_url = rec["coverImage"]!!.jsonObject["large"]!!.jsonPrimitive.content
this.initialized = true
this.url = rec["siteUrl"].string
this.url = rec["siteUrl"]!!.jsonPrimitive.content
}
}
callback.invoke(recs, null)

View File

@ -18,7 +18,7 @@ import eu.kanade.tachiyomi.databinding.SourceFilterSheetBinding
import eu.kanade.tachiyomi.source.CatalogueSource
import eu.kanade.tachiyomi.source.online.BrowseSourceFilterHeader
import eu.kanade.tachiyomi.widget.SimpleNavigationView
import exh.EXHSavedSearch
import exh.savedsearches.EXHSavedSearch
import exh.source.EnhancedHttpSource.Companion.getMainSource
class SourceFilterSheet(

View File

@ -11,7 +11,6 @@ import androidx.core.view.isVisible
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.afollestad.materialdialogs.MaterialDialog
import com.github.salomonbrys.kotson.jsonObject
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.models.Manga
@ -30,6 +29,7 @@ import exh.util.nullIfBlank
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.serialization.json.buildJsonObject
import reactivecircus.flowbinding.android.view.clicks
import reactivecircus.flowbinding.appcompat.QueryTextEvent
import reactivecircus.flowbinding.appcompat.queryTextEvents
@ -203,7 +203,7 @@ open class IndexController :
val allDefault = presenter.sourceFilters == presenter.source.getFilterList()
filterSheet?.dismiss()
if (!allDefault) {
val json = jsonObject("filters" to filterSerializer.serialize(presenter.sourceFilters))
val json = buildJsonObject { put("filters", filterSerializer.serialize(presenter.sourceFilters)) }
onBrowseClick(presenter.query.nullIfBlank(), json.toString())
}
},
@ -232,7 +232,7 @@ open class IndexController :
filterSheet?.dismiss()
if (!allDefault) {
val json = jsonObject("filters" to filterSerializer.serialize(presenter.sourceFilters))
val json = buildJsonObject { put("filters", filterSerializer.serialize(presenter.sourceFilters)) }
onBrowseClick(presenter.query.nullIfBlank(), json.toString())
}
},

View File

@ -1,10 +1,6 @@
package eu.kanade.tachiyomi.ui.browse.source.index
import android.os.Bundle
import com.github.salomonbrys.kotson.array
import com.github.salomonbrys.kotson.obj
import com.github.salomonbrys.kotson.string
import com.google.gson.JsonParser
import eu.davidea.flexibleadapter.items.IFlexible
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga
@ -15,7 +11,8 @@ import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.ui.base.presenter.BasePresenter
import eu.kanade.tachiyomi.ui.browse.source.browse.BrowseSourcePresenter.Companion.toItems
import exh.EXHSavedSearch
import exh.savedsearches.EXHSavedSearch
import exh.savedsearches.JsonSavedSearch
import exh.util.asFlow
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -23,6 +20,8 @@ import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.singleOrNull
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import rx.Observable
import rx.Subscription
import rx.android.schedulers.AndroidSchedulers
@ -232,12 +231,12 @@ open class IndexPresenter(
try {
val id = it.substringBefore(':').toLong()
if (id != source.id) return@map null
val content = JsonParser.parseString(it.substringAfter(':')).obj
val content = Json.decodeFromString<JsonSavedSearch>(it.substringAfter(':'))
val originalFilters = source.getFilterList()
filterSerializer.deserialize(originalFilters, content["filters"].array)
filterSerializer.deserialize(originalFilters, content.filters)
EXHSavedSearch(
content["name"].string,
content["query"].string,
content.name,
content.query,
originalFilters
)
} catch (t: RuntimeException) {

View File

@ -12,8 +12,6 @@ import com.afollestad.materialdialogs.input.getInputField
import com.afollestad.materialdialogs.input.input
import com.bluelinelabs.conductor.RouterTransaction
import com.bluelinelabs.conductor.changehandler.FadeChangeHandler
import com.github.salomonbrys.kotson.fromJson
import com.google.gson.Gson
import com.tfcporciuncula.flow.Preference
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
@ -116,6 +114,8 @@ import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.take
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy
import java.util.Date
import kotlin.time.Duration
@ -128,7 +128,6 @@ import kotlin.time.hours
*/
class SettingsEhController : SettingsController() {
private val gson: Gson by injectLazy()
private val db: DatabaseHelper by injectLazy()
private fun Preference<*>.reconfigure(): Boolean {
@ -687,7 +686,7 @@ class SettingsEhController : SettingsController() {
val updateInfo = try {
val stats =
preferences.eh_autoUpdateStats().get().nullIfBlank()?.let {
gson.fromJson<EHentaiUpdaterStats>(it)
Json.decodeFromString<EHentaiUpdaterStats>(it)
}
val statsText = if (stats != null) {

View File

@ -2,9 +2,6 @@ package exh
import android.content.Context
import com.elvishew.xlog.XLog
import com.github.salomonbrys.kotson.fromJson
import com.google.gson.Gson
import com.google.gson.annotations.SerializedName
import com.pushtorefresh.storio.sqlite.queries.Query
import com.pushtorefresh.storio.sqlite.queries.RawQuery
import eu.kanade.tachiyomi.BuildConfig
@ -28,6 +25,10 @@ import eu.kanade.tachiyomi.source.online.all.Hitomi
import eu.kanade.tachiyomi.source.online.all.NHentai
import exh.merged.sql.models.MergedMangaReference
import exh.source.BlacklistedSources
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy
import java.io.File
import java.net.URI
@ -36,7 +37,6 @@ import java.net.URISyntaxException
object EXHMigrations {
private val db: DatabaseHelper by injectLazy()
private val sourceManager: SourceManager by injectLazy()
private val gson: Gson by injectLazy()
private val logger = XLog.tag("EXHMigrations")
@ -167,7 +167,7 @@ object EXHMigrations {
.executeAsBlocking()
if (mergedMangas.isNotEmpty()) {
val mangaConfigs = mergedMangas.mapNotNull { mergedManga -> readMangaConfig(mergedManga, gson)?.let { mergedManga to it } }
val mangaConfigs = mergedMangas.mapNotNull { mergedManga -> readMangaConfig(mergedManga)?.let { mergedManga to it } }
if (mangaConfigs.isNotEmpty()) {
val mangaToUpdate = mutableListOf<Manga>()
val mergedMangaReferences = mutableListOf<MergedMangaReference>()
@ -237,7 +237,7 @@ object EXHMigrations {
.prepare()
.executeAsBlocking()
val mergedMangaChaptersMatched = mergedMangaChapters.mapNotNull { chapter -> loadedMangaList.firstOrNull { it.manga.id == chapter.id }?.let { it to chapter } }
val parsedChapters = chapters.filter { it.read || it.last_page_read != 0 }.mapNotNull { chapter -> readUrlConfig(chapter.url, gson)?.let { chapter to it } }
val parsedChapters = chapters.filter { it.read || it.last_page_read != 0 }.mapNotNull { chapter -> readUrlConfig(chapter.url)?.let { chapter to it } }
val chaptersToUpdate = mutableListOf<Chapter>()
parsedChapters.forEach { parsedChapter ->
mergedMangaChaptersMatched.firstOrNull { it.second.url == parsedChapter.second.url && it.first.source.id == parsedChapter.second.source && it.first.manga.url == parsedChapter.second.mangaUrl }?.let {
@ -339,23 +339,25 @@ object EXHMigrations {
}
}
@Serializable
private data class UrlConfig(
@SerializedName("s")
@SerialName("s")
val source: Long,
@SerializedName("u")
@SerialName("u")
val url: String,
@SerializedName("m")
@SerialName("m")
val mangaUrl: String
)
@Serializable
private data class MangaConfig(
@SerializedName("c")
@SerialName("c")
val children: List<MangaSource>
) {
companion object {
fun readFromUrl(gson: Gson, url: String): MangaConfig? {
fun readFromUrl(url: String): MangaConfig? {
return try {
gson.fromJson(url)
Json.decodeFromString(url)
} catch (e: Exception) {
null
}
@ -363,14 +365,15 @@ object EXHMigrations {
}
}
private fun readMangaConfig(manga: SManga, gson: Gson): MangaConfig? {
return MangaConfig.readFromUrl(gson, manga.url)
private fun readMangaConfig(manga: SManga): MangaConfig? {
return MangaConfig.readFromUrl(manga.url)
}
@Serializable
private data class MangaSource(
@SerializedName("s")
@SerialName("s")
val source: Long,
@SerializedName("u")
@SerialName("u")
val url: String
) {
fun load(db: DatabaseHelper, sourceManager: SourceManager): LoadedMangaSource? {
@ -380,9 +383,9 @@ object EXHMigrations {
}
}
private fun readUrlConfig(url: String, gson: Gson): UrlConfig? {
private fun readUrlConfig(url: String): UrlConfig? {
return try {
gson.fromJson(url)
Json.decodeFromString(url)
} catch (e: Exception) {
null
}

View File

@ -2,11 +2,6 @@ package exh.debug
import android.app.Application
import com.elvishew.xlog.XLog
import com.github.salomonbrys.kotson.array
import com.github.salomonbrys.kotson.jsonObject
import com.github.salomonbrys.kotson.obj
import com.github.salomonbrys.kotson.string
import com.google.gson.JsonParser
import com.pushtorefresh.storio.sqlite.queries.RawQuery
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.tables.MangaTable
@ -16,13 +11,13 @@ import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.SourceManager.Companion.currentDelegatedSources
import exh.EH_SOURCE_ID
import exh.EXHMigrations
import exh.EXHSavedSearch
import exh.EXH_SOURCE_ID
import exh.eh.EHentaiThrottleManager
import exh.eh.EHentaiUpdateWorker
import exh.metadata.metadata.EHentaiSearchMetadata
import exh.metadata.metadata.base.getFlatMetadataForManga
import exh.metadata.metadata.base.insertFlatMetadata
import exh.savedsearches.JsonSavedSearch
import exh.util.await
import exh.util.cancellable
import exh.util.jobScheduler
@ -31,8 +26,10 @@ import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import uy.kohesive.injekt.injectLazy
import xyz.nulldev.ts.api.http.serializer.FilterSerializer
import java.lang.RuntimeException
@OptIn(FlowPreview::class)
@ -236,22 +233,13 @@ object DebugFunctions {
fun copyEHentaiSavedSearchesToExhentai() {
runBlocking {
val filterSerializer = FilterSerializer()
val source = sourceManager.get(EH_SOURCE_ID) as? CatalogueSource ?: return@runBlocking
val newSource = sourceManager.get(EXH_SOURCE_ID) as? CatalogueSource ?: return@runBlocking
val savedSearches = prefs.eh_savedSearches().get().mapNotNull {
try {
val id = it.substringBefore(':').toLong()
if (id != source.id) return@mapNotNull null
val content = JsonParser.parseString(it.substringAfter(':')).obj
val originalFilters = source.getFilterList()
filterSerializer.deserialize(originalFilters, content["filters"].array)
EXHSavedSearch(
content["name"].string,
content["query"].string,
originalFilters
)
Json.decodeFromString<JsonSavedSearch>(it.substringAfter(':'))
} catch (t: RuntimeException) {
// Load failed
XLog.e("Failed to load saved search!", t)
@ -263,15 +251,7 @@ object DebugFunctions {
try {
val id = it.substringBefore(':').toLong()
if (id != newSource.id) return@mapNotNull null
val content = JsonParser.parseString(it.substringAfter(':')).obj
val originalFilters = source.getFilterList()
filterSerializer.deserialize(originalFilters, content["filters"].array)
EXHSavedSearch(
content["name"].string,
content["query"].string,
originalFilters
)
Json.decodeFromString<JsonSavedSearch>(it.substringAfter(':'))
} catch (t: RuntimeException) {
// Load failed
XLog.e("Failed to load saved search!", t)
@ -284,11 +264,7 @@ object DebugFunctions {
!it.startsWith("${newSource.id}:")
}
val newSerialized = savedSearches.map {
"${newSource.id}:" + jsonObject(
"name" to it.name,
"query" to it.query,
"filters" to filterSerializer.serialize(it.filterList)
).toString()
"${newSource.id}:" + Json.encodeToString(it)
}
prefs.eh_savedSearches().set((otherSerialized + newSerialized).toSet())
}
@ -296,22 +272,13 @@ object DebugFunctions {
fun copyExhentaiSavedSearchesToEHentai() {
runBlocking {
val filterSerializer = FilterSerializer()
val source = sourceManager.get(EXH_SOURCE_ID) as? CatalogueSource ?: return@runBlocking
val newSource = sourceManager.get(EH_SOURCE_ID) as? CatalogueSource ?: return@runBlocking
val savedSearches = prefs.eh_savedSearches().get().mapNotNull {
try {
val id = it.substringBefore(':').toLong()
if (id != source.id) return@mapNotNull null
val content = JsonParser.parseString(it.substringAfter(':')).obj
val originalFilters = source.getFilterList()
filterSerializer.deserialize(originalFilters, content["filters"].array)
EXHSavedSearch(
content["name"].string,
content["query"].string,
originalFilters
)
Json.decodeFromString<JsonSavedSearch>(it.substringAfter(':'))
} catch (t: RuntimeException) {
// Load failed
XLog.e("Failed to load saved search!", t)
@ -323,15 +290,7 @@ object DebugFunctions {
try {
val id = it.substringBefore(':').toLong()
if (id != newSource.id) return@mapNotNull null
val content = JsonParser.parseString(it.substringAfter(':')).obj
val originalFilters = source.getFilterList()
filterSerializer.deserialize(originalFilters, content["filters"].array)
EXHSavedSearch(
content["name"].string,
content["query"].string,
originalFilters
)
Json.decodeFromString<JsonSavedSearch>(it.substringAfter(':'))
} catch (t: RuntimeException) {
// Load failed
XLog.e("Failed to load saved search!", t)
@ -344,11 +303,7 @@ object DebugFunctions {
!it.startsWith("${newSource.id}:")
}
val newSerialized = savedSearches.map {
"${newSource.id}:" + jsonObject(
"name" to it.name,
"query" to it.query,
"filters" to filterSerializer.serialize(it.filterList)
).toString()
"${newSource.id}:" + Json.encodeToString(it)
}
prefs.eh_savedSearches().set((otherSerialized + newSerialized).toSet())
}

View File

@ -8,7 +8,6 @@ import android.content.ComponentName
import android.content.Context
import android.os.Build
import com.elvishew.xlog.XLog
import com.google.gson.Gson
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
@ -38,6 +37,8 @@ import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import rx.schedulers.Schedulers
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -54,7 +55,6 @@ class EHentaiUpdateWorker : JobService(), CoroutineScope {
private val db: DatabaseHelper by injectLazy()
private val prefs: PreferencesHelper by injectLazy()
private val gson: Gson by injectLazy()
private val sourceManager: SourceManager by injectLazy()
private val updateHelper: EHentaiUpdateHelper by injectLazy()
private val logger = XLog.tag("EHUpdater")
@ -242,7 +242,7 @@ class EHentaiUpdateWorker : JobService(), CoroutineScope {
}
} finally {
prefs.eh_autoUpdateStats().set(
gson.toJson(
Json.encodeToString(
EHentaiUpdaterStats(
startTime,
allMeta.size,

View File

@ -1,5 +1,8 @@
package exh.eh
import kotlinx.serialization.Serializable
@Serializable
data class EHentaiUpdaterStats(
val startTime: Long,
val possibleUpdates: Int,

View File

@ -1,20 +1,19 @@
package exh.log
import com.elvishew.xlog.XLog
import com.google.gson.Gson
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
fun OkHttpClient.Builder.maybeInjectEHLogger(): OkHttpClient.Builder {
if (EHLogLevel.shouldLog(EHLogLevel.EXTREME)) {
val logger: HttpLoggingInterceptor.Logger = object : HttpLoggingInterceptor.Logger {
override fun log(message: String) {
try {
Gson().fromJson(message, Any::class.java)
XLog.tag("||EH-NETWORK-JSON").nst().json(message)
} catch (ex: Exception) {
XLog.tag("||EH-NETWORK").nb().nst().d(message)
}
val logger: HttpLoggingInterceptor.Logger = HttpLoggingInterceptor.Logger { message ->
try {
Json.decodeFromString<Any>(message)
XLog.tag("||EH-NETWORK-JSON").nst().json(message)
} catch (ex: Exception) {
XLog.tag("||EH-NETWORK").nb().nst().d(message)
}
}
return addInterceptor(HttpLoggingInterceptor(logger).apply { level = HttpLoggingInterceptor.Level.BODY })

View File

@ -1,24 +1,27 @@
package exh.md.handlers
import com.github.salomonbrys.kotson.string
import com.google.gson.JsonParser
import eu.kanade.tachiyomi.source.model.Page
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.Response
import java.util.Date
class ApiChapterParser {
fun pageListParse(response: Response): List<Page> {
val jsonData = response.body!!.string()
val json = JsonParser.parseString(jsonData).asJsonObject
val json = Json.decodeFromString<JsonObject>(jsonData)
val pages = mutableListOf<Page>()
val hash = json.get("hash").string
val pageArray = json.getAsJsonArray("page_array")
val server = json.get("server").string
val hash = json["hash"]!!.jsonPrimitive.content
val pageArray = json["page_array"]!!.jsonArray
val server = json["server"]!!.jsonPrimitive.content
pageArray.forEach {
val url = "$hash/${it.asString}"
val url = "$hash/${it.jsonPrimitive.content}"
pages.add(Page(pages.size, "$server,${response.request.url},${Date().time}", url))
}
@ -27,8 +30,8 @@ class ApiChapterParser {
fun externalParse(response: Response): String {
val jsonData = response.body!!.string()
val json = JsonParser.parseString(jsonData).asJsonObject
val external = json.get("external").string
val json = Json.decodeFromString<JsonObject>(jsonData)
val external = json["external"]!!.jsonPrimitive.content
return external.substringAfterLast("/")
}
}

View File

@ -1,9 +1,6 @@
package exh.md.handlers
import com.elvishew.xlog.XLog
import com.github.salomonbrys.kotson.nullInt
import com.github.salomonbrys.kotson.obj
import com.google.gson.JsonParser
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.source.model.SChapter
@ -18,6 +15,11 @@ import exh.metadata.metadata.base.RaisedTag
import exh.metadata.metadata.base.getFlatMetadataForManga
import exh.metadata.metadata.base.insertFlatMetadata
import exh.util.floor
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.intOrNull
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.Response
import rx.Completable
import rx.Single
@ -232,8 +234,8 @@ class ApiMangaParser(private val langs: List<String>) {
throw Exception("Null Response")
}
val jsonObject = JsonParser.parseString(body).obj
return jsonObject["manga_id"]?.nullInt ?: throw Exception("No manga associated with chapter")
val jsonObject = Json.decodeFromString<JsonObject>(body)
return jsonObject["manga_id"]?.jsonPrimitive?.intOrNull ?: throw Exception("No manga associated with chapter")
} catch (e: Exception) {
XLog.e(e)
throw e

View File

@ -9,10 +9,12 @@ import exh.metadata.EX_DATE_FORMAT
import exh.metadata.ONGOING_SUFFIX
import exh.metadata.humanReadableByteCount
import exh.metadata.metadata.base.RaisedSearchMetadata
import kotlinx.serialization.Serializable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.util.Date
@Serializable
class EHentaiSearchMetadata : RaisedSearchMetadata() {
var gId: String?
get() = indexedExtra

View File

@ -4,7 +4,9 @@ import android.content.Context
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.SManga
import exh.metadata.metadata.base.RaisedSearchMetadata
import kotlinx.serialization.Serializable
@Serializable
class EightMusesSearchMetadata : RaisedSearchMetadata() {
var path: List<String> = emptyList()

View File

@ -5,7 +5,9 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.SManga
import exh.metadata.metadata.EightMusesSearchMetadata.Companion.ARTIST_NAMESPACE
import exh.metadata.metadata.base.RaisedSearchMetadata
import kotlinx.serialization.Serializable
@Serializable
class HBrowseSearchMetadata : RaisedSearchMetadata() {
var hbId: Long? = null

View File

@ -4,7 +4,9 @@ import android.content.Context
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.SManga
import exh.metadata.metadata.base.RaisedSearchMetadata
import kotlinx.serialization.Serializable
@Serializable
class HentaiCafeSearchMetadata : RaisedSearchMetadata() {
var hcId: String? = null
var readerId: String? = null

View File

@ -5,9 +5,10 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.SManga
import exh.metadata.EX_DATE_FORMAT
import exh.metadata.metadata.base.RaisedSearchMetadata
import exh.plusAssign
import kotlinx.serialization.Serializable
import java.util.Date
@Serializable
class HitomiSearchMetadata : RaisedSearchMetadata() {
var url get() = hlId?.let { urlFromHlId(it) }
set(a) {
@ -26,7 +27,7 @@ class HitomiSearchMetadata : RaisedSearchMetadata() {
var group: String? = null
var type: String? = null
var genre: String? = null
var language: String? = null
@ -101,7 +102,7 @@ class HitomiSearchMetadata : RaisedSearchMetadata() {
pairs += Pair(context.getString(R.string.artist), artists)
}
group?.let { pairs += Pair(context.getString(R.string.group), it) }
type?.let { pairs += Pair(context.getString(R.string.genre), it) }
genre?.let { pairs += Pair(context.getString(R.string.genre), it) }
language?.let { pairs += Pair(context.getString(R.string.language), it) }
val series = series.joinToString()
if (series.isNotBlank()) {

View File

@ -5,7 +5,9 @@ import androidx.core.net.toUri
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.SManga
import exh.metadata.metadata.base.RaisedSearchMetadata
import kotlinx.serialization.Serializable
@Serializable
class MangaDexSearchMetadata : RaisedSearchMetadata() {
var mdId: String? = null

View File

@ -6,9 +6,11 @@ import eu.kanade.tachiyomi.source.model.SManga
import exh.metadata.EX_DATE_FORMAT
import exh.metadata.ONGOING_SUFFIX
import exh.metadata.metadata.base.RaisedSearchMetadata
import kotlinx.serialization.Serializable
import uy.kohesive.injekt.api.get
import java.util.Date
@Serializable
class NHentaiSearchMetadata : RaisedSearchMetadata() {
var url get() = nhId?.let { BASE_URL + nhIdToPath(it) }
set(a) {

View File

@ -6,7 +6,9 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.SManga
import exh.metadata.metadata.base.RaisedSearchMetadata
import exh.metadata.metadata.base.RaisedTitle
import kotlinx.serialization.Serializable
@Serializable
class PervEdenSearchMetadata : RaisedSearchMetadata() {
var pvId: String? = null
@ -23,7 +25,7 @@ class PervEdenSearchMetadata : RaisedSearchMetadata() {
var artist: String? = null
var type: String? = null
var genre: String? = null
var rating: Float? = null
@ -102,7 +104,7 @@ class PervEdenSearchMetadata : RaisedSearchMetadata() {
pairs += Pair(context.getString(R.string.alt_titles), altTitles)
}
artist?.let { pairs += Pair(context.getString(R.string.artist), it) }
type?.let { pairs += Pair(context.getString(R.string.genre), it) }
genre?.let { pairs += Pair(context.getString(R.string.genre), it) }
rating?.let { pairs += Pair(context.getString(R.string.average_rating), it.toString()) }
status?.let { pairs += Pair(context.getString(R.string.status), it) }
lang?.let { pairs += Pair(context.getString(R.string.language), it) }

View File

@ -4,7 +4,9 @@ import android.content.Context
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.SManga
import exh.metadata.metadata.base.RaisedSearchMetadata
import kotlinx.serialization.Serializable
@Serializable
class PururinSearchMetadata : RaisedSearchMetadata() {
var prId: Int? = null

View File

@ -6,10 +6,12 @@ import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.source.model.SManga
import exh.metadata.EX_DATE_FORMAT
import exh.metadata.metadata.base.RaisedSearchMetadata
import kotlinx.serialization.Serializable
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
@Serializable
class TsuminoSearchMetadata : RaisedSearchMetadata() {
var tmId: Int? = null

View File

@ -5,10 +5,15 @@ import eu.kanade.tachiyomi.data.database.DatabaseHelper
import exh.metadata.sql.models.SearchMetadata
import exh.metadata.sql.models.SearchTag
import exh.metadata.sql.models.SearchTitle
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.serializer
import rx.Completable
import rx.Single
import kotlin.reflect.KClass
@Serializable
data class FlatMetadata(
val metadata: SearchMetadata,
val tags: List<SearchTag>,
@ -16,9 +21,10 @@ data class FlatMetadata(
) {
inline fun <reified T : RaisedSearchMetadata> raise(): T = raise(T::class)
@OptIn(InternalSerializationApi::class)
fun <T : RaisedSearchMetadata> raise(clazz: KClass<T>): T =
RaisedSearchMetadata.raiseFlattenGson
.fromJson(metadata.extra, clazz.java).apply {
RaisedSearchMetadata.raiseFlattenJson
.decodeFromString(clazz.serializer(), metadata.extra).apply {
fillBaseFields(this@FlatMetadata)
}
}

View File

@ -1,17 +1,35 @@
package exh.metadata.metadata.base
import android.content.Context
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import eu.kanade.tachiyomi.source.model.SManga
import exh.metadata.forEach
import exh.metadata.metadata.EHentaiSearchMetadata
import exh.metadata.metadata.EightMusesSearchMetadata
import exh.metadata.metadata.HBrowseSearchMetadata
import exh.metadata.metadata.HentaiCafeSearchMetadata
import exh.metadata.metadata.HitomiSearchMetadata
import exh.metadata.metadata.MangaDexSearchMetadata
import exh.metadata.metadata.NHentaiSearchMetadata
import exh.metadata.metadata.PervEdenSearchMetadata
import exh.metadata.metadata.PururinSearchMetadata
import exh.metadata.metadata.TsuminoSearchMetadata
import exh.metadata.sql.models.SearchMetadata
import exh.metadata.sql.models.SearchTag
import exh.metadata.sql.models.SearchTitle
import exh.plusAssign
import kotlinx.serialization.Polymorphic
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.SerializersModule
import kotlinx.serialization.modules.polymorphic
import kotlinx.serialization.modules.subclass
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
@Polymorphic
@Serializable
abstract class RaisedSearchMetadata {
@Transient
var mangaId: Long = -1
@ -67,7 +85,7 @@ abstract class RaisedSearchMetadata {
fun flatten(): FlatMetadata {
require(mangaId != -1L)
val extra = raiseFlattenGson.toJson(this)
val extra = raiseFlattenJson.encodeToString(this)
return FlatMetadata(
SearchMetadata(
mangaId,
@ -122,7 +140,25 @@ abstract class RaisedSearchMetadata {
(this).filter { it.type != TAG_TYPE_VIRTUAL }
.joinToString { (if (it.namespace != null) "${it.namespace}: " else "") + it.name }
val raiseFlattenGson: Gson = GsonBuilder().create()
private val module = SerializersModule {
polymorphic(RaisedSearchMetadata::class) {
subclass(EHentaiSearchMetadata::class)
subclass(EightMusesSearchMetadata::class)
subclass(HBrowseSearchMetadata::class)
subclass(HentaiCafeSearchMetadata::class)
subclass(HitomiSearchMetadata::class)
subclass(MangaDexSearchMetadata::class)
subclass(NHentaiSearchMetadata::class)
subclass(PervEdenSearchMetadata::class)
subclass(PururinSearchMetadata::class)
subclass(TsuminoSearchMetadata::class)
}
}
val raiseFlattenJson = Json {
ignoreUnknownKeys = true
serializersModule = module
}
fun titleDelegate(type: Int) = object : ReadWriteProperty<RaisedSearchMetadata, String?> {
/**

View File

@ -1,5 +1,8 @@
package exh.metadata.metadata.base
import kotlinx.serialization.Serializable
@Serializable
data class RaisedTag(
val namespace: String?,
val name: String,

View File

@ -1,5 +1,8 @@
package exh.metadata.metadata.base
import kotlinx.serialization.Serializable
@Serializable
data class RaisedTitle(
val title: String,
val type: Int = 0

View File

@ -1,5 +1,9 @@
package exh.metadata.sql.models
import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable
@Serializable
data class SearchMetadata(
// Manga ID this gallery is linked to
val mangaId: Long,
@ -17,5 +21,6 @@ data class SearchMetadata(
val extraVersion: Int
) {
// Transient information attached to this piece of metadata, useful for caching
var transientCache: Map<String, Any>? = null
var transientCache: Map<String, @Contextual Any>? = null
}

View File

@ -1,5 +1,8 @@
package exh.metadata.sql.models
import kotlinx.serialization.Serializable
@Serializable
data class SearchTag(
// Tag identifier, unique
val id: Long?,

View File

@ -1,5 +1,8 @@
package exh.metadata.sql.models
import kotlinx.serialization.Serializable
@Serializable
data class SearchTitle(
// Title identifier, unique
val id: Long?,

View File

@ -1,4 +1,4 @@
package exh
package exh.savedsearches
import eu.kanade.tachiyomi.source.model.FilterList

View File

@ -0,0 +1,11 @@
package exh.savedsearches
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonArray
@Serializable
data class JsonSavedSearch(
val name: String,
val query: String,
val filters: JsonArray
)

View File

@ -13,9 +13,6 @@ import android.webkit.WebView
import androidx.appcompat.app.AppCompatActivity
import com.afollestad.materialdialogs.MaterialDialog
import com.elvishew.xlog.XLog
import com.github.salomonbrys.kotson.get
import com.github.salomonbrys.kotson.string
import com.google.gson.JsonParser
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.network.NetworkHelper
@ -28,6 +25,12 @@ import exh.source.DelegatedHttpSource
import exh.util.melt
import kotlinx.android.synthetic.main.eh_activity_captcha.toolbar
import kotlinx.android.synthetic.main.eh_activity_captcha.webview
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.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
@ -153,9 +156,9 @@ class BrowserActionActivity : AppCompatActivity() {
.asObservableSuccess()
.subscribeOn(Schedulers.io())
.map {
val json = JsonParser.parseString(it.body!!.string())
val json = Json.decodeFromString<JsonObject>(it.body!!.string())
it.close()
json["token"].string
json["token"]!!.jsonPrimitive.content
}.melt()
webview.addJavascriptInterface(this@BrowserActionActivity, "exh")
@ -317,7 +320,7 @@ class BrowserActionActivity : AppCompatActivity() {
.build()
).asObservableSuccess()
}.map { response ->
JsonParser.parseString(response.body!!.string())["results"][0]["alternatives"][0]["transcript"].string.trim()
Json.decodeFromString<JsonObject>(response.body!!.string())["results"]!!.jsonArray[0].jsonObject["alternatives"]!!.jsonArray[0].jsonObject["transcript"]!!.jsonPrimitive.content.trim()
}.toSingle()
}

View File

@ -47,7 +47,7 @@ class HitomiDescriptionAdapter(
val meta = controller.presenter.meta
if (meta == null || meta !is HitomiSearchMetadata) return
val genre = meta.type
val genre = meta.genre
if (genre != null) {
val pair = when (genre) {
"doujinshi" -> Pair(SourceTagsUtil.DOUJINSHI_COLOR, R.string.doujinshi)

View File

@ -47,7 +47,7 @@ class PervEdenDescriptionAdapter(
val meta = controller.presenter.meta
if (meta == null || meta !is PervEdenSearchMetadata) return
val genre = meta.type
val genre = meta.genre
if (genre != null) {
val pair = when (genre) {
"Doujinshi" -> Pair(SourceTagsUtil.DOUJINSHI_COLOR, R.string.doujinshi)

View File

@ -1,21 +1,20 @@
package xyz.nulldev.ts.api.http.serializer
import com.github.salomonbrys.kotson.bool
import com.github.salomonbrys.kotson.byte
import com.github.salomonbrys.kotson.char
import com.github.salomonbrys.kotson.double
import com.github.salomonbrys.kotson.float
import com.github.salomonbrys.kotson.get
import com.github.salomonbrys.kotson.int
import com.github.salomonbrys.kotson.long
import com.github.salomonbrys.kotson.obj
import com.github.salomonbrys.kotson.set
import com.github.salomonbrys.kotson.short
import com.github.salomonbrys.kotson.string
import com.google.gson.JsonArray
import com.google.gson.JsonObject
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.boolean
import kotlinx.serialization.json.buildJsonArray
import kotlinx.serialization.json.buildJsonObject
import kotlinx.serialization.json.double
import kotlinx.serialization.json.float
import kotlinx.serialization.json.int
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import kotlinx.serialization.json.long
import kotlinx.serialization.json.put
import kotlinx.serialization.json.putJsonObject
import kotlin.reflect.KMutableProperty1
import kotlin.reflect.full.isSubclassOf
@ -35,7 +34,7 @@ class FilterSerializer {
SortSerializer(this)
)
fun serialize(filters: FilterList) = JsonArray().apply {
fun serialize(filters: FilterList) = buildJsonArray {
filters.forEach {
@Suppress("UNCHECKED_CAST")
add(serialize(it as Filter<Any?>))
@ -43,26 +42,31 @@ class FilterSerializer {
}
fun serialize(filter: Filter<Any?>): JsonObject {
val out = JsonObject()
for (serializer in serializers) {
if (filter::class.isSubclassOf(serializer.clazz)) {
// TODO Not sure how to deal with the mess of types here
@Suppress("UNCHECKED_CAST")
serializer as Serializer<Filter<Any?>>
serializer.serialize(out, filter)
return buildJsonObject {
with(serializer) { serialize(filter) }
out[CLASS_MAPPINGS] = JsonObject()
val classMappings = mutableListOf<Pair<String, Any>>()
serializer.mappings().forEach {
val res = it.second.get(filter)
out[it.first] = res
out[CLASS_MAPPINGS][it.first] = res?.javaClass?.name ?: "null"
serializer.mappings().forEach {
val res = it.second.get(filter)
put(it.first, res.toString())
classMappings += it.first to (res?.javaClass?.name ?: "null")
}
putJsonObject(CLASS_MAPPINGS) {
classMappings.forEach { (t, u) ->
put(t, u.toString())
}
}
put(TYPE, serializer.type)
}
out[TYPE] = serializer.type
return out
}
}
throw IllegalArgumentException("Cannot serialize this Filter object!")
@ -71,13 +75,13 @@ class FilterSerializer {
fun deserialize(filters: FilterList, json: JsonArray) {
filters.zip(json).forEach { (filter, obj) ->
@Suppress("UNCHECKED_CAST")
deserialize(filter as Filter<Any?>, obj.obj)
deserialize(filter as Filter<Any?>, obj.jsonObject)
}
}
fun deserialize(filter: Filter<Any?>, json: JsonObject) {
val serializer = serializers.find {
it.type == json[TYPE].string
it.type == json[TYPE]!!.jsonPrimitive.content
} ?: throw IllegalArgumentException("Cannot deserialize this type!")
// TODO Not sure how to deal with the mess of types here
@ -88,17 +92,17 @@ class FilterSerializer {
serializer.mappings().forEach {
if (it.second is KMutableProperty1) {
val obj = json[it.first]
val res: Any? = when (json[CLASS_MAPPINGS][it.first].string) {
val obj = json[it.first]!!.jsonPrimitive
val res: Any? = when (json[CLASS_MAPPINGS]!!.jsonObject[it.first]!!.jsonPrimitive.content) {
java.lang.Integer::class.java.name -> obj.int
java.lang.Long::class.java.name -> obj.long
java.lang.Float::class.java.name -> obj.float
java.lang.Double::class.java.name -> obj.double
java.lang.String::class.java.name -> obj.string
java.lang.Boolean::class.java.name -> obj.bool
java.lang.Byte::class.java.name -> obj.byte
java.lang.Short::class.java.name -> obj.short
java.lang.Character::class.java.name -> obj.char
java.lang.String::class.java.name -> obj.content
java.lang.Boolean::class.java.name -> obj.boolean
java.lang.Byte::class.java.name -> obj.content.toByte()
java.lang.Short::class.java.name -> obj.content.toShort()
java.lang.Character::class.java.name -> obj.content[0]
"null" -> null
else -> throw IllegalArgumentException("Cannot deserialize this type!")
}

View File

@ -1,20 +1,23 @@
package xyz.nulldev.ts.api.http.serializer
import com.github.salomonbrys.kotson.bool
import com.github.salomonbrys.kotson.int
import com.github.salomonbrys.kotson.nullArray
import com.github.salomonbrys.kotson.nullObj
import com.github.salomonbrys.kotson.set
import com.github.salomonbrys.kotson.string
import com.google.gson.JsonArray
import com.google.gson.JsonNull
import com.google.gson.JsonObject
import eu.kanade.tachiyomi.source.model.Filter
import kotlinx.serialization.json.JsonNull
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonObjectBuilder
import kotlinx.serialization.json.add
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.put
import kotlinx.serialization.json.putJsonArray
import kotlin.reflect.KClass
import kotlin.reflect.KProperty1
interface Serializer<in T : Filter<out Any?>> {
fun serialize(json: JsonObject, filter: T) {}
fun JsonObjectBuilder.serialize(filter: T) {}
fun deserialize(json: JsonObject, filter: T) {}
/**
@ -76,9 +79,9 @@ class SelectSerializer(override val serializer: FilterSerializer) : Serializer<F
override val type = "SELECT"
override val clazz = Filter.Select::class
override fun serialize(json: JsonObject, filter: Filter.Select<Any>) {
override fun JsonObjectBuilder.serialize(filter: Filter.Select<Any>) {
// Serialize values to JSON
json[VALUES] = JsonArray().apply {
putJsonArray(VALUES) {
filter.values.map {
it.toString()
}.forEach { add(it) }
@ -146,15 +149,15 @@ class GroupSerializer(override val serializer: FilterSerializer) : Serializer<Fi
override val type = "GROUP"
override val clazz = Filter.Group::class
override fun serialize(json: JsonObject, filter: Filter.Group<Any?>) {
json[STATE] = JsonArray().apply {
override fun JsonObjectBuilder.serialize(filter: Filter.Group<Any?>) {
putJsonArray(STATE) {
filter.state.forEach {
add(
if (it is Filter<*>) {
@Suppress("UNCHECKED_CAST")
serializer.serialize(it as Filter<Any?>)
} else {
JsonNull.INSTANCE
JsonNull
}
)
}
@ -162,10 +165,10 @@ class GroupSerializer(override val serializer: FilterSerializer) : Serializer<Fi
}
override fun deserialize(json: JsonObject, filter: Filter.Group<Any?>) {
json[STATE].asJsonArray.forEachIndexed { index, jsonElement ->
if (!jsonElement.isJsonNull) {
json[STATE]!!.jsonArray.forEachIndexed { index, jsonElement ->
if (jsonElement !is JsonNull) {
@Suppress("UNCHECKED_CAST")
serializer.deserialize(filter.state[index] as Filter<Any?>, jsonElement.asJsonObject)
serializer.deserialize(filter.state[index] as Filter<Any?>, jsonElement.jsonObject)
}
}
}
@ -184,27 +187,29 @@ class SortSerializer(override val serializer: FilterSerializer) : Serializer<Fil
override val type = "SORT"
override val clazz = Filter.Sort::class
override fun serialize(json: JsonObject, filter: Filter.Sort) {
override fun JsonObjectBuilder.serialize(filter: Filter.Sort) {
// Serialize values
json[VALUES] = JsonArray().apply {
putJsonArray(VALUES) {
filter.values.forEach { add(it) }
}
// Serialize state
json[STATE] = filter.state?.let { (index, ascending) ->
JsonObject().apply {
this[STATE_INDEX] = index
this[STATE_ASCENDING] = ascending
}
} ?: JsonNull.INSTANCE
put(
STATE,
filter.state?.let { (index, ascending) ->
buildJsonObject {
put(STATE_INDEX, index)
put(STATE_ASCENDING, ascending)
}
} ?: JsonNull
)
}
override fun deserialize(json: JsonObject, filter: Filter.Sort) {
// Deserialize state
filter.state = json[STATE].nullObj?.let {
filter.state = (json[STATE] as? JsonObject)?.let {
Filter.Sort.Selection(
it[STATE_INDEX].int,
it[STATE_ASCENDING].bool
it[STATE_INDEX]!!.jsonPrimitive.int,
it[STATE_ASCENDING]!!.jsonPrimitive.boolean
)
}
}
@ -227,19 +232,17 @@ class AutoCompleteSerializer(override val serializer: FilterSerializer) : Serial
override val type = "AUTOCOMPLETE"
override val clazz = Filter.AutoComplete::class
override fun serialize(json: JsonObject, filter: Filter.AutoComplete) {
override fun JsonObjectBuilder.serialize(filter: Filter.AutoComplete) {
// Serialize values to JSON
json[STATE] = JsonArray().apply {
putJsonArray(STATE) {
filter.state.forEach { add(it) }
}
}
override fun deserialize(json: JsonObject, filter: Filter.AutoComplete) {
// Deserialize state
json[STATE].nullArray?.let { array ->
filter.state = array.map {
it.string
}
filter.state = json[STATE]!!.jsonArray.map {
it.jsonPrimitive.content
}
}