mirror of
				https://github.com/recloudstream/cloudstream.git
				synced 2024-08-15 01:53:11 +00:00 
			
		
		
		
	WatchCartoonOnlineProvider
This commit is contained in:
		
							parent
							
								
									2839d59a28
								
							
						
					
					
						commit
						a0ad101605
					
				
					 18 changed files with 354 additions and 41 deletions
				
			
		|  | @ -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<String>? | ||||
|     val tags: List<String>? | ||||
|     val duration: String? | ||||
|     val trailerUrl: String? | ||||
| } | ||||
|  | @ -290,13 +301,13 @@ data class AnimeLoadResponse( | |||
|     override val posterUrl: String?, | ||||
|     override val year: Int?, | ||||
| 
 | ||||
|     val dubEpisodes: ArrayList<AnimeEpisode>?, | ||||
|     val subEpisodes: ArrayList<AnimeEpisode>?, | ||||
|     val dubEpisodes: List<AnimeEpisode>?, | ||||
|     val subEpisodes: List<AnimeEpisode>?, | ||||
|     val showStatus: ShowStatus?, | ||||
| 
 | ||||
|     override val plot: String?, | ||||
|     override val tags: ArrayList<String>? = null, | ||||
|     val synonyms: ArrayList<String>? = null, | ||||
|     override val tags: List<String>? = null, | ||||
|     val synonyms: List<String>? = 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<String>? = null, | ||||
|     override val tags: List<String>? = 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<TvSeriesEpisode>, | ||||
|     val episodes: List<TvSeriesEpisode>, | ||||
| 
 | ||||
|     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<String>? = null, | ||||
|     override val tags: List<String>? = null, | ||||
|     override val duration: String? = null, | ||||
|     override val trailerUrl: String? = null, | ||||
| ) : LoadResponse | ||||
|  |  | |||
|  | @ -18,6 +18,12 @@ class DubbedAnimeProvider : MainAPI() { | |||
|     override val hasQuickSearch: Boolean | ||||
|         get() = true | ||||
| 
 | ||||
|     override val supportedTypes: Set<TvType> | ||||
|         get() = setOf( | ||||
|             TvType.Movie, | ||||
|             TvType.Anime, | ||||
|         ) | ||||
| 
 | ||||
|     data class QueryEpisodeResultRoot( | ||||
|         @JsonProperty("result") | ||||
|         val result: QueryEpisodeResult, | ||||
|  |  | |||
|  | @ -160,7 +160,7 @@ class ShiroProvider : MainAPI() { | |||
|             val set: EnumSet<DubStatus> = | ||||
|                 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, | ||||
|  |  | |||
|  | @ -29,6 +29,9 @@ class TenshiProvider : MainAPI() { | |||
|     override val hasQuickSearch: Boolean | ||||
|         get() = false | ||||
| 
 | ||||
|     override val supportedTypes: Set<TvType> | ||||
|         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<SearchResponse> { | ||||
|         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<AnimeEpisode>(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<AnimeEpisode>()) | ||||
|         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( | ||||
|  |  | |||
|  | @ -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<TvType> | ||||
|         get() = setOf( | ||||
|             TvType.Cartoon, | ||||
|             TvType.Anime, | ||||
|         ) | ||||
| 
 | ||||
|     override fun search(query: String): ArrayList<SearchResponse>? { | ||||
|         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<SearchResponse>() | ||||
| 
 | ||||
|         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<DubStatus> = | ||||
|                     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("<script>(.*?)</script>").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<L;x++){\n" + | ||||
|                 "        c=e[s.charAt(x)];b=(b<<6)+c;l+=6;\n" + | ||||
|                 "        while(l>=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>(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 | ||||
|     } | ||||
| } | ||||
|  | @ -27,6 +27,13 @@ class WcoProvider : MainAPI() { | |||
|     override val hasMainPage: Boolean | ||||
|         get() = true | ||||
| 
 | ||||
|     override val supportedTypes: Set<TvType> | ||||
|         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"), | ||||
|  |  | |||
|  | @ -13,6 +13,11 @@ class HDMProvider : MainAPI() { | |||
|     override val hasDownloadSupport: Boolean | ||||
|         get() = false | ||||
| 
 | ||||
|     override val supportedTypes: Set<TvType> | ||||
|         get() = setOf( | ||||
|             TvType.Movie, | ||||
|         ) | ||||
| 
 | ||||
|     override fun search(query: String): ArrayList<SearchResponse> { | ||||
|         val url = "$mainUrl/search/$query" | ||||
|         val response = khttp.get(url) | ||||
|  |  | |||
|  | @ -20,6 +20,12 @@ class LookMovieProvider : MainAPI() { | |||
|     override val mainUrl: String | ||||
|         get() = "https://lookmovie.io" | ||||
| 
 | ||||
|     override val supportedTypes: Set<TvType> | ||||
|         get() = setOf( | ||||
|             TvType.Movie, | ||||
|             TvType.TvSeries, | ||||
|         ) | ||||
| 
 | ||||
|     data class LookMovieSearchResult( | ||||
|         @JsonProperty("backdrop") val backdrop: String?, | ||||
|         @JsonProperty("imdb_rating") val imdb_rating: String, | ||||
|  |  | |||
|  | @ -23,6 +23,12 @@ class TrailersToProvider : MainAPI() { | |||
|     override val hasChromecastSupport: Boolean | ||||
|         get() = false | ||||
| 
 | ||||
|     override val supportedTypes: Set<TvType> | ||||
|         get() = setOf( | ||||
|             TvType.Movie, | ||||
|             TvType.TvSeries, | ||||
|         ) | ||||
| 
 | ||||
|     override fun getMainPage(): HomePageResponse? { | ||||
|         val response = khttp.get(mainUrl) | ||||
|         val document = Jsoup.parse(response.text) | ||||
|  |  | |||
|  | @ -14,6 +14,11 @@ class VMoveeProvider : MainAPI() { | |||
|     override val mainUrl: String | ||||
|         get() = "https://www.vmovee.watch" | ||||
| 
 | ||||
|     override val supportedTypes: Set<TvType> | ||||
|         get() = setOf( | ||||
|             TvType.Movie, | ||||
|         ) | ||||
| 
 | ||||
|     override fun search(query: String): ArrayList<SearchResponse>? { | ||||
|         val url = "$mainUrl/?s=$query" | ||||
|         val response = khttp.get(url) | ||||
|  |  | |||
|  | @ -61,6 +61,7 @@ class HomeChildItemAdapter( | |||
|                 TvType.Movie -> "Movie" | ||||
|                 TvType.ONA -> "ONA" | ||||
|                 TvType.TvSeries -> "TV" | ||||
|                 TvType.Cartoon -> "Cartoon" | ||||
|             } | ||||
|             // search_result_lang?.visibility = View.GONE | ||||
| 
 | ||||
|  |  | |||
|  | @ -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() | ||||
|  |  | |||
|  | @ -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 | ||||
|                 } | ||||
| 
 | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -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 | ||||
| 
 | ||||
|  |  | |||
|  | @ -47,7 +47,7 @@ object VideoDownloadManager { | |||
|     private var currentDownloads = mutableListOf<Int>() | ||||
| 
 | ||||
|     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) | ||||
|  |  | |||
|  | @ -11,6 +11,9 @@ | |||
|         android:screenOrientation="userLandscape" | ||||
|         app:surface_type="texture_view" | ||||
| > | ||||
|     <!-- | ||||
|           app:fastforward_increment="10000" | ||||
|             app:rewind_increment="10000"--> | ||||
|     <com.google.android.exoplayer2.ui.PlayerView | ||||
|             android:id="@+id/player_view" | ||||
|             app:show_timeout="0" | ||||
|  | @ -18,8 +21,7 @@ | |||
|             app:auto_show="true" | ||||
|             android:layout_width="match_parent" | ||||
|             android:layout_height="match_parent" | ||||
|             app:fastforward_increment="10000" | ||||
|             app:rewind_increment="10000" | ||||
| 
 | ||||
|             app:layout_constraintBottom_toBottomOf="parent" | ||||
|             app:layout_constraintEnd_toEndOf="parent" | ||||
|             app:layout_constraintStart_toStartOf="parent" | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue