mirror of
https://github.com/Suwayomi/Tachidesk.git
synced 2025-12-10 06:42:07 +01:00
Library Update Queries and Mutations (#609)
* Add library update GraphQL endpoints * No need for data classes * UpdateLibraryManga
This commit is contained in:
@@ -80,3 +80,20 @@ class MangaForSourceDataLoader : KotlinDataLoader<Long, MangaNodeList> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class MangaForIdsDataLoader : KotlinDataLoader<List<Int>, MangaNodeList> {
|
||||||
|
override val dataLoaderName = "MangaForIdsDataLoader"
|
||||||
|
override fun getDataLoader(): DataLoader<List<Int>, MangaNodeList> = DataLoaderFactory.newDataLoader { mangaIds ->
|
||||||
|
future {
|
||||||
|
transaction {
|
||||||
|
addLogger(Slf4jSqlDebugLogger)
|
||||||
|
val ids = mangaIds.flatten().distinct()
|
||||||
|
val manga = MangaTable.select { MangaTable.id inList ids }
|
||||||
|
.map { MangaType(it) }
|
||||||
|
mangaIds.map { mangaIds ->
|
||||||
|
manga.filter { it.id in mangaIds }.toNodeList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
package suwayomi.tachidesk.graphql.mutations
|
||||||
|
|
||||||
|
import org.jetbrains.exposed.sql.select
|
||||||
|
import org.jetbrains.exposed.sql.transactions.transaction
|
||||||
|
import org.kodein.di.DI
|
||||||
|
import org.kodein.di.conf.global
|
||||||
|
import org.kodein.di.instance
|
||||||
|
import suwayomi.tachidesk.graphql.types.UpdateStatus
|
||||||
|
import suwayomi.tachidesk.manga.impl.Category
|
||||||
|
import suwayomi.tachidesk.manga.impl.update.IUpdater
|
||||||
|
import suwayomi.tachidesk.manga.model.table.CategoryTable
|
||||||
|
import suwayomi.tachidesk.manga.model.table.toDataClass
|
||||||
|
|
||||||
|
class UpdateMutation {
|
||||||
|
private val updater by DI.global.instance<IUpdater>()
|
||||||
|
|
||||||
|
data class UpdateLibraryMangaInput(
|
||||||
|
val clientMutationId: String? = null
|
||||||
|
)
|
||||||
|
data class UpdateLibraryMangaPayload(
|
||||||
|
val clientMutationId: String?,
|
||||||
|
val updateStatus: UpdateStatus
|
||||||
|
)
|
||||||
|
|
||||||
|
fun updateLibraryManga(input: UpdateLibraryMangaInput): UpdateLibraryMangaPayload {
|
||||||
|
updater.addCategoriesToUpdateQueue(
|
||||||
|
Category.getCategoryList(),
|
||||||
|
clear = true,
|
||||||
|
forceAll = false
|
||||||
|
)
|
||||||
|
|
||||||
|
return UpdateLibraryMangaPayload(input.clientMutationId, UpdateStatus(updater.status.value))
|
||||||
|
}
|
||||||
|
|
||||||
|
data class UpdateCategoryMangaInput(
|
||||||
|
val clientMutationId: String? = null,
|
||||||
|
val categories: List<Int>
|
||||||
|
)
|
||||||
|
data class UpdateCategoryMangaPayload(
|
||||||
|
val clientMutationId: String?,
|
||||||
|
val updateStatus: UpdateStatus
|
||||||
|
)
|
||||||
|
|
||||||
|
fun updateCategoryManga(input: UpdateCategoryMangaInput): UpdateCategoryMangaPayload {
|
||||||
|
val categories = transaction {
|
||||||
|
CategoryTable.select { CategoryTable.id inList input.categories }.map {
|
||||||
|
CategoryTable.toDataClass(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updater.addCategoriesToUpdateQueue(categories, clear = true, forceAll = true)
|
||||||
|
|
||||||
|
return UpdateCategoryMangaPayload(
|
||||||
|
clientMutationId = input.clientMutationId,
|
||||||
|
updateStatus = UpdateStatus(updater.status.value)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
data class UpdateStopInput(
|
||||||
|
val clientMutationId: String? = null
|
||||||
|
)
|
||||||
|
data class UpdateStopPayload(
|
||||||
|
val clientMutationId: String?
|
||||||
|
)
|
||||||
|
|
||||||
|
fun updateStop(input: UpdateStopInput): UpdateStopPayload {
|
||||||
|
updater.reset()
|
||||||
|
return UpdateStopPayload(input.clientMutationId)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package suwayomi.tachidesk.graphql.queries
|
||||||
|
|
||||||
|
import org.kodein.di.DI
|
||||||
|
import org.kodein.di.conf.global
|
||||||
|
import org.kodein.di.instance
|
||||||
|
import suwayomi.tachidesk.graphql.types.UpdateStatus
|
||||||
|
import suwayomi.tachidesk.graphql.types.UpdateStatusType
|
||||||
|
import suwayomi.tachidesk.manga.impl.update.IUpdater
|
||||||
|
import suwayomi.tachidesk.manga.impl.update.JobStatus
|
||||||
|
|
||||||
|
class UpdateQuery {
|
||||||
|
private val updater by DI.global.instance<IUpdater>()
|
||||||
|
|
||||||
|
fun updateStatus(): UpdateStatus {
|
||||||
|
val status = updater.status.value
|
||||||
|
return UpdateStatus(
|
||||||
|
isRunning = status.running,
|
||||||
|
pendingJobs = UpdateStatusType(status.statusMap[JobStatus.PENDING]?.map { it.id }.orEmpty()),
|
||||||
|
runningJobs = UpdateStatusType(status.statusMap[JobStatus.RUNNING]?.map { it.id }.orEmpty()),
|
||||||
|
completeJobs = UpdateStatusType(status.statusMap[JobStatus.COMPLETE]?.map { it.id }.orEmpty()),
|
||||||
|
failedJobs = UpdateStatusType(status.statusMap[JobStatus.FAILED]?.map { it.id }.orEmpty())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
package suwayomi.tachidesk.graphql.queries
|
|
||||||
|
|
||||||
import org.jetbrains.exposed.sql.select
|
|
||||||
import org.jetbrains.exposed.sql.transactions.transaction
|
|
||||||
import org.kodein.di.DI
|
|
||||||
import org.kodein.di.conf.global
|
|
||||||
import org.kodein.di.instance
|
|
||||||
import suwayomi.tachidesk.graphql.types.MangaType
|
|
||||||
import suwayomi.tachidesk.manga.impl.update.IUpdater
|
|
||||||
import suwayomi.tachidesk.manga.impl.update.JobStatus
|
|
||||||
import suwayomi.tachidesk.manga.impl.update.UpdaterSocket
|
|
||||||
import suwayomi.tachidesk.manga.model.table.MangaTable
|
|
||||||
|
|
||||||
class UpdaterQuery {
|
|
||||||
sealed interface UpdaterStatus {
|
|
||||||
data class UpdaterJob(val status: JobStatus, val manga: MangaType)
|
|
||||||
|
|
||||||
data class Running(val jobs: Map<JobStatus, List<MangaType>>) : UpdaterStatus
|
|
||||||
|
|
||||||
// data class Idle
|
|
||||||
}
|
|
||||||
|
|
||||||
private val updater by DI.global.instance<IUpdater>()
|
|
||||||
|
|
||||||
fun updaterStatus() {
|
|
||||||
val status = updater.status.value
|
|
||||||
if (status.running) {
|
|
||||||
val mangaIds = status.statusMap.values.flatMap { mangas -> mangas.map { it.id } }
|
|
||||||
val mangaMap = transaction {
|
|
||||||
MangaTable.select { MangaTable.id inList mangaIds }
|
|
||||||
.map { MangaType(it) }
|
|
||||||
.associateBy { it.id }
|
|
||||||
}
|
|
||||||
UpdaterStatus.Running(
|
|
||||||
status.statusMap.mapValues { (_, mangas) ->
|
|
||||||
mangas.mapNotNull { mangaMap[it.id] }
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
UpdaterSocket
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -19,6 +19,7 @@ import suwayomi.tachidesk.graphql.dataLoaders.ExtensionForSourceDataLoader
|
|||||||
import suwayomi.tachidesk.graphql.dataLoaders.GlobalMetaDataLoader
|
import suwayomi.tachidesk.graphql.dataLoaders.GlobalMetaDataLoader
|
||||||
import suwayomi.tachidesk.graphql.dataLoaders.MangaDataLoader
|
import suwayomi.tachidesk.graphql.dataLoaders.MangaDataLoader
|
||||||
import suwayomi.tachidesk.graphql.dataLoaders.MangaForCategoryDataLoader
|
import suwayomi.tachidesk.graphql.dataLoaders.MangaForCategoryDataLoader
|
||||||
|
import suwayomi.tachidesk.graphql.dataLoaders.MangaForIdsDataLoader
|
||||||
import suwayomi.tachidesk.graphql.dataLoaders.MangaForSourceDataLoader
|
import suwayomi.tachidesk.graphql.dataLoaders.MangaForSourceDataLoader
|
||||||
import suwayomi.tachidesk.graphql.dataLoaders.MangaMetaDataLoader
|
import suwayomi.tachidesk.graphql.dataLoaders.MangaMetaDataLoader
|
||||||
import suwayomi.tachidesk.graphql.dataLoaders.SourceDataLoader
|
import suwayomi.tachidesk.graphql.dataLoaders.SourceDataLoader
|
||||||
@@ -36,6 +37,7 @@ class TachideskDataLoaderRegistryFactory {
|
|||||||
MangaMetaDataLoader(),
|
MangaMetaDataLoader(),
|
||||||
MangaForCategoryDataLoader(),
|
MangaForCategoryDataLoader(),
|
||||||
MangaForSourceDataLoader(),
|
MangaForSourceDataLoader(),
|
||||||
|
MangaForIdsDataLoader(),
|
||||||
CategoryDataLoader(),
|
CategoryDataLoader(),
|
||||||
CategoryMetaDataLoader(),
|
CategoryMetaDataLoader(),
|
||||||
CategoriesForMangaDataLoader(),
|
CategoriesForMangaDataLoader(),
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import suwayomi.tachidesk.graphql.mutations.ExtensionMutation
|
|||||||
import suwayomi.tachidesk.graphql.mutations.MangaMutation
|
import suwayomi.tachidesk.graphql.mutations.MangaMutation
|
||||||
import suwayomi.tachidesk.graphql.mutations.MetaMutation
|
import suwayomi.tachidesk.graphql.mutations.MetaMutation
|
||||||
import suwayomi.tachidesk.graphql.mutations.SourceMutation
|
import suwayomi.tachidesk.graphql.mutations.SourceMutation
|
||||||
|
import suwayomi.tachidesk.graphql.mutations.UpdateMutation
|
||||||
import suwayomi.tachidesk.graphql.queries.BackupQuery
|
import suwayomi.tachidesk.graphql.queries.BackupQuery
|
||||||
import suwayomi.tachidesk.graphql.queries.CategoryQuery
|
import suwayomi.tachidesk.graphql.queries.CategoryQuery
|
||||||
import suwayomi.tachidesk.graphql.queries.ChapterQuery
|
import suwayomi.tachidesk.graphql.queries.ChapterQuery
|
||||||
@@ -27,11 +28,13 @@ import suwayomi.tachidesk.graphql.queries.ExtensionQuery
|
|||||||
import suwayomi.tachidesk.graphql.queries.MangaQuery
|
import suwayomi.tachidesk.graphql.queries.MangaQuery
|
||||||
import suwayomi.tachidesk.graphql.queries.MetaQuery
|
import suwayomi.tachidesk.graphql.queries.MetaQuery
|
||||||
import suwayomi.tachidesk.graphql.queries.SourceQuery
|
import suwayomi.tachidesk.graphql.queries.SourceQuery
|
||||||
|
import suwayomi.tachidesk.graphql.queries.UpdateQuery
|
||||||
import suwayomi.tachidesk.graphql.server.primitives.Cursor
|
import suwayomi.tachidesk.graphql.server.primitives.Cursor
|
||||||
import suwayomi.tachidesk.graphql.server.primitives.GraphQLCursor
|
import suwayomi.tachidesk.graphql.server.primitives.GraphQLCursor
|
||||||
import suwayomi.tachidesk.graphql.server.primitives.GraphQLLongAsString
|
import suwayomi.tachidesk.graphql.server.primitives.GraphQLLongAsString
|
||||||
import suwayomi.tachidesk.graphql.server.primitives.GraphQLUpload
|
import suwayomi.tachidesk.graphql.server.primitives.GraphQLUpload
|
||||||
import suwayomi.tachidesk.graphql.subscriptions.DownloadSubscription
|
import suwayomi.tachidesk.graphql.subscriptions.DownloadSubscription
|
||||||
|
import suwayomi.tachidesk.graphql.subscriptions.UpdateSubscription
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KType
|
import kotlin.reflect.KType
|
||||||
|
|
||||||
@@ -57,7 +60,8 @@ val schema = toSchema(
|
|||||||
TopLevelObject(ExtensionQuery()),
|
TopLevelObject(ExtensionQuery()),
|
||||||
TopLevelObject(MangaQuery()),
|
TopLevelObject(MangaQuery()),
|
||||||
TopLevelObject(MetaQuery()),
|
TopLevelObject(MetaQuery()),
|
||||||
TopLevelObject(SourceQuery())
|
TopLevelObject(SourceQuery()),
|
||||||
|
TopLevelObject(UpdateQuery())
|
||||||
),
|
),
|
||||||
mutations = listOf(
|
mutations = listOf(
|
||||||
TopLevelObject(BackupMutation()),
|
TopLevelObject(BackupMutation()),
|
||||||
@@ -66,9 +70,11 @@ val schema = toSchema(
|
|||||||
TopLevelObject(ExtensionMutation()),
|
TopLevelObject(ExtensionMutation()),
|
||||||
TopLevelObject(MangaMutation()),
|
TopLevelObject(MangaMutation()),
|
||||||
TopLevelObject(MetaMutation()),
|
TopLevelObject(MetaMutation()),
|
||||||
TopLevelObject(SourceMutation())
|
TopLevelObject(SourceMutation()),
|
||||||
|
TopLevelObject(UpdateMutation())
|
||||||
),
|
),
|
||||||
subscriptions = listOf(
|
subscriptions = listOf(
|
||||||
TopLevelObject(DownloadSubscription())
|
TopLevelObject(DownloadSubscription()),
|
||||||
|
TopLevelObject(UpdateSubscription())
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* 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.subscriptions
|
||||||
|
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import org.kodein.di.DI
|
||||||
|
import org.kodein.di.conf.global
|
||||||
|
import org.kodein.di.instance
|
||||||
|
import suwayomi.tachidesk.graphql.types.UpdateStatus
|
||||||
|
import suwayomi.tachidesk.manga.impl.update.IUpdater
|
||||||
|
|
||||||
|
class UpdateSubscription {
|
||||||
|
private val updater by DI.global.instance<IUpdater>()
|
||||||
|
|
||||||
|
fun updateStatusChanged(): Flow<UpdateStatus> {
|
||||||
|
return updater.status.map { updateStatus ->
|
||||||
|
UpdateStatus(updateStatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
package suwayomi.tachidesk.graphql.types
|
||||||
|
|
||||||
|
import com.expediagroup.graphql.generator.annotations.GraphQLIgnore
|
||||||
|
import com.expediagroup.graphql.server.extensions.getValueFromDataLoader
|
||||||
|
import graphql.schema.DataFetchingEnvironment
|
||||||
|
import suwayomi.tachidesk.manga.impl.update.JobStatus
|
||||||
|
import suwayomi.tachidesk.manga.impl.update.UpdateStatus
|
||||||
|
import java.util.concurrent.CompletableFuture
|
||||||
|
|
||||||
|
class UpdateStatus(
|
||||||
|
val isRunning: Boolean,
|
||||||
|
val pendingJobs: UpdateStatusType,
|
||||||
|
val runningJobs: UpdateStatusType,
|
||||||
|
val completeJobs: UpdateStatusType,
|
||||||
|
val failedJobs: UpdateStatusType
|
||||||
|
) {
|
||||||
|
constructor(status: UpdateStatus) : this(
|
||||||
|
isRunning = status.running,
|
||||||
|
pendingJobs = UpdateStatusType(status.statusMap[JobStatus.PENDING]?.map { it.id }.orEmpty()),
|
||||||
|
runningJobs = UpdateStatusType(status.statusMap[JobStatus.RUNNING]?.map { it.id }.orEmpty()),
|
||||||
|
completeJobs = UpdateStatusType(status.statusMap[JobStatus.COMPLETE]?.map { it.id }.orEmpty()),
|
||||||
|
failedJobs = UpdateStatusType(status.statusMap[JobStatus.FAILED]?.map { it.id }.orEmpty())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
class UpdateStatusType(
|
||||||
|
@get:GraphQLIgnore
|
||||||
|
val mangaIds: List<Int>
|
||||||
|
) {
|
||||||
|
fun mangas(dataFetchingEnvironment: DataFetchingEnvironment): CompletableFuture<MangaNodeList> {
|
||||||
|
return dataFetchingEnvironment.getValueFromDataLoader<List<Int>, MangaNodeList>("MangaForIdsDataLoader", mangaIds)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -68,11 +68,19 @@ object UpdateController {
|
|||||||
val updater by DI.global.instance<IUpdater>()
|
val updater by DI.global.instance<IUpdater>()
|
||||||
if (categoryId == null) {
|
if (categoryId == null) {
|
||||||
logger.info { "Adding Library to Update Queue" }
|
logger.info { "Adding Library to Update Queue" }
|
||||||
updater.addCategoriesToUpdateQueue(Category.getCategoryList(), true)
|
updater.addCategoriesToUpdateQueue(
|
||||||
|
Category.getCategoryList(),
|
||||||
|
clear = true,
|
||||||
|
forceAll = false
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
val category = Category.getCategoryById(categoryId)
|
val category = Category.getCategoryById(categoryId)
|
||||||
if (category != null) {
|
if (category != null) {
|
||||||
updater.addCategoriesToUpdateQueue(listOf(category), true)
|
updater.addCategoriesToUpdateQueue(
|
||||||
|
listOf(category),
|
||||||
|
clear = true,
|
||||||
|
forceAll = true
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
logger.info { "No Category found" }
|
logger.info { "No Category found" }
|
||||||
ctx.status(HttpCode.BAD_REQUEST)
|
ctx.status(HttpCode.BAD_REQUEST)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import kotlinx.coroutines.flow.StateFlow
|
|||||||
import suwayomi.tachidesk.manga.model.dataclass.CategoryDataClass
|
import suwayomi.tachidesk.manga.model.dataclass.CategoryDataClass
|
||||||
|
|
||||||
interface IUpdater {
|
interface IUpdater {
|
||||||
fun addCategoriesToUpdateQueue(categories: List<CategoryDataClass>, clear: Boolean?)
|
fun addCategoriesToUpdateQueue(categories: List<CategoryDataClass>, clear: Boolean?, forceAll: Boolean)
|
||||||
val status: StateFlow<UpdateStatus>
|
val status: StateFlow<UpdateStatus>
|
||||||
fun reset()
|
fun reset()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ class Updater : IUpdater {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.info { "Trigger global update (interval= ${serverConfig.globalUpdateInterval}h, lastAutomatedUpdate= ${Date(lastAutomatedUpdate)})" }
|
logger.info { "Trigger global update (interval= ${serverConfig.globalUpdateInterval}h, lastAutomatedUpdate= ${Date(lastAutomatedUpdate)})" }
|
||||||
addCategoriesToUpdateQueue(Category.getCategoryList(), true)
|
addCategoriesToUpdateQueue(Category.getCategoryList(), clear = true, forceAll = false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun scheduleUpdateTask() {
|
fun scheduleUpdateTask() {
|
||||||
@@ -125,7 +125,7 @@ class Updater : IUpdater {
|
|||||||
return tracker.values.toList()
|
return tracker.values.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun addCategoriesToUpdateQueue(categories: List<CategoryDataClass>, clear: Boolean?) {
|
override fun addCategoriesToUpdateQueue(categories: List<CategoryDataClass>, clear: Boolean?, forceAll: Boolean) {
|
||||||
val updater by DI.global.instance<IUpdater>()
|
val updater by DI.global.instance<IUpdater>()
|
||||||
if (clear == true) {
|
if (clear == true) {
|
||||||
updater.reset()
|
updater.reset()
|
||||||
@@ -135,7 +135,11 @@ class Updater : IUpdater {
|
|||||||
val excludedCategories = includeInUpdateStatusToCategoryMap[IncludeInUpdate.EXCLUDE].orEmpty()
|
val excludedCategories = includeInUpdateStatusToCategoryMap[IncludeInUpdate.EXCLUDE].orEmpty()
|
||||||
val includedCategories = includeInUpdateStatusToCategoryMap[IncludeInUpdate.INCLUDE].orEmpty()
|
val includedCategories = includeInUpdateStatusToCategoryMap[IncludeInUpdate.INCLUDE].orEmpty()
|
||||||
val unsetCategories = includeInUpdateStatusToCategoryMap[IncludeInUpdate.UNSET].orEmpty()
|
val unsetCategories = includeInUpdateStatusToCategoryMap[IncludeInUpdate.UNSET].orEmpty()
|
||||||
val categoriesToUpdate = includedCategories.ifEmpty { unsetCategories }
|
val categoriesToUpdate = if (forceAll) {
|
||||||
|
categories
|
||||||
|
} else {
|
||||||
|
includedCategories.ifEmpty { unsetCategories }
|
||||||
|
}
|
||||||
|
|
||||||
logger.debug { "Updating categories: '${categoriesToUpdate.joinToString("', '") { it.name }}'" }
|
logger.debug { "Updating categories: '${categoriesToUpdate.joinToString("', '") { it.name }}'" }
|
||||||
|
|
||||||
@@ -149,7 +153,7 @@ class Updater : IUpdater {
|
|||||||
.filter { if (serverConfig.excludeUnreadChapters) { (it.unreadCount ?: 0L) == 0L } else true }
|
.filter { if (serverConfig.excludeUnreadChapters) { (it.unreadCount ?: 0L) == 0L } else true }
|
||||||
.filter { if (serverConfig.excludeNotStarted) { it.lastReadAt != null } else true }
|
.filter { if (serverConfig.excludeNotStarted) { it.lastReadAt != null } else true }
|
||||||
.filter { if (serverConfig.excludeCompleted) { it.status != MangaStatus.COMPLETED.name } else true }
|
.filter { if (serverConfig.excludeCompleted) { it.status != MangaStatus.COMPLETED.name } else true }
|
||||||
.filter { !excludedCategories.any { category -> mangasToCategoriesMap[it.id]?.contains(category) == true } }
|
.filter { forceAll || !excludedCategories.any { category -> mangasToCategoriesMap[it.id]?.contains(category) == true } }
|
||||||
.toList()
|
.toList()
|
||||||
|
|
||||||
// In case no manga gets updated and no update job was running before, the client would never receive an info about its update request
|
// In case no manga gets updated and no update job was running before, the client would never receive an info about its update request
|
||||||
|
|||||||
Reference in New Issue
Block a user