From 3a67ddf0f697967e4dbc33f3ce84aac142f4b791 Mon Sep 17 00:00:00 2001 From: Syer10 Date: Fri, 31 Mar 2023 20:58:18 -0400 Subject: [PATCH] Add Extensions to Graphql --- .../dataLoaders/ExtensionDataLoader.kt | 47 ++++++++++++++++++ .../graphql/dataLoaders/SourceDataLoader.kt | 20 ++++++++ .../graphql/queries/ExtensionQuery.kt | 30 ++++++++++++ .../TachideskDataLoaderRegistryFactory.kt | 5 +- .../graphql/server/TachideskGraphQLSchema.kt | 4 +- .../tachidesk/graphql/types/ExtensionType.kt | 48 +++++++++++++++++++ .../tachidesk/graphql/types/SourceType.kt | 15 ++++-- 7 files changed, 164 insertions(+), 5 deletions(-) create mode 100644 server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ExtensionDataLoader.kt create mode 100644 server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ExtensionQuery.kt create mode 100644 server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ExtensionType.kt diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ExtensionDataLoader.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ExtensionDataLoader.kt new file mode 100644 index 00000000..37478b75 --- /dev/null +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/ExtensionDataLoader.kt @@ -0,0 +1,47 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +package suwayomi.tachidesk.graphql.dataLoaders + +import com.expediagroup.graphql.dataloader.KotlinDataLoader +import org.dataloader.DataLoader +import org.dataloader.DataLoaderFactory +import org.jetbrains.exposed.sql.StdOutSqlLogger +import org.jetbrains.exposed.sql.addLogger +import org.jetbrains.exposed.sql.select +import org.jetbrains.exposed.sql.transactions.transaction +import suwayomi.tachidesk.graphql.types.ExtensionType +import suwayomi.tachidesk.manga.model.table.ExtensionTable +import suwayomi.tachidesk.manga.model.table.SourceTable +import suwayomi.tachidesk.server.JavalinSetup.future + +class ExtensionDataLoader : KotlinDataLoader { + override val dataLoaderName = "ExtensionDataLoader" + override fun getDataLoader(): DataLoader = DataLoaderFactory.newDataLoader { ids -> + future { + transaction { + addLogger(StdOutSqlLogger) + ExtensionTable.select { ExtensionTable.pkgName inList ids } + .map { ExtensionType(it) } + } + } + } +} + +class ExtensionForSourceDataLoader : KotlinDataLoader { + override val dataLoaderName = "ExtensionForSourceDataLoader" + override fun getDataLoader(): DataLoader = DataLoaderFactory.newDataLoader { ids -> + future { + transaction { + addLogger(StdOutSqlLogger) + ExtensionTable.innerJoin(SourceTable) + .select { SourceTable.id inList ids } + .map { ExtensionType(it) } + } + } + } +} diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/SourceDataLoader.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/SourceDataLoader.kt index 9f5fa6ec..e9ce4ced 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/SourceDataLoader.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/dataLoaders/SourceDataLoader.kt @@ -16,6 +16,7 @@ import org.jetbrains.exposed.sql.addLogger import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.transactions.transaction import suwayomi.tachidesk.graphql.types.SourceType +import suwayomi.tachidesk.manga.model.table.ExtensionTable import suwayomi.tachidesk.manga.model.table.MangaTable import suwayomi.tachidesk.manga.model.table.SourceTable import suwayomi.tachidesk.server.JavalinSetup.future @@ -61,3 +62,22 @@ class SourceForMangaDataLoader : KotlinDataLoader { } } } + +class SourcesForExtensionDataLoader : KotlinDataLoader> { + override val dataLoaderName = "SourcesForExtensionDataLoader" + override fun getDataLoader(): DataLoader> = DataLoaderFactory.newDataLoader { ids -> + future { + transaction { + addLogger(StdOutSqlLogger) + + val sourcesByExtensionPkg = SourceTable.innerJoin(ExtensionTable) + .select { ExtensionTable.pkgName inList ids } + .map { Pair(it[ExtensionTable.pkgName], SourceType(it)) } + .groupBy { it.first } + .mapValues { it.value.mapNotNull { pair -> pair.second } } + + ids.map { sourcesByExtensionPkg[it] ?: emptyList() } + } + } + } +} diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ExtensionQuery.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ExtensionQuery.kt new file mode 100644 index 00000000..68c754b8 --- /dev/null +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/queries/ExtensionQuery.kt @@ -0,0 +1,30 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +package suwayomi.tachidesk.graphql.queries + +import com.expediagroup.graphql.server.extensions.getValueFromDataLoader +import graphql.schema.DataFetchingEnvironment +import org.jetbrains.exposed.sql.selectAll +import org.jetbrains.exposed.sql.transactions.transaction +import suwayomi.tachidesk.graphql.types.ExtensionType +import suwayomi.tachidesk.manga.model.table.ExtensionTable +import java.util.concurrent.CompletableFuture + +class ExtensionQuery { + fun extension(dataFetchingEnvironment: DataFetchingEnvironment, pkgName: String): CompletableFuture { + return dataFetchingEnvironment.getValueFromDataLoader("ExtensionDataLoader", pkgName) + } + + fun extensions(): List { + val results = transaction { + ExtensionTable.selectAll().toList() + } + + return results.map { ExtensionType(it) } + } +} diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskDataLoaderRegistryFactory.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskDataLoaderRegistryFactory.kt index 639f6829..81a95a7a 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskDataLoaderRegistryFactory.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskDataLoaderRegistryFactory.kt @@ -23,7 +23,10 @@ class TachideskDataLoaderRegistryFactory { CategoryMetaDataLoader(), CategoriesForMangaDataLoader(), SourceDataLoader(), - SourceForMangaDataLoader() + SourceForMangaDataLoader(), + SourcesForExtensionDataLoader(), + ExtensionDataLoader(), + ExtensionForSourceDataLoader() ) } } diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskGraphQLSchema.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskGraphQLSchema.kt index 8c41df54..665ea526 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskGraphQLSchema.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/server/TachideskGraphQLSchema.kt @@ -16,6 +16,7 @@ import graphql.schema.GraphQLType import suwayomi.tachidesk.graphql.mutations.ChapterMutation import suwayomi.tachidesk.graphql.queries.CategoryQuery import suwayomi.tachidesk.graphql.queries.ChapterQuery +import suwayomi.tachidesk.graphql.queries.ExtensionQuery import suwayomi.tachidesk.graphql.queries.MangaQuery import suwayomi.tachidesk.graphql.queries.SourceQuery import suwayomi.tachidesk.graphql.subscriptions.DownloadSubscription @@ -39,7 +40,8 @@ val schema = toSchema( TopLevelObject(MangaQuery()), TopLevelObject(ChapterQuery()), TopLevelObject(CategoryQuery()), - TopLevelObject(SourceQuery()) + TopLevelObject(SourceQuery()), + TopLevelObject(ExtensionQuery()) ), mutations = listOf( TopLevelObject(ChapterMutation()) diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ExtensionType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ExtensionType.kt new file mode 100644 index 00000000..93bf09b1 --- /dev/null +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/ExtensionType.kt @@ -0,0 +1,48 @@ +/* + * Copyright (C) Contributors to the Suwayomi project + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +package suwayomi.tachidesk.graphql.types + +import com.expediagroup.graphql.server.extensions.getValueFromDataLoader +import graphql.schema.DataFetchingEnvironment +import org.jetbrains.exposed.sql.ResultRow +import suwayomi.tachidesk.manga.model.table.ExtensionTable +import java.util.concurrent.CompletableFuture + +class ExtensionType( + val apkName: String, + val iconUrl: String, + + val name: String, + val pkgName: String, + val versionName: String, + val versionCode: Int, + val lang: String, + val isNsfw: Boolean, + + val installed: Boolean, + val hasUpdate: Boolean, + val obsolete: Boolean +) { + constructor(row: ResultRow) : this( + apkName = row[ExtensionTable.apkName], + iconUrl = row[ExtensionTable.iconUrl], + name = row[ExtensionTable.name], + pkgName = row[ExtensionTable.pkgName], + versionName = row[ExtensionTable.versionName], + versionCode = row[ExtensionTable.versionCode], + lang = row[ExtensionTable.lang], + isNsfw = row[ExtensionTable.isNsfw], + installed = row[ExtensionTable.isInstalled], + hasUpdate = row[ExtensionTable.hasUpdate], + obsolete = row[ExtensionTable.isObsolete] + ) + + fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture> { + return dataFetchingEnvironment.getValueFromDataLoader>("SourcesForExtensionDataLoader", pkgName) + } +} diff --git a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/SourceType.kt b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/SourceType.kt index c5c7611e..27d2db96 100644 --- a/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/SourceType.kt +++ b/server/src/main/kotlin/suwayomi/tachidesk/graphql/types/SourceType.kt @@ -55,14 +55,23 @@ class SourceType( fun manga(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture> { return dataFetchingEnvironment.getValueFromDataLoader>("MangaForSourceDataLoader", id) } + + fun extension(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture { + return dataFetchingEnvironment.getValueFromDataLoader("ExtensionForSourceDataLoader", id) + } } fun SourceType(row: ResultRow): SourceType? { val catalogueSource = GetCatalogueSource .getCatalogueSourceOrNull(row[SourceTable.id].value) ?: return null - val sourceExtension = ExtensionTable - .select { ExtensionTable.id eq row[SourceTable.extension] } - .first() + val sourceExtension = if (row.hasValue(ExtensionTable.id)) { + row + } else { + ExtensionTable + .select { ExtensionTable.id eq row[SourceTable.extension] } + .first() + } + return SourceType(row, sourceExtension, catalogueSource) }