YushukeMangas: Fix manga id not found (#9279)

Fix manga id not found
This commit is contained in:
Chopper 2025-06-18 10:59:58 -03:00 committed by Draff
parent 6af9f2d853
commit 67b795a5b8
Signed by: Draff
GPG Key ID: E8A89F3211677653
4 changed files with 113 additions and 15 deletions

View File

@ -129,7 +129,12 @@ abstract class YuYu(
genre = details.select(".genre-tag").joinToString { it.text() }
description = details.selectFirst(".sinopse p")?.text()
details.selectFirst(".manga-meta > div")?.ownText()?.let {
status = when (it.lowercase()) {
status = it.toStatus()
}
}
protected fun String.toStatus(): Int {
return when (lowercase()) {
"em andamento" -> SManga.ONGOING
"completo" -> SManga.COMPLETED
"cancelado" -> SManga.CANCELLED
@ -137,11 +142,9 @@ abstract class YuYu(
else -> SManga.UNKNOWN
}
}
setUrlWithoutDomain(document.location())
}
private fun SManga.fetchMangaId(): String {
val document = client.newCall(mangaDetailsRequest(this)).execute().asJsoup()
protected open fun getMangaId(manga: SManga): String {
val document = client.newCall(mangaDetailsRequest(manga)).execute().asJsoup()
return document.select("script")
.map(Element::data)
.firstOrNull(MANGA_ID_REGEX::containsMatchIn)
@ -159,11 +162,11 @@ abstract class YuYu(
}
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
val mangaId = manga.fetchMangaId()
val mangaId = getMangaId(manga)
val chapters = mutableListOf<SChapter>()
var page = 1
do {
val dto = fetchChapterListPage(mangaId, page++).parseAs<ChaptersDto>()
val dto = fetchChapterListPage(mangaId, page++).parseAs<ChaptersDto<String>>()
val document = Jsoup.parseBodyFragment(dto.chapters, baseUrl)
chapters += document.select(chapterListSelector()).map(::chapterFromElement)
} while (dto.hasNext())
@ -194,7 +197,7 @@ abstract class YuYu(
// ============================== Utilities ===========================
@Serializable
class ChaptersDto(val chapters: String, private val remaining: Int) {
class ChaptersDto<T>(val chapters: T, private val remaining: Int) {
fun hasNext() = remaining > 0
}

View File

@ -3,7 +3,7 @@ ext {
extClass = '.YushukeMangas'
themePkg = 'yuyu'
baseUrl = 'https://new.yushukemangas.com'
overrideVersionCode = 6
overrideVersionCode = 7
isNsfw = false
}

View File

@ -0,0 +1,25 @@
package eu.kanade.tachiyomi.extension.pt.yushukemangas
import eu.kanade.tachiyomi.extension.pt.yushukemangas.YushukeMangas.Companion.dateFormat
import eu.kanade.tachiyomi.source.model.SChapter
import keiyoushi.utils.tryParse
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Serializable
class ChapterDto(
val id: Int,
@SerialName("numero")
val number: Float,
@SerialName("titulo")
val name: String,
@SerialName("data_publicacao")
val date: String,
) {
fun toSChapter(chapterUrl: String) = SChapter.create().apply {
name = this@ChapterDto.name
chapter_number = number
date_upload = dateFormat.tryParse(date)
url = "$chapterUrl/capitulo/$id"
}
}

View File

@ -1,7 +1,17 @@
package eu.kanade.tachiyomi.extension.pt.yushukemangas
import eu.kanade.tachiyomi.multisrc.yuyu.YuYu
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import keiyoushi.utils.parseAs
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Response
import org.jsoup.nodes.Document
import rx.Observable
import java.text.SimpleDateFormat
import java.util.Locale
class YushukeMangas : YuYu(
"Yushuke Mangas",
@ -10,8 +20,68 @@ class YushukeMangas : YuYu(
) {
override val client = super.client.newBuilder()
.rateLimit(1, 2)
.rateLimit(2)
.build()
override val versionId = 2
override fun mangaDetailsParse(document: Document): SManga {
if (document.location().contains(MANGA_URL_ID_REGEX).not()) {
return super.mangaDetailsParse(document)
}
return SManga.create().apply {
title = document.selectFirst("h1")!!.text()
thumbnail_url = document.selectFirst(".detalhe-capa-img")?.absUrl("src")
genre = document.select(".detalhe-tags-chips span").joinToString { it.text() }
description = document.selectFirst(".detalhe-sinopse")?.text()
document.selectFirst(".detalhe-chip.status")?.ownText()?.let {
status = it.toStatus()
}
}
}
override fun getMangaId(manga: SManga): String {
return when {
manga.isOldEntry() -> super.getMangaId(manga)
else -> MANGA_URL_ID_REGEX.find(manga.url)?.groups?.get(1)?.value ?: ""
}
}
private fun SManga.isOldEntry(): Boolean = MANGA_URL_ID_REGEX.containsMatchIn(url).not()
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
if (manga.isOldEntry()) {
return super.fetchChapterList(manga)
}
val mangaId = getMangaId(manga).takeIf(String::isNotBlank)
?: throw Exception("Manga ID não encontrado")
val chapters = mutableListOf<SChapter>()
var page = 1
val url = manga.url.replace("/$mangaId", "")
do {
val chaptersDto = fetchChapterListPage(mangaId, page++).parseAs<ChaptersDto<List<ChapterDto>>>()
chapters += chaptersDto.chapters.map { it.toSChapter(url) }
} while (chaptersDto.hasNext())
return Observable.just(chapters)
}
private fun fetchChapterListPage(mangaId: String, page: Int): Response {
val url = "$baseUrl/ajax/get_chapters.php".toHttpUrl().newBuilder()
.addQueryParameter("manga_id", mangaId)
.addQueryParameter("page", page.toString())
.build()
return client
.newCall(GET(url, headers))
.execute()
}
companion object {
val dateFormat = SimpleDateFormat("yyyy-MM-dd", Locale.ROOT)
private val MANGA_URL_ID_REGEX = """\/obra\/(\d+)\/.+$""".toRegex()
}
}