From b9d86b5be2d40d248fe5139e12f4fe157e67c32b Mon Sep 17 00:00:00 2001 From: no-commit <> Date: Sat, 18 Mar 2023 21:31:56 +0100 Subject: [PATCH] Fixed WatchCartoonOnline --- .../com/lagradost/KimCartoonProvider.kt | 3 +- VMoveeProvider/build.gradle.kts | 2 +- .../kotlin/com/lagradost/AsianLoadProvider.kt | 2 +- WatchCartoonOnlineProvider/build.gradle.kts | 2 +- .../lagradost/WatchCartoonOnlineProvider.kt | 255 +++++++++--------- .../WatchCartoonOnlineProviderPlugin.kt | 3 +- 6 files changed, 140 insertions(+), 127 deletions(-) diff --git a/KimCartoonProvider/src/main/kotlin/com/lagradost/KimCartoonProvider.kt b/KimCartoonProvider/src/main/kotlin/com/lagradost/KimCartoonProvider.kt index fcc2c5e..5cf7a7a 100644 --- a/KimCartoonProvider/src/main/kotlin/com/lagradost/KimCartoonProvider.kt +++ b/KimCartoonProvider/src/main/kotlin/com/lagradost/KimCartoonProvider.kt @@ -5,7 +5,6 @@ import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.loadExtractor class KimCartoonProvider : MainAPI() { - override var mainUrl = "https://kimcartoon.li" override var name = "Kim Cartoon" override val hasQuickSearch = true @@ -73,7 +72,7 @@ class KimCartoonProvider : MainAPI() { AnimeSearchResponse( it.select("span").text(), mainUrl + it.attr("href"), - mainUrl, + name, TvType.Cartoon, fixUrl(it.select("img").attr("src")) ) diff --git a/VMoveeProvider/build.gradle.kts b/VMoveeProvider/build.gradle.kts index d983a47..44f3204 100644 --- a/VMoveeProvider/build.gradle.kts +++ b/VMoveeProvider/build.gradle.kts @@ -16,7 +16,7 @@ cloudstream { * 2: Slow * 3: Beta only * */ - status = 1 // will be 3 if unspecified + status = 0 // will be 3 if unspecified tvTypes = listOf( "TvSeries", "Movie", diff --git a/VidstreamBundle/src/main/kotlin/com/lagradost/AsianLoadProvider.kt b/VidstreamBundle/src/main/kotlin/com/lagradost/AsianLoadProvider.kt index 58bafdf..317083a 100644 --- a/VidstreamBundle/src/main/kotlin/com/lagradost/AsianLoadProvider.kt +++ b/VidstreamBundle/src/main/kotlin/com/lagradost/AsianLoadProvider.kt @@ -21,5 +21,5 @@ class AsianLoadProvider : VidstreamProviderTemplate() { override val secretKey = "93422192433952489752342908585752" override val secretDecryptKey = secretKey - override val supportedTypes = setOf(TvType.AsianDrama) + override val supportedTypes = setOf(TvType.AsianDrama, TvType.TvSeries) } diff --git a/WatchCartoonOnlineProvider/build.gradle.kts b/WatchCartoonOnlineProvider/build.gradle.kts index 7d23b0a..0ec4c55 100644 --- a/WatchCartoonOnlineProvider/build.gradle.kts +++ b/WatchCartoonOnlineProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 1 +version = 2 cloudstream { diff --git a/WatchCartoonOnlineProvider/src/main/kotlin/com/lagradost/WatchCartoonOnlineProvider.kt b/WatchCartoonOnlineProvider/src/main/kotlin/com/lagradost/WatchCartoonOnlineProvider.kt index edb9086..c9dd384 100644 --- a/WatchCartoonOnlineProvider/src/main/kotlin/com/lagradost/WatchCartoonOnlineProvider.kt +++ b/WatchCartoonOnlineProvider/src/main/kotlin/com/lagradost/WatchCartoonOnlineProvider.kt @@ -2,10 +2,9 @@ package com.lagradost import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* -import com.lagradost.cloudstream3.utils.AppUtils.parseJson +import com.lagradost.cloudstream3.utils.Coroutines.mainWork import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.Qualities -import org.jsoup.Jsoup import org.mozilla.javascript.Context import org.mozilla.javascript.Scriptable import java.util.* @@ -13,7 +12,8 @@ import java.util.* class WatchCartoonOnlineProvider : MainAPI() { override var name = "WatchCartoonOnline" - override var mainUrl = "https://www.wcostream.com" + override var mainUrl = "https://www.wcostream.net" + override val hasMainPage = true override val supportedTypes = setOf( TvType.Cartoon, @@ -22,94 +22,116 @@ class WatchCartoonOnlineProvider : MainAPI() { TvType.TvSeries ) - override suspend fun search(query: String): List { - val url = "https://www.wcostream.com/search" + override suspend fun getMainPage(page: Int, request: MainPageRequest): HomePageResponse? { + val doc = app.get(mainUrl).document + val rows = doc.select("div.recent-release").mapNotNull { + val rowName = it.text() + val parent = it.parent() ?: return@mapNotNull null + val list = parent.select("ul.items > li").map { item -> + val link = item.select("a").attr("href") + val name = item.text() + newTvSeriesSearchResponse( + name, link + ) { + this.posterUrl = fixUrl(item.select("img").attr("src")) + } + } + HomePageList(rowName, list) + } + return HomePageResponse(rows, false) + } - var response = + + override suspend fun search(query: String): List { + val url = "$mainUrl/search" + + val seriesDocument = app.post( url, headers = mapOf("Referer" to url), data = mapOf("catara" to query, "konuara" to "series") - ).text - var document = Jsoup.parse(response) - var items = document.select("div#blog > div.cerceve").toList() + ).document - val returnValue = ArrayList() - - for (item in items) { - val header = item.selectFirst("> div.iccerceve") - val titleHeader = header!!.selectFirst("> div.aramadabaslik > a") + val series = seriesDocument.select("div#blog > div.cerceve").toList().mapNotNull { item -> + val header = item.selectFirst("> div.iccerceve") ?: return@mapNotNull null + val titleHeader = header.selectFirst("> div.aramadabaslik > a") val title = titleHeader!!.text() val href = fixUrl(titleHeader.attr("href")) val poster = fixUrl(header.selectFirst("> a > img")!!.attr("src")) val genreText = item.selectFirst("div.cerceve-tur-ve-genre")!!.ownText() if (genreText.contains("cartoon")) { - returnValue.add(TvSeriesSearchResponse(title, href, this.name, TvType.Cartoon, poster, null, null)) + TvSeriesSearchResponse( + title, + href, + this.name, + TvType.Cartoon, + poster, + null, + null + ) } else { val isDubbed = genreText.contains("dubbed") val set: EnumSet = EnumSet.of(if (isDubbed) DubStatus.Dubbed else DubStatus.Subbed) - returnValue.add( - AnimeSearchResponse( - title, - href, - this.name, - TvType.Anime, - poster, - null, - set, - ) + AnimeSearchResponse( + title, + href, + this.name, + TvType.Anime, + poster, + null, + set, ) } } // "episodes-search", is used for finding movies, anime episodes should be filtered out - response = + val episodesDocument = app.post( url, headers = mapOf("Referer" to url), data = mapOf("catara" to query, "konuara" to "episodes") - ).text - document = Jsoup.parse(response) - items = document.select("#catlist-listview2 > ul > li") - .filter { it -> it?.text() != null && !it.text().toString().contains("Episode") } + ).document + val items = episodesDocument.select("#catlist-listview2 > ul > li") + // Filter away episodes and blanks + .filterNot { element -> + element.text().contains("Episode") || element.text().isNullOrBlank() + } - for (item in items) { - val titleHeader = item.selectFirst("a") - val title = titleHeader!!.text() + val episodes = items.mapNotNull { item -> + val titleHeader = item.selectFirst("a") ?: return@mapNotNull null + val title = titleHeader.text() val href = fixUrl(titleHeader.attr("href")) //val isDubbed = title.contains("dubbed") //val set: EnumSet = // EnumSet.of(if (isDubbed) DubStatus.Dubbed else DubStatus.Subbed) - returnValue.add( - TvSeriesSearchResponse( - title, - href, - this.name, - TvType.AnimeMovie, - null, - null, - null, - ) + MovieSearchResponse( + title, + href, + this.name, + TvType.AnimeMovie, + null, + null, + null, ) } - return returnValue + return series + episodes } override suspend fun load(url: String): LoadResponse { - val isMovie = !url.contains("/anime/") - val response = app.get(url).text - val document = Jsoup.parse(response) + val isSeries = url.contains("/anime/") + val document = app.get(url).document - return if (!isMovie) { + return if (isSeries) { val title = document.selectFirst("td.vsbaslik > h2")!!.text() - val poster = fixUrlNull(document.selectFirst("div#cat-img-desc > div > img")?.attr("src")) + val poster = + fixUrlNull(document.selectFirst("div#cat-img-desc > div > img")?.attr("src")) val plot = document.selectFirst("div.iltext")!!.text() val genres = document.select("div#cat-genre > div.wcobtn > a").map { it.text() } val episodes = document.select("div#catlist-listview > ul > li > a").reversed().map { val text = it.text() - val match = Regex("Season ([0-9]*) Episode ([0-9]*).*? (.*)").find(text) + val match = Regex("""Season (\d*) Episode (\d*).*? (.*)""").find(text) val href = it.attr("href") if (match != null) { val last = match.groupValues[3] @@ -120,7 +142,7 @@ class WatchCartoonOnlineProvider : MainAPI() { match.groupValues[2].toIntOrNull(), ) } - val match2 = Regex("Episode ([0-9]*).*? (.*)").find(text) + val match2 = Regex("""Episode (\d*).*? (.*)""").find(text) if (match2 != null) { val last = match2.groupValues[2] return@map Episode( @@ -149,36 +171,28 @@ class WatchCartoonOnlineProvider : MainAPI() { tags = genres ) } else { - val title = document.selectFirst(".iltext .Apple-style-span")?.text().toString() - val b = document.select(".iltext b") - val description = if (b.isNotEmpty()) { - b.last()!!.html().split("
")[0] - } else null + val title = document.selectFirst("td.ilxbaslik8")?.text().toString() - TvSeriesLoadResponse( + newMovieLoadResponse( title, url, - this.name, - TvType.TvSeries, - listOf(Episode(url,title)), - null, - null, - description, - null, - null - ) + TvType.AnimeMovie, + url + ) { + plot = document.select("div.iltext").text() + .substringAfter("Episode Description:") + .substringBefore("Share:") + } } } data class LinkResponse( // @JsonProperty("cdn") // val cdn: String, - @JsonProperty("enc") - val enc: String, - @JsonProperty("hd") - val hd: String, - @JsonProperty("server") - val server: String, + @JsonProperty("enc") val enc: String, + @JsonProperty("hd") val hd: String, + @JsonProperty("fhd") val fhd: String, + @JsonProperty("server") val server: String, ) override suspend fun loadLinks( @@ -187,43 +201,54 @@ class WatchCartoonOnlineProvider : MainAPI() { subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ): Boolean { - val response = app.get(data).text - /*val embedUrl = fixUrl( - Regex("itemprop=\"embedURL\" content=\"(.*?)\"").find(response.text)?.groupValues?.get(1) ?: return false - )*/ - val start = response.indexOf("itemprop=\"embedURL") - val foundJS = Regex("").find(response, start)?.groupValues?.get(1) - ?.replace("document.write", "var returnValue = ") + val document = app.get(data).document + val foundJS = document.select("div.iltext > script").html() - val rhino = Context.enter() - rhino.initStandardObjects() - rhino.optimizationLevel = -1 - val scope: Scriptable = rhino.initStandardObjects() + // Find the variable name, eg: var HAi = ""; + val varRegex = Regex("""var (\S*)""") - val decodeBase64 = "atob = function(s) {\n" + - " var e={},i,b=0,c,x,l=0,a,r='',w=String.fromCharCode,L=s.length;\n" + - " var A=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n" + - " for(i=0;i<64;i++){e[A.charAt(i)]=i;}\n" + - " for(x=0;x=8){((a=(b>>>(l-=8))&0xff)||(x<(L-2)))&&(r+=w(a));}\n" + - " }\n" + - " return r;\n" + - "};" + val varName = varRegex.find(foundJS)?.groupValues?.get(1) + ?: throw RuntimeException("Cannot find var name!") - rhino.evaluateString(scope, decodeBase64 + foundJS, "JavaScript", 1, null) - val jsEval = scope.get("returnValue", scope) ?: return false - val src = fixUrl(Regex("src=\"(.*?)\"").find(jsEval as String)?.groupValues?.get(1) ?: return false) + val src = document.select("iframe#frameNewAnimeuploads0").attr("src") ?: mainWork { + // Rhino needs to be on main + val rhino = Context.enter() + rhino.optimizationLevel = -1 + val scope: Scriptable = rhino.initSafeStandardObjects() + + val decodeBase64 = "atob = function(s) {\n" + + " var e={},i,b=0,c,x,l=0,a,r='',w=String.fromCharCode,L=s.length;\n" + + " var A=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n" + + " for(i=0;i<64;i++){e[A.charAt(i)]=i;}\n" + + " for(x=0;x=8){((a=(b>>>(l-=8))&0xff)||(x<(L-2)))&&(r+=w(a));}\n" + + " }\n" + + " return r;\n" + + "};" + val documentJs = """ + document = { write: function () {} }; + """.trimIndent() + rhino.evaluateString(scope, documentJs + decodeBase64 + foundJS, "JavaScript", 1, null) + + val jsEval = scope.get(varName, scope)?.toString() + ?: throw RuntimeException("Cannot get the Rhino scope variable") + val url = + Regex("src=\"(.*?)\"").find(jsEval)?.groupValues?.get(1) ?: return@mainWork null + fixUrl(url) + } ?: return false val embedResponse = app.get( - (src), - headers = mapOf("Referer" to data) + src, + headers = mapOf("Referer" to src) ) val getVidLink = fixUrl( - Regex("get\\(\"(.*?)\"").find(embedResponse.text)?.groupValues?.get(1) ?: return false + Regex("getJSON\\(\"(.*?)\"").find(embedResponse.text)?.groupValues?.get(1) + ?: return false ) - val linkResponse = app.get( + + val link = app.get( getVidLink, headers = mapOf( "sec-ch-ua" to "\"Chromium\";v=\"91\", \" Not;A Brand\";v=\"99\"", "sec-ch-ua-mobile" to "?0", @@ -236,34 +261,24 @@ class WatchCartoonOnlineProvider : MainAPI() { "user-agent" to "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36", "cookie" to "countrytabs=0" ) - ) + ).parsed() - val link = parseJson(linkResponse.text) - - val hdLink = "${link.server}/getvid?evid=${link.hd}" - val sdLink = "${link.server}/getvid?evid=${link.enc}" - - if (link.hd.isNotBlank()) + fun loadLink(server: String, link: String?, quality: Qualities) { + if (link.isNullOrBlank()) return callback.invoke( ExtractorLink( this.name, - this.name + " HD", - hdLink, - "", - Qualities.P720.value - ) - ) - - if (link.enc.isNotBlank()) - callback.invoke( - ExtractorLink( this.name, - this.name + " SD", - sdLink, + "${server}/getvid?evid=${link}", "", - Qualities.P480.value + quality.value ) ) + } + + loadLink(link.server, link.hd, Qualities.P720) + loadLink(link.server, link.enc, Qualities.P480) + loadLink(link.server, link.fhd, Qualities.P1080) return true } diff --git a/WatchCartoonOnlineProvider/src/main/kotlin/com/lagradost/WatchCartoonOnlineProviderPlugin.kt b/WatchCartoonOnlineProvider/src/main/kotlin/com/lagradost/WatchCartoonOnlineProviderPlugin.kt index 60d5758..d17403c 100644 --- a/WatchCartoonOnlineProvider/src/main/kotlin/com/lagradost/WatchCartoonOnlineProviderPlugin.kt +++ b/WatchCartoonOnlineProvider/src/main/kotlin/com/lagradost/WatchCartoonOnlineProviderPlugin.kt @@ -1,4 +1,3 @@ - package com.lagradost import com.lagradost.cloudstream3.plugins.CloudstreamPlugin @@ -6,7 +5,7 @@ import com.lagradost.cloudstream3.plugins.Plugin import android.content.Context @CloudstreamPlugin -class WatchCartoonOnlineProviderPlugin: Plugin() { +class WatchCartoonOnlineProviderPlugin : Plugin() { override fun load(context: Context) { // All providers should be added in this manner. Please don't edit the providers list directly. registerMainAPI(WatchCartoonOnlineProvider())