From f8ac139b678296f1b85a2e5d4c41edb5f658e0d0 Mon Sep 17 00:00:00 2001 From: Jace <54625750+Jacekun@users.noreply.github.com> Date: Sat, 22 Jan 2022 22:14:47 +0800 Subject: [PATCH] fix: multiple providers with reversed episode list. (#498) load links for PinoyMoviesEsprovider. abstracted asianembed helper for multiple providers. --- .../extractors/helper/AsianEmbedHelper.kt | 28 +++ .../extractors/helper/VstreamhubHelper.kt | 51 +++++ .../movieproviders/DramaSeeProvider.kt | 46 ++--- .../movieproviders/KdramaHoodProvider.kt | 34 ++-- .../movieproviders/PinoyMoviePediaProvider.kt | 4 +- .../movieproviders/PinoyMoviesEsProvider.kt | 178 +++++++----------- .../movieproviders/WatchAsianProvider.kt | 25 ++- 7 files changed, 194 insertions(+), 172 deletions(-) create mode 100644 app/src/main/java/com/lagradost/cloudstream3/extractors/helper/AsianEmbedHelper.kt create mode 100644 app/src/main/java/com/lagradost/cloudstream3/extractors/helper/VstreamhubHelper.kt diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/helper/AsianEmbedHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/helper/AsianEmbedHelper.kt new file mode 100644 index 00000000..14b921ed --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/helper/AsianEmbedHelper.kt @@ -0,0 +1,28 @@ +package com.lagradost.cloudstream3.extractors.helper + +import android.util.Log +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.loadExtractor + +class AsianEmbedHelper { + companion object { + fun getUrls(url: String, callback: (ExtractorLink) -> Unit) { + if (url.startsWith("https://asianembed.io")) { + // Fetch links + val doc = app.get(url).document + val links = doc.select("div#list-server-more > ul > li.linkserver") + if (!links.isNullOrEmpty()) { + links.forEach { + val datavid = it.attr("data-video") ?: "" + //Log.i("AsianEmbed", "Result => (datavid) ${datavid}") + if (datavid.isNotEmpty()) { + val res = loadExtractor(datavid, url, callback) + Log.i("AsianEmbed", "Result => ($res) (datavid) ${datavid}") + } + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/helper/VstreamhubHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/helper/VstreamhubHelper.kt new file mode 100644 index 00000000..86995885 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/helper/VstreamhubHelper.kt @@ -0,0 +1,51 @@ +package com.lagradost.cloudstream3.extractors.helper + +import android.util.Log +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.Qualities +import com.lagradost.cloudstream3.utils.loadExtractor + +class VstreamhubHelper { + companion object { + private val baseUrl: String = "https://vstreamhub.com" + private val baseName: String = "Vstreamhub" + + fun getUrls(url: String, callback: (ExtractorLink) -> Unit) { + if (url.startsWith(baseUrl)) { + // Fetch links + val doc = app.get(url).document.select("script") + doc?.forEach { + val innerText = it?.toString() + if (!innerText.isNullOrEmpty()) { + if (innerText.contains("file:")) { + val startString = "file: " + val aa = innerText.substring(innerText.indexOf(startString)) + val linkUrl = aa.substring(startString.length + 1, aa.indexOf("\",")).trim() + //Log.i(baseName, "Result => (linkUrl) ${linkUrl}") + val exlink = ExtractorLink( + name = "$baseName m3u8", + source = baseName, + url = linkUrl, + quality = Qualities.Unknown.value, + referer = url, + isM3u8 = true + ) + callback.invoke(exlink) + } + if (innerText.contains("playerInstance")) { + val aa = innerText.substring(innerText.indexOf("playerInstance.addButton")) + val startString = "window.open([" + val bb = aa.substring(aa.indexOf(startString)) + val datavid = bb.substring(startString.length, bb.indexOf("]")).removeSurrounding("\"") + if (datavid.isNotEmpty()) { + loadExtractor(datavid, url, callback) + //Log.i(baseName, "Result => (datavid) ${datavid}") + } + } + } + } + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/DramaSeeProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/DramaSeeProvider.kt index fa13c660..7df30642 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/DramaSeeProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/DramaSeeProvider.kt @@ -3,6 +3,7 @@ package com.lagradost.cloudstream3.movieproviders import com.fasterxml.jackson.module.kotlin.readValue import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.extractors.* +import com.lagradost.cloudstream3.extractors.helper.AsianEmbedHelper import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.loadExtractor @@ -139,7 +140,7 @@ class DramaSeeProvider : MainAPI() { url, this.name, TvType.TvSeries, - episodeList, + episodeList.reversed(), poster, year, descript, @@ -155,45 +156,32 @@ class DramaSeeProvider : MainAPI() { subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ): Boolean { + var count = 0 mapper.readValue>(data).forEach { item -> if (item.isNotEmpty()) { + count++ var url = item.trim() if (url.startsWith("//")) { url = "https:$url" } //Log.i(this.name, "Result => (url) ${url}") - if (url.startsWith("https://asianembed.io")) { - // Fetch links - val doc = app.get(url).document - val links = doc.select("div#list-server-more > ul > li.linkserver") - if (!links.isNullOrEmpty()) { - links.forEach { - val datavid = it.attr("data-video") ?: "" - //Log.i(this.name, "Result => (datavid) ${datavid}") - if (datavid.isNotEmpty()) { - if (datavid.startsWith("https://fembed-hd.com")) { - val extractor = XStreamCdn() - extractor.domainUrl = "fembed-hd.com" - extractor.getUrl(datavid, url).forEach { link -> - callback.invoke(link) - } - } else { - loadExtractor(datavid, url, callback) - } - } + when { + url.startsWith("https://asianembed.io") -> { + AsianEmbedHelper.getUrls(url, callback) + } + url.startsWith("https://embedsito.com") -> { + val extractor = XStreamCdn() + extractor.domainUrl = "embedsito.com" + extractor.getUrl(url).forEach { link -> + callback.invoke(link) } } - } else if (url.startsWith("https://embedsito.com")) { - val extractor = XStreamCdn() - extractor.domainUrl = "embedsito.com" - extractor.getUrl(url).forEach { link -> - callback.invoke(link) + else -> { + loadExtractor(url, mainUrl, callback) } - } else { - loadExtractor(url, mainUrl, callback) - } // end if + } } } - return true + return count > 0 } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/KdramaHoodProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/KdramaHoodProvider.kt index 18618b67..2ea99a84 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/KdramaHoodProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/KdramaHoodProvider.kt @@ -4,6 +4,7 @@ import android.util.Log import com.fasterxml.jackson.module.kotlin.readValue import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.extractors.* +import com.lagradost.cloudstream3.extractors.helper.AsianEmbedHelper import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.loadExtractor @@ -170,7 +171,7 @@ class KdramaHoodProvider : MainAPI() { url, this.name, TvType.TvSeries, - episodeList, + episodeList.reversed(), poster, year, descript, @@ -195,28 +196,21 @@ class KdramaHoodProvider : MainAPI() { url = "https:$url" } //Log.i(this.name, "Result => (url) ${url}") - if (url.startsWith("https://asianembed.io")) { - // Fetch links - val doc = app.get(url).document - val links = doc.select("div#list-server-more > ul > li.linkserver") - if (!links.isNullOrEmpty()) { - links.forEach { - val datavid = it.attr("data-video") ?: "" - //Log.i(this.name, "Result => (datavid) ${datavid}") - if (datavid.isNotEmpty()) { - loadExtractor(datavid, url, callback) - } + when { + url.startsWith("https://asianembed.io") -> { + AsianEmbedHelper.getUrls(url, callback) + } + url.startsWith("https://embedsito.com") -> { + val extractor = XStreamCdn() + extractor.domainUrl = "embedsito.com" + extractor.getUrl(url).forEach { link -> + callback.invoke(link) } } - } else if (url.startsWith("https://embedsito.com")) { - val extractor = XStreamCdn() - extractor.domainUrl = "embedsito.com" - extractor.getUrl(url).forEach { link -> - callback.invoke(link) + else -> { + loadExtractor(url, mainUrl, callback) } - } else { - loadExtractor(url, mainUrl, callback) - } // end if + } } } return count > 0 diff --git a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/PinoyMoviePediaProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/PinoyMoviePediaProvider.kt index 7ffd8a45..cd52c653 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/PinoyMoviePediaProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/PinoyMoviePediaProvider.kt @@ -178,7 +178,9 @@ class PinoyMoviePediaProvider : MainAPI() { callback: (ExtractorLink) -> Unit ): Boolean { // parse movie servers + var count = 0 mapper.readValue>(data).forEach { link -> + count++ if (link.contains("fembed.com")) { val extractor = FEmbed() extractor.domainUrl = "diasfem.com" @@ -189,6 +191,6 @@ class PinoyMoviePediaProvider : MainAPI() { loadExtractor(link, mainUrl, callback) } } - return true + return count > 0 } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/PinoyMoviesEsProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/PinoyMoviesEsProvider.kt index 776a3eed..d2774d37 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/PinoyMoviesEsProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/PinoyMoviesEsProvider.kt @@ -1,23 +1,30 @@ package com.lagradost.cloudstream3.movieproviders -import android.util.Log +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.module.kotlin.readValue import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.extractors.FEmbed +import com.lagradost.cloudstream3.extractors.helper.VstreamhubHelper import com.lagradost.cloudstream3.network.DdosGuardKiller +import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.loadExtractor -import org.jsoup.Jsoup import org.jsoup.select.Elements class PinoyMoviesEsProvider : MainAPI() { override val name = "Pinoy Movies" - override val mainUrl = "https://pinoymovies.es/" + override val mainUrl = "https://pinoymovies.es" override val lang = "tl" - override val supportedTypes = setOf(TvType.Movie, TvType.TvSeries) + override val supportedTypes = setOf(TvType.Movie) override val hasDownloadSupport = false override val hasMainPage = true override val hasQuickSearch = false + data class EmbedUrl( + @JsonProperty("embed_url") val embed_url: String, + @JsonProperty("type") val type: String + ) + private fun getRowElements(mainbody: Elements, rows: List>, sep: String): MutableList { val all = mutableListOf() for (item in rows) { @@ -60,8 +67,7 @@ class PinoyMoviesEsProvider : MainAPI() { } override suspend fun getMainPage(): HomePageResponse { val all = ArrayList() - val html = app.get(mainUrl).text - val document = Jsoup.parse(html) + val document = app.get(mainUrl).document val mainbody = document.getElementsByTag("body") if (mainbody != null) { // All rows will be hardcoded bc of the nature of the site @@ -88,40 +94,33 @@ class PinoyMoviesEsProvider : MainAPI() { } override suspend fun search(query: String): List { - val url = "$mainUrl/?s=${query}" - val html = app.get(url, interceptor = DdosGuardKiller(true)).text - //Log.i(this.name, "Result => (html) ${Jsoup.parse(html).getElementsByTag("body")}") - val document = Jsoup.parse(html).select("div#archive-content > article") - if (document != null) { - return document.map { - val urlTitle = it?.select("div.data") - // Fetch details - val link = urlTitle?.select("a")?.attr("href") ?: "" - val title = urlTitle?.text() ?: "" - val year = urlTitle?.select("span.year")?.text()?.toIntOrNull() + val url = "$mainUrl/?s=${query.replace(" ", "+")}" + val document = app.get(url, interceptor = DdosGuardKiller(true)) + .document.select("div#archive-content > article") - val image = it?.select("div.poster > img")?.attr("src") + return document?.mapNotNull { + val urlTitle = it?.select("div.data") ?: return@mapNotNull null + // Fetch details + val link = urlTitle.select("a")?.attr("href") ?: return@mapNotNull null + val title = urlTitle.text() ?: "" + val year = urlTitle.select("span.year")?.text()?.toIntOrNull() + val image = it.select("div.poster > img")?.attr("src") - MovieSearchResponse( - title, - link, - this.name, - TvType.Movie, - image, - year - ) - } - } - return listOf() + MovieSearchResponse( + title, + link, + this.name, + TvType.Movie, + image, + year + ) + }?.distinctBy { it.url } ?: listOf() } override suspend fun load(url: String): LoadResponse { - val response = app.get(url).text - val doc = Jsoup.parse(response) + val doc = app.get(url).document val body = doc.getElementsByTag("body") val inner = body?.select("div.sheader") - // Identify if movie or series - val isTvSeries = doc?.select("title")?.text()?.lowercase()?.contains("full episode -") ?: false // Video details val data = inner?.select("div.sheader > div.data") @@ -132,57 +131,28 @@ class PinoyMoviesEsProvider : MainAPI() { val poster = body?.select("div.poster > img")?.attr("src") // Video links - val linksContainer = body?.select("div#playcontainer") - val streamlinks = linksContainer?.toString() ?: "" - //Log.i(this.name, "Result => (streamlinks) ${streamlinks}") + val listOfLinks: MutableList = mutableListOf() + val postlist = body?.select("div#playeroptions > ul > li")?.mapNotNull { + it?.attr("data-post") ?: return@mapNotNull null + }?.filter { it.isNotEmpty() }?.distinct() ?: listOf() - // Parse episodes if series - if (isTvSeries) { - val episodeList = ArrayList() - val epList = body?.select("div#playeroptions > ul > li") - //Log.i(this.name, "Result => (epList) ${epList}") - val epLinks = linksContainer?.select("div > div > div.source-box") - //Log.i(this.name, "Result => (epLinks) ${epLinks}") - if (epList != null) { - for (ep in epList) { - val epTitle = ep.select("span.title")?.text() ?: "" - if (epTitle.isNotEmpty()) { - val epNum = epTitle.lowercase().replace("episode", "").trim().toIntOrNull() - //Log.i(this.name, "Result => (epNum) ${epNum}") - val href = when (epNum != null && epLinks != null) { - true -> epLinks.select("div#source-player-${epNum}") - ?.select("iframe")?.attr("src") ?: "" - false -> "" - } - //Log.i(this.name, "Result => (epLinks href) ${href}") - episodeList.add( - TvSeriesEpisode( - name = name, - season = null, - episode = epNum, - data = href, - posterUrl = poster, - date = year.toString() - ) - ) - } - } - return TvSeriesLoadResponse( - title, - url, - this.name, - TvType.TvSeries, - episodeList, - poster, - year, - descript, - null, - null, - null - ) + postlist.forEach { datapost -> + //Log.i(this.name, "Result => (datapost) ${datapost}") + val content = mapOf( + Pair("action", "doo_player_ajax"), + Pair("post", datapost), + Pair("nume", "1"), + Pair("type", "movie") + ) + val innerPage = app.post("https://pinoymovies.es/wp-admin/admin-ajax.php ", + referer = url, data = content).document.select("body")?.text()?.trim() + if (!innerPage.isNullOrEmpty()) { + val embedData = mapper.readValue(innerPage) + //Log.i(this.name, "Result => (embed_url) ${embedData.embed_url}") + listOfLinks.add(embedData.embed_url) } } - return MovieLoadResponse(title, url, this.name, TvType.Movie, streamlinks, poster, year, descript, null, null) + return MovieLoadResponse(title, url, this.name, TvType.Movie, listOfLinks.toJson(), poster, year, descript, null, null) } override suspend fun loadLinks( @@ -191,41 +161,23 @@ class PinoyMoviesEsProvider : MainAPI() { subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ): Boolean { - val sources = mutableListOf() - try { - if (data.contains("playcontainer")) { - // parse movie servers - //Log.i(this.name, "Result => (data) ${data}") - Jsoup.parse(data).select("div")?.map { item -> - val url = item.select("iframe")?.attr("src") - if (!url.isNullOrEmpty()) { - //Log.i(this.name, "Result => (url) ${url}") - loadExtractor(url, url, callback) - } + // parse movie servers + var count = 0 + mapper.readValue>(data).forEach { link -> + count++ + //Log.i(this.name, "Result => (link) $link") + if (link.startsWith("https://vstreamhub.com")) { + VstreamhubHelper.getUrls(link, callback) + } else if (link.contains("fembed.com")) { + val extractor = FEmbed() + extractor.domainUrl = "diasfem.com" + extractor.getUrl(data).forEach { + callback.invoke(it) } } else { - // parse single link - if (data.contains("fembed.com")) { - val extractor = FEmbed() - extractor.domainUrl = "diasfem.com" - val src = extractor.getUrl(data) - if (src.isNotEmpty()) { - sources.addAll(src) - } - } + loadExtractor(link, mainUrl, callback) } - // Invoke sources - if (sources.isNotEmpty()) { - for (source in sources) { - callback.invoke(source) - //Log.i(this.name, "Result => (source) ${source.url}") - } - return true - } - } catch (e: Exception) { - e.printStackTrace() - Log.i(this.name, "Result => (e) ${e}") } - return false + return count > 0 } } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/WatchAsianProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/WatchAsianProvider.kt index 8df8444f..4c6f9b37 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/WatchAsianProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/WatchAsianProvider.kt @@ -3,6 +3,7 @@ package com.lagradost.cloudstream3.movieproviders import com.fasterxml.jackson.module.kotlin.readValue import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.extractors.* +import com.lagradost.cloudstream3.extractors.helper.AsianEmbedHelper import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.loadExtractor @@ -153,7 +154,7 @@ class WatchAsianProvider : MainAPI() { url, this.name, TvType.TvSeries, - episodeList, + episodeList.reversed(), poster, year, descript, @@ -172,16 +173,22 @@ class WatchAsianProvider : MainAPI() { val links = if (data.startsWith(mainUrl)) { getServerLinks(data) } else { data } - mapper.readValue>(links) - .forEach { item -> - var url = item.trim() - if (url.startsWith("//")) { - url = "https:$url" - } - //Log.i(this.name, "Result => (url) $url") + var count = 0 + mapper.readValue>(links).forEach { item -> + count++ + var url = item.trim() + if (url.startsWith("//")) { + url = "https:$url" + } + //Log.i(this.name, "Result => (url) $url") + if (url.startsWith("https://asianembed.io")) { + // Fetch links + AsianEmbedHelper.getUrls(url, callback) + } else { loadExtractor(url, mainUrl, callback) } - return true + } + return count > 0 } private fun getServerLinks(url: String) : String {