added DOH and Cache + fixed trailers for series

This commit is contained in:
Blatzar 2021-10-18 16:02:05 +02:00
parent f9ef71a389
commit b8195f2ec6
10 changed files with 184 additions and 12 deletions

View file

@ -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"
} }

View file

@ -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,

View file

@ -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") ?: ""

View file

@ -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",
)
))

View file

@ -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)

View file

@ -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)

View 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>

View file

@ -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>

View file

@ -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>

View file

@ -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"