优化
This commit is contained in:
@@ -365,7 +365,7 @@ data class Book(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun save() {
|
fun save() {
|
||||||
if (appDb.bookDao.has(bookUrl) == true) {
|
if (appDb.bookDao.has(bookUrl)) {
|
||||||
appDb.bookDao.update(this)
|
appDb.bookDao.update(this)
|
||||||
} else {
|
} else {
|
||||||
appDb.bookDao.insert(this)
|
appDb.bookDao.insert(this)
|
||||||
|
|||||||
@@ -244,6 +244,7 @@ fun Book.sync(oldBook: Book) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
canUpdate = curBook.canUpdate
|
canUpdate = curBook.canUpdate
|
||||||
|
readConfig = curBook.readConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Book.update() {
|
fun Book.update() {
|
||||||
|
|||||||
@@ -815,7 +815,7 @@ class AnalyzeRule(
|
|||||||
if (bookSource == null || book == null) return
|
if (bookSource == null || book == null) return
|
||||||
runBlocking(coroutineContext) {
|
runBlocking(coroutineContext) {
|
||||||
withTimeout(1800000) {
|
withTimeout(1800000) {
|
||||||
WebBook.getBookInfoAwait(bookSource, book)
|
WebBook.getBookInfoAwait(bookSource, book, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -829,7 +829,7 @@ class AnalyzeRule(
|
|||||||
if (bookSource == null || book == null) return
|
if (bookSource == null || book == null) return
|
||||||
runBlocking(coroutineContext) {
|
runBlocking(coroutineContext) {
|
||||||
withTimeout(1800000) {
|
withTimeout(1800000) {
|
||||||
WebBook.getBookInfoAwait(bookSource, book)
|
WebBook.getBookInfoAwait(bookSource, book, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,9 @@ object BookList {
|
|||||||
baseUrl: String,
|
baseUrl: String,
|
||||||
body: String?,
|
body: String?,
|
||||||
isSearch: Boolean = true,
|
isSearch: Boolean = true,
|
||||||
isRedirect: Boolean = false
|
isRedirect: Boolean = false,
|
||||||
|
filter: ((name: String, author: String) -> Boolean)? = null,
|
||||||
|
shouldBreak: ((size: Int) -> Boolean)? = null
|
||||||
): ArrayList<SearchBook> {
|
): ArrayList<SearchBook> {
|
||||||
body ?: throw NoStackTraceException(
|
body ?: throw NoStackTraceException(
|
||||||
appCtx.getString(
|
appCtx.getString(
|
||||||
@@ -107,6 +109,7 @@ object BookList {
|
|||||||
getSearchItem(
|
getSearchItem(
|
||||||
bookSource, analyzeRule, item, baseUrl, ruleData.getVariable(),
|
bookSource, analyzeRule, item, baseUrl, ruleData.getVariable(),
|
||||||
index == 0,
|
index == 0,
|
||||||
|
filter,
|
||||||
ruleName = ruleName,
|
ruleName = ruleName,
|
||||||
ruleBookUrl = ruleBookUrl,
|
ruleBookUrl = ruleBookUrl,
|
||||||
ruleAuthor = ruleAuthor,
|
ruleAuthor = ruleAuthor,
|
||||||
@@ -121,6 +124,9 @@ object BookList {
|
|||||||
}
|
}
|
||||||
bookList.add(searchBook)
|
bookList.add(searchBook)
|
||||||
}
|
}
|
||||||
|
if (shouldBreak?.invoke(bookList.size) == true) {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val lh = LinkedHashSet(bookList)
|
val lh = LinkedHashSet(bookList)
|
||||||
bookList.clear()
|
bookList.clear()
|
||||||
@@ -177,6 +183,7 @@ object BookList {
|
|||||||
baseUrl: String,
|
baseUrl: String,
|
||||||
variable: String?,
|
variable: String?,
|
||||||
log: Boolean,
|
log: Boolean,
|
||||||
|
filter: ((name: String, author: String) -> Boolean)? = null,
|
||||||
ruleName: List<AnalyzeRule.SourceRule>,
|
ruleName: List<AnalyzeRule.SourceRule>,
|
||||||
ruleBookUrl: List<AnalyzeRule.SourceRule>,
|
ruleBookUrl: List<AnalyzeRule.SourceRule>,
|
||||||
ruleAuthor: List<AnalyzeRule.SourceRule>,
|
ruleAuthor: List<AnalyzeRule.SourceRule>,
|
||||||
@@ -202,6 +209,9 @@ object BookList {
|
|||||||
Debug.log(bookSource.bookSourceUrl, "┌获取作者", log)
|
Debug.log(bookSource.bookSourceUrl, "┌获取作者", log)
|
||||||
searchBook.author = BookHelp.formatBookAuthor(analyzeRule.getString(ruleAuthor))
|
searchBook.author = BookHelp.formatBookAuthor(analyzeRule.getString(ruleAuthor))
|
||||||
Debug.log(bookSource.bookSourceUrl, "└${searchBook.author}", log)
|
Debug.log(bookSource.bookSourceUrl, "└${searchBook.author}", log)
|
||||||
|
if (filter?.invoke(searchBook.name, searchBook.author) == false) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
coroutineContext.ensureActive()
|
coroutineContext.ensureActive()
|
||||||
Debug.log(bookSource.bookSourceUrl, "┌获取分类", log)
|
Debug.log(bookSource.bookSourceUrl, "┌获取分类", log)
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -85,7 +85,12 @@ class SearchModel(private val scope: CoroutineScope, private val callBack: CallB
|
|||||||
callBack.onSearchStart()
|
callBack.onSearchStart()
|
||||||
}.mapParallelSafe(threadCount) {
|
}.mapParallelSafe(threadCount) {
|
||||||
withTimeout(30000L) {
|
withTimeout(30000L) {
|
||||||
WebBook.searchBookAwait(it, searchKey, searchPage)
|
WebBook.searchBookAwait(
|
||||||
|
it, searchKey, searchPage,
|
||||||
|
filter = { name, author ->
|
||||||
|
!precision || name.contains(searchKey) ||
|
||||||
|
author.contains(searchKey)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}.onEach { items ->
|
}.onEach { items ->
|
||||||
for (book in items) {
|
for (book in items) {
|
||||||
|
|||||||
@@ -49,6 +49,8 @@ object WebBook {
|
|||||||
bookSource: BookSource,
|
bookSource: BookSource,
|
||||||
key: String,
|
key: String,
|
||||||
page: Int? = 1,
|
page: Int? = 1,
|
||||||
|
filter: ((name: String, author: String) -> Boolean)? = null,
|
||||||
|
shouldBreak: ((size: Int) -> Boolean)? = null
|
||||||
): ArrayList<SearchBook> {
|
): ArrayList<SearchBook> {
|
||||||
val searchUrl = bookSource.searchUrl
|
val searchUrl = bookSource.searchUrl
|
||||||
if (searchUrl.isNullOrBlank()) {
|
if (searchUrl.isNullOrBlank()) {
|
||||||
@@ -80,7 +82,9 @@ object WebBook {
|
|||||||
baseUrl = res.url,
|
baseUrl = res.url,
|
||||||
body = res.body,
|
body = res.body,
|
||||||
isSearch = true,
|
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<Boolean> {
|
suspend fun runPreUpdateJs(bookSource: BookSource, book: Book): Result<Unit> {
|
||||||
return kotlin.runCatching {
|
return kotlin.runCatching {
|
||||||
val preUpdateJs = bookSource.ruleToc?.preUpdateJs
|
val preUpdateJs = bookSource.ruleToc?.preUpdateJs
|
||||||
if (!preUpdateJs.isNullOrBlank()) {
|
if (!preUpdateJs.isNullOrBlank()) {
|
||||||
kotlin.runCatching {
|
AnalyzeRule(book, bookSource)
|
||||||
AnalyzeRule(book, bookSource)
|
.setCoroutineContext(coroutineContext)
|
||||||
.setCoroutineContext(coroutineContext)
|
.evalJS(preUpdateJs)
|
||||||
.evalJS(preUpdateJs)
|
|
||||||
}.onFailure {
|
|
||||||
AppLog.put("执行preUpdateJs规则失败 书源:${bookSource.bookSourceName}", it)
|
|
||||||
throw it
|
|
||||||
}
|
|
||||||
return@runCatching true
|
|
||||||
}
|
}
|
||||||
return@runCatching false
|
}.onFailure {
|
||||||
|
AppLog.put("执行preUpdateJs规则失败 书源:${bookSource.bookSourceName}", it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,9 +385,11 @@ object WebBook {
|
|||||||
): Result<Book> {
|
): Result<Book> {
|
||||||
return kotlin.runCatching {
|
return kotlin.runCatching {
|
||||||
scope.isActive
|
scope.isActive
|
||||||
searchBookAwait(bookSource, name).firstOrNull {
|
searchBookAwait(
|
||||||
it.name == name && it.author == author
|
bookSource, name,
|
||||||
}?.let { searchBook ->
|
filter = { fName, fAuthor -> fName == name && fAuthor == author },
|
||||||
|
shouldBreak = { it > 0 }
|
||||||
|
).firstOrNull()?.let { searchBook ->
|
||||||
scope.isActive
|
scope.isActive
|
||||||
var book = searchBook.toBook()
|
var book = searchBook.toBook()
|
||||||
if (book.tocUrl.isBlank()) {
|
if (book.tocUrl.isBlank()) {
|
||||||
|
|||||||
@@ -137,7 +137,9 @@ class ChangeCoverViewModel(application: Application) : BaseViewModel(application
|
|||||||
if (source.getSearchRule().coverUrl.isNullOrBlank()) {
|
if (source.getSearchRule().coverUrl.isNullOrBlank()) {
|
||||||
return
|
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
|
if (searchBook.name == name && searchBook.author == author
|
||||||
&& !searchBook.coverUrl.isNullOrEmpty()
|
&& !searchBook.coverUrl.isNullOrEmpty()
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -237,18 +237,18 @@ open class ChangeBookSourceViewModel(application: Application) : BaseViewModel(a
|
|||||||
}
|
}
|
||||||
|
|
||||||
private suspend fun search(source: BookSource) {
|
private suspend fun search(source: BookSource) {
|
||||||
val resultBooks = WebBook.searchBookAwait(source, name)
|
val checkAuthor = AppConfig.changeSourceCheckAuthor
|
||||||
resultBooks.filter { searchBook ->
|
val loadInfo = AppConfig.changeSourceLoadInfo
|
||||||
if (searchBook.name != name) {
|
val loadToc = AppConfig.changeSourceLoadToc
|
||||||
return@filter false
|
val loadWordCount = AppConfig.changeSourceLoadWordCount
|
||||||
}
|
val resultBooks = WebBook.searchBookAwait(
|
||||||
if (AppConfig.changeSourceCheckAuthor && !searchBook.author.contains(author)) {
|
source, name,
|
||||||
return@filter false
|
filter = { fName, fAuthor ->
|
||||||
}
|
fName == name && (!checkAuthor || fAuthor.contains(author))
|
||||||
true
|
})
|
||||||
}.forEach { searchBook ->
|
resultBooks.forEach { searchBook ->
|
||||||
when {
|
when {
|
||||||
AppConfig.changeSourceLoadInfo || AppConfig.changeSourceLoadToc || AppConfig.changeSourceLoadWordCount -> {
|
loadInfo || loadToc || loadWordCount -> {
|
||||||
loadBookInfo(source, searchBook.toBook())
|
loadBookInfo(source, searchBook.toBook())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
bookSource = if (book.isLocal) null else
|
bookSource = if (book.isLocal) null else
|
||||||
appDb.bookSourceDao.getBookSource(book.origin)
|
appDb.bookSourceDao.getBookSource(book.origin)
|
||||||
if (book.tocUrl.isEmpty() && !book.isLocal) {
|
if (book.tocUrl.isEmpty() && !book.isLocal) {
|
||||||
loadBookInfo(book)
|
loadBookInfo(book, runPreUpdateJs = inBookshelf)
|
||||||
} else {
|
} else {
|
||||||
val chapterList = appDb.bookChapterDao.getChapterList(book.bookUrl)
|
val chapterList = appDb.bookChapterDao.getChapterList(book.bookUrl)
|
||||||
if (chapterList.isNotEmpty()) {
|
if (chapterList.isNotEmpty()) {
|
||||||
@@ -166,12 +166,13 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
fun loadBookInfo(
|
fun loadBookInfo(
|
||||||
book: Book,
|
book: Book,
|
||||||
canReName: Boolean = true,
|
canReName: Boolean = true,
|
||||||
|
runPreUpdateJs: Boolean = true,
|
||||||
scope: CoroutineScope = viewModelScope
|
scope: CoroutineScope = viewModelScope
|
||||||
) {
|
) {
|
||||||
if (book.isLocal) {
|
if (book.isLocal) {
|
||||||
LocalBook.upBookInfo(book)
|
LocalBook.upBookInfo(book)
|
||||||
bookData.postValue(book)
|
bookData.postValue(book)
|
||||||
loadChapter(book, scope)
|
loadChapter(book)
|
||||||
} else {
|
} else {
|
||||||
val bookSource = bookSource ?: let {
|
val bookSource = bookSource ?: let {
|
||||||
chapterListData.postValue(emptyList())
|
chapterListData.postValue(emptyList())
|
||||||
@@ -192,22 +193,12 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
}
|
}
|
||||||
bookData.postValue(it)
|
bookData.postValue(it)
|
||||||
if (inBookshelf) {
|
if (inBookshelf) {
|
||||||
if (!appDb.bookDao.has(it.bookUrl)) {
|
it.save()
|
||||||
/**
|
|
||||||
* 来自搜索,同一本书,不同 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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (it.isWebFile) {
|
if (it.isWebFile) {
|
||||||
loadWebFile(it, scope)
|
loadWebFile(it)
|
||||||
} else {
|
} else {
|
||||||
loadChapter(it, scope)
|
loadChapter(it, runPreUpdateJs)
|
||||||
}
|
}
|
||||||
}.onError {
|
}.onError {
|
||||||
AppLog.put("获取书籍信息失败\n${it.localizedMessage}", it)
|
AppLog.put("获取书籍信息失败\n${it.localizedMessage}", it)
|
||||||
@@ -218,6 +209,7 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
|
|
||||||
private fun loadChapter(
|
private fun loadChapter(
|
||||||
book: Book,
|
book: Book,
|
||||||
|
runPreUpdateJs: Boolean = true,
|
||||||
scope: CoroutineScope = viewModelScope
|
scope: CoroutineScope = viewModelScope
|
||||||
) {
|
) {
|
||||||
if (book.isLocal) {
|
if (book.isLocal) {
|
||||||
@@ -240,16 +232,14 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
val oldBook = book.copy()
|
val oldBook = book.copy()
|
||||||
WebBook.getChapterList(scope, bookSource, book, true)
|
WebBook.getChapterList(scope, bookSource, book, runPreUpdateJs)
|
||||||
.onSuccess(IO) {
|
.onSuccess(IO) {
|
||||||
/**
|
|
||||||
* runPreUpdateJs 有可能会修改 book 的书名作者和 bookUrl
|
|
||||||
*/
|
|
||||||
if (inBookshelf) {
|
if (inBookshelf) {
|
||||||
if (oldBook.bookUrl == book.bookUrl) {
|
book.save()
|
||||||
appDb.bookDao.update(book)
|
/**
|
||||||
} else {
|
* runPreUpdateJs 有可能会修改 book 的 bookUrl
|
||||||
appDb.bookDao.insert(book)
|
*/
|
||||||
|
if (oldBook.bookUrl != book.bookUrl) {
|
||||||
BookHelp.updateCacheFolder(oldBook, book)
|
BookHelp.updateCacheFolder(oldBook, book)
|
||||||
}
|
}
|
||||||
appDb.bookChapterDao.delByBook(oldBook.bookUrl)
|
appDb.bookChapterDao.delByBook(oldBook.bookUrl)
|
||||||
|
|||||||
@@ -152,9 +152,10 @@ class MainViewModel(application: Application) : BaseViewModel(application) {
|
|||||||
}
|
}
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
val oldBook = book.copy()
|
val oldBook = book.copy()
|
||||||
WebBook.runPreUpdateJs(source, book)
|
|
||||||
if (book.tocUrl.isBlank()) {
|
if (book.tocUrl.isBlank()) {
|
||||||
WebBook.getBookInfoAwait(source, book)
|
WebBook.getBookInfoAwait(source, book)
|
||||||
|
} else {
|
||||||
|
WebBook.runPreUpdateJs(source, book)
|
||||||
}
|
}
|
||||||
val toc = WebBook.getChapterListAwait(source, book).getOrThrow()
|
val toc = WebBook.getChapterListAwait(source, book).getOrThrow()
|
||||||
book.sync(oldBook)
|
book.sync(oldBook)
|
||||||
|
|||||||
Reference in New Issue
Block a user