Fix ZeroTheme (#10078)

* Fix ZeroTheme

* Throws an exception when old entries are being processed

* Remove url prefix
This commit is contained in:
Chopper 2025-08-16 10:18:16 -03:00 committed by Draff
parent 9f1f449d96
commit 648bb3c295
Signed by: Draff
GPG Key ID: E8A89F3211677653
4 changed files with 49 additions and 7 deletions

View File

@ -2,4 +2,4 @@ plugins {
id("lib-multisrc") id("lib-multisrc")
} }
baseVersionCode = 1 baseVersionCode = 2

View File

@ -1,16 +1,19 @@
package eu.kanade.tachiyomi.multisrc.zerotheme package eu.kanade.tachiyomi.multisrc.zerotheme
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.interceptor.rateLimit
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import keiyoushi.utils.parseAs import keiyoushi.utils.parseAs
import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.nodes.Element
import java.io.IOException
abstract class ZeroTheme( abstract class ZeroTheme(
override val name: String, override val name: String,
@ -20,14 +23,25 @@ abstract class ZeroTheme(
override val supportsLatest: Boolean = true override val supportsLatest: Boolean = true
override val client = network.cloudflareClient.newBuilder() override val client = network.cloudflareClient
.rateLimit(2)
.build()
open val cdnUrl: String = "https://cdn.${baseUrl.substringAfterLast("/")}" open val cdnUrl: String = "https://cdn.${baseUrl.substringAfterLast("/")}"
open val imageLocation: String = "images" open val imageLocation: String = "images"
open val mangaSubString: String by lazy {
val response = client.newCall(GET(baseUrl, headers)).execute()
val script = response.asJsoup().select("script")
.map(Element::data)
.firstOrNull(MANGA_SUBSTRING_REGEX::containsMatchIn)
?: throw IOException("manga substring não foi localizado")
MANGA_SUBSTRING_REGEX.find(script)?.groups?.get(1)?.value
?: throw IOException("Não foi extrair a substring do manga")
}
open val chapterSubString: String = "chapter"
private val sourceLocation: String get() = "$cdnUrl/$imageLocation" private val sourceLocation: String get() = "$cdnUrl/$imageLocation"
// =========================== Popular ================================ // =========================== Popular ================================
@ -61,14 +75,30 @@ abstract class ZeroTheme(
// =========================== Details ================================= // =========================== Details =================================
override fun getMangaUrl(manga: SManga) = "$baseUrl/$mangaSubString/${manga.url.substringAfterLast("/")}"
override fun mangaDetailsRequest(manga: SManga): Request {
checkEntry(manga.url)
return GET(getMangaUrl(manga), headers)
}
override fun mangaDetailsParse(response: Response) = response.toDto<MangaDetailsDto>().toSManga(sourceLocation) override fun mangaDetailsParse(response: Response) = response.toDto<MangaDetailsDto>().toSManga(sourceLocation)
// =========================== Chapter ================================= // =========================== Chapter =================================
override fun getChapterUrl(chapter: SChapter) = "$baseUrl/$chapterSubString/${chapter.url.substringAfterLast("/")}"
override fun chapterListRequest(manga: SManga) = mangaDetailsRequest(manga)
override fun chapterListParse(response: Response) = response.toDto<MangaDetailsDto>().toSChapterList() override fun chapterListParse(response: Response) = response.toDto<MangaDetailsDto>().toSChapterList()
// =========================== Pages =================================== // =========================== Pages ===================================
override fun pageListRequest(chapter: SChapter): Request {
checkEntry(chapter.url)
return GET(getChapterUrl(chapter), headers)
}
override fun pageListParse(response: Response): List<Page> = override fun pageListParse(response: Response): List<Page> =
response.toDto<PageDto>().toPageList(sourceLocation) response.toDto<PageDto>().toPageList(sourceLocation)
@ -76,8 +106,18 @@ abstract class ZeroTheme(
// =========================== Utilities =============================== // =========================== Utilities ===============================
private fun checkEntry(url: String) {
if (listOf(mangaSubString, chapterSubString).any(url::contains)) {
throw IOException("Migre a obra para extensão $name")
}
}
inline fun <reified T> Response.toDto(): T { inline fun <reified T> Response.toDto(): T {
val jsonString = asJsoup().selectFirst("[data-page]")!!.attr("data-page") val jsonString = asJsoup().selectFirst("[data-page]")!!.attr("data-page")
return jsonString.parseAs<T>() return jsonString.parseAs<T>()
} }
companion object {
val MANGA_SUBSTRING_REGEX = """"(\w+)\\/\{slug\}""".toRegex()
}
} }

View File

@ -108,7 +108,7 @@ class MangaDto(
else -> SManga.UNKNOWN else -> SManga.UNKNOWN
} }
genre = genres?.joinToString { it.name } genre = genres?.joinToString { it.name }
url = "/comic/$slug" url = slug
} }
@Serializable @Serializable
@ -130,7 +130,7 @@ class ChapterDto(
name = number.toString() name = number.toString()
chapter_number = number chapter_number = number
date_upload = dateFormat.tryParse(createdAt) date_upload = dateFormat.tryParse(createdAt)
url = "/chapter/$path" url = path
} }
companion object { companion object {

View File

@ -13,4 +13,6 @@ class LerToons : ZeroTheme(
override val client = network.cloudflareClient.newBuilder() override val client = network.cloudflareClient.newBuilder()
.rateLimit(2) .rateLimit(2)
.build() .build()
override val mangaSubString: String = "manga"
} }