Feature/backup suwayomi data (#1430)

* Export meta data

* Import meta data

* Add missing "opdsUseBinaryFileSize" setting to gql

* Export server settings

* Import server settings

* Streamline server config enum handling

* Use "restore amount" in backup import progress
This commit is contained in:
schroda
2025-06-15 23:14:13 +02:00
committed by GitHub
parent 483e3a760f
commit 4086a73727
29 changed files with 662 additions and 155 deletions

View File

@@ -20,11 +20,13 @@ import io.github.oshai.kotlinlogging.KotlinLogging
import io.javalin.http.HttpStatus
import okhttp3.CacheControl
import okhttp3.Response
import org.jetbrains.exposed.dao.id.EntityID
import org.jetbrains.exposed.sql.ResultRow
import org.jetbrains.exposed.sql.SortOrder
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.batchInsert
import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.statements.BatchUpdateStatement
import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update
import suwayomi.tachidesk.manga.impl.MangaList.proxyThumbnailUrl
@@ -256,22 +258,57 @@ object Manga {
key: String,
value: String,
) {
modifyMangasMetas(mapOf(mangaId to mapOf(key to value)))
}
fun modifyMangasMetas(metaByMangaId: Map<Int, Map<String, String>>) {
transaction {
val meta =
val mangaIds = metaByMangaId.keys
val metaKeys = metaByMangaId.flatMap { it.value.keys }
val dbMetaByMangaId =
MangaMetaTable
.selectAll()
.where { (MangaMetaTable.ref eq mangaId) and (MangaMetaTable.key eq key) }
.firstOrNull()
.where { (MangaMetaTable.ref inList mangaIds) and (MangaMetaTable.key inList metaKeys) }
.groupBy { it[MangaMetaTable.ref].value }
if (meta == null) {
MangaMetaTable.insert {
it[MangaMetaTable.key] = key
it[MangaMetaTable.value] = value
it[MangaMetaTable.ref] = mangaId
val existingMetaByMetaId =
mangaIds.flatMap { mangaId ->
val metaByKey = dbMetaByMangaId[mangaId].orEmpty().associateBy { it[MangaMetaTable.key] }
val existingMetas = metaByMangaId[mangaId].orEmpty().filter { (key) -> key in metaByKey.keys }
existingMetas.map { entry ->
val metaId = metaByKey[entry.key]!![MangaMetaTable.id].value
metaId to entry
}
}
} else {
MangaMetaTable.update({ (MangaMetaTable.ref eq mangaId) and (MangaMetaTable.key eq key) }) {
it[MangaMetaTable.value] = value
val newMetaByMangaId =
mangaIds.flatMap { mangaId ->
val metaByKey = dbMetaByMangaId[mangaId].orEmpty().associateBy { it[MangaMetaTable.key] }
metaByMangaId[mangaId]
.orEmpty()
.filter { entry -> entry.key !in metaByKey.keys }
.map { entry -> mangaId to entry }
}
if (existingMetaByMetaId.isNotEmpty()) {
BatchUpdateStatement(MangaMetaTable).apply {
existingMetaByMetaId.forEach { (metaId, entry) ->
addBatch(EntityID(metaId, MangaMetaTable))
this[MangaMetaTable.value] = entry.value
}
execute(this@transaction)
}
}
if (newMetaByMangaId.isNotEmpty()) {
MangaMetaTable.batchInsert(newMetaByMangaId) { (mangaId, entry) ->
this[MangaMetaTable.ref] = EntityID(mangaId, MangaTable)
this[MangaMetaTable.key] = entry.key
this[MangaMetaTable.value] = entry.value
}
}
}