Files
Suwayomi-Server/server/src/main/kotlin/suwayomi/tachidesk/manga/controller/UpdateController.kt
Mitchell Syer 2d535b44d8 Extension API 1.6 (#2120)
* Non-Extension Index changes for 1.6

* Changelog

* Minor fixes

* Implement extension store

* Test build fix

* Docs

* Simplify fetching manga and chapters

* Use EMPTY JsonObject

* Update docs/Configuring-Suwayomi‐Server.md

Co-authored-by: Constantin Piber <59023762+cpiber@users.noreply.github.com>

* Improve Fetch Extension Store

* Fixes

* Simplify deprecated isNsfw in SourceQuery

* Simplify ContentRating in Source.kt

* Simplify isNsfw in SourceType

* No magic numbers for ContentRating, improves safety for future versions of extension api

* Fix SearchTest

* Lint

* Lint

* Optimize imports and fix unchecked cast warning

* Proper extension store queries

* Optimize import fixes

* Add ContentRatingFilter

* Improve extension store sync

* fix: re-sync (#2121)

* Lint

* Add ExtenionStores to the fetchExtensions result since its possible for the stores to change.

* Use a single version of ContentRating

* Exclude ServerConfig.extensionStores from GraphQL

* Use syncDbToPrefs in ExtensionStoreMutation

* Optimize Imports

* Update server/server-config/src/main/kotlin/suwayomi/tachidesk/server/ServerConfig.kt

Co-authored-by: Constantin Piber <59023762+cpiber@users.noreply.github.com>

* Remove replaceWith and add specific description for GQL APIs

* Include OkHttp ZSTD

* Update to latest Mihon extension lib

* Fix latest Mihon Extension Lib

* Lint

* Optimize imports

* Lint

* Review fixes

* Add a index to extesnion table store url

* Lint

---------

Co-authored-by: Constantin Piber <59023762+cpiber@users.noreply.github.com>
2026-06-27 13:39:28 -04:00

158 lines
5.5 KiB
Kotlin

package suwayomi.tachidesk.manga.controller
import io.github.oshai.kotlinlogging.KotlinLogging
import io.javalin.http.HttpStatus
import io.javalin.websocket.WsConfig
import suwayomi.tachidesk.manga.impl.Category
import suwayomi.tachidesk.manga.impl.Chapter
import suwayomi.tachidesk.manga.impl.update.IUpdater
import suwayomi.tachidesk.manga.impl.update.UpdateStatus
import suwayomi.tachidesk.manga.impl.update.UpdaterSocket
import suwayomi.tachidesk.manga.model.dataclass.MangaChapterDataClass
import suwayomi.tachidesk.manga.model.dataclass.PaginatedList
import suwayomi.tachidesk.server.JavalinSetup.Attribute
import suwayomi.tachidesk.server.JavalinSetup.future
import suwayomi.tachidesk.server.JavalinSetup.getAttribute
import suwayomi.tachidesk.server.user.requireUser
import suwayomi.tachidesk.server.util.formParam
import suwayomi.tachidesk.server.util.handler
import suwayomi.tachidesk.server.util.pathParam
import suwayomi.tachidesk.server.util.withOperation
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
/*
* 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/. */
object UpdateController {
private val logger = KotlinLogging.logger { }
/** get recently updated manga chapters */
val recentChapters =
handler(
pathParam<Int>("pageNum"),
documentWith = {
withOperation {
summary("Updates fetch")
description("Get recently updated manga chapters")
}
},
behaviorOf = { ctx, pageNum ->
ctx.getAttribute(Attribute.TachideskUser).requireUser()
ctx.future {
future {
Chapter.getRecentChapters(pageNum)
}.thenApply { ctx.json(it) }
}
},
withResults = {
json<PagedMangaChapterListDataClass>(HttpStatus.OK)
},
)
/**
* Class made for handling return type in the documentation for [UpdateController.recentChapters],
* since OpenApi cannot handle runtime generics.
*/
private class PagedMangaChapterListDataClass : PaginatedList<MangaChapterDataClass>(emptyList(), false)
val categoryUpdate =
handler(
formParam<Int?>("categoryId"),
documentWith = {
withOperation {
summary("Updater start")
description("Starts the updater")
}
},
behaviorOf = { ctx, categoryId ->
ctx.getAttribute(Attribute.TachideskUser).requireUser()
val updater = Injekt.get<IUpdater>()
if (categoryId == null) {
logger.info { "Adding Library to Update Queue" }
updater.addCategoriesToUpdateQueue(
Category.getCategoryList(),
clear = true,
forceAll = false,
)
} else {
val category = Category.getCategoryById(categoryId)
if (category != null) {
updater.addCategoriesToUpdateQueue(
listOf(category),
clear = true,
forceAll = true,
)
} else {
logger.info { "No Category found" }
ctx.status(HttpStatus.BAD_REQUEST)
}
}
},
withResults = {
httpCode(HttpStatus.OK)
httpCode(HttpStatus.BAD_REQUEST)
},
)
fun categoryUpdateWS(ws: WsConfig) {
ws.onConnect { ctx ->
ctx.getAttribute(Attribute.TachideskUser).requireUser()
UpdaterSocket.addClient(ctx)
}
ws.onMessage { ctx ->
UpdaterSocket.handleRequest(ctx)
}
ws.onClose { ctx ->
UpdaterSocket.removeClient(ctx)
}
}
val updateSummary =
handler(
documentWith = {
withOperation {
summary("Updater summary")
description("Gets the latest updater summary")
}
},
behaviorOf = { ctx ->
ctx.getAttribute(Attribute.TachideskUser).requireUser()
val updater = Injekt.get<IUpdater>()
ctx.json(updater.statusDeprecated.value)
},
withResults = {
json<UpdateStatus>(HttpStatus.OK)
},
)
val reset =
handler(
documentWith = {
withOperation {
summary("Updater reset")
description("Stops and resets the Updater")
}
},
behaviorOf = { ctx ->
ctx.getAttribute(Attribute.TachideskUser).requireUser()
val updater = Injekt.get<IUpdater>()
logger.info { "Resetting Updater" }
ctx.future {
future {
updater.reset()
}.thenApply {
ctx.status(HttpStatus.OK)
}
}
},
withResults = {
httpCode(HttpStatus.OK)
},
)
}