导入书源防止非json格式导入

pull/1259/head
gedoor 3 years ago
parent 7e39fd3341
commit 80ad3f0104
  1. 1
      app/src/main/java/io/legado/app/constant/BookType.kt
  2. 21
      app/src/main/java/io/legado/app/data/entities/BookSource.kt
  3. 25
      app/src/main/java/io/legado/app/help/storage/BookSourceAnalyzer.kt
  4. 2
      app/src/main/java/io/legado/app/help/storage/ImportOldData.kt
  5. 28
      app/src/main/java/io/legado/app/ui/association/ImportBookSourceViewModel.kt
  6. 2
      app/src/main/java/io/legado/app/ui/book/info/BookInfoActivity.kt
  7. 2
      app/src/main/java/io/legado/app/ui/book/read/ReadMenu.kt
  8. 14
      app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditActivity.kt
  9. 4
      app/src/main/java/io/legado/app/ui/book/source/edit/BookSourceEditViewModel.kt

@ -3,5 +3,6 @@ package io.legado.app.constant
object BookType { object BookType {
const val default = 0 // 0 文本 const val default = 0 // 0 文本
const val audio = 1 // 1 音频 const val audio = 1 // 1 音频
const val image = 3 //图片
const val local = "loc_book" const val local = "loc_book"
} }

@ -27,15 +27,15 @@ data class BookSource(
var bookSourceGroup: String? = null, // 分组 var bookSourceGroup: String? = null, // 分组
@PrimaryKey @PrimaryKey
var bookSourceUrl: String = "", // 地址,包括 http/https var bookSourceUrl: String = "", // 地址,包括 http/https
var bookSourceType: Int = BookType.default, // 类型,0 文本,1 音频 var bookSourceType: Int = BookType.default, // 类型,0 文本,1 音频, 3 图片
var bookUrlPattern: String? = null, // 详情页url正则 var bookUrlPattern: String? = null, // 详情页url正则
var concurrentRate: String? = null, //并发率 var concurrentRate: String? = null, //并发率
var customOrder: Int = 0, // 手动排序编号 var customOrder: Int = 0, // 手动排序编号
var enabled: Boolean = true, // 是否启用 var enabled: Boolean = true, // 是否启用
var enabledExplore: Boolean = true, // 启用发现 var enabledExplore: Boolean = true, // 启用发现
var header: String? = null, // 请求头 var header: String? = null, // 请求头
var loginUrl: String? = null, // 登录地址 var loginUrl: LoginRule? = null, // 登录地址
var bookSourceComment: String? = null, // 注释 var bookSourceComment: String? = null, // 注释
var lastUpdateTime: Long = 0, // 最后更新时间,用于排序 var lastUpdateTime: Long = 0, // 最后更新时间,用于排序
var weight: Int = 0, // 智能排序的权重 var weight: Int = 0, // 智能排序的权重
var exploreUrl: String? = null, // 发现url var exploreUrl: String? = null, // 发现url
@ -47,17 +47,6 @@ data class BookSource(
var ruleContent: ContentRule? = null // 正文页规则 var ruleContent: ContentRule? = null // 正文页规则
) : Parcelable, JsExtensions { ) : Parcelable, JsExtensions {
@delegate:Transient
@delegate:Ignore
@IgnoredOnParcel
val loginRule by lazy {
if (loginUrl.isJsonObject()) {
return@lazy GSON.fromJsonObject<LoginRule>(loginUrl)
} else {
return@lazy LoginRule(url = loginUrl)
}
}
@delegate:Transient @delegate:Transient
@delegate:Ignore @delegate:Ignore
@IgnoredOnParcel @IgnoredOnParcel
@ -178,7 +167,7 @@ data class BookSource(
&& enabled == source.enabled && enabled == source.enabled
&& enabledExplore == source.enabledExplore && enabledExplore == source.enabledExplore
&& equal(header, source.header) && equal(header, source.header)
&& equal(loginUrl, source.loginUrl) && loginUrl == source.loginUrl
&& equal(exploreUrl, source.exploreUrl) && equal(exploreUrl, source.exploreUrl)
&& equal(searchUrl, source.searchUrl) && equal(searchUrl, source.searchUrl)
&& getSearchRule() == source.getSearchRule() && getSearchRule() == source.getSearchRule()
@ -191,7 +180,7 @@ data class BookSource(
class Converters { class Converters {
@TypeConverter @TypeConverter
fun loginRuleTString(loginRule: LoginRule?): String = GSON.toJson(loginRule) fun loginRuleToString(loginRule: LoginRule?): String = GSON.toJson(loginRule)
@TypeConverter @TypeConverter
fun stringToLoginRule(json: String?): LoginRule? { fun stringToLoginRule(json: String?): LoginRule? {

@ -10,7 +10,7 @@ import io.legado.app.utils.*
import java.util.regex.Pattern import java.util.regex.Pattern
@Suppress("RegExpRedundantEscape") @Suppress("RegExpRedundantEscape")
object OldRule { object BookSourceAnalyzer {
private val headerPattern = Pattern.compile("@Header:\\{.+?\\}", Pattern.CASE_INSENSITIVE) private val headerPattern = Pattern.compile("@Header:\\{.+?\\}", Pattern.CASE_INSENSITIVE)
private val jsPattern = Pattern.compile("\\{\\{.+?\\}\\}", Pattern.CASE_INSENSITIVE) private val jsPattern = Pattern.compile("\\{\\{.+?\\}\\}", Pattern.CASE_INSENSITIVE)
@ -25,10 +25,11 @@ object OldRule {
if (sourceAny?.ruleToc == null) { if (sourceAny?.ruleToc == null) {
source.apply { source.apply {
val jsonItem = jsonPath.parse(json.trim()) val jsonItem = jsonPath.parse(json.trim())
bookSourceUrl = jsonItem.readString("bookSourceUrl") ?: "" bookSourceUrl = jsonItem.readString("bookSourceUrl") ?: return null
bookSourceName = jsonItem.readString("bookSourceName") ?: "" bookSourceName = jsonItem.readString("bookSourceName") ?: ""
bookSourceGroup = jsonItem.readString("bookSourceGroup") bookSourceGroup = jsonItem.readString("bookSourceGroup")
loginUrl = jsonItem.readString("loginUrl") loginUrl =
BookSource.Converters().stringToLoginRule(jsonItem.readString("loginUrl"))
bookSourceComment = jsonItem.readString("bookSourceComment") ?: "" bookSourceComment = jsonItem.readString("bookSourceComment") ?: ""
bookUrlPattern = jsonItem.readString("ruleBookUrlPattern") bookUrlPattern = jsonItem.readString("ruleBookUrlPattern")
customOrder = jsonItem.readInt("serialNumber") ?: 0 customOrder = jsonItem.readInt("serialNumber") ?: 0
@ -97,34 +98,38 @@ object OldRule {
source.enabled = sourceAny.enabled source.enabled = sourceAny.enabled
source.enabledExplore = sourceAny.enabledExplore source.enabledExplore = sourceAny.enabledExplore
source.header = sourceAny.header source.header = sourceAny.header
source.loginUrl = sourceAny.loginUrl source.loginUrl = if (sourceAny.loginUrl is String) {
BookSource.Converters().stringToLoginRule(sourceAny.loginUrl.toString())
} else {
GSON.fromJsonObject(GSON.toJson(sourceAny.loginUrl))
}
source.bookSourceComment = sourceAny.bookSourceComment source.bookSourceComment = sourceAny.bookSourceComment
source.lastUpdateTime = sourceAny.lastUpdateTime source.lastUpdateTime = sourceAny.lastUpdateTime
source.weight = sourceAny.weight source.weight = sourceAny.weight
source.exploreUrl = sourceAny.exploreUrl source.exploreUrl = sourceAny.exploreUrl
source.ruleExplore = if (sourceAny.ruleExplore is String) { source.ruleExplore = if (sourceAny.ruleExplore is String) {
GSON.fromJsonObject(sourceAny.ruleExplore as? String) GSON.fromJsonObject(sourceAny.ruleExplore.toString())
} else { } else {
GSON.fromJsonObject(GSON.toJson(sourceAny.ruleExplore)) GSON.fromJsonObject(GSON.toJson(sourceAny.ruleExplore))
} }
source.searchUrl = sourceAny.searchUrl source.searchUrl = sourceAny.searchUrl
source.ruleSearch = if (sourceAny.ruleSearch is String) { source.ruleSearch = if (sourceAny.ruleSearch is String) {
GSON.fromJsonObject(sourceAny.ruleSearch as? String) GSON.fromJsonObject(sourceAny.ruleSearch.toString())
} else { } else {
GSON.fromJsonObject(GSON.toJson(sourceAny.ruleSearch)) GSON.fromJsonObject(GSON.toJson(sourceAny.ruleSearch))
} }
source.ruleBookInfo = if (sourceAny.ruleBookInfo is String) { source.ruleBookInfo = if (sourceAny.ruleBookInfo is String) {
GSON.fromJsonObject(sourceAny.ruleBookInfo as? String) GSON.fromJsonObject(sourceAny.ruleBookInfo.toString())
} else { } else {
GSON.fromJsonObject(GSON.toJson(sourceAny.ruleBookInfo)) GSON.fromJsonObject(GSON.toJson(sourceAny.ruleBookInfo))
} }
source.ruleToc = if (sourceAny.ruleToc is String) { source.ruleToc = if (sourceAny.ruleToc is String) {
GSON.fromJsonObject(sourceAny.ruleToc as? String) GSON.fromJsonObject(sourceAny.ruleToc.toString())
} else { } else {
GSON.fromJsonObject(GSON.toJson(sourceAny.ruleToc)) GSON.fromJsonObject(GSON.toJson(sourceAny.ruleToc))
} }
source.ruleContent = if (sourceAny.ruleContent is String) { source.ruleContent = if (sourceAny.ruleContent is String) {
GSON.fromJsonObject(sourceAny.ruleContent as? String) GSON.fromJsonObject(sourceAny.ruleContent.toString())
} else { } else {
GSON.fromJsonObject(GSON.toJson(sourceAny.ruleContent)) GSON.fromJsonObject(GSON.toJson(sourceAny.ruleContent))
} }
@ -146,7 +151,7 @@ object OldRule {
var enabled: Boolean = true, // 是否启用 var enabled: Boolean = true, // 是否启用
var enabledExplore: Boolean = true, // 启用发现 var enabledExplore: Boolean = true, // 启用发现
var header: String? = null, // 请求头 var header: String? = null, // 请求头
var loginUrl: String? = null, // 登录地址 var loginUrl: Any? = null, // 登录规则
var bookSourceComment: String? = "", //书源注释 var bookSourceComment: String? = "", //书源注释
var lastUpdateTime: Long = 0, // 最后更新时间,用于排序 var lastUpdateTime: Long = 0, // 最后更新时间,用于排序
var weight: Int = 0, // 智能排序的权重 var weight: Int = 0, // 智能排序的权重

@ -96,7 +96,7 @@ object ImportOldData {
val items: List<Map<String, Any>> = Restore.jsonPath.parse(json).read("$") val items: List<Map<String, Any>> = Restore.jsonPath.parse(json).read("$")
for (item in items) { for (item in items) {
val jsonItem = Restore.jsonPath.parse(item) val jsonItem = Restore.jsonPath.parse(item)
OldRule.jsonToBookSource(jsonItem.jsonString())?.let { BookSourceAnalyzer.jsonToBookSource(jsonItem.jsonString())?.let {
bookSources.add(it) bookSources.add(it)
} }
} }

@ -14,7 +14,7 @@ import io.legado.app.help.SourceHelp
import io.legado.app.help.http.newCall import io.legado.app.help.http.newCall
import io.legado.app.help.http.okHttpClient import io.legado.app.help.http.okHttpClient
import io.legado.app.help.http.text import io.legado.app.help.http.text
import io.legado.app.help.storage.OldRule import io.legado.app.help.storage.BookSourceAnalyzer
import io.legado.app.help.storage.Restore import io.legado.app.help.storage.Restore
import io.legado.app.utils.isAbsUrl import io.legado.app.utils.isAbsUrl
import io.legado.app.utils.isJsonArray import io.legado.app.utils.isJsonArray
@ -101,7 +101,7 @@ class ImportBookSourceViewModel(app: Application) : BaseViewModel(app) {
importSourceUrl(it) importSourceUrl(it)
} }
} else { } else {
OldRule.jsonToBookSource(mText)?.let { BookSourceAnalyzer.jsonToBookSource(mText)?.let {
allSources.add(it) allSources.add(it)
} }
} }
@ -110,7 +110,7 @@ class ImportBookSourceViewModel(app: Application) : BaseViewModel(app) {
val items: List<Map<String, Any>> = Restore.jsonPath.parse(mText).read("$") val items: List<Map<String, Any>> = Restore.jsonPath.parse(mText).read("$")
for (item in items) { for (item in items) {
val jsonItem = Restore.jsonPath.parse(item) val jsonItem = Restore.jsonPath.parse(item)
OldRule.jsonToBookSource(jsonItem.jsonString())?.let { BookSourceAnalyzer.jsonToBookSource(jsonItem.jsonString())?.let {
allSources.add(it) allSources.add(it)
} }
} }
@ -132,11 +132,23 @@ class ImportBookSourceViewModel(app: Application) : BaseViewModel(app) {
okHttpClient.newCall { okHttpClient.newCall {
url(url) url(url)
}.text("utf-8").let { body -> }.text("utf-8").let { body ->
val items: List<Map<String, Any>> = Restore.jsonPath.parse(body).read("$") when {
for (item in items) { body.isJsonArray() -> {
val jsonItem = Restore.jsonPath.parse(item) val items: List<Map<String, Any>> = Restore.jsonPath.parse(body).read("$")
OldRule.jsonToBookSource(jsonItem.jsonString())?.let { source -> for (item in items) {
allSources.add(source) val jsonItem = Restore.jsonPath.parse(item)
BookSourceAnalyzer.jsonToBookSource(jsonItem.jsonString())?.let { source ->
allSources.add(source)
}
}
}
body.isJsonObject() -> {
BookSourceAnalyzer.jsonToBookSource(body)?.let {
allSources.add(it)
}
}
else -> {
throw Exception(context.getString(R.string.wrong_format))
} }
} }
} }

@ -119,7 +119,7 @@ class BookInfoActivity :
menu.findItem(R.id.menu_can_update)?.isChecked = menu.findItem(R.id.menu_can_update)?.isChecked =
viewModel.bookData.value?.canUpdate ?: true viewModel.bookData.value?.canUpdate ?: true
menu.findItem(R.id.menu_login)?.isVisible = menu.findItem(R.id.menu_login)?.isVisible =
!viewModel.bookSource?.loginUrl.isNullOrBlank() !viewModel.bookSource?.loginUrl?.url.isNullOrBlank()
return super.onMenuOpened(featureId, menu) return super.onMenuOpened(featureId, menu)
} }

@ -284,7 +284,7 @@ class ReadMenu @JvmOverloads constructor(
} }
fun upBookView() { fun upBookView() {
binding.tvLogin.isGone = ReadBook.webBook?.bookSource?.loginUrl.isNullOrEmpty() binding.tvLogin.isGone = ReadBook.webBook?.bookSource?.loginUrl?.url.isNullOrEmpty()
ReadBook.curTextChapter?.let { ReadBook.curTextChapter?.let {
binding.tvChapterName.text = it.title binding.tvChapterName.text = it.title
binding.tvChapterName.visible() binding.tvChapterName.visible()

@ -41,7 +41,7 @@ class BookSourceEditActivity :
override val binding by viewBinding(ActivityBookSourceEditBinding::inflate) override val binding by viewBinding(ActivityBookSourceEditBinding::inflate)
override val viewModel by viewModels<BookSourceEditViewModel>() override val viewModel by viewModels<BookSourceEditViewModel>()
private val converters = BookSource.Converters()
private val adapter = BookSourceEditAdapter() private val adapter = BookSourceEditAdapter()
private val sourceEntities: ArrayList<EditEntity> = ArrayList() private val sourceEntities: ArrayList<EditEntity> = ArrayList()
private val searchEntities: ArrayList<EditEntity> = ArrayList() private val searchEntities: ArrayList<EditEntity> = ArrayList()
@ -117,7 +117,7 @@ class BookSourceEditActivity :
R.id.menu_help -> showRuleHelp() R.id.menu_help -> showRuleHelp()
R.id.menu_login -> getSource().let { R.id.menu_login -> getSource().let {
if (checkSource(it)) { if (checkSource(it)) {
if (it.loginUrl.isNullOrEmpty()) { if (it.loginUrl?.url.isNullOrEmpty()) {
toastOnUi(R.string.source_no_login) toastOnUi(R.string.source_no_login)
} else { } else {
startActivity<SourceLoginActivity> { startActivity<SourceLoginActivity> {
@ -199,7 +199,13 @@ class BookSourceEditActivity :
add(EditEntity("bookSourceName", source?.bookSourceName, R.string.source_name)) add(EditEntity("bookSourceName", source?.bookSourceName, R.string.source_name))
add(EditEntity("bookSourceGroup", source?.bookSourceGroup, R.string.source_group)) add(EditEntity("bookSourceGroup", source?.bookSourceGroup, R.string.source_group))
add(EditEntity("bookSourceComment", source?.bookSourceComment, R.string.comment)) add(EditEntity("bookSourceComment", source?.bookSourceComment, R.string.comment))
add(EditEntity("loginUrl", source?.loginUrl, R.string.login_url)) add(
EditEntity(
"loginUrl",
converters.loginRuleToString(source?.loginUrl),
R.string.login_url
)
)
add(EditEntity("bookUrlPattern", source?.bookUrlPattern, R.string.book_url_pattern)) add(EditEntity("bookUrlPattern", source?.bookUrlPattern, R.string.book_url_pattern))
add(EditEntity("header", source?.header, R.string.source_http_header)) add(EditEntity("header", source?.header, R.string.source_http_header))
add( add(
@ -296,7 +302,7 @@ class BookSourceEditActivity :
"bookSourceUrl" -> source.bookSourceUrl = it.value ?: "" "bookSourceUrl" -> source.bookSourceUrl = it.value ?: ""
"bookSourceName" -> source.bookSourceName = it.value ?: "" "bookSourceName" -> source.bookSourceName = it.value ?: ""
"bookSourceGroup" -> source.bookSourceGroup = it.value "bookSourceGroup" -> source.bookSourceGroup = it.value
"loginUrl" -> source.loginUrl = it.value "loginUrl" -> source.loginUrl = converters.stringToLoginRule(it.value)
"bookUrlPattern" -> source.bookUrlPattern = it.value "bookUrlPattern" -> source.bookUrlPattern = it.value
"header" -> source.header = it.value "header" -> source.header = it.value
"bookSourceComment" -> source.bookSourceComment = it.value ?: "" "bookSourceComment" -> source.bookSourceComment = it.value ?: ""

@ -5,7 +5,7 @@ import android.content.Intent
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.BookSource import io.legado.app.data.entities.BookSource
import io.legado.app.help.storage.OldRule import io.legado.app.help.storage.BookSourceAnalyzer
import io.legado.app.utils.GSON import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonObject import io.legado.app.utils.fromJsonObject
import io.legado.app.utils.getClipText import io.legado.app.utils.getClipText
@ -56,7 +56,7 @@ class BookSourceEditViewModel(application: Application) : BaseViewModel(applicat
execute(context = Dispatchers.Main) { execute(context = Dispatchers.Main) {
var source: BookSource? = null var source: BookSource? = null
context.getClipText()?.let { json -> context.getClipText()?.let { json ->
source = OldRule.jsonToBookSource(json) source = BookSourceAnalyzer.jsonToBookSource(json)
} }
source source
}.onError { }.onError {

Loading…
Cancel
Save