Skip to content

Commit

Permalink
Add Source Meta (#875)
Browse files Browse the repository at this point in the history
  • Loading branch information
Syer10 authored Feb 17, 2024
1 parent ea6edae commit af0dde5
Show file tree
Hide file tree
Showing 8 changed files with 181 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import suwayomi.tachidesk.graphql.types.CategoryMetaType
import suwayomi.tachidesk.graphql.types.ChapterMetaType
import suwayomi.tachidesk.graphql.types.GlobalMetaType
import suwayomi.tachidesk.graphql.types.MangaMetaType
import suwayomi.tachidesk.graphql.types.SourceMetaType
import suwayomi.tachidesk.manga.model.table.CategoryMetaTable
import suwayomi.tachidesk.manga.model.table.ChapterMetaTable
import suwayomi.tachidesk.manga.model.table.MangaMetaTable
import suwayomi.tachidesk.manga.model.table.SourceMetaTable
import suwayomi.tachidesk.server.JavalinSetup.future

class GlobalMetaDataLoader : KotlinDataLoader<String, GlobalMetaType?> {
Expand Down Expand Up @@ -88,3 +90,21 @@ class CategoryMetaDataLoader : KotlinDataLoader<Int, List<CategoryMetaType>> {
}
}
}

class SourceMetaDataLoader : KotlinDataLoader<Long, List<SourceMetaType>> {
override val dataLoaderName = "SourceMetaDataLoader"

override fun getDataLoader(): DataLoader<Long, List<SourceMetaType>> =
DataLoaderFactory.newDataLoader<Long, List<SourceMetaType>> { ids ->
future {
transaction {
addLogger(Slf4jSqlDebugLogger)
val metasByRefId =
SourceMetaTable.select { SourceMetaTable.ref inList ids }
.map { SourceMetaType(it) }
.groupBy { it.sourceId }
ids.map { metasByRefId[it].orEmpty() }
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,85 @@ import androidx.preference.EditTextPreference
import androidx.preference.ListPreference
import androidx.preference.MultiSelectListPreference
import androidx.preference.SwitchPreferenceCompat
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.deleteWhere
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction
import suwayomi.tachidesk.graphql.types.FilterChange
import suwayomi.tachidesk.graphql.types.MangaType
import suwayomi.tachidesk.graphql.types.Preference
import suwayomi.tachidesk.graphql.types.SourceMetaType
import suwayomi.tachidesk.graphql.types.SourceType
import suwayomi.tachidesk.graphql.types.preferenceOf
import suwayomi.tachidesk.graphql.types.updateFilterList
import suwayomi.tachidesk.manga.impl.MangaList.insertOrGet
import suwayomi.tachidesk.manga.impl.Source
import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource
import suwayomi.tachidesk.manga.model.table.MangaTable
import suwayomi.tachidesk.manga.model.table.SourceMetaTable
import suwayomi.tachidesk.manga.model.table.SourceTable
import suwayomi.tachidesk.server.JavalinSetup.future
import java.util.concurrent.CompletableFuture

class SourceMutation {
data class SetSourceMetaInput(
val clientMutationId: String? = null,
val meta: SourceMetaType,
)

data class SetSourceMetaPayload(
val clientMutationId: String?,
val meta: SourceMetaType,
)

fun setSourceMeta(input: SetSourceMetaInput): SetSourceMetaPayload {
val (clientMutationId, meta) = input

Source.modifyMeta(meta.sourceId, meta.key, meta.value)

return SetSourceMetaPayload(clientMutationId, meta)
}

data class DeleteSourceMetaInput(
val clientMutationId: String? = null,
val sourceId: Long,
val key: String,
)

data class DeleteSourceMetaPayload(
val clientMutationId: String?,
val meta: SourceMetaType?,
val source: SourceType?,
)

fun deleteSourceMeta(input: DeleteSourceMetaInput): DeleteSourceMetaPayload {
val (clientMutationId, sourceId, key) = input

val (meta, source) =
transaction {
val meta =
SourceMetaTable.select { (SourceMetaTable.ref eq sourceId) and (SourceMetaTable.key eq key) }
.firstOrNull()

SourceMetaTable.deleteWhere { (SourceMetaTable.ref eq sourceId) and (SourceMetaTable.key eq key) }

val source =
transaction {
SourceTable.select { SourceTable.id eq sourceId }.firstOrNull()
?.let { SourceType(it) }
}

if (meta != null) {
SourceMetaType(meta)
} else {
null
} to source
}

return DeleteSourceMetaPayload(clientMutationId, meta, source)
}

enum class FetchSourceMangaType {
SEARCH,
POPULAR,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import suwayomi.tachidesk.graphql.dataLoaders.MangaForIdsDataLoader
import suwayomi.tachidesk.graphql.dataLoaders.MangaForSourceDataLoader
import suwayomi.tachidesk.graphql.dataLoaders.MangaMetaDataLoader
import suwayomi.tachidesk.graphql.dataLoaders.SourceDataLoader
import suwayomi.tachidesk.graphql.dataLoaders.SourceMetaDataLoader
import suwayomi.tachidesk.graphql.dataLoaders.SourcesForExtensionDataLoader
import suwayomi.tachidesk.graphql.dataLoaders.TrackRecordDataLoader
import suwayomi.tachidesk.graphql.dataLoaders.TrackRecordsForMangaIdDataLoader
Expand Down Expand Up @@ -64,6 +65,7 @@ class TachideskDataLoaderRegistryFactory {
CategoriesForMangaDataLoader(),
SourceDataLoader(),
SourcesForExtensionDataLoader(),
SourceMetaDataLoader(),
ExtensionDataLoader(),
ExtensionForSourceDataLoader(),
TrackerDataLoader(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import suwayomi.tachidesk.graphql.server.primitives.PageInfo
import suwayomi.tachidesk.manga.model.table.CategoryMetaTable
import suwayomi.tachidesk.manga.model.table.ChapterMetaTable
import suwayomi.tachidesk.manga.model.table.MangaMetaTable
import suwayomi.tachidesk.manga.model.table.SourceMetaTable
import java.util.concurrent.CompletableFuture

interface MetaType : Node {
Expand Down Expand Up @@ -67,6 +68,22 @@ class CategoryMetaType(
}
}

class SourceMetaType(
override val key: String,
override val value: String,
val sourceId: Long,
) : MetaType {
constructor(row: ResultRow) : this(
key = row[SourceMetaTable.key],
value = row[SourceMetaTable.value],
sourceId = row[SourceMetaTable.ref],
)

fun source(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<SourceType> {
return dataFetchingEnvironment.getValueFromDataLoader<Long, SourceType>("SourceDataLoader", sourceId)
}
}

class GlobalMetaType(
override val key: String,
override val value: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ class SourceType(
fun filters(): List<Filter> {
return getCatalogueSourceOrStub(id).getFilterList().map { filterOf(it) }
}

fun meta(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<List<SourceMetaType>> {
return dataFetchingEnvironment.getValueFromDataLoader<Long, List<SourceMetaType>>("SourceMetaDataLoader", id)
}
}

@Suppress("ktlint:standard:function-naming")
Expand Down
29 changes: 29 additions & 0 deletions server/src/main/kotlin/suwayomi/tachidesk/manga/impl/Source.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.sourcePreferences
import io.javalin.plugin.json.JsonMapper
import mu.KotlinLogging
import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update
import org.kodein.di.DI
import org.kodein.di.conf.global
import org.kodein.di.instance
Expand All @@ -25,6 +28,7 @@ import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.getCatalogue
import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource.unregisterCatalogueSource
import suwayomi.tachidesk.manga.model.dataclass.SourceDataClass
import suwayomi.tachidesk.manga.model.table.ExtensionTable
import suwayomi.tachidesk.manga.model.table.SourceMetaTable
import suwayomi.tachidesk.manga.model.table.SourceTable
import uy.kohesive.injekt.api.get
import xyz.nulldev.androidcompat.androidimpl.CustomContext
Expand Down Expand Up @@ -150,4 +154,29 @@ object Source {
// must reload the source because a preference was changed
unregisterCatalogueSource(sourceId)
}

fun modifyMeta(
sourceId: Long,
key: String,
value: String,
) {
transaction {
val meta =
transaction {
SourceMetaTable.select { (SourceMetaTable.ref eq sourceId) and (SourceMetaTable.key eq key) }
}.firstOrNull()

if (meta == null) {
SourceMetaTable.insert {
it[SourceMetaTable.key] = key
it[SourceMetaTable.value] = value
it[SourceMetaTable.ref] = sourceId
}
} else {
SourceMetaTable.update({ (SourceMetaTable.ref eq sourceId) and (SourceMetaTable.key eq key) }) {
it[SourceMetaTable.value] = value
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package suwayomi.tachidesk.manga.model.table

/*
* 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/. */

import org.jetbrains.exposed.dao.id.IntIdTable
import suwayomi.tachidesk.manga.model.table.ChapterMetaTable.ref

/**
* Metadata storage for clients, about Source with id == [ref].
*/
object SourceMetaTable : IntIdTable() {
val key = varchar("key", 256)
val value = varchar("value", 4096)
val ref = long("source_ref")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package suwayomi.tachidesk.server.database.migration

/*
* 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/. */

import de.neonew.exposed.migrations.helpers.AddTableMigration
import org.jetbrains.exposed.dao.id.IntIdTable
import org.jetbrains.exposed.sql.Table

@Suppress("ClassName", "unused")
class M0036_SourceMeta : AddTableMigration() {
private class SourceMetaTable : IntIdTable() {
val key = varchar("key", 256)
val value = varchar("value", 4096)
val ref = long("source_ref")
}

override val tables: Array<Table>
get() =
arrayOf(
SourceMetaTable(),
)
}

0 comments on commit af0dde5

Please sign in to comment.