document all endpoints (#350)
* Document all endpoints * Forgot about global endpoints
This commit is contained in:
@@ -14,8 +14,8 @@ import suwayomi.tachidesk.global.controller.SettingsController
|
||||
object GlobalAPI {
|
||||
fun defineEndpoints() {
|
||||
path("settings") {
|
||||
get("about", SettingsController::about)
|
||||
get("check-update", SettingsController::checkUpdate)
|
||||
get("about", SettingsController.about)
|
||||
get("check-update", SettingsController.checkUpdate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,22 +7,48 @@ package suwayomi.tachidesk.global.controller
|
||||
* 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 io.javalin.http.Context
|
||||
import io.javalin.http.HttpCode
|
||||
import suwayomi.tachidesk.global.impl.About
|
||||
import suwayomi.tachidesk.global.impl.AboutDataClass
|
||||
import suwayomi.tachidesk.global.impl.AppUpdate
|
||||
import suwayomi.tachidesk.global.impl.UpdateDataClass
|
||||
import suwayomi.tachidesk.server.JavalinSetup.future
|
||||
import suwayomi.tachidesk.server.util.handler
|
||||
import suwayomi.tachidesk.server.util.withOperation
|
||||
|
||||
/** Settings Page/Screen */
|
||||
object SettingsController {
|
||||
/** returns some static info about the current app build */
|
||||
fun about(ctx: Context) {
|
||||
ctx.json(About.getAbout())
|
||||
}
|
||||
val about = handler(
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("About Tachidesk")
|
||||
description("Returns some static info about the current app build")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.json(About.getAbout())
|
||||
},
|
||||
withResults = {
|
||||
json<AboutDataClass>(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
/** check for app updates */
|
||||
fun checkUpdate(ctx: Context) {
|
||||
ctx.json(
|
||||
future { AppUpdate.checkUpdate() }
|
||||
)
|
||||
}
|
||||
val checkUpdate = handler(
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Tachidesk update check")
|
||||
description("Check for app updates")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.json(
|
||||
future { AppUpdate.checkUpdate() }
|
||||
)
|
||||
},
|
||||
withResults = {
|
||||
json<UpdateDataClass>(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -24,31 +24,31 @@ import suwayomi.tachidesk.manga.controller.UpdateController
|
||||
object MangaAPI {
|
||||
fun defineEndpoints() {
|
||||
path("extension") {
|
||||
get("list", ExtensionController::list)
|
||||
get("list", ExtensionController.list)
|
||||
|
||||
get("install/{pkgName}", ExtensionController::install)
|
||||
post("install", ExtensionController::installFile)
|
||||
get("update/{pkgName}", ExtensionController::update)
|
||||
get("uninstall/{pkgName}", ExtensionController::uninstall)
|
||||
get("install/{pkgName}", ExtensionController.install)
|
||||
post("install", ExtensionController.installFile)
|
||||
get("update/{pkgName}", ExtensionController.update)
|
||||
get("uninstall/{pkgName}", ExtensionController.uninstall)
|
||||
|
||||
get("icon/{apkName}", ExtensionController::icon)
|
||||
get("icon/{apkName}", ExtensionController.icon)
|
||||
}
|
||||
|
||||
path("source") {
|
||||
get("list", SourceController::list)
|
||||
get("{sourceId}", SourceController::retrieve)
|
||||
get("list", SourceController.list)
|
||||
get("{sourceId}", SourceController.retrieve)
|
||||
|
||||
get("{sourceId}/popular/{pageNum}", SourceController::popular)
|
||||
get("{sourceId}/latest/{pageNum}", SourceController::latest)
|
||||
get("{sourceId}/popular/{pageNum}", SourceController.popular)
|
||||
get("{sourceId}/latest/{pageNum}", SourceController.latest)
|
||||
|
||||
get("{sourceId}/preferences", SourceController::getPreferences)
|
||||
post("{sourceId}/preferences", SourceController::setPreference)
|
||||
get("{sourceId}/preferences", SourceController.getPreferences)
|
||||
post("{sourceId}/preferences", SourceController.setPreference)
|
||||
|
||||
get("{sourceId}/filters", SourceController::getFilters)
|
||||
post("{sourceId}/filters", SourceController::setFilters)
|
||||
get("{sourceId}/filters", SourceController.getFilters)
|
||||
post("{sourceId}/filters", SourceController.setFilters)
|
||||
|
||||
get("{sourceId}/search", SourceController::searchSingle)
|
||||
// get("all/search", SourceController::searchGlobal) // TODO
|
||||
get("{sourceId}/search", SourceController.searchSingle)
|
||||
// get("all/search", SourceController.searchGlobal) // TODO
|
||||
}
|
||||
|
||||
path("manga") {
|
||||
@@ -75,47 +75,47 @@ object MangaAPI {
|
||||
}
|
||||
|
||||
path("category") {
|
||||
get("", CategoryController::categoryList)
|
||||
post("", CategoryController::categoryCreate)
|
||||
get("", CategoryController.categoryList)
|
||||
post("", CategoryController.categoryCreate)
|
||||
|
||||
// The order here is important {categoryId} needs to be applied last
|
||||
// or throws a NumberFormatException
|
||||
patch("reorder", CategoryController::categoryReorder)
|
||||
patch("reorder", CategoryController.categoryReorder)
|
||||
|
||||
get("{categoryId}", CategoryController::categoryMangas)
|
||||
patch("{categoryId}", CategoryController::categoryModify)
|
||||
delete("{categoryId}", CategoryController::categoryDelete)
|
||||
get("{categoryId}", CategoryController.categoryMangas)
|
||||
patch("{categoryId}", CategoryController.categoryModify)
|
||||
delete("{categoryId}", CategoryController.categoryDelete)
|
||||
}
|
||||
|
||||
path("backup") {
|
||||
post("import", BackupController::protobufImport)
|
||||
post("import/file", BackupController::protobufImportFile)
|
||||
post("import", BackupController.protobufImport)
|
||||
post("import/file", BackupController.protobufImportFile)
|
||||
|
||||
post("validate", BackupController::protobufValidate)
|
||||
post("validate/file", BackupController::protobufValidateFile)
|
||||
post("validate", BackupController.protobufValidate)
|
||||
post("validate/file", BackupController.protobufValidateFile)
|
||||
|
||||
get("export", BackupController::protobufExport)
|
||||
get("export/file", BackupController::protobufExportFile)
|
||||
get("export", BackupController.protobufExport)
|
||||
get("export/file", BackupController.protobufExportFile)
|
||||
}
|
||||
|
||||
path("downloads") {
|
||||
ws("", DownloadController::downloadsWS)
|
||||
|
||||
get("start", DownloadController::start)
|
||||
get("stop", DownloadController::stop)
|
||||
get("clear", DownloadController::stop)
|
||||
get("start", DownloadController.start)
|
||||
get("stop", DownloadController.stop)
|
||||
get("clear", DownloadController.stop)
|
||||
}
|
||||
|
||||
path("download") {
|
||||
get("{mangaId}/chapter/{chapterIndex}", DownloadController::queueChapter)
|
||||
delete("{mangaId}/chapter/{chapterIndex}", DownloadController::unqueueChapter)
|
||||
get("{mangaId}/chapter/{chapterIndex}", DownloadController.queueChapter)
|
||||
delete("{mangaId}/chapter/{chapterIndex}", DownloadController.unqueueChapter)
|
||||
}
|
||||
|
||||
path("update") {
|
||||
get("recentChapters/{pageNum}", UpdateController::recentChapters)
|
||||
post("fetch", UpdateController::categoryUpdate)
|
||||
get("recentChapters/{pageNum}", UpdateController.recentChapters)
|
||||
post("fetch", UpdateController.categoryUpdate)
|
||||
post("reset", UpdateController.reset)
|
||||
get("summary", UpdateController::updateSummary)
|
||||
get("summary", UpdateController.updateSummary)
|
||||
ws("", UpdateController::categoryUpdateWS)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
package suwayomi.tachidesk.manga.controller
|
||||
|
||||
import io.javalin.http.Context
|
||||
import io.javalin.http.HttpCode
|
||||
import suwayomi.tachidesk.manga.impl.backup.AbstractBackupValidator
|
||||
import suwayomi.tachidesk.manga.impl.backup.BackupFlags
|
||||
import suwayomi.tachidesk.manga.impl.backup.proto.ProtoBackupExport
|
||||
import suwayomi.tachidesk.manga.impl.backup.proto.ProtoBackupImport
|
||||
import suwayomi.tachidesk.manga.impl.backup.proto.ProtoBackupValidator
|
||||
import suwayomi.tachidesk.server.JavalinSetup.future
|
||||
import suwayomi.tachidesk.server.util.handler
|
||||
import suwayomi.tachidesk.server.util.withOperation
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Date
|
||||
|
||||
@@ -19,78 +22,156 @@ import java.util.Date
|
||||
object BackupController {
|
||||
|
||||
/** expects a Tachiyomi protobuf backup in the body */
|
||||
fun protobufImport(ctx: Context) {
|
||||
ctx.future(
|
||||
future {
|
||||
ProtoBackupImport.performRestore(ctx.bodyAsInputStream())
|
||||
val protobufImport = handler(
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Restore a backup")
|
||||
description("Expects a Tachiyomi protobuf backup in the body")
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.future(
|
||||
future {
|
||||
ProtoBackupImport.performRestore(ctx.bodyAsInputStream())
|
||||
}
|
||||
)
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
/** expects a Tachiyomi protobuf backup as a file upload, the file must be named "backup.proto.gz" */
|
||||
fun protobufImportFile(ctx: Context) {
|
||||
// TODO: rewrite this with ctx.uploadedFiles(), don't call the multipart field "backup.proto.gz"
|
||||
ctx.future(
|
||||
future {
|
||||
ProtoBackupImport.performRestore(ctx.uploadedFile("backup.proto.gz")!!.content)
|
||||
val protobufImportFile = handler(
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Restore a backup file")
|
||||
description("Expects a Tachiyomi protobuf backup as a file upload, the file must be named \"backup.proto.gz\"")
|
||||
}
|
||||
)
|
||||
}
|
||||
uploadedFile("backup.proto.gz") {
|
||||
it.description("Protobuf backup")
|
||||
it.required(true)
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
// TODO: rewrite this with ctx.uploadedFiles(), don't call the multipart field "backup.proto.gz"
|
||||
ctx.future(
|
||||
future {
|
||||
ProtoBackupImport.performRestore(ctx.uploadedFile("backup.proto.gz")!!.content)
|
||||
}
|
||||
)
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.OK)
|
||||
httpCode(HttpCode.NOT_FOUND)
|
||||
}
|
||||
)
|
||||
|
||||
/** returns a Tachiyomi protobuf backup created from the current database as a body */
|
||||
fun protobufExport(ctx: Context) {
|
||||
ctx.contentType("application/octet-stream")
|
||||
ctx.future(
|
||||
future {
|
||||
ProtoBackupExport.createBackup(
|
||||
BackupFlags(
|
||||
includeManga = true,
|
||||
includeCategories = true,
|
||||
includeChapters = true,
|
||||
includeTracking = true,
|
||||
includeHistory = true,
|
||||
)
|
||||
)
|
||||
val protobufExport = handler(
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Create a backup")
|
||||
description("Returns a Tachiyomi protobuf backup created from the current database as a body")
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.contentType("application/octet-stream")
|
||||
ctx.future(
|
||||
future {
|
||||
ProtoBackupExport.createBackup(
|
||||
BackupFlags(
|
||||
includeManga = true,
|
||||
includeCategories = true,
|
||||
includeChapters = true,
|
||||
includeTracking = true,
|
||||
includeHistory = true,
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
withResults = {
|
||||
mime(HttpCode.OK, "application/octet-stream")
|
||||
}
|
||||
)
|
||||
|
||||
/** returns a Tachiyomi protobuf backup created from the current database as a file */
|
||||
fun protobufExportFile(ctx: Context) {
|
||||
ctx.contentType("application/octet-stream")
|
||||
val currentDate = SimpleDateFormat("yyyy-MM-dd_HH-mm").format(Date())
|
||||
|
||||
ctx.header("Content-Disposition", """attachment; filename="tachidesk_$currentDate.proto.gz"""")
|
||||
ctx.future(
|
||||
future {
|
||||
ProtoBackupExport.createBackup(
|
||||
BackupFlags(
|
||||
includeManga = true,
|
||||
includeCategories = true,
|
||||
includeChapters = true,
|
||||
includeTracking = true,
|
||||
includeHistory = true,
|
||||
)
|
||||
)
|
||||
val protobufExportFile = handler(
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Create a backup file")
|
||||
description("Returns a Tachiyomi protobuf backup created from the current database as a file")
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.contentType("application/octet-stream")
|
||||
val currentDate = SimpleDateFormat("yyyy-MM-dd_HH-mm").format(Date())
|
||||
|
||||
ctx.header("Content-Disposition", """attachment; filename="tachidesk_$currentDate.proto.gz"""")
|
||||
ctx.future(
|
||||
future {
|
||||
ProtoBackupExport.createBackup(
|
||||
BackupFlags(
|
||||
includeManga = true,
|
||||
includeCategories = true,
|
||||
includeChapters = true,
|
||||
includeTracking = true,
|
||||
includeHistory = true,
|
||||
)
|
||||
)
|
||||
}
|
||||
)
|
||||
},
|
||||
withResults = {
|
||||
mime(HttpCode.OK, "application/octet-stream")
|
||||
}
|
||||
)
|
||||
|
||||
/** Reports missing sources and trackers, expects a Tachiyomi protobuf backup in the body */
|
||||
fun protobufValidate(ctx: Context) {
|
||||
ctx.future(
|
||||
future {
|
||||
ProtoBackupValidator.validate(ctx.bodyAsInputStream())
|
||||
val protobufValidate = handler(
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Validate a backup")
|
||||
description("Reports missing sources and trackers, expects a Tachiyomi protobuf backup in the body")
|
||||
}
|
||||
)
|
||||
}
|
||||
body<ByteArray>("") {
|
||||
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.future(
|
||||
future {
|
||||
ProtoBackupValidator.validate(ctx.bodyAsInputStream())
|
||||
}
|
||||
)
|
||||
},
|
||||
withResults = {
|
||||
json<AbstractBackupValidator.ValidationResult>(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
/** Reports missing sources and trackers, expects a Tachiyomi protobuf backup as a file upload, the file must be named "backup.proto.gz" */
|
||||
fun protobufValidateFile(ctx: Context) {
|
||||
ctx.future(
|
||||
future {
|
||||
ProtoBackupValidator.validate(ctx.uploadedFile("backup.proto.gz")!!.content)
|
||||
val protobufValidateFile = handler(
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Validate a backup file")
|
||||
description("Reports missing sources and trackers, expects a Tachiyomi protobuf backup as a file upload, the file must be named \"backup.proto.gz\"")
|
||||
}
|
||||
)
|
||||
}
|
||||
uploadedFile("backup.proto.gz") {
|
||||
it.description("Protobuf backup")
|
||||
it.required(true)
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.future(
|
||||
future {
|
||||
ProtoBackupValidator.validate(ctx.uploadedFile("backup.proto.gz")!!.content)
|
||||
}
|
||||
)
|
||||
},
|
||||
withResults = {
|
||||
json<AbstractBackupValidator.ValidationResult>(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,50 +7,127 @@ package suwayomi.tachidesk.manga.controller
|
||||
* 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 io.javalin.http.Context
|
||||
import io.javalin.http.HttpCode
|
||||
import suwayomi.tachidesk.manga.impl.Category
|
||||
import suwayomi.tachidesk.manga.impl.CategoryManga
|
||||
import suwayomi.tachidesk.manga.model.dataclass.CategoryDataClass
|
||||
import suwayomi.tachidesk.manga.model.dataclass.MangaDataClass
|
||||
import suwayomi.tachidesk.server.util.formParam
|
||||
import suwayomi.tachidesk.server.util.handler
|
||||
import suwayomi.tachidesk.server.util.pathParam
|
||||
import suwayomi.tachidesk.server.util.withOperation
|
||||
|
||||
object CategoryController {
|
||||
/** category list */
|
||||
fun categoryList(ctx: Context) {
|
||||
ctx.json(Category.getCategoryList())
|
||||
}
|
||||
val categoryList = handler(
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Category list")
|
||||
description("get a list of categories")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.json(Category.getCategoryList())
|
||||
},
|
||||
withResults = {
|
||||
json<List<CategoryDataClass>>(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
/** category create */
|
||||
fun categoryCreate(ctx: Context) {
|
||||
val name = ctx.formParam("name")!!
|
||||
Category.createCategory(name)
|
||||
ctx.status(200)
|
||||
}
|
||||
val categoryCreate = handler(
|
||||
formParam<String>("name"),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Category create")
|
||||
description("Create a category")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, name ->
|
||||
if (Category.createCategory(name) != -1) {
|
||||
ctx.status(200)
|
||||
} else {
|
||||
ctx.status(HttpCode.BAD_REQUEST)
|
||||
}
|
||||
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.OK)
|
||||
httpCode(HttpCode.BAD_REQUEST)
|
||||
}
|
||||
)
|
||||
|
||||
/** category modification */
|
||||
fun categoryModify(ctx: Context) {
|
||||
val categoryId = ctx.pathParam("categoryId").toInt()
|
||||
val name = ctx.formParam("name")
|
||||
val isDefault = ctx.formParam("default")?.toBoolean()
|
||||
Category.updateCategory(categoryId, name, isDefault)
|
||||
ctx.status(200)
|
||||
}
|
||||
val categoryModify = handler(
|
||||
pathParam<Int>("categoryId"),
|
||||
formParam<String?>("name"),
|
||||
formParam<Boolean?>("default"),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Category modify")
|
||||
description("Modify a category")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, categoryId, name, isDefault ->
|
||||
Category.updateCategory(categoryId, name, isDefault)
|
||||
ctx.status(200)
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
/** category delete */
|
||||
fun categoryDelete(ctx: Context) {
|
||||
val categoryId = ctx.pathParam("categoryId").toInt()
|
||||
Category.removeCategory(categoryId)
|
||||
ctx.status(200)
|
||||
}
|
||||
val categoryDelete = handler(
|
||||
pathParam<Int>("categoryId"),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Category delete")
|
||||
description("Delete a category")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, categoryId ->
|
||||
Category.removeCategory(categoryId)
|
||||
ctx.status(200)
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
/** returns the manga list associated with a category */
|
||||
fun categoryMangas(ctx: Context) {
|
||||
val categoryId = ctx.pathParam("categoryId").toInt()
|
||||
ctx.json(CategoryManga.getCategoryMangaList(categoryId))
|
||||
}
|
||||
val categoryMangas = handler(
|
||||
pathParam<Int>("categoryId"),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Category manga")
|
||||
description("Returns the manga list associated with a category")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, categoryId ->
|
||||
ctx.json(CategoryManga.getCategoryMangaList(categoryId))
|
||||
},
|
||||
withResults = {
|
||||
json<List<MangaDataClass>>(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
/** category re-ordering */
|
||||
fun categoryReorder(ctx: Context) {
|
||||
val from = ctx.formParam("from")!!.toInt()
|
||||
val to = ctx.formParam("to")!!.toInt()
|
||||
Category.reorderCategory(from, to)
|
||||
ctx.status(200)
|
||||
}
|
||||
val categoryReorder = handler(
|
||||
formParam<Int>("from"),
|
||||
formParam<Int>("to"),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Category re-ordering")
|
||||
description("Re-order a category")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, from, to ->
|
||||
Category.reorderCategory(from, to)
|
||||
ctx.status(200)
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,10 +7,13 @@ package suwayomi.tachidesk.manga.controller
|
||||
* 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 io.javalin.http.Context
|
||||
import io.javalin.http.HttpCode
|
||||
import io.javalin.websocket.WsConfig
|
||||
import suwayomi.tachidesk.manga.impl.download.DownloadManager
|
||||
import suwayomi.tachidesk.server.JavalinSetup.future
|
||||
import suwayomi.tachidesk.server.util.handler
|
||||
import suwayomi.tachidesk.server.util.pathParam
|
||||
import suwayomi.tachidesk.server.util.withOperation
|
||||
|
||||
object DownloadController {
|
||||
/** Download queue stats */
|
||||
@@ -28,45 +31,100 @@ object DownloadController {
|
||||
}
|
||||
|
||||
/** Start the downloader */
|
||||
fun start(ctx: Context) {
|
||||
DownloadManager.start()
|
||||
val start = handler(
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Downloader start")
|
||||
description("Start the downloader")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
DownloadManager.start()
|
||||
|
||||
ctx.status(200)
|
||||
}
|
||||
ctx.status(200)
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
/** Stop the downloader */
|
||||
fun stop(ctx: Context) {
|
||||
DownloadManager.stop()
|
||||
val stop = handler(
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Downloader stop")
|
||||
description("Stop the downloader")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
DownloadManager.stop()
|
||||
|
||||
ctx.status(200)
|
||||
}
|
||||
ctx.status(200)
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
/** clear download queue */
|
||||
fun clear(ctx: Context) {
|
||||
DownloadManager.clear()
|
||||
val clear = handler(
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Downloader clear")
|
||||
description("Clear download queue")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
DownloadManager.clear()
|
||||
|
||||
ctx.status(200)
|
||||
}
|
||||
ctx.status(200)
|
||||
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
/** Queue chapter for download */
|
||||
fun queueChapter(ctx: Context) {
|
||||
val chapterIndex = ctx.pathParam("chapterIndex").toInt()
|
||||
val mangaId = ctx.pathParam("mangaId").toInt()
|
||||
|
||||
ctx.future(
|
||||
future {
|
||||
DownloadManager.enqueue(chapterIndex, mangaId)
|
||||
val queueChapter = handler(
|
||||
pathParam<Int>("chapterIndex"),
|
||||
pathParam<Int>("mangaId"),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Downloader add chapter")
|
||||
description("Queue chapter for download")
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, chapterIndex, mangaId ->
|
||||
ctx.future(
|
||||
future {
|
||||
DownloadManager.enqueue(chapterIndex, mangaId)
|
||||
}
|
||||
)
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.OK)
|
||||
httpCode(HttpCode.NOT_FOUND)
|
||||
}
|
||||
)
|
||||
|
||||
/** delete chapter from download queue */
|
||||
fun unqueueChapter(ctx: Context) {
|
||||
val chapterIndex = ctx.pathParam("chapterIndex").toInt()
|
||||
val mangaId = ctx.pathParam("mangaId").toInt()
|
||||
val unqueueChapter = handler(
|
||||
pathParam<Int>("chapterIndex"),
|
||||
pathParam<Int>("mangaId"),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Downloader remove chapter")
|
||||
description("Delete chapter from download queue")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, chapterIndex, mangaId ->
|
||||
DownloadManager.unqueue(chapterIndex, mangaId)
|
||||
|
||||
DownloadManager.unqueue(chapterIndex, mangaId)
|
||||
|
||||
ctx.status(200)
|
||||
}
|
||||
ctx.status(200)
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
+133
-51
@@ -7,78 +7,160 @@ package suwayomi.tachidesk.manga.controller
|
||||
* 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 io.javalin.http.Context
|
||||
import io.javalin.http.HttpCode
|
||||
import mu.KotlinLogging
|
||||
import suwayomi.tachidesk.manga.impl.extension.Extension
|
||||
import suwayomi.tachidesk.manga.impl.extension.ExtensionsList
|
||||
import suwayomi.tachidesk.manga.model.dataclass.ExtensionDataClass
|
||||
import suwayomi.tachidesk.server.JavalinSetup.future
|
||||
import suwayomi.tachidesk.server.util.handler
|
||||
import suwayomi.tachidesk.server.util.pathParam
|
||||
import suwayomi.tachidesk.server.util.queryParam
|
||||
import suwayomi.tachidesk.server.util.withOperation
|
||||
|
||||
object ExtensionController {
|
||||
private val logger = KotlinLogging.logger {}
|
||||
|
||||
/** list all extensions */
|
||||
fun list(ctx: Context) {
|
||||
ctx.future(
|
||||
future {
|
||||
ExtensionsList.getExtensionList()
|
||||
val list = handler(
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Extension list")
|
||||
description("List all extensions")
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.future(
|
||||
future {
|
||||
ExtensionsList.getExtensionList()
|
||||
}
|
||||
)
|
||||
},
|
||||
withResults = {
|
||||
json<List<ExtensionDataClass>>(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
/** install extension identified with "pkgName" */
|
||||
fun install(ctx: Context) {
|
||||
val pkgName = ctx.pathParam("pkgName")
|
||||
|
||||
ctx.future(
|
||||
future {
|
||||
Extension.installExtension(pkgName)
|
||||
val install = handler(
|
||||
pathParam<String>("pkgName"),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Extension install")
|
||||
description("install extension identified with \"pkgName\"")
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, pkgName ->
|
||||
ctx.future(
|
||||
future {
|
||||
Extension.installExtension(pkgName)
|
||||
}
|
||||
)
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.CREATED)
|
||||
httpCode(HttpCode.FOUND)
|
||||
httpCode(HttpCode.INTERNAL_SERVER_ERROR)
|
||||
}
|
||||
)
|
||||
|
||||
/** install the uploaded apk file */
|
||||
fun installFile(ctx: Context) {
|
||||
|
||||
val uploadedFile = ctx.uploadedFile("file")!!
|
||||
logger.debug { "Uploaded extension file name: " + uploadedFile.filename }
|
||||
|
||||
ctx.future(
|
||||
future {
|
||||
Extension.installExternalExtension(uploadedFile.content, uploadedFile.filename)
|
||||
val installFile = handler(
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Extension install apk")
|
||||
description("Install the uploaded apk file")
|
||||
}
|
||||
)
|
||||
}
|
||||
uploadedFile("file") {
|
||||
it.description("Extension apk")
|
||||
it.required(true)
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
val uploadedFile = ctx.uploadedFile("file")!!
|
||||
logger.debug { "Uploaded extension file name: " + uploadedFile.filename }
|
||||
|
||||
ctx.future(
|
||||
future {
|
||||
Extension.installExternalExtension(uploadedFile.content, uploadedFile.filename)
|
||||
}
|
||||
)
|
||||
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.CREATED)
|
||||
httpCode(HttpCode.FOUND)
|
||||
httpCode(HttpCode.INTERNAL_SERVER_ERROR)
|
||||
}
|
||||
)
|
||||
|
||||
/** update extension identified with "pkgName" */
|
||||
fun update(ctx: Context) {
|
||||
val pkgName = ctx.pathParam("pkgName")
|
||||
|
||||
ctx.future(
|
||||
future {
|
||||
Extension.updateExtension(pkgName)
|
||||
val update = handler(
|
||||
pathParam<String>("pkgName"),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Extension update")
|
||||
description("Update extension identified with \"pkgName\"")
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, pkgName ->
|
||||
ctx.future(
|
||||
future {
|
||||
Extension.updateExtension(pkgName)
|
||||
}
|
||||
)
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.CREATED)
|
||||
httpCode(HttpCode.FOUND)
|
||||
httpCode(HttpCode.NOT_FOUND)
|
||||
httpCode(HttpCode.INTERNAL_SERVER_ERROR)
|
||||
}
|
||||
)
|
||||
|
||||
/** uninstall extension identified with "pkgName" */
|
||||
fun uninstall(ctx: Context) {
|
||||
val pkgName = ctx.pathParam("pkgName")
|
||||
|
||||
Extension.uninstallExtension(pkgName)
|
||||
ctx.status(200)
|
||||
}
|
||||
val uninstall = handler(
|
||||
pathParam<String>("pkgName"),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Extension uninstall")
|
||||
description("Uninstall extension identified with \"pkgName\"")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, pkgName ->
|
||||
Extension.uninstallExtension(pkgName)
|
||||
ctx.status(200)
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.CREATED)
|
||||
httpCode(HttpCode.FOUND)
|
||||
httpCode(HttpCode.NOT_FOUND)
|
||||
httpCode(HttpCode.INTERNAL_SERVER_ERROR)
|
||||
}
|
||||
)
|
||||
|
||||
/** icon for extension named `apkName` */
|
||||
fun icon(ctx: Context) {
|
||||
val apkName = ctx.pathParam("apkName")
|
||||
val useCache = ctx.queryParam("useCache")?.toBoolean() ?: true
|
||||
|
||||
ctx.future(
|
||||
future { Extension.getExtensionIcon(apkName, useCache) }
|
||||
.thenApply {
|
||||
ctx.header("content-type", it.second)
|
||||
it.first
|
||||
}
|
||||
)
|
||||
}
|
||||
val icon = handler(
|
||||
pathParam<String>("apkName"),
|
||||
queryParam("useCache", true),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Extension icon")
|
||||
description("Icon for extension named `apkName`")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, apkName, useCache ->
|
||||
ctx.future(
|
||||
future { Extension.getExtensionIcon(apkName, useCache) }
|
||||
.thenApply {
|
||||
ctx.header("content-type", it.second)
|
||||
it.first
|
||||
}
|
||||
)
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.OK)
|
||||
httpCode(HttpCode.NOT_FOUND)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ package suwayomi.tachidesk.manga.controller
|
||||
* 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 io.javalin.http.Context
|
||||
import io.javalin.http.HttpCode
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import org.kodein.di.DI
|
||||
@@ -18,87 +18,205 @@ import suwayomi.tachidesk.manga.impl.Search
|
||||
import suwayomi.tachidesk.manga.impl.Search.FilterChange
|
||||
import suwayomi.tachidesk.manga.impl.Source
|
||||
import suwayomi.tachidesk.manga.impl.Source.SourcePreferenceChange
|
||||
import suwayomi.tachidesk.manga.model.dataclass.PagedMangaListDataClass
|
||||
import suwayomi.tachidesk.server.JavalinSetup.future
|
||||
import suwayomi.tachidesk.server.util.handler
|
||||
import suwayomi.tachidesk.server.util.pathParam
|
||||
import suwayomi.tachidesk.server.util.queryParam
|
||||
import suwayomi.tachidesk.server.util.withOperation
|
||||
import javax.sound.sampled.SourceDataLine
|
||||
|
||||
object SourceController {
|
||||
/** list of sources */
|
||||
fun list(ctx: Context) {
|
||||
ctx.json(Source.getSourceList())
|
||||
}
|
||||
val list = handler(
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Sources list")
|
||||
description("List of sources")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
ctx.json(Source.getSourceList())
|
||||
},
|
||||
withResults = {
|
||||
json<List<SourceDataLine>>(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
/** fetch source with id `sourceId` */
|
||||
fun retrieve(ctx: Context) {
|
||||
val sourceId = ctx.pathParam("sourceId").toLong()
|
||||
ctx.json(Source.getSource(sourceId)!!)
|
||||
}
|
||||
val retrieve = handler(
|
||||
pathParam<Long>("sourceId"),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Source fetch")
|
||||
description("Fetch source with id `sourceId`")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, sourceId ->
|
||||
ctx.json(Source.getSource(sourceId)!!)
|
||||
},
|
||||
withResults = {
|
||||
json<SourceDataLine>(HttpCode.OK)
|
||||
httpCode(HttpCode.NOT_FOUND)
|
||||
}
|
||||
)
|
||||
|
||||
/** popular mangas from source with id `sourceId` */
|
||||
fun popular(ctx: Context) {
|
||||
val sourceId = ctx.pathParam("sourceId").toLong()
|
||||
val pageNum = ctx.pathParam("pageNum").toInt()
|
||||
ctx.future(
|
||||
future {
|
||||
MangaList.getMangaList(sourceId, pageNum, popular = true)
|
||||
val popular = handler(
|
||||
pathParam<Long>("sourceId"),
|
||||
pathParam<Int>("pageNum"),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Source popular manga")
|
||||
description("Popular mangas from source with id `sourceId`")
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, sourceId, pageNum ->
|
||||
ctx.future(
|
||||
future {
|
||||
MangaList.getMangaList(sourceId, pageNum, popular = true)
|
||||
}
|
||||
)
|
||||
},
|
||||
withResults = {
|
||||
json<PagedMangaListDataClass>(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
/** latest mangas from source with id `sourceId` */
|
||||
fun latest(ctx: Context) {
|
||||
val sourceId = ctx.pathParam("sourceId").toLong()
|
||||
val pageNum = ctx.pathParam("pageNum").toInt()
|
||||
ctx.future(
|
||||
future {
|
||||
MangaList.getMangaList(sourceId, pageNum, popular = false)
|
||||
val latest = handler(
|
||||
pathParam<Long>("sourceId"),
|
||||
pathParam<Int>("pageNum"),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Source latest manga")
|
||||
description("Latest mangas from source with id `sourceId`")
|
||||
}
|
||||
)
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, sourceId, pageNum ->
|
||||
ctx.future(
|
||||
future {
|
||||
MangaList.getMangaList(sourceId, pageNum, popular = false)
|
||||
}
|
||||
)
|
||||
},
|
||||
withResults = {
|
||||
json<PagedMangaListDataClass>(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
/** fetch preferences of source with id `sourceId` */
|
||||
fun getPreferences(ctx: Context) {
|
||||
val sourceId = ctx.pathParam("sourceId").toLong()
|
||||
ctx.json(Source.getSourcePreferences(sourceId))
|
||||
}
|
||||
val getPreferences = handler(
|
||||
pathParam<Long>("sourceId"),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Source preferences")
|
||||
description("Fetch preferences of source with id `sourceId`")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, sourceId ->
|
||||
ctx.json(Source.getSourcePreferences(sourceId))
|
||||
|
||||
},
|
||||
withResults = {
|
||||
json<List<Source.PreferenceObject>>(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
/** set one preference of source with id `sourceId` */
|
||||
fun setPreference(ctx: Context) {
|
||||
val sourceId = ctx.pathParam("sourceId").toLong()
|
||||
val preferenceChange = ctx.bodyAsClass(SourcePreferenceChange::class.java)
|
||||
ctx.json(Source.setSourcePreference(sourceId, preferenceChange))
|
||||
}
|
||||
val setPreference = handler(
|
||||
pathParam<Long>("sourceId"),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Source preference set")
|
||||
description("Set one preference of source with id `sourceId`")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, sourceId ->
|
||||
val preferenceChange = ctx.bodyAsClass(SourcePreferenceChange::class.java)
|
||||
ctx.json(Source.setSourcePreference(sourceId, preferenceChange))
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
/** fetch filters of source with id `sourceId` */
|
||||
fun getFilters(ctx: Context) {
|
||||
val sourceId = ctx.pathParam("sourceId").toLong()
|
||||
val reset = ctx.queryParam("reset")?.toBoolean() ?: false
|
||||
ctx.json(Search.getFilterList(sourceId, reset))
|
||||
}
|
||||
val getFilters = handler(
|
||||
pathParam<Long>("sourceId"),
|
||||
queryParam("reset", false),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Source filters")
|
||||
description("Fetch filters of source with id `sourceId`")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, sourceId, reset ->
|
||||
ctx.json(Search.getFilterList(sourceId, reset))
|
||||
},
|
||||
withResults = {
|
||||
json<List<Search.FilterObject>>(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
private val json by DI.global.instance<Json>()
|
||||
|
||||
/** change filters of source with id `sourceId` */
|
||||
fun setFilters(ctx: Context) {
|
||||
val sourceId = ctx.pathParam("sourceId").toLong()
|
||||
val filterChange = try {
|
||||
json.decodeFromString<List<FilterChange>>(ctx.body())
|
||||
} catch (e: Exception) {
|
||||
listOf(json.decodeFromString<FilterChange>(ctx.body()))
|
||||
}
|
||||
val setFilters = handler(
|
||||
pathParam<Long>("sourceId"),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Source filters set")
|
||||
description("Change filters of source with id `sourceId`")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, sourceId ->
|
||||
val filterChange = try {
|
||||
json.decodeFromString<List<FilterChange>>(ctx.body())
|
||||
} catch (e: Exception) {
|
||||
listOf(json.decodeFromString<FilterChange>(ctx.body()))
|
||||
}
|
||||
|
||||
ctx.json(Search.setFilter(sourceId, filterChange))
|
||||
}
|
||||
ctx.json(Search.setFilter(sourceId, filterChange))
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
/** single source search */
|
||||
fun searchSingle(ctx: Context) {
|
||||
val sourceId = ctx.pathParam("sourceId").toLong()
|
||||
val searchTerm = ctx.queryParam("searchTerm") ?: ""
|
||||
val pageNum = ctx.queryParam("pageNum")?.toInt() ?: 1
|
||||
ctx.future(future { Search.sourceSearch(sourceId, searchTerm, pageNum) })
|
||||
}
|
||||
val searchSingle = handler(
|
||||
pathParam<Long>("sourceId"),
|
||||
queryParam("searchTerm", ""),
|
||||
queryParam("pageNum", 1),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Source search")
|
||||
description("Single source search")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, sourceId, searchTerm, pageNum ->
|
||||
ctx.future(future { Search.sourceSearch(sourceId, searchTerm, pageNum) })
|
||||
},
|
||||
withResults = {
|
||||
json<PagedMangaListDataClass>(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
/** all source search */
|
||||
fun searchAll(ctx: Context) { // TODO
|
||||
val searchTerm = ctx.pathParam("searchTerm")
|
||||
ctx.json(Search.sourceGlobalSearch(searchTerm))
|
||||
}
|
||||
val searchAll = handler(
|
||||
pathParam<String>("searchTerm"),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Source global search")
|
||||
description("All source search")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, searchTerm -> // TODO
|
||||
ctx.json(Search.sourceGlobalSearch(searchTerm))
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
package suwayomi.tachidesk.manga.controller
|
||||
|
||||
import io.javalin.http.Context
|
||||
import io.javalin.http.HttpCode
|
||||
import io.javalin.websocket.WsConfig
|
||||
import kotlinx.coroutines.runBlocking
|
||||
@@ -12,10 +11,15 @@ import suwayomi.tachidesk.manga.impl.Category
|
||||
import suwayomi.tachidesk.manga.impl.CategoryManga
|
||||
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.CategoryDataClass
|
||||
import suwayomi.tachidesk.manga.model.dataclass.MangaDataClass
|
||||
import suwayomi.tachidesk.manga.model.dataclass.PaginatedList
|
||||
import suwayomi.tachidesk.server.JavalinSetup.future
|
||||
import suwayomi.tachidesk.server.util.formParam
|
||||
import suwayomi.tachidesk.server.util.handler
|
||||
import suwayomi.tachidesk.server.util.pathParam
|
||||
import suwayomi.tachidesk.server.util.withOperation
|
||||
|
||||
/*
|
||||
@@ -29,35 +33,57 @@ object UpdateController {
|
||||
private val logger = KotlinLogging.logger { }
|
||||
|
||||
/** get recently updated manga chapters */
|
||||
fun recentChapters(ctx: Context) {
|
||||
val pageNum = ctx.pathParam("pageNum").toInt()
|
||||
|
||||
ctx.future(
|
||||
future {
|
||||
Chapter.getRecentChapters(pageNum)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
fun categoryUpdate(ctx: Context) {
|
||||
val categoryId = ctx.formParam("category")?.toIntOrNull()
|
||||
val categoriesForUpdate = ArrayList<CategoryDataClass>()
|
||||
if (categoryId == null) {
|
||||
logger.info { "Adding Library to Update Queue" }
|
||||
categoriesForUpdate.addAll(Category.getCategoryList())
|
||||
} else {
|
||||
val category = Category.getCategoryById(categoryId)
|
||||
if (category != null) {
|
||||
categoriesForUpdate.add(category)
|
||||
} else {
|
||||
logger.info { "No Category found" }
|
||||
ctx.status(HttpCode.BAD_REQUEST)
|
||||
return
|
||||
val recentChapters = handler(
|
||||
pathParam<Int>("pageNum"),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Updates fetch")
|
||||
description("Get recently updated manga chapters")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, pageNum ->
|
||||
ctx.future(
|
||||
future {
|
||||
Chapter.getRecentChapters(pageNum)
|
||||
}
|
||||
)
|
||||
},
|
||||
withResults = {
|
||||
json<PaginatedList<MangaDataClass>>(HttpCode.OK)
|
||||
}
|
||||
addCategoriesToUpdateQueue(categoriesForUpdate, true)
|
||||
ctx.status(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
val categoryUpdate = handler(
|
||||
formParam<Int?>("categoryId"),
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Updater start")
|
||||
description("Starts the updater")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx, categoryId ->
|
||||
val categoriesForUpdate = ArrayList<CategoryDataClass>()
|
||||
if (categoryId == null) {
|
||||
logger.info { "Adding Library to Update Queue" }
|
||||
categoriesForUpdate.addAll(Category.getCategoryList())
|
||||
} else {
|
||||
val category = Category.getCategoryById(categoryId)
|
||||
if (category != null) {
|
||||
categoriesForUpdate.add(category)
|
||||
} else {
|
||||
logger.info { "No Category found" }
|
||||
ctx.status(HttpCode.BAD_REQUEST)
|
||||
return@handler
|
||||
}
|
||||
}
|
||||
addCategoriesToUpdateQueue(categoriesForUpdate, true)
|
||||
ctx.status(HttpCode.OK)
|
||||
},
|
||||
withResults = {
|
||||
httpCode(HttpCode.OK)
|
||||
httpCode(HttpCode.BAD_REQUEST)
|
||||
}
|
||||
)
|
||||
|
||||
private fun addCategoriesToUpdateQueue(categories: List<CategoryDataClass>, clear: Boolean = false) {
|
||||
val updater by DI.global.instance<IUpdater>()
|
||||
@@ -84,15 +110,27 @@ object UpdateController {
|
||||
}
|
||||
}
|
||||
|
||||
fun updateSummary(ctx: Context) {
|
||||
val updater by DI.global.instance<IUpdater>()
|
||||
ctx.json(updater.getStatus().value.getJsonSummary())
|
||||
}
|
||||
val updateSummary = handler(
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Updater summary")
|
||||
description("Gets the latest updater summary")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
val updater by DI.global.instance<IUpdater>()
|
||||
ctx.json(updater.getStatus().value.getJsonSummary())
|
||||
},
|
||||
withResults = {
|
||||
json<UpdateStatus>(HttpCode.OK)
|
||||
}
|
||||
)
|
||||
|
||||
val reset = handler(
|
||||
documentWith = {
|
||||
withOperation {
|
||||
summary("Stops and resets the Updater")
|
||||
summary("Updater reset")
|
||||
description("Stops and resets the Updater")
|
||||
}
|
||||
},
|
||||
behaviorOf = { ctx ->
|
||||
|
||||
Reference in New Issue
Block a user