pull/783/head
gedoor 4 years ago
parent 0ff8e5ae9a
commit a9fa608da4
  1. 2
      app/src/main/java/io/legado/app/api/controller/BookshelfController.kt
  2. 40
      app/src/main/java/io/legado/app/model/Debug.kt
  3. 20
      app/src/main/java/io/legado/app/model/webBook/PreciseSearch.kt
  4. 2
      app/src/main/java/io/legado/app/model/webBook/SearchBookModel.kt
  5. 26
      app/src/main/java/io/legado/app/model/webBook/WebBook.kt
  6. 2
      app/src/main/java/io/legado/app/service/AudioPlayService.kt
  7. 8
      app/src/main/java/io/legado/app/service/CacheBookService.kt
  8. 4
      app/src/main/java/io/legado/app/service/help/CacheBook.kt
  9. 2
      app/src/main/java/io/legado/app/service/help/CheckSource.kt
  10. 2
      app/src/main/java/io/legado/app/service/help/ReadBook.kt
  11. 4
      app/src/main/java/io/legado/app/ui/audio/AudioPlayViewModel.kt
  12. 2
      app/src/main/java/io/legado/app/ui/book/changecover/ChangeCoverViewModel.kt
  13. 6
      app/src/main/java/io/legado/app/ui/book/changesource/ChangeSourceViewModel.kt
  14. 2
      app/src/main/java/io/legado/app/ui/book/explore/ExploreShowViewModel.kt
  15. 4
      app/src/main/java/io/legado/app/ui/book/info/BookInfoViewModel.kt
  16. 7
      app/src/main/java/io/legado/app/ui/book/read/ReadBookViewModel.kt
  17. 11
      app/src/main/java/io/legado/app/ui/book/source/debug/BookSourceDebugModel.kt
  18. 4
      app/src/main/java/io/legado/app/ui/main/MainViewModel.kt
  19. 38
      app/src/main/java/io/legado/app/ui/main/bookshelf/BookshelfViewModel.kt
  20. 2
      app/src/main/java/io/legado/app/web/utils/SourceDebugWebSocket.kt

@ -66,7 +66,7 @@ object BookshelfController {
} else {
App.db.bookSourceDao.getBookSource(book.origin)?.let { source ->
runBlocking {
WebBook(source).getContentAwait(book, chapter)
WebBook(source).getContentAwait(this, book, chapter)
}.let {
saveBookReadIndex(book, index)
returnData.setData(it)

@ -11,6 +11,7 @@ import io.legado.app.model.webBook.WebBook
import io.legado.app.utils.htmlFormat
import io.legado.app.utils.isAbsUrl
import io.legado.app.utils.msg
import kotlinx.coroutines.CoroutineScope
import java.text.SimpleDateFormat
import java.util.*
@ -101,7 +102,7 @@ object Debug {
}
}
fun startDebug(webBook: WebBook, key: String) {
fun startDebug(scope: CoroutineScope, webBook: WebBook, key: String) {
cancelDebug()
debugSource = webBook.sourceUrl
startTime = System.currentTimeMillis()
@ -111,12 +112,12 @@ object Debug {
book.origin = webBook.sourceUrl
book.bookUrl = key
log(webBook.sourceUrl, "⇒开始访问详情页:$key")
infoDebug(webBook, book)
infoDebug(scope, webBook, book)
}
key.contains("::") -> {
val url = key.substring(key.indexOf("::") + 2)
log(webBook.sourceUrl, "⇒开始访问发现页:$url")
exploreDebug(webBook, url)
exploreDebug(scope, webBook, url)
}
key.startsWith("++")-> {
val url = key.substring(2)
@ -124,7 +125,7 @@ object Debug {
book.origin = webBook.sourceUrl
book.tocUrl = url
log(webBook.sourceUrl, "⇒开始访目录页:$url")
tocDebug(webBook, book)
tocDebug(scope, webBook, book)
}
key.startsWith("--")-> {
val url = key.substring(2)
@ -134,23 +135,23 @@ object Debug {
val chapter = BookChapter()
chapter.title = "调试"
chapter.url = url
contentDebug(webBook, book, chapter, null)
contentDebug(scope, webBook, book, chapter, null)
}
else -> {
log(webBook.sourceUrl, "⇒开始搜索关键字:$key")
searchDebug(webBook, key)
searchDebug(scope, webBook, key)
}
}
}
private fun exploreDebug(webBook: WebBook, url: String) {
private fun exploreDebug(scope: CoroutineScope, webBook: WebBook, url: String) {
log(debugSource, "︾开始解析发现页")
val explore = webBook.exploreBook(url, 1)
val explore = webBook.exploreBook(scope, url, 1)
.onSuccess { exploreBooks ->
if (exploreBooks.isNotEmpty()) {
log(debugSource, "︽发现页解析完成")
log(debugSource, showTime = false)
infoDebug(webBook, exploreBooks[0].toBook())
infoDebug(scope, webBook, exploreBooks[0].toBook())
} else {
log(debugSource, "︽未获取到书籍", state = -1)
}
@ -161,14 +162,14 @@ object Debug {
tasks.add(explore)
}
private fun searchDebug(webBook: WebBook, key: String) {
private fun searchDebug(scope: CoroutineScope, webBook: WebBook, key: String) {
log(debugSource, "︾开始解析搜索页")
val search = webBook.searchBook(key, 1)
val search = webBook.searchBook(scope, key, 1)
.onSuccess { searchBooks ->
if (searchBooks.isNotEmpty()) {
log(debugSource, "︽搜索页解析完成")
log(debugSource, showTime = false)
infoDebug(webBook, searchBooks[0].toBook())
infoDebug(scope, webBook, searchBooks[0].toBook())
} else {
log(debugSource, "︽未获取到书籍", state = -1)
}
@ -179,13 +180,13 @@ object Debug {
tasks.add(search)
}
private fun infoDebug(webBook: WebBook, book: Book) {
private fun infoDebug(scope: CoroutineScope, webBook: WebBook, book: Book) {
log(debugSource, "︾开始解析详情页")
val info = webBook.getBookInfo(book)
val info = webBook.getBookInfo(scope, book)
.onSuccess {
log(debugSource, "︽详情页解析完成")
log(debugSource, showTime = false)
tocDebug(webBook, book)
tocDebug(scope, webBook, book)
}
.onError {
log(debugSource, it.msg, state = -1)
@ -193,15 +194,15 @@ object Debug {
tasks.add(info)
}
private fun tocDebug(webBook: WebBook, book: Book) {
private fun tocDebug(scope: CoroutineScope, webBook: WebBook, book: Book) {
log(debugSource, "︾开始解析目录页")
val chapterList = webBook.getChapterList(book)
val chapterList = webBook.getChapterList(scope, book)
.onSuccess {
if (it.isNotEmpty()) {
log(debugSource, "︽目录页解析完成")
log(debugSource, showTime = false)
val nextChapterUrl = if (it.size > 1) it[1].url else null
contentDebug(webBook, book, it[0], nextChapterUrl)
contentDebug(scope, webBook, book, it[0], nextChapterUrl)
} else {
log(debugSource, "︽目录列表为空", state = -1)
}
@ -213,13 +214,14 @@ object Debug {
}
private fun contentDebug(
scope: CoroutineScope,
webBook: WebBook,
book: Book,
bookChapter: BookChapter,
nextChapterUrl: String?
) {
log(debugSource, "︾开始解析正文页")
val content = webBook.getContent(book, bookChapter, nextChapterUrl)
val content = webBook.getContent(scope, book, bookChapter, nextChapterUrl)
.onSuccess {
log(debugSource, "︽正文页解析完成", state = 1000)
}

@ -0,0 +1,20 @@
package io.legado.app.model.webBook
import io.legado.app.data.entities.BookSource
import kotlinx.coroutines.CoroutineScope
/**
* 精准搜索
*/
object PreciseSearch {
suspend fun searchFirstBook(
scope: CoroutineScope,
bookSources: List<BookSource>,
name: String,
author: String
) {
}
}

@ -68,9 +68,9 @@ class SearchBookModel(private val scope: CoroutineScope, private val callBack: C
searchIndex++
val source = bookSourceList[searchIndex]
val task = WebBook(source).searchBook(
scope,
searchKey,
searchPage,
scope = scope,
context = searchPool!!
).timeout(30000L)
.onSuccess(IO) {

@ -21,9 +21,9 @@ class WebBook(val bookSource: BookSource) {
* 搜索
*/
fun searchBook(
scope: CoroutineScope,
key: String,
page: Int? = 1,
scope: CoroutineScope = Coroutine.DEFAULT,
context: CoroutineContext = Dispatchers.IO,
): Coroutine<ArrayList<SearchBook>> {
return Coroutine.async(scope, context) {
@ -64,20 +64,20 @@ class WebBook(val bookSource: BookSource) {
* 发现
*/
fun exploreBook(
scope: CoroutineScope,
url: String,
page: Int? = 1,
scope: CoroutineScope = Coroutine.DEFAULT,
context: CoroutineContext = Dispatchers.IO,
): Coroutine<List<SearchBook>> {
return Coroutine.async(scope, context) {
exploreBookAwait(url, page, scope)
exploreBookAwait(scope, url, page)
}
}
suspend fun exploreBookAwait(
scope: CoroutineScope = Coroutine.DEFAULT,
url: String,
page: Int? = 1,
scope: CoroutineScope = Coroutine.DEFAULT
): ArrayList<SearchBook> {
val variableBook = SearchBook()
val analyzeUrl = AnalyzeUrl(
@ -103,19 +103,19 @@ class WebBook(val bookSource: BookSource) {
* 书籍信息
*/
fun getBookInfo(
scope: CoroutineScope,
book: Book,
scope: CoroutineScope = Coroutine.DEFAULT,
context: CoroutineContext = Dispatchers.IO,
canReName: Boolean = true,
): Coroutine<Book> {
return Coroutine.async(scope, context) {
getBookInfoAwait(book, scope, canReName)
getBookInfoAwait(scope, book, canReName)
}
}
suspend fun getBookInfoAwait(
book: Book,
scope: CoroutineScope = Coroutine.DEFAULT,
book: Book,
canReName: Boolean = true,
): Book {
book.type = bookSource.bookSourceType
@ -145,18 +145,18 @@ class WebBook(val bookSource: BookSource) {
* 目录
*/
fun getChapterList(
scope: CoroutineScope,
book: Book,
scope: CoroutineScope = Coroutine.DEFAULT,
context: CoroutineContext = Dispatchers.IO
): Coroutine<List<BookChapter>> {
return Coroutine.async(scope, context) {
getChapterListAwait(book, scope)
getChapterListAwait(scope, book)
}
}
suspend fun getChapterListAwait(
scope: CoroutineScope = Coroutine.DEFAULT,
book: Book,
scope: CoroutineScope = Coroutine.DEFAULT
): List<BookChapter> {
book.type = bookSource.bookSourceType
return if (book.bookUrl == book.tocUrl && !book.tocHtml.isNullOrEmpty()) {
@ -176,22 +176,22 @@ class WebBook(val bookSource: BookSource) {
* 章节内容
*/
fun getContent(
scope: CoroutineScope,
book: Book,
bookChapter: BookChapter,
nextChapterUrl: String? = null,
scope: CoroutineScope = Coroutine.DEFAULT,
context: CoroutineContext = Dispatchers.IO
): Coroutine<String> {
return Coroutine.async(scope, context) {
getContentAwait(book, bookChapter, nextChapterUrl, scope)
getContentAwait(scope, book, bookChapter, nextChapterUrl)
}
}
suspend fun getContentAwait(
scope: CoroutineScope,
book: Book,
bookChapter: BookChapter,
nextChapterUrl: String? = null,
scope: CoroutineScope = Coroutine.DEFAULT
): String {
if (bookSource.getContentRule().content.isNullOrEmpty()) {
Debug.log(sourceUrl, "⇒正文规则为空,使用章节链接:${bookChapter.url}")

@ -270,7 +270,7 @@ class AudioPlayService : BaseService(),
val book = AudioPlay.book
val webBook = AudioPlay.webBook
if (book != null && webBook != null) {
webBook.getContent(book, chapter, scope = this@AudioPlayService)
webBook.getContent(this@AudioPlayService, book, chapter)
.onSuccess { content ->
if (content.isEmpty()) {
withContext(Main) {

@ -184,12 +184,8 @@ class CacheBookService : BaseService() {
return@async
}
if (!BookHelp.hasContent(book, bookChapter)) {
webBook.getContent(
book,
bookChapter,
scope = this,
context = searchPool
).timeout(60000L)
webBook.getContent(this, book, bookChapter, context = searchPool)
.timeout(60000L)
.onError {
synchronized(this) {
downloadingList.remove(bookChapter.url)

@ -10,6 +10,7 @@ import io.legado.app.data.entities.BookChapter
import io.legado.app.model.webBook.WebBook
import io.legado.app.service.CacheBookService
import io.legado.app.utils.msg
import kotlinx.coroutines.CoroutineScope
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.CopyOnWriteArraySet
@ -61,6 +62,7 @@ object CacheBook {
}
fun download(
scope: CoroutineScope,
webBook: WebBook,
book: Book,
chapter: BookChapter,
@ -73,7 +75,7 @@ object CacheBook {
downloadMap[book.bookUrl] = CopyOnWriteArraySet()
}
downloadMap[book.bookUrl]?.add(chapter.index)
webBook.getContent(book, chapter)
webBook.getContent(scope, book, chapter)
.onSuccess { content ->
if (ReadBook.book?.bookUrl == book.bookUrl) {
ReadBook.contentLoadFinish(

@ -50,7 +50,7 @@ class CheckSource(val source: BookSource) {
): Coroutine<*> {
val webBook = WebBook(source)
return webBook
.searchBook(keyword, scope = scope, context = context)
.searchBook(scope, keyword, context = context)
.timeout(60000L)
.onError(Dispatchers.IO) {
source.addGroup("失效")

@ -282,7 +282,7 @@ object ReadBook {
val book = book
val webBook = webBook
if (book != null && webBook != null) {
CacheBook.download(webBook, book, chapter)
CacheBook.download(Coroutine.DEFAULT, webBook, book, chapter)
} else if (book != null) {
contentLoadFinish(
book, chapter, "没有书源", resetPageOffset = resetPageOffset

@ -53,7 +53,7 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application)
changeDruChapterIndex: ((chapters: List<BookChapter>) -> Unit)? = null
) {
execute {
AudioPlay.webBook?.getBookInfo(book, this)
AudioPlay.webBook?.getBookInfo(this, book)
?.onSuccess {
loadChapterList(book, changeDruChapterIndex)
}
@ -65,7 +65,7 @@ class AudioPlayViewModel(application: Application) : BaseViewModel(application)
changeDruChapterIndex: ((chapters: List<BookChapter>) -> Unit)? = null
) {
execute {
AudioPlay.webBook?.getChapterList(book, this)
AudioPlay.webBook?.getChapterList(this, book)
?.onSuccess(Dispatchers.IO) { cList ->
if (cList.isNotEmpty()) {
if (changeDruChapterIndex == null) {

@ -98,7 +98,7 @@ class ChangeCoverViewModel(application: Application) : BaseViewModel(application
searchIndex++
val source = bookSourceList[searchIndex]
val task = WebBook(source)
.searchBook(name, scope = this, context = searchPool!!)
.searchBook(this, name, context = searchPool!!)
.timeout(60000L)
.onSuccess(Dispatchers.IO) {
if (it.isNotEmpty()) {

@ -123,7 +123,7 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio
val source = bookSourceList[searchIndex]
val webBook = WebBook(source)
val task = webBook
.searchBook(name, scope = this, context = searchPool!!)
.searchBook(this, name, context = searchPool!!)
.timeout(60000L)
.onSuccess(IO) {
it.forEach { searchBook ->
@ -159,7 +159,7 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio
}
private fun loadBookInfo(webBook: WebBook, book: Book) {
webBook.getBookInfo(book, this)
webBook.getBookInfo(this, book)
.onSuccess {
if (context.getPrefBoolean(PreferKey.changeSourceLoadToc)) {
loadBookToc(webBook, book)
@ -175,7 +175,7 @@ class ChangeSourceViewModel(application: Application) : BaseViewModel(applicatio
}
private fun loadBookToc(webBook: WebBook, book: Book) {
webBook.getChapterList(book, this)
webBook.getChapterList(this, book)
.onSuccess(IO) { chapters ->
if (chapters.isNotEmpty()) {
book.latestChapterTitle = chapters.last().title

@ -34,7 +34,7 @@ class ExploreShowViewModel(application: Application) : BaseViewModel(application
val source = bookSource
val url = exploreUrl
if (source != null && url != null) {
WebBook(source).exploreBook(url, page, this)
WebBook(source).exploreBook(this, url, page)
.timeout(30000L)
.onSuccess(IO) { searchBooks ->
booksData.postValue(searchBooks)

@ -57,7 +57,7 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
loadChapter(book, changeDruChapterIndex)
} else {
App.db.bookSourceDao.getBookSource(book.origin)?.let { bookSource ->
WebBook(bookSource).getBookInfo(book, this, canReName = canReName)
WebBook(bookSource).getBookInfo(this, book, canReName = canReName)
.onSuccess(IO) {
bookData.postValue(book)
if (inBookshelf) {
@ -88,7 +88,7 @@ class BookInfoViewModel(application: Application) : BaseViewModel(application) {
}
} else {
App.db.bookSourceDao.getBookSource(book.origin)?.let { bookSource ->
WebBook(bookSource).getChapterList(book, this)
WebBook(bookSource).getChapterList(this, book)
.onSuccess(IO) {
if (it.isNotEmpty()) {
if (inBookshelf) {

@ -109,7 +109,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
if (book.isLocalBook()) {
loadChapterList(book, changeDruChapterIndex)
} else {
ReadBook.webBook?.getBookInfo(book, this, canReName = false)
ReadBook.webBook?.getBookInfo(this, book, canReName = false)
?.onSuccess {
loadChapterList(book, changeDruChapterIndex)
}
@ -138,7 +138,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
ReadBook.upMsg("LoadTocError:${it.localizedMessage}")
}
} else {
ReadBook.webBook?.getChapterList(book, this)
ReadBook.webBook?.getChapterList(this, book)
?.onSuccess(IO) { cList ->
if (cList.isNotEmpty()) {
if (changeDruChapterIndex == null) {
@ -215,8 +215,7 @@ class ReadBookViewModel(application: Application) : BaseViewModel(application) {
execute {
App.db.bookSourceDao.allTextEnabled.forEach { source ->
try {
WebBook(source)
.searchBookAwait(this, name)
WebBook(source).searchBookAwait(this, name)
.getOrNull(0)?.let {
if (it.name == name && (it.author == author || author == "")) {
val book = it.toBook()

@ -28,11 +28,14 @@ class BookSourceDebugModel(application: Application) : BaseViewModel(application
}
fun startDebug(key: String, start: (() -> Unit)? = null, error: (() -> Unit)? = null) {
webBook?.let {
execute {
Debug.callback = this@BookSourceDebugModel
Debug.startDebug(this, webBook!!, key)
}.onStart {
start?.invoke()
Debug.callback = this
Debug.startDebug(it, key)
} ?: error?.invoke()
}.onError {
error?.invoke()
}
}
override fun printLog(state: Int, msg: String) {

@ -75,7 +75,7 @@ class MainViewModel(application: Application) : BaseViewModel(application) {
}
App.db.bookSourceDao.getBookSource(book.origin)?.let { bookSource ->
val webBook = WebBook(bookSource)
webBook.getChapterList(book, context = upTocPool)
webBook.getChapterList(this, book, context = upTocPool)
.timeout(300000)
.onSuccess(IO) {
App.db.bookDao.update(book)
@ -115,7 +115,7 @@ class MainViewModel(application: Application) : BaseViewModel(application) {
var addToCache = false
while (!addToCache) {
if (CacheBook.downloadCount() < 5) {
CacheBook.download(webBook, book, chapter)
CacheBook.download(this, webBook, book, chapter)
addToCache = true
} else {
delay(1000)

@ -43,7 +43,7 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application)
origin = bookSource.bookSourceUrl,
originName = bookSource.bookSourceName
)
WebBook(bookSource).getBookInfo(book, this)
WebBook(bookSource).getBookInfo(this, book)
.onSuccess(IO) {
it.order = App.db.bookDao.maxOrder + 1
App.db.bookDao.insert(it)
@ -71,13 +71,6 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application)
val bookMap = hashMapOf<String, String?>()
bookMap["name"] = it.name
bookMap["author"] = it.author
bookMap["bookUrl"] = it.bookUrl
bookMap["coverUrl"] = it.coverUrl
bookMap["tocUrl"] = it.tocUrl
bookMap["kind"] = it.kind
bookMap["intro"] = it.getDisplayIntro()
bookMap["origin"] = it.origin
bookMap["originName"] = it.originName
exportList.add(bookMap)
}
GSON.toJson(exportList)
@ -96,23 +89,20 @@ class BookshelfViewModel(application: Application) : BaseViewModel(application)
}
}
text.isJsonArray() -> {
val bookSources = App.db.bookSourceDao.allEnabled
GSON.fromJsonArray<Map<String, String?>>(text)?.forEach {
val book = Book(
bookUrl = it["bookUrl"] ?: "",
name = it["name"] ?: "",
author = it["author"] ?: "",
coverUrl = it["coverUrl"],
tocUrl = it["tocUrl"] ?: "",
kind = it["kind"],
intro = it["intro"] ?: "",
origin = it["origin"] ?: "",
originName = it["originName"] ?: ""
)
if (groupId > 0) {
book.group = groupId
}
if (App.db.bookDao.getBook(book.name, book.author) == null) {
App.db.bookDao.insert(book)
val name = it["name"] ?: ""
val author = it["author"] ?: ""
bookSources.forEach { bookSource ->
runCatching {
val webBook = WebBook(bookSource)
val searchBooks = webBook.searchBookAwait(this, name)
val searchBook = searchBooks.firstOrNull()
if (searchBook != null && searchBook.name == name && searchBook.author == author) {
val book = webBook.getBookInfoAwait(this, searchBook.toBook())
App.db.bookDao.insert(book)
}
}
}
}
}

@ -57,7 +57,7 @@ class SourceDebugWebSocket(handshakeRequest: NanoHTTPD.IHTTPSession) :
}
App.db.bookSourceDao.getBookSource(tag)?.let {
Debug.callback = this
Debug.startDebug(WebBook(it), key)
Debug.startDebug(this, WebBook(it), key)
}
}
}

Loading…
Cancel
Save