Compare commits

...

7 Commits

Author SHA1 Message Date
Syer10
e4440ad502 Lint 2026-06-27 13:03:53 -04:00
Syer10
e71c94547d Add a index to extesnion table store url 2026-06-27 12:59:16 -04:00
Syer10
84a1789850 Review fixes 2026-06-27 12:44:51 -04:00
Syer10
70a027f6f0 Lint 2026-06-26 11:13:55 -04:00
Syer10
650c075723 Optimize imports 2026-06-26 11:09:39 -04:00
Syer10
a69e29d1a5 Lint 2026-06-26 11:07:08 -04:00
Syer10
eec0951a75 Fix latest Mihon Extension Lib 2026-06-26 11:03:33 -04:00
13 changed files with 32 additions and 45 deletions

View File

@@ -21,7 +21,6 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import okhttp3.Cache import okhttp3.Cache
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.brotli.BrotliInterceptor
import okhttp3.logging.HttpLoggingInterceptor import okhttp3.logging.HttpLoggingInterceptor
import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource
import java.net.CookieHandler import java.net.CookieHandler

View File

@@ -21,26 +21,6 @@ class ExtensionStoreDataLoader : KotlinDataLoader<String, ExtensionStoreType> {
override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader<String, ExtensionStoreType> = override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader<String, ExtensionStoreType> =
DataLoaderFactory.newDataLoader { ids -> DataLoaderFactory.newDataLoader { ids ->
future {
transaction {
addLogger(Slf4jSqlDebugLogger)
val manga =
ExtensionStoreTable
.selectAll()
.where { ExtensionStoreTable.indexUrl inList ids }
.map { ExtensionStoreType(it) }
.associateBy { it.indexUrl }
ids.map { manga[it] }
}
}
}
}
class ExtensionStoreForExtension : KotlinDataLoader<String, ExtensionStoreType> {
override val dataLoaderName = "ExtensionStoreForExtension"
override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader<String, ExtensionStoreType> =
DataLoaderFactory.newDataLoader<String, ExtensionStoreType> { ids ->
future { future {
transaction { transaction {
addLogger(Slf4jSqlDebugLogger) addLogger(Slf4jSqlDebugLogger)
@@ -50,14 +30,14 @@ class ExtensionStoreForExtension : KotlinDataLoader<String, ExtensionStoreType>
.where { ExtensionStoreTable.indexUrl inList ids } .where { ExtensionStoreTable.indexUrl inList ids }
.map { ExtensionStoreType(it) } .map { ExtensionStoreType(it) }
.associateBy { it.indexUrl } .associateBy { it.indexUrl }
ids.map { (extensionStoreByIndexUrl[it]) } ids.map { extensionStoreByIndexUrl[it] }
} }
} }
} }
} }
class ExtensionForExtensionStore : KotlinDataLoader<String, ExtensionNodeList> { class ExtensionsForExtensionStore : KotlinDataLoader<String, ExtensionNodeList> {
override val dataLoaderName = "ExtensionForExtensionStore" override val dataLoaderName = "ExtensionsForExtensionStore"
override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader<String, ExtensionNodeList> = override fun getDataLoader(graphQLContext: GraphQLContext): DataLoader<String, ExtensionNodeList> =
DataLoaderFactory.newDataLoader<String, ExtensionNodeList> { ids -> DataLoaderFactory.newDataLoader<String, ExtensionNodeList> { ids ->

View File

@@ -17,7 +17,6 @@ import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.core.greater import org.jetbrains.exposed.v1.core.greater
import org.jetbrains.exposed.v1.core.greaterEq import org.jetbrains.exposed.v1.core.greaterEq
import org.jetbrains.exposed.v1.core.less import org.jetbrains.exposed.v1.core.less
import org.jetbrains.exposed.v1.core.neq
import org.jetbrains.exposed.v1.jdbc.selectAll import org.jetbrains.exposed.v1.jdbc.selectAll
import org.jetbrains.exposed.v1.jdbc.transactions.transaction import org.jetbrains.exposed.v1.jdbc.transactions.transaction
import suwayomi.tachidesk.graphql.directives.RequireAuth import suwayomi.tachidesk.graphql.directives.RequireAuth

View File

@@ -20,10 +20,9 @@ import suwayomi.tachidesk.graphql.dataLoaders.DisplayScoreForTrackRecordDataLoad
import suwayomi.tachidesk.graphql.dataLoaders.DisplayScoreForTrackSearchDataLoader import suwayomi.tachidesk.graphql.dataLoaders.DisplayScoreForTrackSearchDataLoader
import suwayomi.tachidesk.graphql.dataLoaders.DownloadedChapterCountForMangaDataLoader import suwayomi.tachidesk.graphql.dataLoaders.DownloadedChapterCountForMangaDataLoader
import suwayomi.tachidesk.graphql.dataLoaders.ExtensionDataLoader import suwayomi.tachidesk.graphql.dataLoaders.ExtensionDataLoader
import suwayomi.tachidesk.graphql.dataLoaders.ExtensionForExtensionStore
import suwayomi.tachidesk.graphql.dataLoaders.ExtensionForSourceDataLoader import suwayomi.tachidesk.graphql.dataLoaders.ExtensionForSourceDataLoader
import suwayomi.tachidesk.graphql.dataLoaders.ExtensionStoreDataLoader import suwayomi.tachidesk.graphql.dataLoaders.ExtensionStoreDataLoader
import suwayomi.tachidesk.graphql.dataLoaders.ExtensionStoreForExtension import suwayomi.tachidesk.graphql.dataLoaders.ExtensionsForExtensionStore
import suwayomi.tachidesk.graphql.dataLoaders.FirstUnreadChapterForMangaDataLoader import suwayomi.tachidesk.graphql.dataLoaders.FirstUnreadChapterForMangaDataLoader
import suwayomi.tachidesk.graphql.dataLoaders.GlobalMetaDataLoader import suwayomi.tachidesk.graphql.dataLoaders.GlobalMetaDataLoader
import suwayomi.tachidesk.graphql.dataLoaders.HasDuplicateChaptersForMangaDataLoader import suwayomi.tachidesk.graphql.dataLoaders.HasDuplicateChaptersForMangaDataLoader
@@ -81,9 +80,8 @@ class TachideskDataLoaderRegistryFactory {
SourceMetaDataLoader(), SourceMetaDataLoader(),
ExtensionDataLoader(), ExtensionDataLoader(),
ExtensionForSourceDataLoader(), ExtensionForSourceDataLoader(),
ExtensionForExtensionStore(), ExtensionsForExtensionStore(),
ExtensionStoreDataLoader(), ExtensionStoreDataLoader(),
ExtensionStoreForExtension(),
TrackerDataLoader(), TrackerDataLoader(),
TrackerStatusesDataLoader(), TrackerStatusesDataLoader(),
TrackerScoresDataLoader(), TrackerScoresDataLoader(),

View File

@@ -40,7 +40,7 @@ class ExtensionStoreType(
) )
fun extensions(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<ExtensionNodeList> = fun extensions(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<ExtensionNodeList> =
dataFetchingEnvironment.getValueFromDataLoader<String, ExtensionNodeList>("ExtensionForExtensionStore", indexUrl) dataFetchingEnvironment.getValueFromDataLoader<String, ExtensionNodeList>("ExtensionsForExtensionStore", indexUrl)
} }
data class ExtensionStoreNodeList( data class ExtensionStoreNodeList(

View File

@@ -72,7 +72,7 @@ class ExtensionType(
dataFetchingEnvironment.getValueFromDataLoader<String, SourceNodeList>("SourcesForExtensionDataLoader", pkgName) dataFetchingEnvironment.getValueFromDataLoader<String, SourceNodeList>("SourcesForExtensionDataLoader", pkgName)
fun extensionStore(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<ExtensionStoreType> = fun extensionStore(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<ExtensionStoreType> =
dataFetchingEnvironment.getValueFromDataLoader<String, ExtensionStoreType>("ExtensionStoreForExtension", storeIndexUrl.orEmpty()) dataFetchingEnvironment.getValueFromDataLoader<String, ExtensionStoreType>("ExtensionStoreDataLoader", storeIndexUrl.orEmpty())
} }
data class ExtensionNodeList( data class ExtensionNodeList(

View File

@@ -45,7 +45,6 @@ import suwayomi.tachidesk.manga.impl.util.source.GetCatalogueSource
import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse.clearCachedImage import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse.clearCachedImage
import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse.getImageResponse import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse.getImageResponse
import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse.saveImage import suwayomi.tachidesk.manga.impl.util.storage.ImageResponse.saveImage
import suwayomi.tachidesk.manga.model.dataclass.ContentWarning
import suwayomi.tachidesk.manga.model.table.ExtensionTable import suwayomi.tachidesk.manga.model.table.ExtensionTable
import suwayomi.tachidesk.manga.model.table.SourceTable import suwayomi.tachidesk.manga.model.table.SourceTable
import suwayomi.tachidesk.server.ApplicationDirs import suwayomi.tachidesk.server.ApplicationDirs

View File

@@ -45,7 +45,8 @@ data class NetworkExtensionStore(
@ProtoNumber(4) val extensionLib: String, @ProtoNumber(4) val extensionLib: String,
@ProtoNumber(5) val versionCode: Long, @ProtoNumber(5) val versionCode: Long,
@ProtoNumber(6) val versionName: String, @ProtoNumber(6) val versionName: String,
@ProtoNumber(7) val sources: List<Source>, @ProtoNumber(7) val contentWarning: ContentWarning,
@ProtoNumber(8) val sources: List<Source>,
) )
@Serializable @Serializable
@@ -61,21 +62,25 @@ data class NetworkExtensionStore(
@ProtoNumber(3) val language: String, @ProtoNumber(3) val language: String,
@ProtoNumber(4) val homeUrl: String = "", @ProtoNumber(4) val homeUrl: String = "",
@ProtoNumber(5) val mirrorUrls: List<String> = emptyList(), @ProtoNumber(5) val mirrorUrls: List<String> = emptyList(),
@ProtoNumber(6) val contentWarning: ContentWarning = ContentWarning.SAFE, // @ProtoNumber(6) val contentWarning: ContentWarning = ContentWarning.SAFE,
@ProtoNumber(7) val message: String? = null, @ProtoNumber(7) val message: String? = null,
) )
@Serializable @Serializable
enum class ContentWarning { enum class ContentWarning {
@ProtoNumber(0) @ProtoNumber(0)
@JsonNames("CONTENT_WARNING_UNSPECIFIED")
UNSPECIFIED,
@ProtoNumber(1)
@JsonNames("CONTENT_WARNING_SAFE") @JsonNames("CONTENT_WARNING_SAFE")
SAFE, SAFE,
@ProtoNumber(1) @ProtoNumber(2)
@JsonNames("CONTENT_WARNING_MIXED") @JsonNames("CONTENT_WARNING_MIXED")
MIXED, MIXED,
@ProtoNumber(2) @ProtoNumber(3)
@JsonNames("CONTENT_WARNING_NSFW") @JsonNames("CONTENT_WARNING_NSFW")
NSFW, NSFW,
} }
@@ -110,11 +115,14 @@ fun NetworkExtensionStore.ExtensionList.toExtensionInfos(store: ExtensionStore):
versionName = extension.versionName, versionName = extension.versionName,
lang = if (lang.size == 1) lang.first() else "all", lang = if (lang.size == 1) lang.first() else "all",
contentWarning = contentWarning =
when (extension.sources.maxOfOrNull { it.contentWarning }) { when (extension.contentWarning) {
NetworkExtensionStore.ContentWarning.SAFE -> ContentWarning.SAFE NetworkExtensionStore.ContentWarning.SAFE,
NetworkExtensionStore.ContentWarning.UNSPECIFIED,
-> ContentWarning.SAFE
NetworkExtensionStore.ContentWarning.MIXED -> ContentWarning.MIXED NetworkExtensionStore.ContentWarning.MIXED -> ContentWarning.MIXED
NetworkExtensionStore.ContentWarning.NSFW -> ContentWarning.NSFW NetworkExtensionStore.ContentWarning.NSFW -> ContentWarning.NSFW
null -> ContentWarning.SAFE
}, },
sources = sources =
extension.sources.map { source -> extension.sources.map { source ->
@@ -125,9 +133,13 @@ fun NetworkExtensionStore.ExtensionList.toExtensionInfos(store: ExtensionStore):
homeUrl = source.homeUrl, homeUrl = source.homeUrl,
message = source.message, message = source.message,
contentWarning = contentWarning =
when (source.contentWarning) { when (extension.contentWarning) { // todo source.contentWarning
NetworkExtensionStore.ContentWarning.SAFE -> ContentWarning.SAFE NetworkExtensionStore.ContentWarning.SAFE,
NetworkExtensionStore.ContentWarning.UNSPECIFIED,
-> ContentWarning.SAFE
NetworkExtensionStore.ContentWarning.MIXED -> ContentWarning.MIXED NetworkExtensionStore.ContentWarning.MIXED -> ContentWarning.MIXED
NetworkExtensionStore.ContentWarning.NSFW -> ContentWarning.NSFW NetworkExtensionStore.ContentWarning.NSFW -> ContentWarning.NSFW
}, },
) )

View File

@@ -10,7 +10,7 @@ package suwayomi.tachidesk.manga.model.table
import org.jetbrains.exposed.v1.core.dao.id.IntIdTable import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
object ExtensionStoreTable : IntIdTable() { object ExtensionStoreTable : IntIdTable() {
val indexUrl = varchar("index_url", 2048) val indexUrl = varchar("index_url", 2048).uniqueIndex()
val name = varchar("name", 256) val name = varchar("name", 256)
val badgeLabel = varchar("badge_label", 32) val badgeLabel = varchar("badge_label", 32)
val signingKey = varchar("signing_key", 512) val signingKey = varchar("signing_key", 512)

View File

@@ -11,7 +11,7 @@ import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
object ExtensionTable : IntIdTable() { object ExtensionTable : IntIdTable() {
val apkName = varchar("apk_name", 1024).nullable() val apkName = varchar("apk_name", 1024).nullable()
val storeIndexUrl = varchar("store_index_url", 2048).nullable() val storeIndexUrl = varchar("store_index_url", 2048).nullable().index()
// default is the local source icon from tachiyomi // default is the local source icon from tachiyomi
@Suppress("ktlint:standard:max-line-length") @Suppress("ktlint:standard:max-line-length")

View File

@@ -9,7 +9,6 @@ import org.jetbrains.exposed.v1.core.SortOrder
import org.jetbrains.exposed.v1.core.alias import org.jetbrains.exposed.v1.core.alias
import org.jetbrains.exposed.v1.core.and import org.jetbrains.exposed.v1.core.and
import org.jetbrains.exposed.v1.core.eq import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.core.greater
import org.jetbrains.exposed.v1.core.inList import org.jetbrains.exposed.v1.core.inList
import org.jetbrains.exposed.v1.core.inSubQuery import org.jetbrains.exposed.v1.core.inSubQuery
import org.jetbrains.exposed.v1.core.intLiteral import org.jetbrains.exposed.v1.core.intLiteral

View File

@@ -34,6 +34,7 @@ class M0057_AddNewExtensionApiFields : SQLMigration() {
} }
} }
ALTER TABLE EXTENSION ALTER COLUMN store_index_url ${MAYBE_TYPE_PREFIX}VARCHAR(2048); ALTER TABLE EXTENSION ALTER COLUMN store_index_url ${MAYBE_TYPE_PREFIX}VARCHAR(2048);
CREATE INDEX extension_store_index_url ON EXTENSION (store_index_url);
ALTER TABLE EXTENSION ALTER COLUMN version_code ${MAYBE_TYPE_PREFIX}BIGINT; ALTER TABLE EXTENSION ALTER COLUMN version_code ${MAYBE_TYPE_PREFIX}BIGINT;
ALTER TABLE EXTENSION ALTER COLUMN apk_name DROP NOT NULL; ALTER TABLE EXTENSION ALTER COLUMN apk_name DROP NOT NULL;
${ ${

View File

@@ -14,7 +14,7 @@ import org.jetbrains.exposed.v1.core.dao.id.IntIdTable
@Suppress("ClassName", "unused") @Suppress("ClassName", "unused")
class M0058_AddExtensionStore : AddTableMigration() { class M0058_AddExtensionStore : AddTableMigration() {
private class ExtensionStoreTable : IntIdTable() { private class ExtensionStoreTable : IntIdTable() {
val indexUrl = varchar("index_url", 2048) val indexUrl = varchar("index_url", 2048).uniqueIndex()
val name = varchar("name", 256) val name = varchar("name", 256)
val badgeLabel = varchar("badge_label", 32) val badgeLabel = varchar("badge_label", 32)
val signingKey = varchar("signing_key", 512) val signingKey = varchar("signing_key", 512)