BoyLove: fix page list parsing and balance server load (#13463)
* BoyLove: fix page list parsing and balance server load * revert chapter list part
This commit is contained in:
parent
b2f0bc043e
commit
609af00c7b
|
@ -6,7 +6,7 @@ ext {
|
||||||
extName = 'BoyLove'
|
extName = 'BoyLove'
|
||||||
pkgNameSuffix = 'zh.boylove'
|
pkgNameSuffix = 'zh.boylove'
|
||||||
extClass = '.BoyLove'
|
extClass = '.BoyLove'
|
||||||
extVersionCode = 2
|
extVersionCode = 3
|
||||||
isNsfw = true
|
isNsfw = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,12 +21,14 @@ import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.json.decodeFromStream
|
import kotlinx.serialization.json.decodeFromStream
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
|
import org.jsoup.select.Evaluator
|
||||||
import rx.Observable
|
import rx.Observable
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
|
// Uses MACCMS http://www.maccms.la/
|
||||||
// 支持站点,不要添加屏蔽广告选项,何况广告本来就不多
|
// 支持站点,不要添加屏蔽广告选项,何况广告本来就不多
|
||||||
class BoyLove : HttpSource(), ConfigurableSource {
|
class BoyLove : HttpSource(), ConfigurableSource {
|
||||||
override val name = "香香腐宅"
|
override val name = "香香腐宅"
|
||||||
|
@ -93,12 +95,30 @@ class BoyLove : HttpSource(), ConfigurableSource {
|
||||||
override fun chapterListParse(response: Response): List<SChapter> =
|
override fun chapterListParse(response: Response): List<SChapter> =
|
||||||
response.parseAs<ListPageDto<ChapterDto>>().list.map { it.toSChapter() }
|
response.parseAs<ListPageDto<ChapterDto>>().list.map { it.toSChapter() }
|
||||||
|
|
||||||
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> =
|
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
|
||||||
chapter.url.substringAfter(':').ifEmpty {
|
val chapterUrl = chapter.url
|
||||||
|
val index = chapterUrl.indexOf(':') // old URL format
|
||||||
|
if (index == -1) return fetchPageList(chapterUrl)
|
||||||
|
return chapterUrl.substring(index + 1).ifEmpty {
|
||||||
return Observable.just(emptyList())
|
return Observable.just(emptyList())
|
||||||
}.split(',').mapIndexed { i, url ->
|
}.split(',').mapIndexed { i, url ->
|
||||||
Page(i, imageUrl = url.toImageUrl())
|
Page(i, imageUrl = url.toImageUrl())
|
||||||
}.let { Observable.just(it) }
|
}.let { Observable.just(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fetchPageList(chapterUrl: String): Observable<List<Page>> =
|
||||||
|
client.newCall(GET(baseUrl + chapterUrl, headers)).asObservableSuccess().map { response ->
|
||||||
|
val root = response.asJsoup().selectFirst(Evaluator.Tag("section"))
|
||||||
|
val images = root.select(Evaluator.Class("reader-cartoon-image"))
|
||||||
|
val urlList = if (images.isEmpty()) {
|
||||||
|
root.select(Evaluator.Tag("img")).map { it.attr("src").trim().toImageUrl() }
|
||||||
|
} else {
|
||||||
|
images.map { it.child(0) }
|
||||||
|
.filter { it.attr("src").endsWith("load.png") }
|
||||||
|
.map { it.attr("data-original").trim().toImageUrl() }
|
||||||
|
}
|
||||||
|
urlList.mapIndexed { index, imageUrl -> Page(index, imageUrl = imageUrl) }
|
||||||
|
}
|
||||||
|
|
||||||
override fun pageListParse(response: Response) = throw UnsupportedOperationException("Not used.")
|
override fun pageListParse(response: Response) = throw UnsupportedOperationException("Not used.")
|
||||||
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException("Not used.")
|
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException("Not used.")
|
||||||
|
|
|
@ -3,28 +3,33 @@ package eu.kanade.tachiyomi.extension.zh.boylove
|
||||||
import eu.kanade.tachiyomi.source.model.SChapter
|
import eu.kanade.tachiyomi.source.model.SChapter
|
||||||
import eu.kanade.tachiyomi.source.model.SManga
|
import eu.kanade.tachiyomi.source.model.SManga
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import org.jsoup.Jsoup
|
import kotlinx.serialization.json.JsonPrimitive
|
||||||
import org.jsoup.select.Evaluator
|
import kotlinx.serialization.json.long
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
|
import java.util.Date
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
internal const val IMAGE_HOST = "https://blcnimghost1.cc" // 也有 2
|
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class MangaDto(
|
class MangaDto(
|
||||||
val id: Int,
|
val id: Int,
|
||||||
val title: String,
|
private val title: String,
|
||||||
val image: String,
|
private val update_time: JsonPrimitive,
|
||||||
val auther: String,
|
private val image: String,
|
||||||
val desc: String,
|
private val auther: String,
|
||||||
val mhstatus: Int,
|
private val desc: String,
|
||||||
val keyword: String,
|
private val mhstatus: Int,
|
||||||
|
private val keyword: String,
|
||||||
) {
|
) {
|
||||||
fun toSManga() = SManga.create().apply {
|
fun toSManga() = SManga.create().apply {
|
||||||
url = id.toString()
|
url = id.toString()
|
||||||
title = this@MangaDto.title
|
title = this@MangaDto.title
|
||||||
author = auther
|
author = auther
|
||||||
description = desc
|
val updateTime = if (update_time.isString) {
|
||||||
|
update_time.content
|
||||||
|
} else {
|
||||||
|
dateFormat.format(Date(update_time.long * 1000))
|
||||||
|
}
|
||||||
|
description = "更新时间:$updateTime\n\n$desc"
|
||||||
genre = keyword.replace(",", ", ")
|
genre = keyword.replace(",", ", ")
|
||||||
status = when (mhstatus) {
|
status = when (mhstatus) {
|
||||||
0 -> SManga.ONGOING
|
0 -> SManga.ONGOING
|
||||||
|
@ -36,29 +41,22 @@ class MangaDto(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun String.toImageUrl() = if (startsWith("http")) this else "$IMAGE_HOST$this"
|
fun String.toImageUrl() =
|
||||||
|
if (startsWith("http")) {
|
||||||
|
this
|
||||||
|
} else {
|
||||||
|
val i = (hashCode() and 1) + 1 // 1 or 2
|
||||||
|
"https://blcnimghost$i.cc$this"
|
||||||
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class ChapterDto(
|
class ChapterDto(
|
||||||
val id: Int,
|
private val id: Int,
|
||||||
val title: String,
|
private val title: String,
|
||||||
val manhua_id: Int,
|
|
||||||
val update_time: String,
|
|
||||||
val content: String?,
|
|
||||||
val imagelist: String,
|
|
||||||
) {
|
) {
|
||||||
fun toSChapter() = SChapter.create().apply {
|
fun toSChapter() = SChapter.create().apply {
|
||||||
url = "$manhua_id/$id:${getImages()}"
|
url = "/home/book/capter/id/$id"
|
||||||
name = title.trim()
|
name = title.trim()
|
||||||
date_upload = dateFormat.parse(update_time)?.time ?: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getImages(): String {
|
|
||||||
return imagelist.ifEmpty {
|
|
||||||
if (content == null) return ""
|
|
||||||
Jsoup.parse(content).select(Evaluator.Tag("img"))
|
|
||||||
.joinToString(",") { it.attr("src") }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue