Fix (EXH): Migrate old source to new source for merge references

This commit is contained in:
Cuong-Tran 2025-02-11 14:03:30 +07:00
parent caa0d9b92e
commit 235dec019d
7 changed files with 80 additions and 41 deletions

View file

@ -30,6 +30,10 @@ class SmartSearchMerge(
private val getCategories: GetCategories = Injekt.get(),
private val setMangaCategories: SetMangaCategories = Injekt.get(),
) {
/**
* @param originalMangaId ID of the existed merged entry or the original manga which will be used to create the new merged entry
* @param manga The manga which will be merged into existed merged entry or the new merged entry (newly created by using [originalMangaId])
*/
suspend fun smartSearchMerge(manga: Manga, originalMangaId: Long): Manga {
// KMK -->
val context = Injekt.get<Application>()

View file

@ -359,6 +359,7 @@ class MangaRestorer(
/**
* Restores the categories a manga is in.
* Only if [backupCategories] is provided and user chooses to restore it.
*
* @param manga the manga whose categories have to be restored.
* @param categories the categories to restore.
@ -507,46 +508,50 @@ class MangaRestorer(
}
// Iterate over them
backupMergedMangaReferences.forEach { backupMergedMangaReference ->
// If the backupMergedMangaReference isn't in the db,
// remove the id and insert a new backupMergedMangaReference
// Store the inserted id in the backupMergedMangaReference
if (dbMergedMangaReferences.none {
backupMergedMangaReference.mergeUrl == it.mergeUrl &&
backupMergedMangaReference.mangaUrl == it.mangaUrl
}
) {
// Let the db assign the id
// KMK -->
val mergedManga = handler.awaitList {
// KMK <--
mangasQueries.getMangaByUrlAndSource(
backupMergedMangaReference.mangaUrl,
backupMergedMangaReference.mangaSourceId,
MangaMapper::mapManga,
)
backupMergedMangaReferences
// KMK -->
.map { EXHMigrations.migrateBackupMergedMangaReference(it) }
// KMK <--
.forEach { backupMergedMangaReference ->
// If the backupMergedMangaReference isn't in the db,
// remove the id and insert a new backupMergedMangaReference
// Store the inserted id in the backupMergedMangaReference
if (dbMergedMangaReferences.none {
backupMergedMangaReference.mergeUrl == it.mergeUrl &&
backupMergedMangaReference.mangaUrl == it.mangaUrl
}
) {
// Let the db assign the id
// KMK -->
}.firstOrNull()
// KMK <--
?: return@forEach
backupMergedMangaReference.getMergedMangaReference().run {
handler.await {
mergedQueries.insert(
infoManga = isInfoManga,
getChapterUpdates = getChapterUpdates,
chapterSortMode = chapterSortMode.toLong(),
chapterPriority = chapterPriority.toLong(),
downloadChapters = downloadChapters,
mergeId = mergeMangaId,
mergeUrl = mergeUrl,
mangaId = mergedManga.id,
mangaUrl = mangaUrl,
mangaSource = mangaSourceId,
val mergedManga = handler.awaitList {
// KMK <--
mangasQueries.getMangaByUrlAndSource(
backupMergedMangaReference.mangaUrl,
backupMergedMangaReference.mangaSourceId,
MangaMapper::mapManga,
)
// KMK -->
}.firstOrNull()
// KMK <--
?: return@forEach
backupMergedMangaReference.getMergedMangaReference().run {
handler.await {
mergedQueries.insert(
infoManga = isInfoManga,
getChapterUpdates = getChapterUpdates,
chapterSortMode = chapterSortMode.toLong(),
chapterPriority = chapterPriority.toLong(),
downloadChapters = downloadChapters,
mergeId = mergeMangaId,
mergeUrl = mergeUrl,
mangaId = mergedManga.id,
mangaUrl = mangaUrl,
mangaSource = mangaSourceId,
)
}
}
}
}
}
}
private suspend fun restoreFlatMetadata(mangaId: Long, backupFlatMetadata: BackupFlatMetadata) {

View file

@ -1,6 +1,7 @@
package exh
import eu.kanade.tachiyomi.data.backup.models.BackupFeed
import eu.kanade.tachiyomi.data.backup.models.BackupMergedMangaReference
import eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
import exh.source.EH_OLD_ID
import exh.source.EH_SOURCE_ID
@ -64,6 +65,30 @@ object EXHMigrations {
}
// KMK -->
/**
* Migrate old source ID of delegated sources in old backup
*/
fun migrateBackupMergedMangaReference(mergeReference: BackupMergedMangaReference): BackupMergedMangaReference {
return when (mergeReference.mangaSourceId) {
NHENTAI_OLD_ID -> mergeReference.copy(
mangaSourceId = NHENTAI_SOURCE_ID,
)
TSUMINO_OLD_ID -> mergeReference.copy(
mangaSourceId = TSUMINO_SOURCE_ID,
)
HBROWSE_OLD_ID -> mergeReference.copy(
mangaSourceId = HBROWSE_SOURCE_ID,
)
EH_OLD_ID -> mergeReference.copy(
mangaSourceId = EH_SOURCE_ID,
)
EXH_OLD_ID -> mergeReference.copy(
mangaSourceId = EXH_SOURCE_ID,
)
else -> mergeReference
}
}
/**
* Migrate old source ID of delegated sources in old backup
*/

View file

@ -11,8 +11,8 @@ object MigrateUtils {
val handler = migrationContext.get<DatabaseHandler>() ?: return
runBlocking {
handler.await { ehQueries.migrateSource(newId, oldId) }
// KMK -->
handler.await { ehQueries.migrateMergedSource(newId, oldId) }
// Migrate saved searches & feeds
handler.await { ehQueries.migrateSourceSavedSearch(newId, oldId) }
handler.await { ehQueries.migrateSourceFeed(newId, oldId) }

View file

@ -7,6 +7,11 @@ SET source = :newId
WHERE source = :oldId;
-- KMK -->
migrateMergedSource:
UPDATE merged
SET manga_source = :newId
WHERE manga_source = :oldId;
migrateSourceSavedSearch:
UPDATE saved_search
SET source = :newId

View file

@ -7,10 +7,10 @@ CREATE TABLE merged(
chapter_sort_mode INTEGER NOT NULL,
chapter_priority INTEGER NOT NULL,
download_chapters INTEGER AS Boolean NOT NULL,
merge_id INTEGER NOT NULL,
merge_url TEXT NOT NULL,
manga_id INTEGER,
manga_url TEXT NOT NULL,
merge_id INTEGER NOT NULL, -- Point to the fake manga which was created as a merge entry
merge_url TEXT NOT NULL, -- URL of the merge entry, usually is the original first manga used to create a merge entry
manga_id INTEGER, -- Point to actual children manga entry which is a part of this merge entry
manga_url TEXT NOT NULL, -- URL of the actual children manga entry which is a part of this merge entry
manga_source INTEGER NOT NULL,
FOREIGN KEY(manga_id) REFERENCES mangas (_id)
ON DELETE SET NULL,

View file

@ -10,7 +10,7 @@ data class MergedMangaReference(
// If false the manga will not grab chapter updates
val getChapterUpdates: Boolean,
// The mode in which the chapters are handeled, only set in the main merge reference
// The mode in which the chapters are handled, only set in the main merge reference
val chapterSortMode: Int,
// chapter priority the deduplication uses