forked from recloudstream/cloudstream
added DOH and Cache + fixed trailers for series
This commit is contained in:
parent
f9ef71a389
commit
b8195f2ec6
10 changed files with 184 additions and 12 deletions
|
@ -63,6 +63,9 @@ android {
|
||||||
debuggable true
|
debuggable true
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
}
|
}
|
||||||
|
debug {
|
||||||
|
applicationIdSuffix ".debug"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
sourceCompatibility JavaVersion.VERSION_1_8
|
||||||
|
@ -141,5 +144,6 @@ dependencies {
|
||||||
implementation "androidx.work:work-runtime-ktx:2.7.0-rc01"
|
implementation "androidx.work:work-runtime-ktx:2.7.0-rc01"
|
||||||
|
|
||||||
// Networking
|
// Networking
|
||||||
implementation "com.squareup.okhttp3:okhttp:4.9.0"
|
implementation "com.squareup.okhttp3:okhttp:4.9.1"
|
||||||
|
implementation "com.squareup.okhttp3:okhttp-dnsoverhttps:4.9.1"
|
||||||
}
|
}
|
|
@ -26,6 +26,9 @@ import com.lagradost.cloudstream3.APIHolder.apis
|
||||||
import com.lagradost.cloudstream3.APIHolder.getApiDubstatusSettings
|
import com.lagradost.cloudstream3.APIHolder.getApiDubstatusSettings
|
||||||
import com.lagradost.cloudstream3.APIHolder.restrictedApis
|
import com.lagradost.cloudstream3.APIHolder.restrictedApis
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
|
import com.lagradost.cloudstream3.network.get
|
||||||
|
import com.lagradost.cloudstream3.network.initRequestClient
|
||||||
|
import com.lagradost.cloudstream3.network.text
|
||||||
import com.lagradost.cloudstream3.receivers.VideoDownloadRestartReceiver
|
import com.lagradost.cloudstream3.receivers.VideoDownloadRestartReceiver
|
||||||
import com.lagradost.cloudstream3.ui.APIRepository
|
import com.lagradost.cloudstream3.ui.APIRepository
|
||||||
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO
|
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO
|
||||||
|
@ -46,6 +49,7 @@ import com.lagradost.cloudstream3.utils.UIHelper.toPx
|
||||||
import kotlinx.android.synthetic.main.activity_main.*
|
import kotlinx.android.synthetic.main.activity_main.*
|
||||||
import kotlinx.android.synthetic.main.fragment_result.*
|
import kotlinx.android.synthetic.main.fragment_result.*
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import java.util.zip.GZIPInputStream
|
||||||
import kotlin.concurrent.thread
|
import kotlin.concurrent.thread
|
||||||
|
|
||||||
|
|
||||||
|
@ -290,6 +294,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
true
|
true
|
||||||
) // THEME IS SET BEFORE VIEW IS CREATED TO APPLY THE THEME TO THE MAIN VIEW
|
) // THEME IS SET BEFORE VIEW IS CREATED TO APPLY THE THEME TO THE MAIN VIEW
|
||||||
updateLocale()
|
updateLocale()
|
||||||
|
initRequestClient()
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
try {
|
try {
|
||||||
if (isCastApiAvailable()) {
|
if (isCastApiAvailable()) {
|
||||||
|
@ -334,7 +339,8 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
// Fucks up anime info layout since that has its own layout
|
// Fucks up anime info layout since that has its own layout
|
||||||
cast_mini_controller_holder?.isVisible = !listOf(R.id.navigation_results,R.id.navigation_player).contains(destination.id)
|
cast_mini_controller_holder?.isVisible =
|
||||||
|
!listOf(R.id.navigation_results, R.id.navigation_player).contains(destination.id)
|
||||||
|
|
||||||
nav_view.isVisible = listOf(
|
nav_view.isVisible = listOf(
|
||||||
R.id.navigation_home,
|
R.id.navigation_home,
|
||||||
|
|
|
@ -183,7 +183,7 @@ class TrailersToProvider : MainAPI() {
|
||||||
|
|
||||||
return isSucc
|
return isSucc
|
||||||
} else if (url.contains("/episode/")) {
|
} else if (url.contains("/episode/")) {
|
||||||
val response = get(url).text
|
val response = get(url, params = mapOf("preview" to "1")).text
|
||||||
val document = Jsoup.parse(response)
|
val document = Jsoup.parse(response)
|
||||||
// val qSub = document.select("subtitle-content")
|
// val qSub = document.select("subtitle-content")
|
||||||
val subUrl = document.select("subtitle-content")?.attr("data-url") ?: ""
|
val subUrl = document.select("subtitle-content")?.attr("data-url") ?: ""
|
||||||
|
|
|
@ -0,0 +1,67 @@
|
||||||
|
package com.lagradost.cloudstream3.network
|
||||||
|
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.dnsoverhttps.DnsOverHttps
|
||||||
|
import java.net.InetAddress
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Based on https://github.com/tachiyomiorg/tachiyomi/blob/master/app/src/main/java/eu/kanade/tachiyomi/network/DohProviders.kt
|
||||||
|
*/
|
||||||
|
|
||||||
|
private fun OkHttpClient.Builder.addGenericDns(url: String, ips: List<String>) = dns(
|
||||||
|
DnsOverHttps
|
||||||
|
.Builder()
|
||||||
|
.client(build())
|
||||||
|
.url(url.toHttpUrl())
|
||||||
|
.bootstrapDnsHosts(
|
||||||
|
ips.map { InetAddress.getByName(it) }
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
|
||||||
|
fun OkHttpClient.Builder.addGoogleDns() = (
|
||||||
|
addGenericDns(
|
||||||
|
"https://dns.google/dns-query",
|
||||||
|
listOf(
|
||||||
|
"8.8.4.4",
|
||||||
|
"8.8.8.8"
|
||||||
|
)
|
||||||
|
))
|
||||||
|
|
||||||
|
fun OkHttpClient.Builder.addCloudFlareDns() = (
|
||||||
|
addGenericDns(
|
||||||
|
"https://cloudflare-dns.com/dns-query",
|
||||||
|
// https://www.cloudflare.com/ips/
|
||||||
|
listOf(
|
||||||
|
"1.1.1.1",
|
||||||
|
"1.0.0.1",
|
||||||
|
"2606:4700:4700::1111",
|
||||||
|
"2606:4700:4700::1001"
|
||||||
|
)
|
||||||
|
))
|
||||||
|
|
||||||
|
// Commented out as it doesn't work
|
||||||
|
//fun OkHttpClient.Builder.addOpenDns() = (
|
||||||
|
// addGenericDns(
|
||||||
|
// "https://doh.opendns.com/dns-query",
|
||||||
|
// // https://support.opendns.com/hc/en-us/articles/360038086532-Using-DNS-over-HTTPS-DoH-with-OpenDNS
|
||||||
|
// listOf(
|
||||||
|
// "208.67.222.222",
|
||||||
|
// "208.67.220.220",
|
||||||
|
// "2620:119:35::35",
|
||||||
|
// "2620:119:53::53",
|
||||||
|
// )
|
||||||
|
// ))
|
||||||
|
|
||||||
|
|
||||||
|
fun OkHttpClient.Builder.addAdGuardDns() = (
|
||||||
|
addGenericDns(
|
||||||
|
"https://dns.adguard.com/dns-query",
|
||||||
|
// https://github.com/AdguardTeam/AdGuardDNS
|
||||||
|
listOf(
|
||||||
|
// "Non-filtering"
|
||||||
|
"94.140.14.140",
|
||||||
|
"94.140.14.141",
|
||||||
|
)
|
||||||
|
))
|
|
@ -1,12 +1,20 @@
|
||||||
package com.lagradost.cloudstream3.network
|
package com.lagradost.cloudstream3.network
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.USER_AGENT
|
import com.lagradost.cloudstream3.USER_AGENT
|
||||||
import okhttp3.*
|
import okhttp3.*
|
||||||
import okhttp3.Headers.Companion.toHeaders
|
import okhttp3.Headers.Companion.toHeaders
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
|
import okhttp3.dnsoverhttps.DnsOverHttps
|
||||||
|
import java.io.File
|
||||||
|
import java.net.InetAddress
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
var baseClient = OkHttpClient()
|
||||||
private const val DEFAULT_TIME = 10
|
private const val DEFAULT_TIME = 10
|
||||||
private val DEFAULT_TIME_UNIT = TimeUnit.MINUTES
|
private val DEFAULT_TIME_UNIT = TimeUnit.MINUTES
|
||||||
private const val DEFAULT_USER_AGENT = USER_AGENT
|
private const val DEFAULT_USER_AGENT = USER_AGENT
|
||||||
|
@ -15,6 +23,28 @@ private val DEFAULT_DATA: Map<String, String> = mapOf()
|
||||||
private val DEFAULT_COOKIES: Map<String, String> = mapOf()
|
private val DEFAULT_COOKIES: Map<String, String> = mapOf()
|
||||||
private val DEFAULT_REFERER: String? = null
|
private val DEFAULT_REFERER: String? = null
|
||||||
|
|
||||||
|
fun Context.initRequestClient() {
|
||||||
|
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
|
val dns = settingsManager.getInt(this.getString(R.string.dns_pref), 0)
|
||||||
|
baseClient = OkHttpClient.Builder()
|
||||||
|
.cache(
|
||||||
|
// Note that you need to add a ResponseInterceptor to make this 100% active.
|
||||||
|
// The server response dictates if and when stuff should be cached.
|
||||||
|
Cache(
|
||||||
|
directory = File(cacheDir, "http_cache"),
|
||||||
|
maxSize = 50L * 1024L * 1024L // 50 MiB
|
||||||
|
)
|
||||||
|
).apply {
|
||||||
|
when (dns) {
|
||||||
|
1 -> addGoogleDns()
|
||||||
|
2 -> addCloudFlareDns()
|
||||||
|
// 3 -> addOpenDns()
|
||||||
|
4 -> addAdGuardDns()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Needs to be build as otherwise the other builders will change this object
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
/** WARNING! CAN ONLY BE READ ONCE */
|
/** WARNING! CAN ONLY BE READ ONCE */
|
||||||
val Response.text: String
|
val Response.text: String
|
||||||
|
@ -93,14 +123,13 @@ fun get(
|
||||||
timeout: Long = 0L,
|
timeout: Long = 0L,
|
||||||
interceptor: Interceptor? = null
|
interceptor: Interceptor? = null
|
||||||
): Response {
|
): Response {
|
||||||
|
val client = baseClient
|
||||||
val client = OkHttpClient().newBuilder()
|
.newBuilder()
|
||||||
.followRedirects(allowRedirects)
|
.followRedirects(allowRedirects)
|
||||||
.followSslRedirects(allowRedirects)
|
.followSslRedirects(allowRedirects)
|
||||||
.callTimeout(timeout, TimeUnit.SECONDS)
|
.callTimeout(timeout, TimeUnit.SECONDS)
|
||||||
|
|
||||||
if (interceptor != null) client.addInterceptor(interceptor)
|
if (interceptor != null) client.addInterceptor(interceptor)
|
||||||
|
|
||||||
val request = getRequestCreator(url, headers, referer, params, cookies, cacheTime, cacheUnit)
|
val request = getRequestCreator(url, headers, referer, params, cookies, cacheTime, cacheUnit)
|
||||||
return client.build().newCall(request).execute()
|
return client.build().newCall(request).execute()
|
||||||
}
|
}
|
||||||
|
@ -118,7 +147,8 @@ fun post(
|
||||||
cacheUnit: TimeUnit = DEFAULT_TIME_UNIT,
|
cacheUnit: TimeUnit = DEFAULT_TIME_UNIT,
|
||||||
timeout: Long = 0L
|
timeout: Long = 0L
|
||||||
): Response {
|
): Response {
|
||||||
val client = OkHttpClient().newBuilder()
|
val client = baseClient
|
||||||
|
.newBuilder()
|
||||||
.followRedirects(allowRedirects)
|
.followRedirects(allowRedirects)
|
||||||
.followSslRedirects(allowRedirects)
|
.followSslRedirects(allowRedirects)
|
||||||
.callTimeout(timeout, TimeUnit.SECONDS)
|
.callTimeout(timeout, TimeUnit.SECONDS)
|
||||||
|
|
|
@ -16,6 +16,7 @@ import com.lagradost.cloudstream3.MainActivity.Companion.setLocale
|
||||||
import com.lagradost.cloudstream3.MainActivity.Companion.showToast
|
import com.lagradost.cloudstream3.MainActivity.Companion.showToast
|
||||||
import com.lagradost.cloudstream3.R
|
import com.lagradost.cloudstream3.R
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
|
import com.lagradost.cloudstream3.network.initRequestClient
|
||||||
import com.lagradost.cloudstream3.ui.APIRepository
|
import com.lagradost.cloudstream3.ui.APIRepository
|
||||||
import com.lagradost.cloudstream3.ui.subtitles.SubtitlesFragment
|
import com.lagradost.cloudstream3.ui.subtitles.SubtitlesFragment
|
||||||
import com.lagradost.cloudstream3.utils.InAppUpdater.Companion.runAutoUpdate
|
import com.lagradost.cloudstream3.utils.InAppUpdater.Companion.runAutoUpdate
|
||||||
|
@ -53,6 +54,7 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
val localePreference = findPreference<Preference>(getString(R.string.locale_key))!!
|
val localePreference = findPreference<Preference>(getString(R.string.locale_key))!!
|
||||||
val benenePreference = findPreference<Preference>(getString(R.string.benene_count))!!
|
val benenePreference = findPreference<Preference>(getString(R.string.benene_count))!!
|
||||||
val watchQualityPreference = findPreference<Preference>(getString(R.string.quality_pref_key))!!
|
val watchQualityPreference = findPreference<Preference>(getString(R.string.quality_pref_key))!!
|
||||||
|
val dnsPreference = findPreference<Preference>(getString(R.string.dns_key))!!
|
||||||
val legalPreference = findPreference<Preference>(getString(R.string.legal_notice_key))!!
|
val legalPreference = findPreference<Preference>(getString(R.string.legal_notice_key))!!
|
||||||
val subdubPreference = findPreference<Preference>(getString(R.string.display_sub_key))!!
|
val subdubPreference = findPreference<Preference>(getString(R.string.display_sub_key))!!
|
||||||
val providerLangPreference = findPreference<Preference>(getString(R.string.provider_lang_key))!!
|
val providerLangPreference = findPreference<Preference>(getString(R.string.provider_lang_key))!!
|
||||||
|
@ -154,6 +156,25 @@ class SettingsFragment : PreferenceFragmentCompat() {
|
||||||
return@setOnPreferenceClickListener true
|
return@setOnPreferenceClickListener true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dnsPreference.setOnPreferenceClickListener {
|
||||||
|
val prefNames = resources.getStringArray(R.array.dns_pref)
|
||||||
|
val prefValues = resources.getIntArray(R.array.dns_pref_values)
|
||||||
|
val settingsManager = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
||||||
|
val currentDns =
|
||||||
|
settingsManager.getInt(getString(R.string.dns_pref), 0)
|
||||||
|
context?.showBottomDialog(
|
||||||
|
prefNames.toList(),
|
||||||
|
prefValues.indexOf(currentDns),
|
||||||
|
getString(R.string.dns_pref),
|
||||||
|
true,
|
||||||
|
{}) {
|
||||||
|
settingsManager.edit().putInt(getString(R.string.dns_pref), prefValues[it]).apply()
|
||||||
|
context?.initRequestClient()
|
||||||
|
}
|
||||||
|
return@setOnPreferenceClickListener true
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(context)
|
val settingsManager = PreferenceManager.getDefaultSharedPreferences(context)
|
||||||
|
|
||||||
|
|
10
app/src/main/res/drawable/ic_baseline_dns_24.xml
Normal file
10
app/src/main/res/drawable/ic_baseline_dns_24.xml
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24"
|
||||||
|
android:tint="@color/white">
|
||||||
|
<path
|
||||||
|
android:fillColor="@android:color/white"
|
||||||
|
android:pathData="M20,13H4c-0.55,0 -1,0.45 -1,1v6c0,0.55 0.45,1 1,1h16c0.55,0 1,-0.45 1,-1v-6c0,-0.55 -0.45,-1 -1,-1zM7,19c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM20,3H4c-0.55,0 -1,0.45 -1,1v6c0,0.55 0.45,1 1,1h16c0.55,0 1,-0.45 1,-1V4c0,-0.55 -0.45,-1 -1,-1zM7,9c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2z"/>
|
||||||
|
</vector>
|
|
@ -31,6 +31,21 @@
|
||||||
<item>-2</item>
|
<item>-2</item>
|
||||||
</array>
|
</array>
|
||||||
|
|
||||||
|
<array name="dns_pref">
|
||||||
|
<item>None</item>
|
||||||
|
<item>Google</item>
|
||||||
|
<item>Cloudflare</item>
|
||||||
|
<!-- <item>OpenDns</item>-->
|
||||||
|
<item>AdGuard</item>
|
||||||
|
</array>
|
||||||
|
<array name="dns_pref_values">
|
||||||
|
<item>0</item>
|
||||||
|
<item>1</item>
|
||||||
|
<item>2</item>
|
||||||
|
<!-- <item>3</item>-->
|
||||||
|
<item>4</item>
|
||||||
|
</array>
|
||||||
|
|
||||||
<array name="episode_long_click_options">
|
<array name="episode_long_click_options">
|
||||||
<item>@string/episode_action_chomecast_episode</item>
|
<item>@string/episode_action_chomecast_episode</item>
|
||||||
<item>@string/episode_action_chomecast_mirror</item>
|
<item>@string/episode_action_chomecast_mirror</item>
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
<string name="display_sub_key" translatable="false">display_sub_key</string>
|
<string name="display_sub_key" translatable="false">display_sub_key</string>
|
||||||
<string name="show_fillers_key" translatable="false">show_fillers_key</string>
|
<string name="show_fillers_key" translatable="false">show_fillers_key</string>
|
||||||
<string name="provider_lang_key" translatable="false">provider_lang_key</string>
|
<string name="provider_lang_key" translatable="false">provider_lang_key</string>
|
||||||
|
<string name="dns_key" translatable="false">dns_key</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- FORMAT MIGHT TRANSLATE, WILL CAUSE CRASH IF APPLIED WRONG -->
|
<!-- FORMAT MIGHT TRANSLATE, WILL CAUSE CRASH IF APPLIED WRONG -->
|
||||||
|
@ -166,7 +167,9 @@
|
||||||
<string name="double_tap_to_seek_settings_des">Tap twice on the right or left side to seek forwards or backwards
|
<string name="double_tap_to_seek_settings_des">Tap twice on the right or left side to seek forwards or backwards
|
||||||
</string>
|
</string>
|
||||||
<string name="use_system_brightness_settings">Use system brightness</string>
|
<string name="use_system_brightness_settings">Use system brightness</string>
|
||||||
<string name="use_system_brightness_settings_des">Use system brightness in the app player instead of an dark overlay</string>
|
<string name="use_system_brightness_settings_des">Use system brightness in the app player instead of an dark
|
||||||
|
overlay
|
||||||
|
</string>
|
||||||
|
|
||||||
<string name="search">Search</string>
|
<string name="search">Search</string>
|
||||||
<string name="settings_info">Info</string>
|
<string name="settings_info">Info</string>
|
||||||
|
@ -261,6 +264,10 @@
|
||||||
<string name="dont_show_again">Don\'t show again</string>
|
<string name="dont_show_again">Don\'t show again</string>
|
||||||
<string name="update">Update</string>
|
<string name="update">Update</string>
|
||||||
<string name="watch_quality_pref">Preferred watch quality</string>
|
<string name="watch_quality_pref">Preferred watch quality</string>
|
||||||
|
<string name="dns_pref">DNS over HTTPS</string>
|
||||||
|
<string name="dns_pref_summary">Useful for bypassing ISP blocks</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="display_subbed_dubbed_settings">Display Dubbed/Subbed Anime</string>
|
<string name="display_subbed_dubbed_settings">Display Dubbed/Subbed Anime</string>
|
||||||
|
|
||||||
<string name="resize_fit">Fit to screen</string>
|
<string name="resize_fit">Fit to screen</string>
|
||||||
|
@ -269,15 +276,21 @@
|
||||||
|
|
||||||
<string name="legal_notice" translatable="false">Disclaimer</string>
|
<string name="legal_notice" translatable="false">Disclaimer</string>
|
||||||
<string name="legal_notice_key" translatable="false">legal_notice_key</string>
|
<string name="legal_notice_key" translatable="false">legal_notice_key</string>
|
||||||
<string name="legal_notice_text" translatable="false">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.
|
<string name="legal_notice_text" translatable="false">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.
|
In case of copyright infringement, please directly contact the responsible parties or the streaming websites.
|
||||||
|
|
||||||
The app is purely for educational and personal use.
|
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.
|
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.
|
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.
|
||||||
</string>
|
</string>
|
||||||
<string name="general">General</string>
|
<string name="general">General</string>
|
||||||
<string name="provider_lang_settings">Provider Languages</string>
|
<string name="provider_lang_settings">Provider Languages</string>
|
||||||
|
|
|
@ -93,6 +93,12 @@
|
||||||
android:icon="@drawable/ic_baseline_skip_next_24"
|
android:icon="@drawable/ic_baseline_skip_next_24"
|
||||||
android:title="@string/show_fillers_settings"
|
android:title="@string/show_fillers_settings"
|
||||||
android:defaultValue="true"/>
|
android:defaultValue="true"/>
|
||||||
|
<Preference
|
||||||
|
android:key="@string/dns_key"
|
||||||
|
android:title="@string/dns_pref"
|
||||||
|
android:summary="@string/dns_pref_summary"
|
||||||
|
android:icon="@drawable/ic_baseline_dns_24">
|
||||||
|
</Preference>
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory
|
<PreferenceCategory
|
||||||
android:key="search"
|
android:key="search"
|
||||||
|
|
Loading…
Reference in a new issue