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,8 +1,9 @@ | |||
| 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() { | ||||
|  | @ -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,13 +84,23 @@ 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") | ||||
|         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, | ||||
|  | @ -76,65 +108,69 @@ class AnimeflvnetProvider : MainAPI() { | |||
|                     TvType.Anime, | ||||
|                     fixUrl(image), | ||||
|                     null, | ||||
|                 if (title.contains("Latino") || title.contains("Castellano")) EnumSet.of(DubStatus.Dubbed) else EnumSet.of( | ||||
|                     DubStatus.Subbed | ||||
|                 ), | ||||
|                     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 type = doc.selectFirst("span.Type.A").text() | ||||
|         val genre = doc.select("a.Tag") | ||||
|             .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 | ||||
|         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 genre = doc.select("nav.Nvgnrs a") | ||||
|             .map { it?.text()?.trim().toString() } | ||||
| 
 | ||||
|         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,6 +297,25 @@ class GogoanimeProvider : MainAPI() { | |||
|                         source: GogoSource, | ||||
|                         sourceCallback: (ExtractorLink) -> Unit | ||||
|                     ) { | ||||
|                         if (source.file.contains("m3u8")) { | ||||
|                             M3u8Helper().m3u8Generation( | ||||
|                             M3u8Helper.M3u8Stream( | ||||
|                                 source.file, | ||||
|                                 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, | ||||
|  | @ -311,6 +327,7 @@ class GogoanimeProvider : MainAPI() { | |||
|                                 ) | ||||
|                             ) | ||||
|                         } | ||||
|                     } | ||||
| 
 | ||||
|                     sources.source?.forEach { | ||||
|                         invokeGogoSource(it, callback) | ||||
|  |  | |||
|  | @ -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" | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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,18 +20,19 @@ 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 { | ||||
|         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, | ||||
|  | @ -42,12 +43,10 @@ class BflixProvider(providerUrl: String, providerName: String) : MainAPI() { | |||
|                     null, | ||||
|                 ) | ||||
|             } | ||||
| 
 | ||||
|                 items.add(HomePageList(i.second, home)) | ||||
|             items.add(HomePageList(name, test)) | ||||
|         } catch (e: Exception) { | ||||
|             e.printStackTrace() | ||||
|         } | ||||
|         } | ||||
| 
 | ||||
|         if (items.size <= 0) throw ErrorLoadingException() | ||||
|         return HomePageResponse(items) | ||||
|  | @ -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,27 +150,108 @@ 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,10 +97,18 @@ class PeliSmartProvider: MainAPI() { | |||
|             val href = li.selectFirst("a").attr("href") | ||||
|             val preregex = Regex("(\\d+)\\. ") | ||||
|             val name = li.selectFirst("a").text().replace(preregex,"") | ||||
|             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, | ||||
|                 null, | ||||
|                 null, | ||||
|                     season, | ||||
|                     episode, | ||||
|                     href, | ||||
|                 ) | ||||
|         } | ||||
|  | @ -138,23 +147,14 @@ 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/") | ||||
|          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/") | ||||
|         }.toList() | ||||
|         for (link in link1) { | ||||
|             for (extractor in extractorApis) { | ||||
|                 if (link.startsWith(extractor.mainUrl)) { | ||||
|                     extractor.getSafeUrl(link, data)?.forEach { | ||||
|                         callback(it) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|              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,41 +15,51 @@ 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") | ||||
|         map.forEach { | ||||
|             items.add(HomePageList( | ||||
|                 it.key, | ||||
|                 document.select(it.value).select("a.Posters-link").map { element -> | ||||
|                     element.toSearchResult() | ||||
|                 } | ||||
|             )) | ||||
|         } | ||||
|         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, | ||||
|                         link, | ||||
|                         this.name, | ||||
|                         if (link.contains("/pelicula/")) TvType.Movie else TvType.TvSeries, | ||||
|                         it.selectFirst(".Posters-img").attr("src"), | ||||
|                         null, | ||||
|                 href, | ||||
|                 name, | ||||
|                 TvType.Movie, | ||||
|                 posterUrl, | ||||
|                 null, | ||||
|                 null | ||||
|             ) | ||||
|         } | ||||
| 
 | ||||
|                 items.add(HomePageList(i.second, home)) | ||||
|             } catch (e: Exception) { | ||||
|                 e.printStackTrace() | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         if (items.size <= 0) throw ErrorLoadingException() | ||||
|         return HomePageResponse(items) | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun search(query: String): List<SearchResponse> { | ||||
|  | @ -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,20 +165,9 @@ 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