From 64d7d3f300939f2401cc8db08ee0417d9c724ee2 Mon Sep 17 00:00:00 2001 From: Horis <8674809+821938089@users.noreply.github.com> Date: Tue, 25 Mar 2025 12:20:50 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/legado/app/data/entities/Book.kt | 2 +- .../io/legado/app/help/book/BookExtensions.kt | 1 + .../app/model/analyzeRule/AnalyzeRule.kt | 4 +-- .../io/legado/app/model/webBook/BookList.kt | 12 ++++++- .../legado/app/model/webBook/SearchModel.kt | 7 +++- .../io/legado/app/model/webBook/WebBook.kt | 31 ++++++++-------- .../book/changecover/ChangeCoverViewModel.kt | 4 ++- .../changesource/ChangeBookSourceViewModel.kt | 22 ++++++------ .../app/ui/book/info/BookInfoViewModel.kt | 36 +++++++------------ .../io/legado/app/ui/main/MainViewModel.kt | 3 +- 10 files changed, 66 insertions(+), 56 deletions(-) diff --git a/app/src/main/java/io/legado/app/data/entities/Book.kt b/app/src/main/java/io/legado/app/data/entities/Book.kt index ae9bdbc35..3a05d2338 100644 --- a/app/src/main/java/io/legado/app/data/entities/Book.kt +++ b/app/src/main/java/io/legado/app/data/entities/Book.kt @@ -365,7 +365,7 @@ data class Book( } fun save() { - if (appDb.bookDao.has(bookUrl) == true) { + if (appDb.bookDao.has(bookUrl)) { appDb.bookDao.update(this) } else { appDb.bookDao.insert(this) diff --git a/app/src/main/java/io/legado/app/help/book/BookExtensions.kt b/app/src/main/java/io/legado/app/help/book/BookExtensions.kt index 10cedb856..dd18cce18 100644 --- a/app/src/main/java/io/legado/app/help/book/BookExtensions.kt +++ b/app/src/main/java/io/legado/app/help/book/BookExtensions.kt @@ -244,6 +244,7 @@ fun Book.sync(oldBook: Book) { } } canUpdate = curBook.canUpdate + readConfig = curBook.readConfig } fun Book.update() { diff --git a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt index 1c990e61a..853f4bf5e 100644 --- a/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt +++ b/app/src/main/java/io/legado/app/model/analyzeRule/AnalyzeRule.kt @@ -815,7 +815,7 @@ class AnalyzeRule( if (bookSource == null || book == null) return runBlocking(coroutineContext) { withTimeout(1800000) { - WebBook.getBookInfoAwait(bookSource, book) + WebBook.getBookInfoAwait(bookSource, book, false) } } } @@ -829,7 +829,7 @@ class AnalyzeRule( if (bookSource == null || book == null) return runBlocking(coroutineContext) { withTimeout(1800000) { - WebBook.getBookInfoAwait(bookSource, book) + WebBook.getBookInfoAwait(bookSource, book, false) } } } diff --git a/app/src/main/java/io/legado/app/model/webBook/BookList.kt b/app/src/main/java/io/legado/app/model/webBook/BookList.kt index d8a1ba56b..2a01d8461 100644 --- a/app/src/main/java/io/legado/app/model/webBook/BookList.kt +++ b/app/src/main/java/io/legado/app/model/webBook/BookList.kt @@ -32,7 +32,9 @@ object BookList { baseUrl: String, body: String?, isSearch: Boolean = true, - isRedirect: Boolean = false + isRedirect: Boolean = false, + filter: ((name: String, author: String) -> Boolean)? = null, + shouldBreak: ((size: Int) -> Boolean)? = null ): ArrayList { body ?: throw NoStackTraceException( appCtx.getString( @@ -107,6 +109,7 @@ object BookList { getSearchItem( bookSource, analyzeRule, item, baseUrl, ruleData.getVariable(), index == 0, + filter, ruleName = ruleName, ruleBookUrl = ruleBookUrl, ruleAuthor = ruleAuthor, @@ -121,6 +124,9 @@ object BookList { } bookList.add(searchBook) } + if (shouldBreak?.invoke(bookList.size) == true) { + break + } } val lh = LinkedHashSet(bookList) bookList.clear() @@ -177,6 +183,7 @@ object BookList { baseUrl: String, variable: String?, log: Boolean, + filter: ((name: String, author: String) -> Boolean)? = null, ruleName: List, ruleBookUrl: List, ruleAuthor: List, @@ -202,6 +209,9 @@ object BookList { Debug.log(bookSource.bookSourceUrl, "┌获取作者", log) searchBook.author = BookHelp.formatBookAuthor(analyzeRule.getString(ruleAuthor)) Debug.log(bookSource.bookSourceUrl, "└${searchBook.author}", log) + if (filter?.invoke(searchBook.name, searchBook.author) == false) { + return null + } coroutineContext.ensureActive() Debug.log(bookSource.bookSourceUrl, "┌获取分类", log) try { diff --git a/app/src/main/java/io/legado/app/model/webBook/SearchModel.kt b/app/src/main/java/io/legado/app/model/webBook/SearchModel.kt index 50dd83186..e9f71b287 100644 --- a/app/src/main/java/io/legado/app/model/webBook/SearchModel.kt +++ b/app/src/main/java/io/legado/app/model/webBook/SearchModel.kt @@ -85,7 +85,12 @@ class SearchModel(private val scope: CoroutineScope, private val callBack: CallB callBack.onSearchStart() }.mapParallelSafe(threadCount) { withTimeout(30000L) { - WebBook.searchBookAwait(it, searchKey, searchPage) + WebBook.searchBookAwait( + it, searchKey, searchPage, + filter = { name, author -> + !precision || name.contains(searchKey) || + author.contains(searchKey) + }) } }.onEach { items -> for (book in items) { diff --git a/app/src/main/java/io/legado/app/model/webBook/WebBook.kt b/app/src/main/java/io/legado/app/model/webBook/WebBook.kt index f446a370c..fbd1518b0 100644 --- a/app/src/main/java/io/legado/app/model/webBook/WebBook.kt +++ b/app/src/main/java/io/legado/app/model/webBook/WebBook.kt @@ -49,6 +49,8 @@ object WebBook { bookSource: BookSource, key: String, page: Int? = 1, + filter: ((name: String, author: String) -> Boolean)? = null, + shouldBreak: ((size: Int) -> Boolean)? = null ): ArrayList { val searchUrl = bookSource.searchUrl if (searchUrl.isNullOrBlank()) { @@ -80,7 +82,9 @@ object WebBook { baseUrl = res.url, body = res.body, isSearch = true, - isRedirect = res.raw.priorResponse?.isRedirect == true + isRedirect = res.raw.priorResponse?.isRedirect == true, + filter = filter, + shouldBreak = shouldBreak ) } @@ -207,21 +211,16 @@ object WebBook { } } - suspend fun runPreUpdateJs(bookSource: BookSource, book: Book): Result { + suspend fun runPreUpdateJs(bookSource: BookSource, book: Book): Result { return kotlin.runCatching { val preUpdateJs = bookSource.ruleToc?.preUpdateJs if (!preUpdateJs.isNullOrBlank()) { - kotlin.runCatching { - AnalyzeRule(book, bookSource) - .setCoroutineContext(coroutineContext) - .evalJS(preUpdateJs) - }.onFailure { - AppLog.put("执行preUpdateJs规则失败 书源:${bookSource.bookSourceName}", it) - throw it - } - return@runCatching true + AnalyzeRule(book, bookSource) + .setCoroutineContext(coroutineContext) + .evalJS(preUpdateJs) } - return@runCatching false + }.onFailure { + AppLog.put("执行preUpdateJs规则失败 书源:${bookSource.bookSourceName}", it) } } @@ -386,9 +385,11 @@ object WebBook { ): Result { return kotlin.runCatching { scope.isActive - searchBookAwait(bookSource, name).firstOrNull { - it.name == name && it.author == author - }?.let { searchBook -> + searchBookAwait( + bookSource, name, + filter = { fName, fAuthor -> fName == name && fAuthor == author }, + shouldBreak = { it > 0 } + ).firstOrNull()?.let { searchBook -> scope.isActive var book = searchBook.toBook() if (book.tocUrl.isBlank()) { diff --git a/app/src/main/java/io/legado/app/ui/book/changecover/ChangeCoverViewModel.kt b/app/src/main/java/io/legado/app/ui/book/changecover/ChangeCoverViewModel.kt index d2291bb7f..2df4a0b5c 100644 --- a/app/src/main/java/io/legado/app/ui/book/changecover/ChangeCoverViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/changecover/ChangeCoverViewModel.kt @@ -137,7 +137,9 @@ class ChangeCoverViewModel(application: Application) : BaseViewModel(application if (source.getSearchRule().coverUrl.isNullOrBlank()) { return } - val searchBook = WebBook.searchBookAwait(source, name).firstOrNull() ?: return + val searchBook = WebBook.searchBookAwait( + source, name, + shouldBreak = { it > 0 }).firstOrNull() ?: return if (searchBook.name == name && searchBook.author == author && !searchBook.coverUrl.isNullOrEmpty() ) { diff --git a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceViewModel.kt b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceViewModel.kt index d0b7e1d08..499f81b60 100644 --- a/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/changesource/ChangeBookSourceViewModel.kt @@ -237,18 +237,18 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a } private suspend fun search(source: BookSource) { - val resultBooks = WebBook.searchBookAwait(source, name) - resultBooks.filter { searchBook -> - if (searchBook.name != name) { - return@filter false - } - if (AppConfig.changeSourceCheckAuthor && !searchBook.author.contains(author)) { - return@filter false - } - true - }.forEach { searchBook -> + val checkAuthor = AppConfig.changeSourceCheckAuthor + val loadInfo = AppConfig.changeSourceLoadInfo + val loadToc = AppConfig.changeSourceLoadToc + val loadWordCount = AppConfig.changeSourceLoadWordCount + val resultBooks = WebBook.searchBookAwait( + source, name, + filter = { fName, fAuthor -> + fName == name && (!checkAuthor || fAuthor.contains(author)) + }) + resultBooks.forEach { searchBook -> when { - AppConfig.changeSourceLoadInfo || AppConfig.changeSourceLoadToc || AppConfig.changeSourceLoadWordCount -> { + loadInfo || loadToc || loadWordCount -> { loadBookInfo(source, searchBook.toBook()) } diff --git a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt index aeee7c217..73cf7d5f3 100644 --- a/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt @@ -98,7 +98,7 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { bookSource = if (book.isLocal) null else appDb.bookSourceDao.getBookSource(book.origin) if (book.tocUrl.isEmpty() && !book.isLocal) { - loadBookInfo(book) + loadBookInfo(book, runPreUpdateJs = inBookshelf) } else { val chapterList = appDb.bookChapterDao.getChapterList(book.bookUrl) if (chapterList.isNotEmpty()) { @@ -166,12 +166,13 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { fun loadBookInfo( book: Book, canReName: Boolean = true, + runPreUpdateJs: Boolean = true, scope: CoroutineScope = viewModelScope ) { if (book.isLocal) { LocalBook.upBookInfo(book) bookData.postValue(book) - loadChapter(book, scope) + loadChapter(book) } else { val bookSource = bookSource ?: let { chapterListData.postValue(emptyList()) @@ -192,22 +193,12 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { } bookData.postValue(it) if (inBookshelf) { - if (!appDb.bookDao.has(it.bookUrl)) { - /** - * 来自搜索,同一本书,不同 bookUrl - */ - appDb.bookDao.insert(it) - } else { - appDb.bookDao.update(it) - } - if (dbBook != null && (dbBook.name != book.name || dbBook.bookUrl != book.bookUrl)) { - BookHelp.updateCacheFolder(dbBook, book) - } + it.save() } if (it.isWebFile) { - loadWebFile(it, scope) + loadWebFile(it) } else { - loadChapter(it, scope) + loadChapter(it, runPreUpdateJs) } }.onError { AppLog.put("获取书籍信息失败\n${it.localizedMessage}", it) @@ -218,6 +209,7 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { private fun loadChapter( book: Book, + runPreUpdateJs: Boolean = true, scope: CoroutineScope = viewModelScope ) { if (book.isLocal) { @@ -240,16 +232,14 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) { return } val oldBook = book.copy() - WebBook.getChapterList(scope, bookSource, book, true) + WebBook.getChapterList(scope, bookSource, book, runPreUpdateJs) .onSuccess(IO) { - /** - * runPreUpdateJs 有可能会修改 book 的书名作者和 bookUrl - */ if (inBookshelf) { - if (oldBook.bookUrl == book.bookUrl) { - appDb.bookDao.update(book) - } else { - appDb.bookDao.insert(book) + book.save() + /** + * runPreUpdateJs 有可能会修改 book 的 bookUrl + */ + if (oldBook.bookUrl != book.bookUrl) { BookHelp.updateCacheFolder(oldBook, book) } appDb.bookChapterDao.delByBook(oldBook.bookUrl) diff --git a/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt b/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt index a5d18f8fe..60f8dae8c 100644 --- a/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/main/MainViewModel.kt @@ -152,9 +152,10 @@ class MainViewModel(application: Application) : BaseViewModel(application) { } kotlin.runCatching { val oldBook = book.copy() - WebBook.runPreUpdateJs(source, book) if (book.tocUrl.isBlank()) { WebBook.getBookInfoAwait(source, book) + } else { + WebBook.runPreUpdateJs(source, book) } val toc = WebBook.getChapterListAwait(source, book).getOrThrow() book.sync(oldBook)