diff --git a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt index 37cf64de..4feef790 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/MainAPI.kt @@ -100,6 +100,7 @@ object APIHolder { OpenVidsProvider(), IdlixProvider(), MultiplexProvider(), + VidSrcProvider(), // Metadata providers //TmdbProvider(), diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/GogoanimeProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/GogoanimeProvider.kt index e57df76b..e3118d35 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/GogoanimeProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/GogoanimeProvider.kt @@ -92,7 +92,9 @@ class GogoanimeProvider : MainAPI() { secretDecryptKey: String?, // This could be removed, but i prefer it verbose isUsingAdaptiveKeys: Boolean, - isUsingAdaptiveData: Boolean + isUsingAdaptiveData: Boolean, + // If you don't want to re-fetch the document + iframeDocument: Document? = null ) = safeApiCall { // https://github.com/saikou-app/saikou/blob/3e756bd8e876ad7a9318b17110526880525a5cd3/app/src/main/java/ani/saikou/anime/source/extractors/GogoCDN.kt // No Licence on the following code @@ -104,9 +106,9 @@ class GogoanimeProvider : MainAPI() { val id = Regex("id=([^&]+)").find(iframeUrl)!!.value.removePrefix("id=") - var document: Document? = null + var document: Document? = iframeDocument val foundIv = - iv ?: app.get(iframeUrl).document.also { document = it } + iv ?: (document ?: app.get(iframeUrl).document.also { document = it }) .select("""div.wrapper[class*=container]""") .attr("class").split("-").lastOrNull() ?: return@safeApiCall val foundKey = secretKey ?: getKey(base64Decode(id) + foundIv) ?: return@safeApiCall diff --git a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/MonoschinosProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/MonoschinosProvider.kt index e06d2e66..2548bb8b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/animeproviders/MonoschinosProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/animeproviders/MonoschinosProvider.kt @@ -50,12 +50,12 @@ class MonoschinosProvider : MainAPI() { HomePageList( "Capítulos actualizados", app.get(mainUrl, timeout = 120).document.select(".col-6").map { - val title = it.selectFirst("p.animetitles")!!.text() + val title = it.selectFirst("p.animetitles")?.text() ?: it.selectFirst(".animetitles")?.text() ?: "" val poster = it.selectFirst(".animeimghv")!!.attr("data-src") val epRegex = Regex("episodio-(\\d+)") val url = it.selectFirst("a")?.attr("href")!!.replace("ver/", "anime/") .replace(epRegex, "sub-espanol") - val epNum = it.selectFirst(".positioning h5")?.text()?.toIntOrNull() + val epNum = (it.selectFirst(".positioning h5")?.text() ?: it.selectFirst("div.positioning p")?.text())?.toIntOrNull() newAnimeSearchResponse(title, url) { this.posterUrl = fixUrl(poster) addDubStatus(getDubStatus(title), epNum) 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 dc7b1d9f..2e0565bf 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/DramaSeeProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/DramaSeeProvider.kt @@ -1,11 +1,7 @@ package com.lagradost.cloudstream3.movieproviders -import com.fasterxml.jackson.module.kotlin.readValue import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.animeproviders.GogoanimeProvider.Companion.extractVidstream -import com.lagradost.cloudstream3.extractors.XStreamCdn -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 @@ -19,25 +15,23 @@ class DramaSeeProvider : MainAPI() { override val supportedTypes = setOf(TvType.AsianDrama) override suspend fun getMainPage(): HomePageResponse { - val headers = mapOf("X-Requested-By" to "dramasee.net") + val headers = mapOf("X-Requested-By" to mainUrl) val document = app.get(mainUrl, headers = headers).document val mainbody = document.getElementsByTag("body") return HomePageResponse( - mainbody?.select("section")?.map { row -> - val main = row?.select("main") ?: return@map null - val title = main.select("div.title > div > h2")?.text() ?: "Main" - val inner = main.select("li.series-item") ?: return@map null + mainbody.select("section.block_area.block_area_home")?.map { main -> + val title = main.select("h2.cat-heading").text() ?: "Main" + val inner = main.select("div.flw-item") ?: return@map null HomePageList( title, inner.mapNotNull { - // Get inner div from article val innerBody = it?.selectFirst("a") // Fetch details val link = fixUrlNull(innerBody?.attr("href")) ?: return@mapNotNull null - val image = fixUrlNull(innerBody?.select("img")?.attr("src")) ?: "" - val name = it?.selectFirst("a.series-name")?.text() ?: "" + val image = fixUrlNull(it.select("img").attr("data-src")) ?: "" + val name = innerBody?.attr("title") ?: "" //Log.i(this.name, "Result => (innerBody, image) ${innerBody} / ${image}") MovieSearchResponse( name, @@ -55,20 +49,17 @@ class DramaSeeProvider : MainAPI() { override suspend fun search(query: String): List { val url = "$mainUrl/search?q=$query" - val html = app.get(url).document - val document = html.getElementsByTag("body") - .select("section > main > ul.series > li") ?: return listOf() + val document = app.get(url).document + val posters = document.select ("div.film-poster") - return document.mapNotNull { - if (it == null) { - return@mapNotNull null - } - val innerA = it.select("a.series-img") ?: return@mapNotNull null + + return posters.mapNotNull { + val innerA = it.select("a") ?: return@mapNotNull null val link = fixUrlNull(innerA.attr("href")) ?: return@mapNotNull null - val title = it.select("a.series-name")?.text() ?: return@mapNotNull null - val year = null - val imgsrc = innerA.select("img")?.attr("src") ?: return@mapNotNull null - val image = fixUrlNull(imgsrc) + val title = innerA.attr("title") ?: return@mapNotNull null + val year = Regex(""".*\((\d{4})\)""").find(title)?.groupValues?.getOrNull(1)?.toIntOrNull() + val imgSrc = it.select("img")?.attr("data-src") ?: return@mapNotNull null + val image = fixUrlNull(imgSrc) MovieSearchResponse( name = title, @@ -84,12 +75,12 @@ class DramaSeeProvider : MainAPI() { override suspend fun load(url: String): LoadResponse { val doc = app.get(url).document val body = doc.getElementsByTag("body") - val inner = body?.select("div.series-info") + val inner = body?.select("div.anis-content") // Video details - val poster = fixUrlNull(inner?.select("div.img > img")?.attr("src")) ?: "" + val poster = fixUrlNull(inner?.select("img.film-poster-img")?.attr("src")) ?: "" //Log.i(this.name, "Result => (imgLinkCode) ${imgLinkCode}") - val title = inner?.select("h1.series-name")?.text() ?: "" + val title = inner?.select("h2.film-name.dynamic-name")?.text() ?: "" val year = if (title.length > 5) { title.substring(title.length - 5) .trim().trimEnd(')').toIntOrNull() @@ -97,15 +88,14 @@ class DramaSeeProvider : MainAPI() { null } //Log.i(this.name, "Result => (year) ${title.substring(title.length - 5)}") - val seriesBody = body?.select("div.series-body") - val descript = seriesBody?.firstOrNull()?.select("div.js-content")?.text() - val tags = seriesBody?.select("div.series-tags > a") + val descript = body?.firstOrNull()?.select("div.film-description.m-hide")?.text() + val tags = inner?.select("div.item.item-list > a") ?.mapNotNull { it?.text()?.trim() ?: return@mapNotNull null } - val recs = body?.select("ul.series > li")?.mapNotNull { - val a = it.select("a.series-img") ?: return@mapNotNull null + val recs = body.select("div.flw-item")?.mapNotNull { + val a = it.select("a") ?: return@mapNotNull null val aUrl = fixUrlNull(a.attr("href")) ?: return@mapNotNull null - val aImg = fixUrlNull(a.select("img")?.attr("src")) - val aName = a.select("img")?.attr("alt") ?: return@mapNotNull null + val aImg = fixUrlNull(it.select("img")?.attr("data-src")) + val aName = a.attr("title") ?: return@mapNotNull null val aYear = aName.trim().takeLast(5).removeSuffix(")").toIntOrNull() MovieSearchResponse( url = aUrl, @@ -118,40 +108,41 @@ class DramaSeeProvider : MainAPI() { } // Episodes Links - val episodeList = ArrayList() - body?.select("ul.episodes > li")?.forEach { ep -> - val innerA = ep.select("a") ?: return@forEach - val count = innerA.select("span.episode")?.text()?.toIntOrNull() ?: 0 - val epLink = fixUrlNull(innerA.attr("href")) ?: return@forEach - //Log.i(this.name, "Result => (epLink) ${epLink}") - if (epLink.isNotBlank()) { - // Fetch video links - val epVidLinkEl = app.get(epLink, referer = mainUrl).document - val ajaxUrl = epVidLinkEl.select("div#js-player")?.attr("embed") - //Log.i(this.name, "Result => (ajaxUrl) ${ajaxUrl}") - if (!ajaxUrl.isNullOrEmpty()) { - val innerPage = app.get(fixUrl(ajaxUrl), referer = epLink).document - val listOfLinks = mutableListOf() - innerPage.select("div.player.active > main > div")?.forEach { em -> - val href = fixUrlNull(em.attr("src")) ?: "" - if (href.isNotBlank()) { - listOfLinks.add(href) - } - } + val episodeUrl = body.select("a.btn.btn-radius.btn-primary.btn-play").attr("href") + val episodeDoc = app.get(episodeUrl).document - //Log.i(this.name, "Result => (listOfLinks) ${listOfLinks.toJson()}") - episodeList.add( - Episode( - name = null, - season = null, - episode = count, - data = listOfLinks.distinct().toJson(), - posterUrl = poster, - date = null - ) - ) - } - } + + val episodeList = episodeDoc.select("div.ss-list.ss-list-min > a").mapNotNull { ep -> + val episodeNumber = ep.attr("data-number").toIntOrNull() + val epLink = fixUrlNull(ep.attr("href")) ?: return@mapNotNull null + +// if (epLink.isNotBlank()) { +// // Fetch video links +// val epVidLinkEl = app.get(epLink, referer = mainUrl).document +// val ajaxUrl = epVidLinkEl.select("div#js-player")?.attr("embed") +// //Log.i(this.name, "Result => (ajaxUrl) ${ajaxUrl}") +// if (!ajaxUrl.isNullOrEmpty()) { +// val innerPage = app.get(fixUrl(ajaxUrl), referer = epLink).document +// val listOfLinks = mutableListOf() +// innerPage.select("div.player.active > main > div")?.forEach { em -> +// val href = fixUrlNull(em.attr("src")) ?: "" +// if (href.isNotBlank()) { +// listOfLinks.add(href) +// } +// } +// +// //Log.i(this.name, "Result => (listOfLinks) ${listOfLinks.toJson()}") +// +// } +// } + Episode( + name = null, + season = null, + episode = episodeNumber, + data = epLink, + posterUrl = null, + date = null + ) } //If there's only 1 episode, consider it a movie. @@ -161,7 +152,7 @@ class DramaSeeProvider : MainAPI() { url = url, apiName = this.name, type = TvType.Movie, - dataUrl = episodeList[0].data, + dataUrl = episodeList.first().data, posterUrl = poster, year = year, plot = descript, @@ -174,7 +165,7 @@ class DramaSeeProvider : MainAPI() { url = url, apiName = this.name, type = TvType.AsianDrama, - episodes = episodeList.reversed(), + episodes = episodeList, posterUrl = poster, year = year, plot = descript, @@ -189,33 +180,37 @@ class DramaSeeProvider : MainAPI() { subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ): Boolean { - var count = 0 - mapper.readValue>(data).apmap { item -> - if (item.isNotEmpty()) { - count++ - val url = fixUrl(item.trim()) - //Log.i(this.name, "Result => (url) ${url}") - when { - url.startsWith("https://asianembed.io") || url.startsWith("https://asianload.io") -> { - val iv = "9262859232435825" - val secretKey = "93422192433952489752342908585752" - extractVidstream(url, this.name, callback, iv, secretKey, secretKey, - isUsingAdaptiveKeys = false, - isUsingAdaptiveData = false - ) - AsianEmbedHelper.getUrls(url, callback) - } - url.startsWith("https://embedsito.com") -> { - val extractor = XStreamCdn() - extractor.domainUrl = "embedsito.com" - extractor.getSafeUrl(url)?.forEach(callback) - } - else -> { - loadExtractor(url, mainUrl, callback) - } + println("DATATATAT $data") + + val document = app.get(data).document + val iframeUrl = document.select("iframe").attr("src") + val iframe = app.get(iframeUrl) + val iframeDoc = iframe.document + + argamap({ + iframeDoc.select(".list-server-items > .linkserver") + .forEach { element -> + val status = element.attr("data-status") ?: return@forEach + if (status != "1") return@forEach + val extractorData = element.attr("data-video") ?: return@forEach + loadExtractor(extractorData, iframe.url, callback) } - } - } - return count > 0 + }, { + val iv = "9262859232435825" + val secretKey = "93422192433952489752342908585752" + val secretDecryptKey = "93422192433952489752342908585752" + extractVidstream( + iframe.url, + this.name, + callback, + iv, + secretKey, + secretDecryptKey, + isUsingAdaptiveKeys = false, + isUsingAdaptiveData = true, + iframeDocument = iframeDoc + ) + }) + return true } } diff --git a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/FilmanProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/FilmanProvider.kt index c82fff2e..8561568e 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/FilmanProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/FilmanProvider.kt @@ -1,12 +1,9 @@ package com.lagradost.cloudstream3.movieproviders import com.fasterxml.jackson.annotation.JsonProperty -import com.fasterxml.jackson.module.kotlin.readValue import com.lagradost.cloudstream3.* -import com.lagradost.cloudstream3.utils.AppUtils.parseJson +import com.lagradost.cloudstream3.utils.* import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson -import com.lagradost.cloudstream3.utils.ExtractorLink -import com.lagradost.cloudstream3.utils.loadExtractor import org.jsoup.Jsoup import org.jsoup.select.Elements @@ -90,7 +87,7 @@ class FilmanProvider : MainAPI() { val document = Jsoup.parse(response) val documentTitle = document.select("title").text().trim() - if (documentTitle.startsWith("Logowanie")){ + if (documentTitle.startsWith("Logowanie")) { throw RuntimeException("This page seems to be locked behind a login-wall on the website, unable to scrape it. If it is not please report it.") } diff --git a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/TheFlixToProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/TheFlixToProvider.kt index 81bd5757..38f08ec9 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/TheFlixToProvider.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/TheFlixToProvider.kt @@ -3,6 +3,7 @@ package com.lagradost.cloudstream3.movieproviders import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.LoadResponse.Companion.addActors +import com.lagradost.cloudstream3.network.cookies import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.ExtractorLink import com.lagradost.cloudstream3.utils.getQualityFromName @@ -22,6 +23,8 @@ class TheFlixToProvider : MainAPI() { TvType.TvSeries, ) + + data class HomeJson( @JsonProperty("props") val props: HomeProps = HomeProps(), ) @@ -92,9 +95,54 @@ class TheFlixToProvider : MainAPI() { @JsonProperty("conversionDate") val conversionDate: String? = null, @JsonProperty("id") val id: Int? = null, @JsonProperty("available") val available: Boolean? = null, + @JsonProperty("videos" ) val videos : ArrayList? = arrayListOf(), ) + private suspend fun getCookies(): Map { + // val cookieResponse = app.post( + // "https://theflix.to:5679/authorization/session/continue?contentUsageType=Viewing", + // headers = mapOf( + // "Host" to "theflix.to:5679", + // "User-Agent" to "Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0", + // "Accept" to "application/json, text/plain," + // "Accept-Language" to "en-US,en;q=0.5", + // "Content-Type" to "application/json;charset=utf-8", + // "Content-Length" to "35", + // "Origin" to "https://theflix.to", + // "DNT" to "1", + // "Connection" to "keep-alive", + // "Referer" to "https://theflix.to/", + // "Sec-Fetch-Dest" to "empty", + // "Sec-Fetch-Mode" to "cors", + // "Sec-Fetch-Site" to "same-site",)).okhttpResponse.headers.values("Set-Cookie") + + val cookies = app.post( + "$mainUrl:5679/authorization/session/continue?contentUsageType=Viewing", + headers = mapOf( + "Host" to "theflix.to:5679", + "User-Agent" to USER_AGENT, + "Accept" to "application/json, text/plain, */*", + "Accept-Language" to "en-US,en;q=0.5", + "Content-Type" to "application/json;charset=utf-8", + "Content-Length" to "35", + "Origin" to mainUrl, + "DNT" to "1", + "Connection" to "keep-alive", + "Referer" to mainUrl, + "Sec-Fetch-Dest" to "empty", + "Sec-Fetch-Mode" to "cors", + "Sec-Fetch-Site" to "same-site",) + ).cookies + /* val cookieRegex = Regex("(theflix\\..*?id\\=[a-zA-Z0-9]{0,8}[a-zA-Z0-9_-]+)") + val findcookie = cookieRegex.findAll(cookieResponse.toString()).map { it.value }.toList() + val cookiesstring = findcookie.toString().replace(", ","; ").replace("[","").replace("]","") + val cookiesmap = mapOf("Cookie" to cookiesstring) */ + latestCookies = cookies + return latestCookies + } + + override suspend fun getMainPage(): HomePageResponse { val items = ArrayList() val doc = app.get(mainUrl).document @@ -131,7 +179,7 @@ class TheFlixToProvider : MainAPI() { if (type?.contains("TV") == true) TvType.TvSeries else TvType.Movie val link = if (typeinfo == TvType.Movie) "$mainUrl/movie/${info.id}-${cleanTitle(title)}" - else "$mainUrl/tv-show/${info.id}-${cleanTitle(title)}/season-1/episode-1" + else "$mainUrl/tv-show/${info.id}-${cleanTitle(title).replace("?","")}/season-1/episode-1" TvSeriesSearchResponse( title, link, @@ -226,67 +274,53 @@ class TheFlixToProvider : MainAPI() { } return search } - - - data class LoadMain( - @JsonProperty("props") val props: LoadProps = LoadProps(), - @JsonProperty("page") var page: String? = null, - //@JsonProperty("query") val query: Query? = Query(), - @JsonProperty("buildId") val buildId: String? = null, - @JsonProperty("runtimeConfig") val runtimeConfig: RuntimeConfig? = RuntimeConfig(), - @JsonProperty("isFallback") val isFallback: Boolean? = null, - @JsonProperty("customServer") val customServer: Boolean? = null, - @JsonProperty("appGip") val appGip: Boolean? = null + data class LoadMain ( + @JsonProperty("props" ) val props : LoadProps? = LoadProps(), + @JsonProperty("page" ) val page : String? = null, + @JsonProperty("buildId" ) val buildId : String? = null, + @JsonProperty("runtimeConfig" ) val runtimeConfig : RuntimeConfig? = RuntimeConfig(), + @JsonProperty("isFallback" ) val isFallback : Boolean? = null, + @JsonProperty("gssp" ) val gssp : Boolean? = null, + @JsonProperty("customServer" ) val customServer : Boolean? = null, + @JsonProperty("appGip" ) val appGip : Boolean? = null ) - data class RuntimeConfig( - @JsonProperty("AddThisService") val AddThisService: AddThisService? = AddThisService(), - //@JsonProperty("Application") val Application: Application? = Application(), - //@JsonProperty("Content") val Content: Content? = Content(), - //@JsonProperty("GtmService") val GtmService: GtmService? = GtmService(), - //@JsonProperty("IptvChannels") val IptvChannels: IptvChannels? = IptvChannels(), - //@JsonProperty("Notifications") val Notifications: Notifications? = Notifications(), - //@JsonProperty("Payments") val Payments: Payments? = Payments(), - //@JsonProperty("Redux") val Redux: Redux? = Redux(), - //@JsonProperty("Search") val Search: Search? = Search(), - @JsonProperty("Services") val Services: Services? = Services(), - //@JsonProperty("Sitemap") val Sitemap: Sitemap? = Sitemap(), - //@JsonProperty("Support") val Support: Support? = Support(), - @JsonProperty("Videos") val Videos: Videos? = Videos() + data class LoadProps ( + @JsonProperty("pageProps" ) val pageProps : LoadPageProps? = LoadPageProps(), + @JsonProperty("__N_SSP" ) val _NSSP : Boolean? = null ) - - data class Server( - @JsonProperty("Url") var Url: String? = null - ) - - data class Services( - - @JsonProperty("Server") val Server: Server? = Server(), - @JsonProperty("TmdbServer") val TmdbServer: Server? = Server() - - ) - - data class AddThisService( - @JsonProperty("PublicId") val PublicId: String? = null - ) - - data class LoadProps( - @JsonProperty("pageProps") val pageProps: LoadPageProps = LoadPageProps(), - ) - - data class LoadPageProps( - @JsonProperty("selectedTv") val selectedTv: TheFlixMetadata? = TheFlixMetadata(), + data class LoadPageProps ( + @JsonProperty("selectedTv" ) val selectedTv : TheFlixMetadata? = TheFlixMetadata(), @JsonProperty("movie") val movie: TheFlixMetadata? = TheFlixMetadata(), - @JsonProperty("videoUrl") val videoUrl: String? = null, - @JsonProperty("recommendationsList") val recommendationsList: RecommendationsList? = RecommendationsList(), + @JsonProperty("recommendationsList" ) val recommendationsList : RecommendationsList? = RecommendationsList(), + @JsonProperty("basePageSegments" ) val basePageSegments : ArrayList? = arrayListOf() ) - data class Genres( - @JsonProperty("name") val name: String, - @JsonProperty("id") val id: Int? = null + data class TheFlixMetadata ( + @JsonProperty("episodeRuntime" ) val episodeRuntime : Int? = null, + @JsonProperty("name" ) val name : String? = null, + @JsonProperty("numberOfSeasons" ) val numberOfSeasons : Int? = null, + @JsonProperty("numberOfEpisodes" ) val numberOfEpisodes : Int? = null, + @JsonProperty("originalLanguage" ) val originalLanguage : String? = null, + @JsonProperty("popularity" ) val popularity : Double? = null, + @JsonProperty("status" ) val status : String? = null, + @JsonProperty("voteAverage" ) val voteAverage : Double? = null, + @JsonProperty("voteCount" ) val voteCount : Int? = null, + @JsonProperty("cast" ) val cast : String? = null, + @JsonProperty("director" ) val director : String? = null, + @JsonProperty("overview" ) val overview : String? = null, + @JsonProperty("posterUrl" ) val posterUrl : String? = null, + @JsonProperty("releaseDate" ) val releaseDate : String? = null, + @JsonProperty("createdAt" ) val createdAt : String? = null, + @JsonProperty("updatedAt" ) val updatedAt : String? = null, + @JsonProperty("id" ) val id : Int? = null, + @JsonProperty("available" ) val available : Boolean? = null, + @JsonProperty("genres" ) val genres : ArrayList? = arrayListOf(), + @JsonProperty("seasons" ) val seasons : ArrayList? = arrayListOf(), + @JsonProperty("videos" ) val videos : ArrayList? = arrayListOf(), + @JsonProperty("runtime" ) val runtime : Int? = null, ) - data class Seasons( @JsonProperty("name") val name: String? = null, @JsonProperty("numberOfEpisodes") val numberOfEpisodes: Int? = null, @@ -297,7 +331,7 @@ class TheFlixToProvider : MainAPI() { @JsonProperty("createdAt") val createdAt: String? = null, @JsonProperty("updatedAt") val updatedAt: String? = null, @JsonProperty("id") val id: Int? = null, - @JsonProperty("episodes") val episodes: ArrayList = arrayListOf() + @JsonProperty("episodes") val episodes: ArrayList? = arrayListOf() ) data class Episodes( @@ -311,68 +345,55 @@ class TheFlixToProvider : MainAPI() { @JsonProperty("createdAt") val createdAt: String? = null, @JsonProperty("updatedAt") val updatedAt: String? = null, @JsonProperty("id") val id: Int? = null, - @JsonProperty("videos") val videos: ArrayList = arrayListOf() - ) - - data class Videos( - @JsonProperty("language") val language: String? = null, - @JsonProperty("name") val name: String? = null, - @JsonProperty("id") val id: Int? = null - ) - - data class RecommendationsList( - @JsonProperty("docs") val docs: ArrayList = arrayListOf(), - @JsonProperty("total") val total: Int? = null, - @JsonProperty("page") val page: Int? = null, - @JsonProperty("limit") val limit: Int? = null, - @JsonProperty("pages") val pages: Int? = null, - @JsonProperty("type") val type: String? = null, - ) - - data class LoadDocs( - @JsonProperty("name") val name: String = String(), - @JsonProperty("originalLanguage") val originalLanguage: String? = null, - @JsonProperty("popularity") val popularity: Double? = null, - @JsonProperty("runtime") val runtime: Int? = null, - @JsonProperty("status") val status: String? = null, - @JsonProperty("voteAverage") val voteAverage: Double? = null, - @JsonProperty("voteCount") val voteCount: Int? = null, - @JsonProperty("cast") val cast: String? = null, - @JsonProperty("director") val director: String? = null, - @JsonProperty("overview") val overview: String? = null, - @JsonProperty("posterUrl") val posterUrl: String? = null, - @JsonProperty("releaseDate") val releaseDate: String? = null, - @JsonProperty("createdAt") val createdAt: String? = null, - @JsonProperty("updatedAt") val updatedAt: String? = null, - @JsonProperty("id") val id: Int? = null, - @JsonProperty("available") val available: Boolean? = null, + @JsonProperty("videos") val videos: ArrayList? = arrayListOf() ) - data class TheFlixMetadata( - @JsonProperty("episodeRuntime") val episodeRuntime: Int? = null, - @JsonProperty("name") val name: String = String(), - @JsonProperty("originalLanguage") val originalLanguage: String? = null, - @JsonProperty("popularity") val popularity: Double? = null, - @JsonProperty("runtime") val runtime: Int? = null, - @JsonProperty("numberOfSeasons") val numberOfSeasons: Int? = null, - @JsonProperty("numberOfEpisodes") val numberOfEpisodes: Int? = null, - @JsonProperty("status") val status: String? = null, - @JsonProperty("voteAverage") val voteAverage: Double? = null, - @JsonProperty("voteCount") val voteCount: Int? = null, - @JsonProperty("cast") val cast: String? = null, - @JsonProperty("director") val director: String? = null, - @JsonProperty("overview") val overview: String? = null, - @JsonProperty("posterUrl") val posterUrl: String? = null, - @JsonProperty("releaseDate") val releaseDate: String? = null, - @JsonProperty("conversionDate") val conversionDate: String? = null, - @JsonProperty("createdAt") val createdAt: String? = null, - @JsonProperty("updatedAt") val updatedAt: String? = null, - @JsonProperty("id") val id: Int? = null, - @JsonProperty("available") val available: Boolean? = null, - @JsonProperty("genres") val genres: ArrayList = arrayListOf(), - @JsonProperty("videos") val videos: ArrayList = arrayListOf(), - @JsonProperty("seasons") val seasons: ArrayList = arrayListOf() + data class Genres ( + @JsonProperty("name" ) val name : String? = null, + @JsonProperty("id" ) val id : Int? = null + ) + + data class RuntimeConfig ( + @JsonProperty("AddThisService" ) val AddThisService : RuntimeConfigData? = RuntimeConfigData(), + @JsonProperty("Application" ) val Application : RuntimeConfigData? = RuntimeConfigData(), + @JsonProperty("GtmService" ) val GtmService : RuntimeConfigData? = RuntimeConfigData(), + @JsonProperty("Services" ) val Services : RuntimeConfigData? = RuntimeConfigData(), + ) + + data class RuntimeConfigData( + @JsonProperty("PublicId" ) val PublicId : String? = null, + @JsonProperty("ContentUsageType" ) val ContentUsageType : String? = null, + @JsonProperty("IsDevelopmentMode" ) val IsDevelopmentMode : Boolean? = null, + @JsonProperty("IsDevelopmentOrProductionMode" ) val IsDevelopmentOrProductionMode : Boolean? = null, + @JsonProperty("IsProductionMode" ) val IsProductionMode : Boolean? = null, + @JsonProperty("IsStagingMode" ) val IsStagingMode : Boolean? = null, + @JsonProperty("IsTestMode" ) val IsTestMode : Boolean? = null, + @JsonProperty("Mode" ) val Mode : String? = null, + @JsonProperty("Name" ) val Name : String? = null, + @JsonProperty("Url" ) val Url : String? = null, + @JsonProperty("UseFilterInfoInUrl" ) val UseFilterInfoInUrl : Boolean? = null, + @JsonProperty("TrackingId" ) val TrackingId : String? = null, + @JsonProperty("Server" ) val Server : Server? = Server(), + @JsonProperty("TmdbServer" ) val TmdbServer : TmdbServer? = TmdbServer(), + ) + + data class TmdbServer ( + @JsonProperty("Url" ) val Url : String? = null + ) + + + data class Server ( + @JsonProperty("Url" ) val Url : String? = null + ) + + data class RecommendationsList ( + @JsonProperty("docs" ) val docs : ArrayList = arrayListOf(), + @JsonProperty("total" ) val total : Int? = null, + @JsonProperty("page" ) val page : Int? = null, + @JsonProperty("limit" ) val limit : Int? = null, + @JsonProperty("pages" ) val pages : Int? = null, + @JsonProperty("type" ) val type : String? = null, ) private fun cleanTitle(title: String): String { @@ -395,60 +416,21 @@ class TheFlixToProvider : MainAPI() { } private suspend fun getLoadMan(url: String): LoadMain { - val og = app.get(url, cookies = latestCookies) + getCookies() + val og = app.get(url, headers = latestCookies) val soup = og.document val script = soup.selectFirst("script[type=application/json]")!!.data() return parseJson(script) } - // I legit cant figure this out - private suspend fun getLoadMainRetry(url: String): LoadMain { - val first = getLoadMan(url) - val notFound = "/404" - if (first.page == notFound) { - first.runtimeConfig?.Services?.TmdbServer?.Url?.let { authUrl -> - val optionsUrl = "$authUrl/authorization/session/continue?contentUsageType=Viewing" - val options = app.options( - optionsUrl, - headers = mapOf( - "User-Agent" to USER_AGENT, - "Access-Control-Request-Method" to "POST", - "Access-Control-Request-Headers" to "content-type", - "Origin" to url, - "Referer" to mainUrl, - ) - ) - //{"affiliateCode":"","pathname":"/movie/696806-the-adam-project"} - val data = mapOf("affiliateCode" to "", "pathname" to url.removePrefix(mainUrl)) - val resp = app.post( - optionsUrl, headers = mapOf( - "User-Agent" to USER_AGENT, - "Content-Type" to "application/json;charset=UTF-8", - "Accept" to "application/json, text/plain, */*", - "Origin" to url, - "Referer" to mainUrl, - ), data = data - ) - - latestCookies = resp.cookies - val newData = getLoadMan(url) - if (newData.page == notFound) { - throw ErrorLoadingException("404 Not found") - } - return newData - } - } - return first - } - override suspend fun load(url: String): LoadResponse? { val tvtype = if (url.contains("movie")) TvType.Movie else TvType.TvSeries - val json = getLoadMainRetry(url) + val json = getLoadMan(url) val episodes = ArrayList() val isMovie = tvtype == TvType.Movie - val pageMain = json.props.pageProps + val pageMain = json.props?.pageProps - val metadata: TheFlixMetadata? = if (isMovie) pageMain.movie else pageMain.selectedTv + val metadata: TheFlixMetadata? = if (isMovie) pageMain?.movie else pageMain?.selectedTv val available = metadata?.available @@ -463,9 +445,9 @@ class TheFlixToProvider : MainAPI() { val description = metadata.overview if (!isMovie) { - metadata.seasons.map { seasons -> + metadata.seasons?.map { seasons -> val seasonPoster = seasons.posterUrl ?: metadata.posterUrl - seasons.episodes.forEach { epi -> + seasons.episodes?.forEach { epi -> val episodenu = epi.episodeNumber val seasonum = epi.seasonNumber val title = epi.name @@ -474,7 +456,7 @@ class TheFlixToProvider : MainAPI() { val ratinginfo = (epi.voteAverage)?.times(10)?.toInt() val rating = if (ratinginfo?.equals(0) == true) null else ratinginfo val eps = Episode( - "$mainUrl/tv-show/$movieId-${cleanTitle(movietitle)}/season-$seasonum/episode-$episodenu", + "$mainUrl/tv-show/$movieId-${cleanTitle(movietitle!!)}/season-$seasonum/episode-$episodenu", title, seasonum, episodenu, @@ -482,7 +464,7 @@ class TheFlixToProvider : MainAPI() { posterUrl = seasonPoster, rating = rating, ) - if (test.isNotEmpty()) { + if (test!!.isNotEmpty()) { episodes.add(eps) } else { //Nothing, will prevent seasons/episodes with no videos to be added @@ -492,9 +474,9 @@ class TheFlixToProvider : MainAPI() { } val rating = metadata.voteAverage?.toFloat()?.times(1000)?.toInt() - val tags = metadata.genres.map { it.name } + val tags = metadata.genres?.mapNotNull { it.name } - val recommendationsitem = pageMain.recommendationsList?.docs?.map { loadDocs -> + val recommendationsitem = pageMain?.recommendationsList?.docs?.map { loadDocs -> val title = loadDocs.name val posterrec = loadDocs.posterUrl val link = if (isMovie) "$mainUrl/movie/${loadDocs.id}-${cleanTitle(title)}" @@ -516,7 +498,7 @@ class TheFlixToProvider : MainAPI() { return when (tvtype) { TvType.TvSeries -> { - return newTvSeriesLoadResponse(movietitle, url, TvType.TvSeries, episodes) { + return newTvSeriesLoadResponse(movietitle!!, url, TvType.TvSeries, episodes) { this.posterUrl = poster this.year = year?.toIntOrNull() this.plot = description @@ -529,7 +511,7 @@ class TheFlixToProvider : MainAPI() { } } TvType.Movie -> { - newMovieLoadResponse(movietitle, url, TvType.Movie, url) { + newMovieLoadResponse(movietitle!!, url, TvType.Movie, url) { this.year = year?.toIntOrNull() this.posterUrl = poster this.plot = description @@ -546,27 +528,76 @@ class TheFlixToProvider : MainAPI() { } + data class VideoData ( + @JsonProperty("url" ) val url : String? = null, + @JsonProperty("id" ) val id : String? = null, + @JsonProperty("type" ) val type : String? = null, + ) + + override suspend fun loadLinks( data: String, isCasting: Boolean, subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ): Boolean { - val json = getLoadMainRetry(data) - val extractedLink = json.props.pageProps.videoUrl + val json = getLoadMan(data) + val authhost = json.runtimeConfig?.Services?.Server?.Url + val isMovie = data.contains("/movie/") val qualityReg = Regex("(\\d+p)") - if (extractedLink != null) { - val quality = qualityReg.find(extractedLink)?.value ?: "" - callback( - ExtractorLink( - name, - "$name $quality", - extractedLink, - "", - getQualityFromName(quality), - false - ) - ) + if (isMovie){ + json.props?.pageProps?.movie?.videos?.apmap { id -> + val jsonmovie = app.get("$authhost/movies/videos/$id/request-access?contentUsageType=Viewing", + headers = latestCookies).parsedSafe() ?: return@apmap false + val extractedlink = jsonmovie.url + if (!extractedlink.isNullOrEmpty()) { + val quality = qualityReg.find(extractedlink)?.value ?: "" + callback( + ExtractorLink( + name, + name, + extractedlink, + "", + getQualityFromName(quality), + false + ) + ) + } else null + } + } + else + { + val dataRegex = Regex("(season-(\\d+)\\/episode-(\\d+))") + val cleandatainfo = dataRegex.find(data)?.value?.replace(Regex("(season-|episode-)"),"")?.replace("/","x") + val tesatt = cleandatainfo.let { str -> + str?.split("x")?.mapNotNull { subStr -> subStr.toIntOrNull() } + } + val epID = tesatt?.getOrNull(1) + val seasonid = tesatt?.getOrNull(0) + json.props?.pageProps?.selectedTv?.seasons?.map { + it.episodes?.map { + val epsInfo = Triple(it.seasonNumber, it.episodeNumber, it.videos) + if (epsInfo.first == seasonid && epsInfo.second == epID) { + epsInfo.third?.apmap { id -> + val jsonserie = app.get("$authhost/tv/videos/$id/request-access?contentUsageType=Viewing", headers = latestCookies).parsedSafe() ?: return@apmap false + val extractedlink = jsonserie.url + if (!extractedlink.isNullOrEmpty()) { + val quality = qualityReg.find(extractedlink)?.value ?: "" + callback( + ExtractorLink( + name, + name, + extractedlink, + "", + getQualityFromName(quality), + false + ) + ) + } else null + } + } + } + } } return true } diff --git a/app/src/main/java/com/lagradost/cloudstream3/movieproviders/VidSrcProvider.kt b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/VidSrcProvider.kt new file mode 100644 index 00000000..84036abb --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/movieproviders/VidSrcProvider.kt @@ -0,0 +1,73 @@ +package com.lagradost.cloudstream3.movieproviders + +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.metaproviders.TmdbLink +import com.lagradost.cloudstream3.metaproviders.TmdbProvider +import com.lagradost.cloudstream3.utils.AppUtils.parseJson +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.M3u8Helper.Companion.generateM3u8 +import com.lagradost.cloudstream3.utils.loadExtractor + +class VidSrcProvider : TmdbProvider() { + override val apiName = "VidSrc" + override var name = "VidSrc" + override var mainUrl = "https://v2.vidsrc.me" + override val useMetaLoadResponse = true + override val instantLinkLoading = false + override val supportedTypes = setOf( + TvType.Movie, + TvType.TvSeries, + ) + + override suspend fun loadLinks( + data: String, + isCasting: Boolean, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ): Boolean { + val mappedData = parseJson(data) + val (id, site) = if (mappedData.imdbID != null) listOf( + mappedData.imdbID, + "imdb" + ) else listOf(mappedData.tmdbID.toString(), "tmdb") + val isMovie = mappedData.episode == null && mappedData.season == null + val embedUrl = if (isMovie) { + if(site == "imdb") "$mainUrl/embed/$id" else + "$mainUrl/embed/$id" + } else { + val suffix = "$id/${mappedData.season ?: 1}-${mappedData.episode ?: 1}" + if (site == "imdb") "$mainUrl/embed/$suffix" else + "$mainUrl/embed/$suffix" + } + val iframedoc = app.get(embedUrl).document + + val serverslist = iframedoc.select("div#sources.button_content div#content div#list div").map { + val datahash = it.attr("data-hash") + if (datahash.isNotBlank()) { + val links = try { + app.get("$mainUrl/src/$datahash", referer = "https://source.vidsrc.me/").url + } catch (e: Exception) { + "" + } + links + } else "" + } + + serverslist.apmap { server -> + val linkfixed = server.replace("https://vidsrc.xyz/","https://embedsito.com/") + if (linkfixed.contains("/pro")) { + val srcresponse = app.get(server, referer = mainUrl).text + val m3u8Regex = Regex("((https:|http:)\\/\\/.*\\.m3u8)") + val srcm3u8 = m3u8Regex.find(srcresponse)?.value ?: return@apmap false + generateM3u8( + name, + srcm3u8, + mainUrl + ).forEach(callback) + } else + loadExtractor(linkfixed, embedUrl, callback) + } + + return true + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsLang.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsLang.kt index 6ae4a68e..2f047cf7 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsLang.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/SettingsLang.kt @@ -41,7 +41,8 @@ class SettingsLang : PreferenceFragmentCompat() { Triple("", "Arabic", "ar"), Triple("", "Turkish", "tr"), Triple("", "Macedonian", "mk"), - Triple("\uD83C\uDDE7\uD83C\uDDF7", "Portuguese (Brazil)", "pt"), + Triple("\uD83C\uDDF5\uD83C\uDDF9", "Portuguese", "pt"), + Triple("\uD83C\uDDE7\uD83C\uDDF7", "Brazilian Portuguese", "bp"), Triple("", "Romanian", "ro"), Triple("", "Italian", "it"), Triple("", "Chinese", "zh"), diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt index a5a605a5..58f5d411 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt @@ -63,7 +63,11 @@ open class ExtractorLink( override val headers: Map = mapOf(), /** Used for getExtractorVerifierJob() */ open val extractorData: String? = null, -) : VideoDownloadManager.IDownloadableMinimum +) : VideoDownloadManager.IDownloadableMinimum { + override fun toString(): String { + return "ExtractorLink(name=$name, url=$url, referer=$referer, isM3u8=$isM3u8)" + } +} data class ExtractorUri( val uri: Uri, diff --git a/app/src/main/res/values-bp/strings.xml b/app/src/main/res/values-bp/strings.xml new file mode 100644 index 00000000..39fd2212 --- /dev/null +++ b/app/src/main/res/values-bp/strings.xml @@ -0,0 +1,551 @@ + + + + search_providers_list + app_locale + search_type_list + auto_update + skip_update_key + prerelease_update + manual_check_update + fast_forward_button_time + benene_count + subtitle_settings_key + subtitle_settings_chromecast_key + quality_pref_key + prefer_limit_title_key + prefer_limit_title_rez_key + video_buffer_size_key + video_buffer_length_key + video_buffer_clear_key + video_buffer_disk_key + unknown_prerelease + use_system_brightness_key + swipe_enabled_key + playback_speed_enabled_key + player_resize_enabled_key + pip_enabled_key + double_tap_enabled_key + double_tap_pause_enabled_key + double_tap_seek_time_key + swipe_vertical_enabled_key + display_sub_key + show_fillers_key + show_trailers_key + show_kitsu_posters_key + random_button_key + provider_lang_key + dns_key + download_path_key + Cloudstream + app_layout_key + primary_color_key + restore_key + killswitch_key + backup_key + prefer_media_type_key + app_theme_key + episode_sync_enabled_key + log_enabled_key + show_logcat_key + bottom_title_key + poster_ui_key + subtitles_encoding_key + override_site_key + + + %d %s | %sMB + %s • %sGB + %sMB / %sMB + %dMB + %s %s + +%d + -%d + %d + %d + %.1f/10.0 + %d + %s Ep %d + Elenco: %s + O episódio %d vai ser lançado em + %dd %dh %dm + %dh %dm + %dm + + + Poster + @string/result_poster_img_des + Episode Poster + Main Poster + Next Random + @string/play_episode + Go back + @string/home_change_provider_img_des + Change Provider + Preview Background + + + Velocidade (%.2fx) + Nota: %.1f + Nova atualização encontrada!\n%s -> %s + Filler + %d min + + CloudStream + Início + Procurar + Downloads + Configurações + + Procurar… + Procurar no %s… + + Sem dados + Mais Opções + Próximo episódio + @string/synopsis + Gêneros + Compartilhar + Abrir no Navegador + Pular Carregamento + Carregando… + + Assistindo + Em espera + Completado + Deixado + Planejando assistir + Nenhum + Reassistindo + + Assistir Filme + Transmitir Torrent + Fontes + Legendas + Tentar reconectar… + Voltar + Assistir Episódio + + + Baixar + Baixado + Baixando + Download Pausado + Download Iniciado + Download Falhado + Download Cancelado + Download Finalizado + %s - %s + Transmitir + + Erro Carregando Links + Armazenamento Interno + + Dub + Leg + + Deletar Arquivo + Assistir Arquivo + Retomar Download + Pausar Download + + Desativar relatório automático de erros + Mais info + Esconder + Assistir + Info + Filtrar Marcadores + Marcadores + Remover + Selecionar marcador + Aplicar + Cancelar + Copiar + Fechar + Limpar + Salvar + + Velocidade do Reprodutor + + Configurar Legendas + Cor do Texto + Cor do Contorno + Cor do Fundo + Cor da Janela + Tipo de Borda + Elevação da Legenda + Fonte + Tamanho da Fonte + + Pesquisar usando fornecedor + Pesquisar usando genêros + + %d Benenes doados aos desenvolvedores + Nenhuma Benenes doada + + Autosseleção de Lingua + Baixar Linguas + Lingua da legenda + Segure para retornar a configuração padrão + Importe fontes colocando elas em %s + Continue Assistindo + + Remover + Mais Info + @string/home_play + + Uma VPN pode ser necessária para esse fornecedor funcionar corretamente + Esse fornecedor é um torrent, uma VPN é recomendada + + Metadados não são oferecidas pelo site, o carregamento do video pode falhar se ele não existir no site. + + Descrição + Sinopse não encontrada + Descrição não encontrada + + Mostrar logcat 🐈 + + Picture-in-picture + Continua a reprodução em um player miniatura que sobrepõe outros aplicativos + Redimensionar player + Remover bordas pretas + Legendas + Configurações de legendas do Player + Legendas do Chromecast + Configurações de legendas do Chromecast + + Modo Eigengravy + Adiciona um botão de velocidade no player + Deslize para avançar o vídeo + Deslize para a esq. ou dir. para controlar o tempo no player + Deslize para mudar as configurações + Deslize para o lado esq. ou dir. para ajustar brilho ou volume + Toque duplo para avançar o vídeo + Toque duplo para pausar + Segundos avançados no player + Toque duplo no lado direito ou esquerdo para regredir ou avançar vídeo + Toque no meio para pausar + Usar brilho do sistema + Usar brilho do sistema no player ao invés da sobreposição escura + + Atualizar progresso assistido + Sincronize automaticamente seu progresso do episódio + + Restaurar dados de backup + Baixar metadados mais recentes do github + Se você quiser acesso a todos os fornecedores (mesmo os quebrados) desmarque isso + + Fazer Backup + Arquivo de Backup carregado + Falha em restaurar dados do arquivo %s + Dados salvos com sucesso + Permissões de armazenamento faltando, por favor tente denovo + Erro no backup de %s + + Procurar + Contas + Atualizações e backup + O que é Nginx ? + Nginx é um software que pode ser usado para exibir arquivos de um servidor que você possui. Clique para ver um guia de configuração do Nginx + + Info + Procura Avançada + Mostrar resultados separados por fornecedor + Só enviar dados sobre travamentos + Não enviar nenhum dado + Mostrar episódios de Filler em anime + Mostrar trailers + Mostrar posters do kitsu + + Mostrar atualizações do app + Automaticamente procurar por novas atualizações ao abrir + Atualizar para pré-lançamento + Procura atualizações do pré-lançamento ao invés de apenas do lançamento oficial + Github + App de Light novel pelos mesmos desenvolvedores + App de Anime pelos mesmos desenvolvedores + Junte-se ao Discord + Dar um benene para os desenvolvedores + Benene dada + + Linguagem do App + + Esse fornecedor não possui suporte para Chromecast + Nenhum link encontrado + Link copiado para área de transferência + Assistir Episódio + Restaurar para o padrão + Desculpe, a aplicação travou. Um relatório de erro anônimo será enviado para os + desenvolvedores + + + Temporada + Nenhuma Temporada + Episódio + Episódios + S + E + Nenhum Episódio encontrado + + Deletar Arquivo + Deletar + @string/sort_cancel + Pausar + Retomar + -30 + +30 + Isso apagará %s permanentemente\nVocê tem certeza? + %dm\nsobrando + + + Em andamento + Concluído + Estado + Ano + Nota + Duração + Site + Sinopse + + Na fila + Sem Legendas + Padrão + + Livre + Usado + App + + + Filmes + Séries + Desenhos Animados + Anime + Torrents + Documentários + OVA + Dramas Asiáticos + + + Filme + Série + Desenho Animado + @string/anime + @string/ova + Torrent + Documentário + Drama Asiático + + Erro de fornecimento + Erro remoto + Erro de renderização + Erro de player inesperado + Erro ao baixar, verifique as permissões de armazenamento + + Episódio pelo Chromecast + Alternativa pelo Chromecast + Assistir no App + Assistir no VLC + Assistir no navegador + Copiar link + Auto download + Baixar por servidor alternativo + Recarregar links + Baixar legendas + + Etiqueta de qualidade + Etiqueta Dub + Etiqueta Sub + Título + show_hd_key + show_dub_key + show_sub_key + show_title_key + Alternar elementos da interface no pôster + + Nenhuma Atualização encontrada + Procurar nova Atualização + + Bloquear + Mudar Tamanho + Fonte + Pular OP + + Não mostrar de novo + Pular essa Atualização + Atualizar + Qualidade preferida + Máximo de caracteres do título de vídeos + Resolução do player de vídeo + + Tamanho do buffer do vídeo + Comprimento do buffer do vídeo + Cache do vídeo em disco + Limpar cache de vídeo e imagem + + Causará travamentos aleatórios se definido muito alto. Não mude caso tiver pouca memória RAM, como um Android TV ou um telefone antigo + Pode causar problemas em sistemas com pouco espaço de armazenamento se definido muito alto, como em dispositivos Android TV + + DNS sobre HTTPS + Útil para burlar bloqueios de provedores de internet + + Clonar site + Remover site + Adiciona um clone de um site existente, com uma url diferente + + Caminho para Download + + Url do servidor Nginx + + Mostrar Anime Dublado/Legendado + + Ajustar para a Tela + Esticar + Zoom + + Aviso Legal + legal_notice_key + Any legal issues regarding the content on this application + should be taken up with the actual file hosts and providers themselves as we are not affiliated with them. + + In case of copyright infringement, please directly contact the responsible parties or the streaming websites. + + The app is purely for educational and personal use. + + CloudStream 3 does not host any content on the app, and has no control over what media is put up or taken down. + CloudStream 3 functions like any other search engine, such as Google. CloudStream 3 does not host, upload or + manage any videos, films or content. It simply crawls, aggregates and displayes links in a convenient, + user-friendly interface. + + It merely scrapes 3rd-party websites that are publicly accessable via any regular web browser. It is the + responsibility of user to avoid any actions that might violate the laws governing his/her locality. Use + CloudStream 3 at your own risk. + + Geral + Botão Aleatório + Mostra o botão Aleatório na página inicial + Linguagem dos fornecedores + Layout do App + Mídia preferida + Codificação das legendas + Linguagem + Layout + + Auto + Layout de TV + Layout de celular + Layout de emulador + + Cor principal + Tema do App + Local do título do poster + Coloca o título debaixo do poster + + + + anilist_key + mal_key + opensubtitles_key + nginx_key + senha123 + MeuNomeLegal + oi@mundo.com + 127.0.0.1 + MeuSiteLegal + examplo.com + Codigo da Língua (bp) + + + %s %s + Conta + Sair + Entrar + Trocar conta + Adicionar conta + Criar conta + Adicionar sincronização + %s adicionado + Sincronizar + Nota + %d / 10 + /?? + /%d + %s autenticado + Falha em autenticar para %s + + + Nenhum + Normal + Tudo + Max + Min + @string/none + Contornado + Afundado + Sombreado + Em Relevo + Sincronizar legendas + 1000ms + Atraso de legenda + Use isto se as legendas forem mostradas %dms adiantadas + Use isto se as legendas forem mostradas %dms atrasadas + Sem atraso de legenda + + + Já fiz vinho com toque de kiwi para belga sexy. + + Recomendada + %s carregada + Carregar de arquivo + Carregar da Internet + Arquivo baixado + Protagonista + Coadjuvante + Figurante + + Fonte + Aleatório + + Em breve… + + Cam + Cam + Cam + HQ + HD + TS + TC + BlueRay + WP + DVD + 4K + SD + UHD + HDR + SDR + Web + + Imagem de Poster + Player + Resolução e título + Título + Resolução + Id invalida + Dado invalido + Erro + Remover legendas ocultas(CC) das legendas + Remover bloat das legendas + Extras + Trailer + diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index bd898dae..f9b68f2a 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -14,6 +14,10 @@ %d %s Ep %d Cast: %s + Bölüm %d şu tarihte yayınlanacak: + %dd %dh %dm + %dh %dm + %dm Poster @@ -32,64 +36,67 @@ Puan: %.1f Yeni güncelleme bulundu!\n%s -> %s Filler - %d min + %d dakika CloudStream - Ana Sayfa + Ana sayfa Arama - İndirmeler + İndirilenler Ayarlar Ara… - Veri Yok - Daha Fazla Seçenek + %s sağlayıcısında ara… + + Veri yok + Daha fazla seçenek Sonraki bölüm @string/synopsis Türler Paylaş - Tarayıcıda Aç - Yüklemeyi Atla + Tarayıcıda aç + Yüklemeyi atla Yükleniyor… İzleniyor - Bekleniyor + Beklemede Tamamlandı Bırakıldı Planlandı Hiçbiri - Yeniden İzleniyor + Yeniden izleniyor - Filmi Oynat - Torrent Oynat + Filmi oynat + Torrent oynat Kaynaklar - Altyazılar + Alt yazılar Yeniden bağlan… - Geri Dön - Bölümü Oynat + Geri dön + Bölümü oynat İndir İndirildi İndiriliyor - İndirme Durduruldu - İndirme Başlatıldı - İndirme Başarısız - İndirme İptal Edildi - İndirme Bitti + İndirme duraklatıldı + İndirme başladı + İndirme başarısız oldu + İndirme iptal edildi + İndirme bitti %s - %s + Yayınla - Bağlantıları Yükleme Başarısız - Dahili Depolama + Bağlantılar yüklenirken hata oluştu + Dahili depolama - Dublaj - Altyazı + Dublajlı + Alt yazılı - Dosyayı Sil - Dosyayı Oynat - İndirmeyi Sürdür - İndirmeyi Durdur + Dosyayı sil + Dosyayı oynat + İndirmeyi sürdür + İndirmeyi duraklat - Otomatik hata raporlamayı devre dışı bırak + Otomatik hata raporlamayı kapat Daha fazla bilgi Gizle Oynat @@ -99,23 +106,23 @@ Kaldır İzleme durumunu ayarla Uygula - İptal Et + İptal et Kopyala Kapat Temizle Kaydet - Oynatma Hızı + Oynatıcı hızı - Altyazı Ayarları - Metin Rengi - Dış Hat Rengi - Arkaplan Rengi - Pencere Rengi - Kenar Tipi - Altyazı Yüksekliği - Font - Font Büyüklüğü + Alt yazı ayarları + Yazı rengi + Dış hat rengi + Arka plan rengi + Pencere rengi + Kenar tipi + Alt yazı yüksekliği + Yazı tipi + Yazı boyutu Sağlayıcıları kullanarak ara Türleri kullanarak ara @@ -123,97 +130,99 @@ Geliştiricilere %d muz verildi Hiç muz verilmedi - Dili otomatik seç - Dilleri İndir + Otomatik seçilecek dil + İndirilecek diller + Alt yazı dili Varsayılana döndürmek için basılı tut - İzlemeye Devam Et + Fontları içe aktarmak için %s konumuna yerleştirin + İzlemeye devam et Kaldır - Daha Fazla Bilgi + Daha fazla bilgi @string/home_play - Bu sağlayıcının düzgün çalışması için VPN gerekebilir - Bu sağlayıcı bir Torrent, VPN kullanmanız önerilir + Bu sağlayıcının düzgün çalışması için bir VPN gerekebilir + Bu sağlayıcı bir torrent. VPN önerilir - Site Metadata verisini sağlamadı, video eğer sitede bulunmuyorsa oynatma başarısız olabilir + Metadata verisi site tarafından sağlanmadı, video yüklemesi eğer sitede bulunmuyorsa oynatma başarısız olacak Açıklama - Senaryo bulunamadı + Konu bulunamadı Açıklama bulunamadı - logcat\'i göster 🐈 + Logcat\'i göster 🐈 Resim-içinde-resim - Diğer uygulamaların üzerinde minyatür oynatıcıyı çalıştırır - Yeniden boyutlandırma butonu - Siyah kenarlıkları kaldır - Altyazılar - Oynatıcı altyazı seçenekleri - Chromecast Altyazıları - Chromecast Altyazı Ayarları + Diğer uygulamaların üzerinde minyatür bir oynatıcıda oynatmaya devam eder + Oynatıcı yeniden boyutlandırma butonu + Siyah sınırları kaldır + Alt yazı + Oynatıcı alt yazı ayarları + Chromecast alt yazı + Chromecast alt yazı ayarları - Eigengravy Modu - Hız seçeneği ekler + Eigengravy modu + Oynatıcıya bir hız seçeneği ekler Gözlemek için kaydır - Zamanı ayarlamak için sağa ve sola kaydır + Zamanı ayarlamak için sağa veya sola kaydır Ayarları değiştirmek için kaydır Sol ve sağ taraftan kaydırarak parlaklık ve sesi ayarla Gözlemek için çift tıkla Durdurmak için çift tıkla - İleri ve geri atlamak için sağ ve sola çift tıkla - - Durdurmak için ortaya bas + Player seek amount + İleri ve geri atlamak için sağa ve sola çift tıkla + Durdurmak için ortaya tıkla Sistem parlaklığını kullan - Oynatıcıda karanlık kaplama yerine sistem parlaklığını kullan - + Oynatıcıda karanlık kaplama yerine sistem parlaklığını kullan İzleme ilerlemesini güncelle Mevcut bölüm ilerlemesini otomatik güncelle - Yedekten veri iade et - Github\'dan en son metadata\'yı indir - If you want access to all providers (even broken ones) turn this off Tüm sağlayıcılara erişim istiyorsan (bozuk olanlar dahil) bunu kapat + Yedekten geri yükle + GitHub\'tan en son metadata\'yı indir + Tüm sağlayıcılara erişmek istiyorsanız (bozuk olanlara bile) bunu kapatın - Veri Yedekle - Yedek dosyayı yüklendi - Dosyadan veri iade etme başarısız %s - Veri başarıyla depolandı + Yedekle + Yedek dosyası yüklendi + Geri yükleme başarısız oldu: %s + Başarıyla yedeklendi Depolama izinleri eksik, lütfen tekrar deneyin - Yedekleme hatası %s + %s yedeklenirken hata Ara + Hesaplar + Güncellemeler ve yedek Nginx nedir? - Nginx sahip olduğun sunucundaki dosyaları görüntülemek için kullanılabilecek bir yazılımdır. Nginx kurulum rehberini görmek için tıkla + Nginx, sahip olduğunuz bir sunucudan dosyaları görüntülemek için kullanılabilecek bir yazılımdır. Nginx kurulum kılavuzunu görmek için tıklayın Bilgi - Gelişmiş Arama - Sağlaayıcılar ile ayrılmış arama sonuçlarını verir - Sadece çökme durumunda veri gönderir + Gelişmiş arama + Sağlayıcılara göre ayrılmış arama sonuçlarını verir + Yalnızca çökmelerle ilgili verileri gönderir Hiç veri göndermez Anime için filler bölümleri gösterir + Fragmanları göster + Kitsu\'dan posterleri göster + Uygulama güncellemelerini göster - Uygulamayı başlattığında yeni güncelleme olup olmadığını kontrol et - Ön sürüme güncelle - Sadece tam sürümler yerine ön sürümleri de ara - Github - Aynı geliştiricilerden LightNovel uygulaması - Aynı geliştiricilerden anime uygulaması + Başlangıçta yeni güncellemeleri otomatik olarak ara + Ön sürümlere güncelle + Sadece tam sürümler yerine ön sürüm güncellemelerini de ara + GitHub + Aynı geliştiriciler tarafından LightNovel uygulaması + Aynı geliştiriciler tarafından anime uygulaması Discord\'a katıl Geliştiricilere muz ver - Verilen muzlar - - Uygulama Dili + Verilen muz + Uygulama dili Bu sağlayıcının Chromecast desteği yok Bağlantı bulunamadı - - Bağlantı panoya kopyalandı - Bölümü Oynat - Varsayılan değere dön - Üzgünüm, uygulama çöktü. Anonim hata raporu geliştiricilere gönderilecek - + Bölümü oynat + Varsayılana sıfırla + Üzgünüz, uygulama çöktü. Geliştiricilere isimsiz bir hata raporu gönderilecek Sezon Sezon yok @@ -221,18 +230,17 @@ Bölümler S B - Bölüm Bulunamadı + Bölüm bulunamadı - Dosyayı Sil + Dosyayı sil Sil @string/sort_cancel Durdur Sürdür -30 +30 - Dosya tamamen silinecek %s\nEmin misin? - %dm\nkalan - + %s dosyası tamamen silinecek\nEmins misiniz? + %dm\nkaldı Devam ediyor Tamamlandı @@ -243,83 +251,98 @@ Site Özet - kuyrukta - Altyazı Yok + Sıraya alındı + Alt yazı yok Varsayılan - Kullanılabilir + Boş Kullanılan Uygulama Filmler Diziler - Çizgi Filmler - Anime + Çizgi filmler + Animeler Torrentler Belgeseller OVA - Asya Dramaları + Asya dramaları Film Dizi - Çizgi Film + Çizgi film @string/anime @string/ova Torrent Belgesel - Asya Draması + Asya draması Kaynak hatası - Uzak sunucu hatası - Oluşturucu hatası - Oynatıcıda beklenmeyen hata - İndirme hatası, depolama izinlerini kontrol et + Sunucu hatası + İşleyici hatası + Beklenmeyen oynatıcı hatası + İndirme hatası, depolama izinlerini kontrol edin - - Chromecast bölümü - Chromecast yansıtma + Bölümü Chromecast ile yayınla + Bağlantıyı Chromecast ile yayınla Uygulamada oynat VLC\'de oynat Tarayıcıda oynat - Bağlantıyı kopyala + Linki kopyala Otomatik indir - Ayna kaynaktan indir - Bağlantıyı yeniden yükle - Altyazıları indir + Şu kaynaktan indir + Bağlantıları yenile + Alt yazıları indir + Kalite etiketi + Dublaj etiketi + Alt yazı etiketi + Başlık + show_hd_key + show_dub_key + show_sub_key + show_title_key + Poster üzerindeki öğeler Güncelleme bulunamadı - Güncellemeyi kontrol et + Güncellemeleri denetle Kilitle - Boyutlandır + Yeniden boyutlandır Kaynak - Başlangıcı atla + OP\'yi geç - Tekrar gösterme + Bir daha gösterme + Bu güncellemeyi atla Güncelle Tercih edilen izleme kalitesi - Oynatıcıda başlık karakterini sınırla - Video ara bellek boyutu - Video ara bellek uzunluğu - Video disk önbelleği + Oynatıcıdaki maksimum başlık karakter sayısı + Oynatıcının üst tarafındaki öğeler + + Video arabelleği boyutu + Video arabelleği uzunluğu + Diskteki video önbelleği Video ve resim önbelleğini temizle - Android TV cihazları veya eski telefonlar gibi RAM\'i düşük olan sistemlerde çok yüksek ayarlarsanız sorun çıkarabilir - Çok yükseğe ayarlarsanız, Android TV cihazları gibi düşük depolama alanına sahip sistemlerde sorunlara neden olabilir + Çok yükseğe ayarlanırsa rastgele çökmelere neden olur. Android TV veya eski bir telefon gibi ram miktarı düşük cihazlarda değiştirmeyin + Çok yükseğe ayarlanırsa, Android TV cihazları gibi düşük depolama alanına sahip sistemlerde sorunlara neden olabilir - HTTPS üzeri DNS - İSS engellerine karşı kullanışlu + HTTPS üzerinden DNS + ISP bloklarını atlatmak için kullanışlıdır - İndirme yolu + Klon site + Siteyi kaldır + Farklı bir URL ile mevcut bir sitenin klonunu ekleyin - Nginx sunucu url\'si + İndirme konumu - Dublajlı/Altyazılı Anime göster + Nginx sunucu URL\'i - Ekrana Sığdır + Dublajlı/Alt yazılı animeleri göster + + Ekrana sığdır Uzat Yakınlaştır @@ -342,21 +365,39 @@ CloudStream 3 at your own risk. Genel - Sağlayıcı Dilleri - Uygulama Düzeni - Tercih Edilen Medya + Rastgele butonu + Ana sayfada rastgele butonunu göster + Sağlayıcı dilleri + Uygulama düzeni + Tercih edilen medya + Alt yazı kodlaması + Dil + Düzen Otomatik - TV Düzeni - Telefon Düzeni - Emülatör Düzeni + TV düzeni + Telefon düzeni + Emülatör düzeni + + Birincil renk + Uygualama teması + Poster başlık konumu + Başlığı posterin altına yerleştir - Birincil Renk - Uygulama Teması anilist_key mal_key + opensubtitles_key + nginx_key + şifre123 + HavalıKullanıcıAdı + hello@world.com + 127.0.0.1 + MyCoolSite + example.com + Dil kodu (tr) + %s %s - hesap - Çıkış - Giriş + hesabı + Çıkış yap + Giriş yap Hesap değiştir Hesap ekle + Hesap oluştur Bölüm takibi ekle Eklendi %s Senkronize et @@ -378,26 +420,26 @@ %d / 10 /?? /%d - Doğrulandı %s - Doğrulama Başarısız %s + %s için doğrulama başarılı + %s için doğrulama başarısız Hiçbiri Normal Hepsi - Maks - Min + Maksimum + Minimum @string/none - Dış Hat - Depresif + Dış hat + Çökmüş Gölge Yükseltilmiş - Altyazı senkronu + Alt yazı senkronu 1000ms - Altyazı gecikmesi - Bunu altyazılar %dms erken geliyorsa kullan - Bunu altyazılar %dms geç kalıyorsa kullan - Altyazı gecikmesi yok + Alt yazı gecikmesi + Alt yazılar %dms erken gözüküyorsa bunu kullanın + Alt yazılar %dms geç gözüküyorsa bunu kullanın + Alt yazı gecikmesi yok Pijamalı hasta yağız şoföre çabucak güvendi - Tavsiye edilen - Yüklendi %s + Önerilen + %s yüklendi Dosyadan yükle + İnternetten yükle İndirilen dosya - Ana - Destekliyor - Arkaplan + Baş + Yardımcı + Geri plan Kaynak + Rastgele - Çok Yakında… + Çok yakında… Cam Cam @@ -436,5 +480,17 @@ SDR Web - Poster Resmi + Poster fotoğrafı + Oynatıcı + Çözünürlük ve başlık + Başlık + Çözünürlük + Geçersiz ID + Geçersiz veri + Hata + Alt yazılardan seçmeli alt yazıyı kaldır + Alt yazılardaki şişkinliği kaldır + Ekstralar + Fragman + diff --git a/app/src/main/res/values-vi/array.xml b/app/src/main/res/values-vi/array.xml index 243b1313..197aac78 100644 --- a/app/src/main/res/values-vi/array.xml +++ b/app/src/main/res/values-vi/array.xml @@ -261,7 +261,7 @@ Tối Xám Amoled - Flashbang + Sáng AmoledLight diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 6bdf3a37..f7d7aedf 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -1,9 +1,63 @@ + + search_providers_list + app_locale + search_type_list + auto_update + skip_update_key + prerelease_update + manual_check_update + fast_forward_button_time + benene_count + subtitle_settings_key + subtitle_settings_chromecast_key + quality_pref_key + prefer_limit_title_key + prefer_limit_title_rez_key + video_buffer_size_key + video_buffer_length_key + video_buffer_clear_key + video_buffer_disk_key + unknown_prerelease + use_system_brightness_key + swipe_enabled_key + playback_speed_enabled_key + player_resize_enabled_key + pip_enabled_key + double_tap_enabled_key + double_tap_pause_enabled_key + double_tap_seek_time_key + swipe_vertical_enabled_key + display_sub_key + show_fillers_key + show_trailers_key + show_kitsu_posters_key + random_button_key + provider_lang_key + dns_key + download_path_key + Cloudstream + app_layout_key + primary_color_key + restore_key + killswitch_key + backup_key + prefer_media_type_key + app_theme_key + episode_sync_enabled_key + log_enabled_key + show_logcat_key + bottom_title_key + poster_ui_key + subtitles_encoding_key + override_site_key + %d %s | %sMB %s • %sGB %sMB / %sMB + %dMB %s %s +%d -%d @@ -11,11 +65,11 @@ %d %.1f/10.0 %d - %s Ep %d - Cast: %s - L\'episodio %d uscirà in - %dg %do %dm - %do %dm + %s Tập %d + Diễn viên: %s + Tập %d sẽ ra mắt sau + %dd %dh %dm + %dh %dm %dm @@ -24,7 +78,9 @@ Episode Poster Main Poster Next Random + @string/play_episode Go back + @string/home_change_provider_img_des Change Provider Preview Background @@ -35,7 +91,7 @@ Bộ lọc %d phút - + CloudStream Trang Chủ Tìm Kiếm Tải Về @@ -47,6 +103,7 @@ Không có dữ liệu Thêm tuỳ chọn Tập tiếp theo + @string/synopsis Thể loại Chia sẻ Mở bằng trình duyệt @@ -55,7 +112,7 @@ Đang xem Đang chờ - Hoàn thành + Đã xem Bỏ qua Xem sau Mặc định @@ -64,12 +121,13 @@ Xem Ngay Xem Bằng Torrent Nguồn Phim - Phụ Đề + Phụ đề Thử kết nối lại… Quay lại Xem Tập Phim + - Tải Xuống + Tải xuống Đã tải Đang tải Tạm dừng @@ -130,7 +188,7 @@ Ngôn ngữ phụ đề Giữ để làm mới toàn bộ Thêm phông chữ tại %s - Đang Xem + Tiếp tục xem Loại bỏ Thông tin thêm @@ -150,26 +208,27 @@ Chế độ cửa sổ nhỏ Tiếp tục xem phim khi thoát app hoặc đang tìm kiếm Bật nút thu phóng khi xem - Điều này sẽ xóa khoảng đen của phim + Xóa khoảng đen của phim Phụ đề Cài đặt phụ đề Phụ đề Chromecast Cài đặt phụ đề Chromecast - Điều chỉnh tốc độ khi xem phim + Chỉnh tốc độ phim Có thể điều chỉnh tốc độ phát phim Vuốt để tua nhanh - Bạn có thể vuốt trái hoặc phải để tua nhanh khi đang xem phim - Vuốt để điều chỉnh âm lượng và độ sáng + Bạn có thể vuốt trái hoặc phải để tua nhanh khi xem phim + Vuốt để chỉnh độ sáng và âm lượng Vuốt từ dưới lên trên ở bên trái hoặc phải đều điều chỉnh độ sáng và âm lượng Nhấn 2 lần để tua - Chạm 2 lần để tạm dừng - Nhấn 2 lần vào bên trái hoặc màn hình để tua trước hoặc sau + Nhấn 2 lần để tạm dừng + Thời lượng tua + Nhấn 2 lần vào bên trái hoặc bên phải màn hình để tua trước hoặc sau Nhấn vào giữa để tạm dừng Sử dụng độ sáng hệ thống Sử dụng độ sáng hệ thống trong trình phát ứng dụng - + Cập nhật tiến trình xem Tự động đồng bộ tiến trình hiện tại của bạn Khôi phục dữ liệu từ bản sao lưu @@ -267,8 +326,8 @@ Phim Lẻ Phim Bộ Hoạt Hình - Anime - OVA + @string/anime + @string/ova Torrent Phim Tài Liệu Truyền Hình Châu Á @@ -294,6 +353,10 @@ Nhãn lồng tiếng Nhãn phụ đề Tiêu đề + show_hd_key + show_dub_key + show_sub_key + show_title_key Thay đổi giao diện trên poster Bạn đang dùng phiên bản mới nhất @@ -301,18 +364,18 @@ Khóa Thu Phóng - Phụ đề + Tuỳ chọn Tập tiếp - Không hiển thị lại - Bỏ qua bản cập nhật này + Không hiện lại + Bỏ qua Cập nhật Tự động chọn chất lượng phim Kí tự tối đa trên tiêu đề - Độ phân giải tối đa + Định dạng trình phát - Kích thước video cache - Dung lượng bộ nhớ đệm + Dung lượng video cache + Thời lượng bộ nhớ đệm Dung lượng video cache Xoá hình ảnh và video @@ -337,6 +400,23 @@ Phóng to Disclaimer + legal_notice_key + Any legal issues regarding the content on this application + should be taken up with the actual file hosts and providers themselves as we are not affiliated with them. + + In case of copyright infringement, please directly contact the responsible parties or the streaming websites. + + The app is purely for educational and personal use. + + CloudStream 3 does not host any content on the app, and has no control over what media is put up or taken down. + CloudStream 3 functions like any other search engine, such as Google. CloudStream 3 does not host, upload or + manage any videos, films or content. It simply crawls, aggregates and displayes links in a convenient, + user-friendly interface. + + It merely scrapes 3rd-party websites that are publicly accessable via any regular web browser. It is the + responsibility of user to avoid any actions that might violate the laws governing his/her locality. Use + CloudStream 3 at your own risk. + Tổng quan Nút ngẫu nhiên Hiện nút ngẫu nhiên trên trang chủ @@ -358,6 +438,10 @@ Đặt tiêu đề dưới poster + anilist_key + mal_key + opensubtitles_key + nginx_key Mật khẩu Tài khoản Email @@ -366,6 +450,14 @@ example.com Mã ngôn ngữ (vi) + %s %s tài khoản Đăng xuất @@ -410,7 +502,7 @@ Được đề xuất Đã tải %s - Chọn tệp + Chọn từ máy Chọn từ Internet Tệp đã tải Vai chính @@ -447,8 +539,8 @@ Id không hợp lệ Lỗi dữ liệu Lỗi - - - + Xoá phụ đề đã dùng + Loại bỏ mã hoá phụ đề + Thêm Trailer diff --git a/docs/providers.json b/docs/providers.json index d06b9fbb..babde033 100644 --- a/docs/providers.json +++ b/docs/providers.json @@ -472,7 +472,7 @@ "TheFlixToProvider": { "language": "en", "name": "TheFlix.to", - "status": 0, + "status": 1, "url": "https://theflix.to" }, "TrailersTwoProvider": { @@ -511,6 +511,12 @@ "status": 1, "url": "https://vidembed.cc" }, + "VidSrcProvider": { + "language": "en", + "name": "VidSrc", + "status": 1, + "url": "https://v2.vidsrc.me" + }, "WatchAsianProvider": { "language": "en", "name": "WatchAsian",