Merge branch 'gedoor:master' into master

pull/1276/head
ag2s20150909 3 years ago committed by GitHub
commit 5b7687393a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      app/src/main/java/io/legado/app/data/AppDatabase.kt
  2. 14
      app/src/main/java/io/legado/app/data/entities/BaseSource.kt
  3. 4
      app/src/main/java/io/legado/app/data/entities/BookSource.kt
  4. 2
      app/src/main/java/io/legado/app/data/entities/RssSource.kt
  5. 62
      app/src/main/java/io/legado/app/model/rss/Rss.kt
  6. 10
      app/src/main/java/io/legado/app/service/CheckSourceService.kt
  7. 12
      app/src/main/java/io/legado/app/ui/login/RuleUiLoginDialog.kt
  8. 2
      app/src/main/java/io/legado/app/utils/EncoderUtils.kt
  9. 2
      build.gradle

@ -50,7 +50,7 @@ abstract class AppDatabase : RoomDatabase() {
fun createDatabase(context: Context) = fun createDatabase(context: Context) =
Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME) Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
.fallbackToDestructiveMigration() .fallbackToDestructiveMigrationFrom(1, 2, 3, 4, 5, 6, 7, 8, 9)
.addMigrations(*DatabaseMigrations.migrations) .addMigrations(*DatabaseMigrations.migrations)
.allowMainThreadQueries() .allowMainThreadQueries()
.addCallback(dbCallback) .addCallback(dbCallback)

@ -17,9 +17,21 @@ import javax.script.SimpleBindings
@Suppress("unused") @Suppress("unused")
interface BaseSource : JsExtensions { interface BaseSource : JsExtensions {
var loginUrl: String?
var header: String?
fun getStoreUrl(): String fun getStoreUrl(): String
var header: String? fun getLoginJs(): String? {
val loginJs = loginUrl
return when {
loginJs == null -> null
loginJs.startsWith("@js:") -> loginJs.substring(4)
loginJs.startsWith("<js>") ->
loginJs.substring(4, loginJs.lastIndexOf("<"))
else -> loginJs
}
}
/** /**
* 解析header规则 * 解析header规则

@ -28,7 +28,7 @@ data class BookSource(
var enabled: Boolean = true, // 是否启用 var enabled: Boolean = true, // 是否启用
var enabledExplore: Boolean = true, // 启用发现 var enabledExplore: Boolean = true, // 启用发现
override var header: String? = null, // 请求头 override var header: String? = null, // 请求头
var loginUrl: String? = null, // 登录地址 override var loginUrl: String? = null, // 登录地址
var loginUi: List<RowUi>? = null, //登录UI var loginUi: List<RowUi>? = null, //登录UI
var loginCheckJs: String? = null, //登录检测js var loginCheckJs: String? = null, //登录检测js
var bookSourceComment: String? = null, // 注释 var bookSourceComment: String? = null, // 注释
@ -50,7 +50,7 @@ data class BookSource(
@delegate:Transient @delegate:Transient
@delegate:Ignore @delegate:Ignore
@IgnoredOnParcel @IgnoredOnParcel
val exploreKinds by lazy { val exploreKinds: List<ExploreKind> by lazy {
val exploreUrl = exploreUrl ?: return@lazy emptyList() val exploreUrl = exploreUrl ?: return@lazy emptyList()
val kinds = arrayListOf<ExploreKind>() val kinds = arrayListOf<ExploreKind>()
var ruleStr = exploreUrl var ruleStr = exploreUrl

@ -21,7 +21,7 @@ data class RssSource(
var sourceComment: String? = null, var sourceComment: String? = null,
var enabled: Boolean = true, var enabled: Boolean = true,
override var header: String? = null, // 请求头 override var header: String? = null, // 请求头
var loginUrl: String? = null, // 登录地址 override var loginUrl: String? = null, // 登录地址
var loginUi: List<RowUi>? = null, //登录UI var loginUi: List<RowUi>? = null, //登录UI
var loginCheckJs: String? = null, //登录检测js var loginCheckJs: String? = null, //登录检测js
var sortUrl: String? = null, var sortUrl: String? = null,

@ -12,6 +12,7 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
@Suppress("MemberVisibilityCanBePrivate")
object Rss { object Rss {
fun getArticles( fun getArticles(
@ -23,18 +24,27 @@ object Rss {
context: CoroutineContext = Dispatchers.IO context: CoroutineContext = Dispatchers.IO
): Coroutine<RssResult> { ): Coroutine<RssResult> {
return Coroutine.async(scope, context) { return Coroutine.async(scope, context) {
val ruleData = RuleData() getArticlesAwait(sortName, sortUrl, rssSource, page)
val analyzeUrl = AnalyzeUrl(
sortUrl,
page = page,
ruleData = ruleData,
headerMapF = rssSource.getHeaderMap()
)
val body = analyzeUrl.getStrResponse(rssSource.sourceUrl).body
RssParserByRule.parseXML(sortName, sortUrl, body, rssSource, ruleData)
} }
} }
suspend fun getArticlesAwait(
sortName: String,
sortUrl: String,
rssSource: RssSource,
page: Int,
): RssResult {
val ruleData = RuleData()
val analyzeUrl = AnalyzeUrl(
sortUrl,
page = page,
ruleData = ruleData,
headerMapF = rssSource.getHeaderMap()
)
val body = analyzeUrl.getStrResponse(rssSource.sourceUrl).body
return RssParserByRule.parseXML(sortName, sortUrl, body, rssSource, ruleData)
}
fun getContent( fun getContent(
scope: CoroutineScope, scope: CoroutineScope,
rssArticle: RssArticle, rssArticle: RssArticle,
@ -43,19 +53,27 @@ object Rss {
context: CoroutineContext = Dispatchers.IO context: CoroutineContext = Dispatchers.IO
): Coroutine<String> { ): Coroutine<String> {
return Coroutine.async(scope, context) { return Coroutine.async(scope, context) {
val analyzeUrl = AnalyzeUrl( getContentAwait(rssArticle, ruleContent, rssSource)
rssArticle.link,
baseUrl = rssArticle.origin,
ruleData = rssArticle,
headerMapF = rssSource.getHeaderMap()
)
val body = analyzeUrl.getStrResponse(rssArticle.origin).body
Debug.log(rssSource.sourceUrl, "≡获取成功:${rssSource.sourceUrl}")
Debug.log(rssSource.sourceUrl, body, state = 20)
val analyzeRule = AnalyzeRule(rssArticle, rssSource)
analyzeRule.setContent(body)
.setBaseUrl(NetworkUtils.getAbsoluteURL(rssArticle.origin, rssArticle.link))
analyzeRule.getString(ruleContent)
} }
} }
suspend fun getContentAwait(
rssArticle: RssArticle,
ruleContent: String,
rssSource: RssSource,
): String {
val analyzeUrl = AnalyzeUrl(
rssArticle.link,
baseUrl = rssArticle.origin,
ruleData = rssArticle,
headerMapF = rssSource.getHeaderMap()
)
val body = analyzeUrl.getStrResponse(rssArticle.origin).body
Debug.log(rssSource.sourceUrl, "≡获取成功:${rssSource.sourceUrl}")
Debug.log(rssSource.sourceUrl, body, state = 20)
val analyzeRule = AnalyzeRule(rssArticle, rssSource)
analyzeRule.setContent(body)
.setBaseUrl(NetworkUtils.getAbsoluteURL(rssArticle.origin, rssArticle.link))
return analyzeRule.getString(ruleContent)
}
} }

@ -113,9 +113,6 @@ class CheckSourceService : BaseService() {
var books = webBook.searchBookAwait(this, CheckSource.keyword) var books = webBook.searchBookAwait(this, CheckSource.keyword)
if (books.isEmpty()) { if (books.isEmpty()) {
val exs = source.exploreKinds val exs = source.exploreKinds
if (exs.isEmpty()) {
throw Exception("搜索内容为空并且没有发现")
}
var url: String? = null var url: String? = null
for (ex in exs) { for (ex in exs) {
url = ex.url url = ex.url
@ -123,11 +120,14 @@ class CheckSourceService : BaseService() {
break break
} }
} }
books = webBook.exploreBookAwait(this, url!!) if (url.isNullOrBlank()) {
throw Exception("搜索内容为空并且没有发现")
}
books = webBook.exploreBookAwait(this, url)
} }
val book = webBook.getBookInfoAwait(this, books.first().toBook()) val book = webBook.getBookInfoAwait(this, books.first().toBook())
val toc = webBook.getChapterListAwait(this, book) val toc = webBook.getChapterListAwait(this, book)
val content = webBook.getContentAwait(this, book, toc.first()) val content = webBook.getContentAwait(this, book, toc.first(), toc.getOrNull(2)?.url)
if (content.isBlank()) { if (content.isBlank()) {
throw Exception("正文内容为空") throw Exception("正文内容为空")
} }

@ -15,6 +15,7 @@ import io.legado.app.ui.widget.text.EditText
import io.legado.app.ui.widget.text.TextInputLayout import io.legado.app.ui.widget.text.TextInputLayout
import io.legado.app.utils.GSON import io.legado.app.utils.GSON
import io.legado.app.utils.applyTint import io.legado.app.utils.applyTint
import io.legado.app.utils.toastOnUi
import io.legado.app.utils.viewbindingdelegate.viewBinding import io.legado.app.utils.viewbindingdelegate.viewBinding
class RuleUiLoginDialog : BaseDialogFragment() { class RuleUiLoginDialog : BaseDialogFragment() {
@ -84,9 +85,14 @@ class RuleUiLoginDialog : BaseDialogFragment() {
} }
} }
bookSource.putLoginInfo(GSON.toJson(loginData)) bookSource.putLoginInfo(GSON.toJson(loginData))
bookSource.loginUrl?.let { bookSource.getLoginJs()?.let {
try {
bookSource.evalJS(it) bookSource.evalJS(it)
toastOnUi(R.string.success)
} catch (e: Exception) {
e.printStackTrace()
toastOnUi(e.localizedMessage ?: "ERROR")
}
} }
} }
} }

@ -125,6 +125,8 @@ object EncoderUtils {
* @param key The key. * @param key The key.
* @param algorithm The name of algorithm. * @param algorithm The name of algorithm.
* @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>. * @param transformation The name of the transformation, e.g., <i>DES/CBC/PKCS5Padding</i>.
* @param iv The buffer with the IV. The contents of the
* buffer are copied to protect against subsequent modification.
* @param isEncrypt True to encrypt, false otherwise. * @param isEncrypt True to encrypt, false otherwise.
* @return the bytes of symmetric encryption or decryption * @return the bytes of symmetric encryption or decryption
*/ */

@ -1,7 +1,7 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
ext.kotlin_version = '1.5.30-M1' ext.kotlin_version = '1.5.30'
repositories { repositories {
google() google()
mavenCentral() mavenCentral()

Loading…
Cancel
Save