Files
Suwayomi-Server/server/src/main/kotlin/suwayomi/tachidesk/manga/MangaAPI.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

151 lines
6.3 KiB
Kotlin

package suwayomi.tachidesk.manga
/*
* 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 io.javalin.apibuilder.ApiBuilder.delete
import io.javalin.apibuilder.ApiBuilder.get
import io.javalin.apibuilder.ApiBuilder.head
import io.javalin.apibuilder.ApiBuilder.patch
import io.javalin.apibuilder.ApiBuilder.path
import io.javalin.apibuilder.ApiBuilder.post
import io.javalin.apibuilder.ApiBuilder.put
import io.javalin.apibuilder.ApiBuilder.ws
import suwayomi.tachidesk.manga.controller.BackupController
import suwayomi.tachidesk.manga.controller.CategoryController
import suwayomi.tachidesk.manga.controller.DownloadController
import suwayomi.tachidesk.manga.controller.ExtensionController
import suwayomi.tachidesk.manga.controller.MangaController
import suwayomi.tachidesk.manga.controller.SourceController
import suwayomi.tachidesk.manga.controller.TrackController
import suwayomi.tachidesk.manga.controller.UpdateController
object MangaAPI {
fun defineEndpoints() {
path("extension") {
get("list", ExtensionController.list)
get("install/{pkgName}", ExtensionController.install)
post("install", ExtensionController.installFile)
get("update/{pkgName}", ExtensionController.update)
get("uninstall/{pkgName}", ExtensionController.uninstall)
get("icon/{pkgName}", ExtensionController.icon)
}
path("source") {
get("list", SourceController.list)
get("{sourceId}", SourceController.retrieve)
get("{sourceId}/popular/{pageNum}", SourceController.popular)
get("{sourceId}/latest/{pageNum}", SourceController.latest)
get("{sourceId}/preferences", SourceController.getPreferences)
post("{sourceId}/preferences", SourceController.setPreference)
get("{sourceId}/filters", SourceController.getFilters)
post("{sourceId}/filters", SourceController.setFilters)
get("{sourceId}/search", SourceController.searchSingle)
post("{sourceId}/quick-search", SourceController.quickSearchSingle)
// get("all/search", SourceController.searchGlobal) // TODO
}
path("manga") {
get("{mangaId}", MangaController.retrieve)
get("{mangaId}/full", MangaController.retrieveFull)
get("{mangaId}/thumbnail", MangaController.thumbnail)
get("{mangaId}/category", MangaController.categoryList)
get("{mangaId}/category/{categoryId}", MangaController.addToCategory)
delete("{mangaId}/category/{categoryId}", MangaController.removeFromCategory)
get("{mangaId}/library", MangaController.addToLibrary)
delete("{mangaId}/library", MangaController.removeFromLibrary)
patch("{mangaId}/meta", MangaController.meta)
get("{mangaId}/chapters", MangaController.chapterList)
post("{mangaId}/chapter/batch", MangaController.chapterBatch)
get("{mangaId}/chapter/{chapterIndex}", MangaController.chapterRetrieve)
patch("{mangaId}/chapter/{chapterIndex}", MangaController.chapterModify)
put("{mangaId}/chapter/{chapterIndex}", MangaController.chapterModify)
delete("{mangaId}/chapter/{chapterIndex}", MangaController.chapterDelete)
patch("{mangaId}/chapter/{chapterIndex}/meta", MangaController.chapterMeta)
get("{mangaId}/chapter/{chapterIndex}/page/{index}", MangaController.pageRetrieve)
}
path("chapter") {
post("batch", MangaController.anyChapterBatch)
get("{chapterId}/download", MangaController.downloadChapter)
head("{chapterId}/download", MangaController.downloadChapter)
}
path("category") {
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)
get("{categoryId}", CategoryController.categoryMangas)
patch("{categoryId}", CategoryController.categoryModify)
delete("{categoryId}", CategoryController.categoryDelete)
patch("{categoryId}/meta", CategoryController.meta)
}
path("backup") {
post("import", BackupController.protobufImport)
post("import/file", BackupController.protobufImportFile)
post("validate", BackupController.protobufValidate)
post("validate/file", BackupController.protobufValidateFile)
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.clear)
}
path("download") {
get("{mangaId}/chapter/{chapterIndex}", DownloadController.queueChapter)
delete("{mangaId}/chapter/{chapterIndex}", DownloadController.unqueueChapter)
patch("{mangaId}/chapter/{chapterIndex}/reorder/{to}", DownloadController.reorderChapter)
post("batch", DownloadController.queueChapters)
delete("batch", DownloadController.unqueueChapters)
}
path("update") {
get("recentChapters/{pageNum}", UpdateController.recentChapters)
post("fetch", UpdateController.categoryUpdate)
post("reset", UpdateController.reset)
get("summary", UpdateController.updateSummary)
ws("", UpdateController::categoryUpdateWS)
}
path("track") {
get("list", TrackController.list)
post("login", TrackController.login)
post("logout", TrackController.logout)
post("search", TrackController.search)
post("bind", TrackController.bind)
post("update", TrackController.update)
get("{trackerId}/thumbnail", TrackController.thumbnail)
}
}
}