Delete BookChapterList.kt

pull/891/head
bushixuanqi 4 years ago committed by GitHub
parent bc81041c0f
commit 136386cbfc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 274
      app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt

@ -1,274 +0,0 @@
package io.legado.app.model.webBook
import android.text.TextUtils
import io.legado.app.R
import io.legado.app.data.entities.Book
import io.legado.app.data.entities.BookChapter
import io.legado.app.data.entities.BookSource
import io.legado.app.data.entities.rule.TocRule
import io.legado.app.help.coroutine.Coroutine
import io.legado.app.model.Debug
import io.legado.app.model.analyzeRule.AnalyzeRule
import io.legado.app.model.analyzeRule.AnalyzeUrl
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ensureActive
import kotlinx.coroutines.suspendCancellableCoroutine
import splitties.init.appCtx
import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException
object BookChapterList {
suspend fun analyzeChapterList(
scope: CoroutineScope,
book: Book,
body: String?,
bookSource: BookSource,
baseUrl: String,
redirectUrl: String
): List<BookChapter> = suspendCancellableCoroutine { block ->
kotlin.runCatching {
val chapterList = ArrayList<BookChapter>()
body ?: throw Exception(
appCtx.getString(R.string.error_get_web_content, baseUrl)
)
Debug.log(bookSource.bookSourceUrl, "≡获取成功:${baseUrl}")
val tocRule = bookSource.getTocRule()
val nextUrlList = arrayListOf(baseUrl)
var reverse = AnalyzeRule.userReverse
var listRule = tocRule.chapterList ?: ""
if (listRule.startsWith("-")) {
reverse = true
listRule = listRule.substring(1)
}
if (listRule.startsWith("+")) {
listRule = listRule.substring(1)
}
var chapterData =
analyzeChapterList(
scope, book, baseUrl, redirectUrl, body,
tocRule, listRule, bookSource, log = true
)
chapterData.chapterList?.let {
chapterList.addAll(it)
}
when (chapterData.nextUrl.size) {
0 -> {
block.resume(finish(book, chapterList, reverse))
}
1 -> {
Coroutine.async(scope = scope) {
var nextUrl = chapterData.nextUrl[0]
while (nextUrl.isNotEmpty() && !nextUrlList.contains(nextUrl)) {
nextUrlList.add(nextUrl)
AnalyzeUrl(
ruleUrl = nextUrl,
book = book,
headerMapF = bookSource.getHeaderMap()
).getStrResponse(bookSource.bookSourceUrl).body?.let { nextBody ->
chapterData = analyzeChapterList(
this, book, nextUrl, nextUrl,
nextBody, tocRule, listRule, bookSource
)
nextUrl = chapterData.nextUrl.firstOrNull() ?: ""
chapterData.chapterList?.let {
chapterList.addAll(it)
}
}
}
Debug.log(bookSource.bookSourceUrl, "◇目录总页数:${nextUrlList.size}")
block.resume(finish(book, chapterList, reverse))
}.onError {
block.resumeWithException(it)
}
}
else -> {
val chapterDataList = arrayListOf<ChapterData<String>>()
for (item in chapterData.nextUrl) {
if (!nextUrlList.contains(item)) {
val data = ChapterData(nextUrl = item)
chapterDataList.add(data)
nextUrlList.add(item)
}
}
Debug.log(bookSource.bookSourceUrl, "◇目录总页数:${nextUrlList.size}")
for (item in chapterDataList) {
downloadToc(
scope, item, book, bookSource,
tocRule, listRule, chapterList, chapterDataList,
{
block.resume(finish(book, chapterList, reverse))
}
) {
block.cancel(it)
}
}
}
}
}.onFailure {
block.cancel(it)
}
}
private fun downloadToc(
scope: CoroutineScope,
chapterData: ChapterData<String>,
book: Book,
bookSource: BookSource,
tocRule: TocRule,
listRule: String,
chapterList: ArrayList<BookChapter>,
chapterDataList: ArrayList<ChapterData<String>>,
onFinish: () -> Unit,
onError: (error: Throwable) -> Unit
) {
Coroutine.async(scope = scope) {
val nextBody = AnalyzeUrl(
ruleUrl = chapterData.nextUrl,
book = book,
headerMapF = bookSource.getHeaderMap()
).getStrResponse(bookSource.bookSourceUrl).body
?: throw Exception("${chapterData.nextUrl}, 下载失败")
val nextChapterData = analyzeChapterList(
this, book, chapterData.nextUrl, chapterData.nextUrl,
nextBody, tocRule, listRule, bookSource, false
)
synchronized(chapterDataList) {
val isFinished = addChapterListIsFinish(
chapterDataList,
chapterData,
nextChapterData.chapterList
)
if (isFinished) {
chapterDataList.forEach { item ->
item.chapterList?.let {
chapterList.addAll(it)
}
}
onFinish()
}
}
}.onError {
onError.invoke(it)
}
}
private fun addChapterListIsFinish(
chapterDataList: ArrayList<ChapterData<String>>,
chapterData: ChapterData<String>,
chapterList: List<BookChapter>?
): Boolean {
chapterData.chapterList = chapterList
chapterDataList.forEach {
if (it.chapterList == null) {
return false
}
}
return true
}
private fun finish(
book: Book,
chapterList: ArrayList<BookChapter>,
reverse: Boolean
): ArrayList<BookChapter> {
//去重
if (!reverse) {
chapterList.reverse()
}
val lh = LinkedHashSet(chapterList)
val list = ArrayList(lh)
list.reverse()
Debug.log(book.origin, "◇目录总数:${list.size}")
for ((index, item) in list.withIndex()) {
item.index = index
}
book.latestChapterTitle = list.last().title
book.durChapterTitle =
list.getOrNull(book.durChapterIndex)?.title ?: book.latestChapterTitle
if (book.totalChapterNum < list.size) {
book.lastCheckCount = list.size - book.totalChapterNum
book.latestChapterTime = System.currentTimeMillis()
}
book.totalChapterNum = list.size
return list
}
private fun analyzeChapterList(
scope: CoroutineScope,
book: Book,
baseUrl: String,
redirectUrl: String,
body: String,
tocRule: TocRule,
listRule: String,
bookSource: BookSource,
getNextUrl: Boolean = true,
log: Boolean = false
): ChapterData<List<String>> {
val analyzeRule = AnalyzeRule(book)
analyzeRule.setContent(body).setBaseUrl(baseUrl)
analyzeRule.setRedirectUrl(redirectUrl)
//获取目录列表
val chapterList = arrayListOf<BookChapter>()
Debug.log(bookSource.bookSourceUrl, "┌获取目录列表", log)
val elements = analyzeRule.getElements(listRule)
Debug.log(bookSource.bookSourceUrl, "└列表大小:${elements.size}", log)
//获取下一页链接
val nextUrlList = arrayListOf<String>()
val nextTocRule = tocRule.nextTocUrl
if (getNextUrl && !nextTocRule.isNullOrEmpty()) {
Debug.log(bookSource.bookSourceUrl, "┌获取目录下一页列表", log)
analyzeRule.getStringList(nextTocRule, true)?.let {
for (item in it) {
if (item != baseUrl) {
nextUrlList.add(item)
}
}
}
Debug.log(
bookSource.bookSourceUrl,
"" + TextUtils.join("\n", nextUrlList),
log
)
}
scope.ensureActive()
if (elements.isNotEmpty()) {
Debug.log(bookSource.bookSourceUrl, "┌解析目录列表", log)
val nameRule = analyzeRule.splitSourceRule(tocRule.chapterName)
val urlRule = analyzeRule.splitSourceRule(tocRule.chapterUrl)
val vipRule = analyzeRule.splitSourceRule(tocRule.isVip)
val update = analyzeRule.splitSourceRule(tocRule.updateTime)
var isVip: String?
for (item in elements) {
scope.ensureActive()
analyzeRule.setContent(item)
val bookChapter = BookChapter(bookUrl = book.bookUrl, baseUrl = baseUrl)
analyzeRule.chapter = bookChapter
bookChapter.title = analyzeRule.getString(nameRule)
bookChapter.url = analyzeRule.getString(urlRule)
bookChapter.tag = analyzeRule.getString(update)
isVip = analyzeRule.getString(vipRule)
if (bookChapter.url.isEmpty()) {
bookChapter.url = baseUrl
}
if (bookChapter.title.isNotEmpty()) {
if (isVip.isNotEmpty() && isVip != "null" && isVip != "false" && isVip != "0") {
bookChapter.title = "\uD83D\uDD12" + bookChapter.title
}
chapterList.add(bookChapter)
}
}
Debug.log(bookSource.bookSourceUrl, "└解析目录列表完成", log)
Debug.log(bookSource.bookSourceUrl, "┌首章名称", log)
Debug.log(bookSource.bookSourceUrl, "${chapterList[0].title}", log)
Debug.log(bookSource.bookSourceUrl, "┌首章链接", log)
Debug.log(bookSource.bookSourceUrl, "${chapterList[0].url}", log)
Debug.log(bookSource.bookSourceUrl, "┌首章信息", log)
Debug.log(bookSource.bookSourceUrl, "${chapterList[0].tag}", log)
}
return ChapterData(chapterList, nextUrlList)
}
}
Loading…
Cancel
Save