diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 55e61766..80f6fd73 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -139,6 +139,10 @@ android { abortOnError = false checkReleaseBuilds = false } + + buildFeatures { + buildConfig = true + } namespace = "com.lagradost.cloudstream3" } @@ -195,13 +199,13 @@ dependencies { // PlayBack implementation("com.jaredrummler:colorpicker:1.1.0") // Subtitle Color Picker implementation("com.github.recloudstream:media-ffmpeg:1.1.0") // Custom FF-MPEG Lib for Audio Codecs - implementation("com.github.teamnewpipe:NewPipeExtractor:eac850") /* For Trailers + implementation("com.github.teamnewpipe:NewPipeExtractor:6dc25f7") /* For Trailers ^ Update to Latest Commits if Trailers Misbehave, github.com/TeamNewPipe/NewPipeExtractor/commits/dev */ implementation("com.github.albfernandez:juniversalchardet:2.4.0") // Subtitle Decoding // Crash Reports (AcraApplication.kt) - implementation("ch.acra:acra-core:5.11.2") - implementation("ch.acra:acra-toast:5.11.2") + implementation("ch.acra:acra-core:5.11.3") + implementation("ch.acra:acra-toast:5.11.3") // UI Stuff implementation("com.facebook.shimmer:shimmer:0.5.0") // Shimmering Effect (Loading Skeleton) @@ -226,7 +230,7 @@ dependencies { // Downloading & Networking implementation("androidx.work:work-runtime:2.9.0") implementation("androidx.work:work-runtime-ktx:2.9.0") - implementation("com.github.Blatzar:NiceHttp:0.4.4") // HTTP Lib + implementation("com.github.Blatzar:NiceHttp:0.4.5") // HTTP Lib } tasks.register("androidSourcesJar", Jar::class) { diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/EmturbovidExtractor.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/EmturbovidExtractor.kt new file mode 100644 index 00000000..641f13d3 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/EmturbovidExtractor.kt @@ -0,0 +1,39 @@ +package com.lagradost.cloudstream3.extractors + +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.utils.ExtractorApi +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.Qualities + +open class EmturbovidExtractor : ExtractorApi() { + override var name = "Emturbovid" + override var mainUrl = "https://emturbovid.com" + override val requiresReferer = false + + override suspend fun getUrl(url: String, referer: String?): List? { + val response = app.get( + url, referer = referer ?: "$mainUrl/" + ) + val playerScript = + response.document.selectXpath("//script[contains(text(),'var urlPlay')]") + .html() + + val sources = mutableListOf() + if (playerScript.isNotBlank()) { + val m3u8Url = + playerScript.substringAfter("var urlPlay = '").substringBefore("'") + + sources.add( + ExtractorLink( + source = name, + name = name, + url = m3u8Url, + referer = "$mainUrl/", + quality = Qualities.Unknown.value, + isM3u8 = true + ) + ) + } + return sources + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/Mediafire.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/Mediafire.kt new file mode 100644 index 00000000..bdc9c66c --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/Mediafire.kt @@ -0,0 +1,43 @@ +package com.lagradost.cloudstream3.extractors + +import com.lagradost.cloudstream3.SubtitleFile +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.utils.ExtractorApi +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.INFER_TYPE +import com.lagradost.cloudstream3.utils.Qualities + +open class Mediafire : ExtractorApi() { + override val name = "Mediafire" + override val mainUrl = "https://www.mediafire.com" + override val requiresReferer = true + + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + val res = app.get(url, referer = referer).document + val title = res.select("div.dl-btn-label").text() + val video = res.selectFirst("a#downloadButton")?.attr("href") + + callback.invoke( + ExtractorLink( + this.name, + this.name, + video ?: return, + "", + getQuality(title), + INFER_TYPE + ) + ) + + } + + private fun getQuality(str: String?): Int { + return Regex("(\\d{3,4})[pP]").find(str ?: "")?.groupValues?.getOrNull(1)?.toIntOrNull() + ?: Qualities.Unknown.value + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/Rabbitstream.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/Rabbitstream.kt index 498eb6a4..d5b52dd7 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/Rabbitstream.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/Rabbitstream.kt @@ -16,13 +16,13 @@ import javax.crypto.Cipher import javax.crypto.spec.IvParameterSpec import javax.crypto.spec.SecretKeySpec -// Code found in https://github.com/Claudemirovsky/keys -// special credits to @Claudemirovsky for providing key +// Code found in https://github.com/theonlymo/keys +// special credits to @theonlymo for providing key class Megacloud : Rabbitstream() { override val name = "Megacloud" override val mainUrl = "https://megacloud.tv" override val embed = "embed-2/ajax/e-1" - override val key = "https://raw.githubusercontent.com/Claudemirovsky/keys/e1/key" + override val key = "https://raw.githubusercontent.com/theonlymo/keys/e1/key" } class Dokicloud : Rabbitstream() { @@ -35,7 +35,7 @@ open class Rabbitstream : ExtractorApi() { override val mainUrl = "https://rabbitstream.net" override val requiresReferer = false open val embed = "ajax/embed-4" - open val key = "https://raw.githubusercontent.com/Claudemirovsky/keys/e4/key" + open val key = "https://raw.githubusercontent.com/theonlymo/keys/e4/key" override suspend fun getUrl( url: String, diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/StreamWishExtractor.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/StreamWishExtractor.kt new file mode 100644 index 00000000..77d98e49 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/StreamWishExtractor.kt @@ -0,0 +1,34 @@ +package com.lagradost.cloudstream3.extractors + +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.network.WebViewResolver +import com.lagradost.cloudstream3.utils.ExtractorApi +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.Qualities + +open class StreamWishExtractor : ExtractorApi() { + override var name = "StreamWish" + override var mainUrl = "https://streamwish.to" + override val requiresReferer = false + + override suspend fun getUrl(url: String, referer: String?): List? { + val response = app.get( + url, referer = referer ?: "$mainUrl/", interceptor = WebViewResolver( + Regex("""master\.m3u8""") + ) + ) + val sources = mutableListOf() + if (response.url.contains("m3u8")) + sources.add( + ExtractorLink( + source = name, + name = name, + url = response.url, + referer = referer ?: "$mainUrl/", + quality = Qualities.Unknown.value, + isM3u8 = true + ) + ) + return sources + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/VidhideExtractor.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/VidhideExtractor.kt new file mode 100644 index 00000000..a5307d93 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/VidhideExtractor.kt @@ -0,0 +1,34 @@ +package com.lagradost.cloudstream3.extractors + +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.network.WebViewResolver +import com.lagradost.cloudstream3.utils.ExtractorApi +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.Qualities + +open class VidhideExtractor : ExtractorApi() { + override var name = "VidHide" + override var mainUrl = "https://vidhide.com" + override val requiresReferer = false + + override suspend fun getUrl(url: String, referer: String?): List? { + val response = app.get( + url, referer = referer ?: "$mainUrl/", interceptor = WebViewResolver( + Regex("""master\.m3u8""") + ) + ) + val sources = mutableListOf() + if (response.url.contains("m3u8")) + sources.add( + ExtractorLink( + source = name, + name = name, + url = response.url, + referer = referer ?: "$mainUrl/", + quality = Qualities.Unknown.value, + isM3u8 = true + ) + ) + return sources + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/Vidplay.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/Vidplay.kt index 8653a347..b9a07a6d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/Vidplay.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/Vidplay.kt @@ -10,8 +10,8 @@ import com.lagradost.cloudstream3.utils.M3u8Helper import javax.crypto.Cipher import javax.crypto.spec.SecretKeySpec -// Code found in https://github.com/Claudemirovsky/worstsource-keys -// special credits to @Claudemirovsky for providing key +// Code found in https://github.com/KillerDogeEmpire/vidplay-keys +// special credits to @KillerDogeEmpire for providing key class MyCloud : Vidplay() { override val name = "MyCloud" @@ -27,7 +27,7 @@ open class Vidplay : ExtractorApi() { override val mainUrl = "https://vidplay.site" override val requiresReferer = true open val key = - "https://raw.githubusercontent.com/Claudemirovsky/worstsource-keys/keys/keys.json" + "https://raw.githubusercontent.com/KillerDogeEmpire/vidplay-keys/keys/keys.json" override suspend fun getUrl( url: String, diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/YoutubeExtractor.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/YoutubeExtractor.kt index 23704e90..4e854630 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/extractors/YoutubeExtractor.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/YoutubeExtractor.kt @@ -70,19 +70,18 @@ open class YoutubeExtractor : ExtractorApi() { } } ytVideos[url]?.mapNotNull { - if (it.isVideoOnly || it.height <= 0) return@mapNotNull null + if (it.isVideoOnly() || it.height <= 0) return@mapNotNull null ExtractorLink( this.name, this.name, - it.url ?: return@mapNotNull null, + it.content ?: return@mapNotNull null, "", it.height ) }?.forEach(callback) ytVideosSubtitles[url]?.mapNotNull { - SubtitleFile(it.languageTag ?: return@mapNotNull null, it.url ?: return@mapNotNull null) + SubtitleFile(it.languageTag ?: return@mapNotNull null, it.content ?: return@mapNotNull null) }?.forEach(subtitleCallback) } - } \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/network/WebViewResolver.kt b/app/src/main/java/com/lagradost/cloudstream3/network/WebViewResolver.kt index 9171aed9..2c11bcdd 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/network/WebViewResolver.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/network/WebViewResolver.kt @@ -2,6 +2,8 @@ package com.lagradost.cloudstream3.network import android.annotation.SuppressLint import android.net.http.SslError +import android.os.Handler +import android.os.Looper import android.webkit.* import com.lagradost.cloudstream3.AcraApplication import com.lagradost.cloudstream3.AcraApplication.Companion.context @@ -27,15 +29,26 @@ import java.net.URI * @param additionalUrls this will make resolveUsingWebView also return all other requests matching the list of Regex. * @param userAgent if null then will use the default user agent * @param useOkhttp will try to use the okhttp client as much as possible, but this might cause some requests to fail. Disable for cloudflare. + * @param script pass custom js to execute + * @param scriptCallback will be called with the result from custom js * */ class WebViewResolver( val interceptUrl: Regex, val additionalUrls: List = emptyList(), val userAgent: String? = USER_AGENT, - val useOkhttp: Boolean = true + val useOkhttp: Boolean = true, + val script: String? = null, + val scriptCallback: ((String) -> Unit)? = null ) : Interceptor { + constructor( + interceptUrl: Regex, + additionalUrls: List = emptyList(), + userAgent: String? = USER_AGENT, + useOkhttp: Boolean = true + ) : this(interceptUrl, additionalUrls, userAgent, useOkhttp, null, null) + companion object { var webViewUserAgent: String? = null @@ -136,6 +149,14 @@ class WebViewResolver( val webViewUrl = request.url.toString() println("Loading WebView URL: $webViewUrl") + if (script != null) { + val handler = Handler(Looper.getMainLooper()) + handler.post { + view.evaluateJavascript("$script") + { scriptCallback?.invoke(it) } + } + } + if (interceptUrl.containsMatchIn(webViewUrl)) { fixedRequest = request.toRequest()?.also { requestCallBack(it) diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollAdapter.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollAdapter.kt index 9d95a5fa..666fbc24 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollAdapter.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/home/HomeScrollAdapter.kt @@ -81,6 +81,7 @@ class HomeScrollAdapter : RecyclerView.Adapter() { binding.homeScrollPreviewTags.apply { text = card.tags?.joinToString(" • ") ?: "" isGone = card.tags.isNullOrEmpty() + maxLines = 2 } binding.homeScrollPreviewTitle.text = card.name } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/AbstractPlayerFragment.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/AbstractPlayerFragment.kt index 17a90da9..cfa6682d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/AbstractPlayerFragment.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/AbstractPlayerFragment.kt @@ -102,6 +102,8 @@ abstract class AbstractPlayerFragment( throw NotImplementedError() } + open fun playerStatusChanged(){} + open fun playerDimensionsLoaded(width: Int, height: Int) { throw NotImplementedError() } @@ -431,6 +433,7 @@ abstract class AbstractPlayerFragment( is StatusEvent -> { updateIsPlaying(wasPlaying = event.wasPlaying, isPlaying = event.isPlaying) + playerStatusChanged() } is PositionEvent -> { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt index de5aa55e..e8d74752 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/FullScreenPlayer.kt @@ -1480,7 +1480,6 @@ open class FullScreenPlayer : AbstractPlayerFragment() { playerGoBack.setOnClickListener { activity?.popCurrentPage() - activity?.showSystemUI() } playerSourcesBtt.setOnClickListener { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt index 386e8df0..ceb4728d 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/GeneratorPlayer.kt @@ -146,6 +146,12 @@ class GeneratorPlayer : FullScreenPlayer() { } } + override fun playerStatusChanged() { + if(player.getIsPlaying()){ + viewModel.forceClearCache = false + } + } + private fun noSubtitles(): Boolean { return setSubtitles(null) } @@ -913,10 +919,15 @@ class GeneratorPlayer : FullScreenPlayer() { override fun playerError(exception: Throwable) { Log.i(TAG, "playerError = $currentSelectedLink") + if(!hasNextMirror()){ + viewModel.forceClearCache = true + } super.playerError(exception) } private fun noLinksFound() { + viewModel.forceClearCache = true + showToast(R.string.no_links_found_toast, Toast.LENGTH_SHORT) activity?.popCurrentPage() } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerGeneratorViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerGeneratorViewModel.kt index 3179cb9f..0d98f205 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerGeneratorViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/PlayerGeneratorViewModel.kt @@ -45,6 +45,8 @@ class PlayerGeneratorViewModel : ViewModel() { */ private var currentLoadingEpisodeId: Int? = null + var forceClearCache = false + fun setSubtitleYear(year: Int?) { _currentSubtitleYear.postValue(year) } @@ -168,7 +170,7 @@ class PlayerGeneratorViewModel : ViewModel() { } } - fun loadLinks(clearCache: Boolean = false, type: LoadType = LoadType.InApp) { + fun loadLinks(type: LoadType = LoadType.InApp) { Log.i(TAG, "loadLinks") currentJob?.cancel() @@ -183,7 +185,7 @@ class PlayerGeneratorViewModel : ViewModel() { // load more data _loadingLinks.postValue(Resource.Loading()) val loadingState = safeApiCall { - generator?.generateLinks(type = type, clearCache = clearCache, callback = { + generator?.generateLinks(type = type, clearCache = forceClearCache, callback = { currentLinks.add(it) // Clone to prevent ConcurrentModificationException normalSafeApiCall { diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/player/RepoLinkGenerator.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/player/RepoLinkGenerator.kt index 5626e9a0..0a194785 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/player/RepoLinkGenerator.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/player/RepoLinkGenerator.kt @@ -2,6 +2,7 @@ package com.lagradost.cloudstream3.ui.player import android.util.Log import com.lagradost.cloudstream3.APIHolder.getApiFromNameNull +import com.lagradost.cloudstream3.APIHolder.unixTime import com.lagradost.cloudstream3.LoadResponse import com.lagradost.cloudstream3.ui.APIRepository import com.lagradost.cloudstream3.ui.result.ResultEpisode @@ -10,6 +11,12 @@ import com.lagradost.cloudstream3.utils.ExtractorUri import kotlin.math.max import kotlin.math.min +data class Cache( + val linkCache: MutableSet, + val subtitleCache: MutableSet, + var lastCachedTimestamp: Long = unixTime +) + class RepoLinkGenerator( private val episodes: List, private var currentIndex: Int = 0, @@ -17,7 +24,7 @@ class RepoLinkGenerator( ) : IGenerator { companion object { const val TAG = "RepoLink" - val cache: HashMap, Pair, MutableSet>> = + val cache: HashMap, Cache> = hashMapOf() } @@ -76,10 +83,10 @@ class RepoLinkGenerator( val index = currentIndex val current = episodes.getOrNull(index + offset) ?: return false - val (currentLinkCache, currentSubsCache) = if (clearCache) { - Pair(mutableSetOf(), mutableSetOf()) + val (currentLinkCache, currentSubsCache, lastCachedTimestamp) = if (clearCache) { + Cache(mutableSetOf(), mutableSetOf(), unixTime) } else { - cache[current.apiName to current.id] ?: Pair(mutableSetOf(), mutableSetOf()) + cache[current.apiName to current.id] ?: Cache(mutableSetOf(), mutableSetOf(), unixTime) } //val currentLinkCache = if (clearCache) mutableSetOf() else linkCache[index].toMutableSet() @@ -89,6 +96,12 @@ class RepoLinkGenerator( val currentSubsUrls = mutableSetOf() // makes all subs urls unique val currentSubsNames = mutableSetOf() // makes all subs names unique + val invalidateCache = unixTime - lastCachedTimestamp > 60 * 20 // 20 minutes + if(invalidateCache){ + currentLinkCache.clear() + currentSubsCache.clear() + } + currentLinkCache.filter { allowedTypes.contains(it.type) }.forEach { link -> currentLinks.add(link.url) callback(link to null) @@ -147,7 +160,7 @@ class RepoLinkGenerator( } } ) - cache[Pair(current.apiName, current.id)] = Pair(currentLinkCache, currentSubsCache) + cache[Pair(current.apiName, current.id)] = Cache(currentLinkCache, currentSubsCache, unixTime) return result } diff --git a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginsViewModel.kt b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginsViewModel.kt index 471105be..151c8d57 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginsViewModel.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/ui/settings/extensions/PluginsViewModel.kt @@ -160,7 +160,7 @@ class PluginsViewModel : ViewModel() { PluginManager.downloadPlugin( activity, metadata.url, - metadata.name, + metadata.internalName, repo, isEnabled ) to message @@ -257,4 +257,4 @@ class PluginsViewModel : ViewModel() { false to downloadedPlugins.filterTvTypes().filterLang().sortByQuery(currentQuery) ) } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/Event.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/Event.kt index 57a5f8e4..a0dfe734 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/Event.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/Event.kt @@ -3,18 +3,24 @@ package com.lagradost.cloudstream3.utils class Event { private val observers = mutableSetOf<(T) -> Unit>() - val size : Int get() = observers.size + val size: Int get() = observers.size operator fun plusAssign(observer: (T) -> Unit) { - observers.add(observer) + synchronized(observers) { + observers.add(observer) + } } operator fun minusAssign(observer: (T) -> Unit) { - observers.remove(observer) + synchronized(observers) { + observers.remove(observer) + } } operator fun invoke(value: T) { - for (observer in observers) - observer(value) + synchronized(observers) { + for (observer in observers) + observer(value) + } } -} \ No newline at end of file +} 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 1ae1b9b5..4f9c5e8c 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt @@ -103,6 +103,7 @@ import com.lagradost.cloudstream3.extractors.Odnoklassniki import com.lagradost.cloudstream3.extractors.TauVideo import com.lagradost.cloudstream3.extractors.SibNet import com.lagradost.cloudstream3.extractors.ContentX +import com.lagradost.cloudstream3.extractors.EmturbovidExtractor import com.lagradost.cloudstream3.extractors.Hotlinger import com.lagradost.cloudstream3.extractors.FourCX import com.lagradost.cloudstream3.extractors.HDMomPlayer @@ -115,6 +116,7 @@ import com.lagradost.cloudstream3.extractors.TRsTX import com.lagradost.cloudstream3.extractors.VidMoxy import com.lagradost.cloudstream3.extractors.PixelDrain import com.lagradost.cloudstream3.extractors.MailRu +import com.lagradost.cloudstream3.extractors.Mediafire import com.lagradost.cloudstream3.extractors.OkRuSSL import com.lagradost.cloudstream3.extractors.OkRuHTTP import com.lagradost.cloudstream3.extractors.Okrulink @@ -153,6 +155,7 @@ import com.lagradost.cloudstream3.extractors.StreamSB9 import com.lagradost.cloudstream3.extractors.StreamTape import com.lagradost.cloudstream3.extractors.StreamTapeNet import com.lagradost.cloudstream3.extractors.StreamTapeXyz +import com.lagradost.cloudstream3.extractors.StreamWishExtractor import com.lagradost.cloudstream3.extractors.StreamhideCom import com.lagradost.cloudstream3.extractors.StreamhideTo import com.lagradost.cloudstream3.extractors.Streamhub2 @@ -181,6 +184,7 @@ import com.lagradost.cloudstream3.extractors.VideoVard import com.lagradost.cloudstream3.extractors.VideovardSX import com.lagradost.cloudstream3.extractors.Vidgomunime import com.lagradost.cloudstream3.extractors.Vidgomunimesb +import com.lagradost.cloudstream3.extractors.VidhideExtractor import com.lagradost.cloudstream3.extractors.Vidmoly import com.lagradost.cloudstream3.extractors.Vidmolyme import com.lagradost.cloudstream3.extractors.Vido @@ -214,6 +218,7 @@ import com.lagradost.cloudstream3.extractors.Ztreamhub import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.mvvm.normalSafeApiCall import kotlinx.coroutines.delay +import me.xdrop.fuzzywuzzy.FuzzySearch import org.jsoup.Jsoup import java.net.URL import java.util.UUID @@ -598,6 +603,18 @@ suspend fun loadExtractor( } } + // this is to match mirror domains - like example.com, example.net + for (extractor in extractorApis) { + if (FuzzySearch.partialRatio( + extractor.mainUrl, + currentUrl + ) > 80 + ) { + extractor.getSafeUrl(currentUrl, referer, subtitleCallback, callback) + return true + } + } + return false } @@ -819,6 +836,7 @@ val extractorApis: MutableList = arrayListOf( Gdriveplayer(), DatabaseGdrive(), DatabaseGdrive2(), + Mediafire(), YoutubeExtractor(), YoutubeShortLinkExtractor(), @@ -840,6 +858,9 @@ val extractorApis: MutableList = arrayListOf( Rabbitstream(), Dokicloud(), Megacloud(), + VidhideExtractor(), + StreamWishExtractor(), + EmturbovidExtractor() ) diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/InAppUpdater.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/InAppUpdater.kt index 0dce0b2a..28c18fec 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/InAppUpdater.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/InAppUpdater.kt @@ -191,7 +191,7 @@ class InAppUpdater { Update( shouldUpdate, foundAsset.browser_download_url, - tagResponse.github_object.sha, + tagResponse.github_object.sha.take(10), found.body, found.node_id ) @@ -293,7 +293,13 @@ class InAppUpdater { update.updateVersion ) ) - builder.setMessage("${update.changelog}") + + val logRegex = Regex("\\[(.*?)\\]\\((.*?)\\)") + val sanitizedChangelog = update.changelog?.replace(logRegex) { matchResult -> + matchResult.groupValues[1] + } // Sanitized because it looks cluttered + + builder.setMessage(sanitizedChangelog) val context = this builder.apply { diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt index d0a2e500..76142f72 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/UIHelper.kt @@ -35,7 +35,9 @@ import androidx.core.graphics.blue import androidx.core.graphics.drawable.toBitmapOrNull import androidx.core.graphics.green import androidx.core.graphics.red +import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat +import androidx.core.view.WindowInsetsControllerCompat import androidx.core.view.marginBottom import androidx.core.view.marginLeft import androidx.core.view.marginRight @@ -57,6 +59,7 @@ import com.google.android.material.chip.Chip import com.google.android.material.chip.ChipDrawable import com.google.android.material.chip.ChipGroup import com.lagradost.cloudstream3.CommonActivity.activity +import com.lagradost.cloudstream3.MainActivity import com.lagradost.cloudstream3.R import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.ui.result.UiImage @@ -87,8 +90,9 @@ object UIHelper { if (view == null) return view.removeAllViews() val context = view.context ?: return + val maxTags = tags.take(10) // Limited because they are too much - tags.forEach { tag -> + maxTags.forEach { tag -> val chip = Chip(context) val chipDrawable = ChipDrawable.createFromAttributes( context, @@ -180,9 +184,7 @@ object UIHelper { try { if (this is FragmentActivity) { val navHostFragment = supportFragmentManager.findFragmentById(R.id.nav_host_fragment) as? NavHostFragment? - navHostFragment?.navController?.let { - it.navigate(navigation, arguments) - } + navHostFragment?.navController?.navigate(navigation, arguments) } } catch (t: Throwable) { logError(t) @@ -402,17 +404,16 @@ object UIHelper { // Enables regular immersive mode. // For "lean back" mode, remove SYSTEM_UI_FLAG_IMMERSIVE. // Or for "sticky immersive," replace it with SYSTEM_UI_FLAG_IMMERSIVE_STICKY - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + /** BUGGED AF **/ + /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - if (window.insetsController != null) { - - window!!.insetsController?.hide(WindowInsetsCompat.Type.systemBars()) - window!!.insetsController?.systemBarsBehavior = - WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + WindowCompat.setDecorFitsSystemWindows(window, false) + WindowInsetsControllerCompat(window, View(this)).let { controller -> + controller.hide(WindowInsetsCompat.Type.systemBars()) + controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE } - } + }*/ - else { @Suppress("DEPRECATION") window.decorView.systemUiVisibility = ( View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY @@ -425,7 +426,7 @@ object UIHelper { or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or View.SYSTEM_UI_FLAG_FULLSCREEN ) - } + //} } fun FragmentActivity.popCurrentPage() { @@ -496,13 +497,13 @@ object UIHelper { } fun Activity.changeStatusBarState(hide: Boolean): Int { - @Suppress("DEPRECATION") return if (hide) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { window.insetsController?.hide(WindowInsets.Type.statusBars()) } else { + @Suppress("DEPRECATION") window.setFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN @@ -525,17 +526,16 @@ object UIHelper { // except for the ones that make the content appear under the system bars. fun Activity.showSystemUI() { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + /*if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - if (window.insetsController != null) { - window!!.insetsController?.show(WindowInsetsCompat.Type.systemBars()) - } + WindowCompat.setDecorFitsSystemWindows(window, true) + WindowInsetsControllerCompat(window, View(this)).show(WindowInsetsCompat.Type.systemBars()) - } else { - @Suppress("DEPRECATION") + } else {*/ /** WINDOW COMPAT IS BUGGY DUE TO FU*KED UP PLAYER AND TRAILERS **/ + Suppress("DEPRECATION") window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) - } + //} changeStatusBarState(isEmulatorSettings()) } diff --git a/app/src/main/res/values-ajp/strings.xml b/app/src/main/res/values-ajp/strings.xml index 131b9eec..550d83a9 100644 --- a/app/src/main/res/values-ajp/strings.xml +++ b/app/src/main/res/values-ajp/strings.xml @@ -210,7 +210,7 @@ مشي بـ\"%s\" نزل الترجمة ما تفرجيا بعد مرة - فضّي التخزين المؤقت للصور والڤيديوات + فضّي التخزين الموقت للصور والڤيديوات أفي المقدمة الجودة المفضلة (Wi-Fi) رسوم مُتَحَرِكة @@ -260,7 +260,7 @@ نسوخ موقع (clone site) زر العشوائي مدو - فرجي زر \"عشوائي\" على الصفحة الرئيسية + فرجي زر \"عشوائي\" بالصفحة الرئيسية وبصفحة الرفّ الميزات فرجي أنمي المدبلج-المترجم النسخ الإحتياطي @@ -595,4 +595,5 @@ برومو غير إتجاه الشاشة أوتوماتيكيًا حسب شكل الڤيديو رجع نعمل لاود لاللينك + نعمل كَپي للعنوان! diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 16ece880..a8e79d22 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -283,7 +283,7 @@ 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. عام زر العشوائي - إظهار زر العشوائي على الصفحة الرئيسية + إظهار زر عشوائي على الصفحة الرئيسية والمكتبة لغات المزود واجهة التطبيق المحتوى المفضل @@ -623,4 +623,5 @@ الدوران التلقائي تدوير تمكين التبديل التلقائي لاتجاه الشاشة بناءً على اتجاه الفيديو + تم نسخ العنوان! diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 27ed3d11..00c968f2 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -265,7 +265,7 @@ Jakékoli právní otázky týkající se obsahu této aplikace je třeba řešit se samotnými hostiteli a poskytovateli souborů, protože s nimi nejsme nijak spojeni. V případě porušení autorských práv se obraťte přímo na odpovědné strany nebo na webové stránky, na kterých se streamování odehrává. Aplikace je určena výhradně pro vzdělávací a osobní účely. CloudStream 3 v aplikaci nehostuje žádný obsah a nemá žádnou kontrolu nad tím, jaká média jsou v aplikaci umístěna nebo odstraněna. CloudStream 3 funguje jako jakýkoli jiný vyhledávač, například Google. Služba CloudStream 3 nehostuje, nenahrává ani nespravuje žádná videa, filmy ani obsah. Pouze vyhledává, agreguje a zobrazuje odkazy v pohodlném, uživatelsky přívětivém rozhraní. Pouze shromažďuje webové stránky třetích stran, které jsou veřejně přístupné prostřednictvím jakéhokoli běžného webového prohlížeče. Je odpovědností uživatele, aby se vyvaroval jakýchkoli akcí, které by mohly porušovat zákony platné v jeho lokalitě. Použijte CloudStream 3 na vlastní nebezpečí. Obecné Náhodné tlačítko - Zobrazit na domovské stránce náhodné tlačítko + Zobrazit na domovské stránce a v knihovně náhodné tlačítko Jazyk poskytovatelů Rozložení aplikace Preferovaná média @@ -615,4 +615,5 @@ Automatické otáčení Otočení Zapnout automatické otáčení obrazovky v závislosti na orientaci videa + Název zkopírován! diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index 0f6c4d90..02b14393 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -585,4 +585,8 @@ \n \nWollen sie dieses Element trotzdem hinzufügen, das existierende ersetzen oder diese Aktion abbrechen? Links wurden neu geladen + Drehen + Zeige einen Umschalter für Bildschirmorientierung an + Automatisch drehen + Titel kopiert! diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 508f28fe..342894f7 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -305,7 +305,7 @@ Aspecto Características Botón aleatorio - Mostrar el botón aleatorio en la página de inicio + Mostrar el botón aleatorio en la página de inicio y en la biblioteca Cuenta Cerrar sesión Cambiar cuenta @@ -591,4 +591,5 @@ Giro automático Girar Activar el cambio automático de la orientación de la pantalla en función de la orientación del vídeo + ¡Título copiado! diff --git a/app/src/main/res/values-hr/strings.xml b/app/src/main/res/values-hr/strings.xml index a81e94f0..3e6759a0 100644 --- a/app/src/main/res/values-hr/strings.xml +++ b/app/src/main/res/values-hr/strings.xml @@ -94,7 +94,7 @@ Kopiraj Zatvori Očisti - Sačuvaj + Spremi Brzina playera Postavke titlova Boja teksta @@ -298,7 +298,7 @@ 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. Općenito Random gumb - Prikaži gumb za slučajni odabir reprodukcija na početnoj stranici + Prikaži gumb za slučajni odabir reprodukcija na početnoj stranici i biblioteci Jezici pružatelja usluga Izgled aplikacije Preferirani mediji @@ -609,4 +609,12 @@ Preskoči odabir računa pri pokretanju Upravljanje računima Uredi račun + Linkovi ponovno učitani + Rotiraj + Prikaži gumb za prebacivanje orijentacije zaslona + Omogućuje automatsko mijenjanje orijentacije zaslona na temelju orijentacije videa + Automatsko rotiranje + Naslov je kopiran! + rotiraj_video_tipka + automatski_rotiraj_video_tipka diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index fbd44d91..04e27c85 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -219,4 +219,27 @@ 言語の自動選択 リンクの読み込みエラー 137905 + リンクがリロードされました + 自動バグ報告を無効にする + プレーヤーの速度 + 字幕設定 + ダブ + サブ + 説明が見つかりません + スワイプして設定を変更します + 輪郭の色 + 字幕の標高 + %d ベネネスが開発者に与えられました + このプロバイダーが正しく動作するには VPN が必要になる可能性があります + このプロバイダーは torrent です、VPN をお勧めします + プレーヤーのサイズ変更ボタン + 黒い境界線を削除します + プレーヤーの字幕設定 + Chromecastの字幕 + Chromecastの字幕設定 + プレーヤーに速度オプションを追加します + スワイプして探す + 次のエピソードを自動再生する + 現在のエピソードが終了したら次のエピソードを開始する + 長押しするとデフォルトにリセットされます diff --git a/app/src/main/res/values-ne/strings.xml b/app/src/main/res/values-ne/strings.xml index 42eba3cc..1e23f8af 100644 --- a/app/src/main/res/values-ne/strings.xml +++ b/app/src/main/res/values-ne/strings.xml @@ -1,2 +1,88 @@ - + + गति (%.2fx) + अर्को अनियमित + पृष्ठभूमि देखाउनुहोस् + %1$dh %2$dm + पोस्टर + पछाडी जाउ + एपिसोडको पोस्टर + प्रोवाइडर परिवर्तन गर्नुहोस् + रेटिंग: %.1f + %1$dd %2$dh %3$dm + %dm + विज्ञापन + मुख्य पोस्टर + %1$s Ep %2$d + अभिनेता:%s + नयाँ अपडेट भेटियो! +\n%1$s -> %2$s + फिलर + %d मिनेट + क्लाउडस्ट्रीम + क्लाउडस्ट्रीममा प्ले गर्नुहोस् + होम् + खोजी + डाउनलोडस + सेटिङह + खोज्नुहोस्… + %s खोज्नुहोस्… + थप विकल्पहरू + विधाहरू + सेयर गर्नुहोस् + ब्राउजरमा खाेल्नुहाेस् + ब्राउजर + लोड गर्न छोड्नुहोस् + लोड हुँदै… + होल्डमा भएको + अधुरै छाडेको + हेर्ने योजना + चलचित्र प्ले गर्नुहोस् + ट्रेलर प्ले गर्नुहोस् + लाइभस्ट्रिम प्ले गर्नुहोस् + उपशीर्षक + पुनः प्रयास गर्नुहोस… + पछाडि जानुहोस् + एपिसोड प्ले गर्नुहोस् + डाउनलोड + डाउनलोड भयो + डाउनलोड हुदैछ + डाउनलोड रोकियो + डाउनलोड सुरु भयो + डाउनलोड असफल भयो + डाउनलोड रद्द गरियो + डाउनलोड भयो + अपडेट सुरु + स्ट्रिम + लिङ्क लोड गर्दा त्रुटि भयो + लिङ्कहरू रिलोड गरियो + भित्री स्टोरेज + Dub + Sub + फाइल मेट्नुहोस् + फाइल प्ले गर्नुहोस् + डाउनलोड सुचारु गर्नुहोस् + डाउनलोड रोक्नुहोस् + थप जानकारी + लुकाउनुहोस् + प्ले + जानकारी + बुकमार्कहरू फिल्टर गर्नुहोस् + बुकमार्कहरू + हटाउनुहोस् + हेरेको स्थिति राख्नुहोस् + कपी + बन्द + खाली गर्नुहोस् + सेव + एपिसोड %d रिलीज हुने समय + डाटा छैन + अर्को एपिसोड + हेर्दै गरेको + पुरा भएको + पुन: हेर्दै + स्ट्रिम टोरेन्ट + स्रोतहरू + स्वचालित बग रिपोर्टिङ असक्षम गर्नुहोस् + लागू गर्नुहोस् + diff --git a/app/src/main/res/values-no/strings.xml b/app/src/main/res/values-no/strings.xml index a1ccec46..49b559ed 100644 --- a/app/src/main/res/values-no/strings.xml +++ b/app/src/main/res/values-no/strings.xml @@ -532,4 +532,11 @@ \nLaster ikke inn noen utvidelser ved oppstart til filen er fjernet. Biblioteket ditt er tomt :( \nLogg inn på en bibliotekkonto eller legg til programmer i ditt lokale bibliotek. + Rediger + Profiler + Favoritter + Lås profil + Bruk + Hjelp + Profilbakgrunn diff --git a/app/src/main/res/values-or/strings.xml b/app/src/main/res/values-or/strings.xml index eb3d7cd3..bdc55780 100644 --- a/app/src/main/res/values-or/strings.xml +++ b/app/src/main/res/values-or/strings.xml @@ -158,4 +158,5 @@ ପରବର୍ତ୍ତୀ ଅଧ୍ୟାୟ କୌଣସି ତଥ୍ୟ ନାହିଁ %1$s ଅ %2$d + ଆଦ୍ୟ ବାଦ୍ ଦିଅ diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 393ca0ba..82bd3581 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -421,12 +421,12 @@ Oтoбpaжeниe Трейлер %s (отключено) - Следующий + Далее В CloudStream по умолчанию не установлены сайты. Вам необходимо установить сайты из репозиториев. \n -\nИз-за безмозглой DMCA-атаки со стороны Sky UK Limited 🤮 мы не можем привязать сайт репозитория в приложении. +\nИз-за безмозглой жалобы DMCA от Sky UK Limited 🤮 мы не можем привязать сайт репозитория в приложении. \n -\nПрисоединяйтесь к нашему Discord или ищите в интернете. +\nПрисоединяйтесь к нашему Discord-серверу или найдите в интернете. Недопустимые данные Разрешение и название Предыдущий @@ -551,4 +551,5 @@ \nБудет иметь общий приоритет видео 10. \n \nПРИМЕЧАНИЕ. Если сумма равна 10 или более, плеер автоматически пропустит загрузку при загрузке этой ссылки! + Ссылки перезагружены diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index 2a90a307..0f6f37cd 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -13,7 +13,7 @@ Affisch Ingen Data Mer Instälningar - Gå tillbacka + Gå tillbaka Nästa avsnitt Affisch Genrer @@ -24,8 +24,8 @@ Tittar på Pausad Avslutad - Dropped - Plannerad + Släppt + Planerad Spela Upp Strömma Torrent Källor @@ -39,10 +39,10 @@ Dub Sub Ta bort - Spela upp + Spela upp fil Inaktivera automatisk felrapportering Mer information - Hide + Göm @string/result_poster_img_des Spela upp Info @@ -64,10 +64,10 @@ Font Sök med följande leverantörer Sök med följande filmtyper - %d Bananer donerade till utvecklarna + %d bananer donerade till utvecklarna Inga bananer givna Automatisk val av undertextspråk - Automatisk nerladdaning av språk + Automatisk nedladdning av språk Håll inne för att återställa till standard Fortsätt titta Ta bort @@ -297,7 +297,7 @@ Referer Nästa 1000 ms - Lägga till en klon av en befintlig webbplats med en annan webbadress. + Lägga till en klon av en befintlig webbplats med en annan webbadress Ogiltigt ID Ogiltig webbadress Orsakar krascher om inställningen är för hög på enheter med lågt minne, t.ex. Android TV. @@ -403,7 +403,7 @@ Starta om Testa leverantörer Föredragen videokvalitet (Mobildata) - Visa en slumpknapp på förstasidan + Visa slumpmässig knapp på förstasidan och biblioteket 18+ Ljudspår Direktsändningar @@ -433,4 +433,163 @@ Hjälp Kvalitet Ström + Databasens namn + All %s har redan laddats ner + Ladda ner alla tillägg från den här databasen? + Felsäkert läge på + Applicera vid omstart + Intern spelare + Kamera HD + Tillägg nedladdad + Lager URL + Börjat hämta %1$d %2$s… + Affisch titel plats + Laddat %s + Huvudsaklig + Stödjande + Bakgrund + Offentlig lista + Språk + Installera tillägget först + Önskad videospelare + Spelare visas - Sök förlopp + Sök förlopp som används när spelaren är synlig + Starta + Stopp + Återställ + Avslutat prenumerationen på %s + Avsnitt %d släppt! + Den här listan är tom. Försök byta till en annan. + Tillägg borttagen + Tillägg laddade + Tillägg + Säkerhetskopierings antal + Uppdatera visnings förlopp + Välj läge för att filtrera nedladdning av plugins + Utgåva + Status + Ange PIN-kod + Ange PIN-kod för %s + Ange aktuell PIN-kod + Lås profil + Felaktig PIN-kod. Försök igen. + PIN-koden måste vara fyra tecken + Välj ett konto + Hantera konton + Redigera konto + Loggat in som %s + Hoppa över val av konto vid start + auto_rotera_video_nyckel + Förbi passera blockering av GitHub genom att använda jsDelivr. Kan göra att uppdateringar försenas med några dagar. + Funktion + Önskad media + Lägg titeln under affischen + Tillagt %s + Lägg till spårning + Betygsatt + Inaktivera + Web + Affischbild + Vad vill du se + Lägg till databas + Uppdaterade %d tillägg + Nedladdat %1$d %2$s + Inaktiverad: %d + Ej hämtad: %d + Visa community databaser + Blandad inledning + Skippa %s + CloudStream har inga webbplatser installerade som standard. Du måste installera webbplatserna från databaser. +\n +\nPå grund av en hjärnlös DMCA-borttagning av Sky UK Limited kan vi inte länka databaser på denna applikation. +\n +\nGå med i vår Discord eller sök online. + Välj bibliotek + Ditt bibliotek är tomt :( +\nLogga in på ett bibliotekskonto eller lägg till program i ditt lokala bibliotek. + Visa hoppa över popups för introduktion/eftertexter + Ta bort från sett + Fil i säkertläge hittades! +\nLaddar inte några tillägg vid start tills filen har tagits bort. + Uppdaterar prenumererade program + Prenumererad + Prenumerera + UI kunde inte skapas korrekt, detta är en MASSIV BUG och bör rapporteras omedelbart %s + Du har redan röstat + Avprenumerera + Lägg till i favoriter + Lägg till + Potentiell Dublett Hittad + Ta bort från favoriter + Ersätt + Ersätt alla + Filler + Förbikoppla ISP + Kamera + Kamera + Alla tillägg stängdes av på grund av en krasch för att hjälpa dig hitta den som orsakar problem. + Storlek + Författarna + Stödd + Inga tillägg hittades i databasen + Databasen hittades inte, kontrollera URL:n och prova VPN + Flerfils nedladdning + Tillägg + Hämtat: %d + Betyg: %s + För mycket text. Det gick inte att spara till urklipp. + Hög kvalite + Synka + Slutet + Blandad avslut + Prenumererar på %s + Visa krasch info + HLS spellista + Kunde inte ladda %s + Inledning + Sammanfattning + Gester + %s autentiserad + Statister + Länka till strömmen + Radera databasen + Profil bakgrund + WP + Auto rotera + Rotera + Visa en växlingsknapp för skärmorientering + Aktivera automatisk växling av skärmorientering baserat på videoorientering + Länkar omladdade + Spelare dold - Sökförlopp + Blu-ray + Detta kommer också att ta bort alla tillägg för databasen + Ladda ner listan över webbplatser du vill använda + %s (Inaktiverad) + Beskrivning + Eftertexter + Introduktion + Favoriter + Ange standard + %s togs bort från favoriter + %s har lagts till i favoriter + Använd standard konto + rotera_video_nyckel + PIN-kod + Sök mängden som används när spelaren är dold + Det verkar som om ett potentiellt duplicerat objekt redan finns i ditt bibliotek: +\n +\n\'%s.\' +\n +\nVill du lägga till det här objektet ändå, ersätta det befintliga eller avbryta åtgärden? + Det verkar som om ett potentiellt duplicerat objekt redan finns i ditt bibliotek: \'%s.\' +\n +\nVill du lägga till det här objektet ändå, ersätta det befintliga eller avbryta åtgärden? + Här kan du ändra hur källorna ska sorteras, om en video har högre prioritet visas den högre upp i källvalet. Summan av källprioriteten och kvalitetsprioriteten är videoprioriteten. +\n +\nKälla A: 3 +\nKvalitet B: 7 +\nKommer att ha en kombinerad videoprioritet på 10. +\n +\nOBS: Om summan är 10 eller mer kommer spelaren automatiskt att hoppa över laddningen när den länken laddas! + Titel kopierad! diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index 4d8ae42c..e8b7881a 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -308,7 +308,7 @@ 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. Genel Rastgele İçerik - Ana sayfada rastgele bir film veya dizi seçen bir tuş göster + Anasayfada ve Kütüphanede rastgele düğmesini göster Sağlayıcı dilleri Uygulama düzeni Tercih edilen medya @@ -638,4 +638,5 @@ Döndür Video yönüne göre ekran yönünün otomatik olarak değişmesini sağla Bağlantılar Yeniden Yüklendi + Başlık kopyalandı! diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index aae04cb0..58bd4a7b 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -282,7 +282,7 @@ Особливості Загальне Випадкова кнопка - Показувати кнопку на Головній сторінці, яка вибирає випадковий фільм чи серіал + Показувати кнопку на Головній сторінці та в Бібліотеці, яка вибирає випадковий фільм чи серіал Мови постачальника Макет застосунку Бажані медіа @@ -591,4 +591,5 @@ auto_rotate_video_key Автоповорот Ввімкнути автоматичний поворот екрана на основі орієнтації відео + Назву скопійовано! diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index ba81f968..cb38c6d1 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -309,7 +309,7 @@ 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. 通用 随机按钮 - 在主页中显示随机按钮 + 在主页和库中显示随机按钮 片源语言 应用布局 首选类型 @@ -592,4 +592,22 @@ \n注意:如果总和为 10 或更多,则加载该链接时播放器将自动跳过加载! 质量 个人资料背景 + PIN + 链接已重新加载 + 禁用 + PIN码不正确,请再试一次。 + PIN码必须为4个字符 + 选择一个账户 + 账户管理 + 订阅 + 取消订阅 + 添加 + 替换 + 替换全部 + 仓库中未找到插件 + 旋转 + 自动旋转 + 以%s的身份登录 + 使用默认账户 + 选择过滤插件的下载模式 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 678bc568..eb0dc3a8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -67,6 +67,8 @@ enable_nsfw_on_providers_key skip_startup_account_select_key enable_skip_op_from_database + rotate_video_key + auto_rotate_video_key %d %s | %s %s • %s @@ -736,9 +738,7 @@ Skip account selection at startup Use Default Account Rotate - rotate_video_key Display a toggle button for screen orientation - auto_rotate_video_key Enable automatic switching of screen orientation based on video orientation Auto rotate diff --git a/build.gradle.kts b/build.gradle.kts index 939c62a6..d2959529 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,8 +5,8 @@ buildscript { mavenCentral() } dependencies { - classpath("com.android.tools.build:gradle:8.1.4") - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.21") + classpath("com.android.tools.build:gradle:8.2.1") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.9.22") classpath("org.jetbrains.dokka:dokka-gradle-plugin:1.9.10") // NOTE: Do not place your application dependencies here; they belong @@ -22,7 +22,7 @@ allprojects { } plugins { - id("com.google.devtools.ksp") version "1.9.21-1.0.15" apply false + id("com.google.devtools.ksp") version "1.9.22-1.0.16" apply false } tasks.register("clean") { diff --git a/fastlane/metadata/android/hr/changelogs/2.txt b/fastlane/metadata/android/hr/changelogs/2.txt new file mode 100644 index 00000000..5736c7ce --- /dev/null +++ b/fastlane/metadata/android/hr/changelogs/2.txt @@ -0,0 +1 @@ +- Dodan je dnevnik promjena! diff --git a/fastlane/metadata/android/hr/full_description.txt b/fastlane/metadata/android/hr/full_description.txt new file mode 100644 index 00000000..9272be26 --- /dev/null +++ b/fastlane/metadata/android/hr/full_description.txt @@ -0,0 +1,10 @@ +CloudStream-3 omogućuje emitiranje i preuzimanje filmova, TV serija i animea. + +Aplikacija ne koristi oglase i analitike te +podržava stranice s trailerima, filmovima i više, npr. + +Oznake + +Preuzimanja titlova + +Chromecast podrška diff --git a/fastlane/metadata/android/hr/short_description.txt b/fastlane/metadata/android/hr/short_description.txt new file mode 100644 index 00000000..09b5d4c5 --- /dev/null +++ b/fastlane/metadata/android/hr/short_description.txt @@ -0,0 +1 @@ +Emitirajte i preuzmite filmove, TV serije i anime. diff --git a/fastlane/metadata/android/hr/title.txt b/fastlane/metadata/android/hr/title.txt new file mode 100644 index 00000000..dde89d58 --- /dev/null +++ b/fastlane/metadata/android/hr/title.txt @@ -0,0 +1 @@ +CloudStream diff --git a/fastlane/metadata/android/sv-SE/changelogs/2.txt b/fastlane/metadata/android/sv-SE/changelogs/2.txt new file mode 100644 index 00000000..efc57c61 --- /dev/null +++ b/fastlane/metadata/android/sv-SE/changelogs/2.txt @@ -0,0 +1 @@ +- Ändringslogg tillagd! diff --git a/fastlane/metadata/android/sv-SE/full_description.txt b/fastlane/metadata/android/sv-SE/full_description.txt new file mode 100644 index 00000000..977b37b9 --- /dev/null +++ b/fastlane/metadata/android/sv-SE/full_description.txt @@ -0,0 +1,10 @@ +CloudStream-3 låter dig streama och ladda ner filmer, TV-serier och anime. + +Appen levereras utan annonser och analyser och +stöder flera trailer- och film webbplatser och mer, t.ex. + +Bokmärken + +Nedladdning av undertexter + +Stöd för Chromecast diff --git a/fastlane/metadata/android/sv-SE/short_description.txt b/fastlane/metadata/android/sv-SE/short_description.txt new file mode 100644 index 00000000..c982f004 --- /dev/null +++ b/fastlane/metadata/android/sv-SE/short_description.txt @@ -0,0 +1 @@ +Streama och ladda ner filmer, TV serier och anime. diff --git a/fastlane/metadata/android/sv-SE/title.txt b/fastlane/metadata/android/sv-SE/title.txt new file mode 100644 index 00000000..dde89d58 --- /dev/null +++ b/fastlane/metadata/android/sv-SE/title.txt @@ -0,0 +1 @@ +CloudStream diff --git a/gradle.properties b/gradle.properties index b8aa1f91..6a873a6a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,6 +19,5 @@ android.useAndroidX=true # android.enableJetifier=true # Kotlin code style for this project: "official" or "obsolete": kotlin.code.style=official -android.defaults.buildfeatures.buildconfig=true android.nonTransitiveRClass=false android.nonFinalResIds=false \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index d7c9c9bc..fc2d0f86 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Fri Apr 30 17:11:15 CEST 2021 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME