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:
stevenyomi 2022-09-15 00:12:02 +08:00 committed by GitHub
parent b2f0bc043e
commit 609af00c7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 31 deletions

View File

@ -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
} }

View File

@ -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.")

View File

@ -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") }
}
} }
} }