mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	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…
	
	Add table
		Add a link
		
	
		Reference in a new issue