forked from recloudstream/cloudstream
Fixes on multiple providers and added some extractors (#734)
* Fixes on Providers and Extractors Co-authored-by: Osten <11805592+LagradOst@users.noreply.github.com>
This commit is contained in:
parent
8aa907d1d9
commit
3b08e82787
12 changed files with 502 additions and 235 deletions
|
@ -1,11 +1,12 @@
|
|||
package com.lagradost.cloudstream3.animeproviders
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
import java.util.*
|
||||
|
||||
class AnimeflvnetProvider : MainAPI() {
|
||||
class AnimeflvnetProvider:MainAPI() {
|
||||
companion object {
|
||||
fun getType(t: String): TvType {
|
||||
return if (t.contains("OVA") || t.contains("Especial")) TvType.OVA
|
||||
|
@ -13,9 +14,8 @@ class AnimeflvnetProvider : MainAPI() {
|
|||
else TvType.Anime
|
||||
}
|
||||
}
|
||||
|
||||
override val mainUrl = "https://m.animeflv.net"
|
||||
override val name = "AnimeFLV"
|
||||
override val mainUrl = "https://www3.animeflv.net"
|
||||
override val name = "Animeflv.net"
|
||||
override val lang = "es"
|
||||
override val hasMainPage = true
|
||||
override val hasChromecastSupport = true
|
||||
|
@ -28,21 +28,24 @@ class AnimeflvnetProvider : MainAPI() {
|
|||
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val urls = listOf(
|
||||
Pair("$mainUrl/browse?type[]=movie&order=updated", "Peliculas actualizadas"),
|
||||
Pair("$mainUrl/browse?order=updated", "Animes recientemente actualizados"),
|
||||
Pair("$mainUrl/browse?status[]=2&order=default", "Animes finalizados"),
|
||||
Pair("$mainUrl/browse?type[]=movie&order=updated", "Películas"),
|
||||
Pair("$mainUrl/browse?status[]=2&order=default", "Animes"),
|
||||
Pair("$mainUrl/browse?status[]=1&order=rating", "En emision"),
|
||||
)
|
||||
val items = ArrayList<HomePageList>()
|
||||
for (i in urls) {
|
||||
try {
|
||||
val doc = app.get(i.first).document
|
||||
val home = doc.select("ul.List-Animes li.Anime").map {
|
||||
val title = it.selectFirst("h2.title").text()
|
||||
val poster = it.selectFirst(".Image img").attr("src")
|
||||
items.add(
|
||||
HomePageList(
|
||||
"Últimos episodios",
|
||||
app.get(mainUrl).document.select("main.Main ul.ListEpisodios li").map {
|
||||
val title = it.selectFirst("strong.Title").text()
|
||||
val poster = it.selectFirst("span img").attr("src")
|
||||
val epRegex = Regex("(-(\\d+)\$)")
|
||||
val url = it.selectFirst("a").attr("href").replace(epRegex,"")
|
||||
.replace("ver/","anime/")
|
||||
val epNum = it.selectFirst("span.Capi").text().replace("Episodio ","").toIntOrNull()
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
fixUrl(it.selectFirst("a").attr("href")),
|
||||
fixUrl(url),
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
fixUrl(poster),
|
||||
|
@ -50,10 +53,29 @@ class AnimeflvnetProvider : MainAPI() {
|
|||
if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(
|
||||
DubStatus.Dubbed
|
||||
) else EnumSet.of(DubStatus.Subbed),
|
||||
subEpisodes = epNum,
|
||||
dubEpisodes = epNum,
|
||||
)
|
||||
})
|
||||
)
|
||||
for ((url, name) in urls) {
|
||||
try {
|
||||
val doc = app.get(url).document
|
||||
val home = doc.select("ul.ListAnimes li article").map {
|
||||
val title = it.selectFirst("h3.Title").text()
|
||||
val poster = it.selectFirst("figure img").attr("src")
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
fixUrl(it.selectFirst("a").attr("href")),
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
fixUrl(poster),
|
||||
null,
|
||||
if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(DubStatus.Subbed),
|
||||
)
|
||||
}
|
||||
|
||||
items.add(HomePageList(i.second, home))
|
||||
items.add(HomePageList(name, home))
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
@ -62,80 +84,94 @@ class AnimeflvnetProvider : MainAPI() {
|
|||
return HomePageResponse(items)
|
||||
}
|
||||
|
||||
data class SearchObject (
|
||||
@JsonProperty("id") val id: String,
|
||||
@JsonProperty("title") val title: String,
|
||||
@JsonProperty("type") val type: String,
|
||||
@JsonProperty("last_id") val lastId: String,
|
||||
@JsonProperty("slug") val slug: String
|
||||
)
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "${mainUrl}/browse?q=${query}"
|
||||
val doc = app.get(url).document
|
||||
return doc.select("ul.List-Animes li.Anime").map {
|
||||
val title = it.selectFirst("h2.title").text()
|
||||
val href = fixUrl(it.selectFirst("a").attr("href"))
|
||||
val image = it.selectFirst(".Image img").attr("src")
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
href,
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
fixUrl(image),
|
||||
null,
|
||||
if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(
|
||||
DubStatus.Subbed
|
||||
),
|
||||
)
|
||||
val response = app.post("https://www3.animeflv.net/api/animes/search",
|
||||
data = mapOf(Pair("value",query))
|
||||
).text
|
||||
val json = parseJson<List<SearchObject>>(response)
|
||||
return json.map { searchr ->
|
||||
val title = searchr.title
|
||||
val href = "$mainUrl/anime/${searchr.slug}"
|
||||
val image = "$mainUrl/uploads/animes/covers/${searchr.id}.jpg"
|
||||
AnimeSearchResponse(
|
||||
title,
|
||||
href,
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
fixUrl(image),
|
||||
null,
|
||||
if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of(DubStatus.Subbed),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun load(url: String): LoadResponse {
|
||||
val doc = app.get(url).document
|
||||
val episodes = ArrayList<AnimeEpisode>()
|
||||
val title = doc.selectFirst("h1.Title").text()
|
||||
val description = doc.selectFirst(".Anime > header:nth-child(1) > p:nth-child(3)").text()
|
||||
.replace("Sinopsis: ", "")
|
||||
val poster = doc.selectFirst(".Image img").attr("src")
|
||||
val episodes = doc.select("li.Episode").map { li ->
|
||||
val href = fixUrl(li.selectFirst("a").attr("href"))
|
||||
AnimeEpisode(
|
||||
fixUrl(href), "Episodio" + li.selectFirst("a").text().replace(title, "")
|
||||
)
|
||||
val poster = doc.selectFirst("div.AnimeCover div.Image figure img").attr("src")
|
||||
val description = doc.selectFirst("div.Description p").text()
|
||||
val type = doc.selectFirst("span.Type").text()
|
||||
val status = when (doc.selectFirst("p.AnmStts span")?.text()) {
|
||||
"En emision" -> ShowStatus.Ongoing
|
||||
"Finalizado" -> ShowStatus.Completed
|
||||
else -> null
|
||||
}
|
||||
val type = doc.selectFirst("span.Type.A").text()
|
||||
val genre = doc.select("a.Tag")
|
||||
val genre = doc.select("nav.Nvgnrs a")
|
||||
.map { it?.text()?.trim().toString() }
|
||||
|
||||
val status =
|
||||
when (doc.selectFirst("article.Anime.Single.Bglg header p strong.Anm-On")?.text()) {
|
||||
"En emisión" -> ShowStatus.Ongoing
|
||||
"Finalizado" -> ShowStatus.Completed
|
||||
else -> null
|
||||
doc.select("script").map { script ->
|
||||
if (script.data().contains("var episodes = [")) {
|
||||
val data = script.data().substringAfter("var episodes = [").substringBefore("];")
|
||||
data.split("],").forEach {
|
||||
val epNum = it.removePrefix("[").substringBefore(",")
|
||||
// val epthumbid = it.removePrefix("[").substringAfter(",").substringBefore("]")
|
||||
val animeid = doc.selectFirst("div.Strs.RateIt").attr("data-id")
|
||||
val epthumb = "https://cdn.animeflv.net/screenshots/$animeid/$epNum/th_3.jpg"
|
||||
val link = url.replace("/anime/","/ver/")+"-$epNum"
|
||||
episodes.add( AnimeEpisode(
|
||||
link,
|
||||
null,
|
||||
posterUrl = epthumb,
|
||||
episode = epNum.toIntOrNull()
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
return newAnimeLoadResponse(title, url, getType(type)) {
|
||||
posterUrl = fixUrl(poster)
|
||||
addEpisodes(DubStatus.Subbed, episodes)
|
||||
addEpisodes(DubStatus.Subbed, episodes.reversed())
|
||||
showStatus = status
|
||||
plot = description
|
||||
tags = genre
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
//There might be a better way to do this, but this one works
|
||||
val html = app.get(data).text
|
||||
val linkRegex = Regex("""(https:.*?\.html.*)""")
|
||||
|
||||
val videos = linkRegex.findAll(html).map {
|
||||
it.value.replace("\\/", "/")
|
||||
}.toList()
|
||||
|
||||
val serversRegex =
|
||||
Regex("(https?://(www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_+.~#?&/=]*))")
|
||||
|
||||
serversRegex.findAll(videos.toString()).map {
|
||||
it.value.replace("https://embedsb.com", "https://watchsb.com")
|
||||
}.forEach { link ->
|
||||
loadExtractor(link, data, callback)
|
||||
app.get(data).document.select("script").apmap { script ->
|
||||
if (script.data().contains("var videos = {") || script.data().contains("var anime_id =") || script.data().contains("server")) {
|
||||
val videos = script.data().replace("\\/", "/")
|
||||
fetchUrls(videos).map {
|
||||
it.replace("https://embedsb.com/e/","https://watchsb.com/e/")
|
||||
.replace("https://ok.ru","http://ok.ru")
|
||||
}.apmap {
|
||||
loadExtractor(it, data, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,10 +2,7 @@ package com.lagradost.cloudstream3.animeproviders
|
|||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.utils.AppUtils
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.getQualityFromName
|
||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import org.jsoup.Jsoup
|
||||
import java.util.*
|
||||
import javax.crypto.Cipher
|
||||
|
@ -300,16 +297,36 @@ class GogoanimeProvider : MainAPI() {
|
|||
source: GogoSource,
|
||||
sourceCallback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
sourceCallback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
"${this.name} ${source.label?.replace("0 P", "0p") ?: ""}",
|
||||
if (source.file.contains("m3u8")) {
|
||||
M3u8Helper().m3u8Generation(
|
||||
M3u8Helper.M3u8Stream(
|
||||
source.file,
|
||||
"https://gogoplay.io",
|
||||
getQualityFromName(source.label ?: ""),
|
||||
isM3u8 = source.type == "hls"
|
||||
)
|
||||
headers = mapOf("Referer" to "https://gogoplay.io")
|
||||
), true
|
||||
)
|
||||
.map { stream ->
|
||||
val qualityString = if ((stream.quality ?: 0) == 0) "" else "${stream.quality}p"
|
||||
sourceCallback( ExtractorLink(
|
||||
name,
|
||||
"$name $qualityString",
|
||||
stream.streamUrl,
|
||||
"https://gogoplay.io",
|
||||
getQualityFromName(stream.quality.toString()),
|
||||
true
|
||||
))
|
||||
}
|
||||
} else if (source.file.contains("vidstreaming")) {
|
||||
sourceCallback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
"${this.name} ${source.label?.replace("0 P", "0p") ?: ""}",
|
||||
source.file,
|
||||
"https://gogoplay.io",
|
||||
getQualityFromName(source.label ?: ""),
|
||||
isM3u8 = source.type == "hls"
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
sources.source?.forEach {
|
||||
|
|
|
@ -10,10 +10,6 @@ import com.lagradost.cloudstream3.utils.getQualityFromName
|
|||
|
||||
|
||||
|
||||
class ZplayerV2 : GenericM3U8() {
|
||||
override val name = "Zplayer V2"
|
||||
override val mainUrl = "https://v2.zplayer.live"
|
||||
}
|
||||
|
||||
open class GenericM3U8 : ExtractorApi() {
|
||||
override val name = "Upstream"
|
||||
|
|
|
@ -45,7 +45,7 @@ class StreamSB9 : StreamSB() {
|
|||
}
|
||||
|
||||
// This is a modified version of https://github.com/jmir1/aniyomi-extensions/blob/master/src/en/genoanime/src/eu/kanade/tachiyomi/animeextension/en/genoanime/extractors/StreamSBExtractor.kt
|
||||
// The following code is under the Apache License 2.0 https://github.com/jmir1/aniyomi-extensions/blob/master/LICENSE
|
||||
// The following code is under the Apache License 2.0 https://github.com/jmir1/aniyomi-extensions/blob/master/LICENSE
|
||||
open class StreamSB : ExtractorApi() {
|
||||
override val name = "StreamSB"
|
||||
override val mainUrl = "https://watchsb.com"
|
||||
|
@ -91,7 +91,7 @@ open class StreamSB : ExtractorApi() {
|
|||
val master = "$mainUrl/sources41/566d337678566f743674494a7c7c${bytesToHex}7c7c346b6767586d6934774855537c7c73747265616d7362/6565417268755339773461447c7c346133383438333436313335376136323337373433383634376337633465366534393338373136643732373736343735373237613763376334363733353737303533366236333463353333363534366137633763373337343732363536313664373336327c7c6b586c3163614468645a47617c7c73747265616d7362"
|
||||
val headers = mapOf(
|
||||
"Host" to url.substringAfter("https://").substringBefore("/"),
|
||||
"User-Agent" to USER_AGENT,
|
||||
"User-Agent" to "Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0",
|
||||
"Accept" to "application/json, text/plain, */*",
|
||||
"Accept-Language" to "en-US,en;q=0.5",
|
||||
"Referer" to url,
|
||||
|
@ -109,7 +109,9 @@ open class StreamSB : ExtractorApi() {
|
|||
allowRedirects = false
|
||||
).text
|
||||
val mapped = urltext.let { parseJson<Main>(it) }
|
||||
if (urltext.contains("m3u8")) return M3u8Helper().m3u8Generation(
|
||||
val testurl = app.get(mapped.streamData.file, headers = headers).text
|
||||
val urlmain = mapped.streamData.file.substringBefore("/hls/")
|
||||
if (urltext.contains("m3u8") && testurl.contains("EXTM3U")) return M3u8Helper().m3u8Generation(
|
||||
M3u8Helper.M3u8Stream(
|
||||
mapped.streamData.file,
|
||||
headers = mapOf(
|
||||
|
@ -127,11 +129,12 @@ open class StreamSB : ExtractorApi() {
|
|||
), true
|
||||
)
|
||||
.map { stream ->
|
||||
val cleanstreamurl = stream.streamUrl.replace(Regex("https://.*/hls/"), "$urlmain/hls/")
|
||||
val qualityString = if ((stream.quality ?: 0) == 0) "" else "${stream.quality}p"
|
||||
ExtractorLink(
|
||||
name,
|
||||
"$name $qualityString",
|
||||
stream.streamUrl,
|
||||
cleanstreamurl,
|
||||
url,
|
||||
getQualityFromName(stream.quality.toString()),
|
||||
true
|
||||
|
@ -139,4 +142,4 @@ open class StreamSB : ExtractorApi() {
|
|||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package com.lagradost.cloudstream3.extractors
|
||||
|
||||
import com.lagradost.cloudstream3.apmap
|
||||
import com.lagradost.cloudstream3.app
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
|
||||
class Zplayer: ZplayerV2() {
|
||||
override val name: String = "Zplayer"
|
||||
override val mainUrl: String = "https://zplayer.live"
|
||||
}
|
||||
|
||||
class Upstream: ZplayerV2() {
|
||||
override val name: String = "Upstream" //Here 'cause works
|
||||
override val mainUrl: String = "https://upstream.to"
|
||||
}
|
||||
|
||||
open class ZplayerV2 : ExtractorApi() {
|
||||
override val name = "Zplayer V2"
|
||||
override val mainUrl = "https://v2.zplayer.live"
|
||||
override val requiresReferer = false
|
||||
|
||||
override suspend fun getUrl(url: String, referer: String?): List<ExtractorLink> {
|
||||
val doc = app.get(url).document
|
||||
val sources = mutableListOf<ExtractorLink>()
|
||||
doc.select("script").map { script ->
|
||||
if (script.data().contains("eval(function(p,a,c,k,e,d)")) {
|
||||
val testdata = getAndUnpack(script.data())
|
||||
val m3u8regex = Regex("((https:|http:)\\/\\/.*\\.m3u8)")
|
||||
m3u8regex.findAll(testdata).map {
|
||||
it.value
|
||||
}.toList().apmap { urlm3u8 ->
|
||||
if (urlm3u8.contains("m3u8")) {
|
||||
val testurl = app.get(urlm3u8, headers = mapOf("Referer" to url)).text
|
||||
if (testurl.contains("EXTM3U")) {
|
||||
M3u8Helper().m3u8Generation(
|
||||
M3u8Helper.M3u8Stream(
|
||||
urlm3u8,
|
||||
headers = mapOf("Referer" to url)
|
||||
), true
|
||||
)
|
||||
.map { stream ->
|
||||
val qualityString = if ((stream.quality ?: 0) == 0) "" else "${stream.quality}p"
|
||||
sources.add( ExtractorLink(
|
||||
name,
|
||||
"$name $qualityString",
|
||||
stream.streamUrl,
|
||||
url,
|
||||
getQualityFromName(stream.quality.toString()),
|
||||
true
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return sources
|
||||
}
|
||||
}
|
|
@ -20,33 +20,32 @@ class BflixProvider(providerUrl: String, providerName: String) : MainAPI() {
|
|||
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val items = ArrayList<HomePageList>()
|
||||
val urls = listOf(
|
||||
Pair("$mainUrl/home", "Movies"),
|
||||
Pair("$mainUrl/tv-series", "Series"),
|
||||
Pair("$mainUrl/top-imdb", "Top"),
|
||||
val soup = app.get("$mainUrl/home").document
|
||||
val testa = listOf(
|
||||
Pair("Movies", "div.tab-content[data-name=movies] div.filmlist div.item"),
|
||||
Pair("Shows", "div.tab-content[data-name=shows] div.filmlist div.item"),
|
||||
Pair("Trending", "div.tab-content[data-name=trending] div.filmlist div.item"),
|
||||
Pair("Latest Movies", "div.container section.bl:contains(Latest Movies) div.filmlist div.item"),
|
||||
Pair("Latest TV-Series", "div.container section.bl:contains(Latest TV-Series) div.filmlist div.item"),
|
||||
)
|
||||
for (i in urls) {
|
||||
try {
|
||||
val response = app.get(i.first)
|
||||
val soup = Jsoup.parse(response.text)
|
||||
val home = soup.select(".filmlist div.item").map {
|
||||
val title = it.selectFirst("h3 a").text()
|
||||
val link = fixUrl(it.selectFirst("a").attr("href"))
|
||||
TvSeriesSearchResponse(
|
||||
title,
|
||||
link,
|
||||
this.name,
|
||||
if (link.contains("/movie/")) TvType.Movie else TvType.TvSeries,
|
||||
it.selectFirst("a.poster img").attr("src"),
|
||||
null,
|
||||
null,
|
||||
)
|
||||
}
|
||||
|
||||
items.add(HomePageList(i.second, home))
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
for ((name, element) in testa) try {
|
||||
val test = soup.select(element).map {
|
||||
val title = it.selectFirst("h3 a").text()
|
||||
val link = fixUrl(it.selectFirst("a").attr("href"))
|
||||
// val quality = it.selectFirst("div.quality").text()
|
||||
TvSeriesSearchResponse(
|
||||
title,
|
||||
link,
|
||||
this.name,
|
||||
if (link.contains("/movie/")) TvType.Movie else TvType.TvSeries,
|
||||
it.selectFirst("a.poster img").attr("src"),
|
||||
null,
|
||||
null,
|
||||
)
|
||||
}
|
||||
items.add(HomePageList(name, test))
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
||||
if (items.size <= 0) throw ErrorLoadingException()
|
||||
|
@ -248,7 +247,15 @@ class BflixProvider(providerUrl: String, providerName: String) : MainAPI() {
|
|||
year = null
|
||||
)
|
||||
}
|
||||
|
||||
val rating = soup.selectFirst(".info span.imdb").text().toFloatOrNull()
|
||||
?.times(1000)?.toInt()
|
||||
val durationdoc = soup.selectFirst("div.info div.meta").toString()
|
||||
val durationregex = Regex("((\\d+) min)")
|
||||
val yearegex = Regex("<span>(\\d+)<\\/span>")
|
||||
val duration = if (durationdoc.contains("na min")) null
|
||||
else durationregex.find(durationdoc)?.destructured?.component1()?.replace(" min","")?.toIntOrNull()
|
||||
val year = if (mainUrl == "https://bflix.ru") { yearegex.find(durationdoc)?.destructured?.component1()
|
||||
?.replace(Regex("<span>|<\\/span>"),"") } else null
|
||||
return when (tvType) {
|
||||
TvType.TvSeries -> {
|
||||
TvSeriesLoadResponse(
|
||||
|
@ -258,13 +265,14 @@ class BflixProvider(providerUrl: String, providerName: String) : MainAPI() {
|
|||
tvType,
|
||||
episodes!!,
|
||||
poster,
|
||||
null,
|
||||
year?.toIntOrNull(),
|
||||
description,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
rating,
|
||||
tags,
|
||||
recommendations = recommendations,
|
||||
duration = duration,
|
||||
)
|
||||
}
|
||||
TvType.Movie -> {
|
||||
|
@ -275,12 +283,13 @@ class BflixProvider(providerUrl: String, providerName: String) : MainAPI() {
|
|||
tvType,
|
||||
url,
|
||||
poster,
|
||||
null,
|
||||
year?.toIntOrNull(),
|
||||
description,
|
||||
null,
|
||||
null,
|
||||
rating,
|
||||
tags,
|
||||
recommendations = recommendations
|
||||
recommendations = recommendations,
|
||||
duration = duration
|
||||
)
|
||||
}
|
||||
else -> null
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package com.lagradost.cloudstream3.movieproviders
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.extractors.Evoload
|
||||
import com.lagradost.cloudstream3.extractors.FEmbed
|
||||
import com.lagradost.cloudstream3.extractors.StreamTape
|
||||
import com.lagradost.cloudstream3.extractors.Cinestart
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import java.util.*
|
||||
|
||||
|
@ -30,9 +30,9 @@ class CinecalidadProvider:MainAPI() {
|
|||
Pair("$mainUrl/genero-de-la-pelicula/peliculas-en-calidad-4k/", "4K UHD"),
|
||||
)
|
||||
|
||||
for (i in urls) {
|
||||
for ((url, name) in urls) {
|
||||
try {
|
||||
val soup = app.get(i.first).document
|
||||
val soup = app.get(url).document
|
||||
val home = soup.select(".item.movies").map {
|
||||
val title = it.selectFirst("div.in_title").text()
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
|
@ -47,9 +47,9 @@ class CinecalidadProvider:MainAPI() {
|
|||
)
|
||||
}
|
||||
|
||||
items.add(HomePageList(i.second, home))
|
||||
items.add(HomePageList(name, home))
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
logError(e)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,15 +99,20 @@ class CinecalidadProvider:MainAPI() {
|
|||
val poster: String? = soup.selectFirst(".alignnone").attr("data-src")
|
||||
val episodes = soup.select("div.se-c div.se-a ul.episodios li").map { li ->
|
||||
val href = li.selectFirst("a").attr("href")
|
||||
val epThumb = li.selectFirst("div.imagen img").attr("data-src") ?: li.selectFirst("div.imagen img").attr("src")
|
||||
|
||||
val epThumb = li.selectFirst("img.lazy").attr("data-src")
|
||||
val name = li.selectFirst(".episodiotitle a").text()
|
||||
val seasonid = li.selectFirst(".numerando").text().replace(Regex("(S|E)"),"").let { str ->
|
||||
str.split("-").mapNotNull { subStr -> subStr.toIntOrNull() }
|
||||
}
|
||||
val isValid = seasonid.size == 2
|
||||
val episode = if (isValid) seasonid.getOrNull(1) else null
|
||||
val season = if (isValid) seasonid.getOrNull(0) else null
|
||||
TvSeriesEpisode(
|
||||
name,
|
||||
null,
|
||||
null,
|
||||
season,
|
||||
episode,
|
||||
href,
|
||||
epThumb
|
||||
if (epThumb.contains("svg")) null else epThumb
|
||||
)
|
||||
}
|
||||
return when (val tvType = if (url.contains("/ver-pelicula/")) TvType.Movie else TvType.TvSeries) {
|
||||
|
@ -145,28 +150,109 @@ class CinecalidadProvider:MainAPI() {
|
|||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
app.get(data).document.select(".dooplay_player_option").apmap {
|
||||
|
||||
val datam = app.get(data)
|
||||
val doc = datam.document
|
||||
val datatext = datam.text
|
||||
|
||||
doc.select(".dooplay_player_option").apmap {
|
||||
val url = it.attr("data-option")
|
||||
if (url.startsWith("https://evoload.io")) {
|
||||
val extractor = Evoload()
|
||||
if (url.startsWith("https://cinestart.net")) {
|
||||
val extractor = Cinestart()
|
||||
extractor.getSafeUrl(url)?.forEach { link ->
|
||||
callback.invoke(link)
|
||||
}
|
||||
} else {
|
||||
loadExtractor(url, mainUrl, callback)
|
||||
}
|
||||
if (url.startsWith("https://cinecalidad.lol")) {
|
||||
val cineurlregex = Regex("(https:\\/\\/cinecalidad\\.lol\\/play\\/\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
||||
cineurlregex.findAll(url).map {
|
||||
it.value.replace("/play/","/play/r.php")
|
||||
}.toList().apmap {
|
||||
app.get(it,
|
||||
headers = mapOf(
|
||||
"Host" to "cinecalidad.lol",
|
||||
"User-Agent" to USER_AGENT,
|
||||
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
|
||||
"Accept-Language" to "en-US,en;q=0.5",
|
||||
"DNT" to "1",
|
||||
"Connection" to "keep-alive",
|
||||
"Referer" to data,
|
||||
"Upgrade-Insecure-Requests" to "1",
|
||||
"Sec-Fetch-Dest" to "iframe",
|
||||
"Sec-Fetch-Mode" to "navigate",
|
||||
"Sec-Fetch-Site" to "same-origin",
|
||||
"Sec-Fetch-User" to "?1",
|
||||
),
|
||||
allowRedirects = false).response.headers.values("location").apmap { extractedurl ->
|
||||
if (extractedurl.contains("cinestart")) {
|
||||
loadExtractor(extractedurl, mainUrl, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((app.get(data).text.contains("en castellano"))) app.get("$data?ref=es").document.select(".dooplay_player_option").apmap {
|
||||
if (datatext.contains("en castellano")) app.get("$data?ref=es").document.select(".dooplay_player_option").apmap {
|
||||
val url = it.attr("data-option")
|
||||
if (url.startsWith("https://evoload.io")) {
|
||||
val extractor = Evoload()
|
||||
if (url.startsWith("https://cinestart.net")) {
|
||||
val extractor = Cinestart()
|
||||
extractor.getSafeUrl(url)?.forEach { link ->
|
||||
callback.invoke(link)
|
||||
}
|
||||
} else {
|
||||
loadExtractor(url, mainUrl, callback)
|
||||
}
|
||||
|
||||
if (url.startsWith("https://cinecalidad.lol")) {
|
||||
val cineurlregex = Regex("(https:\\/\\/cinecalidad\\.lol\\/play\\/\\?h=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)")
|
||||
cineurlregex.findAll(url).map {
|
||||
it.value.replace("/play/","/play/r.php")
|
||||
}.toList().apmap {
|
||||
app.get(it,
|
||||
headers = mapOf(
|
||||
"Host" to "cinecalidad.lol",
|
||||
"User-Agent" to USER_AGENT,
|
||||
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
|
||||
"Accept-Language" to "en-US,en;q=0.5",
|
||||
"DNT" to "1",
|
||||
"Connection" to "keep-alive",
|
||||
"Referer" to data,
|
||||
"Upgrade-Insecure-Requests" to "1",
|
||||
"Sec-Fetch-Dest" to "iframe",
|
||||
"Sec-Fetch-Mode" to "navigate",
|
||||
"Sec-Fetch-Site" to "same-origin",
|
||||
"Sec-Fetch-User" to "?1",
|
||||
),
|
||||
allowRedirects = false).response.headers.values("location").apmap { extractedurl ->
|
||||
if (extractedurl.contains("cinestart")) {
|
||||
loadExtractor(extractedurl, mainUrl, callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (datatext.contains("Subtítulo LAT") || datatext.contains("Forzados LAT")) {
|
||||
doc.select("#panel_descarga.pane a").apmap {
|
||||
val link = if (data.contains("serie") || data.contains("episodio")) "${data}${it.attr("href")}"
|
||||
else it.attr("href")
|
||||
val docsub = app.get(link)
|
||||
val linksub = docsub.document
|
||||
val validsub = docsub.text
|
||||
if (validsub.contains("Subtítulo") || validsub.contains("Forzados")) {
|
||||
val langregex = Regex("(Subtítulo.*\$|Forzados.*\$)")
|
||||
val langdoc = linksub.selectFirst("div.titulo h3").text()
|
||||
val reallang = langregex.find(langdoc)?.destructured?.component1()
|
||||
linksub.select("a.link").apmap {
|
||||
val sublink = if (data.contains("serie") || data.contains("episodio")) "${data}${it.attr("href")}"
|
||||
else it.attr("href")
|
||||
subtitleCallback(
|
||||
SubtitleFile(reallang!!, sublink)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package com.lagradost.cloudstream3.movieproviders
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
import com.fasterxml.jackson.module.kotlin.readValue
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
import java.util.*
|
||||
|
||||
class CuevanaProvider:MainAPI() {
|
||||
|
@ -24,9 +25,27 @@ class CuevanaProvider:MainAPI() {
|
|||
Pair(mainUrl, "Recientemente actualizadas"),
|
||||
Pair("$mainUrl/estrenos/", "Estrenos"),
|
||||
)
|
||||
for (i in urls) {
|
||||
items.add(
|
||||
HomePageList(
|
||||
"Series",
|
||||
app.get("$mainUrl/serie", timeout = 120).document.select("section.home-series li").map {
|
||||
val title = it.selectFirst("h2.Title").text()
|
||||
val poster = it.selectFirst("img.lazy").attr("data-src")
|
||||
val url = it.selectFirst("a").attr("href")
|
||||
TvSeriesSearchResponse(
|
||||
title,
|
||||
url,
|
||||
this.name,
|
||||
TvType.Anime,
|
||||
poster,
|
||||
null,
|
||||
null,
|
||||
)
|
||||
})
|
||||
)
|
||||
for ((url, name) in urls) {
|
||||
try {
|
||||
val soup = app.get(i.first).document
|
||||
val soup = app.get(url).document
|
||||
val home = soup.select("section li.xxx.TPostMv").map {
|
||||
val title = it.selectFirst("h2.Title").text()
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
|
@ -41,7 +60,7 @@ class CuevanaProvider:MainAPI() {
|
|||
)
|
||||
}
|
||||
|
||||
items.add(HomePageList(i.second, home))
|
||||
items.add(HomePageList(name, home))
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
}
|
||||
|
@ -80,7 +99,7 @@ class CuevanaProvider:MainAPI() {
|
|||
null
|
||||
)
|
||||
}
|
||||
}.toList()
|
||||
}
|
||||
}
|
||||
override suspend fun load(url: String): LoadResponse? {
|
||||
val soup = app.get(url, timeout = 120).document
|
||||
|
@ -88,24 +107,47 @@ class CuevanaProvider:MainAPI() {
|
|||
val description = soup.selectFirst(".Description p")?.text()?.trim()
|
||||
val poster: String? = soup.selectFirst(".movtv-info div.Image img").attr("data-src")
|
||||
val year1 = soup.selectFirst("footer p.meta").toString()
|
||||
val yearRegex = Regex("(\\d+)<\\/span>")
|
||||
val year = yearRegex.findAll(year1).map {
|
||||
it.value.replace("</span>","")
|
||||
}.toList().first().toIntOrNull()
|
||||
val yearRegex = Regex("<span>(\\d+)</span>")
|
||||
val yearf = yearRegex.find(year1)?.destructured?.component1()?.replace(Regex("<span>|</span>"),"")
|
||||
val year = if (yearf.isNullOrBlank()) null else yearf.toIntOrNull()
|
||||
val episodes = soup.select(".all-episodes li.TPostMv article").map { li ->
|
||||
val href = li.select("a").attr("href")
|
||||
val epThumb =
|
||||
li.selectFirst("div.Image img").attr("data-src") ?: li.selectFirst("img.lazy").attr("data-srcc")
|
||||
val name = li.selectFirst("h2.Title").text()
|
||||
val seasonid = li.selectFirst("span.Year").text().let { str ->
|
||||
str.split("x").mapNotNull { subStr -> subStr.toIntOrNull() }
|
||||
}
|
||||
val isValid = seasonid.size == 2
|
||||
val episode = if (isValid) seasonid.getOrNull(1) else null
|
||||
val season = if (isValid) seasonid.getOrNull(0) else null
|
||||
TvSeriesEpisode(
|
||||
name,
|
||||
null,
|
||||
null,
|
||||
season,
|
||||
episode,
|
||||
href,
|
||||
fixUrl(epThumb)
|
||||
)
|
||||
}
|
||||
return when (val tvType = if (episodes.isEmpty()) TvType.Movie else TvType.TvSeries) {
|
||||
val tags = soup.select("ul.InfoList li.AAIco-adjust:contains(Genero) a").map { it.text() }
|
||||
val tvType = if (episodes.isEmpty()) TvType.Movie else TvType.TvSeries
|
||||
val recelement = if (tvType == TvType.TvSeries) "main section div.series_listado.series div.xxx"
|
||||
else "main section ul.MovieList li"
|
||||
val recommendations =
|
||||
soup.select(recelement).mapNotNull { element ->
|
||||
val recTitle = element.select("h2.Title").text() ?: return@mapNotNull null
|
||||
val image = element.select("figure img")?.attr("data-src")
|
||||
val recUrl = fixUrl(element.select("a").attr("href"))
|
||||
MovieSearchResponse(
|
||||
recTitle,
|
||||
recUrl,
|
||||
this.name,
|
||||
TvType.Movie,
|
||||
image,
|
||||
year = null
|
||||
)
|
||||
}
|
||||
|
||||
return when (tvType) {
|
||||
TvType.TvSeries -> {
|
||||
TvSeriesLoadResponse(
|
||||
title,
|
||||
|
@ -116,6 +158,8 @@ class CuevanaProvider:MainAPI() {
|
|||
poster,
|
||||
year,
|
||||
description,
|
||||
tags = tags,
|
||||
recommendations = recommendations
|
||||
)
|
||||
}
|
||||
TvType.Movie -> {
|
||||
|
@ -128,6 +172,8 @@ class CuevanaProvider:MainAPI() {
|
|||
poster,
|
||||
year,
|
||||
description,
|
||||
tags = tags,
|
||||
recommendations = recommendations
|
||||
)
|
||||
}
|
||||
else -> null
|
||||
|
@ -199,7 +245,7 @@ class CuevanaProvider:MainAPI() {
|
|||
}.toList().apmap { gotolink ->
|
||||
app.post("https://api.cuevana3.io/ir/redirect_ddh.php", allowRedirects = false,
|
||||
headers = mapOf("Host" to "api.cuevana3.io",
|
||||
"User-Agent" to "Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0",
|
||||
"User-Agent" to USER_AGENT,
|
||||
"Accept" to "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
|
||||
"Accept-Language" to "en-US,en;q=0.5",
|
||||
"Content-Type" to "application/x-www-form-urlencoded",
|
||||
|
|
|
@ -26,9 +26,9 @@ class EntrepeliculasyseriesProvider:MainAPI() {
|
|||
Pair("$mainUrl/anime/", "Animes"),
|
||||
)
|
||||
|
||||
for (i in urls) {
|
||||
for ((url, name) in urls) {
|
||||
try {
|
||||
val soup = app.get(i.first).document
|
||||
val soup = app.get(url).document
|
||||
val home = soup.select("ul.list-movie li").map {
|
||||
val title = it.selectFirst("a.link-title h2").text()
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
|
@ -43,7 +43,7 @@ class EntrepeliculasyseriesProvider:MainAPI() {
|
|||
)
|
||||
}
|
||||
|
||||
items.add(HomePageList(i.second, home))
|
||||
items.add(HomePageList(name, home))
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
}
|
||||
|
@ -96,13 +96,18 @@ class EntrepeliculasyseriesProvider:MainAPI() {
|
|||
val episodes = soup.select(".TPostMv article").map { li ->
|
||||
val href = (li.select("a") ?: li.select(".C a") ?: li.select("article a")).attr("href")
|
||||
val epThumb = li.selectFirst("div.Image img").attr("data-src")
|
||||
val name = li.selectFirst("h2.Title").text()
|
||||
val seasonid = li.selectFirst("span.Year").text().let { str ->
|
||||
str.split("x").mapNotNull { subStr -> subStr.toIntOrNull() }
|
||||
}
|
||||
val isValid = seasonid.size == 2
|
||||
val episode = if (isValid) seasonid.getOrNull(1) else null
|
||||
val season = if (isValid) seasonid.getOrNull(0) else null
|
||||
TvSeriesEpisode(
|
||||
name,
|
||||
null,
|
||||
null,
|
||||
season,
|
||||
episode,
|
||||
href,
|
||||
epThumb
|
||||
fixUrl(epThumb)
|
||||
)
|
||||
}
|
||||
return when (val tvType = if (url.contains("/pelicula/")) TvType.Movie else TvType.TvSeries) {
|
||||
|
|
|
@ -3,7 +3,8 @@ package com.lagradost.cloudstream3.movieproviders
|
|||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.extractorApis
|
||||
import java.util.ArrayList
|
||||
import com.lagradost.cloudstream3.utils.loadExtractor
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
class PeliSmartProvider: MainAPI() {
|
||||
override val mainUrl = "https://pelismart.com"
|
||||
|
@ -26,9 +27,9 @@ class PeliSmartProvider: MainAPI() {
|
|||
Pair("$mainUrl/documentales/", "Documentales"),
|
||||
)
|
||||
|
||||
for (i in urls) {
|
||||
for ((url, name) in urls) {
|
||||
try {
|
||||
val soup = app.get(i.first).document
|
||||
val soup = app.get(url).document
|
||||
val home = soup.select(".description-off").map {
|
||||
val title = it.selectFirst("h3.entry-title a").text()
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
|
@ -43,7 +44,7 @@ class PeliSmartProvider: MainAPI() {
|
|||
)
|
||||
}
|
||||
|
||||
items.add(HomePageList(i.second, home))
|
||||
items.add(HomePageList(name, home))
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
|
@ -96,12 +97,20 @@ class PeliSmartProvider: MainAPI() {
|
|||
val href = li.selectFirst("a").attr("href")
|
||||
val preregex = Regex("(\\d+)\\. ")
|
||||
val name = li.selectFirst("a").text().replace(preregex,"")
|
||||
TvSeriesEpisode(
|
||||
name,
|
||||
null,
|
||||
null,
|
||||
href,
|
||||
)
|
||||
val regextest = Regex("(temporada-(\\d+)-capitulo-(\\d+)|temporada-(\\d+)-episodio-(\\d+))")
|
||||
val test = regextest.find(href)?.destructured?.component1()?.replace(Regex("(temporada-|-)"),"")
|
||||
val seasonid = test.let { str ->
|
||||
str?.split("episodio","capitulo")?.mapNotNull { subStr -> subStr.toIntOrNull() }
|
||||
}
|
||||
val isValid = seasonid?.size == 2
|
||||
val episode = if (isValid) seasonid?.getOrNull(1) else null
|
||||
val season = if (isValid) seasonid?.getOrNull(0) else null
|
||||
TvSeriesEpisode(
|
||||
name,
|
||||
season,
|
||||
episode,
|
||||
href,
|
||||
)
|
||||
}
|
||||
return when (val tvType = if (episodes.isEmpty()) TvType.Movie else TvType.TvSeries) {
|
||||
TvType.TvSeries -> {
|
||||
|
@ -138,24 +147,15 @@ class PeliSmartProvider: MainAPI() {
|
|||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
val soup = app.get(data).text
|
||||
val linkRegex = Regex("""(https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&\/\/=]*))""")
|
||||
val link1 = linkRegex.findAll(soup).map {
|
||||
it.value.replace("https://pelismart.com/p/1.php?v=","https://evoload.io/e/")
|
||||
.replace("https://pelismart.com/p/2.php?v=","https://streamtape.com/e/")
|
||||
.replace("https://pelismart.com/p/4.php?v=","https://dood.to/e/")
|
||||
.replace("https://pelismarthd.com/p/1.php?v=","https://evoload.io/e/")
|
||||
.replace("https://pelismarthd.com/p/2.php?v=","https://streamtape.com/e/")
|
||||
.replace("https://pelismarthd.com/p/4.php?v=","https://dood.to/e/")
|
||||
}.toList()
|
||||
for (link in link1) {
|
||||
for (extractor in extractorApis) {
|
||||
if (link.startsWith(extractor.mainUrl)) {
|
||||
extractor.getSafeUrl(link, data)?.forEach {
|
||||
callback(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fetchUrls(soup).apmap {
|
||||
val urlc = it.replace("https://pelismart.com/p/1.php?v=","https://evoload.io/e/")
|
||||
.replace("https://pelismart.com/p/2.php?v=","https://streamtape.com/e/")
|
||||
.replace("https://pelismart.com/p/4.php?v=","https://dood.to/e/")
|
||||
.replace("https://pelismarthd.com/p/1.php?v=","https://evoload.io/e/")
|
||||
.replace("https://pelismarthd.com/p/2.php?v=","https://streamtape.com/e/")
|
||||
.replace("https://pelismarthd.com/p/4.php?v=","https://dood.to/e/")
|
||||
loadExtractor(urlc, data, callback)
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package com.lagradost.cloudstream3.movieproviders
|
|||
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import org.jsoup.nodes.Element
|
||||
import java.util.*
|
||||
|
||||
class PelisplusHDProvider:MainAPI() {
|
||||
|
@ -14,42 +15,52 @@ class PelisplusHDProvider:MainAPI() {
|
|||
override val supportedTypes = setOf(
|
||||
TvType.Movie,
|
||||
TvType.TvSeries,
|
||||
TvType.Anime,
|
||||
)
|
||||
override suspend fun getMainPage(): HomePageResponse {
|
||||
val items = ArrayList<HomePageList>()
|
||||
val urls = listOf(
|
||||
Pair("$mainUrl/peliculas", "Peliculas"),
|
||||
Pair("$mainUrl/series", "Series"),
|
||||
Pair("$mainUrl/generos/dorama", "Doramas"),
|
||||
Pair("$mainUrl/animes", "Animes"),
|
||||
val document = app.get(mainUrl).document
|
||||
val map = mapOf(
|
||||
"Películas" to "#default-tab-1",
|
||||
"Series" to "#default-tab-2",
|
||||
"Anime" to "#default-tab-3",
|
||||
"Doramas" to "#default-tab-4",
|
||||
)
|
||||
for (i in urls) {
|
||||
try {
|
||||
val soup = app.get(i.first).document
|
||||
val home = soup.select("a.Posters-link").map {
|
||||
val title = it.selectFirst(".listing-content p").text()
|
||||
val link = it.selectFirst("a").attr("href")
|
||||
TvSeriesSearchResponse(
|
||||
title,
|
||||
link,
|
||||
this.name,
|
||||
if (link.contains("/pelicula/")) TvType.Movie else TvType.TvSeries,
|
||||
it.selectFirst(".Posters-img").attr("src"),
|
||||
null,
|
||||
null,
|
||||
)
|
||||
map.forEach {
|
||||
items.add(HomePageList(
|
||||
it.key,
|
||||
document.select(it.value).select("a.Posters-link").map { element ->
|
||||
element.toSearchResult()
|
||||
}
|
||||
|
||||
items.add(HomePageList(i.second, home))
|
||||
} catch (e: Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
))
|
||||
}
|
||||
|
||||
if (items.size <= 0) throw ErrorLoadingException()
|
||||
return HomePageResponse(items)
|
||||
}
|
||||
private fun Element.toSearchResult(): SearchResponse {
|
||||
val title = this.select(".listing-content p").text()
|
||||
val href = this.select("a").attr("href")
|
||||
val posterUrl = this.select(".Posters-img").attr("src")
|
||||
val isMovie = href.contains("/pelicula/")
|
||||
return if (isMovie) {
|
||||
MovieSearchResponse(
|
||||
title,
|
||||
href,
|
||||
name,
|
||||
TvType.Movie,
|
||||
posterUrl,
|
||||
null
|
||||
)
|
||||
} else {
|
||||
TvSeriesSearchResponse(
|
||||
title,
|
||||
href,
|
||||
name,
|
||||
TvType.Movie,
|
||||
posterUrl,
|
||||
null,
|
||||
null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val url = "https://pelisplushd.net/search?s=${query}"
|
||||
|
@ -93,10 +104,17 @@ class PelisplusHDProvider:MainAPI() {
|
|||
val episodes = soup.select("div.tab-pane .btn").map { li ->
|
||||
val href = li.selectFirst("a").attr("href")
|
||||
val name = li.selectFirst(".btn-primary.btn-block").text()
|
||||
val seasonid = href.replace("/capitulo/","-")
|
||||
.replace(Regex("$mainUrl/.*/.*/temporada/"),"").let { str ->
|
||||
str.split("-").mapNotNull { subStr -> subStr.toIntOrNull() }
|
||||
}
|
||||
val isValid = seasonid.size == 2
|
||||
val episode = if (isValid) seasonid.getOrNull(1) else null
|
||||
val season = if (isValid) seasonid.getOrNull(0) else null
|
||||
TvSeriesEpisode(
|
||||
name,
|
||||
null,
|
||||
null,
|
||||
season,
|
||||
episode,
|
||||
href,
|
||||
)
|
||||
}
|
||||
|
@ -117,7 +135,7 @@ class PelisplusHDProvider:MainAPI() {
|
|||
poster,
|
||||
year,
|
||||
description,
|
||||
ShowStatus.Ongoing,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
tags,
|
||||
|
@ -147,22 +165,11 @@ class PelisplusHDProvider:MainAPI() {
|
|||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
val soup = app.get(data).document
|
||||
val selector = soup.selectFirst("div.player > script").toString()
|
||||
val linkRegex = Regex("""(https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&\/\/=]*))""")
|
||||
val links = linkRegex.findAll(selector).map {
|
||||
it.value.replace("https://pelisplushd.net/fembed.php?url=","https://www.fembed.com/v/")
|
||||
.replace("https://pelistop.co/","https://watchsb.com/")
|
||||
}.toList()
|
||||
for (link in links) {
|
||||
for (extractor in extractorApis) {
|
||||
if (link.startsWith(extractor.mainUrl)) {
|
||||
extractor.getSafeUrl(link, data)?.forEach {
|
||||
callback(it)
|
||||
}
|
||||
}
|
||||
app.get(data).document.select("div.player > script").map { script ->
|
||||
fetchUrls(script.data().replace("https://pelisplushd.net/fembed.php?url=","https://www.fembed.com/v/")).apmap {
|
||||
loadExtractor(it, data, callback)
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -136,9 +136,12 @@ val extractorApis: Array<ExtractorApi> = arrayOf(
|
|||
|
||||
AsianLoad(),
|
||||
|
||||
ZplayerV2(),
|
||||
GenericM3U8(),
|
||||
// GenericM3U8(),
|
||||
Jawcloud(),
|
||||
Zplayer(),
|
||||
ZplayerV2(),
|
||||
Upstream(),
|
||||
|
||||
|
||||
// StreamSB.kt works
|
||||
// SBPlay(),
|
||||
|
|
Loading…
Reference in a new issue