Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix(src/es): PelisPlusPh & MonosChinos fixes #182

Merged
merged 1 commit into from
Jan 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/es/monoschinos/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ext {
extName = 'MonosChinos'
extClass = '.MonosChinos'
extVersionCode = 31
extVersionCode = 32
}

apply from: "$rootDir/common.gradle"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,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
Expand All @@ -38,7 +37,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

Expand Down Expand Up @@ -81,20 +80,20 @@ 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
}
}
}
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()
Expand All @@ -107,13 +106,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)
}
}
Expand All @@ -122,31 +121,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")
Expand All @@ -156,31 +174,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) }.sort()
}
Expand Down Expand Up @@ -244,6 +240,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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
)
}
}
2 changes: 1 addition & 1 deletion src/es/pelisplushd/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ext {
extName = 'Pelisplushd'
extClass = '.PelisplushdFactory'
extVersionCode = 69
extVersionCode = 70
}

apply from: "$rootDir/common.gradle"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -52,14 +54,17 @@ 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() }
}
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Loading