forked from recloudstream/cloudstream
minor crash fixes + suspended stuff
This commit is contained in:
parent
cb11cd13e6
commit
051ca7a68d
8 changed files with 99 additions and 111 deletions
|
@ -40,10 +40,7 @@ class DownloaderTestImpl private constructor(builder: OkHttpClient.Builder) : Do
|
|||
throw ReCaptchaException("reCaptcha Challenge requested", url)
|
||||
}
|
||||
val body = response.body
|
||||
var responseBodyToReturn: String? = null
|
||||
if (body != null) {
|
||||
responseBodyToReturn = body.string()
|
||||
}
|
||||
val responseBodyToReturn: String = body.string()
|
||||
val latestUrl = response.request.url.toString()
|
||||
return Response(
|
||||
response.code, response.message, response.headers.toMultimap(),
|
||||
|
|
|
@ -88,7 +88,8 @@ object APIHolder {
|
|||
}
|
||||
|
||||
private fun getLoadResponseIdFromUrl(url: String, apiName: String): Int {
|
||||
return url.replace(getApiFromNameNull(apiName)?.mainUrl ?: "", "").replace("/", "").hashCode()
|
||||
return url.replace(getApiFromNameNull(apiName)?.mainUrl ?: "", "").replace("/", "")
|
||||
.hashCode()
|
||||
}
|
||||
|
||||
fun LoadResponse.getId(): Int {
|
||||
|
@ -109,39 +110,43 @@ object APIHolder {
|
|||
// Try document.select("script[src*=https://www.google.com/recaptcha/api.js?render=]").attr("src").substringAfter("render=")
|
||||
// To get the key
|
||||
suspend fun getCaptchaToken(url: String, key: String, referer: String? = null): String? {
|
||||
val uri = Uri.parse(url)
|
||||
val domain = encodeToString(
|
||||
(uri.scheme + "://" + uri.host + ":443").encodeToByteArray(),
|
||||
0
|
||||
).replace("\n", "").replace("=", ".")
|
||||
try {
|
||||
val uri = Uri.parse(url)
|
||||
val domain = encodeToString(
|
||||
(uri.scheme + "://" + uri.host + ":443").encodeToByteArray(),
|
||||
0
|
||||
).replace("\n", "").replace("=", ".")
|
||||
|
||||
val vToken =
|
||||
app.get(
|
||||
"https://www.google.com/recaptcha/api.js?render=$key",
|
||||
referer = referer,
|
||||
cacheTime = 0
|
||||
)
|
||||
.text
|
||||
.substringAfter("releases/")
|
||||
.substringBefore("/")
|
||||
val recapToken =
|
||||
app.get("https://www.google.com/recaptcha/api2/anchor?ar=1&hl=en&size=invisible&cb=cs3&k=$key&co=$domain&v=$vToken")
|
||||
.document
|
||||
.selectFirst("#recaptcha-token")?.attr("value")
|
||||
if (recapToken != null) {
|
||||
return app.post(
|
||||
"https://www.google.com/recaptcha/api2/reload?k=$key",
|
||||
data = mapOf(
|
||||
"v" to vToken,
|
||||
"k" to key,
|
||||
"c" to recapToken,
|
||||
"co" to domain,
|
||||
"sa" to "",
|
||||
"reason" to "q"
|
||||
), cacheTime = 0
|
||||
).text
|
||||
.substringAfter("rresp\",\"")
|
||||
.substringBefore("\"")
|
||||
val vToken =
|
||||
app.get(
|
||||
"https://www.google.com/recaptcha/api.js?render=$key",
|
||||
referer = referer,
|
||||
cacheTime = 0
|
||||
)
|
||||
.text
|
||||
.substringAfter("releases/")
|
||||
.substringBefore("/")
|
||||
val recapToken =
|
||||
app.get("https://www.google.com/recaptcha/api2/anchor?ar=1&hl=en&size=invisible&cb=cs3&k=$key&co=$domain&v=$vToken")
|
||||
.document
|
||||
.selectFirst("#recaptcha-token")?.attr("value")
|
||||
if (recapToken != null) {
|
||||
return app.post(
|
||||
"https://www.google.com/recaptcha/api2/reload?k=$key",
|
||||
data = mapOf(
|
||||
"v" to vToken,
|
||||
"k" to key,
|
||||
"c" to recapToken,
|
||||
"co" to domain,
|
||||
"sa" to "",
|
||||
"reason" to "q"
|
||||
), cacheTime = 0
|
||||
).text
|
||||
.substringAfter("rresp\",\"")
|
||||
.substringBefore("\"")
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
|
|
@ -10,10 +10,6 @@ import android.view.KeyEvent
|
|||
import android.view.Menu
|
||||
import android.view.MenuItem
|
||||
import android.view.WindowManager
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.ActivityResult
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.annotation.IdRes
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.view.isVisible
|
||||
|
@ -36,7 +32,6 @@ import com.lagradost.cloudstream3.APIHolder.apis
|
|||
import com.lagradost.cloudstream3.APIHolder.getApiDubstatusSettings
|
||||
import com.lagradost.cloudstream3.APIHolder.initAll
|
||||
import com.lagradost.cloudstream3.APIHolder.updateHasTrailers
|
||||
import com.lagradost.cloudstream3.CommonActivity.currentToast
|
||||
import com.lagradost.cloudstream3.CommonActivity.loadThemes
|
||||
import com.lagradost.cloudstream3.CommonActivity.onColorSelectedEvent
|
||||
import com.lagradost.cloudstream3.CommonActivity.onDialogDismissedEvent
|
||||
|
@ -45,10 +40,12 @@ import com.lagradost.cloudstream3.CommonActivity.showToast
|
|||
import com.lagradost.cloudstream3.CommonActivity.updateLocale
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.network.initClient
|
||||
import com.lagradost.cloudstream3.plugins.PluginManager
|
||||
import com.lagradost.cloudstream3.receivers.VideoDownloadRestartReceiver
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.OAuth2Apis
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.accountManagers
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appString
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringRepo
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.inAppAuths
|
||||
import com.lagradost.cloudstream3.ui.APIRepository
|
||||
import com.lagradost.cloudstream3.ui.download.DOWNLOAD_NAVIGATE_TO
|
||||
|
@ -58,8 +55,10 @@ import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isEmula
|
|||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTvSettings
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsGeneral
|
||||
import com.lagradost.cloudstream3.ui.setup.HAS_DONE_SETUP_KEY
|
||||
import com.lagradost.cloudstream3.ui.setup.SetupFragmentExtensions
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.isCastApiAvailable
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.loadCache
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.loadRepository
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.loadResult
|
||||
import com.lagradost.cloudstream3.utils.BackupUtils.setUpBackup
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||
|
@ -68,6 +67,7 @@ import com.lagradost.cloudstream3.utils.DataStore.removeKey
|
|||
import com.lagradost.cloudstream3.utils.DataStore.setKey
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.migrateResumeWatching
|
||||
import com.lagradost.cloudstream3.utils.DataStoreHelper.setViewPos
|
||||
import com.lagradost.cloudstream3.utils.Event
|
||||
import com.lagradost.cloudstream3.utils.IOnBackPressed
|
||||
import com.lagradost.cloudstream3.utils.InAppUpdater.Companion.runAutoUpdate
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.changeStatusBarState
|
||||
|
@ -83,17 +83,8 @@ import com.lagradost.nicehttp.ResponseParser
|
|||
import kotlinx.android.synthetic.main.activity_main.*
|
||||
import kotlinx.android.synthetic.main.fragment_result_swipe.*
|
||||
import java.io.File
|
||||
import kotlin.concurrent.thread
|
||||
import kotlin.reflect.KClass
|
||||
import com.lagradost.cloudstream3.plugins.PluginManager
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringRepo
|
||||
import com.lagradost.cloudstream3.ui.setup.SetupFragmentExtensions
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.loadRepository
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.main
|
||||
import com.lagradost.cloudstream3.utils.Event
|
||||
import kotlinx.coroutines.delay
|
||||
import java.lang.ref.WeakReference
|
||||
import java.net.URI
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
|
||||
const val VLC_PACKAGE = "org.videolan.vlc"
|
||||
|
@ -659,7 +650,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
|
||||
handleAppIntent(intent)
|
||||
|
||||
thread {
|
||||
ioSafe {
|
||||
runAutoUpdate()
|
||||
}
|
||||
|
||||
|
|
|
@ -5,11 +5,10 @@ import com.fasterxml.jackson.annotation.JsonProperty
|
|||
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
|
||||
import com.lagradost.cloudstream3.apmap
|
||||
import com.lagradost.cloudstream3.apmapIndexed
|
||||
import com.lagradost.cloudstream3.app
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.mvvm.suspendSafeApiCall
|
||||
import com.lagradost.cloudstream3.plugins.PluginManager.getPluginSanitizedFileName
|
||||
import com.lagradost.cloudstream3.plugins.PluginManager.getPluginsLocal
|
||||
import com.lagradost.cloudstream3.ui.settings.extensions.REPOSITORIES_KEY
|
||||
import com.lagradost.cloudstream3.ui.settings.extensions.RepositoryData
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
||||
|
@ -80,10 +79,15 @@ object RepositoryManager {
|
|||
|
||||
private suspend fun parsePlugins(pluginUrls: String): List<SitePlugin> {
|
||||
// Take manifestVersion and such into account later
|
||||
val response = app.get(pluginUrls)
|
||||
// Normal parsed function not working?
|
||||
// return response.parsedSafe()
|
||||
return tryParseJson<Array<SitePlugin>>(response.text)?.toList() ?: emptyList()
|
||||
return try {
|
||||
val response = app.get(pluginUrls)
|
||||
// Normal parsed function not working?
|
||||
// return response.parsedSafe()
|
||||
tryParseJson<Array<SitePlugin>>(response.text)?.toList() ?: emptyList()
|
||||
} catch (e : Exception) {
|
||||
logError(e)
|
||||
emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,22 +3,11 @@ package com.lagradost.cloudstream3.ui.result
|
|||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.ImageView
|
||||
import android.widget.TextView
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.DiffUtil
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.lagradost.cloudstream3.ActorData
|
||||
import com.lagradost.cloudstream3.ActorRole
|
||||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.ui.download.DownloadButtonViewHolder
|
||||
import com.lagradost.cloudstream3.ui.home.ParentItemAdapter
|
||||
import com.lagradost.cloudstream3.ui.settings.AccountAdapter
|
||||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.isTrueTvSettings
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.setImage
|
||||
import kotlinx.android.synthetic.main.cast_item.view.*
|
||||
import org.schabi.newpipe.extractor.timeago.patterns.it
|
||||
|
||||
typealias SelectData = Pair<UiText?, Any>
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.getPref
|
|||
import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setUpToolbar
|
||||
import com.lagradost.cloudstream3.utils.BackupUtils.backup
|
||||
import com.lagradost.cloudstream3.utils.BackupUtils.restorePrompt
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||
import com.lagradost.cloudstream3.utils.InAppUpdater.Companion.runAutoUpdate
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.dismissSafe
|
||||
import com.lagradost.cloudstream3.utils.UIHelper.hideKeyboard
|
||||
|
@ -25,7 +26,6 @@ import okhttp3.internal.closeQuietly
|
|||
import java.io.BufferedReader
|
||||
import java.io.InputStreamReader
|
||||
import java.io.OutputStream
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
class SettingsUpdates : PreferenceFragmentCompat() {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
|
@ -116,8 +116,8 @@ class SettingsUpdates : PreferenceFragmentCompat() {
|
|||
}
|
||||
|
||||
getPref(R.string.manual_check_update_key)?.setOnPreferenceClickListener {
|
||||
thread {
|
||||
if (!requireActivity().runAutoUpdate(false)) {
|
||||
ioSafe {
|
||||
if (activity?.runAutoUpdate(false) == false) {
|
||||
activity?.runOnUiThread {
|
||||
CommonActivity.showToast(
|
||||
activity,
|
||||
|
|
|
@ -41,7 +41,7 @@ class SetupFragmentProviderLanguage : Fragment() {
|
|||
val langs = APIHolder.apis.map { it.lang }.toSet()
|
||||
.sortedBy { SubtitleHelper.fromTwoLettersToLanguage(it) }
|
||||
|
||||
val currentList = current.map { langs.indexOf(it) }
|
||||
val currentList = current.map { langs.indexOf(it) }.filter { it != -1 } // TODO LOOK INTO
|
||||
val languageNames = langs.map {
|
||||
val emoji = SubtitleHelper.getFlagFromIso(it)
|
||||
val name = SubtitleHelper.fromTwoLettersToLanguage(it)
|
||||
|
|
|
@ -15,15 +15,14 @@ import com.lagradost.cloudstream3.CommonActivity.showToast
|
|||
import com.lagradost.cloudstream3.R
|
||||
import com.lagradost.cloudstream3.app
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import okio.*
|
||||
import okio.BufferedSink
|
||||
import okio.buffer
|
||||
import okio.sink
|
||||
import java.io.File
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
|
||||
class InAppUpdater {
|
||||
|
@ -68,10 +67,14 @@ class InAppUpdater {
|
|||
@JsonProperty("updateNodeId") val updateNodeId: String?
|
||||
)
|
||||
|
||||
private fun Activity.getAppUpdate(): Update {
|
||||
private suspend fun Activity.getAppUpdate(): Update {
|
||||
return try {
|
||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
if (settingsManager.getBoolean(getString(R.string.prerelease_update_key), resources.getBoolean(R.bool.is_prerelease))) {
|
||||
if (settingsManager.getBoolean(
|
||||
getString(R.string.prerelease_update_key),
|
||||
resources.getBoolean(R.bool.is_prerelease)
|
||||
)
|
||||
) {
|
||||
getPreReleaseUpdate()
|
||||
} else {
|
||||
getReleaseUpdate()
|
||||
|
@ -82,16 +85,16 @@ class InAppUpdater {
|
|||
}
|
||||
}
|
||||
|
||||
private fun Activity.getReleaseUpdate(): Update {
|
||||
private suspend fun Activity.getReleaseUpdate(): Update {
|
||||
val url = "https://api.github.com/repos/$GITHUB_USER_NAME/$GITHUB_REPO/releases"
|
||||
val headers = mapOf("Accept" to "application/vnd.github.v3+json")
|
||||
val response =
|
||||
parseJson<List<GithubRelease>>(runBlocking {
|
||||
parseJson<List<GithubRelease>>(
|
||||
app.get(
|
||||
url,
|
||||
headers = headers
|
||||
).text
|
||||
})
|
||||
)
|
||||
|
||||
val versionRegex = Regex("""(.*?((\d+)\.(\d+)\.(\d+))\.apk)""")
|
||||
val versionRegexLocal = Regex("""(.*?((\d+)\.(\d+)\.(\d+)).*)""")
|
||||
|
@ -148,7 +151,7 @@ class InAppUpdater {
|
|||
return Update(false, null, null, null, null)
|
||||
}
|
||||
|
||||
private fun Activity.getPreReleaseUpdate(): Update = runBlocking {
|
||||
private suspend fun Activity.getPreReleaseUpdate(): Update {
|
||||
val tagUrl =
|
||||
"https://api.github.com/repos/$GITHUB_USER_NAME/$GITHUB_REPO/git/ref/tags/pre-release"
|
||||
val releaseUrl = "https://api.github.com/repos/$GITHUB_USER_NAME/$GITHUB_REPO/releases"
|
||||
|
@ -171,14 +174,14 @@ class InAppUpdater {
|
|||
|
||||
val shouldUpdate =
|
||||
(getString(R.string.commit_hash)
|
||||
.trim {c->c.isWhitespace()}
|
||||
.trim { c -> c.isWhitespace() }
|
||||
.take(7)
|
||||
!=
|
||||
tagResponse.github_object.sha
|
||||
.trim {c->c.isWhitespace()}
|
||||
.take(7))
|
||||
!=
|
||||
tagResponse.github_object.sha
|
||||
.trim { c -> c.isWhitespace() }
|
||||
.take(7))
|
||||
|
||||
return@runBlocking if (foundAsset != null) {
|
||||
return if (foundAsset != null) {
|
||||
Update(
|
||||
shouldUpdate,
|
||||
foundAsset.browser_download_url,
|
||||
|
@ -194,25 +197,24 @@ class InAppUpdater {
|
|||
|
||||
private val updateLock = Mutex()
|
||||
|
||||
private fun Activity.downloadUpdate(url: String): Boolean {
|
||||
private suspend fun Activity.downloadUpdate(url: String): Boolean {
|
||||
try {
|
||||
Log.d(LOG_TAG, "Downloading update: $url")
|
||||
|
||||
Log.d(LOG_TAG, "Downloading update: $url")
|
||||
val localContext = this
|
||||
|
||||
val localContext = this
|
||||
val downloadedFile = File.createTempFile("CloudStream", ".apk")
|
||||
val sink: BufferedSink = downloadedFile.sink().buffer()
|
||||
|
||||
val downloadedFile = File.createTempFile("CloudStream",".apk")
|
||||
val sink: BufferedSink = downloadedFile.sink().buffer()
|
||||
|
||||
|
||||
ioSafe {
|
||||
updateLock.withLock {
|
||||
sink.writeAll(app.get(url).body.source() )
|
||||
sink.writeAll(app.get(url).body.source())
|
||||
sink.close()
|
||||
openApk(localContext, Uri.fromFile(downloadedFile))
|
||||
}
|
||||
return true
|
||||
} catch (e: Exception) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private fun openApk(context: Context, uri: Uri) {
|
||||
|
@ -236,7 +238,7 @@ class InAppUpdater {
|
|||
}
|
||||
}
|
||||
|
||||
fun Activity.runAutoUpdate(checkAutoUpdate: Boolean = true): Boolean {
|
||||
suspend fun Activity.runAutoUpdate(checkAutoUpdate: Boolean = true): Boolean {
|
||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
|
||||
if (!checkAutoUpdate || settingsManager.getBoolean(
|
||||
|
@ -247,7 +249,8 @@ class InAppUpdater {
|
|||
val update = getAppUpdate()
|
||||
if (update.shouldUpdate && update.updateURL != null) {
|
||||
//Check if update should be skipped
|
||||
val updateNodeId = settingsManager.getString(getString(R.string.skip_update_key), "")
|
||||
val updateNodeId =
|
||||
settingsManager.getString(getString(R.string.skip_update_key), "")
|
||||
if (update.updateNodeId.equals(updateNodeId)) {
|
||||
return false
|
||||
}
|
||||
|
@ -273,11 +276,8 @@ class InAppUpdater {
|
|||
builder.apply {
|
||||
setPositiveButton(R.string.update) { _, _ ->
|
||||
showToast(context, R.string.download_started, Toast.LENGTH_LONG)
|
||||
thread {
|
||||
val downloadStatus =
|
||||
normalSafeApiCall { context.downloadUpdate(update.updateURL) }
|
||||
?: false
|
||||
if (!downloadStatus) {
|
||||
ioSafe {
|
||||
if (!downloadUpdate(update.updateURL))
|
||||
runOnUiThread {
|
||||
showToast(
|
||||
context,
|
||||
|
@ -285,7 +285,6 @@ class InAppUpdater {
|
|||
Toast.LENGTH_LONG
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -293,7 +292,10 @@ class InAppUpdater {
|
|||
|
||||
if (checkAutoUpdate) {
|
||||
setNeutralButton(R.string.skip_update) { _, _ ->
|
||||
settingsManager.edit().putString(getString(R.string.skip_update_key), update.updateNodeId ?: "")
|
||||
settingsManager.edit().putString(
|
||||
getString(R.string.skip_update_key),
|
||||
update.updateNodeId ?: ""
|
||||
)
|
||||
.apply()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue