mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
Merge 2363aadc5a
into 0b4de81811
This commit is contained in:
commit
c810bd2d8e
12 changed files with 370 additions and 69 deletions
|
@ -38,6 +38,7 @@ 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.AcraApplication.Companion.context
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
|
||||
import com.lagradost.cloudstream3.CommonActivity.loadThemes
|
||||
|
@ -58,6 +59,7 @@ import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStri
|
|||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringRepo
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringResumeWatching
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.appStringSearch
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.githubApi
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.inAppAuths
|
||||
import com.lagradost.cloudstream3.ui.APIRepository
|
||||
import com.lagradost.cloudstream3.ui.WatchType
|
||||
|
@ -84,6 +86,8 @@ import com.lagradost.cloudstream3.utils.AppUtils.loadRepository
|
|||
import com.lagradost.cloudstream3.utils.AppUtils.loadResult
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.loadSearchResult
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.setDefaultFocus
|
||||
import com.lagradost.cloudstream3.utils.BackupUtils.backupGithub
|
||||
import com.lagradost.cloudstream3.utils.BackupUtils.restorePromptGithub
|
||||
import com.lagradost.cloudstream3.utils.BackupUtils.setUpBackup
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||
import com.lagradost.cloudstream3.utils.DataStore.getKey
|
||||
|
@ -443,6 +447,7 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
//private var mCastSession: CastSession? = null
|
||||
lateinit var mSessionManager: SessionManager
|
||||
private val mSessionManagerListener: SessionManagerListener<Session> by lazy { SessionManagerListenerImpl() }
|
||||
private val accountsLoginLock = Mutex()
|
||||
|
||||
private inner class SessionManagerListenerImpl : SessionManagerListener<Session> {
|
||||
override fun onSessionStarting(session: Session) {
|
||||
|
@ -503,6 +508,10 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
}
|
||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
if (githubApi.getLatestLoginData() != null && settingsManager.getBoolean(getString(R.string.automatic_cloud_backups), true)) {
|
||||
this@MainActivity.backupGithub()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -640,36 +649,52 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
}
|
||||
}
|
||||
|
||||
lateinit var viewModel: ResultViewModel2
|
||||
lateinit var viewModel: ResultViewModel2
|
||||
|
||||
override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
|
||||
viewModel =
|
||||
ViewModelProvider(this)[ResultViewModel2::class.java]
|
||||
override fun onCreateView(name: String, context: Context, attrs: AttributeSet): View? {
|
||||
viewModel =
|
||||
ViewModelProvider(this)[ResultViewModel2::class.java]
|
||||
|
||||
return super.onCreateView(name, context, attrs)
|
||||
}
|
||||
return super.onCreateView(name, context, attrs)
|
||||
}
|
||||
|
||||
private fun hidePreviewPopupDialog() {
|
||||
viewModel.clear()
|
||||
bottomPreviewPopup.dismissSafe(this)
|
||||
}
|
||||
private fun hidePreviewPopupDialog() {
|
||||
viewModel.clear()
|
||||
bottomPreviewPopup.dismissSafe(this)
|
||||
}
|
||||
|
||||
var bottomPreviewPopup: BottomSheetDialog? = null
|
||||
private fun showPreviewPopupDialog(): BottomSheetDialog {
|
||||
val ret = (bottomPreviewPopup ?: run {
|
||||
val builder =
|
||||
BottomSheetDialog(this)
|
||||
builder.setContentView(R.layout.bottom_resultview_preview)
|
||||
builder.setOnDismissListener {
|
||||
bottomPreviewPopup = null
|
||||
viewModel.clear()
|
||||
var bottomPreviewPopup: BottomSheetDialog? = null
|
||||
private fun showPreviewPopupDialog(): BottomSheetDialog {
|
||||
val ret = (bottomPreviewPopup ?: run {
|
||||
val builder =
|
||||
BottomSheetDialog(this)
|
||||
builder.setContentView(R.layout.bottom_resultview_preview)
|
||||
builder.setOnDismissListener {
|
||||
bottomPreviewPopup = null
|
||||
viewModel.clear()
|
||||
}
|
||||
builder.setCanceledOnTouchOutside(true)
|
||||
builder.show()
|
||||
builder
|
||||
})
|
||||
bottomPreviewPopup = ret
|
||||
return ret
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
val settingsManager = PreferenceManager.getDefaultSharedPreferences(this)
|
||||
super.onStart()
|
||||
ioSafe {
|
||||
accountsLoginLock.withLock {
|
||||
if (githubApi.getLatestLoginData() != null && settingsManager.getBoolean(
|
||||
getString(R.string.automatic_cloud_backups),
|
||||
true
|
||||
)
|
||||
) {
|
||||
context?.restorePromptGithub()
|
||||
}
|
||||
}
|
||||
builder.setCanceledOnTouchOutside(true)
|
||||
builder.show()
|
||||
builder
|
||||
})
|
||||
bottomPreviewPopup = ret
|
||||
return ret
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
|
@ -845,15 +870,17 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
|
||||
// init accounts
|
||||
ioSafe {
|
||||
for (api in accountManagers) {
|
||||
api.init()
|
||||
}
|
||||
accountsLoginLock.withLock{
|
||||
for (api in accountManagers) {
|
||||
api.init()
|
||||
}
|
||||
|
||||
inAppAuths.amap { api ->
|
||||
try {
|
||||
api.initialize()
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
inAppAuths.amap { api ->
|
||||
try {
|
||||
api.initialize()
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1078,4 +1105,4 @@ class MainActivity : AppCompatActivity(), ColorPickerDialogListener {
|
|||
// }
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,6 +11,7 @@ abstract class AccountManager(private val defIndex: Int) : AuthAPI {
|
|||
val malApi = MALApi(0)
|
||||
val aniListApi = AniListApi(0)
|
||||
val openSubtitlesApi = OpenSubtitlesApi(0)
|
||||
val githubApi = GithubApi(0)
|
||||
val indexSubtitlesApi = IndexSubtitleApi()
|
||||
val addic7ed = Addic7ed()
|
||||
|
||||
|
@ -23,7 +24,7 @@ abstract class AccountManager(private val defIndex: Int) : AuthAPI {
|
|||
// this needs init with context and can be accessed in settings
|
||||
val accountManagers
|
||||
get() = listOf(
|
||||
malApi, aniListApi, openSubtitlesApi, //nginxApi
|
||||
malApi, aniListApi, openSubtitlesApi, githubApi //nginxApi
|
||||
)
|
||||
|
||||
// used for active syncing
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
package com.lagradost.cloudstream3.syncproviders.providers
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.context
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.getKey
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.removeKey
|
||||
import com.lagradost.cloudstream3.AcraApplication.Companion.setKey
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.syncproviders.AuthAPI
|
||||
import com.lagradost.cloudstream3.syncproviders.InAppAuthAPI
|
||||
import com.lagradost.cloudstream3.syncproviders.InAppAuthAPIManager
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
||||
import com.lagradost.cloudstream3.utils.BackupUtils.getBackup
|
||||
import com.lagradost.cloudstream3.utils.BackupUtils.restorePromptGithub
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||
import com.lagradost.nicehttp.RequestBodyTypes
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
|
||||
|
||||
class GithubApi(index: Int) : InAppAuthAPIManager(index){
|
||||
override val idPrefix = "Github"
|
||||
override val name = "Github"
|
||||
override val icon = R.drawable.ic_github_logo
|
||||
override val requiresPassword = true
|
||||
override val createAccountUrl = "https://github.com/settings/tokens/new?description=Cloudstream+Backup&scopes=gist"
|
||||
|
||||
data class GithubOAuthEntity(
|
||||
var gistId: String,
|
||||
var token: String,
|
||||
var userName: String,
|
||||
var userAvatar: String,
|
||||
)
|
||||
|
||||
companion object {
|
||||
const val GITHUB_USER_KEY: String = "github_user" // user data like profile
|
||||
var currentSession: GithubOAuthEntity? = null
|
||||
}
|
||||
|
||||
private fun getAuthKey(): GithubOAuthEntity? {
|
||||
return getKey(accountId, GITHUB_USER_KEY)
|
||||
}
|
||||
|
||||
data class GistsElements (
|
||||
@JsonProperty("id") val gistId:String,
|
||||
@JsonProperty("files") val files: Map<String, File>,
|
||||
@JsonProperty("owner") val owner: OwnerData
|
||||
)
|
||||
data class OwnerData(
|
||||
@JsonProperty("login") val userName: String,
|
||||
@JsonProperty("avatar_url") val userAvatar : String
|
||||
)
|
||||
data class File (
|
||||
@JsonProperty("content") val dataRaw: String?
|
||||
)
|
||||
|
||||
data class GistRequestBody(
|
||||
@JsonProperty("description") val description: String,
|
||||
@JsonProperty("public") val public : Boolean,
|
||||
@JsonProperty("files") val files: FilesGist?
|
||||
)
|
||||
data class FilesGist(
|
||||
@JsonProperty("Cloudstream_Backup_data.txt") val description: ContentFilesGist?,
|
||||
)
|
||||
data class ContentFilesGist(
|
||||
@JsonProperty("content") val description: String?,
|
||||
)
|
||||
|
||||
private suspend fun initLogin(githubToken: String): Boolean{
|
||||
val response = app.get("https://api.github.com/gists",
|
||||
headers= mapOf(
|
||||
Pair("Accept" , "application/vnd.github+json"),
|
||||
Pair("Authorization", "token $githubToken"),
|
||||
)
|
||||
)
|
||||
|
||||
if (!response.isSuccessful) { return false }
|
||||
|
||||
val repo = tryParseJson<List<GistsElements>>(response.text)?.filter {
|
||||
it.files.keys.first() == "Cloudstream_Backup_data.txt"
|
||||
}
|
||||
|
||||
if (repo?.isEmpty() == true){
|
||||
val backupData = context?.getBackup()
|
||||
val gitResponse = app.post("https://api.github.com/gists",
|
||||
headers= mapOf(
|
||||
Pair("Accept" , "application/vnd.github+json"),
|
||||
Pair("Authorization", "token $githubToken"),
|
||||
),
|
||||
requestBody = GistRequestBody("Cloudstream private backup gist", false, FilesGist(ContentFilesGist(backupData?.toJson()))).toJson().toRequestBody(
|
||||
RequestBodyTypes.JSON.toMediaTypeOrNull()))
|
||||
|
||||
if (!gitResponse.isSuccessful) {return false}
|
||||
tryParseJson<GistsElements>(gitResponse.text).let {
|
||||
setKey(accountId, GITHUB_USER_KEY, GithubOAuthEntity(
|
||||
token = githubToken,
|
||||
gistId = it?.gistId?: run {
|
||||
return false
|
||||
},
|
||||
userName = it.owner.userName,
|
||||
userAvatar = it.owner.userAvatar
|
||||
))
|
||||
}
|
||||
return true
|
||||
}
|
||||
else{
|
||||
repo?.first().let {
|
||||
setKey(accountId, GITHUB_USER_KEY, GithubOAuthEntity(
|
||||
token = githubToken,
|
||||
gistId = it?.gistId?: run {
|
||||
return false
|
||||
},
|
||||
userName = it.owner.userName,
|
||||
userAvatar = it.owner.userAvatar
|
||||
))
|
||||
ioSafe {
|
||||
context?.restorePromptGithub()
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
override suspend fun login(data: InAppAuthAPI.LoginData): Boolean {
|
||||
switchToNewAccount()
|
||||
val githubToken = data.password ?: throw IllegalArgumentException ("Requires Password")
|
||||
try {
|
||||
if (initLogin(githubToken)) {
|
||||
registerAccount()
|
||||
return true
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logError(e)
|
||||
}
|
||||
switchToOldAccount()
|
||||
return false
|
||||
}
|
||||
|
||||
override fun getLatestLoginData(): InAppAuthAPI.LoginData? {
|
||||
val current = getAuthKey() ?: return null
|
||||
return InAppAuthAPI.LoginData(server = current.gistId, password = current.token, username = current.userName)
|
||||
}
|
||||
override suspend fun initialize() {
|
||||
currentSession = getAuthKey()
|
||||
val gistId = currentSession?.gistId ?: return
|
||||
val token = currentSession?.token ?: return
|
||||
setKey(gistId, token)
|
||||
}
|
||||
override fun logOut() {
|
||||
removeKey(accountId, GITHUB_USER_KEY)
|
||||
removeAccountKeys()
|
||||
currentSession = getAuthKey()
|
||||
}
|
||||
|
||||
override fun loginInfo(): AuthAPI.LoginInfo? {
|
||||
return getAuthKey()?.let { user ->
|
||||
AuthAPI.LoginInfo(
|
||||
profilePicture = user.userAvatar,
|
||||
name = user.userName,
|
||||
accountIndex = accountIndex,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -126,8 +126,8 @@ class OpenSubtitlesApi(index: Int) : InAppAuthAPIManager(index), AbstractSubApi
|
|||
}
|
||||
|
||||
override suspend fun login(data: InAppAuthAPI.LoginData): Boolean {
|
||||
val username = data.username ?: throw ErrorLoadingException("Requires Username")
|
||||
val password = data.password ?: throw ErrorLoadingException("Requires Password")
|
||||
val username = data.username ?: throw IllegalArgumentException ("Requires Username")
|
||||
val password = data.password ?: throw IllegalArgumentException ("Requires Password")
|
||||
switchToNewAccount()
|
||||
try {
|
||||
if (initLogin(username, password)) {
|
||||
|
|
|
@ -93,6 +93,7 @@ class HomeFragment : Fragment() {
|
|||
val configEvent = Event<Int>()
|
||||
var currentSpan = 1
|
||||
val listHomepageItems = mutableListOf<SearchResponse>()
|
||||
val reloadStoredDataEvent = Event<Unit>()
|
||||
|
||||
private val errorProfilePics = listOf(
|
||||
R.drawable.monke_benene,
|
||||
|
@ -477,15 +478,21 @@ class HomeFragment : Fragment() {
|
|||
bookmarksUpdatedEvent += ::bookmarksUpdated
|
||||
afterPluginsLoadedEvent += ::afterPluginsLoaded
|
||||
mainPluginsLoadedEvent += ::afterMainPluginsLoaded
|
||||
reloadStoredDataEvent += ::reloadStoredEvent
|
||||
}
|
||||
|
||||
override fun onStop() {
|
||||
bookmarksUpdatedEvent -= ::bookmarksUpdated
|
||||
afterPluginsLoadedEvent -= ::afterPluginsLoaded
|
||||
mainPluginsLoadedEvent -= ::afterMainPluginsLoaded
|
||||
reloadStoredDataEvent -= ::reloadStoredEvent
|
||||
super.onStop()
|
||||
}
|
||||
|
||||
private fun reloadStoredEvent(input: Unit) {
|
||||
reloadStored()
|
||||
}
|
||||
|
||||
private fun reloadStored() {
|
||||
homeViewModel.loadResumeWatching()
|
||||
val list = EnumSet.noneOf(WatchType::class.java)
|
||||
|
|
|
@ -20,6 +20,7 @@ import com.lagradost.cloudstream3.syncproviders.AccountManager
|
|||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.aniListApi
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.malApi
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.openSubtitlesApi
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.githubApi
|
||||
import com.lagradost.cloudstream3.syncproviders.AuthAPI
|
||||
import com.lagradost.cloudstream3.syncproviders.InAppAuthAPI
|
||||
import com.lagradost.cloudstream3.syncproviders.OAuth2API
|
||||
|
@ -227,6 +228,8 @@ class SettingsAccount : PreferenceFragmentCompat() {
|
|||
R.string.mal_key to malApi,
|
||||
R.string.anilist_key to aniListApi,
|
||||
R.string.opensubtitles_key to openSubtitlesApi,
|
||||
R.string.github_key to githubApi
|
||||
|
||||
)
|
||||
|
||||
for ((key, api) in syncApis) {
|
||||
|
|
|
@ -19,6 +19,7 @@ import com.lagradost.cloudstream3.ui.settings.SettingsFragment.Companion.setPadd
|
|||
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.BackupUtils.restorePromptGithub
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||
import com.lagradost.cloudstream3.utils.InAppUpdater.Companion.runAutoUpdate
|
||||
import com.lagradost.cloudstream3.utils.SingleSelectionHelper.showBottomDialog
|
||||
|
@ -31,6 +32,7 @@ import java.io.BufferedReader
|
|||
import java.io.InputStreamReader
|
||||
import java.io.OutputStream
|
||||
|
||||
|
||||
class SettingsUpdates : PreferenceFragmentCompat() {
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
|
|
@ -14,14 +14,18 @@ import com.fasterxml.jackson.annotation.JsonProperty
|
|||
import com.fasterxml.jackson.module.kotlin.readValue
|
||||
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.plugins.PLUGINS_KEY
|
||||
import com.lagradost.cloudstream3.plugins.PLUGINS_KEY_LOCAL
|
||||
import com.lagradost.cloudstream3.syncproviders.AccountManager.Companion.githubApi
|
||||
import com.lagradost.cloudstream3.syncproviders.providers.AniListApi.Companion.ANILIST_CACHED_LIST
|
||||
import com.lagradost.cloudstream3.syncproviders.providers.AniListApi.Companion.ANILIST_SHOULD_UPDATE_LIST
|
||||
import com.lagradost.cloudstream3.syncproviders.providers.AniListApi.Companion.ANILIST_TOKEN_KEY
|
||||
import com.lagradost.cloudstream3.syncproviders.providers.AniListApi.Companion.ANILIST_UNIXTIME_KEY
|
||||
import com.lagradost.cloudstream3.syncproviders.providers.AniListApi.Companion.ANILIST_USER_KEY
|
||||
import com.lagradost.cloudstream3.syncproviders.providers.GithubApi
|
||||
import com.lagradost.cloudstream3.syncproviders.providers.GithubApi.Companion.GITHUB_USER_KEY
|
||||
import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_CACHED_LIST
|
||||
import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_REFRESH_TOKEN_KEY
|
||||
import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_SHOULD_UPDATE_LIST
|
||||
|
@ -29,6 +33,11 @@ import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_T
|
|||
import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_UNIXTIME_KEY
|
||||
import com.lagradost.cloudstream3.syncproviders.providers.MALApi.Companion.MAL_USER_KEY
|
||||
import com.lagradost.cloudstream3.syncproviders.providers.OpenSubtitlesApi.Companion.OPEN_SUBTITLES_USER_KEY
|
||||
import com.lagradost.cloudstream3.ui.home.HomeFragment
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||
|
||||
import com.lagradost.cloudstream3.utils.Coroutines.ioSafe
|
||||
import com.lagradost.cloudstream3.utils.DataStore.getDefaultSharedPrefs
|
||||
import com.lagradost.cloudstream3.utils.DataStore.getSharedPrefs
|
||||
import com.lagradost.cloudstream3.utils.DataStore.mapper
|
||||
|
@ -37,12 +46,14 @@ import com.lagradost.cloudstream3.utils.UIHelper.checkWrite
|
|||
import com.lagradost.cloudstream3.utils.UIHelper.requestRW
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager.getBasePath
|
||||
import com.lagradost.cloudstream3.utils.VideoDownloadManager.isDownloadDir
|
||||
import com.lagradost.nicehttp.RequestBodyTypes
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import java.io.IOException
|
||||
import java.io.PrintWriter
|
||||
import java.lang.System.currentTimeMillis
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
object BackupUtils {
|
||||
|
||||
/**
|
||||
|
@ -65,14 +76,15 @@ object BackupUtils {
|
|||
// The plugins themselves are not backed up
|
||||
PLUGINS_KEY,
|
||||
PLUGINS_KEY_LOCAL,
|
||||
|
||||
GITHUB_USER_KEY,
|
||||
OPEN_SUBTITLES_USER_KEY,
|
||||
"nginx_user", // Nginx user key
|
||||
|
||||
)
|
||||
|
||||
/** false if blacklisted key */
|
||||
private fun String.isTransferable(): Boolean {
|
||||
return !nonTransferableKeys.contains(this)
|
||||
return !nonTransferableKeys.contains(this) and !nonTransferableKeys.any { this.endsWith(it) }
|
||||
}
|
||||
|
||||
private var restoreFileSelector: ActivityResultLauncher<Array<String>>? = null
|
||||
|
@ -286,4 +298,46 @@ object BackupUtils {
|
|||
setKeyRaw(it.key, it.value, isEditingAppSettings)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun FragmentActivity.backupGithub(){
|
||||
val backup = this.getBackup().toJson()
|
||||
|
||||
val gistId = githubApi.getLatestLoginData()?.server ?: throw IllegalArgumentException ("Requires Username")
|
||||
val token = githubApi.getLatestLoginData()?.password ?: throw IllegalArgumentException ("Requires Username")
|
||||
|
||||
ioSafe {
|
||||
app.patch("https://api.github.com/gists/$gistId",
|
||||
headers= mapOf(
|
||||
Pair("Accept" , "application/vnd.github+json"),
|
||||
Pair("Authorization", "token $token"),
|
||||
),
|
||||
requestBody = GithubApi.GistRequestBody(
|
||||
"Cloudstream private backup gist",
|
||||
false,
|
||||
GithubApi.FilesGist(GithubApi.ContentFilesGist(backup)))
|
||||
.toJson()
|
||||
.toRequestBody(RequestBodyTypes.JSON.toMediaTypeOrNull())
|
||||
)
|
||||
}
|
||||
showToast(
|
||||
this,
|
||||
R.string.backup_success,
|
||||
Toast.LENGTH_LONG
|
||||
)
|
||||
}
|
||||
suspend fun Context.restorePromptGithub() {
|
||||
val gistId = githubApi.getLatestLoginData()?.server ?: throw IllegalAccessException()
|
||||
val jsonData = app.get("https://api.github.com/gists/$gistId").text
|
||||
val dataRaw =
|
||||
parseJson<GithubApi.GistsElements>(jsonData ?: "").files.values.first().dataRaw
|
||||
?: throw IllegalAccessException()
|
||||
val data = parseJson<BackupFile>(dataRaw)
|
||||
restore(
|
||||
data,
|
||||
restoreSettings = true,
|
||||
restoreDataStore = true
|
||||
)
|
||||
HomeFragment.reloadStoredDataEvent.invoke(Unit)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -141,6 +141,8 @@
|
|||
<!--<string name="episode_sync_settings">Update watch progress</string>-->
|
||||
<string name="episode_sync_settings_des">Sincronizza automaticamente gli episodi guardati</string>
|
||||
<string name="restore_settings">Ripristinare i dati da backup</string>
|
||||
<string name="automatic_restore_settings">Backup automatico su Github</string>
|
||||
|
||||
<string name="backup_settings">Backup data</string>
|
||||
<string name="restore_success">File di backup caricato</string>
|
||||
<string name="restore_failed_format" formatted="true">Impossibile ripristinare i dati dal file %s</string>
|
||||
|
@ -343,7 +345,7 @@
|
|||
<string name="subtitle_offset_extra_hint_none_format">Nessun ritardo dei sottotitoli</string>
|
||||
<!--
|
||||
Example text (pangram) can optionally be translated; if you do, include all the letters in the alphabet,
|
||||
see:
|
||||
see:
|
||||
https://en.wikipedia.org/w/index.php?title=Pangram&oldid=225849300
|
||||
https://en.wikipedia.org/wiki/The_quick_brown_fox_jumps_over_the_lazy_dog
|
||||
-->
|
||||
|
@ -507,4 +509,4 @@
|
|||
<string name="delayed_update_notice">L\'app verrà aggiornata all\'uscita</string>
|
||||
<string name="update_started">Aggiornamento avviato</string>
|
||||
<string name="plugin_downloaded">Plugin scaricato</string>
|
||||
</resources>
|
||||
</resources>
|
||||
|
|
|
@ -61,6 +61,8 @@
|
|||
<string name="pref_filter_search_quality_key" translatable="false">pref_filter_search_quality_key</string>
|
||||
<string name="enable_nsfw_on_providers_key" translatable="false">enable_nsfw_on_providers_key</string>
|
||||
<string name="enable_skip_op_from_database" translatable="false">enable_skip_op_from_database</string>
|
||||
<string name="automatic_cloud_backups" translatable="false">automatic_cloud_backups</string>
|
||||
|
||||
<!-- FORMAT MIGHT TRANSLATE, WILL CAUSE CRASH IF APPLIED WRONG -->
|
||||
<string name="extra_info_format" formatted="true" translatable="false">%d %s | %s</string>
|
||||
<string name="storage_size_format" formatted="true" translatable="false">%s • %s</string>
|
||||
|
@ -222,7 +224,12 @@
|
|||
<string name="episode_sync_settings">Update watch progress</string>
|
||||
<string name="episode_sync_settings_des">Automatically sync your current episode progress</string>
|
||||
<string name="restore_settings">Restore data from backup</string>
|
||||
<string name="backup_settings">Back up data</string>
|
||||
<string name="automatic_restore_settings">Automatic backup from Github</string>
|
||||
|
||||
<string name="cloud_backups_off">Cloud Backup deactivated</string>
|
||||
<string name="cloud_backups_on">Cloud Backup enabled</string>
|
||||
|
||||
<string name="backup_settings">Backup data</string>
|
||||
<string name="restore_success">Loaded backup file</string>
|
||||
<string name="restore_failed_format" formatted="true">Failed to restore data from file %s</string>
|
||||
<string name="backup_success">Data stored</string>
|
||||
|
@ -428,6 +435,7 @@
|
|||
<string name="anilist_key" translatable="false">anilist_key</string>
|
||||
<string name="mal_key" translatable="false">mal_key</string>
|
||||
<string name="opensubtitles_key" translatable="false">opensubtitles_key</string>
|
||||
<string name="github_key" translatable="false">github_key</string>
|
||||
<string name="nginx_key" translatable="false">nginx_key</string>
|
||||
<string name="example_password">password123</string>
|
||||
<string name="example_username">MyCoolUsername</string>
|
||||
|
@ -479,7 +487,7 @@
|
|||
<string name="subtitle_offset_extra_hint_none_format">No subtitle delay</string>
|
||||
<!--
|
||||
Example text (pangram) can optionally be translated; if you do, include all the letters in the alphabet,
|
||||
see:
|
||||
see:
|
||||
https://en.wikipedia.org/w/index.php?title=Pangram&oldid=225849300
|
||||
https://en.wikipedia.org/wiki/The_quick_brown_fox_jumps_over_the_lazy_dog
|
||||
-->
|
||||
|
|
|
@ -1,27 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<Preference
|
||||
android:key="@string/mal_key"
|
||||
android:icon="@drawable/mal_logo" />
|
||||
android:key="@string/mal_key"
|
||||
android:icon="@drawable/mal_logo" />
|
||||
|
||||
<Preference
|
||||
android:key="@string/anilist_key"
|
||||
android:icon="@drawable/ic_anilist_icon" />
|
||||
android:key="@string/anilist_key"
|
||||
android:icon="@drawable/ic_anilist_icon" />
|
||||
<Preference
|
||||
android:key="@string/opensubtitles_key"
|
||||
android:icon="@drawable/open_subtitles_icon" />
|
||||
<!-- <Preference-->
|
||||
<!-- android:key="@string/nginx_key"-->
|
||||
<!-- android:icon="@drawable/nginx" />-->
|
||||
android:key="@string/opensubtitles_key"
|
||||
android:icon="@drawable/open_subtitles_icon" />
|
||||
<Preference
|
||||
android:key="@string/github_key"
|
||||
android:icon="@drawable/ic_github_logo" />
|
||||
<!-- <Preference-->
|
||||
<!-- android:key="@string/nginx_key"-->
|
||||
<!-- android:icon="@drawable/nginx" />-->
|
||||
|
||||
<!-- <Preference-->
|
||||
<!-- android:title="@string/nginx_info_title"-->
|
||||
<!-- android:icon="@drawable/nginx_question"-->
|
||||
<!-- android:summary="@string/nginx_info_summary">-->
|
||||
<!-- <intent-->
|
||||
<!-- android:action="android.intent.action.VIEW"-->
|
||||
<!-- android:data="https://www.sarlays.com/use-nginx-with-cloudstream/" />-->
|
||||
<!-- </Preference>-->
|
||||
<!-- <Preference-->
|
||||
<!-- android:title="@string/nginx_info_title"-->
|
||||
<!-- android:icon="@drawable/nginx_question"-->
|
||||
<!-- android:summary="@string/nginx_info_summary">-->
|
||||
<!-- <intent-->
|
||||
<!-- android:action="android.intent.action.VIEW"-->
|
||||
<!-- android:data="https://www.sarlays.com/use-nginx-with-cloudstream/" />-->
|
||||
<!-- </Preference>-->
|
||||
|
||||
</PreferenceScreen>
|
|
@ -1,6 +1,34 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<Preference
|
||||
android:title="@string/check_for_update"
|
||||
app:icon="@drawable/ic_baseline_system_update_24"
|
||||
app:key="@string/manual_check_update_key"
|
||||
app:summary="@string/app_version" />
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/baseline_save_as_24"
|
||||
android:key="@string/backup_key"
|
||||
android:title="@string/backup_settings" />
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/baseline_restore_page_24"
|
||||
android:key="@string/restore_key"
|
||||
android:title="@string/restore_settings" />
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:icon="@drawable/baseline_restore_page_24"
|
||||
android:key="@string/automatic_cloud_backups"
|
||||
android:summaryOff="@string/cloud_backups_off"
|
||||
android:summaryOn="@string/cloud_backups_on"
|
||||
android:title="@string/automatic_restore_settings" />
|
||||
|
||||
<Preference
|
||||
android:icon="@drawable/baseline_description_24"
|
||||
android:key="@string/show_logcat_key"
|
||||
android:title="@string/show_log_cat" />
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_baseline_bug_report_24"
|
||||
|
@ -9,7 +37,7 @@
|
|||
android:summaryOn="@string/bug_report_settings_on"
|
||||
android:title="@string/pref_disable_acra" />
|
||||
|
||||
<PreferenceCategory
|
||||
<PreferenceCategory
|
||||
android:title="@string/pref_category_app_updates">
|
||||
<Preference
|
||||
android:title="@string/check_for_update"
|
||||
|
@ -37,7 +65,7 @@
|
|||
app:key="@string/auto_update_key" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
<PreferenceCategory
|
||||
android:title="@string/pref_category_backup">
|
||||
<Preference
|
||||
android:icon="@drawable/baseline_save_as_24"
|
||||
|
@ -50,14 +78,14 @@
|
|||
android:title="@string/restore_settings" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
<PreferenceCategory
|
||||
android:title="@string/pref_category_extensions">
|
||||
<SwitchPreference
|
||||
android:defaultValue="true"
|
||||
android:icon="@drawable/ic_baseline_extension_24"
|
||||
android:key="@string/auto_update_plugins_key"
|
||||
android:title="@string/automatic_plugin_updates" />
|
||||
|
||||
|
||||
<SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:icon="@drawable/ic_baseline_extension_24"
|
||||
|
@ -66,7 +94,7 @@
|
|||
android:summary="@string/automatic_plugin_download_summary" />
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
<PreferenceCategory
|
||||
android:title="@string/pref_category_actions">
|
||||
<Preference
|
||||
android:icon="@drawable/baseline_description_24"
|
||||
|
@ -77,4 +105,4 @@
|
|||
android:title="@string/redo_setup_process"
|
||||
app:key="@string/redo_setup_key" />
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
</PreferenceScreen>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue