diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/KoreaderSyncMutation.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/KoreaderSyncMutation.kt index bb4da763..71d933e1 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/KoreaderSyncMutation.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/mutations/KoreaderSyncMutation.kt @@ -1,14 +1,21 @@ package suwayomi.tachidesk.graphql.mutations +import graphql.execution.DataFetcherResult import graphql.schema.DataFetchingEnvironment +import org.jetbrains.exposed.sql.selectAll +import org.jetbrains.exposed.sql.transactions.transaction +import org.jetbrains.exposed.sql.update +import suwayomi.tachidesk.graphql.asDataFetcherResult import suwayomi.tachidesk.graphql.server.getAttribute +import suwayomi.tachidesk.graphql.types.ChapterType import suwayomi.tachidesk.graphql.types.KoSyncConnectPayload import suwayomi.tachidesk.graphql.types.LogoutKoSyncAccountPayload import suwayomi.tachidesk.graphql.types.SettingsType +import suwayomi.tachidesk.graphql.types.SyncConflictInfoType import suwayomi.tachidesk.manga.impl.sync.KoreaderSyncService +import suwayomi.tachidesk.manga.model.table.ChapterTable import suwayomi.tachidesk.server.JavalinSetup.Attribute import suwayomi.tachidesk.server.JavalinSetup.future -import suwayomi.tachidesk.server.JavalinSetup.getAttribute import suwayomi.tachidesk.server.user.requireUser import java.util.concurrent.CompletableFuture @@ -53,4 +60,100 @@ class KoreaderSyncMutation { settings = SettingsType(), ) } + + data class PushKoSyncProgressInput( + val clientMutationId: String? = null, + val chapterId: Int, + ) + + data class PushKoSyncProgressPayload( + val clientMutationId: String?, + val success: Boolean, + val chapter: ChapterType?, + ) + + fun pushKoSyncProgress( + dataFetchingEnvironment: DataFetchingEnvironment, + input: PushKoSyncProgressInput, + ): CompletableFuture> = + future { + asDataFetcherResult { + dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser() + + KoreaderSyncService.pushProgress(input.chapterId) + + val chapter = + transaction { + ChapterTable + .selectAll() + .where { ChapterTable.id eq input.chapterId } + .firstOrNull() + ?.let { ChapterType(it) } + } + + PushKoSyncProgressPayload( + clientMutationId = input.clientMutationId, + success = true, + chapter = chapter, + ) + } + } + + data class PullKoSyncProgressInput( + val clientMutationId: String? = null, + val chapterId: Int, + ) + + data class PullKoSyncProgressPayload( + val clientMutationId: String?, + val chapter: ChapterType?, + val syncConflict: SyncConflictInfoType?, + ) + + fun pullKoSyncProgress( + dataFetchingEnvironment: DataFetchingEnvironment, + input: PullKoSyncProgressInput, + ): CompletableFuture> = + future { + asDataFetcherResult { + dataFetchingEnvironment.getAttribute(Attribute.TachideskUser).requireUser() + + val syncResult = KoreaderSyncService.checkAndPullProgress(input.chapterId) + var syncConflictInfo: SyncConflictInfoType? = null + + if (syncResult != null) { + if (syncResult.isConflict) { + syncConflictInfo = + SyncConflictInfoType( + deviceName = syncResult.device, + remotePage = syncResult.pageRead, + ) + } + + if (syncResult.shouldUpdate) { + transaction { + ChapterTable.update({ ChapterTable.id eq input.chapterId }) { + it[lastPageRead] = syncResult.pageRead + it[lastReadAt] = syncResult.timestamp + } + } + } + } + + val chapter = + transaction { + ChapterTable + .selectAll() + .where { ChapterTable.id eq input.chapterId } + .firstOrNull() + ?.let { ChapterType(it) } + } + + PullKoSyncProgressPayload( + clientMutationId = input.clientMutationId, + chapter = chapter, + syncConflict = syncConflictInfo, + ) + } + } }