Extension mutations (#560)

This commit is contained in:
Mitchell Syer
2023-05-26 19:39:17 -04:00
committed by GitHub
parent 458ca7c7cf
commit 2230796504
3 changed files with 133 additions and 9 deletions

View File

@@ -1,10 +1,127 @@
package suwayomi.tachidesk.graphql.mutations package suwayomi.tachidesk.graphql.mutations
/** import eu.kanade.tachiyomi.source.local.LocalSource
* TODO Mutations import org.jetbrains.exposed.sql.select
* - Install import org.jetbrains.exposed.sql.transactions.transaction
* - Update import suwayomi.tachidesk.graphql.types.ExtensionType
* - Uninstall import suwayomi.tachidesk.manga.impl.extension.Extension
* - Check for updates (global mutation?) import suwayomi.tachidesk.manga.impl.extension.ExtensionsList
*/ import suwayomi.tachidesk.manga.model.table.ExtensionTable
class ExtensionMutation import suwayomi.tachidesk.server.JavalinSetup.future
import java.util.concurrent.CompletableFuture
class ExtensionMutation {
data class UpdateExtensionPatch(
val install: Boolean? = null,
val update: Boolean? = null,
val uninstall: Boolean? = null
)
data class UpdateExtensionPayload(
val clientMutationId: String?,
val extension: ExtensionType
)
data class UpdateExtensionInput(
val clientMutationId: String? = null,
val id: String,
val patch: UpdateExtensionPatch
)
data class UpdateExtensionsPayload(
val clientMutationId: String?,
val extensions: List<ExtensionType>
)
data class UpdateExtensionsInput(
val clientMutationId: String? = null,
val ids: List<String>,
val patch: UpdateExtensionPatch
)
private suspend fun updateExtensions(ids: List<String>, patch: UpdateExtensionPatch) {
val extensions = transaction {
ExtensionTable.select { ExtensionTable.pkgName inList ids }
.map { ExtensionType(it) }
}
if (patch.update == true) {
extensions.filter { it.hasUpdate }.forEach {
Extension.updateExtension(it.pkgName)
}
}
if (patch.install == true) {
extensions.filterNot { it.isInstalled }.forEach {
Extension.installExtension(it.pkgName)
}
}
if (patch.uninstall == true) {
extensions.filter { it.isInstalled }.forEach {
Extension.uninstallExtension(it.pkgName)
}
}
}
fun updateExtension(input: UpdateExtensionInput): CompletableFuture<UpdateExtensionPayload> {
val (clientMutationId, id, patch) = input
return future {
updateExtensions(listOf(id), patch)
}.thenApply {
val extension = transaction {
ExtensionType(ExtensionTable.select { ExtensionTable.pkgName eq id }.first())
}
UpdateExtensionPayload(
clientMutationId = clientMutationId,
extension = extension
)
}
}
fun updateExtensions(input: UpdateExtensionsInput): CompletableFuture<UpdateExtensionsPayload> {
val (clientMutationId, ids, patch) = input
return future {
updateExtensions(ids, patch)
}.thenApply {
val extensions = transaction {
ExtensionTable.select { ExtensionTable.pkgName inList ids }
.map { ExtensionType(it) }
}
UpdateExtensionsPayload(
clientMutationId = clientMutationId,
extensions = extensions
)
}
}
data class FetchExtensionsInput(
val clientMutationId: String? = null
)
data class FetchExtensionsPayload(
val clientMutationId: String?,
val extensions: List<ExtensionType>
)
fun fetchExtensions(
input: FetchExtensionsInput
): CompletableFuture<FetchExtensionsPayload> {
val (clientMutationId) = input
return future {
ExtensionsList.fetchExtensions()
}.thenApply {
val extensions = transaction {
ExtensionTable.select { ExtensionTable.name neq LocalSource.EXTENSION_NAME }
.map { ExtensionType(it) }
}
FetchExtensionsPayload(
clientMutationId = clientMutationId,
extensions = extensions
)
}
}
}

View File

@@ -8,12 +8,14 @@
package suwayomi.tachidesk.graphql.queries package suwayomi.tachidesk.graphql.queries
import com.expediagroup.graphql.server.extensions.getValueFromDataLoader import com.expediagroup.graphql.server.extensions.getValueFromDataLoader
import eu.kanade.tachiyomi.source.local.LocalSource
import graphql.schema.DataFetchingEnvironment import graphql.schema.DataFetchingEnvironment
import org.jetbrains.exposed.sql.Column import org.jetbrains.exposed.sql.Column
import org.jetbrains.exposed.sql.Op import org.jetbrains.exposed.sql.Op
import org.jetbrains.exposed.sql.SortOrder import org.jetbrains.exposed.sql.SortOrder
import org.jetbrains.exposed.sql.SqlExpressionBuilder.greater import org.jetbrains.exposed.sql.SqlExpressionBuilder.greater
import org.jetbrains.exposed.sql.SqlExpressionBuilder.less import org.jetbrains.exposed.sql.SqlExpressionBuilder.less
import org.jetbrains.exposed.sql.SqlExpressionBuilder.neq
import org.jetbrains.exposed.sql.andWhere import org.jetbrains.exposed.sql.andWhere
import org.jetbrains.exposed.sql.selectAll import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
@@ -151,6 +153,8 @@ class ExtensionQuery {
val queryResults = transaction { val queryResults = transaction {
val res = ExtensionTable.selectAll() val res = ExtensionTable.selectAll()
res.adjustWhere { ExtensionTable.name neq LocalSource.EXTENSION_NAME }
res.applyOps(condition, filter) res.applyOps(condition, filter)
if (orderBy != null || (last != null || before != null)) { if (orderBy != null || (last != null || before != null)) {

View File

@@ -30,7 +30,7 @@ object ExtensionsList {
var lastUpdateCheck: Long = 0 var lastUpdateCheck: Long = 0
var updateMap = ConcurrentHashMap<String, OnlineExtension>() var updateMap = ConcurrentHashMap<String, OnlineExtension>()
suspend fun getExtensionList(): List<ExtensionDataClass> { suspend fun fetchExtensions() {
// update if 60 seconds has passed or requested offline and database is empty // update if 60 seconds has passed or requested offline and database is empty
if (lastUpdateCheck + 60.seconds.inWholeMilliseconds < System.currentTimeMillis()) { if (lastUpdateCheck + 60.seconds.inWholeMilliseconds < System.currentTimeMillis()) {
logger.debug("Getting extensions list from the internet") logger.debug("Getting extensions list from the internet")
@@ -41,7 +41,10 @@ object ExtensionsList {
} else { } else {
logger.debug("used cached extension list") logger.debug("used cached extension list")
} }
}
suspend fun getExtensionList(): List<ExtensionDataClass> {
fetchExtensions()
return extensionTableAsDataClass() return extensionTableAsDataClass()
} }