From 48f1bac534bd0bf870acb56e20bb83b650b13ff4 Mon Sep 17 00:00:00 2001 From: imper1aldev <23511335+imper1aldev@users.noreply.github.com> Date: Wed, 8 Jan 2025 14:50:22 -0600 Subject: [PATCH] fix(src/es): PelisPlusPh & MonosChinos fixes (#497) * PelisPlusPh fixes Closes #489 * MonosChinos fixes Closes #450 --- src/es/monoschinos/build.gradle | 2 +- .../es/monoschinos/MonosChinos.kt | 109 ++++++++++-------- .../es/monoschinos/MonosChinosFilters.kt | 82 +++++++++---- src/es/pelisplushd/build.gradle | 2 +- .../es/pelisplushd/Pelisplushd.kt | 2 + .../es/pelisplushd/PelisplushdFactory.kt | 2 +- .../es/pelisplushd/Pelisplusph.kt | 7 +- .../es/pelisplushd/Pelisplusto.kt | 2 + 8 files changed, 130 insertions(+), 78 deletions(-) diff --git a/src/es/monoschinos/build.gradle b/src/es/monoschinos/build.gradle index a22dc4c4..e716c223 100644 --- a/src/es/monoschinos/build.gradle +++ b/src/es/monoschinos/build.gradle @@ -1,7 +1,7 @@ ext { extName = 'MonosChinos' extClass = '.MonosChinos' - extVersionCode = 29 + extVersionCode = 30 } apply from: "$rootDir/common.gradle" diff --git a/src/es/monoschinos/src/eu/kanade/tachiyomi/animeextension/es/monoschinos/MonosChinos.kt b/src/es/monoschinos/src/eu/kanade/tachiyomi/animeextension/es/monoschinos/MonosChinos.kt index 9adcbbcf..9f786cbe 100644 --- a/src/es/monoschinos/src/eu/kanade/tachiyomi/animeextension/es/monoschinos/MonosChinos.kt +++ b/src/es/monoschinos/src/eu/kanade/tachiyomi/animeextension/es/monoschinos/MonosChinos.kt @@ -24,7 +24,6 @@ import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking -import eu.kanade.tachiyomi.util.parseAs import okhttp3.FormBody import okhttp3.Request import okhttp3.Response @@ -37,7 +36,7 @@ class MonosChinos : ConfigurableAnimeSource, AnimeHttpSource() { override val name = "MonosChinos" - override val baseUrl = "https://monoschinos2.com" + override val baseUrl = "https://monoschinos2.net" override val id = 6957694006954649296 @@ -80,7 +79,7 @@ class MonosChinos : ConfigurableAnimeSource, AnimeHttpSource() { status = document.select(".lh-sm .ms-2").eachText().let { items -> when { items.any { it.contains("Finalizado") } -> SAnime.COMPLETED - items.any { it.contains("Estreno") } -> SAnime.ONGOING + items.any { it.contains("En emision") || it.contains("Estreno") } -> SAnime.ONGOING else -> SAnime.UNKNOWN } } @@ -88,12 +87,12 @@ class MonosChinos : ConfigurableAnimeSource, AnimeHttpSource() { return animeDetails } - override fun popularAnimeRequest(page: Int) = GET("$baseUrl/animes?p=$page", headers) + override fun popularAnimeRequest(page: Int) = GET("$baseUrl/animes?pag=$page", headers) override fun popularAnimeParse(response: Response): AnimesPage { val document = response.asJsoup() val elements = document.select(".ficha_efecto a") - val nextPage = document.select(".pagination [rel=\"next\"]").any() + val nextPage = document.select(".pagination [title=\"Siguiente página\"]").any() val animeList = elements.map { element -> SAnime.create().apply { title = element.selectFirst(".title_cap")!!.text() @@ -106,13 +105,13 @@ class MonosChinos : ConfigurableAnimeSource, AnimeHttpSource() { override fun latestUpdatesParse(response: Response) = popularAnimeParse(response) - override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/emision?p=$page", headers) + override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/animes?estado=en+emision&pag=$page", headers) override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request { val params = MonosChinosFilters.getSearchParameters(filters) return when { - query.isNotBlank() -> GET("$baseUrl/buscar?q=$query", headers) - params.filter.isNotBlank() -> GET("$baseUrl/animes${params.getQuery()}&p=$page", headers) + query.isNotBlank() -> GET("$baseUrl/animes?buscar=$query&pag=$page", headers) + params.filter.isNotBlank() -> GET("$baseUrl/animes${params.getQuery()}&pag=$page", headers) else -> popularAnimeRequest(page) } } @@ -121,31 +120,50 @@ class MonosChinos : ConfigurableAnimeSource, AnimeHttpSource() { override fun episodeListParse(response: Response): List<SEpisode> { val document = response.asJsoup() - val token = document.select("meta[name='csrf-token']").attr("content") - val capListLink = document.select(".caplist").attr("data-ajax") val referer = document.location() + val dt = document.select("#dt") - val detail = getEpisodeDetails(capListLink, token, referer) - val total = detail.eps.size - val perPage = detail.perpage ?: return emptyList() + val total = dt.attr("data-e").toInt() + val perPage = 50.0 val pages = (total / perPage).ceilPage() + val i = dt.attr("data-i") + val u = dt.attr("data-u") + var pageIdx = 1 return (1..pages).parallelCatchingFlatMapBlocking { - getEpisodePage(detail.paginateUrl ?: "", it, token, referer).caps.mapIndexed { idx, ep -> - val episodeNumber = (ep.episodio ?: (idx + 1)) - SEpisode.create().apply { - name = "Capítulo $episodeNumber" - episode_number = episodeNumber.toFloat() - setUrlWithoutDomain(ep.url ?: "") - } - } - }.reversed() + val formBody = FormBody.Builder() + .add("acc", "episodes") + .add("i", i) + .add("u", u) + .add("p", pageIdx.toString()) + .build() + + val request = Request.Builder() + .url("$baseUrl/ajax_pagination") + .post(formBody) + .header("accept", "application/json, text/javascript, */*; q=0.01") + .header("accept-language", "es-419,es;q=0.8") + .header("content-type", "application/x-www-form-urlencoded; charset=UTF-8") + .header("origin", baseUrl) + .header("referer", referer) + .header("x-requested-with", "XMLHttpRequest") + .build() + pageIdx++ + + client.newCall(request).execute().getEpisodes() + } } - private fun getEpisodeDetails(capListLink: String, token: String, referer: String): EpisodesDto { - val formBody = FormBody.Builder().add("_token", token).build() + override fun videoListParse(response: Response): List<Video> { + val document = response.asJsoup() + val i = document.select(".opt").attr("data-encrypt") + val referer = document.location() + val formBody = FormBody.Builder() + .add("acc", "opt") + .add("i", i) + .build() val request = Request.Builder() - .url(capListLink) + .url("$baseUrl/ajax_pagination") .post(formBody) .header("accept", "application/json, text/javascript, */*; q=0.01") .header("accept-language", "es-419,es;q=0.8") @@ -155,31 +173,9 @@ class MonosChinos : ConfigurableAnimeSource, AnimeHttpSource() { .header("x-requested-with", "XMLHttpRequest") .build() - return client.newCall(request).execute().parseAs<EpisodesDto>() - } + val serverDocument = client.newCall(request).execute().asJsoup() - private fun getEpisodePage(paginateUrl: String, page: Int, token: String, referer: String): EpisodeInfoDto { - val formBodyEp = FormBody.Builder() - .add("_token", token) - .add("p", "$page") - .build() - val requestEp = Request.Builder() - .url(paginateUrl) - .post(formBodyEp) - .header("accept", "application/json, text/javascript, */*; q=0.01") - .header("accept-language", "es-419,es;q=0.8") - .header("content-type", "application/x-www-form-urlencoded; charset=UTF-8") - .header("origin", baseUrl) - .header("referer", referer) - .header("x-requested-with", "XMLHttpRequest") - .build() - - return client.newCall(requestEp).execute().parseAs<EpisodeInfoDto>() - } - - override fun videoListParse(response: Response): List<Video> { - val document = response.asJsoup() - return document.select("[data-player]") + return serverDocument.select("[data-player]") .map { String(Base64.decode(it.attr("data-player"), Base64.DEFAULT)) } .parallelCatchingFlatMapBlocking { serverVideoResolver(it) } } @@ -242,6 +238,21 @@ class MonosChinos : ConfigurableAnimeSource, AnimeHttpSource() { private fun Double.ceilPage(): Int = if (this % 1 == 0.0) this.toInt() else ceil(this).toInt() + private fun Response.getEpisodes(): List<SEpisode> { + val document = this.asJsoup() + return document.select(".ko").mapIndexed { idx, it -> + val episodeNumber = try { + it.select("h2").text().substringAfter("Capítulo").trim().toFloat() + } catch (e: Exception) { idx + 1f } + + SEpisode.create().apply { + name = it.select(".fs-6").text() + episode_number = episodeNumber + setUrlWithoutDomain(it.attr("abs:href")) + } + } + } + override fun setupPreferenceScreen(screen: PreferenceScreen) { ListPreference(screen.context).apply { key = PREF_SERVER_KEY diff --git a/src/es/monoschinos/src/eu/kanade/tachiyomi/animeextension/es/monoschinos/MonosChinosFilters.kt b/src/es/monoschinos/src/eu/kanade/tachiyomi/animeextension/es/monoschinos/MonosChinosFilters.kt index 3fba586b..520b6e09 100644 --- a/src/es/monoschinos/src/eu/kanade/tachiyomi/animeextension/es/monoschinos/MonosChinosFilters.kt +++ b/src/es/monoschinos/src/eu/kanade/tachiyomi/animeextension/es/monoschinos/MonosChinosFilters.kt @@ -54,86 +54,118 @@ object MonosChinosFilters { if (filters.isEmpty()) return FilterSearchParams() return FilterSearchParams( filters.parseCheckbox<GenresFilter>(DoramasytFiltersData.GENRES, "genero") + + filters.parseCheckbox<YearsFilter>(DoramasytFiltersData.YEARS, "anio") + filters.parseCheckbox<TypesFilter>(DoramasytFiltersData.TYPES, "tipo") + - filters.asQueryPart<YearsFilter>("fecha") + - filters.asQueryPart<LettersFilter>("letra"), + filters.asQueryPart<StatusFilter>("estado") + + filters.asQueryPart<SortFilter>("orden"), ) } val FILTER_LIST get() = AnimeFilterList( AnimeFilter.Header("La busqueda por texto ignora el filtro"), GenresFilter(), - TypesFilter(), YearsFilter(), - LettersFilter(), + TypesFilter(), + StatusFilter(), + SortFilter(), ) class GenresFilter : CheckBoxFilterList("Género", DoramasytFiltersData.GENRES.map { CheckBoxVal(it.first, false) }) + class YearsFilter : CheckBoxFilterList("Año", DoramasytFiltersData.YEARS.map { CheckBoxVal(it.first, false) }) + class TypesFilter : CheckBoxFilterList("Tipo", DoramasytFiltersData.TYPES.map { CheckBoxVal(it.first, false) }) - class YearsFilter : QueryPartFilter("Año", DoramasytFiltersData.YEARS) + class StatusFilter : QueryPartFilter("Estado", DoramasytFiltersData.STATUS) - class LettersFilter : QueryPartFilter("Letra", DoramasytFiltersData.LETTER) + class SortFilter : QueryPartFilter("Orden", DoramasytFiltersData.SORT) private object DoramasytFiltersData { val TYPES = arrayOf( - Pair("<Selecionar>", ""), - Pair("Pelicula", "pelicula"), Pair("Anime", "anime"), + Pair("Audio Japonés", "audio-japones"), + Pair("Corto", "corto"), + Pair("Donghua", "donghua"), + Pair("Especial", "especial"), + Pair("Ona", "ona"), + Pair("Ova", "ova"), + Pair("Película", "pelicula"), + Pair("Película 1080p", "pelicula-1080p"), + Pair("TV", "tv"), + Pair("Sin Censura", "sin-censura"), ) - val YEARS = arrayOf(Pair("<Seleccionar>", "")) + (1982..Calendar.getInstance().get(Calendar.YEAR)).map { Pair("$it", "$it") }.reversed().toTypedArray() + val STATUS = arrayOf( + Pair("Todos", ""), + Pair("En emisión", "en-emision"), + Pair("Finalizado", "finalizado"), + ) - val LETTER = arrayOf(Pair("<Seleccionar>", "")) + ('A'..'Z').map { Pair("$it", "$it") }.toTypedArray() + val YEARS = (1968..Calendar.getInstance().get(Calendar.YEAR)).map { Pair("$it", "$it") }.reversed().toTypedArray() val GENRES = arrayOf( - Pair("<Selecionar>", ""), Pair("Acción", "accion"), + Pair("Aenime", "aenime"), + Pair("Anime Latino", "anime-latino"), + Pair("Artes Marciales", "artes-marciales"), Pair("Aventura", "aventura"), + Pair("Aventuras", "aventuras"), + Pair("Blu-ray", "blu-ray"), Pair("Carreras", "carreras"), + Pair("Castellano", "castellano"), Pair("Ciencia Ficción", "ciencia-ficcion"), Pair("Comedia", "comedia"), Pair("Cyberpunk", "cyberpunk"), + Pair("Demencia", "demencia"), + Pair("Dementia", "dementia"), + Pair("Demonios", "demonios"), Pair("Deportes", "deportes"), Pair("Drama", "drama"), Pair("Ecchi", "ecchi"), Pair("Escolares", "escolares"), + Pair("Espacial", "espacial"), Pair("Fantasía", "fantasia"), Pair("Gore", "gore"), Pair("Harem", "harem"), + Pair("Historia paralela", "historia-paralela"), + Pair("Historico", "historico"), Pair("Horror", "horror"), + Pair("Infantil", "infantil"), Pair("Josei", "josei"), + Pair("Juegos", "juegos"), + Pair("Latino", "latino"), Pair("Lucha", "lucha"), Pair("Magia", "magia"), Pair("Mecha", "mecha"), Pair("Militar", "militar"), Pair("Misterio", "misterio"), + Pair("Monogatari", "monogatari"), Pair("Música", "musica"), + Pair("Parodia", "parodia"), Pair("Parodias", "parodias"), + Pair("Policía", "policia"), Pair("Psicológico", "psicologico"), + Pair("Recuentos de la vida", "recuentos-de-la-vida"), Pair("Recuerdos de la vida", "recuerdos-de-la-vida"), + Pair("Romance", "romance"), + Pair("Samurai", "samurai"), Pair("Seinen", "seinen"), Pair("Shojo", "shojo"), Pair("Shonen", "shonen"), + Pair("Shoujo", "shoujo"), + Pair("Shounen", "shounen"), Pair("Sobrenatural", "sobrenatural"), + Pair("Superpoderes", "superpoderes"), + Pair("Suspenso", "suspenso"), + Pair("Terror", "terror"), Pair("Vampiros", "vampiros"), Pair("Yaoi", "yaoi"), Pair("Yuri", "yuri"), - Pair("Latino", "latino"), - Pair("Espacial", "espacial"), - Pair("Histórico", "historico"), - Pair("Samurai", "samurai"), - Pair("Artes Marciales", "artes-marciales"), - Pair("Demonios", "demonios"), - Pair("Romance", "romance"), - Pair("Dementia", "dementia"), - Pair(" Policía", "policia"), - Pair("Castellano", "castellano"), - Pair("Historia paralela", "historia-paralela"), - Pair("Aenime", "aenime"), - Pair("Blu-ray", "blu-ray"), - Pair("Monogatari", "monogatari"), + ) + + val SORT = arrayOf( + Pair("Descendente", "desc"), + Pair("Ascendente", "asc"), ) } } diff --git a/src/es/pelisplushd/build.gradle b/src/es/pelisplushd/build.gradle index edabfe2c..6da4424b 100644 --- a/src/es/pelisplushd/build.gradle +++ b/src/es/pelisplushd/build.gradle @@ -1,7 +1,7 @@ ext { extName = 'Pelisplushd' extClass = '.PelisplushdFactory' - extVersionCode = 59 + extVersionCode = 60 } apply from: "$rootDir/common.gradle" diff --git a/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplushd.kt b/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplushd.kt index 1ddaf869..2f26c25d 100644 --- a/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplushd.kt +++ b/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplushd.kt @@ -39,6 +39,8 @@ import uy.kohesive.injekt.api.get open class Pelisplushd(override val name: String, override val baseUrl: String) : ConfigurableAnimeSource, ParsedAnimeHttpSource() { + override val id: Long = 1400819034564144238L + override val lang = "es" override val supportsLatest = false diff --git a/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/PelisplushdFactory.kt b/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/PelisplushdFactory.kt index 0a0d39a4..7f6d3707 100644 --- a/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/PelisplushdFactory.kt +++ b/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/PelisplushdFactory.kt @@ -7,6 +7,6 @@ class PelisplushdFactory : AnimeSourceFactory { override fun createSources(): List<AnimeSource> = listOf( Pelisplushd("PelisPlusHD", "https://pelisplushd.bz"), Pelisplusto("PelisPlusTo", "https://ww3.pelisplus.to"), - Pelisplusph("PelisPlusPh", "https://www.pelisplushd.ph"), + Pelisplusph("PelisPlusPh", "https://ww5.pelisplushd.pe"), ) } diff --git a/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplusph.kt b/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplusph.kt index aaf7d33f..e724edba 100644 --- a/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplusph.kt +++ b/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplusph.kt @@ -16,6 +16,8 @@ import org.jsoup.nodes.Element class Pelisplusph(override val name: String, override val baseUrl: String) : Pelisplushd(name, baseUrl) { + override val id: Long = 4917265654298497443L + override val supportsLatest = false companion object { @@ -52,7 +54,7 @@ class Pelisplusph(override val name: String, override val baseUrl: String) : Pel anime.title = document.selectFirst(".info-content h1")!!.text() document.select(".info-content p").map { p -> if (p.select(".content-type").text().contains("Sinópsis:")) { - anime.description = p.select(".sinopsis")!!.text() + anime.description = p.select(".sinopsis").text() } if (p.select(".content-type").text().contains("Géneros:")) { anime.genre = p.select(".content-type-a a").joinToString { it.text() } @@ -60,6 +62,9 @@ class Pelisplusph(override val name: String, override val baseUrl: String) : Pel if (p.select(".content-type").text().contains("Reparto:")) { anime.artist = p.select(".content-type ~ span").text().substringBefore(",") } + if (p.select(".content-type").text().contains("Actores:")) { + anime.artist = p.select(".content-type ~ span").text().substringBefore(",") + } } anime.status = if (document.location().contains("/serie/")) SAnime.UNKNOWN else SAnime.COMPLETED diff --git a/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplusto.kt b/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplusto.kt index 20aff832..76e685ee 100644 --- a/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplusto.kt +++ b/src/es/pelisplushd/src/eu/kanade/tachiyomi/animeextension/es/pelisplushd/Pelisplusto.kt @@ -23,6 +23,8 @@ import uy.kohesive.injekt.injectLazy class Pelisplusto(override val name: String, override val baseUrl: String) : Pelisplushd(name, baseUrl) { + override val id: Long = 1705636111422561130L + private val json: Json by injectLazy() override val supportsLatest = false