Skip to content

Commit

Permalink
Add Backup and Restore of Extension Repos (mihonapp/mihon#1057)
Browse files Browse the repository at this point in the history
* Backup/Restore Extension Repos

* Refactor

* Moving to Under App Settings

* Sort by URL, Check existing by SHA and Error Logging

Untested. Currently in a lecture and can't test if the changes really work.

* Changes to logic

* Don't ask me what's happening here

* Renaming Variables

* Fixing restoreAmount & changes to logic

Co-Authored-By: AntsyLich <59261191+AntsyLich@users.noreply.github.com>

---------

Co-authored-by: AntsyLich <59261191+AntsyLich@users.noreply.github.com>
(cherry picked from commit 3126308)
  • Loading branch information
Animeboynz authored and cuong-tran committed Aug 8, 2024
1 parent 9658c25 commit 652126c
Show file tree
Hide file tree
Showing 10 changed files with 157 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ import com.hippo.unifile.UniFile
import eu.kanade.tachiyomi.BuildConfig
import eu.kanade.tachiyomi.data.backup.BackupFileValidator
import eu.kanade.tachiyomi.data.backup.create.creators.CategoriesBackupCreator
import eu.kanade.tachiyomi.data.backup.create.creators.ExtensionRepoBackupCreator
import eu.kanade.tachiyomi.data.backup.create.creators.FeedBackupCreator
import eu.kanade.tachiyomi.data.backup.create.creators.MangaBackupCreator
import eu.kanade.tachiyomi.data.backup.create.creators.PreferenceBackupCreator
import eu.kanade.tachiyomi.data.backup.create.creators.SavedSearchBackupCreator
import eu.kanade.tachiyomi.data.backup.create.creators.SourcesBackupCreator
import eu.kanade.tachiyomi.data.backup.models.Backup
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
import eu.kanade.tachiyomi.data.backup.models.BackupExtensionRepos
import eu.kanade.tachiyomi.data.backup.models.BackupFeed
import eu.kanade.tachiyomi.data.backup.models.BackupManga
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
Expand Down Expand Up @@ -52,6 +54,7 @@ class BackupCreator(
private val categoriesBackupCreator: CategoriesBackupCreator = CategoriesBackupCreator(),
private val mangaBackupCreator: MangaBackupCreator = MangaBackupCreator(),
private val preferenceBackupCreator: PreferenceBackupCreator = PreferenceBackupCreator(),
private val extensionRepoBackupCreator: ExtensionRepoBackupCreator = ExtensionRepoBackupCreator(),
private val sourcesBackupCreator: SourcesBackupCreator = SourcesBackupCreator(),
// KMK -->
private val feedBackupCreator: FeedBackupCreator = FeedBackupCreator(),
Expand Down Expand Up @@ -99,10 +102,13 @@ class BackupCreator(
backupCategories = backupCategories(options),
backupSources = backupSources(backupManga),
backupPreferences = backupAppPreferences(options),
backupExtensionRepo = backupExtensionRepos(options),
backupSourcePreferences = backupSourcePreferences(options),

// SY -->
backupSavedSearches = backupSavedSearches(),
// SY <--

// KMK -->
backupFeeds = backupFeeds(),
// KMK <--
Expand Down Expand Up @@ -160,6 +166,12 @@ class BackupCreator(
return preferenceBackupCreator.createApp(includePrivatePreferences = options.privateSettings)
}

suspend fun backupExtensionRepos(options: BackupOptions): List<BackupExtensionRepos> {
if (!options.extensionRepoSettings) return emptyList()

return extensionRepoBackupCreator()
}

fun backupSourcePreferences(options: BackupOptions): List<BackupSourcePreferences> {
if (!options.sourceSettings) return emptyList()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ data class BackupOptions(
val tracking: Boolean = true,
val history: Boolean = true,
val appSettings: Boolean = true,
val extensionRepoSettings: Boolean = true,
val sourceSettings: Boolean = true,
val privateSettings: Boolean = false,
// SY -->
Expand All @@ -27,6 +28,7 @@ data class BackupOptions(
tracking,
history,
appSettings,
extensionRepoSettings,
sourceSettings,
privateSettings,
// SY -->
Expand All @@ -35,7 +37,7 @@ data class BackupOptions(
// SY <--
)

fun canCreate() = libraryEntries || categories || appSettings || sourceSettings
fun canCreate() = libraryEntries || categories || appSettings || extensionRepoSettings || sourceSettings

companion object {
val libraryOptions = persistentListOf(
Expand Down Expand Up @@ -89,6 +91,11 @@ data class BackupOptions(
getter = BackupOptions::appSettings,
setter = { options, enabled -> options.copy(appSettings = enabled) },
),
Entry(
label = MR.strings.extensionRepo_settings,
getter = BackupOptions::extensionRepoSettings,
setter = { options, enabled -> options.copy(extensionRepoSettings = enabled) },
),
Entry(
label = MR.strings.source_settings,
getter = BackupOptions::sourceSettings,
Expand All @@ -109,11 +116,12 @@ data class BackupOptions(
tracking = array[3],
history = array[4],
appSettings = array[5],
sourceSettings = array[6],
privateSettings = array[7],
extensionRepoSettings = array[6],
sourceSettings = array[7],
privateSettings = array[8],
// SY -->
customInfo = array[8],
readEntries = array[9],
customInfo = array[9],
readEntries = array[10],
// SY <--
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package eu.kanade.tachiyomi.data.backup.create.creators

import eu.kanade.tachiyomi.data.backup.models.BackupExtensionRepos
import eu.kanade.tachiyomi.data.backup.models.backupExtensionReposMapper
import mihon.domain.extensionrepo.interactor.GetExtensionRepo
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get

class ExtensionRepoBackupCreator(
private val getExtensionRepos: GetExtensionRepo = Injekt.get(),
) {

suspend operator fun invoke(): List<BackupExtensionRepos> {
return getExtensionRepos.getAll()
.map(backupExtensionReposMapper)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package eu.kanade.tachiyomi.data.backup.models
import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber

@Suppress("MagicNumber")
@Serializable
data class Backup(
@ProtoNumber(1) val backupManga: List<BackupManga>,
Expand All @@ -11,6 +12,7 @@ data class Backup(
@ProtoNumber(101) var backupSources: List<BackupSource> = emptyList(),
@ProtoNumber(104) var backupPreferences: List<BackupPreference> = emptyList(),
@ProtoNumber(105) var backupSourcePreferences: List<BackupSourcePreferences> = emptyList(),
@ProtoNumber(106) var backupExtensionRepo: List<BackupExtensionRepos> = emptyList(),
// SY specific values
@ProtoNumber(600) var backupSavedSearches: List<BackupSavedSearch> = emptyList(),
// KMK -->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package eu.kanade.tachiyomi.data.backup.models

import kotlinx.serialization.Serializable
import kotlinx.serialization.protobuf.ProtoNumber
import mihon.domain.extensionrepo.model.ExtensionRepo

@Suppress("MagicNumber")
@Serializable
class BackupExtensionRepos(
@ProtoNumber(1) var baseUrl: String,
@ProtoNumber(2) var name: String,
@ProtoNumber(3) var shortName: String?,
@ProtoNumber(4) var website: String,
@ProtoNumber(5) var signingKeyFingerprint: String,
)

val backupExtensionReposMapper = { repo: ExtensionRepo ->
BackupExtensionRepos(
baseUrl = repo.baseUrl,
name = repo.name,
shortName = repo.shortName,
website = repo.website,
signingKeyFingerprint = repo.signingKeyFingerprint,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import android.net.Uri
import eu.kanade.tachiyomi.data.backup.BackupDecoder
import eu.kanade.tachiyomi.data.backup.BackupNotifier
import eu.kanade.tachiyomi.data.backup.models.BackupCategory
import eu.kanade.tachiyomi.data.backup.models.BackupExtensionRepos
import eu.kanade.tachiyomi.data.backup.models.BackupFeed
import eu.kanade.tachiyomi.data.backup.models.BackupManga
import eu.kanade.tachiyomi.data.backup.models.BackupPreference
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
import eu.kanade.tachiyomi.data.backup.models.BackupSourcePreferences
import eu.kanade.tachiyomi.data.backup.restore.restorers.CategoriesRestorer
import eu.kanade.tachiyomi.data.backup.restore.restorers.ExtensionRepoRestorer
import eu.kanade.tachiyomi.data.backup.restore.restorers.FeedRestorer
import eu.kanade.tachiyomi.data.backup.restore.restorers.MangaRestorer
import eu.kanade.tachiyomi.data.backup.restore.restorers.PreferenceRestorer
Expand All @@ -36,6 +38,7 @@ class BackupRestorer(

private val categoriesRestorer: CategoriesRestorer = CategoriesRestorer(),
private val preferenceRestorer: PreferenceRestorer = PreferenceRestorer(context),
private val extensionRepoRestorer: ExtensionRepoRestorer = ExtensionRepoRestorer(),
private val mangaRestorer: MangaRestorer = MangaRestorer(isSync),
// SY -->
private val savedSearchRestorer: SavedSearchRestorer = SavedSearchRestorer(),
Expand Down Expand Up @@ -93,6 +96,9 @@ class BackupRestorer(
if (options.appSettings) {
restoreAmount += 1
}
if (options.extensionRepoSettings) {
restoreAmount += backup.backupExtensionRepo.size
}
if (options.sourceSettings) {
restoreAmount += 1
}
Expand Down Expand Up @@ -120,6 +126,9 @@ class BackupRestorer(
if (options.libraryEntries) {
restoreManga(backup.backupManga, if (options.categories) backup.backupCategories else emptyList())
}
if (options.extensionRepoSettings) {
restoreExtensionRepos(backup.backupExtensionRepo)
}

// TODO: optionally trigger online library + tracker update
}
Expand Down Expand Up @@ -208,6 +217,29 @@ class BackupRestorer(
)
}

private fun CoroutineScope.restoreExtensionRepos(
backupExtensionRepo: List<BackupExtensionRepos>
) = launch {
backupExtensionRepo
.forEach {
ensureActive()

try {
extensionRepoRestorer(it)
} catch (e: Exception) {
errors.add(Date() to "Error Adding Repo: ${it.name} : ${e.message}")
}

restoreProgress += 1
notifier.showRestoreProgress(
context.stringResource(MR.strings.extensionRepo_settings),
restoreProgress,
restoreAmount,
isSync,
)
}
}

private fun writeErrorLog(): File {
try {
if (errors.isNotEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ data class RestoreOptions(
val libraryEntries: Boolean = true,
val categories: Boolean = true,
val appSettings: Boolean = true,
val extensionRepoSettings: Boolean = true,
val sourceSettings: Boolean = true,
// SY -->
val savedSearches: Boolean = true,
Expand All @@ -19,14 +20,17 @@ data class RestoreOptions(
libraryEntries,
categories,
appSettings,
extensionRepoSettings,
sourceSettings,
// SY -->
savedSearches
// SY <--
)

fun canRestore() = libraryEntries || categories || appSettings || sourceSettings /* SY --> */ ||
savedSearches /* SY <-- */
fun canRestore() = libraryEntries || categories || appSettings || extensionRepoSettings || sourceSettings ||
// SY -->
savedSearches
// SY <--

companion object {
val options = persistentListOf(
Expand All @@ -45,6 +49,11 @@ data class RestoreOptions(
getter = RestoreOptions::appSettings,
setter = { options, enabled -> options.copy(appSettings = enabled) },
),
Entry(
label = MR.strings.extensionRepo_settings,
getter = RestoreOptions::extensionRepoSettings,
setter = { options, enabled -> options.copy(extensionRepoSettings = enabled) },
),
Entry(
label = MR.strings.source_settings,
getter = RestoreOptions::sourceSettings,
Expand All @@ -63,9 +72,10 @@ data class RestoreOptions(
libraryEntries = array[0],
categories = array[1],
appSettings = array[2],
sourceSettings = array[3],
extensionRepoSettings = array[3],
sourceSettings = array[4],
// SY -->
savedSearches = array[4]
savedSearches = array[5]
// SY <--
)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package eu.kanade.tachiyomi.data.backup.restore.restorers

import eu.kanade.tachiyomi.data.backup.models.BackupExtensionRepos
import mihon.domain.extensionrepo.interactor.GetExtensionRepo
import tachiyomi.data.DatabaseHandler
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get

class ExtensionRepoRestorer(
private val handler: DatabaseHandler = Injekt.get(),
private val getExtensionRepos: GetExtensionRepo = Injekt.get()
) {

suspend operator fun invoke(
backupRepo: BackupExtensionRepos,
) {
val dbRepos = getExtensionRepos.getAll()
val existingReposBySHA = dbRepos.associateBy { it.signingKeyFingerprint }
val existingReposByUrl = dbRepos.associateBy { it.baseUrl }

val urlExists = existingReposByUrl[backupRepo.baseUrl]
val shaExists = existingReposBySHA[backupRepo.signingKeyFingerprint]

if (urlExists != null && urlExists.signingKeyFingerprint != backupRepo.signingKeyFingerprint) {
error("Already Exists with different signing key fingerprint")
} else if (shaExists != null) {
error("${shaExists.name} has the same signing key fingerprint")
} else {
handler.await {
extension_reposQueries.insert(
backupRepo.baseUrl,
backupRepo.name,
backupRepo.shortName,
backupRepo.website,
backupRepo.signingKeyFingerprint
)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ class SyncManager(
backupCategories = backupCreator.backupCategories(backupOptions),
backupSources = backupCreator.backupSources(backupManga),
backupPreferences = backupCreator.backupAppPreferences(backupOptions),
backupExtensionRepo = backupCreator.backupExtensionRepos(backupOptions),
backupSourcePreferences = backupCreator.backupSourcePreferences(backupOptions),

// SY -->
Expand Down
1 change: 1 addition & 0 deletions i18n/src/commonMain/moko-resources/base/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@
<string name="backup_choice">What do you want to backup?</string>
<string name="app_settings">App settings</string>
<string name="source_settings">Source settings</string>
<string name="extensionRepo_settings">Extension Repos</string>
<string name="private_settings">Include sensitive settings (e.g., tracker login tokens)</string>
<string name="creating_backup">Creating backup</string>
<string name="creating_backup_error">Backup failed</string>
Expand Down

0 comments on commit 652126c

Please sign in to comment.