diff --git a/lib-multisrc/yuyu/src/eu/kanade/tachiyomi/multisrc/yuyu/YuYu.kt b/lib-multisrc/yuyu/src/eu/kanade/tachiyomi/multisrc/yuyu/YuYu.kt index 1e4c24c49..061d1cd2b 100644 --- a/lib-multisrc/yuyu/src/eu/kanade/tachiyomi/multisrc/yuyu/YuYu.kt +++ b/lib-multisrc/yuyu/src/eu/kanade/tachiyomi/multisrc/yuyu/YuYu.kt @@ -129,19 +129,22 @@ 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()) { - "em andamento" -> SManga.ONGOING - "completo" -> SManga.COMPLETED - "cancelado" -> SManga.CANCELLED - "hiato" -> SManga.ON_HIATUS - else -> SManga.UNKNOWN - } + status = it.toStatus() } - setUrlWithoutDomain(document.location()) } - private fun SManga.fetchMangaId(): String { - val document = client.newCall(mangaDetailsRequest(this)).execute().asJsoup() + protected fun String.toStatus(): Int { + return when (lowercase()) { + "em andamento" -> SManga.ONGOING + "completo" -> SManga.COMPLETED + "cancelado" -> SManga.CANCELLED + "hiato" -> SManga.ON_HIATUS + else -> SManga.UNKNOWN + } + } + + 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> { - val mangaId = manga.fetchMangaId() + val mangaId = getMangaId(manga) val chapters = mutableListOf() var page = 1 do { - val dto = fetchChapterListPage(mangaId, page++).parseAs() + val dto = fetchChapterListPage(mangaId, page++).parseAs>() 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(val chapters: T, private val remaining: Int) { fun hasNext() = remaining > 0 } diff --git a/src/pt/yushukemangas/build.gradle b/src/pt/yushukemangas/build.gradle index 415561c46..59ecd0676 100644 --- a/src/pt/yushukemangas/build.gradle +++ b/src/pt/yushukemangas/build.gradle @@ -3,7 +3,7 @@ ext { extClass = '.YushukeMangas' themePkg = 'yuyu' baseUrl = 'https://new.yushukemangas.com' - overrideVersionCode = 6 + overrideVersionCode = 7 isNsfw = false } diff --git a/src/pt/yushukemangas/src/eu/kanade/tachiyomi/extension/pt/yushukemangas/ChapterDto.kt b/src/pt/yushukemangas/src/eu/kanade/tachiyomi/extension/pt/yushukemangas/ChapterDto.kt new file mode 100644 index 000000000..93bfa0abf --- /dev/null +++ b/src/pt/yushukemangas/src/eu/kanade/tachiyomi/extension/pt/yushukemangas/ChapterDto.kt @@ -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" + } +} diff --git a/src/pt/yushukemangas/src/eu/kanade/tachiyomi/extension/pt/yushukemangas/YushukeMangas.kt b/src/pt/yushukemangas/src/eu/kanade/tachiyomi/extension/pt/yushukemangas/YushukeMangas.kt index f1582e5ef..9b1d8f7f2 100644 --- a/src/pt/yushukemangas/src/eu/kanade/tachiyomi/extension/pt/yushukemangas/YushukeMangas.kt +++ b/src/pt/yushukemangas/src/eu/kanade/tachiyomi/extension/pt/yushukemangas/YushukeMangas.kt @@ -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> { + if (manga.isOldEntry()) { + return super.fetchChapterList(manga) + } + + val mangaId = getMangaId(manga).takeIf(String::isNotBlank) + ?: throw Exception("Manga ID não encontrado") + + val chapters = mutableListOf() + var page = 1 + val url = manga.url.replace("/$mangaId", "") + do { + val chaptersDto = fetchChapterListPage(mangaId, page++).parseAs>>() + 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() + } }