Experimental Backup Restore fix

This commit is contained in:
Jobobby04 2021-03-11 19:09:30 -05:00
parent 84abe044a3
commit 3d507600cb
6 changed files with 130 additions and 97 deletions

View File

@ -10,6 +10,7 @@ import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.toSChapter
import eu.kanade.tachiyomi.source.online.all.EHentai
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
@ -33,6 +34,16 @@ abstract class AbstractBackupManager(protected val context: Context) {
internal fun getMangaFromDatabase(manga: Manga): Manga? =
databaseHelper.getManga(manga.url, manga.source).executeAsBlocking()
internal suspend fun getChapters(source: Source, manga: Manga /* SY --> */, throttleManager: EHentaiThrottleManager /* SY <-- */): List<SChapter> {
return if (source is EHentai) {
source.getChapterList(manga.toMangaInfo(), throttleManager::throttle)
.map { it.toSChapter() }
} else {
source.getChapterList(manga.toMangaInfo())
.map { it.toSChapter() }
}
}
/**
* Fetches chapter information.
*
@ -41,16 +52,7 @@ abstract class AbstractBackupManager(protected val context: Context) {
* @param chapters list of chapters in the backup
* @return Updated manga chapters.
*/
internal open suspend fun restoreChapters(source: Source, manga: Manga, chapters: List<Chapter> /* SY --> */, throttleManager: EHentaiThrottleManager /* SY <-- */): Pair<List<Chapter>, List<Chapter>> {
// SY -->
val fetchedChapters = if (source is EHentai) {
source.getChapterList(manga.toMangaInfo(), throttleManager::throttle)
.map { it.toSChapter() }
} else {
source.getChapterList(manga.toMangaInfo())
.map { it.toSChapter() }
}
// SY <--
internal open suspend fun restoreChapters(source: Source, manga: Manga, chapters: List<Chapter>, fetchedChapters: List<SChapter>): Pair<List<Chapter>, List<Chapter>> {
val syncedChapters = syncChaptersWithSource(databaseHelper, fetchedChapters, manga, source)
if (syncedChapters.first.isNotEmpty()) {
chapters.forEach { it.manga_id = manga.id }

View File

@ -9,6 +9,7 @@ import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.util.chapter.NoChaptersException
import eu.kanade.tachiyomi.util.system.createFileInCacheDir
import exh.eh.EHentaiThrottleManager
@ -69,9 +70,9 @@ abstract class AbstractBackupRestore<T : AbstractBackupManager>(protected val co
* @param manga manga that needs updating
* @return Updated manga chapters.
*/
internal suspend fun updateChapters(source: Source, manga: Manga, chapters: List<Chapter>): Pair<List<Chapter>, List<Chapter>> {
internal suspend fun updateChapters(source: Source, manga: Manga, chapters: List<Chapter>, fetchedChapters: List<SChapter>): Pair<List<Chapter>, List<Chapter>> {
return try {
backupManager.restoreChapters(source, manga, chapters /* SY --> */, throttleManager /* SY <-- */)
backupManager.restoreChapters(source, manga, chapters, fetchedChapters)
} catch (e: Exception) {
// If there's any error, return empty update and continue.
val errorMessage = if (e is NoChaptersException) {

View File

@ -29,11 +29,9 @@ import eu.kanade.tachiyomi.data.database.models.History
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaCategory
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.source.online.MetadataSource
import eu.kanade.tachiyomi.source.online.all.MergedSource
import exh.metadata.metadata.base.getFlatMetadataForManga
import exh.metadata.metadata.base.insertFlatMetadataAsync
import exh.savedsearches.JsonSavedSearch
@ -47,6 +45,7 @@ import kotlinx.serialization.protobuf.ProtoBuf
import okio.buffer
import okio.gzip
import okio.sink
import tachiyomi.source.model.MangaInfo
import timber.log.Timber
import kotlin.math.max
@ -241,20 +240,19 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
* @param manga manga that needs updating
* @return Updated manga info.
*/
suspend fun restoreMangaFetch(source: Source?, manga: Manga, online: Boolean): Manga {
return if (online && source != null /* SY --> */ && source !is MergedSource /* SY <-- */) {
val networkManga = source.getMangaDetails(manga.toMangaInfo())
manga.also {
it.copyFrom(networkManga.toSManga())
it.favorite = manga.favorite
it.initialized = true
it.id = insertManga(manga)
fun restoreMangaFetch(manga: Manga, networkManga: MangaInfo) {
manga.apply {
copyFrom(networkManga.toSManga())
favorite = manga.favorite
initialized = true
id = insertManga(manga)
}
} else {
manga.also {
it.initialized = it.description != null
it.id = insertManga(it)
}
fun restoreMangaNoFetch(manga: Manga) {
manga.apply {
initialized = description != null
id = insertManga(this)
}
}
@ -499,21 +497,18 @@ class FullBackupManager(context: Context) : AbstractBackupManager(context) {
* @param backupMergedMangaReferences the list of backup manga references for the merged manga
*/
internal fun restoreMergedMangaReferencesForManga(manga: Manga, backupMergedMangaReferences: List<BackupMergedMangaReference>) {
if (backupMergedMangaReferences.isEmpty()) return
// Get merged manga references from file and from db
val dbMergedMangaReferences = databaseHelper.getMergedMangaReferences().executeAsBlocking()
// Iterate over them
backupMergedMangaReferences.forEach { backupMergedMangaReference ->
// Used to know if the merged manga reference is already in the db
var found = false
for (dbMergedMangaReference in dbMergedMangaReferences) {
// If the backupMergedMangaReference is already in the db, assign the id to the file's backupMergedMangaReference
// and do nothing
if (backupMergedMangaReference.mergeUrl == dbMergedMangaReference.mergeUrl && backupMergedMangaReference.mangaUrl == dbMergedMangaReference.mangaUrl) {
found = true
break
}
}
val found = dbMergedMangaReferences.any { backupMergedMangaReference.mergeUrl == it.mergeUrl && backupMergedMangaReference.mangaUrl == it.mangaUrl }
// If the backupMergedMangaReference isn't in the db, remove the id and insert a new backupMergedMangaReference
// Store the inserted id in the backupMergedMangaReference
if (!found) {

View File

@ -15,6 +15,7 @@ import eu.kanade.tachiyomi.data.backup.full.models.BackupSerializer
import eu.kanade.tachiyomi.data.database.models.Chapter
import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.online.all.MergedSource
import exh.EXHMigrations
@ -137,7 +138,6 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier, private val
) {
val dbManga = backupManager.getMangaFromDatabase(manga)
db.inTransaction {
if (dbManga == null) {
// Manga not in database
restoreMangaFetch(source, manga, chapters, categories, history, tracks, backupCategories, mergedMangaReferences, flatMetadata, online)
@ -148,7 +148,6 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier, private val
restoreMangaNoFetch(source, manga, chapters, categories, history, tracks, backupCategories, mergedMangaReferences, flatMetadata, online)
}
}
}
/**
* Fetches manga information
@ -170,22 +169,36 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier, private val
online: Boolean
) {
try {
val fetchedManga = backupManager.restoreMangaFetch(source, manga, online)
fetchedManga.id ?: return
val networkManga = if (online && source != null /* SY --> */ && source !is MergedSource /* SY <-- */) {
source.getMangaDetails(manga.toMangaInfo())
} else null
val fetchedChapters = if (online && source != null && source !is MergedSource) {
backupManager.getChapters(source, manga, throttleManager)
} else null
if (online && source != null) {
db.inTransaction {
if (networkManga != null) {
backupManager.restoreMangaFetch(manga, networkManga)
} else {
backupManager.restoreMangaNoFetch(manga)
}
manga.id ?: return
if (fetchedChapters != null && source != null) {
// SY -->
if (source !is MergedSource) {
updateChapters(source, fetchedManga, chapters)
updateChapters(source, manga, chapters, fetchedChapters)
}
// SY <--
} else {
backupManager.restoreChaptersForMangaOffline(fetchedManga, chapters)
backupManager.restoreChaptersForMangaOffline(manga, chapters)
}
restoreExtraForManga(fetchedManga, categories, history, tracks, backupCategories, mergedMangaReferences, flatMetadata)
restoreExtraForManga(manga, categories, history, tracks, backupCategories, mergedMangaReferences, flatMetadata)
}
updateTracking(fetchedManga, tracks)
updateTracking(manga, tracks)
} catch (e: Exception) {
errors.add(Date() to "${manga.title} - ${e.message}")
}
@ -203,15 +216,23 @@ class FullBackupRestore(context: Context, notifier: BackupNotifier, private val
flatMetadata: BackupFlatMetadata?,
online: Boolean
) {
if (online && source != null) {
val dbChapters = if (source !is MergedSource) backupManager.databaseHelper.getChapters(backupManga).executeAsBlocking() else emptyList()
val fetchedChapters = if (online && source != null && source !is MergedSource && !(dbChapters.isNotEmpty() && dbChapters.size >= chapters.size)) {
backupManager.getChapters(source, backupManga, throttleManager)
} else null
db.inTransaction {
if (fetchedChapters != null && source != null) {
if (/* SY --> */ source !is MergedSource && /* SY <-- */ !backupManager.restoreChaptersForManga(backupManga, chapters)) {
updateChapters(source, backupManga, chapters)
updateChapters(source, backupManga, chapters, fetchedChapters)
}
} else {
backupManager.restoreChaptersForMangaOffline(backupManga, chapters)
}
restoreExtraForManga(backupManga, categories, history, tracks, backupCategories, mergedMangaReferences, flatMetadata)
}
updateTracking(backupManga, tracks)
}

View File

@ -48,19 +48,19 @@ import eu.kanade.tachiyomi.data.database.models.MangaCategory
import eu.kanade.tachiyomi.data.database.models.MangaImpl
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.database.models.TrackImpl
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
import eu.kanade.tachiyomi.source.LocalSource
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.source.online.all.MergedSource
import exh.eh.EHentaiThrottleManager
import exh.merged.sql.models.MergedMangaReference
import exh.savedsearches.JsonSavedSearch
import exh.source.MERGED_SOURCE_ID
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import tachiyomi.source.model.MangaInfo
import timber.log.Timber
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
@ -278,13 +278,12 @@ class LegacyBackupManager(context: Context, version: Int = CURRENT_VERSION) : Ab
* @param manga manga that needs updating
* @return Updated manga.
*/
suspend fun fetchManga(source: Source, manga: Manga): Manga {
val networkManga = source.getMangaDetails(manga.toMangaInfo())
return manga.also {
it.copyFrom(networkManga.toSManga())
it.favorite = true
it.initialized = true
it.id = insertManga(manga)
fun fetchManga(networkManga: MangaInfo, manga: Manga) {
manga.apply {
copyFrom(networkManga.toSManga())
favorite = true
initialized = true
id = insertManga(this)
}
}
@ -295,7 +294,7 @@ class LegacyBackupManager(context: Context, version: Int = CURRENT_VERSION) : Ab
* @param manga manga that needs updating
* @return [Observable] that contains manga
*/
override suspend fun restoreChapters(source: Source, manga: Manga, chapters: List<Chapter>, throttleManager: EHentaiThrottleManager): Pair<List<Chapter>, List<Chapter>> {
override suspend fun restoreChapters(source: Source, manga: Manga, chapters: List<Chapter>, fetchedChapters: List<SChapter>): Pair<List<Chapter>, List<Chapter>> {
// SY -->
return if (source is MergedSource) {
val syncedChapters = source.fetchChaptersAndSync(manga, false)
@ -305,7 +304,7 @@ class LegacyBackupManager(context: Context, version: Int = CURRENT_VERSION) : Ab
updateChapters(syncedChapters.first)
syncedChapters
} else {
super.restoreChapters(source, manga, chapters, throttleManager)
super.restoreChapters(source, manga, chapters, fetchedChapters)
}
}

View File

@ -20,7 +20,9 @@ import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.MangaImpl
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.database.models.TrackImpl
import eu.kanade.tachiyomi.data.database.models.toMangaInfo
import eu.kanade.tachiyomi.source.Source
import eu.kanade.tachiyomi.source.online.all.MergedSource
import exh.EXHMigrations
import java.util.Date
@ -154,7 +156,6 @@ class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : Abstract
) {
val dbManga = backupManager.getMangaFromDatabase(manga)
db.inTransaction {
if (dbManga == null) {
// Manga not in database
restoreMangaFetch(source, manga, chapters, categories, history, tracks)
@ -165,7 +166,6 @@ class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : Abstract
restoreMangaNoFetch(source, manga, chapters, categories, history, tracks)
}
}
}
/**
* Fetches manga information.
@ -183,14 +183,19 @@ class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : Abstract
tracks: List<Track>
) {
try {
val fetchedManga = backupManager.fetchManga(source, manga)
fetchedManga.id ?: return
val networkManga = source.getMangaDetails(manga.toMangaInfo())
val fetchedChapters = if (source !is MergedSource) {
backupManager.getChapters(source, manga, throttleManager)
} else emptyList()
db.inTransaction {
backupManager.fetchManga(networkManga, manga)
manga.id ?: return
updateChapters(source, fetchedManga, chapters)
updateChapters(source, manga, chapters, fetchedChapters)
restoreExtraForManga(fetchedManga, categories, history, tracks)
updateTracking(fetchedManga, tracks)
restoreExtraForManga(manga, categories, history, tracks)
}
updateTracking(manga, tracks)
} catch (e: Exception) {
errors.add(Date() to "${manga.title} - ${e.message}")
}
@ -204,11 +209,21 @@ class LegacyBackupRestore(context: Context, notifier: BackupNotifier) : Abstract
history: List<DHistory>,
tracks: List<Track>
) {
if (!backupManager.restoreChaptersForManga(backupManga, chapters)) {
updateChapters(source, backupManga, chapters)
val dbChapters = backupManager.databaseHelper.getChapters(backupManga).executeAsBlocking()
val fetchedChapters = if (dbChapters.isNotEmpty() && dbChapters.size >= chapters.size) {
backupManager.getChapters(source, backupManga, throttleManager)
} else {
null
}
db.inTransaction {
if (!backupManager.restoreChaptersForManga(backupManga, chapters) && fetchedChapters != null) {
updateChapters(source, backupManga, chapters, fetchedChapters)
}
restoreExtraForManga(backupManga, categories, history, tracks)
}
updateTracking(backupManga, tracks)
}