EternalMangas: Move to Multi and fix pages not found (#3258)

* Move to Multi and fix pages

* skill issue

* mmmm

* remode id
This commit is contained in:
bapeey 2024-05-28 23:54:13 -05:00 committed by GitHub
parent a26934612a
commit dd00ec4067
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 109 additions and 15 deletions

View File

@ -2,7 +2,7 @@ plugins {
id("lib-multisrc")
}
baseVersionCode = 1
baseVersionCode = 2
dependencies {
api(project(":lib:i18n"))

View File

@ -73,7 +73,7 @@ abstract class MangaEsp(
return MangasPage(mangas, false)
}
private var comicsList = mutableListOf<SeriesDto>()
protected var comicsList = mutableListOf<SeriesDto>()
override fun fetchSearchManga(
page: Int,
@ -93,7 +93,7 @@ abstract class MangaEsp(
override fun searchMangaParse(response: Response): MangasPage = throw UnsupportedOperationException()
private fun searchMangaParse(response: Response, page: Int, query: String, filters: FilterList): MangasPage {
protected open fun searchMangaParse(response: Response, page: Int, query: String, filters: FilterList): MangasPage {
val document = response.asJsoup()
val script = document.select("script:containsData(self.__next_f.push)").joinToString { it.data() }
val jsonString = MANGA_LIST_REGEX.find(script)?.groupValues?.get(1)
@ -105,7 +105,7 @@ abstract class MangaEsp(
private var filteredList = mutableListOf<SeriesDto>()
private fun parseComicsList(page: Int, query: String, filterList: FilterList): MangasPage {
protected open fun parseComicsList(page: Int, query: String, filterList: FilterList): MangasPage {
if (page == 1) {
filteredList.clear()
@ -228,21 +228,21 @@ abstract class MangaEsp(
override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException()
private fun Element.imgAttr(): String = when {
protected open fun Element.imgAttr(): String = when {
hasAttr("data-lazy-src") -> attr("abs:data-lazy-src")
hasAttr("data-src") -> attr("abs:data-src")
hasAttr("data-cfsrc") -> attr("abs:data-cfsrc")
else -> attr("abs:src")
}
private fun String.unescape(): String {
fun String.unescape(): String {
return UNESCAPE_REGEX.replace(this, "$1")
}
companion object {
private val UNESCAPE_REGEX = """\\(.)""".toRegex()
private val MANGA_LIST_REGEX = """self\.__next_f\.push\(.*data\\":(\[.*trending.*])\}""".toRegex()
val MANGA_LIST_REGEX = """self\.__next_f\.push\(.*data\\":(\[.*trending.*])\}""".toRegex()
private val MANGA_DETAILS_REGEX = """self\.__next_f\.push\(.*data\\":(\{.*lastChapters.*\}).*\\"numFollow""".toRegex()
private const val MANGAS_PER_PAGE = 15
const val MANGAS_PER_PAGE = 15
}
}

View File

@ -44,7 +44,9 @@ class SeriesDto(
val trending: TrendingDto? = null,
@SerialName("autors") private val authors: List<AuthorDto> = emptyList(),
private val artists: List<ArtistDto> = emptyList(),
@Suppress("unused") // Used in some sources
@SerialName("idioma")
val language: String? = null,
) {
fun toSManga(): SManga {
return SManga.create().apply {

View File

@ -1,6 +1,6 @@
ext {
extName = 'EternalMangas'
extClass = '.EternalMangas'
extClass = '.EternalMangasFactory'
themePkg = 'mangaesp'
baseUrl = 'https://eternalmangas.com'
overrideVersionCode = 0

View File

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 21 KiB

After

Width:  |  Height:  |  Size: 21 KiB

View File

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 32 KiB

View File

@ -0,0 +1,82 @@
package eu.kanade.tachiyomi.extension.all.eternalmangas
import eu.kanade.tachiyomi.multisrc.mangaesp.MangaEsp
import eu.kanade.tachiyomi.multisrc.mangaesp.SeriesDto
import eu.kanade.tachiyomi.multisrc.mangaesp.TopSeriesDto
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import okhttp3.FormBody
import okhttp3.Response
open class EternalMangas(
lang: String,
private val internalLang: String,
) : MangaEsp(
"EternalMangas",
"https://eternalmangas.com",
lang,
) {
override fun popularMangaParse(response: Response): MangasPage {
val body = response.body.string()
val responseData = json.decodeFromString<TopSeriesDto>(body)
val topDaily = responseData.response.topDaily.flatten().map { it.data }
val topWeekly = responseData.response.topWeekly.flatten().map { it.data }
val topMonthly = responseData.response.topMonthly.flatten().map { it.data }
val mangas = (topDaily + topWeekly + topMonthly).distinctBy { it.slug }
.filter { it.language == internalLang }
.map { it.toSManga() }
return MangasPage(mangas, false)
}
override fun latestUpdatesParse(response: Response): MangasPage {
val responseData = json.decodeFromString<LatestUpdatesDto>(response.body.string())
val mangas = responseData.updates[internalLang]?.flatten()?.map { it.toSManga() } ?: emptyList()
return MangasPage(mangas, false)
}
override fun searchMangaParse(response: Response, page: Int, query: String, filters: FilterList): MangasPage {
val document = response.asJsoup()
val script = document.select("script:containsData(self.__next_f.push)").joinToString { it.data() }
val jsonString = MANGA_LIST_REGEX.find(script)?.groupValues?.get(1)
?: throw Exception(intl["comics_list_error"])
val unescapedJson = jsonString.unescape()
comicsList = json.decodeFromString<List<SeriesDto>>(unescapedJson)
.filter { it.language == internalLang }
.toMutableList()
return parseComicsList(page, query, filters)
}
override fun pageListParse(response: Response): List<Page> {
var document = response.asJsoup()
document.selectFirst("body > form[method=post]")?.let {
val action = it.attr("action")
val inputs = it.select("input")
val form = FormBody.Builder()
inputs.forEach { input ->
form.add(input.attr("name"), input.attr("value"))
}
document = client.newCall(POST(action, headers, form.build())).execute().asJsoup()
}
return document.select("main > img").mapIndexed { i, img ->
Page(i, imageUrl = img.imgAttr())
}
}
@Serializable
class LatestUpdatesDto(
val updates: Map<String, List<List<SeriesDto>>>,
)
}

View File

@ -0,0 +1,15 @@
package eu.kanade.tachiyomi.extension.all.eternalmangas
import eu.kanade.tachiyomi.source.SourceFactory
class EternalMangasFactory : SourceFactory {
override fun createSources() = listOf(
EternalMangasES(),
EternalMangasEN(),
EternalMangasPTBR(),
)
}
class EternalMangasES : EternalMangas("es", "es")
class EternalMangasEN : EternalMangas("en", "en")
class EternalMangasPTBR : EternalMangas("pt-BR", "pt")

View File

@ -1,5 +0,0 @@
package eu.kanade.tachiyomi.extension.es.eternalmangas
import eu.kanade.tachiyomi.multisrc.mangaesp.MangaEsp
class EternalMangas : MangaEsp("EternalMangas", "https://eternalmangas.com", "es")