fix(es/cuevana): Change domain (#2016)

This commit is contained in:
imper1aldev
2023-08-05 18:29:58 -06:00
committed by GitHub
parent c7c6f4403f
commit c7902b38ae
3 changed files with 79 additions and 69 deletions

View File

@ -5,7 +5,7 @@ ext {
extName = 'Cuevana'
pkgNameSuffix = 'es.cuevana'
extClass = '.Cuevana'
extVersionCode = 17
extVersionCode = 18
libVersion = '13'
}
@ -15,6 +15,8 @@ dependencies {
implementation project(path: ':lib-streamsb-extractor')
implementation project(path: ':lib-okru-extractor')
implementation project(path: ':lib-voe-extractor')
implementation project(path: ':lib-streamtape-extractor')
implementation "dev.datlag.jsunpacker:jsunpacker:1.0.1"
}
apply from: "$rootDir/common.gradle"

View File

@ -4,6 +4,7 @@ import android.app.Application
import android.content.SharedPreferences
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.es.cuevana.extractors.StreamWishExtractor
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
import eu.kanade.tachiyomi.animesource.model.AnimeFilterList
@ -14,6 +15,7 @@ import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.lib.doodextractor.DoodExtractor
import eu.kanade.tachiyomi.lib.okruextractor.OkruExtractor
import eu.kanade.tachiyomi.lib.streamsbextractor.StreamSBExtractor
import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
import eu.kanade.tachiyomi.lib.youruploadextractor.YourUploadExtractor
import eu.kanade.tachiyomi.network.GET
@ -22,10 +24,8 @@ import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
@ -38,7 +38,7 @@ class Cuevana : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val name = "Cuevana"
override val baseUrl = "https://n2.cuevana3.me"
override val baseUrl = "https://www12.cuevana3.ch"
override val lang = "es"
@ -52,15 +52,15 @@ class Cuevana : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
override fun popularAnimeSelector(): String = "section li.xxx.TPostMv div.TPost"
override fun popularAnimeSelector(): String = ".MovieList .TPostMv .TPost"
override fun popularAnimeRequest(page: Int): Request = GET("$baseUrl/peliculas/page/$page")
override fun popularAnimeRequest(page: Int): Request = GET("$baseUrl/peliculas?page=$page")
override fun popularAnimeFromElement(element: Element): SAnime {
val anime = SAnime.create()
anime.setUrlWithoutDomain(element.selectFirst("a")!!.attr("href"))
anime.title = element.select("a .Title").text()
anime.thumbnail_url = element.select("a .Image figure.Objf img").attr("data-src")
anime.thumbnail_url = element.select("a .Image figure.Objf img").attr("abs:data-src")
return anime
}
@ -70,13 +70,13 @@ class Cuevana : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val episodes = mutableListOf<SEpisode>()
val document = response.asJsoup()
if (response.request.url.toString().contains("/serie/")) {
document.select("[id*=season-]").mapIndexed { idxSeason, season ->
document.select("[id*=season-]").reversed().mapIndexed { idxSeason, season ->
val noSeason = try {
season.attr("id").substringAfter("season-").toInt()
} catch (e: Exception) {
idxSeason
}
season.select(".TPostMv article.TPost").mapIndexed { idxCap, cap ->
season.select(".TPostMv article.TPost").reversed().mapIndexed { idxCap, cap ->
val epNum = try { cap.select("a div.Image span.Year").text().substringAfter("x").toFloat() } catch (e: Exception) { idxCap.toFloat() }
val episode = SEpisode.create()
val date = cap.select("a > p").text()
@ -90,8 +90,7 @@ class Cuevana : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
} else {
val episode = SEpisode.create().apply {
val epnum = 1
episode_number = epnum.toFloat()
episode_number = 1f
name = "PELÍCULA"
}
episode.setUrlWithoutDomain(response.request.url.toString())
@ -107,13 +106,12 @@ class Cuevana : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun videoListParse(response: Response): List<Video> {
val document = response.asJsoup()
val videoList = mutableListOf<Video>()
document.select("div.TPlayer.embed_div iframe").map {
document.select("ul.anime_muti_link li").map {
val langPrefix = try {
val optLanguage = it.parent()!!.attr("id")
val languageTag = document.selectFirst("li[data-tplayernv=$optLanguage]")!!.closest(".open_submenu")!!.selectFirst("div:first-child")!!.text()
val languageTag = it.selectFirst(".cdtr span")!!.text()
if (languageTag.lowercase().contains("latino")) {
"[LAT]"
} else if (languageTag.lowercase().contains("españa")) {
} else if (languageTag.lowercase().contains("castellano")) {
"[CAST]"
} else if (languageTag.lowercase().contains("subtitulado")) {
"[SUB]"
@ -121,53 +119,12 @@ class Cuevana : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
""
}
} catch (e: Exception) { "" }
val regIsUrl = "https?:\\/\\/(www\\.)?[-a-zA-Z0-9@:%._\\+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_\\+.~#?&//=]*)".toRegex()
val iframe = urlServerSolver(it.attr("data-src"))
if (iframe.contains("apialfa.tomatomatela.club")) {
try {
val tomkey = iframe.substringAfter("?h=")
val clientGoTo = OkHttpClient().newBuilder().build()
val mediaType = "application/x-www-form-urlencoded".toMediaType()
val bodyGoTo = "url=$tomkey".toRequestBody(mediaType)
val requestGoTo = Request.Builder()
.url("https://apialfa.tomatomatela.club/ir/rd.php")
.method("POST", bodyGoTo)
.addHeader("Host", "apialfa.tomatomatela.club")
.addHeader(
"User-Agent",
"Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0",
)
.addHeader(
"Accept",
"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
)
.addHeader("Accept-Language", "en-US,en;q=0.5")
.addHeader("Content-Type", "application/x-www-form-urlencoded")
.addHeader("Origin", "null")
.addHeader("DNT", "1")
.addHeader("Connection", "keep-alive")
.addHeader("Upgrade-Insecure-Requests", "1")
.addHeader("Sec-Fetch-Dest", "iframe")
.addHeader("Sec-Fetch-Mode", "navigate")
.addHeader("Sec-Fetch-Site", "same-origin")
.build()
val responseGoto = clientGoTo.newCall(requestGoTo).execute()
val locations = responseGoto!!.networkResponse.toString()
fetchUrls(locations).map {
if (!it.contains("ir/rd.php")) {
loadExtractor(it, langPrefix).map { video -> videoList.add(video) }
}
}
} catch (e: Exception) { }
}
if (regIsUrl.containsMatchIn(iframe) &&
!iframe.contains("apialfa.tomatomatela.club")
) {
try {
loadExtractor(iframe, langPrefix).map { video -> videoList.add(video) }
} catch (e: Exception) { }
}
val url = it.attr("abs:data-video")
try {
loadExtractor(url, langPrefix).map { video -> videoList.add(video) }
} catch (_: Exception) { }
}
return videoList
}
@ -197,7 +154,7 @@ class Cuevana : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val status = json["status"]!!.jsonPrimitive!!.content
val file = json["file"]!!.jsonPrimitive!!.content
if (status == "200") { videoList.add(Video(file, "$prefix Tomatomatela", file, headers = null)) }
} catch (e: Exception) { }
} catch (_: Exception) { }
}
if (embedUrl.contains("yourupload")) {
val videos = YourUploadExtractor(client).videoFromUrl(url, headers = headers)
@ -227,7 +184,13 @@ class Cuevana : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
)
}
if (embedUrl.contains("voe")) {
VoeExtractor(client).videoFromUrl(url)?.let { videoList.add(it) }
VoeExtractor(client).videoFromUrl(url, "$prefix Voe")?.let { videoList.add(it) }
}
if (embedUrl.contains("streamtape")) {
StreamTapeExtractor(client).videoFromUrl(url, "$prefix StreamTape")?.let { videoList.add(it) }
}
if (embedUrl.contains("wishembed") || embedUrl.contains("streamwish") || embedUrl.contains("wish")) {
StreamWishExtractor(client, headers).videosFromUrl(url, "$prefix StreamWish:")?.let { videoList.addAll(it) }
}
return videoList
}
@ -272,8 +235,8 @@ class Cuevana : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val genreFilter = filterList.find { it is GenreFilter } as GenreFilter
return when {
query.isNotBlank() -> GET("$baseUrl/page/$page?s=$query", headers)
genreFilter.state != 0 -> GET("$baseUrl/category/${genreFilter.toUriPart()}/page/$page")
query.isNotBlank() -> GET("$baseUrl/search.html?keyword=$query&page=$page", headers)
genreFilter.state != 0 -> GET("$baseUrl/category/${genreFilter.toUriPart()}?page=$page")
else -> popularAnimeRequest(page)
}
}
@ -288,10 +251,10 @@ class Cuevana : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun animeDetailsParse(document: Document): SAnime {
val anime = SAnime.create()
anime.title = document.selectFirst("#top-single div.backdrop article.TPost header .Title")!!.text()
anime.thumbnail_url = document.selectFirst("#top-single div.backdrop article div.Image figure img")!!.attr("data-src")
anime.description = document.selectFirst("#top-single div.backdrop article.TPost div.Description")!!.text().trim()
anime.genre = document.select("#MvTb-Info ul.InfoList li:nth-child(2) > a").joinToString { it.text() }
anime.title = document.selectFirst(".TPost header .Title")!!.text()
anime.thumbnail_url = document.selectFirst(".backdrop article div.Image figure img")!!.attr("abs:data-src")
anime.description = document.selectFirst(".backdrop article.TPost div.Description")!!.text().trim()
anime.genre = document.select("ul.InfoList li:nth-child(1) > a").joinToString { it.text() }
anime.status = SAnime.UNKNOWN
return anime
}

View File

@ -0,0 +1,45 @@
package eu.kanade.tachiyomi.animeextension.es.cuevana.extractors
import dev.datlag.jsunpacker.JsUnpacker
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
class StreamWishExtractor(private val client: OkHttpClient, private val headers: Headers) {
fun videosFromUrl(url: String, prefix: String): List<Video> {
val videoList = mutableListOf<Video>()
val doc = client.newCall(GET(url, headers = headers)).execute().asJsoup()
val jsEval = doc.selectFirst("script:containsData(m3u8)")?.data() ?: "UwU"
val masterUrl = JsUnpacker.unpackAndCombine(jsEval)
?.substringAfter("source")
?.substringAfter("file:\"")
?.substringBefore("\"")
?: return emptyList()
val playlistHeaders = headers.newBuilder()
.add("Accept", "*/*")
.add("Host", masterUrl.toHttpUrl().host)
.add("Origin", "https://${url.toHttpUrl().host}")
.set("Referer", "https://${url.toHttpUrl().host}/")
.build()
val masterBase = "https://${masterUrl.toHttpUrl().host}${masterUrl.toHttpUrl().encodedPath}"
.substringBeforeLast("/") + "/"
val masterPlaylist = client.newCall(
GET(masterUrl, headers = playlistHeaders),
).execute().body.string()
val separator = "#EXT-X-STREAM-INF:"
masterPlaylist.substringAfter(separator).split(separator).forEach {
val quality = prefix + it.substringAfter("RESOLUTION=").substringAfter("x").substringBefore(",") + "p "
val videoUrl = masterBase + it.substringAfter("\n").substringBefore("\n")
videoList.add(Video(videoUrl, quality, videoUrl, headers = playlistHeaders))
}
return videoList
}
}