Просмотр исходного кода

Merge pull request #1610 from Xwite/master

书源校验按搜索发现分别校验
kunfei 4 лет назад
Родитель
Сommit
9d8cd56217

+ 1 - 1
app/src/main/assets/help/SourceMBookHelp.md

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

+ 5 - 0
app/src/main/assets/updateLog.md

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

+ 7 - 0
app/src/main/java/io/legado/app/data/entities/BookSource.kt

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

+ 54 - 35
app/src/main/java/io/legado/app/service/CheckSourceService.kt

@@ -9,6 +9,7 @@ import io.legado.app.constant.EventBus
 import io.legado.app.constant.IntentAction
 import io.legado.app.data.appDb
 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.help.AppConfig
 import io.legado.app.help.coroutine.CompositeCoroutine
@@ -34,7 +35,6 @@ class CheckSourceService : BaseService() {
     private val checkedIds = ArrayList<String>()
     private var processIndex = 0
     private var notificationMsg = ""
-    private var books = ArrayList<SearchBook>()
 
     private val notificationBuilder by lazy {
         NotificationCompat.Builder(this, AppConst.channelIdReadAloud)
@@ -112,7 +112,10 @@ class CheckSourceService : BaseService() {
         }
     }
 
-    fun check(source: BookSource) {
+    /**
+     *校验书源
+     */
+    private fun check(source: BookSource) {
         execute(context = searchCoroutine) {
             Debug.startChecking(source)
             var searchWord = CheckSource.keyword
@@ -126,7 +129,7 @@ class CheckSourceService : BaseService() {
                 ?.filterNot {
                     it.startsWith("Error: ")
                 }?.joinToString("\n")
-            //校验搜索 用户设置校验搜索 并且 搜索链接不为空
+            //校验搜索书籍 用户设置校验搜索 并且 搜索链接不为空
             if (CheckSource.checkSearch && !source.searchUrl.isNullOrBlank()) {
                 val searchBooks = WebBook.searchBookAwait(this, source, searchWord)
                 if (searchBooks.isEmpty()) {
@@ -136,10 +139,10 @@ class CheckSourceService : BaseService() {
                     }
                 } else {
                     source.removeGroup("搜索失效")
-                    books = searchBooks
+                    checkBook(searchBooks.first().toBook(), source)
                 }
             }
-            //校验发现
+            //校验发现书籍
             if (CheckSource.checkDiscovery) {
                 val exs = source.exploreKinds
                 var url: String? = null
@@ -164,42 +167,15 @@ class CheckSourceService : BaseService() {
                         }
                     } else {
                         source.removeGroup("发现失效")
-                        if (books.isEmpty()) books = exploreBooks
-                    }
-                }
-            }
-            //校验详情
-            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("正文失效")
+                        checkBook(exploreBooks.first().toBook(), source, false)
                     }
                 }
             }
-            if (source.hasGroup("搜索失效")) throw NoStackTraceException("搜索失效")
-            if (source.hasGroup("发现失效")) throw NoStackTraceException("发现失效")
+            val finalCheckMessage = source.getInvalidGroupNames()
+            if (!finalCheckMessage.isNullOrBlank()) throw NoStackTraceException(finalCheckMessage)
         }.timeout(CheckSource.timeout)
             .onError(searchCoroutine) {
                 when(it) {
-                    is ContentEmptyException -> source.addGroup("正文失效")
-                    is TocEmptyException -> source.addGroup("目录失效")
                     //校验超时不能正常实现 不能识别
                     is TimeoutCancellationException -> source.addGroup("校验超时")
                     //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) {
         synchronized(this) {
             check()

+ 1 - 0
app/src/main/java/io/legado/app/ui/book/read/config/HttpTtsEditViewModel.kt

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

+ 9 - 1
app/src/main/java/io/legado/app/ui/book/read/config/SpeakEngineDialog.kt

@@ -26,6 +26,7 @@ import io.legado.app.lib.theme.primaryColor
 import io.legado.app.model.ReadAloud
 import io.legado.app.model.ReadBook
 import io.legado.app.ui.document.HandleFileContract
+import io.legado.app.ui.login.SourceLoginActivity
 import io.legado.app.utils.*
 import io.legado.app.utils.viewbindingdelegate.viewBinding
 import kotlinx.coroutines.launch
@@ -217,7 +218,14 @@ class SpeakEngineDialog(val callBack: CallBack) : BaseDialogFragment(R.layout.di
             binding.run {
                 cbName.setOnClickListener {
                     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 {