From a0ad101605b6900a557f1d130046b10a22aa0878 Mon Sep 17 00:00:00 2001 From: LagradOst Date: Sat, 14 Aug 2021 19:31:27 +0200 Subject: [PATCH] WatchCartoonOnlineProvider --- app/build.gradle | 3 + .../com/lagradost/cloudstream3/MainAPI.kt | 33 ++- .../animeproviders/DubbedAnimeProvider.kt | 6 + .../animeproviders/ShiroProvider.kt | 2 +- .../animeproviders/TenshiProvider.kt | 35 ++- .../WatchCartoonOnlineProvider.kt | 224 ++++++++++++++++++ .../animeproviders/WcoProvider.kt | 7 + .../movieproviders/HDMProvider.kt | 5 + .../movieproviders/LookMovieProvider.kt | 6 + .../movieproviders/TrailersToProvider.kt | 6 + .../movieproviders/VMoveeProvider.kt | 5 + .../ui/home/HomeChildItemAdapter.kt | 1 + .../cloudstream3/ui/player/PlayerFragment.kt | 17 +- .../cloudstream3/ui/result/ResultFragment.kt | 11 +- .../cloudstream3/ui/result/ResultViewModel.kt | 12 +- .../cloudstream3/ui/search/SearchAdaptor.kt | 2 +- .../utils/VideoDownloadManager.kt | 14 +- app/src/main/res/layout/fragment_player.xml | 6 +- 18 files changed, 354 insertions(+), 41 deletions(-) create mode 100644 app/src/main/java/com/lagradost/cloudstream3/animeproviders/WatchCartoonOnlineProvider.kt diff --git a/app/build.gradle b/app/build.gradle index cf761fd4..6a90f835 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -94,4 +94,7 @@ dependencies { // subtitle color picker implementation 'com.jaredrummler:colorpicker:1.1.0' + + //run JS + implementation 'org.mozilla:rhino:1.7R4' } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt index e384fa9d..110c4b13 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt @@ -6,17 +6,18 @@ import com.fasterxml.jackson.databind.DeserializationFeature import com.fasterxml.jackson.databind.json.JsonMapper import com.fasterxml.jackson.module.kotlin.KotlinModule import com.lagradost.cloudstream3.animeproviders.DubbedAnimeProvider -import com.lagradost.cloudstream3.animeproviders.ShiroProvider import com.lagradost.cloudstream3.animeproviders.TenshiProvider +import com.lagradost.cloudstream3.animeproviders.WatchCartoonOnlineProvider import com.lagradost.cloudstream3.animeproviders.WcoProvider import com.lagradost.cloudstream3.movieproviders.HDMProvider -import com.lagradost.cloudstream3.movieproviders.MeloMovieProvider import com.lagradost.cloudstream3.movieproviders.TrailersToProvider import com.lagradost.cloudstream3.movieproviders.VMoveeProvider import com.lagradost.cloudstream3.utils.ExtractorLink import java.util.* -const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0" + +const val USER_AGENT = + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" val baseHeader = mapOf("User-Agent" to USER_AGENT) val mapper = JsonMapper.builder().addModule(KotlinModule()) .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false).build()!! @@ -37,6 +38,7 @@ object APIHolder { HDMProvider(), //LookMovieProvider(), // RECAPTCHA (Please allow up to 5 seconds...) VMoveeProvider(), + WatchCartoonOnlineProvider(), ) fun getApiFromName(apiName: String?): MainAPI { @@ -86,6 +88,14 @@ abstract class MainAPI { open val hasMainPage = false open val hasQuickSearch = false + open val supportedTypes = setOf( + TvType.Movie, + TvType.TvSeries, + TvType.Cartoon, + TvType.Anime, + TvType.ONA + ) + open fun getMainPage(): HomePageResponse? { return null } @@ -177,6 +187,7 @@ enum class DubStatus { enum class TvType { Movie, TvSeries, + Cartoon, Anime, ONA, } @@ -255,7 +266,7 @@ interface LoadResponse { val year: Int? val plot: String? val rating: Int? // 0-100 - val tags: ArrayList? + val tags: List? val duration: String? val trailerUrl: String? } @@ -290,13 +301,13 @@ data class AnimeLoadResponse( override val posterUrl: String?, override val year: Int?, - val dubEpisodes: ArrayList?, - val subEpisodes: ArrayList?, + val dubEpisodes: List?, + val subEpisodes: List?, val showStatus: ShowStatus?, override val plot: String?, - override val tags: ArrayList? = null, - val synonyms: ArrayList? = null, + override val tags: List? = null, + val synonyms: List? = null, val malId: Int? = null, val anilistId: Int? = null, @@ -318,7 +329,7 @@ data class MovieLoadResponse( val imdbId: String?, override val rating: Int? = null, - override val tags: ArrayList? = null, + override val tags: List? = null, override val duration: String? = null, override val trailerUrl: String? = null, ) : LoadResponse @@ -339,7 +350,7 @@ data class TvSeriesLoadResponse( override val url: String, override val apiName: String, override val type: TvType, - val episodes: ArrayList, + val episodes: List, override val posterUrl: String?, override val year: Int?, @@ -348,7 +359,7 @@ data class TvSeriesLoadResponse( val showStatus: ShowStatus?, val imdbId: String?, override val rating: Int? = null, - override val tags: ArrayList? = null, + override val tags: List? = null, override val duration: String? = null, override val trailerUrl: String? = null, ) : LoadResponse diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/DubbedAnimeProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/DubbedAnimeProvider.kt index c8a13424..2b14968b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/DubbedAnimeProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/DubbedAnimeProvider.kt @@ -18,6 +18,12 @@ class DubbedAnimeProvider : MainAPI() { override val hasQuickSearch: Boolean get() = true + override val supportedTypes: Set + get() = setOf( + TvType.Movie, + TvType.Anime, + ) + data class QueryEpisodeResultRoot( @JsonProperty("result") val result: QueryEpisodeResult, diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ShiroProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ShiroProvider.kt index 9bf96c27..457a68f4 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ShiroProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/ShiroProvider.kt @@ -160,7 +160,7 @@ class ShiroProvider : MainAPI() { val set: EnumSet = EnumSet.of(if (isDubbed) DubStatus.Dubbed else DubStatus.Subbed) - val episodeCount = data.episodeCount?.toIntOrNull() + val episodeCount = data.episodeCount.toIntOrNull() return@map AnimeSearchResponse( data.name.replace("Dubbed", ""), // i.english ?: i.canonicalTitle, diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/TenshiProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/TenshiProvider.kt index e16f54b7..83ea1ae9 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/TenshiProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/TenshiProvider.kt @@ -29,6 +29,9 @@ class TenshiProvider : MainAPI() { override val hasQuickSearch: Boolean get() = false + override val supportedTypes: Set + get() = setOf(TvType.Anime, TvType.Movie, TvType.ONA) + private fun autoLoadToken(): Boolean { if (token != null) return true return loadToken() @@ -91,7 +94,11 @@ class TenshiProvider : MainAPI() { private fun dateParser(dateString: String): String? { val format = SimpleDateFormat("dd 'of' MMM',' yyyy") val newFormat = SimpleDateFormat("dd-MM-yyyy") - return newFormat.format(format.parse(dateString.replace("th ", " ").replace("st ", " ").replace("nd ", " ").replace("rd ", " "))) + return newFormat.format( + format.parse( + dateString.replace("th ", " ").replace("st ", " ").replace("nd ", " ").replace("rd ", " ") + ) + ) } // data class TenshiSearchResponse( @@ -147,14 +154,14 @@ class TenshiProvider : MainAPI() { override fun search(query: String): ArrayList { val url = "$mainUrl/anime" - var response = khttp.get(url, params=mapOf("q" to query), cookies=mapOf("loop-view" to "thumb")) + var response = khttp.get(url, params = mapOf("q" to query), cookies = mapOf("loop-view" to "thumb")) var document = Jsoup.parse(response.text) val returnValue = parseSearchPage(document) while (!document.select("""a.page-link[rel="next"]""").isEmpty()) { val link = document.select("""a.page-link[rel="next"]""") if (link != null && !link.isEmpty()) { - response = khttp.get(link[0].attr("href"), cookies=mapOf("loop-view" to "thumb")) + response = khttp.get(link[0].attr("href"), cookies = mapOf("loop-view" to "thumb")) document = Jsoup.parse(response.text) returnValue.addAll(parseSearchPage(document)) } else { @@ -166,7 +173,7 @@ class TenshiProvider : MainAPI() { } override fun load(url: String): LoadResponse { - val response = khttp.get(url, timeout = 120.0, cookies=mapOf("loop-view" to "thumb")) + val response = khttp.get(url, timeout = 120.0, cookies = mapOf("loop-view" to "thumb")) val document = Jsoup.parse(response.text) val englishTitle = document.selectFirst("span.value > span[title=\"English\"]")?.parent()?.text()?.trim() @@ -177,13 +184,14 @@ class TenshiProvider : MainAPI() { val episodes = ArrayList(episodeNodes?.map { AnimeEpisode( - it.attr("href"), - it.selectFirst(".episode-title")?.text()?.trim(), - it.selectFirst("img")?.attr("src"), - dateParser(it.selectFirst(".episode-date").text().trim()).toString(), - null, - it.attr("data-content").trim(), - ) } + it.attr("href"), + it.selectFirst(".episode-title")?.text()?.trim(), + it.selectFirst("img")?.attr("src"), + dateParser(it.selectFirst(".episode-date").text().trim()).toString(), + null, + it.attr("data-content").trim(), + ) + } ?: ArrayList()) val status = when (document.selectFirst("li.status > .value")?.text()?.trim()) { "Ongoing" -> ShowStatus.Ongoing @@ -200,7 +208,8 @@ class TenshiProvider : MainAPI() { val synopsis = document.selectFirst(".entry-description > .card-body")?.text()?.trim() val genre = document.select("li.genre.meta-data > span.value").map { it?.text()?.trim().toString() } - val synonyms = document.select("li.synonym.meta-data > div.info-box > span.value").map { it?.text()?.trim().toString() } + val synonyms = + document.select("li.synonym.meta-data > div.info-box > span.value").map { it?.text()?.trim().toString() } return AnimeLoadResponse( englishTitle, @@ -231,7 +240,7 @@ class TenshiProvider : MainAPI() { ): Boolean { val response = khttp.get(data) val src = Jsoup.parse(response.text).selectFirst(".embed-responsive > iframe").attr("src") - val mp4moe = Jsoup.parse(khttp.get(src, headers=mapOf("Referer" to data)).text).selectFirst("video#player") + val mp4moe = Jsoup.parse(khttp.get(src, headers = mapOf("Referer" to data)).text).selectFirst("video#player") val sources = mp4moe.select("source").map { ExtractorLink( diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/WatchCartoonOnlineProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/WatchCartoonOnlineProvider.kt new file mode 100644 index 00000000..be39e7d2 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/WatchCartoonOnlineProvider.kt @@ -0,0 +1,224 @@ +package com.lagradost.cloudstream3.animeproviders + +import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.module.kotlin.readValue +import com.lagradost.cloudstream3.* +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.* + + +class WatchCartoonOnlineProvider : MainAPI() { + override val name: String + get() = "WatchCartoonOnline" + override val mainUrl: String + get() = "https://www.wcostream.com" + + override val supportedTypes: Set + get() = setOf( + TvType.Cartoon, + TvType.Anime, + ) + + override fun search(query: String): ArrayList? { + val url = "https://www.wcostream.com/search" + + val response = + khttp.post( + url, + headers = mapOf("Referer" to url), + data = mapOf("catara" to query, "konuara" to "series") + ) + val document = Jsoup.parse(response.text) + val items = document.select("div#blog > div.cerceve") + if (items.isNullOrEmpty()) return ArrayList() + val returnValue = ArrayList() + + for (item in items) { + val header = item.selectFirst("> div.iccerceve") + 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)) + } 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, + null, + set, + null, + null + ) + ) + } + } + return returnValue + } + + override fun load(url: String): LoadResponse? { + val response = khttp.get(url) + val document = Jsoup.parse(response.text) + + val title = document.selectFirst("td.vsbaslik > h2").text() + val poster = fixUrl(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 href = it.attr("href") + if (match != null) { + val last = match.groupValues[3] + return@map TvSeriesEpisode( + if (last.startsWith("English")) null else last, + match.groupValues[1].toIntOrNull(), + match.groupValues[2].toIntOrNull(), + href + ) + } + val match2 = Regex("Episode ([0-9]*).*? (.*)").find(text) + if (match2 != null) { + val last = match2.groupValues[2] + return@map TvSeriesEpisode( + if (last.startsWith("English")) null else last, + null, + match2.groupValues[1].toIntOrNull(), + href + ) + } + return@map TvSeriesEpisode( + text, + null, + null, + href + ) + } + + return TvSeriesLoadResponse( + title, + url, + this.name, + TvType.TvSeries, + episodes, + poster, + null, + plot, + null, + null, + tags = genres + ) + } + + data class LinkResponse( + // @JsonProperty("cdn") + // val cdn: String, + @JsonProperty("enc") + val enc: String, + @JsonProperty("hd") + val hd: String, + @JsonProperty("server") + val server: String, + ) + + override fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + val response = khttp.get(data) + /*val embedUrl = fixUrl( + Regex("itemprop=\"embedURL\" content=\"(.*?)\"").find(response.text)?.groupValues?.get(1) ?: return false + )*/ + val text = response.text + val start = text.indexOf("itemprop=\"embedURL") + val foundJS = Regex("").find(text, start)?.groupValues?.get(1) + ?.replace("document.write", "var returnValue = ") + println("JS: $foundJS") + val rhino = Context.enter() + rhino.initStandardObjects() + rhino.optimizationLevel = -1 + val scope: Scriptable = rhino.initStandardObjects() + + 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" + + "};" + + 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 embedResponse = khttp.get( + (src), + headers = mapOf("Referer" to data) + ) + + val getVidLink = fixUrl( + Regex("get\\(\"(.*?)\"").find(embedResponse.text)?.groupValues?.get(1) ?: return false + ) + val linkResponse = khttp.get( + getVidLink, headers = mapOf( + "sec-ch-ua" to "\"Chromium\";v=\"91\", \" Not;A Brand\";v=\"99\"", + "sec-ch-ua-mobile" to "?0", + "sec-fetch-dest" to "empty", + "sec-fetch-mode" to "cors", + "sec-fetch-site" to "same-origin", + "accept" to "*/*", + "x-requested-with" to "XMLHttpRequest", + "referer" to src.replace(" ", "%20"), + "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" + ) + ) + println("LINK:" + linkResponse.text) + val link = mapper.readValue(linkResponse.text) + + val hdLink = "${link.server}/getvid?evid=${link.hd}" + val sdLink = "${link.server}/getvid?evid=${link.enc}" + + if (link.hd.isNotBlank()) + callback.invoke( + ExtractorLink( + this.name, + this.name + " HD", + hdLink, + "", + Qualities.HD.value + ) + ) + + if (link.enc.isNotBlank()) + callback.invoke( + ExtractorLink( + this.name, + this.name + " SD", + sdLink, + "", + Qualities.SD.value + ) + ) + + return true + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/WcoProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/WcoProvider.kt index 361a342d..a686eaec 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/WcoProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/WcoProvider.kt @@ -27,6 +27,13 @@ class WcoProvider : MainAPI() { override val hasMainPage: Boolean get() = true + override val supportedTypes: Set + get() = setOf( + TvType.Movie, + TvType.Anime, + TvType.ONA + ) + override fun getMainPage(): HomePageResponse? { val urls = listOf( Pair("$mainUrl/ajax/list/recently_updated?type=tv", "Recently Updated Anime"), diff --git a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/HDMProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/HDMProvider.kt index 71595185..08d62553 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/HDMProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/HDMProvider.kt @@ -13,6 +13,11 @@ class HDMProvider : MainAPI() { override val hasDownloadSupport: Boolean get() = false + override val supportedTypes: Set + get() = setOf( + TvType.Movie, + ) + override fun search(query: String): ArrayList { val url = "$mainUrl/search/$query" val response = khttp.get(url) diff --git a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/LookMovieProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/LookMovieProvider.kt index e9cf854a..15ecdfe6 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/LookMovieProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/LookMovieProvider.kt @@ -20,6 +20,12 @@ class LookMovieProvider : MainAPI() { override val mainUrl: String get() = "https://lookmovie.io" + override val supportedTypes: Set + get() = setOf( + TvType.Movie, + TvType.TvSeries, + ) + data class LookMovieSearchResult( @JsonProperty("backdrop") val backdrop: String?, @JsonProperty("imdb_rating") val imdb_rating: String, diff --git a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/TrailersToProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/TrailersToProvider.kt index 9378d283..e5ecf411 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/TrailersToProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/TrailersToProvider.kt @@ -23,6 +23,12 @@ class TrailersToProvider : MainAPI() { override val hasChromecastSupport: Boolean get() = false + override val supportedTypes: Set + get() = setOf( + TvType.Movie, + TvType.TvSeries, + ) + override fun getMainPage(): HomePageResponse? { val response = khttp.get(mainUrl) val document = Jsoup.parse(response.text) diff --git a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/VMoveeProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/VMoveeProvider.kt index fdbe8126..ed4a2cf8 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/VMoveeProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/VMoveeProvider.kt @@ -14,6 +14,11 @@ class VMoveeProvider : MainAPI() { override val mainUrl: String get() = "https://www.vmovee.watch" + override val supportedTypes: Set + get() = setOf( + TvType.Movie, + ) + override fun search(query: String): ArrayList? { val url = "$mainUrl/?s=$query" val response = khttp.get(url) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeChildItemAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeChildItemAdapter.kt index 5714f488..9ad3b467 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeChildItemAdapter.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeChildItemAdapter.kt @@ -61,6 +61,7 @@ class HomeChildItemAdapter( TvType.Movie -> "Movie" TvType.ONA -> "ONA" TvType.TvSeries -> "TV" + TvType.Cartoon -> "Cartoon" } // search_result_lang?.visibility = View.GONE diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt index 6848abeb..3d281a5d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerFragment.kt @@ -796,7 +796,7 @@ class PlayerFragment : Fragment() { } //endregion - private fun onSubStyleChanged(style : SaveCaptionStyle) { + private fun onSubStyleChanged(style: SaveCaptionStyle) { context?.let { ctx -> subStyle = style subView?.setStyle(ctx.fromSaveToStyle(style)) @@ -1131,7 +1131,7 @@ class PlayerFragment : Fragment() { val speedsNumbers = listOf(0.5f, 0.75f, 1f, 1.25f, 1.5f, 1.75f, 2f) val speedIndex = speedsNumbers.indexOf(playbackSpeed) - context?.showDialog(speedsText,speedIndex,"Player Speed", false, { + context?.showDialog(speedsText, speedIndex, "Player Speed", false, { activity?.hideSystemUI() }) { index -> playbackSpeed = speedsNumbers[index] @@ -1541,8 +1541,19 @@ class PlayerFragment : Fragment() { /*FastAniApi.currentHeaders?.forEach { dataSource.setRequestProperty(it.key, it.value) }*/ - if (currentUrl != null) + if (currentUrl != null) { dataSource.setRequestProperty("Referer", currentUrl.referer) + // extra stuff + dataSource.setRequestProperty( + "sec-ch-ua", + "\"Chromium\";v=\"91\", \" Not;A Brand\";v=\"99\"" + ) + dataSource.setRequestProperty("sec-ch-ua-mobile", "?0") + // dataSource.setRequestProperty("Sec-Fetch-Site", "none") //same-site + dataSource.setRequestProperty("Sec-Fetch-User", "?1") + dataSource.setRequestProperty("Sec-Fetch-Mode", "navigate") + dataSource.setRequestProperty("Sec-Fetch-Dest", "document") + } dataSource } else { DefaultDataSourceFactory(requireContext(), USER_AGENT).createDataSource() diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt index cb14d20e..327142a7 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultFragment.kt @@ -238,14 +238,14 @@ class ResultFragment : Fragment() { var startAction: Int? = null private fun lateFixDownloadButton(show: Boolean) { - if (show) { - result_movie_parent.visibility = VISIBLE - result_episodes_text.visibility = GONE - result_episodes.visibility = GONE - } else { + if(!show || currentType?.isMovieType() == true) { result_movie_parent.visibility = GONE result_episodes_text.visibility = VISIBLE result_episodes.visibility = VISIBLE + } else { + result_movie_parent.visibility = VISIBLE + result_episodes_text.visibility = GONE + result_episodes.visibility = GONE } } @@ -430,6 +430,7 @@ class ResultFragment : Fragment() { TvType.Movie -> "Movies" TvType.TvSeries -> "TVSeries/$titleName" TvType.ONA -> "ONA" + TvType.Cartoon -> "Cartoons/$titleName" else -> null } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt index 88d61e40..46cedc33 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/result/ResultViewModel.kt @@ -119,7 +119,6 @@ class ResultViewModel : ViewModel() { rangeList.add("${i + 1}-${currentList.size}") } } - _rangeOptions.postValue(rangeList) val cRange = range ?: if (selection != null) { 0 @@ -133,14 +132,19 @@ class ResultViewModel : ViewModel() { cRange } - selectedRangeInt.postValue(realRange) - selectedRange.postValue(rangeList[realRange]) - if (currentList.size > EPISODE_RANGE_OVERLOAD) { currentList = currentList.subList( realRange * EPISODE_RANGE_SIZE, minOf(currentList.size, (realRange + 1) * EPISODE_RANGE_SIZE) ) + _rangeOptions.postValue(rangeList) + selectedRangeInt.postValue(realRange) + selectedRange.postValue(rangeList[realRange]) + } else { + val allRange ="1-${currentList.size}" + _rangeOptions.postValue(listOf(allRange)) + selectedRangeInt.postValue(0) + selectedRange.postValue(allRange) } _publicEpisodes.postValue(currentList) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchAdaptor.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchAdaptor.kt index 3dda63f6..b02504ae 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchAdaptor.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/search/SearchAdaptor.kt @@ -50,7 +50,6 @@ class SearchAdapter( is CardViewHolder -> { holder.bind(cardList[position]) } - } } @@ -94,6 +93,7 @@ class SearchAdapter( TvType.Movie -> "Movie" TvType.ONA -> "ONA" TvType.TvSeries -> "TV" + TvType.Cartoon -> "Cartoon" } // search_result_lang?.visibility = View.GONE diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt index 3a03c9c3..f1a9cc5f 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/VideoDownloadManager.kt @@ -47,7 +47,7 @@ object VideoDownloadManager { private var currentDownloads = mutableListOf() private const val USER_AGENT = - "Mozilla/5.0 (Windows NT 10.0; rv:68.0) Gecko/20100101 Firefox/68.0" + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36" @DrawableRes const val imgDone = R.drawable.rddone @@ -511,6 +511,18 @@ object VideoDownloadManager { connection.setRequestProperty("Accept-Encoding", "identity") connection.setRequestProperty("User-Agent", USER_AGENT) if (link.referer.isNotEmpty()) connection.setRequestProperty("Referer", link.referer) + + // extra stuff + connection.setRequestProperty( + "sec-ch-ua", + "\"Chromium\";v=\"91\", \" Not;A Brand\";v=\"99\"" + ) + connection.setRequestProperty("sec-ch-ua-mobile", "?0") + // dataSource.setRequestProperty("Sec-Fetch-Site", "none") //same-site + connection.setRequestProperty("Sec-Fetch-User", "?1") + connection.setRequestProperty("Sec-Fetch-Mode", "navigate") + connection.setRequestProperty("Sec-Fetch-Dest", "document") + if (resume) connection.setRequestProperty("Range", "bytes=${fileLength}-") val resumeLength = (if (resume) fileLength else 0) diff --git a/app/src/main/res/layout/fragment_player.xml b/app/src/main/res/layout/fragment_player.xml index fdc742b8..8667305c 100644 --- a/app/src/main/res/layout/fragment_player.xml +++ b/app/src/main/res/layout/fragment_player.xml @@ -11,6 +11,9 @@ android:screenOrientation="userLandscape" app:surface_type="texture_view" > +