js内添加source变量

pull/1259/head
gedoor 3 years ago
parent cbd204e25d
commit 99a269e864
  1. 25
      app/src/main/java/io/legado/app/data/entities/BaseSource.kt
  2. 7
      app/src/main/java/io/legado/app/data/entities/BookChapter.kt
  3. 4
      app/src/main/java/io/legado/app/data/entities/BookSource.kt
  4. 4
      app/src/main/java/io/legado/app/data/entities/RssSource.kt
  5. 6
      app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt
  6. 20
      app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeUrl.kt
  7. 2
      app/src/main/java/io/legado/app/model/rss/Rss.kt
  8. 2
      app/src/main/java/io/legado/app/model/rss/RssParserByRule.kt
  9. 2
      app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt
  10. 4
      app/src/main/java/io/legado/app/model/webBook/BookContent.kt
  11. 2
      app/src/main/java/io/legado/app/model/webBook/BookInfo.kt
  12. 2
      app/src/main/java/io/legado/app/model/webBook/BookList.kt
  13. 37
      app/src/main/java/io/legado/app/ui/book/login/SourceLoginDialog.kt

@ -1,17 +1,20 @@
package io.legado.app.data.entities
import android.util.Base64
import io.legado.app.constant.AppConst
import io.legado.app.help.AppConfig
import io.legado.app.help.CacheManager
import io.legado.app.help.JsExtensions
import io.legado.app.help.http.CookieStore
import io.legado.app.utils.EncoderUtils
import io.legado.app.utils.GSON
import io.legado.app.utils.fromJsonObject
import java.util.*
import javax.script.SimpleBindings
interface BaseSource : JsExtensions {
fun getStoreUrl(): String
var header: String?
fun getHeaderMap() = HashMap<String, String>().apply {
@ -31,6 +34,26 @@ interface BaseSource : JsExtensions {
}
}
fun getLoginHeader(): Map<String, String>? {
val cache = CacheManager.get("login_${getStoreUrl()}") ?: return null
val byteArrayB = Base64.decode(cache, Base64.DEFAULT)
val byteArrayA = EncoderUtils.decryptAES(byteArrayB, AppConst.androidId.toByteArray())
?: return null
val headerStr = String(byteArrayA)
return GSON.fromJsonObject(headerStr)
}
fun putLoginHeader(header: String) {
val data = Base64.encodeToString(
EncoderUtils.decryptAES(
header.toByteArray(),
AppConst.androidId.toByteArray()
),
Base64.DEFAULT
)
CacheManager.put("login_${getStoreUrl()}", data)
}
/**
* 执行JS
*/

@ -6,6 +6,7 @@ import androidx.room.ForeignKey
import androidx.room.Ignore
import androidx.room.Index
import io.legado.app.model.analyzeRule.AnalyzeUrl
import io.legado.app.model.analyzeRule.RuleDataInterface
import io.legado.app.utils.GSON
import io.legado.app.utils.MD5Utils
import io.legado.app.utils.NetworkUtils
@ -39,16 +40,16 @@ data class BookChapter(
var startFragmentId: String? = null, //EPUB书籍当前章节的fragmentId
var endFragmentId: String? = null, //EPUB书籍下一章节的fragmentId
var variable: String? = null //变量
) : Parcelable {
) : Parcelable, RuleDataInterface {
@delegate:Transient
@delegate:Ignore
@IgnoredOnParcel
val variableMap by lazy {
override val variableMap by lazy {
GSON.fromJsonObject<HashMap<String, String>>(variable) ?: HashMap()
}
fun putVariable(key: String, value: String) {
override fun putVariable(key: String, value: String) {
variableMap[key] = value
variable = GSON.toJson(variableMap)
}

@ -45,6 +45,10 @@ data class BookSource(
var ruleContent: ContentRule? = null // 正文页规则
) : Parcelable, BaseSource {
override fun getStoreUrl(): String {
return bookSourceUrl
}
@delegate:Transient
@delegate:Ignore
@IgnoredOnParcel

@ -43,6 +43,10 @@ data class RssSource(
var customOrder: Int = 0
) : Parcelable, BaseSource {
override fun getStoreUrl(): String {
return sourceUrl
}
override fun equals(other: Any?): Boolean {
if (other is RssSource) {
return other.sourceUrl == sourceUrl

@ -5,6 +5,7 @@ import androidx.annotation.Keep
import io.legado.app.constant.AppConst.SCRIPT_ENGINE
import io.legado.app.constant.AppPattern.JS_PATTERN
import io.legado.app.data.entities.BaseBook
import io.legado.app.data.entities.BaseSource
import io.legado.app.data.entities.BookChapter
import io.legado.app.help.CacheManager
import io.legado.app.help.JsExtensions
@ -24,7 +25,7 @@ import kotlin.collections.HashMap
*/
@Keep
@Suppress("unused", "RegExpRedundantEscape", "MemberVisibilityCanBePrivate")
class AnalyzeRule(val ruleData: RuleDataInterface) : JsExtensions {
class AnalyzeRule(val ruleData: RuleDataInterface, private val source: BaseSource) : JsExtensions {
var book = if (ruleData is BaseBook) ruleData else null
@ -626,6 +627,7 @@ class AnalyzeRule(val ruleData: RuleDataInterface) : JsExtensions {
bindings["java"] = this
bindings["cookie"] = CookieStore
bindings["cache"] = CacheManager
bindings["source"] = source
bindings["book"] = book
bindings["result"] = result
bindings["baseUrl"] = baseUrl
@ -642,7 +644,7 @@ class AnalyzeRule(val ruleData: RuleDataInterface) : JsExtensions {
override fun ajax(urlStr: String): String? {
return runBlocking {
kotlin.runCatching {
val analyzeUrl = AnalyzeUrl(urlStr, book = book)
val analyzeUrl = AnalyzeUrl(urlStr, book = book, source = source)
analyzeUrl.getStrResponse(urlStr).body
}.onFailure {
it.printStackTrace()

@ -8,6 +8,7 @@ import io.legado.app.constant.AppConst.SCRIPT_ENGINE
import io.legado.app.constant.AppConst.UA_NAME
import io.legado.app.constant.AppPattern.JS_PATTERN
import io.legado.app.data.entities.BaseBook
import io.legado.app.data.entities.BaseSource
import io.legado.app.data.entities.BookChapter
import io.legado.app.help.AppConfig
import io.legado.app.help.CacheManager
@ -36,7 +37,8 @@ class AnalyzeUrl(
val book: BaseBook? = null,
val chapter: BookChapter? = null,
private val ruleData: RuleDataInterface? = null,
headerMapF: Map<String, String>? = null
private val source: BaseSource? = null,
headerMapF: Map<String, String>? = null,
) : JsExtensions {
companion object {
val paramPattern: Pattern = Pattern.compile("\\s*,\\s*(?=\\{)")
@ -104,20 +106,9 @@ class AnalyzeUrl(
val analyze = RuleAnalyzer(ruleUrl) //创建解析
val bindings = SimpleBindings()
bindings["java"] = this
bindings["cookie"] = CookieStore
bindings["cache"] = CacheManager
bindings["baseUrl"] = baseUrl
bindings["page"] = page
bindings["key"] = key
bindings["speakText"] = speakText
bindings["speakSpeed"] = speakSpeed
bindings["book"] = book
//替换所有内嵌{{js}}
val url = analyze.innerRule("{{", "}}") {
val jsEval = SCRIPT_ENGINE.eval(it, bindings) ?: ""
val jsEval = evalJS(it) ?: ""
when {
jsEval is String -> jsEval
jsEval is Double && jsEval % 1.0 == 0.0 -> String.format("%.0f", jsEval)
@ -234,6 +225,7 @@ class AnalyzeUrl(
private fun evalJS(jsStr: String, result: Any? = null): Any? {
val bindings = SimpleBindings()
bindings["java"] = this
bindings["baseUrl"] = baseUrl
bindings["cookie"] = CookieStore
bindings["cache"] = CacheManager
bindings["page"] = page
@ -241,8 +233,8 @@ class AnalyzeUrl(
bindings["speakText"] = speakText
bindings["speakSpeed"] = speakSpeed
bindings["book"] = book
bindings["source"] = source
bindings["result"] = result
bindings["baseUrl"] = baseUrl
return SCRIPT_ENGINE.eval(jsStr, bindings)
}

@ -52,7 +52,7 @@ object Rss {
val body = analyzeUrl.getStrResponse(rssArticle.origin).body
Debug.log(rssSource.sourceUrl, "≡获取成功:${rssSource.sourceUrl}")
Debug.log(rssSource.sourceUrl, body, state = 20)
val analyzeRule = AnalyzeRule(rssArticle)
val analyzeRule = AnalyzeRule(rssArticle, rssSource)
analyzeRule.setContent(body)
.setBaseUrl(NetworkUtils.getAbsoluteURL(rssArticle.origin, rssArticle.link))
analyzeRule.getString(ruleContent)

@ -38,7 +38,7 @@ object RssParserByRule {
return RssParserDefault.parseXML(sortName, body, sourceUrl)
} else {
val articleList = mutableListOf<RssArticle>()
val analyzeRule = AnalyzeRule(ruleData)
val analyzeRule = AnalyzeRule(ruleData, rssSource)
analyzeRule.setContent(body).setBaseUrl(sortUrl)
analyzeRule.setRedirectUrl(sortUrl)
var reverse = false

@ -140,7 +140,7 @@ object BookChapterList {
getNextUrl: Boolean = true,
log: Boolean = false
): ChapterData<List<String>> {
val analyzeRule = AnalyzeRule(book)
val analyzeRule = AnalyzeRule(book, bookSource)
analyzeRule.setContent(body).setBaseUrl(baseUrl)
analyzeRule.setRedirectUrl(redirectUrl)
//获取目录列表

@ -47,7 +47,7 @@ object BookContent {
val content = StringBuilder()
val nextUrlList = arrayListOf(baseUrl)
val contentRule = bookSource.getContentRule()
val analyzeRule = AnalyzeRule(book).setContent(body, baseUrl)
val analyzeRule = AnalyzeRule(book, bookSource).setContent(body, baseUrl)
analyzeRule.setRedirectUrl(baseUrl)
analyzeRule.nextChapterUrl = mNextChapterUrl
scope.ensureActive()
@ -131,7 +131,7 @@ object BookContent {
nextChapterUrl: String?,
printLog: Boolean = true
): ContentData<List<String>> {
val analyzeRule = AnalyzeRule(book)
val analyzeRule = AnalyzeRule(book, bookSource)
analyzeRule.setContent(body, baseUrl)
val rUrl = analyzeRule.setRedirectUrl(redirectUrl)
analyzeRule.nextChapterUrl = nextChapterUrl

@ -32,7 +32,7 @@ object BookInfo {
)
Debug.log(bookSource.bookSourceUrl, "≡获取成功:${baseUrl}")
Debug.log(bookSource.bookSourceUrl, body, state = 20)
val analyzeRule = AnalyzeRule(book)
val analyzeRule = AnalyzeRule(book, bookSource)
analyzeRule.setContent(body).setBaseUrl(baseUrl)
analyzeRule.setRedirectUrl(redirectUrl)
analyzeBookInfo(scope, book, body, analyzeRule, bookSource, baseUrl, redirectUrl, canReName)

@ -39,7 +39,7 @@ object BookList {
val bookList = ArrayList<SearchBook>()
Debug.log(bookSource.bookSourceUrl, "≡获取成功:${analyzeUrl.ruleUrl}")
Debug.log(bookSource.bookSourceUrl, body, state = 10)
val analyzeRule = AnalyzeRule(variableBook)
val analyzeRule = AnalyzeRule(variableBook, bookSource)
analyzeRule.setContent(body).setBaseUrl(baseUrl)
analyzeRule.setRedirectUrl(baseUrl)
bookSource.bookUrlPattern?.let {

@ -2,28 +2,30 @@ package io.legado.app.ui.book.login
import android.os.Bundle
import android.text.InputType
import android.util.Base64
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.FragmentManager
import io.legado.app.R
import io.legado.app.base.BaseDialogFragment
import io.legado.app.constant.AppConst
import io.legado.app.data.entities.rule.LoginRule
import io.legado.app.data.appDb
import io.legado.app.databinding.DialogLoginBinding
import io.legado.app.help.CacheManager
import io.legado.app.lib.theme.primaryColor
import io.legado.app.ui.widget.text.EditText
import io.legado.app.ui.widget.text.TextInputLayout
import io.legado.app.utils.EncoderUtils
import io.legado.app.utils.GSON
import io.legado.app.utils.applyTint
import io.legado.app.utils.viewbindingdelegate.viewBinding
class SourceLoginDialog : BaseDialogFragment() {
private val binding by viewBinding(DialogLoginBinding::bind)
companion object {
fun start(fragmentManager: FragmentManager, sourceUrl: String) {
}
}
private val binding by viewBinding(DialogLoginBinding::bind)
override fun onCreateView(
inflater: LayoutInflater,
@ -35,19 +37,27 @@ class SourceLoginDialog : BaseDialogFragment() {
override fun onFragmentCreated(view: View, savedInstanceState: Bundle?) {
binding.toolBar.setBackgroundColor(primaryColor)
val sourceUrl = arguments?.getString("sourceUrl")
val loginRule = arguments?.getParcelable<LoginRule>("loginRule")
val sourceUrl = arguments?.getString("sourceUrl") ?: return
val bookSource = appDb.bookSourceDao.getBookSource(sourceUrl) ?: return
val loginHeader = bookSource.getLoginHeader()
val loginRule = bookSource.loginUrl
loginRule?.ui?.forEachIndexed { index, rowUi ->
when (rowUi.type) {
"text" -> layoutInflater.inflate(R.layout.item_source_edit, binding.root)
.apply {
id = index
findViewById<EditText>(R.id.editText).apply {
setText(loginHeader?.get(rowUi.name))
}
}
"password" -> layoutInflater.inflate(R.layout.item_source_edit, binding.root)
.apply {
id = index
findViewById<EditText>(R.id.editText)?.inputType =
findViewById<EditText>(R.id.editText).apply {
inputType =
InputType.TYPE_TEXT_VARIATION_PASSWORD or InputType.TYPE_CLASS_TEXT
setText(loginHeader?.get(rowUi.name))
}
}
}
}
@ -66,14 +76,7 @@ class SourceLoginDialog : BaseDialogFragment() {
}
}
}
val data = Base64.encodeToString(
EncoderUtils.decryptAES(
GSON.toJson(loginData).toByteArray(),
AppConst.androidId.toByteArray()
),
Base64.DEFAULT
)
CacheManager.put("login_$sourceUrl", data)
bookSource.putLoginHeader(GSON.toJson(loginData))
}
}
return@setOnMenuItemClickListener true

Loading…
Cancel
Save