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 getCategories: GetCategories = Injekt.get(),
private val setMangaCategories: SetMangaCategories = 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 { suspend fun smartSearchMerge(manga: Manga, originalMangaId: Long): Manga {
// KMK --> // KMK -->
val context = Injekt.get<Application>() val context = Injekt.get<Application>()

View file

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

View file

@ -1,6 +1,7 @@
package exh package exh
import eu.kanade.tachiyomi.data.backup.models.BackupFeed 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 eu.kanade.tachiyomi.data.backup.models.BackupSavedSearch
import exh.source.EH_OLD_ID import exh.source.EH_OLD_ID
import exh.source.EH_SOURCE_ID import exh.source.EH_SOURCE_ID
@ -64,6 +65,30 @@ object EXHMigrations {
} }
// KMK --> // 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 * Migrate old source ID of delegated sources in old backup
*/ */

View file

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

View file

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

View file

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

View file

@ -10,7 +10,7 @@ data class MergedMangaReference(
// If false the manga will not grab chapter updates // If false the manga will not grab chapter updates
val getChapterUpdates: Boolean, 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, val chapterSortMode: Int,
// chapter priority the deduplication uses // chapter priority the deduplication uses