This commit is contained in:
kunfei
2023-03-02 10:05:11 +08:00
parent 57ebf6d10b
commit 323854f647
13 changed files with 64 additions and 84 deletions
@@ -68,7 +68,7 @@ object BookSourceController {
fun deleteSources(postData: String?): ReturnData { fun deleteSources(postData: String?): ReturnData {
kotlin.runCatching { kotlin.runCatching {
GSON.fromJsonArray<BookSource>(postData).getOrThrow()?.let { GSON.fromJsonArray<BookSource>(postData).getOrThrow().let {
it.forEach { source -> it.forEach { source ->
appDb.bookSourceDao.delete(source) appDb.bookSourceDao.delete(source)
SourceConfig.removeSource(source.bookSourceUrl) SourceConfig.removeSource(source.bookSourceUrl)
@@ -3,10 +3,13 @@ package io.legado.app.data.entities
import android.os.Parcelable import android.os.Parcelable
import android.text.TextUtils import android.text.TextUtils
import androidx.room.* import androidx.room.*
import com.jayway.jsonpath.DocumentContext import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonDeserializer
import com.google.gson.JsonElement
import io.legado.app.constant.AppPattern import io.legado.app.constant.AppPattern
import io.legado.app.utils.* import io.legado.app.utils.*
import kotlinx.parcelize.Parcelize import kotlinx.parcelize.Parcelize
import java.lang.reflect.Type
@Parcelize @Parcelize
@Entity(tableName = "rssSources", indices = [(Index(value = ["sourceUrl"], unique = false))]) @Entity(tableName = "rssSources", indices = [(Index(value = ["sourceUrl"], unique = false))])
@@ -171,65 +174,35 @@ data class RssSource(
@Suppress("MemberVisibilityCanBePrivate") @Suppress("MemberVisibilityCanBePrivate")
companion object { companion object {
private val gson by lazy {
fun fromJsonDoc(doc: DocumentContext): Result<RssSource> { GSON.newBuilder()
return kotlin.runCatching { .registerTypeAdapter(String::class.java, RssJsonDeserializer())
val loginUi = doc.read<Any>("$.loginUi") .create()
RssSource(
sourceUrl = doc.readString("$.sourceUrl")!!,
sourceName = doc.readString("$.sourceName")!!,
sourceIcon = doc.readString("$.sourceIcon") ?: "",
sourceGroup = doc.readString("$.sourceGroup"),
sourceComment = doc.readString("$.sourceComment"),
enabled = doc.readBool("$.enabled") ?: true,
concurrentRate = doc.readString("$.concurrentRate"),
header = doc.readString("$.header"),
loginUrl = doc.readString("$.loginUrl"),
loginUi = if (loginUi is List<*>) GSON.toJson(loginUi) else loginUi?.toString(),
loginCheckJs = doc.readString("$.loginCheckJs"),
sortUrl = doc.readString("$.sortUrl"),
singleUrl = doc.readBool("$.singleUrl") ?: false,
articleStyle = doc.readInt("$.articleStyle") ?: 0,
ruleArticles = doc.readString("$.ruleArticles"),
ruleNextPage = doc.readString("$.ruleNextPage"),
ruleTitle = doc.readString("$.ruleTitle"),
rulePubDate = doc.readString("$.rulePubDate"),
ruleDescription = doc.readString("$.ruleDescription"),
ruleImage = doc.readString("$.ruleImage"),
ruleLink = doc.readString("$.ruleLink"),
ruleContent = doc.readString("$.ruleContent"),
style = doc.readString("$.style"),
injectJs = doc.readString("$.injectJs"),
enableJs = doc.readBool("$.enableJs") ?: true,
loadWithBaseUrl = doc.readBool("$.loadWithBaseUrl") ?: true,
enabledCookieJar = doc.readBool("$.enabledCookieJar") ?: false,
customOrder = doc.readInt("$.customOrder") ?: 0,
lastUpdateTime = doc.readLong("$.lastUpdateTime") ?: 0L,
coverDecodeJs = doc.readString("$.coverDecodeJs"),
variableComment = doc.readString("$.variableComment"),
contentBlacklist = doc.readString("$.contentBlacklist"),
contentWhitelist = doc.readString("$.contentWhitelist")
)
}
} }
fun fromJson(json: String): Result<RssSource> { fun fromJson(json: String): Result<RssSource> {
return fromJsonDoc(jsonPath.parse(json)) return gson.fromJsonObject(json)
} }
fun fromJsonArray(jsonArray: String): Result<ArrayList<RssSource>> { fun fromJsonArray(jsonArray: String): Result<List<RssSource>> {
return kotlin.runCatching { return gson.fromJsonArray(jsonArray)
val sources = arrayListOf<RssSource>()
val doc = jsonPath.parse(jsonArray).read<List<*>>("$")
doc.forEach {
val jsonItem = jsonPath.parse(it)
fromJsonDoc(jsonItem).getOrThrow().let { source ->
sources.add(source)
}
}
sources
}
} }
} }
class RssJsonDeserializer : JsonDeserializer<String?> {
override fun deserialize(
json: JsonElement,
typeOfT: Type?,
context: JsonDeserializationContext?
): String? {
return when {
json.isJsonPrimitive -> json.asString
json.isJsonNull -> null
else -> json.toString()
}
}
}
} }
@@ -87,7 +87,7 @@ object DefaultData {
appCtx.assets.open("defaultData${File.separator}coverRule.json") appCtx.assets.open("defaultData${File.separator}coverRule.json")
.readBytes() .readBytes()
) )
GSON.fromJsonObject<BookCover.CoverRule>(json).getOrThrow()!! GSON.fromJsonObject<BookCover.CoverRule>(json).getOrThrow()
} }
val dictRules: List<DictRule> by lazy { val dictRules: List<DictRule> by lazy {
@@ -95,7 +95,7 @@ object DefaultData {
appCtx.assets.open("defaultData${File.separator}dictRules.json") appCtx.assets.open("defaultData${File.separator}dictRules.json")
.readBytes() .readBytes()
) )
GSON.fromJsonArray<DictRule>(json).getOrThrow()!! GSON.fromJsonArray<DictRule>(json).getOrThrow()
} }
val keyboardAssists: List<KeyboardAssist> by lazy { val keyboardAssists: List<KeyboardAssist> by lazy {
@@ -103,7 +103,7 @@ object DefaultData {
appCtx.assets.open("defaultData${File.separator}keyboardAssists.json") appCtx.assets.open("defaultData${File.separator}keyboardAssists.json")
.readBytes() .readBytes()
) )
GSON.fromJsonArray<KeyboardAssist>(json).getOrNull()!! GSON.fromJsonArray<KeyboardAssist>(json).getOrThrow()
} }
fun importDefaultHttpTTS() { fun importDefaultHttpTTS() {
@@ -50,7 +50,7 @@ suspend fun BookSource.exploreKinds(): List<ExploreKind> {
} }
} }
if (ruleStr.isJsonArray()) { if (ruleStr.isJsonArray()) {
GSON.fromJsonArray<ExploreKind?>(ruleStr).getOrThrow()?.let { GSON.fromJsonArray<ExploreKind?>(ruleStr).getOrThrow().let {
kinds.addAll(it.filterNotNull()) kinds.addAll(it.filterNotNull())
} }
} else { } else {
@@ -218,7 +218,7 @@ object LocalBook {
SimpleBindings().also { it["src"] = tempFileName } SimpleBindings().also { it["src"] = tempFileName }
).toString() ).toString()
val bookMess = GSON.fromJsonObject<HashMap<String, String>>(jsonStr) val bookMess = GSON.fromJsonObject<HashMap<String, String>>(jsonStr)
.getOrThrow() ?: HashMap() .getOrThrow()
name = bookMess["name"] ?: tempFileName name = bookMess["name"] ?: tempFileName
author = bookMess["author"]?.takeIf { it.length != tempFileName.length } ?: "" author = bookMess["author"]?.takeIf { it.length != tempFileName.length } ?: ""
} catch (e: Exception) { } catch (e: Exception) {
@@ -71,11 +71,11 @@ class ImportDictRuleViewModel(app: Application) : BaseViewModel(app) {
private suspend fun importSourceAwait(text: String) { private suspend fun importSourceAwait(text: String) {
when { when {
text.isJsonObject() -> { text.isJsonObject() -> {
GSON.fromJsonObject<DictRule>(text).getOrThrow()?.let { GSON.fromJsonObject<DictRule>(text).getOrThrow().let {
allSources.add(it) allSources.add(it)
} }
} }
text.isJsonArray() -> GSON.fromJsonArray<DictRule>(text).getOrThrow()?.let { items -> text.isJsonArray() -> GSON.fromJsonArray<DictRule>(text).getOrThrow().let { items ->
allSources.addAll(items) allSources.addAll(items)
} }
text.isAbsUrl() -> { text.isAbsUrl() -> {
@@ -104,12 +104,8 @@ class ImportRssSourceViewModel(app: Application) : BaseViewModel(app) {
} }
} }
mText.isJsonArray() -> { mText.isJsonArray() -> {
val items: List<Map<String, Any>> = jsonPath.parse(mText).read("$") RssSource.fromJsonArray(mText).getOrThrow().let {
for (item in items) { allSources.addAll(it)
val jsonItem = jsonPath.parse(item)
RssSource.fromJsonDoc(jsonItem).getOrThrow().let {
allSources.add(it)
}
} }
} }
mText.isAbsUrl() -> { mText.isAbsUrl() -> {
@@ -68,12 +68,12 @@ class ImportThemeViewModel(app: Application) : BaseViewModel(app) {
private suspend fun importSourceAwait(text: String) { private suspend fun importSourceAwait(text: String) {
when { when {
text.isJsonObject() -> { text.isJsonObject() -> {
GSON.fromJsonObject<ThemeConfig.Config>(text).getOrThrow()?.let { GSON.fromJsonObject<ThemeConfig.Config>(text).getOrThrow().let {
allSources.add(it) allSources.add(it)
} }
} }
text.isJsonArray() -> GSON.fromJsonArray<ThemeConfig.Config>(text).getOrThrow() text.isJsonArray() -> GSON.fromJsonArray<ThemeConfig.Config>(text).getOrThrow()
?.let { items -> .let { items ->
allSources.addAll(items) allSources.addAll(items)
} }
text.isAbsUrl() -> { text.isAbsUrl() -> {
@@ -71,12 +71,12 @@ class ImportTxtTocRuleViewModel(app: Application) : BaseViewModel(app) {
private suspend fun importSourceAwait(text: String) { private suspend fun importSourceAwait(text: String) {
when { when {
text.isJsonObject() -> { text.isJsonObject() -> {
GSON.fromJsonObject<TxtTocRule>(text).getOrThrow()?.let { GSON.fromJsonObject<TxtTocRule>(text).getOrThrow().let {
allSources.add(it) allSources.add(it)
} }
} }
text.isJsonArray() -> GSON.fromJsonArray<TxtTocRule>(text).getOrThrow() text.isJsonArray() -> GSON.fromJsonArray<TxtTocRule>(text).getOrThrow()
?.let { items -> .let { items ->
allSources.addAll(items) allSources.addAll(items)
} }
text.isAbsUrl() -> { text.isAbsUrl() -> {
@@ -3,7 +3,6 @@ package io.legado.app.ui.book.toc.rule
import android.app.Application import android.app.Application
import io.legado.app.base.BaseViewModel import io.legado.app.base.BaseViewModel
import io.legado.app.data.appDb import io.legado.app.data.appDb
import io.legado.app.data.entities.DictRule
import io.legado.app.data.entities.TxtTocRule import io.legado.app.data.entities.TxtTocRule
import io.legado.app.help.DefaultData import io.legado.app.help.DefaultData
import io.legado.app.help.http.newCallResponseBody import io.legado.app.help.http.newCallResponseBody
@@ -43,7 +42,7 @@ class TxtTocRuleViewModel(app: Application) : BaseViewModel(app) {
okHttpClient.newCallResponseBody { okHttpClient.newCallResponseBody {
url(url) url(url)
}.text("utf-8").let { json -> }.text("utf-8").let { json ->
GSON.fromJsonArray<TxtTocRule>(json).getOrThrow()?.let { GSON.fromJsonArray<TxtTocRule>(json).getOrThrow().let {
appDb.txtTocRuleDao.insert(*it.toTypedArray()) appDb.txtTocRuleDao.insert(*it.toTypedArray())
} }
} }
@@ -109,7 +109,7 @@ class DictRuleEditDialog() : BaseDialogFragment(R.layout.dialog_dict_rule_edit,
return return
} }
execute { execute {
GSON.fromJsonObject<DictRule>(text).getOrThrow()!! GSON.fromJsonObject<DictRule>(text).getOrThrow()
}.onSuccess { }.onSuccess {
success.invoke(it) success.invoke(it)
}.onError { }.onError {
@@ -125,7 +125,7 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application)
private fun importBookshelfByJson(json: String, groupId: Long) { private fun importBookshelfByJson(json: String, groupId: Long) {
execute { execute {
val bookSources = appDb.bookSourceDao.allEnabled val bookSources = appDb.bookSourceDao.allEnabled
GSON.fromJsonArray<Map<String, String?>>(json).getOrThrow()?.forEach { bookInfo -> GSON.fromJsonArray<Map<String, String?>>(json).getOrThrow().forEach { bookInfo ->
if (!isActive) return@execute if (!isActive) return@execute
val name = bookInfo["name"] ?: "" val name = bookInfo["name"] ?: ""
val author = bookInfo["author"] ?: "" val author = bookInfo["author"] ?: ""
@@ -27,29 +27,41 @@ val GSON: Gson by lazy {
inline fun <reified T> genericType(): Type = object : TypeToken<T>() {}.type inline fun <reified T> genericType(): Type = object : TypeToken<T>() {}.type
inline fun <reified T> Gson.fromJsonObject(json: String?): Result<T?> { inline fun <reified T> Gson.fromJsonObject(json: String?): Result<T> {
return kotlin.runCatching { return kotlin.runCatching {
fromJson(json, genericType<T>()) as? T if (json == null) {
throw JsonSyntaxException("解析字符串为空")
}
fromJson(json, genericType<T>()) as T
} }
} }
inline fun <reified T> Gson.fromJsonArray(json: String?): Result<List<T>?> { inline fun <reified T> Gson.fromJsonArray(json: String?): Result<List<T>> {
return kotlin.runCatching { return kotlin.runCatching {
fromJson(json, ParameterizedTypeImpl(T::class.java)) as? List<T> if (json == null) {
throw JsonSyntaxException("解析字符串为空")
}
fromJson(json, ParameterizedTypeImpl(T::class.java)) as List<T>
} }
} }
inline fun <reified T> Gson.fromJsonObject(inputStream: InputStream?): Result<T?> { inline fun <reified T> Gson.fromJsonObject(inputStream: InputStream?): Result<T> {
return kotlin.runCatching { return kotlin.runCatching {
if (inputStream == null) {
throw JsonSyntaxException("解析流为空")
}
val reader = InputStreamReader(inputStream) val reader = InputStreamReader(inputStream)
fromJson(reader, genericType<T>()) as? T fromJson(reader, genericType<T>()) as T
} }
} }
inline fun <reified T> Gson.fromJsonArray(inputStream: InputStream?): Result<List<T>?> { inline fun <reified T> Gson.fromJsonArray(inputStream: InputStream?): Result<List<T>> {
return kotlin.runCatching { return kotlin.runCatching {
if (inputStream == null) {
throw JsonSyntaxException("解析流为空")
}
val reader = InputStreamReader(inputStream) val reader = InputStreamReader(inputStream)
fromJson(reader, ParameterizedTypeImpl(T::class.java)) as? List<T> fromJson(reader, ParameterizedTypeImpl(T::class.java)) as List<T>
} }
} }