Merge pull request #1610 from Xwite/master

书源校验按搜索发现分别校验
pull/1615/head
kunfei 3 years ago committed by GitHub
commit ceab84fa81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      app/src/main/assets/help/SourceMBookHelp.md
  2. 5
      app/src/main/assets/updateLog.md
  3. 7
      app/src/main/java/io/legado/app/data/entities/BookSource.kt
  4. 89
      app/src/main/java/io/legado/app/service/CheckSourceService.kt
  5. 1
      app/src/main/java/io/legado/app/ui/book/read/config/HttpTtsEditViewModel.kt
  6. 10
      app/src/main/java/io/legado/app/ui/book/read/config/SpeakEngineDialog.kt

@ -24,6 +24,6 @@
* 校验所选 * 校验所选
* 校验书源可批量校验书源,由于网络等原因结果仅限参考 * 校验书源可批量校验书源,由于网络等原因结果仅限参考
* "校验成功"是指所选的校验项目全部通过 * "校验成功"是指所选的校验项目全部通过
* 可正常识别搜索为空、发现为空、目录为空、正文为空、校验超时导致的失效,其余原因导致的视为规则失效 * 可正常识别搜索为空、发现为空、搜索(发现)目录为空、搜索(发现)正文为空、校验超时导致的失效,其余原因(网站异常、源码变动)导致的视为规则失效
* 校验搜索优先使用书源填写的校验关键词,不存在时使用用户输入的关键词 * 校验搜索优先使用书源填写的校验关键词,不存在时使用用户输入的关键词
* 校验结束后会自动筛选"失效"书源 * 校验结束后会自动筛选"失效"书源

@ -13,6 +13,11 @@
**2022/02/11** **2022/02/11**
* 目录正文现在按照搜索发现分别校验
* 书源校验的超时校验存在bug
**2022/02/11**
* 可以单独给书籍设置朗读tts * 可以单独给书籍设置朗读tts
* 目录界面菜单添加替换开关,开启替换加载时间会长一些 * 目录界面菜单添加替换开关,开启替换加载时间会长一些
* 书源校验添加规则失效分组,更新书源界面帮助文档 * 书源校验添加规则失效分组,更新书源界面帮助文档

@ -142,6 +142,13 @@ data class BookSource(
return false return false
} }
fun getInvalidGroupNames(): String? {
return bookSourceGroup?.splitNotBlank(AppPattern.splitGroupRegex)?.toHashSet()?.filter {
"失效" in it
}?.joinToString()
}
fun equal(source: BookSource) = fun equal(source: BookSource) =
equal(bookSourceName, source.bookSourceName) equal(bookSourceName, source.bookSourceName)
&& equal(bookSourceUrl, source.bookSourceUrl) && equal(bookSourceUrl, source.bookSourceUrl)

@ -9,6 +9,7 @@ import io.legado.app.constant.EventBus
import io.legado.app.constant.IntentAction import io.legado.app.constant.IntentAction
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.data.entities.Book
import io.legado.app.data.entities.SearchBook import io.legado.app.data.entities.SearchBook
import io.legado.app.help.AppConfig import io.legado.app.help.AppConfig
import io.legado.app.help.coroutine.CompositeCoroutine import io.legado.app.help.coroutine.CompositeCoroutine
@ -34,7 +35,6 @@ class CheckSourceService : BaseService() {
private val checkedIds = ArrayList<String>() private val checkedIds = ArrayList<String>()
private var processIndex = 0 private var processIndex = 0
private var notificationMsg = "" private var notificationMsg = ""
private var books = ArrayList<SearchBook>()
private val notificationBuilder by lazy { private val notificationBuilder by lazy {
NotificationCompat.Builder(this, AppConst.channelIdReadAloud) NotificationCompat.Builder(this, AppConst.channelIdReadAloud)
@ -112,7 +112,10 @@ class CheckSourceService : BaseService() {
} }
} }
fun check(source: BookSource) { /**
*校验书源
*/
private fun check(source: BookSource) {
execute(context = searchCoroutine) { execute(context = searchCoroutine) {
Debug.startChecking(source) Debug.startChecking(source)
var searchWord = CheckSource.keyword var searchWord = CheckSource.keyword
@ -126,7 +129,7 @@ class CheckSourceService : BaseService() {
?.filterNot { ?.filterNot {
it.startsWith("Error: ") it.startsWith("Error: ")
}?.joinToString("\n") }?.joinToString("\n")
//校验搜索 用户设置校验搜索 并且 搜索链接不为空 //校验搜索书籍 用户设置校验搜索 并且 搜索链接不为空
if (CheckSource.checkSearch && !source.searchUrl.isNullOrBlank()) { if (CheckSource.checkSearch && !source.searchUrl.isNullOrBlank()) {
val searchBooks = WebBook.searchBookAwait(this, source, searchWord) val searchBooks = WebBook.searchBookAwait(this, source, searchWord)
if (searchBooks.isEmpty()) { if (searchBooks.isEmpty()) {
@ -136,10 +139,10 @@ class CheckSourceService : BaseService() {
} }
} else { } else {
source.removeGroup("搜索失效") source.removeGroup("搜索失效")
books = searchBooks checkBook(searchBooks.first().toBook(), source)
} }
} }
//校验发现 //校验发现书籍
if (CheckSource.checkDiscovery) { if (CheckSource.checkDiscovery) {
val exs = source.exploreKinds val exs = source.exploreKinds
var url: String? = null var url: String? = null
@ -164,42 +167,15 @@ class CheckSourceService : BaseService() {
} }
} else { } else {
source.removeGroup("发现失效") source.removeGroup("发现失效")
if (books.isEmpty()) books = exploreBooks checkBook(exploreBooks.first().toBook(), source, false)
}
}
}
//校验详情
if (CheckSource.checkInfo) {
var book = books.first().toBook()
if (book.tocUrl.isBlank()) {
book = WebBook.getBookInfoAwait(this, source, book)
}
//校验目录
if (CheckSource.checkCategory) {
val toc = WebBook.getChapterListAwait(this, source, book)
val nextChapterUrl = toc.getOrNull(1)?.url ?: toc.first().url
source.removeGroup("目录失效")
//校验正文
if (CheckSource.checkContent) {
WebBook.getContentAwait(
this,
bookSource = source,
book = book,
bookChapter = toc.first(),
nextChapterUrl = nextChapterUrl,
needSave = false
)
source.removeGroup("正文失效")
} }
} }
} }
if (source.hasGroup("搜索失效")) throw NoStackTraceException("搜索失效") val finalCheckMessage = source.getInvalidGroupNames()
if (source.hasGroup("发现失效")) throw NoStackTraceException("发现失效") if (!finalCheckMessage.isNullOrBlank()) throw NoStackTraceException(finalCheckMessage)
}.timeout(CheckSource.timeout) }.timeout(CheckSource.timeout)
.onError(searchCoroutine) { .onError(searchCoroutine) {
when(it) { when(it) {
is ContentEmptyException -> source.addGroup("正文失效")
is TocEmptyException -> source.addGroup("目录失效")
//校验超时不能正常实现 不能识别 //校验超时不能正常实现 不能识别
is TimeoutCancellationException -> source.addGroup("校验超时") is TimeoutCancellationException -> source.addGroup("校验超时")
//NoStackTraceException 已经添加了分组,其余的视为规则失效 //NoStackTraceException 已经添加了分组,其余的视为规则失效
@ -221,6 +197,49 @@ class CheckSourceService : BaseService() {
} }
} }
/**
*校验书源的详情目录正文
*/
private suspend fun checkBook(book: Book, source: BookSource, isSearchBook: Boolean = true) {
kotlin.runCatching {
var mBook = book
//校验详情
if (CheckSource.checkInfo) {
if (mBook.tocUrl.isBlank()) {
mBook = WebBook.getBookInfoAwait(this, source, mBook)
}
//校验目录
if (CheckSource.checkCategory) {
val toc = WebBook.getChapterListAwait(this, source, mBook)
val nextChapterUrl = toc.getOrNull(1)?.url ?: toc.first().url
//校验正文
if (CheckSource.checkContent) {
WebBook.getContentAwait(
this,
bookSource = source,
book = mBook,
bookChapter = toc.first(),
nextChapterUrl = nextChapterUrl,
needSave = false
)
}
}
}
}.onFailure {
val bookType = if (isSearchBook) "搜索" else "发现"
when (it) {
is ContentEmptyException -> source.addGroup("${bookType}正文失效")
is TocEmptyException -> source.addGroup("${bookType}目录失效")
//超时??js错误
else -> throw it
}
}.onSuccess {
val bookType = if (isSearchBook) "搜索" else "发现"
source.removeGroup("${bookType}目录失效")
source.removeGroup("${bookType}正文失效")
}
}
private fun onNext(sourceUrl: String, sourceName: String) { private fun onNext(sourceUrl: String, sourceName: String) {
synchronized(this) { synchronized(this) {
check() check()

@ -37,6 +37,7 @@ class HttpTtsEditViewModel(app: Application) : BaseViewModel(app) {
id = httpTTS.id id = httpTTS.id
execute { execute {
appDb.httpTTSDao.insert(httpTTS) appDb.httpTTSDao.insert(httpTTS)
if (ReadAloud.ttsEngine == httpTTS.id.toString()) ReadAloud.upReadAloudClass()
}.onSuccess { }.onSuccess {
success?.invoke() success?.invoke()
} }

@ -26,6 +26,7 @@ import io.legado.app.lib.theme.primaryColor
import io.legado.app.model.ReadAloud import io.legado.app.model.ReadAloud
import io.legado.app.model.ReadBook import io.legado.app.model.ReadBook
import io.legado.app.ui.document.HandleFileContract import io.legado.app.ui.document.HandleFileContract
import io.legado.app.ui.login.SourceLoginActivity
import io.legado.app.utils.* import io.legado.app.utils.*
import io.legado.app.utils.viewbindingdelegate.viewBinding import io.legado.app.utils.viewbindingdelegate.viewBinding
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
@ -217,7 +218,14 @@ class SpeakEngineDialog(val callBack: CallBack) : BaseDialogFragment(R.layout.di
binding.run { binding.run {
cbName.setOnClickListener { cbName.setOnClickListener {
getItemByLayoutPosition(holder.layoutPosition)?.let { httpTTS -> getItemByLayoutPosition(holder.layoutPosition)?.let { httpTTS ->
upTts(httpTTS.id.toString()) val id = httpTTS.id.toString()
upTts(id)
if (!httpTTS.loginUrl.isNullOrBlank()) {
startActivity<SourceLoginActivity> {
putExtra("type", "httpTts")
putExtra("key", id)
}
}
} }
} }
ivEdit.setOnClickListener { ivEdit.setOnClickListener {

Loading…
Cancel
Save