pull/464/head
Robot 4 years ago
commit c56485e8dc
  1. 11
      app/src/main/java/io/legado/app/data/AppDatabase.kt
  2. 9
      app/src/main/java/io/legado/app/data/entities/BookChapter.kt
  3. 26
      app/src/main/java/io/legado/app/model/webBook/BookChapterList.kt
  4. 88
      app/src/main/java/io/legado/app/model/webBook/WebBook.kt
  5. 2
      app/src/main/java/io/legado/app/ui/book/read/page/provider/ChapterProvider.kt
  6. 7
      app/src/main/java/io/legado/app/utils/NetworkUtils.kt

@ -18,7 +18,7 @@ import java.util.*
ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class, ReplaceRule::class, SearchBook::class, SearchKeyword::class, Cookie::class,
RssSource::class, Bookmark::class, RssArticle::class, RssReadRecord::class, RssSource::class, Bookmark::class, RssArticle::class, RssReadRecord::class,
RssStar::class, TxtTocRule::class, ReadRecord::class, HttpTTS::class], RssStar::class, TxtTocRule::class, ReadRecord::class, HttpTTS::class],
version = 22, version = 23,
exportSchema = true exportSchema = true
) )
abstract class AppDatabase : RoomDatabase() { abstract class AppDatabase : RoomDatabase() {
@ -57,7 +57,8 @@ abstract class AppDatabase : RoomDatabase() {
migration_18_19, migration_18_19,
migration_19_20, migration_19_20,
migration_20_21, migration_20_21,
migration_21_22 migration_21_22,
migration_22_23
) )
.allowMainThreadQueries() .allowMainThreadQueries()
.addCallback(dbCallback) .addCallback(dbCallback)
@ -194,6 +195,12 @@ abstract class AppDatabase : RoomDatabase() {
database.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS `index_books_name_author` ON `books` (`name`, `author`) ") database.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS `index_books_name_author` ON `books` (`name`, `author`) ")
} }
} }
private val migration_22_23 = object : Migration(22, 23) {
override fun migrate(database: SupportSQLiteDatabase) {
database.execSQL("ALTER TABLE chapters ADD baseUrl TEXT NOT NULL DEFAULT ''")
}
}
} }
} }

@ -6,6 +6,7 @@ import androidx.room.ForeignKey
import androidx.room.Ignore import androidx.room.Ignore
import androidx.room.Index import androidx.room.Index
import io.legado.app.utils.GSON import io.legado.app.utils.GSON
import io.legado.app.utils.NetworkUtils
import io.legado.app.utils.fromJsonObject import io.legado.app.utils.fromJsonObject
import kotlinx.android.parcel.IgnoredOnParcel import kotlinx.android.parcel.IgnoredOnParcel
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
@ -26,13 +27,14 @@ import kotlinx.android.parcel.Parcelize
) // 删除书籍时自动删除章节 ) // 删除书籍时自动删除章节
data class BookChapter( data class BookChapter(
var url: String = "", // 章节地址 var url: String = "", // 章节地址
var title: String = "", // 章节标题 var title: String = "", // 章节标题
var baseUrl: String = "", //用来拼接相对url
var bookUrl: String = "", // 书籍地址 var bookUrl: String = "", // 书籍地址
var index: Int = 0, // 章节序号 var index: Int = 0, // 章节序号
var resourceUrl: String? = null, // 音频真实URL var resourceUrl: String? = null, // 音频真实URL
var tag: String? = null, // var tag: String? = null, //
var start: Long? = null, // 章节起始位置 var start: Long? = null, // 章节起始位置
var end: Long? = null, // 章节终止位置 var end: Long? = null, // 章节终止位置
var variable: String? = null //变量 var variable: String? = null //变量
) : Parcelable { ) : Parcelable {
@ -57,5 +59,8 @@ data class BookChapter(
return false return false
} }
fun getAbsoluteURL(): String {
return NetworkUtils.getAbsoluteURL(baseUrl, url)!!
}
} }

@ -65,16 +65,16 @@ object BookChapterList {
headerMapF = bookSource.getHeaderMap() headerMapF = bookSource.getHeaderMap()
).getResponseAwait(bookSource.bookSourceUrl) ).getResponseAwait(bookSource.bookSourceUrl)
.body?.let { nextBody -> .body?.let { nextBody ->
chapterData = analyzeChapterList( chapterData = analyzeChapterList(
book, nextUrl, nextBody, tocRule, listRule, bookSource book, nextUrl, nextBody, tocRule, listRule, bookSource
) )
nextUrl = if (chapterData.nextUrl.isNotEmpty()) { nextUrl = if (chapterData.nextUrl.isNotEmpty()) {
chapterData.nextUrl[0] chapterData.nextUrl[0]
} else "" } else ""
chapterData.chapterList?.let { chapterData.chapterList?.let {
chapterList.addAll(it) chapterList.addAll(it)
}
} }
}
} }
Debug.log(bookSource.bookSourceUrl, "◇目录总页数:${nextUrlList.size}") Debug.log(bookSource.bookSourceUrl, "◇目录总页数:${nextUrlList.size}")
block.resume(finish(book, chapterList, reverse)) block.resume(finish(book, chapterList, reverse))
@ -241,13 +241,15 @@ object BookChapterList {
var isVip: String? var isVip: String?
for (item in elements) { for (item in elements) {
analyzeRule.setContent(item) analyzeRule.setContent(item)
val bookChapter = BookChapter(bookUrl = book.bookUrl) val bookChapter = BookChapter(bookUrl = book.bookUrl, baseUrl = baseUrl)
analyzeRule.chapter = bookChapter analyzeRule.chapter = bookChapter
bookChapter.title = analyzeRule.getString(nameRule) bookChapter.title = analyzeRule.getString(nameRule)
bookChapter.url = analyzeRule.getString(urlRule) bookChapter.url = analyzeRule.getString(urlRule)
bookChapter.tag = analyzeRule.getString(update) bookChapter.tag = analyzeRule.getString(update)
isVip = analyzeRule.getString(vipRule) isVip = analyzeRule.getString(vipRule)
if (bookChapter.url.isEmpty()) bookChapter.url = baseUrl if (bookChapter.url.isEmpty()) {
bookChapter.url = baseUrl
}
if (bookChapter.title.isNotEmpty()) { if (bookChapter.title.isNotEmpty()) {
if (isVip.isNotEmpty() && isVip != "null" && isVip != "false" && isVip != "0") { if (isVip.isNotEmpty() && isVip != "null" && isVip != "false" && isVip != "0") {
bookChapter.title = "\uD83D\uDD12" + bookChapter.title bookChapter.title = "\uD83D\uDD12" + bookChapter.title
@ -257,7 +259,7 @@ object BookChapterList {
} }
Debug.log(bookSource.bookSourceUrl, "${chapterList[0].title}", log) Debug.log(bookSource.bookSourceUrl, "${chapterList[0].title}", log)
Debug.log(bookSource.bookSourceUrl, "┌获取首章链接", log) Debug.log(bookSource.bookSourceUrl, "┌获取首章链接", log)
Debug.log(bookSource.bookSourceUrl, "${chapterList[0].url}", log) Debug.log(bookSource.bookSourceUrl, "${chapterList[0].getAbsoluteURL()}", log)
Debug.log(bookSource.bookSourceUrl, "┌获取首章信息", log) Debug.log(bookSource.bookSourceUrl, "┌获取首章信息", log)
Debug.log(bookSource.bookSourceUrl, "${chapterList[0].tag}", log) Debug.log(bookSource.bookSourceUrl, "${chapterList[0].tag}", log)
} }

@ -128,18 +128,24 @@ class WebBook(val bookSource: BookSource) {
): Coroutine<List<BookChapter>> { ): Coroutine<List<BookChapter>> {
return Coroutine.async(scope, context) { return Coroutine.async(scope, context) {
book.type = bookSource.bookSourceType book.type = bookSource.bookSourceType
val body = if (book.bookUrl == book.tocUrl && !book.tocHtml.isNullOrEmpty()) {
if (book.bookUrl == book.tocUrl && !book.tocHtml.isNullOrEmpty()) { BookChapterList.analyzeChapterList(
book.tocHtml this,
} else { book,
AnalyzeUrl( book.tocHtml,
book = book, bookSource,
ruleUrl = book.tocUrl, book.tocUrl
baseUrl = book.bookUrl, )
headerMapF = bookSource.getHeaderMap() } else {
).getResponseAwait(bookSource.bookSourceUrl).body val res = AnalyzeUrl(
} book = book,
BookChapterList.analyzeChapterList(this, book, body, bookSource, book.tocUrl) ruleUrl = book.tocUrl,
baseUrl = book.bookUrl,
headerMapF = bookSource.getHeaderMap()
).getResponseAwait(bookSource.bookSourceUrl)
BookChapterList.analyzeChapterList(this, book, res.body, bookSource, res.url)
}
} }
} }
@ -173,31 +179,37 @@ class WebBook(val bookSource: BookSource) {
Debug.log(sourceUrl, "⇒正文规则为空,使用章节链接:${bookChapter.url}") Debug.log(sourceUrl, "⇒正文规则为空,使用章节链接:${bookChapter.url}")
return bookChapter.url return bookChapter.url
} }
val body = return if (bookChapter.url == book.bookUrl && !book.tocHtml.isNullOrEmpty()) {
if (bookChapter.url == book.bookUrl && !book.tocHtml.isNullOrEmpty()) { BookContent.analyzeContent(
book.tocHtml scope,
} else { book.tocHtml,
val analyzeUrl = AnalyzeUrl( book,
ruleUrl = bookChapter.url, bookChapter,
baseUrl = book.tocUrl, bookSource,
headerMapF = bookSource.getHeaderMap(), bookChapter.getAbsoluteURL(),
book = book, nextChapterUrl
chapter = bookChapter )
) } else {
analyzeUrl.getResponseAwait( val res = AnalyzeUrl(
bookSource.bookSourceUrl, ruleUrl = bookChapter.getAbsoluteURL(),
jsStr = bookSource.getContentRule().webJs, baseUrl = book.tocUrl,
sourceRegex = bookSource.getContentRule().sourceRegex headerMapF = bookSource.getHeaderMap(),
).body book = book,
} chapter = bookChapter
return BookContent.analyzeContent( ).getResponseAwait(
scope, bookSource.bookSourceUrl,
body, jsStr = bookSource.getContentRule().webJs,
book, sourceRegex = bookSource.getContentRule().sourceRegex
bookChapter, )
bookSource, BookContent.analyzeContent(
bookChapter.url, scope,
nextChapterUrl res.body,
) book,
bookChapter,
bookSource,
res.url,
nextChapterUrl
)
}
} }
} }

@ -102,7 +102,7 @@ object ChapterProvider {
return TextChapter( return TextChapter(
bookChapter.index, bookChapter.index,
bookChapter.title, bookChapter.title,
bookChapter.url, bookChapter.getAbsoluteURL(),
textPages, textPages,
pageLines, pageLines,
pageLengths, pageLengths,

@ -11,9 +11,10 @@ import java.util.regex.Pattern
@Suppress("unused", "MemberVisibilityCanBePrivate") @Suppress("unused", "MemberVisibilityCanBePrivate")
object NetworkUtils { object NetworkUtils {
fun getUrl(response: Response<*>): String { fun getUrl(response: Response<*>): String {
val networkResponse = response.raw().networkResponse() response.raw().networkResponse()?.let {
return networkResponse?.request()?.url()?.toString() return it.request().url().toString()
?: response.raw().request().url().toString() }
return response.raw().request().url().toString()
} }
private val notNeedEncoding: BitSet by lazy { private val notNeedEncoding: BitSet by lazy {

Loading…
Cancel
Save