From fa935c0e98a9871cbc15b19d2c543449e6e8f873 Mon Sep 17 00:00:00 2001 From: Omur Sahin Date: Sat, 12 Sep 2026 11:57:56 +0300 Subject: [PATCH 1/2] komga drivers --- .gitignore | 4 + README.md | 4 +- auth/komga-auth.yaml | 17 + .../komga/komga-database.sqlite | Bin 0 -> 593920 bytes dockerfiles/komga.dockerfile | 18 + dockerfiles/komga.yaml | 30 + experiments/bb-exp.py | 1 + experiments/wb-exp.py | 1 + jacoco.dockerfile | 1 + .../cs/rest/komga/komga/build.gradle.kts | 55 +- .../em/embedded/rest/komga/build.gradle.kts | 26 + .../komga/EmbeddedEvoMasterController.java | 221 + .../em/external/rest/komga/build.gradle.kts | 51 + .../komga/ExternalEvoMasterController.java | 268 + jdk_17_gradle/gradle.properties | 2 + jdk_17_gradle/gradle/libs.versions.toml | 9 + .../gradle/wrapper/gradle-wrapper.properties | 2 +- jdk_17_gradle/settings.gradle.kts | 6 + openapi/komga.json | 14681 ++++++++++++++++ scripts/build/docker-compose.build.yml | 2 + scripts/dist-wb.py | 3 + scripts/dockerize/data/sut.csv | 1 + statistics/data.csv | 1 + statistics/table_emb.md | 1 + 24 files changed, 15387 insertions(+), 18 deletions(-) create mode 100644 auth/komga-auth.yaml create mode 100644 dockerfiles/additional_files/komga/komga-database.sqlite create mode 100644 dockerfiles/komga.dockerfile create mode 100644 dockerfiles/komga.yaml create mode 100644 jdk_17_gradle/em/embedded/rest/komga/build.gradle.kts create mode 100644 jdk_17_gradle/em/embedded/rest/komga/src/main/java/em/embedded/komga/EmbeddedEvoMasterController.java create mode 100644 jdk_17_gradle/em/external/rest/komga/build.gradle.kts create mode 100644 jdk_17_gradle/em/external/rest/komga/src/main/java/em/external/komga/ExternalEvoMasterController.java create mode 100644 jdk_17_gradle/gradle.properties create mode 100644 openapi/komga.json diff --git a/.gitignore b/.gitignore index 01d903295..5b7adffdc 100644 --- a/.gitignore +++ b/.gitignore @@ -287,6 +287,10 @@ jdk_17_maven/em/embedded/rest/familie-ba-sak/target/ /jdk_17_gradle/build/ /jdk_17_gradle/em/embedded/rest/bibliothek/build/ /jdk_17_gradle/em/external/rest/bibliothek/build/ +/jdk_17_gradle/.kotlin/ +/jdk_17_gradle/tmp/ +/jdk_17_gradle/em/embedded/rest/komga/build/ +/jdk_17_gradle/em/external/rest/komga/build/ /jdk_17_maven/cs/grpc/signal-registration/target/ /jdk_17_maven/em/embedded/grpc/signal-registration/target/ /jdk_17_maven/em/external/grpc/signal-registration/target/ diff --git a/README.md b/README.md index 1eee0d7a7..671061eb0 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ How to setup authentication information, based on the current content of the ini Auth configuration files can found in the [auth](auth) folder. -### REST: Java/Kotlin (43) +### REST: Java/Kotlin (44) * **AdoptMe** (not-known license), [jdk_21_maven/cs/rest/adoptme](jdk_21_maven/cs/rest/adoptme), from [https://github.com/daanimelian/Programacion3-TPO](https://github.com/daanimelian/Programacion3-TPO) @@ -117,6 +117,8 @@ Auth configuration files can found in the [auth](auth) folder. * **JoinUs** (not-known license), [jdk_21_maven/cs/rest/joinus](jdk_21_maven/cs/rest/joinus), from [https://github.com/KLAJDI16/joinUs](https://github.com/KLAJDI16/joinUs) +* **Komga** (MIT), [jdk_17_gradle/cs/rest/komga](jdk_17_gradle/cs/rest/komga), from [https://github.com/gotson/komga](https://github.com/gotson/komga) + * **Languagetool** (LGPL), [jdk_8_maven/cs/rest/original/languagetool](jdk_8_maven/cs/rest/original/languagetool), from [https://github.com/languagetool-org/languagetool](https://github.com/languagetool-org/languagetool) * **LoveMining** (not-known license), [jdk_21_maven/cs/rest/lovemining](jdk_21_maven/cs/rest/lovemining), from [https://github.com/Andryd22/LoveMining](https://github.com/Andryd22/LoveMining) diff --git a/auth/komga-auth.yaml b/auth/komga-auth.yaml new file mode 100644 index 000000000..12d8f829b --- /dev/null +++ b/auth/komga-auth.yaml @@ -0,0 +1,17 @@ +auth: + - name: wfd_admin1 + fixedHeaders: + - name: Authorization + value: Basic d2ZkX2FkbWluMUB3ZmQuaW52YWxpZDpXZmQtQWRtaW4tUGFzczE= + - name: wfd_admin2 + fixedHeaders: + - name: Authorization + value: Basic d2ZkX2FkbWluMkB3ZmQuaW52YWxpZDpXZmQtQWRtaW4tUGFzczI= + - name: wfd_user1 + fixedHeaders: + - name: Authorization + value: Basic d2ZkX3VzZXIxQHdmZC5pbnZhbGlkOldmZC1Vc2VyLVBhc3Mx + - name: wfd_user2 + fixedHeaders: + - name: Authorization + value: Basic d2ZkX3VzZXIyQHdmZC5pbnZhbGlkOldmZC1Vc2VyLVBhc3My diff --git a/dockerfiles/additional_files/komga/komga-database.sqlite b/dockerfiles/additional_files/komga/komga-database.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..daff9c85a2960dd6391998c1eaebda9af1afb1cb GIT binary patch literal 593920 zcmeFa3w&GGedkH=1%eU*+q4YJvaBoFGRcUN@Fpo)wl9H85+WWHa6yT3-5Zd+6cK>{ z1%P_kaZ<>SJes!Yr_*NB?ab7j-DyABrmx*klXSW>={sq2oIgKlgos3sQD$QRV(1`4G70fBygf`JVszpL6a7<@|+IsUdS~)!Ig}!G*i->+0_A zdY0q5y1IJkzwf92w3q84def_aqMt6y`%Z6rx=wxY!9J=T@O_!de82A>eBbna-S-#1 z|J(P6zOSkmJ2l325V$)8&JFhaFPw07l`5<9&HA-6O$n*E)u<|;rM!?!3VA6lhPtxEiJ-MzEjHvvX+t(!C4?EikP^9gA(s;} zq9i8MLSE$43#yJ3pBJTcHj$i33Yw-jtYapb5+s`OW}U9}+rrRELJLZzN~Nj;)nieM9h1DXfF)wN zQBB>r-enrFF;$O^lO|?^#I7lX9OU&LleW%WXZ!p8&qX_NRZQx7G;&hV>8krf`1HPbvjv4K1 z#gnwMXXq?XzN;b>-qZsl9kg|FWG0!*izDM)A;T~7$rRg1sEfau0@_!rIp#N8qPOW~ zqqZfFbBg2wKf9eI(c?3GYUwgrrij`JpVR1To#hu6giJzO%%%$4MJ8#;W`z7)R?L&d z9L>Be?Sb?(p=^xw>8`HMN*u?hFKrK;&5(t}%+5k=`t2;0%urk`@+s3Xeb=TtHzLs3 zE=jRD8b1Z}Jnatn1dX?zg4)JAFm|%H-_IZFv~KB3R#1D>_wu^S?Vp%%y;fCLr?v8} z8^v2vePvzVC`#+4dZSvq<#@5%wsIYFlsU$!d(~s53T-&bWqDPq6)RVdanyG+0k*AN z$F9q@dZ}7D#x2rJrftb+G@z~f$5!R~O0BfnuvLcwfiXj$n!t}WZf(k@f>67Fs>c)w z1{|~yhn1`KtqsLxO|#jVXcs z@wqd{(`Syajf{^}sy9Z)^v=sS<&`bgb%`~wW7M3hZ>_Az_4+Zkdrb+HbMz1y97}fh z`=6ia6dASwq;pf_78TE}QZc(gMeH0EqbI3&grj2UK`QnSu(Nr$@0(P1eVCoihdw=& z-T&qN3;VvduRi#vgBybndVbvV-|j0n|;0e*gn_T*VfG%_|E+I2 z+6zrI-5lAQ9ll2P20WZ$FBqH*M=3L0F-k@9#mYh8aH@!#5ll1Tnh5HfJlh9OfA{-5e>T<0l*G*p5Se&BHpZx>5kGybx~=<{CVoPbKh|ECpgtzdCV9Im*+9fpNU`~6o>>n2Ear} zlaL%o-Y0$Jea`kG-5ZAudmhhW&0Z`R2~0$%Rw(Lf+-6N)lWTHiMYi-;laM4uMlxks z|6U1y?WY{=1!&|SHAdd!c~rF*j0L0NsbHX7TCP!maixvTYOTR-+$z(p0DWLhT`fuuAr&@)f|;qzZ&W7;0`fv|Ll962(aR6_oc>PR3KjD

sYb0>U+0!f71O9* zB}q!9M3v0Isnsw1xwC=5i;s{2bw&?(9#IU$LeXF}8Vkkf-paaMX_Qvfz%H&dO4myb zb7~oa61xp!5tVdNW?Z=asqb2)4nd}d%o&+Z- zwM+&h_0p=mLZiIG?kQ|-8oXn=0L>^>MAAfEB&oO5l$^DqN->k~o&WHcoJ~fm2gu~<;Uy(d4`?Q1!5}RRQEdPnQc^Uei5MwK zHOcZ8Gw2_?y5VdvaPdJh=pW{lK0c@!q@^eniUbtzE#1;CYu#dszxdF5zV4`aBKF)c zDLynTD2j(w#Wc>5Xe2bTR=Ua2fJSKP{CT|u?HICLrxx%(*W+X&)Q8THi!jdV>9C-aBpKZ($@9b=$;|E&05VIxcoO9OEqoTIvAb0>LmyC9O5ORKwyeeaxfYT1j^MLv`jT> zr46=2(8tswKvbCsW$w}j+Y>00{9|7`JmzdHdU1%1sT08C8B&Z*vPm9}g(j>MAP_Jv zTPDC~*8liJgWy_8F0ayc(wY?Ed z3??ZtNh!<#epLGMPdl29O!YL~`)Ea&I?(JO1@YCW{wf}pv?8h3Ch zw zt{Fj-dX>4uRbuDKkG;fp4DEp$4mA4)$bv9jRr1h)W`TT;PEw@WH#p_$3hgIp^lnsZ zSIs^KHEA;$X!{#QUee@QPraY%`+Y}0La{A3xe*W-vhO{Zuey>S~)!K~2PF(40s=x{!F$*z`H|3r2KI=W>jd)LaN4>|qk9r^S-sc_k z_745Gp}!sa>!H6G`eSk%FAx9$5C8!X009sH0T2KI5C8#SmC-0GBN0}H!>kO2SQ!kmG7w

C>z{b&8cIPqK1+oRud|u<{-6 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%0DJzw-!;%RR317#_=&*}4gB4}XWZZI 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 literal 0 HcmV?d00001 diff --git a/dockerfiles/komga.dockerfile b/dockerfiles/komga.dockerfile new file mode 100644 index 000000000..9698a547a --- /dev/null +++ b/dockerfiles/komga.dockerfile @@ -0,0 +1,18 @@ +FROM amazoncorretto:17-alpine-jdk + +COPY ./dist/komga-sut.jar . +COPY ./dist/jacocoagent.jar . + + + + +COPY ./dockerfiles/additional_files/komga/komga-database.sqlite . + + + + +ENTRYPOINT \ + java \ + -javaagent:jacocoagent.jar=output=tcpserver,address=*,port=6300,append=false,dumponexit=false \ + -jar komga-sut.jar \ + --server.port=8080 --komga.config-dir=/tmp/komga --komga.database.file=/komga-database.sqlite \ No newline at end of file diff --git a/dockerfiles/komga.yaml b/dockerfiles/komga.yaml new file mode 100644 index 000000000..48daabc09 --- /dev/null +++ b/dockerfiles/komga.yaml @@ -0,0 +1,30 @@ +services: + mitmproxy: + image: mitmproxy/mitmproxy:10.2.4 + user: "0:0" + environment: + MITM_LOG_DIR: /custom-logs + MITM_LOG_FILE: ${MITM_LOG_FILE:-minlog.csv} + command: > + mitmdump + --mode reverse:http://sut-komga:8080 + --listen-host 0.0.0.0 + --listen-port 8080 + --set keep_host_header=true + -s /addons/minlog.py + volumes: + - ${HOST_LOG_DIR:-./mitm-logs}:/custom-logs + - ./addons:/addons:ro + ports: + - "${HOST_PORT:-8080}:8080" + depends_on: + - sut-komga + sut-komga: + image: webfuzzing/wfd-komga:FINAL +# build: +# dockerfile: ./dockerfiles/komga.dockerfile +# context: .. + environment: + AUTH_PORT: ${AUTH_PORT:-8081} + ports: + - "${JACOCO_PORT:-6300}:6300" \ No newline at end of file diff --git a/experiments/bb-exp.py b/experiments/bb-exp.py index 00f2f5eba..da8fb838f 100644 --- a/experiments/bb-exp.py +++ b/experiments/bb-exp.py @@ -94,6 +94,7 @@ def __init__(self, name, auth, sleep, schemaformat, classfiles): Sut("gestaohospital",False,SLEEP,JSON,["jdk_8_maven/cs/rest-gui/gestaohospital/target/classes"]), Sut("http-patch-spring",False,SLEEP,JSON,["jdk_11_maven/cs/rest/http-patch-spring/target/classes"]), Sut("joinus",True,SLEEP,JSON,["jdk_21_maven/cs/rest/joinus/target/classes"]), + Sut("komga",True,SLEEP,JSON,["jdk_17_gradle/cs/rest/komga/komga/build/classes"]), Sut("languagetool",False,SLEEP,JSON,["jdk_8_maven/cs/rest/original/languagetool/languagetool-core/target/classes", "jdk_8_maven/cs/rest/original/languagetool/languagetool-gui-commons/target/classes", "jdk_8_maven/cs/rest/original/languagetool/languagetool-language-modules/all/target/classes", diff --git a/experiments/wb-exp.py b/experiments/wb-exp.py index 36f8be7d8..a5bd1002d 100644 --- a/experiments/wb-exp.py +++ b/experiments/wb-exp.py @@ -197,6 +197,7 @@ def __init__(self, name, platform): Sut("http-patch-spring", JDK_11), Sut("jasper", JDK_25), Sut("joinus", JDK_21), + Sut("komga", JDK_17), Sut("languagetool", JDK_8), Sut("lovemining", JDK_21), Sut("market", JDK_11), diff --git a/jacoco.dockerfile b/jacoco.dockerfile index ff880c7ac..b818f8fcb 100644 --- a/jacoco.dockerfile +++ b/jacoco.dockerfile @@ -30,6 +30,7 @@ COPY jdk_8_maven/cs/rest-gui/genome-nexus/web/target/classes ${CLASS_FILES}/jdk COPY jdk_8_maven/cs/rest-gui/gestaohospital/target/classes ${CLASS_FILES}/jdk_8_maven/cs/rest-gui/gestaohospital/target/classes COPY jdk_11_maven/cs/rest/http-patch-spring/target/classes ${CLASS_FILES}/jdk_11_maven/cs/rest/http-patch-spring/target/classes COPY jdk_21_maven/cs/rest/joinus/target/classes ${CLASS_FILES}/jdk_21_maven/cs/rest/joinus/target/classes +COPY jdk_17_gradle/cs/rest/komga/komga/build/classes ${CLASS_FILES}/jdk_17_gradle/cs/rest/komga/komga/build/classes COPY jdk_8_maven/cs/rest/original/languagetool/languagetool-core/target/classes ${CLASS_FILES}/jdk_8_maven/cs/rest/original/languagetool/languagetool-core/target/classes COPY jdk_8_maven/cs/rest/original/languagetool/languagetool-gui-commons/target/classes ${CLASS_FILES}/jdk_8_maven/cs/rest/original/languagetool/languagetool-gui-commons/target/classes COPY jdk_8_maven/cs/rest/original/languagetool/languagetool-language-modules/all/target/classes ${CLASS_FILES}/jdk_8_maven/cs/rest/original/languagetool/languagetool-language-modules/all/target/classes diff --git a/jdk_17_gradle/cs/rest/komga/komga/build.gradle.kts b/jdk_17_gradle/cs/rest/komga/komga/build.gradle.kts index 5a0fae29c..153f6478f 100644 --- a/jdk_17_gradle/cs/rest/komga/komga/build.gradle.kts +++ b/jdk_17_gradle/cs/rest/komga/komga/build.gradle.kts @@ -5,12 +5,18 @@ import org.jetbrains.kotlin.util.prefixIfNot import org.springframework.boot.gradle.plugin.SpringBootPlugin plugins { - kotlin("jvm") - kotlin("plugin.spring") - kotlin("kapt") + // MODIFIED: versions come from komga's own root build, which WFD does not use + run { + val kotlinVersion = "2.4.10" + kotlin("jvm") version kotlinVersion + kotlin("plugin.spring") version kotlinVersion + kotlin("kapt") version kotlinVersion + } id("org.springframework.boot") version libs.versions.springboot.get() alias(libs.plugins.gradleGitProperties) - id("nu.studer.jooq") version "10.2.1" + // MODIFIED: 10.2.1 needs Gradle >= 8.6 and a JDK 21 Gradle JVM, this level is 8.5 / JDK 17. + // jOOQ codegen stays 3.19.35, only the "this-escape" SuppressWarnings hint differs + id("nu.studer.jooq") version "9.0" id("org.flywaydb.flyway") version "13.1.0" id("com.github.johnrengelman.processes") version "0.5.0" id("org.springdoc.openapi-gradle-plugin") version "1.9.0" @@ -18,6 +24,14 @@ plugins { jacoco } +// MODIFIED: set by komga's own root build, which WFD does not use +group = "org.gotson" +version = "1.26.3" + +repositories { + mavenCentral() +} + val benchmarkSourceSet = sourceSets.create("benchmark") { java { @@ -181,6 +195,12 @@ tasks { enabled = true } + // MODIFIED: WFD expects a single self-contained jar named komga-sut.jar + bootJar { + archiveVersion.set("") + archiveClassifier.set("sut") + } + register("webuiCopyDist") { description = "Copies the WebUI build into resources/public" group = "web" @@ -251,7 +271,8 @@ springBoot { excludes = setOf("time") properties { // but rerun if the gradle.properties file changed - inputs.file("$rootDir/gradle.properties") + // MODIFIED: rootDir is the WFD level here, komga's own root is one folder up + inputs.file("$projectDir/../gradle.properties") } } } @@ -376,12 +397,13 @@ tasks.whenTaskAdded { } } -tasks.runKtlintFormatOverMainSourceSet { - dependsOn("generateTasksJooq") -} -tasks.runKtlintCheckOverMainSourceSet { - dependsOn("generateTasksJooq") -} +// MODIFIED: ktlint is applied by komga's own root build, which WFD does not use +// tasks.runKtlintFormatOverMainSourceSet { +// dependsOn("generateTasksJooq") +// } +// tasks.runKtlintCheckOverMainSourceSet { +// dependsOn("generateTasksJooq") +// } tasks.compileKotlin { dependsOn("generateTasksJooq") } @@ -399,11 +421,12 @@ tasks.jacocoTestReport { dependsOn(tasks.test) } -configure { - filter { - exclude("**/db/migration/**") - } -} +// MODIFIED: ktlint is applied by komga's own root build, which WFD does not use +// configure { +// filter { +// exclude("**/db/migration/**") +// } +// } project.afterEvaluate { tasks.named("forkedSpringBootRun") { diff --git a/jdk_17_gradle/em/embedded/rest/komga/build.gradle.kts b/jdk_17_gradle/em/embedded/rest/komga/build.gradle.kts new file mode 100644 index 000000000..efdd28cd2 --- /dev/null +++ b/jdk_17_gradle/em/embedded/rest/komga/build.gradle.kts @@ -0,0 +1,26 @@ + +repositories { + mavenLocal() + mavenCentral() +} + + +plugins { + `java-library` +} + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + +val EVOMASTER_VERSION = project.ext.get("EVOMASTER_VERSION") + +dependencies{ + implementation("org.evomaster:evomaster-client-java-controller:$EVOMASTER_VERSION") + implementation("org.evomaster:evomaster-client-java-dependencies:$EVOMASTER_VERSION"){ + exclude("com.github.tomakehurst") + } + + api(project(":cs:rest:komga")) +} diff --git a/jdk_17_gradle/em/embedded/rest/komga/src/main/java/em/embedded/komga/EmbeddedEvoMasterController.java b/jdk_17_gradle/em/embedded/rest/komga/src/main/java/em/embedded/komga/EmbeddedEvoMasterController.java new file mode 100644 index 000000000..59bd87384 --- /dev/null +++ b/jdk_17_gradle/em/embedded/rest/komga/src/main/java/em/embedded/komga/EmbeddedEvoMasterController.java @@ -0,0 +1,221 @@ +package em.embedded.komga; + +import org.evomaster.client.java.controller.AuthUtils; +import org.evomaster.client.java.controller.EmbeddedSutController; +import org.evomaster.client.java.controller.InstrumentedSutStarter; +import org.evomaster.client.java.controller.api.dto.SutInfoDto; +import org.evomaster.client.java.controller.api.dto.auth.AuthenticationDto; +import org.evomaster.client.java.controller.problem.ProblemInfo; +import org.evomaster.client.java.controller.problem.RestProblem; +import org.evomaster.client.java.sql.DbSpecification; +import org.gotson.komga.Application; +import org.springframework.boot.SpringApplication; +import org.springframework.context.ConfigurableApplicationContext; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; +import java.time.Duration; +import java.util.Base64; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import java.util.stream.Stream; + + +/** + * Class used to start/stop the SUT. + */ +public class EmbeddedEvoMasterController extends EmbeddedSutController { + + public static void main(String[] args) { + + int port = 40100; + if (args.length > 0) { + port = Integer.parseInt(args[0]); + } + + EmbeddedEvoMasterController controller = new EmbeddedEvoMasterController(port); + InstrumentedSutStarter starter = new InstrumentedSutStarter(controller); + + starter.start(); + } + + private static final String[][] SEEDED_USERS = { + {"wfd_admin1@wfd.invalid", "Wfd-Admin-Pass1", "[\"ADMIN\",\"FILE_DOWNLOAD\",\"PAGE_STREAMING\",\"KOBO_SYNC\",\"KOREADER_SYNC\"]"}, + {"wfd_admin2@wfd.invalid", "Wfd-Admin-Pass2", "[\"ADMIN\",\"FILE_DOWNLOAD\",\"PAGE_STREAMING\",\"KOBO_SYNC\",\"KOREADER_SYNC\"]"}, + {"wfd_user1@wfd.invalid", "Wfd-User-Pass1", "[\"FILE_DOWNLOAD\",\"PAGE_STREAMING\",\"KOBO_SYNC\",\"KOREADER_SYNC\"]"}, + {"wfd_user2@wfd.invalid", "Wfd-User-Pass2", "[\"FILE_DOWNLOAD\",\"PAGE_STREAMING\",\"KOBO_SYNC\",\"KOREADER_SYNC\"]"} + }; + + private static final Path CONFIG_DIR = Paths.get("tmp", "komga", "embedded").toAbsolutePath(); + + /** live database file -> snapshot taken right after seeding */ + private static final List DATABASES = List.of("database.sqlite", "tasks.sqlite"); + + private ConfigurableApplicationContext ctx; + + private final HttpClient http = HttpClient.newBuilder() + .connectTimeout(Duration.ofSeconds(10)) + .build(); + + public EmbeddedEvoMasterController() { + this(0); + } + + public EmbeddedEvoMasterController(int port) { + setControllerPort(port); + } + + + @Override + public String startSut() { + + // a fresh config dir means a fresh SQLite database, with no user in it + deleteRecursively(CONFIG_DIR); + + // same as what Komga's own main() does before starting Spring + System.setProperty("org.jooq.no-logo", "true"); + System.setProperty("org.jooq.no-tips", "true"); + + ctx = SpringApplication.run(Application.class, + new String[]{"--server.port=0", + "--komga.config-dir=" + CONFIG_DIR, + // Logback holds this file open, it must sit outside the wiped config dir + "--logging.file.name=" + CONFIG_DIR.getParent().resolve("embedded.log") + }); + + seedUsers(); + eachDatabase("backup to"); + + return "http://localhost:" + getSutPort(); + } + + protected int getSutPort() { + return (Integer) ((Map) ctx.getEnvironment() + .getPropertySources().get("server.ports").getSource()) + .get("local.server.port"); + } + + + @Override + public boolean isSutRunning() { + return ctx != null && ctx.isRunning(); + } + + @Override + public void stopSut() { + ctx.stop(); + ctx.close(); + } + + @Override + public String getPackagePrefixesToCover() { + return "org.gotson.komga."; + } + + @Override + public void resetStateOfSUT() { + eachDatabase("restore from"); + } + + @Override + public List getDbSpecifications() { + return null; + } + + @Override + public List getInfoForAuthentication() { + return Stream.of(SEEDED_USERS) + .map(u -> AuthUtils.getForBasic(u[0], u[0], u[1])) + .collect(Collectors.toList()); + } + + @Override + public ProblemInfo getProblemInfo() { + return new RestProblem( + "http://localhost:" + getSutPort() + "/v3/api-docs", + null + ); + } + + @Override + public SutInfoDto.OutputFormat getPreferredOutputFormat() { + return SutInfoDto.OutputFormat.JAVA_JUNIT_5; + } + + + private void seedUsers() { + String baseUrl = "http://localhost:" + getSutPort(); + + send(HttpRequest.newBuilder(URI.create(baseUrl + "/api/v1/claim")) + .header("X-Komga-Email", SEEDED_USERS[0][0]) + .header("X-Komga-Password", SEEDED_USERS[0][1]) + .POST(HttpRequest.BodyPublishers.noBody())); + + String admin = "Basic " + Base64.getEncoder().encodeToString( + (SEEDED_USERS[0][0] + ":" + SEEDED_USERS[0][1]).getBytes()); + + for (int i = 1; i < SEEDED_USERS.length; i++) { + String body = "{\"email\":\"" + SEEDED_USERS[i][0] + "\",\"password\":\"" + SEEDED_USERS[i][1] + + "\",\"roles\":" + SEEDED_USERS[i][2] + "}"; + send(HttpRequest.newBuilder(URI.create(baseUrl + "/api/v2/users")) + .header("Authorization", admin) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(body))); + } + } + + private void send(HttpRequest.Builder builder) { + try { + HttpResponse response = http.send(builder.timeout(Duration.ofSeconds(30)).build(), + HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() >= 300) { + throw new IllegalStateException("Failed to seed users: " + response.statusCode() + " " + response.body()); + } + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); + } + } + + /** sqlite-jdbc extension over SQLite's Online Backup API: safe while the SUT is connected */ + private void eachDatabase(String command) { + for (String db : DATABASES) { + Path live = CONFIG_DIR.resolve(db); + try (Connection connection = DriverManager.getConnection( + "jdbc:sqlite:" + live + "?busy_timeout=30000"); + Statement statement = connection.createStatement()) { + statement.executeUpdate(command + " '" + live + ".seed'"); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + } + + private void deleteRecursively(Path root) { + if (!Files.exists(root)) { + return; + } + try (Stream paths = Files.walk(root)) { + paths.sorted(Comparator.reverseOrder()).forEach(p -> { + try { + Files.delete(p); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/jdk_17_gradle/em/external/rest/komga/build.gradle.kts b/jdk_17_gradle/em/external/rest/komga/build.gradle.kts new file mode 100644 index 000000000..e2aa80645 --- /dev/null +++ b/jdk_17_gradle/em/external/rest/komga/build.gradle.kts @@ -0,0 +1,51 @@ + +repositories { + mavenLocal() + mavenCentral() +} + + +plugins { + `java-library` + id("com.gradleup.shadow") version "8.3.8" +} + +java { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 +} + + +val EVOMASTER_VERSION = project.ext.get("EVOMASTER_VERSION") + +dependencies{ + implementation("org.evomaster:evomaster-client-java-controller:$EVOMASTER_VERSION") + implementation("org.evomaster:evomaster-client-java-instrumentation:$EVOMASTER_VERSION") + runtimeOnly("org.xerial:sqlite-jdbc:${libs.versions.sqliteJdbc.get()}") +} + + +tasks.shadowJar { + archiveBaseName.set("${project.name}-evomaster-runner") + archiveClassifier.set("") + archiveVersion.set("") + isZip64 = true + manifest { + attributes["Implementation-Title"] = "EM" + attributes["Implementation-Version"] = "1.0" + attributes["Main-Class"] = "em.external.komga.ExternalEvoMasterController" + attributes["Premain-Class"] = "org.evomaster.client.java.instrumentation.InstrumentingAgent" + attributes["Agent-Class"] = "org.evomaster.client.java.instrumentation.InstrumentingAgent" + attributes["Can-Redefine-Classes"] = "true" + attributes["Can-Retransform-Classes"] = "true" + } + relocate("org.slf4j", "shaded.emb.org.slf4j") + relocate("com.fasterxml.jackson", "shaded.emb.com.fasterxml.jackson") + mergeServiceFiles() +} + +tasks { + "build" { + dependsOn(shadowJar) + } +} diff --git a/jdk_17_gradle/em/external/rest/komga/src/main/java/em/external/komga/ExternalEvoMasterController.java b/jdk_17_gradle/em/external/rest/komga/src/main/java/em/external/komga/ExternalEvoMasterController.java new file mode 100644 index 000000000..1dc9a0aa3 --- /dev/null +++ b/jdk_17_gradle/em/external/rest/komga/src/main/java/em/external/komga/ExternalEvoMasterController.java @@ -0,0 +1,268 @@ +package em.external.komga; + +import org.evomaster.client.java.controller.AuthUtils; +import org.evomaster.client.java.controller.ExternalSutController; +import org.evomaster.client.java.controller.InstrumentedSutStarter; +import org.evomaster.client.java.controller.api.dto.SutInfoDto; +import org.evomaster.client.java.controller.api.dto.auth.AuthenticationDto; +import org.evomaster.client.java.controller.problem.ProblemInfo; +import org.evomaster.client.java.controller.problem.RestProblem; +import org.evomaster.client.java.sql.DbSpecification; + +import java.io.IOException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import java.sql.Statement; +import java.time.Duration; +import java.util.Base64; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class ExternalEvoMasterController extends ExternalSutController { + + + public static void main(String[] args) { + + int controllerPort = 40100; + if (args.length > 0) { + controllerPort = Integer.parseInt(args[0]); + } + int sutPort = 12345; + if (args.length > 1) { + sutPort = Integer.parseInt(args[1]); + } + String jarLocation = "cs/rest/komga/komga/build/libs"; + if (args.length > 2) { + jarLocation = args[2]; + } + if(! jarLocation.endsWith(".jar")) { + jarLocation += "/komga-sut.jar"; + } + + int timeoutSeconds = 120; + if(args.length > 3){ + timeoutSeconds = Integer.parseInt(args[3]); + } + String command = "java"; + if(args.length > 4){ + command = args[4]; + } + + + ExternalEvoMasterController controller = + new ExternalEvoMasterController(controllerPort, jarLocation, + sutPort, timeoutSeconds, command); + controller.setNeedsJdk17Options(true); + InstrumentedSutStarter starter = new InstrumentedSutStarter(controller); + + starter.start(); + } + + private static final String[][] SEEDED_USERS = { + {"wfd_admin1@wfd.invalid", "Wfd-Admin-Pass1", "[\"ADMIN\",\"FILE_DOWNLOAD\",\"PAGE_STREAMING\",\"KOBO_SYNC\",\"KOREADER_SYNC\"]"}, + {"wfd_admin2@wfd.invalid", "Wfd-Admin-Pass2", "[\"ADMIN\",\"FILE_DOWNLOAD\",\"PAGE_STREAMING\",\"KOBO_SYNC\",\"KOREADER_SYNC\"]"}, + {"wfd_user1@wfd.invalid", "Wfd-User-Pass1", "[\"FILE_DOWNLOAD\",\"PAGE_STREAMING\",\"KOBO_SYNC\",\"KOREADER_SYNC\"]"}, + {"wfd_user2@wfd.invalid", "Wfd-User-Pass2", "[\"FILE_DOWNLOAD\",\"PAGE_STREAMING\",\"KOBO_SYNC\",\"KOREADER_SYNC\"]"} + }; + + private final int timeoutSeconds; + private final int sutPort; + private String jarLocation; + + private final Path configDir; + + /** live database file -> snapshot taken right after seeding */ + private static final List DATABASES = List.of("database.sqlite", "tasks.sqlite"); + + private final HttpClient http = HttpClient.newBuilder() + .connectTimeout(Duration.ofSeconds(10)) + .build(); + + + public ExternalEvoMasterController(){ + this(40100, "../core/target", 12345, 120, "java"); + } + + public ExternalEvoMasterController(String jarLocation) { + this(); + this.jarLocation = jarLocation; + } + + public ExternalEvoMasterController( + int controllerPort, String jarLocation, int sutPort, int timeoutSeconds, String command + ) { + + if(jarLocation==null || jarLocation.isEmpty()){ + throw new IllegalArgumentException("Missing jar location"); + } + + this.sutPort = sutPort; + this.jarLocation = jarLocation; + this.timeoutSeconds = timeoutSeconds; + this.configDir = Paths.get("tmp", "komga", "p" + sutPort).toAbsolutePath(); + setControllerPort(controllerPort); + setJavaCommand(command); + } + + + @Override + public String[] getInputParameters() { + return new String[]{ + "--server.port=" + sutPort, + "--komga.config-dir=" + configDir + }; + } + + public String[] getJVMParameters() { + return new String[]{}; + } + + @Override + public String getBaseURL() { + return "http://localhost:" + sutPort; + } + + @Override + public String getPathToExecutableJar() { + return jarLocation; + } + + @Override + public String getLogMessageOfInitializedServer() { + return "Started ApplicationKt in"; + } + + @Override + public long getMaxAwaitForInitializationInSeconds() { + return timeoutSeconds; + } + + @Override + public void preStart() { + // a fresh config dir means a fresh SQLite database, with no user in it + deleteRecursively(configDir); + } + + @Override + public void postStart() { + seedUsers(); + eachDatabase("backup to"); + } + + @Override + public void resetStateOfSUT() { + eachDatabase("restore from"); + } + + @Override + public void preStop() { + } + + @Override + public void postStop() { + } + + + @Override + public String getPackagePrefixesToCover() { + return "org.gotson.komga."; + } + + @Override + public ProblemInfo getProblemInfo() { + return new RestProblem( + getBaseURL() + "/v3/api-docs", + null + ); + } + + @Override + public SutInfoDto.OutputFormat getPreferredOutputFormat() { + return SutInfoDto.OutputFormat.JAVA_JUNIT_5; + } + + @Override + public List getInfoForAuthentication() { + return Stream.of(SEEDED_USERS) + .map(u -> AuthUtils.getForBasic(u[0], u[0], u[1])) + .collect(Collectors.toList()); + } + + @Override + public List getDbSpecifications() { + return null; + } + + + private void seedUsers() { + send(HttpRequest.newBuilder(URI.create(getBaseURL() + "/api/v1/claim")) + .header("X-Komga-Email", SEEDED_USERS[0][0]) + .header("X-Komga-Password", SEEDED_USERS[0][1]) + .POST(HttpRequest.BodyPublishers.noBody())); + + String admin = "Basic " + Base64.getEncoder().encodeToString( + (SEEDED_USERS[0][0] + ":" + SEEDED_USERS[0][1]).getBytes()); + + for (int i = 1; i < SEEDED_USERS.length; i++) { + String body = "{\"email\":\"" + SEEDED_USERS[i][0] + "\",\"password\":\"" + SEEDED_USERS[i][1] + + "\",\"roles\":" + SEEDED_USERS[i][2] + "}"; + send(HttpRequest.newBuilder(URI.create(getBaseURL() + "/api/v2/users")) + .header("Authorization", admin) + .header("Content-Type", "application/json") + .POST(HttpRequest.BodyPublishers.ofString(body))); + } + } + + private void send(HttpRequest.Builder builder) { + try { + HttpResponse response = http.send(builder.timeout(Duration.ofSeconds(30)).build(), + HttpResponse.BodyHandlers.ofString()); + if (response.statusCode() >= 300) { + throw new IllegalStateException("Failed to seed users: " + response.statusCode() + " " + response.body()); + } + } catch (IOException | InterruptedException e) { + throw new RuntimeException(e); + } + } + + /** sqlite-jdbc extension over SQLite's Online Backup API: safe while the SUT is connected */ + private void eachDatabase(String command) { + for (String db : DATABASES) { + Path live = configDir.resolve(db); + try (Connection connection = DriverManager.getConnection( + "jdbc:sqlite:" + live + "?busy_timeout=30000"); + Statement statement = connection.createStatement()) { + statement.executeUpdate(command + " '" + live + ".seed'"); + } catch (SQLException e) { + throw new RuntimeException(e); + } + } + } + + private void deleteRecursively(Path root) { + if (!Files.exists(root)) { + return; + } + try (Stream paths = Files.walk(root)) { + paths.sorted(Comparator.reverseOrder()).forEach(p -> { + try { + Files.delete(p); + } catch (IOException e) { + throw new RuntimeException(e); + } + }); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} diff --git a/jdk_17_gradle/gradle.properties b/jdk_17_gradle/gradle.properties new file mode 100644 index 000000000..eb1569156 --- /dev/null +++ b/jdk_17_gradle/gradle.properties @@ -0,0 +1,2 @@ +# komga is a large Kotlin codebase, the default heap is not enough to compile it +kotlin.daemon.jvmargs=-Xmx2G diff --git a/jdk_17_gradle/gradle/libs.versions.toml b/jdk_17_gradle/gradle/libs.versions.toml index b0ae4f337..dd289f636 100644 --- a/jdk_17_gradle/gradle/libs.versions.toml +++ b/jdk_17_gradle/gradle/libs.versions.toml @@ -1,5 +1,12 @@ [versions] indra = "3.1.1" +# komga +sqliteJdbc = "3.53.2.1" +nightmonkeys = "1.1.0" +twelvemonkeys = "3.14.0" +springboot = "3.5.16" +lucene = "9.9.1" # v10 requires JDK 21 +jooq = "3.19.35" # should be aligned with the version provided by Spring Boot [plugins] indra = { id = "net.kyori.indra", version.ref = "indra" } @@ -7,6 +14,8 @@ indra-checkstyle = { id = "net.kyori.indra.checkstyle", version.ref = "indra" } spotless = { id = "com.diffplug.spotless", version = "6.19.0" } spring-boot = { id = "org.springframework.boot", version = "3.1.1" } spring-dependency-management = { id = "io.spring.dependency-management", version = "1.1.1" } +# komga +gradleGitProperties = { id = "com.gorylenko.gradle-git-properties", version = "4.0.1" } [libraries] jetbrains-annotations = { group = "org.jetbrains", name = "annotations", version = "24.0.1" } diff --git a/jdk_17_gradle/gradle/wrapper/gradle-wrapper.properties b/jdk_17_gradle/gradle/wrapper/gradle-wrapper.properties index fae08049a..a59520664 100644 --- a/jdk_17_gradle/gradle/wrapper/gradle-wrapper.properties +++ b/jdk_17_gradle/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/jdk_17_gradle/settings.gradle.kts b/jdk_17_gradle/settings.gradle.kts index 2aa31f55c..82239f59b 100644 --- a/jdk_17_gradle/settings.gradle.kts +++ b/jdk_17_gradle/settings.gradle.kts @@ -2,7 +2,13 @@ rootProject.name = "emb_jdk_17_gradle" include("cs:rest:bibliothek") +// the komga SUT is a multi-module build; only its server module is needed here +include("cs:rest:komga") +project(":cs:rest:komga").projectDir = file("cs/rest/komga/komga") + if (System.getenv("BUILD_EVOMASTER") != "false") { include("em:embedded:rest:bibliothek") include("em:external:rest:bibliothek") + include("em:embedded:rest:komga") + include("em:external:rest:komga") } diff --git a/openapi/komga.json b/openapi/komga.json new file mode 100644 index 000000000..562ddb59b --- /dev/null +++ b/openapi/komga.json @@ -0,0 +1,14681 @@ +{ + "openapi": "3.1.0", + "info": { + "description": "Komga REST API.\n\n## Reference\n\nCheck the API reference:\n- on the [Komga website](https://komga.org/docs/openapi/komga-api)\n- on any running Komga instance at `/swagger-ui.html`\n- on [GitHub](https://raw.githubusercontent.com/gotson/komga/refs/heads/master/komga/docs/openapi.json)\n\n## Authentication\n\nMost endpoints require authentication. Authentication is done using either:\n- Basic Authentication\n- Passing an API Key in the `X-API-Key` header\n\n## Sessions\n\nUpon successful authentication, a session is created, and can be reused.\n\n- By default, a `KOMGA-SESSION` cookie is set via `Set-Cookie` response header. This works well for browsers and clients that can handle cookies.\n- If you specify a header `X-Auth-Token` during authentication, the session ID will be returned via this same header. You can then pass that header again for subsequent requests to reuse the session.\n\nIf you need to set the session cookie later on, you can call `/api/v1/login/set-cookie` with `X-Auth-Token`. The response will contain the `Set-Cookie` header.\n\n## Remember Me\n\nDuring authentication, if a request parameter `remember-me` is passed and set to `true`, the server will also return a `komga-remember-me` cookie. This cookie will be used to login automatically even if the session has expired.\n\n## Logout\n\nYou can explicitly logout an existing session by calling `/api/logout`. This would return a `204`.\n\n## Deprecation\n\nAPI endpoints marked as deprecated will be removed in the next major version.", + "license": { + "name": "MIT", + "url": "https://github.com/gotson/komga/blob/master/LICENSE" + }, + "title": "Komga API", + "version": "1.26.3" + }, + "externalDocs": { + "description": "Komga documentation", + "url": "https://komga.org" + }, + "servers": [ + { + "url": "http://localhost:12345", + "description": "Generated server url" + } + ], + "security": [ + { + "basicAuth": [] + }, + { + "apiKey": [] + } + ], + "tags": [ + { + "name": "Deprecated" + }, + { + "description": "Manage libraries.", + "name": "Libraries" + }, + { + "description": "Manage series.", + "name": "Series" + }, + { + "description": "Manage posters for series.", + "name": "Series Poster" + }, + { + "description": "Manage books.", + "name": "Books" + }, + { + "description": "Manage posters for books.", + "name": "Book Poster" + }, + { + "name": "Book Pages" + }, + { + "name": "WebPub Manifest" + }, + { + "name": "Import" + }, + { + "description": "Provide font files and CSS for the Epub Reader.", + "name": "Fonts" + }, + { + "description": "Manage duplicate pages. Duplicate pages are identified by a page hash.", + "name": "Duplicate Pages" + }, + { + "description": "Manage collections.", + "name": "Collections" + }, + { + "description": "Manage posters for collections.", + "name": "Collection Poster" + }, + { + "name": "Collection Series" + }, + { + "description": "Manage readlists.", + "name": "Readlists" + }, + { + "description": "Manage posters for readlists.", + "name": "Readlist Poster" + }, + { + "name": "Readlist Books" + }, + { + "description": "Retrieve referential metadata from all items in the Komga server.", + "name": "Referential metadata" + }, + { + "description": "Manage current user.", + "name": "Current user" + }, + { + "description": "Manage users.", + "name": "Users" + }, + { + "description": "Manage API Keys", + "name": "API Keys" + }, + { + "name": "User session" + }, + { + "description": "List registered OAuth2 providers", + "name": "OAuth2" + }, + { + "description": "Sync points are automatically created during a Kobo sync.", + "name": "Sync points" + }, + { + "description": "Claim a freshly installed Komga server.", + "name": "Claim" + }, + { + "description": "Manage server tasks", + "name": "Tasks" + }, + { + "description": "Server events history", + "name": "History" + }, + { + "description": "List files from the host server's file system", + "name": "File system" + }, + { + "description": "Store and retrieve server settings", + "name": "Server settings" + }, + { + "description": "Retrieve releases information", + "name": "Releases" + }, + { + "description": "Retrieve announcements from the Komga website", + "name": "Announcements" + }, + { + "description": "Manage server", + "name": "Management" + }, + { + "name": "Mihon" + }, + { + "name": "ComicRack" + }, + { + "description": "Store and retrieve global and per-user settings. Those settings are not used by Komga itself, but can be stored for convenience by client applications.", + "name": "Client settings" + } + ], + "paths": { + "/actuator/info": { + "get": { + "description": "Required role: **ADMIN**", + "operationId": "getActuatorInfo", + "responses": { + "200": { + "content": { + "application/json": { + "examples": { + "Example": { + "value": "{\n \"git\": {\n \"branch\": \"master\",\n \"commit\": {\n \"id\": \"9be980d\",\n \"time\": \"2025-03-12T03:40:38Z\"\n }\n },\n \"build\": {\n \"artifact\": \"komga\",\n \"name\": \"komga\",\n \"version\": \"1.21.2\",\n \"group\": \"komga\"\n },\n \"java\": {\n \"version\": \"23.0.2\",\n \"vendor\": {\n \"name\": \"Eclipse Adoptium\",\n \"version\": \"Temurin-23.0.2+7\"\n },\n \"runtime\": {\n \"name\": \"OpenJDK Runtime Environment\",\n \"version\": \"23.0.2+7\"\n },\n \"jvm\": {\n \"name\": \"OpenJDK 64-Bit Server VM\",\n \"vendor\": \"Eclipse Adoptium\",\n \"version\": \"23.0.2+7\"\n }\n },\n \"os\": {\n \"name\": \"Linux\",\n \"version\": \"6.8.0-57-generic\",\n \"arch\": \"amd64\"\n }\n}" + } + }, + "schema": { + "additionalProperties": true + } + } + }, + "description": "OK" + } + }, + "summary": "Get server information", + "tags": [ + "Management" + ] + }, + "summary": "Get general information about the server" + }, + "/api/logout": { + "get": { + "description": "Invalidates the current session and clean up any remember-me authentication.", + "operationId": "postLogout", + "responses": { + "204": { + "description": "No Content" + } + }, + "summary": "Logout", + "tags": [ + "User session" + ] + }, + "post": { + "description": "Invalidates the current session and clean up any remember-me authentication.", + "operationId": "postLogout_1", + "responses": { + "204": { + "description": "No Content" + } + }, + "summary": "Logout", + "tags": [ + "User session" + ] + }, + "summary": "Logout current session" + }, + "/api/v1/age-ratings": { + "get": { + "deprecated": true, + "description": "Use GET /v2/age-ratings instead. Deprecated since 1.26.0", + "operationId": "getAgeRatings_1", + "parameters": [ + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List age ratings", + "tags": [ + "Deprecated", + "Referential metadata" + ] + } + }, + "/api/v1/announcements": { + "get": { + "description": "Required role: **ADMIN**", + "operationId": "getAnnouncements", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/JsonFeedDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Retrieve announcements", + "tags": [ + "Announcements" + ] + }, + "put": { + "description": "Required role: **ADMIN**", + "operationId": "markAnnouncementsRead", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Mark announcements as read", + "tags": [ + "Announcements" + ] + } + }, + "/api/v1/authors": { + "get": { + "deprecated": true, + "description": "Use GET /api/v2/authors instead. Deprecated since 1.20.0.", + "operationId": "getAuthorsDeprecated", + "parameters": [ + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "type": "string", + "default": "" + } + }, + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "series_id", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AuthorDto" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List authors", + "tags": [ + "Deprecated", + "Referential metadata" + ] + } + }, + "/api/v1/authors/names": { + "get": { + "deprecated": true, + "description": "Use GET /v2/authors/names instead. Deprecated since 1.26.0", + "operationId": "getAuthorsNames_1", + "parameters": [ + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "type": "string", + "default": "" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List authors' names", + "tags": [ + "Deprecated", + "Referential metadata" + ] + } + }, + "/api/v1/authors/roles": { + "get": { + "deprecated": true, + "description": "Use GET /v2/authors/roles instead. Deprecated since 1.26.0", + "operationId": "getAuthorsRoles_1", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List authors' roles", + "tags": [ + "Deprecated", + "Referential metadata" + ] + } + }, + "/api/v1/books": { + "get": { + "deprecated": true, + "description": "Use POST /api/v1/books/list instead. Deprecated since 1.19.0.", + "operationId": "getAllBooksDeprecated", + "parameters": [ + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "media_status", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "UNKNOWN", + "ERROR", + "READY", + "UNSUPPORTED", + "OUTDATED" + ] + } + } + }, + { + "in": "query", + "name": "read_status", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "UNREAD", + "READ", + "IN_PROGRESS" + ] + } + } + }, + { + "in": "query", + "name": "released_after", + "required": false, + "schema": { + "type": "string", + "format": "date" + } + }, + { + "in": "query", + "name": "tag", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + }, + { + "description": "Sorting criteria in the format: property(,asc|desc). Default sort order is ascending. Multiple sort criteria are supported.", + "in": "query", + "name": "sort", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageBookDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List books", + "tags": [ + "Books", + "Deprecated" + ] + } + }, + "/api/v1/books/duplicates": { + "get": { + "description": "Return books that have the same file hash.\n\nRequired role: **ADMIN**", + "operationId": "getBooksDuplicates", + "parameters": [ + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + }, + { + "description": "Sorting criteria in the format: property(,asc|desc). Default sort order is ascending. Multiple sort criteria are supported.", + "in": "query", + "name": "sort", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageBookDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List duplicate books", + "tags": [ + "Books" + ] + } + }, + "/api/v1/books/import": { + "post": { + "description": "Required role: **ADMIN**", + "operationId": "importBooks", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BookImportBatchDto" + } + } + }, + "required": true + }, + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Import books", + "tags": [ + "Import" + ] + } + }, + "/api/v1/books/latest": { + "get": { + "description": "Return newly added or updated books.", + "operationId": "getBooksLatest", + "parameters": [ + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageBookDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List latest books", + "tags": [ + "Books" + ] + } + }, + "/api/v1/books/list": { + "post": { + "operationId": "getBooks", + "parameters": [ + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + }, + { + "description": "Sorting criteria in the format: property(,asc|desc). Default sort order is ascending. Multiple sort criteria are supported.", + "in": "query", + "name": "sort", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BookSearch" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageBookDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List books", + "tags": [ + "Books" + ] + } + }, + "/api/v1/books/metadata": { + "patch": { + "description": "Set a field to null to unset the metadata. You can omit fields you don't want to update.\n\nRequired role: **ADMIN**", + "operationId": "updateBookMetadataByBatch", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/BookMetadataUpdateDto" + }, + "description": "A map of book IDs which values are the metadata fields to update. Set a field to null to unset the metadata. You can omit fields you don't want to update." + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Update book metadata in bulk", + "tags": [ + "Books" + ] + } + }, + "/api/v1/books/ondeck": { + "get": { + "description": "Return first unread book of series with at least one book read and no books in progress.", + "operationId": "getBooksOnDeck", + "parameters": [ + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageBookDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List books on deck", + "tags": [ + "Books" + ] + } + }, + "/api/v1/books/thumbnails": { + "put": { + "description": "Required role: **ADMIN**", + "operationId": "booksRegenerateThumbnails", + "parameters": [ + { + "in": "query", + "name": "for_bigger_result_only", + "required": false, + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Regenerate books posters", + "tags": [ + "Book Poster" + ] + } + }, + "/api/v1/books/{bookId}": { + "get": { + "operationId": "getBookById", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BookDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + }, + "404": { + "description": "Not Found" + } + }, + "summary": "Get book details", + "tags": [ + "Books" + ] + } + }, + "/api/v1/books/{bookId}/analyze": { + "post": { + "description": "Required role: **ADMIN**", + "operationId": "bookAnalyze", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Analyze book", + "tags": [ + "Books" + ] + } + }, + "/api/v1/books/{bookId}/file": { + "delete": { + "description": "Required role: **ADMIN**", + "operationId": "deleteBookFile", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Delete book file", + "tags": [ + "Books" + ] + }, + "get": { + "description": "Download the book file.\n\nRequired role: **FILE_DOWNLOAD**", + "operationId": "downloadBookFile", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StreamingResponseBody" + } + }, + "application/octet-stream": { + "schema": { + "$ref": "#/components/schemas/StreamingResponseBody" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Download book file", + "tags": [ + "Books" + ] + } + }, + "/api/v1/books/{bookId}/file/*": { + "get": { + "description": "Download the book file.\n\nRequired role: **FILE_DOWNLOAD**", + "operationId": "downloadBookFile_1", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StreamingResponseBody" + } + }, + "application/octet-stream": { + "schema": { + "$ref": "#/components/schemas/StreamingResponseBody" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Download book file", + "tags": [ + "Books" + ] + } + }, + "/api/v1/books/{bookId}/manifest": { + "get": { + "operationId": "getBookWebPubManifest", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/divina+json": { + "schema": { + "$ref": "#/components/schemas/WPPublicationDto" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/WPPublicationDto" + } + }, + "application/webpub+json": { + "schema": { + "$ref": "#/components/schemas/WPPublicationDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Get book's WebPub manifest", + "tags": [ + "WebPub Manifest" + ] + } + }, + "/api/v1/books/{bookId}/manifest/divina": { + "get": { + "operationId": "getBookWebPubManifestDivina", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/divina+json": { + "schema": { + "$ref": "#/components/schemas/WPPublicationDto" + } + }, + "application/json": { + "schema": { + "$ref": "#/components/schemas/WPPublicationDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Get book's WebPub manifest (DiViNa)", + "tags": [ + "WebPub Manifest" + ] + } + }, + "/api/v1/books/{bookId}/manifest/epub": { + "get": { + "operationId": "getBookWebPubManifestEpub", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WPPublicationDto" + } + }, + "application/webpub+json": { + "schema": { + "$ref": "#/components/schemas/WPPublicationDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Get book's WebPub manifest (Epub)", + "tags": [ + "WebPub Manifest" + ] + } + }, + "/api/v1/books/{bookId}/manifest/pdf": { + "get": { + "operationId": "getBookWebPubManifestPdf", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/WPPublicationDto" + } + }, + "application/webpub+json": { + "schema": { + "$ref": "#/components/schemas/WPPublicationDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Get book's WebPub manifest (PDF)", + "tags": [ + "WebPub Manifest" + ] + } + }, + "/api/v1/books/{bookId}/metadata": { + "patch": { + "description": "Set a field to null to unset the metadata. You can omit fields you don't want to update.\n\nRequired role: **ADMIN**", + "operationId": "updateBookMetadata", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BookMetadataUpdateDto" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Update book metadata", + "tags": [ + "Books" + ] + } + }, + "/api/v1/books/{bookId}/metadata/refresh": { + "post": { + "description": "Required role: **ADMIN**", + "operationId": "bookRefreshMetadata", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Refresh book metadata", + "tags": [ + "Books" + ] + } + }, + "/api/v1/books/{bookId}/next": { + "get": { + "operationId": "getBookSiblingNext", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BookDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Get next book in series", + "tags": [ + "Books" + ] + } + }, + "/api/v1/books/{bookId}/pages": { + "get": { + "operationId": "getBookPages", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PageDto" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List book pages", + "tags": [ + "Book Pages" + ] + } + }, + "/api/v1/books/{bookId}/pages/{pageNumber}": { + "get": { + "description": "Required role: **PAGE_STREAMING**", + "operationId": "getBookPageByNumber", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "pageNumber", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + }, + { + "description": "Convert the image to the provided format.", + "in": "query", + "name": "convert", + "required": false, + "schema": { + "type": "string", + "enum": [ + "jpeg", + "png" + ] + } + }, + { + "description": "If set to true, pages will start at index 0. If set to false, pages will start at index 1.", + "in": "query", + "name": "zero_based", + "required": false, + "schema": { + "type": "boolean", + "default": false + } + }, + { + "description": "Some very limited server driven content negotiation is handled. If a book is a PDF book, and the Accept header contains 'application/pdf' as a more specific type than other 'image/' types, a raw PDF page will be returned.", + "in": "header", + "name": "Accept", + "required": false, + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MediaType" + } + } + }, + { + "in": "query", + "name": "contentNegotiation", + "required": false, + "schema": { + "type": "boolean", + "default": true + } + } + ], + "responses": { + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + }, + "default": { + "content": { + "image/*": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "description": "default response" + } + }, + "summary": "Get book page image", + "tags": [ + "Book Pages" + ] + } + }, + "/api/v1/books/{bookId}/pages/{pageNumber}/raw": { + "get": { + "description": "Returns the book page in raw format, without content negotiation.\n\nRequired role: **PAGE_STREAMING**", + "operationId": "getBookPageRawByNumber", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "pageNumber", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "content": { + "*/*": { + "schema": { + "type": "string", + "format": "byte" + } + }, + "application/json": { + "schema": { + "type": "string", + "format": "byte" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Get raw book page", + "tags": [ + "Book Pages" + ] + } + }, + "/api/v1/books/{bookId}/pages/{pageNumber}/thumbnail": { + "get": { + "description": "The image is resized to 300px on the largest dimension.", + "operationId": "getBookPageThumbnailByNumber", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "pageNumber", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/jpeg": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "description": "default response" + } + }, + "summary": "Get book page thumbnail", + "tags": [ + "Book Pages" + ] + } + }, + "/api/v1/books/{bookId}/positions": { + "get": { + "description": "The Positions API is a proposed standard for OPDS 2 and Readium. It is used by the Epub Reader.", + "operationId": "getBookPositions", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/R2Positions" + } + }, + "application/vnd.readium.position-list+json": { + "schema": { + "$ref": "#/components/schemas/R2Positions" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List book's positions", + "tags": [ + "WebPub Manifest" + ] + } + }, + "/api/v1/books/{bookId}/previous": { + "get": { + "operationId": "getBookSiblingPrevious", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BookDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Get previous book in series", + "tags": [ + "Books" + ] + } + }, + "/api/v1/books/{bookId}/progression": { + "get": { + "description": "The Progression API is a proposed standard for OPDS 2 and Readium. It is used by the Epub Reader.", + "operationId": "getBookProgression", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/R2Progression" + } + }, + "application/vnd.readium.progression+json": { + "schema": { + "$ref": "#/components/schemas/R2Progression" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Get book progression", + "tags": [ + "WebPub Manifest" + ] + }, + "put": { + "description": "The Progression API is a proposed standard for OPDS 2 and Readium. It is used by the Epub Reader.", + "operationId": "updateBookProgression", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/R2Progression" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Mark book progression", + "tags": [ + "WebPub Manifest" + ] + } + }, + "/api/v1/books/{bookId}/read-progress": { + "delete": { + "description": "Mark book as unread", + "operationId": "deleteBookReadProgress", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Mark book as unread", + "tags": [ + "Books" + ] + }, + "patch": { + "description": "Mark book as read and/or change page progress.", + "operationId": "markBookReadProgress", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReadProgressUpdateDto" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Mark book's read progress", + "tags": [ + "Books" + ] + } + }, + "/api/v1/books/{bookId}/readlists": { + "get": { + "operationId": "getReadListsByBookId", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ReadListDto" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List book's readlists", + "tags": [ + "Books" + ] + } + }, + "/api/v1/books/{bookId}/resource/{resource}": { + "get": { + "description": "Return a resource from within an Epub book.", + "operationId": "getBookEpubResource", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "resource", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "*/*": { + "schema": { + "type": "string", + "format": "byte" + } + }, + "application/json": { + "schema": { + "type": "string", + "format": "byte" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "security": [], + "summary": "Get Epub resource", + "tags": [ + "WebPub Manifest" + ] + } + }, + "/api/v1/books/{bookId}/thumbnail": { + "get": { + "operationId": "getBookThumbnail", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/jpeg": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "description": "default response" + } + }, + "summary": "Get book's poster image", + "tags": [ + "Book Poster" + ] + } + }, + "/api/v1/books/{bookId}/thumbnails": { + "get": { + "operationId": "getBookThumbnails", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ThumbnailBookDto" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List book posters", + "tags": [ + "Book Poster" + ] + }, + "post": { + "description": "Required role: **ADMIN**", + "operationId": "addUserUploadedBookThumbnail", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "selected", + "required": false, + "schema": { + "type": "boolean" + } + } + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "file": { + "type": "string", + "format": "binary" + } + }, + "required": [ + "file" + ] + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ThumbnailBookDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Add book poster", + "tags": [ + "Book Poster" + ] + } + }, + "/api/v1/books/{bookId}/thumbnails/{thumbnailId}": { + "delete": { + "description": "Only uploaded posters can be deleted.\n\nRequired role: **ADMIN**", + "operationId": "deleteUserUploadedBookThumbnail", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "thumbnailId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Delete book poster", + "tags": [ + "Book Poster" + ] + }, + "get": { + "operationId": "getBookThumbnailById", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "thumbnailId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/jpeg": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "description": "default response" + } + }, + "summary": "Get book poster image", + "tags": [ + "Book Poster" + ] + } + }, + "/api/v1/books/{bookId}/thumbnails/{thumbnailId}/selected": { + "put": { + "description": "Required role: **ADMIN**", + "operationId": "markBookThumbnailSelected", + "parameters": [ + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "thumbnailId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Mark book poster as selected", + "tags": [ + "Book Poster" + ] + } + }, + "/api/v1/claim": { + "get": { + "description": "Check whether this server has already been claimed.", + "operationId": "getClaimStatus", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ClaimStatus" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "security": [], + "summary": "Retrieve claim status", + "tags": [ + "Claim" + ] + }, + "post": { + "description": "Creates an admin user with the provided credentials.", + "operationId": "claimServer", + "parameters": [ + { + "in": "header", + "name": "X-Komga-Email", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "header", + "name": "X-Komga-Password", + "required": true, + "schema": { + "type": "string", + "minLength": 1 + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "security": [], + "summary": "Claim server", + "tags": [ + "Claim" + ] + } + }, + "/api/v1/client-settings/global": { + "delete": { + "description": "Setting key should be a valid lowercase namespace string like 'application.domain.key'\n\nRequired role: **ADMIN**", + "operationId": "deleteGlobalSettings", + "requestBody": { + "content": { + "application/json": { + "example": [ + "application.key1", + "application.key2" + ], + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Delete global settings", + "tags": [ + "Client settings" + ] + }, + "patch": { + "description": "Setting key should be a valid lowercase namespace string like 'application.domain.key'\n\nRequired role: **ADMIN**", + "operationId": "saveGlobalSetting", + "requestBody": { + "content": { + "application/json": { + "example": { + "application.key1": { + "value": "a string value", + "allowUnauthorized": true + }, + "application.key2": { + "value": "{\"json\":\"object\"}", + "allowUnauthorized": false + } + }, + "schema": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/ClientSettingGlobalUpdateDto" + } + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Save global settings", + "tags": [ + "Client settings" + ] + } + }, + "/api/v1/client-settings/global/list": { + "get": { + "description": "For unauthenticated users, only settings with 'allowUnauthorized=true' will be returned.", + "operationId": "getGlobalSettings", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/ClientSettingDto" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "security": [], + "summary": "Retrieve global client settings", + "tags": [ + "Client settings" + ] + } + }, + "/api/v1/client-settings/user": { + "delete": { + "description": "Setting key should be a valid lowercase namespace string like 'application.domain.key'", + "operationId": "deleteUserSettings", + "requestBody": { + "content": { + "application/json": { + "example": [ + "application.key1", + "application.key2" + ], + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Delete user settings", + "tags": [ + "Client settings" + ] + }, + "patch": { + "description": "Setting key should be a valid lowercase namespace string like 'application.domain.key'", + "operationId": "saveUserSetting", + "requestBody": { + "content": { + "application/json": { + "example": { + "application.key1": { + "value": "a string value" + }, + "application.key2": { + "value": "{\"json\":\"object\"}" + } + }, + "schema": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/ClientSettingUserUpdateDto" + } + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Save user settings", + "tags": [ + "Client settings" + ] + } + }, + "/api/v1/client-settings/user/list": { + "get": { + "operationId": "getUserSettings", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "object", + "additionalProperties": { + "$ref": "#/components/schemas/ClientSettingDto" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Retrieve user client settings", + "tags": [ + "Client settings" + ] + } + }, + "/api/v1/collections": { + "get": { + "operationId": "getCollections", + "parameters": [ + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageCollectionDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List collections", + "tags": [ + "Collections" + ] + }, + "post": { + "description": "Required role: **ADMIN**", + "operationId": "createCollection", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CollectionCreationDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CollectionDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Create collection", + "tags": [ + "Collections" + ] + } + }, + "/api/v1/collections/{id}": { + "delete": { + "description": "Required role: **ADMIN**", + "operationId": "deleteCollectionById", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Delete collection", + "tags": [ + "Collections" + ] + }, + "get": { + "operationId": "getCollectionById", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CollectionDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Get collection details", + "tags": [ + "Collections" + ] + }, + "patch": { + "description": "Required role: **ADMIN**", + "operationId": "updateCollectionById", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CollectionUpdateDto" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Update collection", + "tags": [ + "Collections" + ] + } + }, + "/api/v1/collections/{id}/series": { + "get": { + "operationId": "getSeriesByCollectionId", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "ENDED", + "ONGOING", + "ABANDONED", + "HIATUS" + ] + } + } + }, + { + "in": "query", + "name": "read_status", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "UNREAD", + "READ", + "IN_PROGRESS" + ] + } + } + }, + { + "in": "query", + "name": "publisher", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "language", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "genre", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "tag", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "age_rating", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "release_year", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "deleted", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "in": "query", + "name": "complete", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + }, + { + "description": "Author criteria in the format: name,role. Multiple author criteria are supported.", + "in": "query", + "name": "author", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageSeriesDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List collection's series", + "tags": [ + "Collection Series" + ] + } + }, + "/api/v1/collections/{id}/thumbnail": { + "get": { + "operationId": "getCollectionThumbnail", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/jpeg": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "description": "default response" + } + }, + "summary": "Get collection's poster image", + "tags": [ + "Collection Poster" + ] + } + }, + "/api/v1/collections/{id}/thumbnails": { + "get": { + "operationId": "getCollectionThumbnails", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ThumbnailSeriesCollectionDto" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List collection's posters", + "tags": [ + "Collection Poster" + ] + }, + "post": { + "description": "Required role: **ADMIN**", + "operationId": "addUserUploadedCollectionThumbnail", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "selected", + "required": false, + "schema": { + "type": "boolean" + } + } + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "file": { + "type": "string", + "format": "binary" + } + }, + "required": [ + "file" + ] + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ThumbnailSeriesCollectionDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Add collection poster", + "tags": [ + "Collection Poster" + ] + } + }, + "/api/v1/collections/{id}/thumbnails/{thumbnailId}": { + "delete": { + "description": "Required role: **ADMIN**", + "operationId": "deleteUserUploadedCollectionThumbnail", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "thumbnailId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Delete collection poster", + "tags": [ + "Collection Poster" + ] + }, + "get": { + "operationId": "getCollectionThumbnailById", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "thumbnailId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/jpeg": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "description": "default response" + } + }, + "summary": "Get collection poster image", + "tags": [ + "Collection Poster" + ] + } + }, + "/api/v1/collections/{id}/thumbnails/{thumbnailId}/selected": { + "put": { + "description": "Required role: **ADMIN**", + "operationId": "markCollectionThumbnailSelected", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "thumbnailId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Mark collection poster as selected", + "tags": [ + "Collection Poster" + ] + } + }, + "/api/v1/filesystem": { + "post": { + "description": "List folders and files from the host server's file system. If no request body is passed then the root directories are returned.\n\nRequired role: **ADMIN**", + "operationId": "getDirectoryListing", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DirectoryRequestDto" + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DirectoryListingDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Directory listing", + "tags": [ + "File system" + ] + } + }, + "/api/v1/fonts/families": { + "get": { + "description": "List all available font families.", + "operationId": "getFonts", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List font families", + "tags": [ + "Fonts" + ] + } + }, + "/api/v1/fonts/resource/{fontFamily}/css": { + "get": { + "description": "Download a CSS file with the @font-face block for the font family. This is used by the Epub Reader to change fonts.", + "operationId": "getFontFamilyAsCss", + "parameters": [ + { + "in": "path", + "name": "fontFamily", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "text/css": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "security": [], + "summary": "Download CSS file", + "tags": [ + "Fonts" + ] + } + }, + "/api/v1/fonts/resource/{fontFamily}/{fontFile}": { + "get": { + "operationId": "getFontFile", + "parameters": [ + { + "in": "path", + "name": "fontFamily", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "fontFile", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "security": [], + "summary": "Download font file", + "tags": [ + "Fonts" + ] + } + }, + "/api/v1/genres": { + "get": { + "deprecated": true, + "description": "Use GET /v2/genres instead. Deprecated since 1.26.0", + "operationId": "getGenres_1", + "parameters": [ + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List genres", + "tags": [ + "Deprecated", + "Referential metadata" + ] + } + }, + "/api/v1/history": { + "get": { + "description": "Required role: **ADMIN**", + "operationId": "getHistoricalEvents", + "parameters": [ + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + }, + { + "description": "Sorting criteria in the format: property(,asc|desc). Default sort order is ascending. Multiple sort criteria are supported.", + "in": "query", + "name": "sort", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageHistoricalEventDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List historical events", + "tags": [ + "History" + ] + } + }, + "/api/v1/languages": { + "get": { + "deprecated": true, + "description": "Use GET /v2/languages instead. Deprecated since 1.26.0", + "operationId": "getLanguages_1", + "parameters": [ + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List languages", + "tags": [ + "Deprecated", + "Referential metadata" + ] + } + }, + "/api/v1/libraries": { + "get": { + "description": "The libraries are filtered based on the current user's permissions", + "operationId": "getLibraries", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/LibraryDto" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List all libraries", + "tags": [ + "Libraries" + ] + }, + "post": { + "description": "Required role: **ADMIN**", + "operationId": "addLibrary", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LibraryCreationDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LibraryDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Create a library", + "tags": [ + "Libraries" + ] + } + }, + "/api/v1/libraries/{libraryId}": { + "delete": { + "description": "Required role: **ADMIN**", + "operationId": "deleteLibraryById", + "parameters": [ + { + "in": "path", + "name": "libraryId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Delete a library", + "tags": [ + "Libraries" + ] + }, + "get": { + "operationId": "getLibraryById", + "parameters": [ + { + "in": "path", + "name": "libraryId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LibraryDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Get details for a single library", + "tags": [ + "Libraries" + ] + }, + "patch": { + "description": "You can omit fields you don't want to update\n\nRequired role: **ADMIN**", + "operationId": "updateLibraryById", + "parameters": [ + { + "in": "path", + "name": "libraryId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LibraryUpdateDto" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Update a library", + "tags": [ + "Libraries" + ] + }, + "put": { + "deprecated": true, + "description": "Use PATCH /api/v1/libraries/{libraryId} instead. Deprecated since 1.3.0.\n\nRequired role: **ADMIN**", + "operationId": "updateLibraryByIdDeprecated", + "parameters": [ + { + "in": "path", + "name": "libraryId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LibraryUpdateDto" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Update a library", + "tags": [ + "Deprecated", + "Libraries" + ] + } + }, + "/api/v1/libraries/{libraryId}/analyze": { + "post": { + "description": "Required role: **ADMIN**", + "operationId": "libraryAnalyze", + "parameters": [ + { + "in": "path", + "name": "libraryId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Analyze a library", + "tags": [ + "Libraries" + ] + } + }, + "/api/v1/libraries/{libraryId}/empty-trash": { + "post": { + "description": "Required role: **ADMIN**", + "operationId": "libraryEmptyTrash", + "parameters": [ + { + "in": "path", + "name": "libraryId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Empty trash for a library", + "tags": [ + "Libraries" + ] + } + }, + "/api/v1/libraries/{libraryId}/metadata/refresh": { + "post": { + "description": "Required role: **ADMIN**", + "operationId": "libraryRefreshMetadata", + "parameters": [ + { + "in": "path", + "name": "libraryId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Refresh metadata for a library", + "tags": [ + "Libraries" + ] + } + }, + "/api/v1/libraries/{libraryId}/scan": { + "post": { + "description": "Required role: **ADMIN**", + "operationId": "libraryScan", + "parameters": [ + { + "in": "path", + "name": "libraryId", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "deep", + "required": false, + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Scan a library", + "tags": [ + "Libraries" + ] + } + }, + "/api/v1/login/set-cookie": { + "get": { + "description": "Forcefully return Set-Cookie header, even if the session is contained in the X-Auth-Token header.", + "operationId": "convertHeaderSessionToCookie", + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Set cookie", + "tags": [ + "User session" + ] + } + }, + "/api/v1/oauth2/providers": { + "get": { + "operationId": "getOAuth2Providers", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/OAuth2ClientDto" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "security": [], + "summary": "List registered OAuth2 providers", + "tags": [ + "OAuth2" + ] + } + }, + "/api/v1/page-hashes": { + "get": { + "description": "Required role: **ADMIN**", + "operationId": "getKnownPageHashes", + "parameters": [ + { + "in": "query", + "name": "action", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "DELETE_AUTO", + "DELETE_MANUAL", + "IGNORE" + ] + } + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + }, + { + "description": "Sorting criteria in the format: property(,asc|desc). Default sort order is ascending. Multiple sort criteria are supported.", + "in": "query", + "name": "sort", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PagePageHashKnownDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List known duplicates", + "tags": [ + "Duplicate Pages" + ] + }, + "put": { + "description": "Required role: **ADMIN**", + "operationId": "createOrUpdateKnownPageHash", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageHashCreationDto" + } + } + }, + "required": true + }, + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Mark duplicate page as known", + "tags": [ + "Duplicate Pages" + ] + } + }, + "/api/v1/page-hashes/unknown": { + "get": { + "description": "Required role: **ADMIN**", + "operationId": "getUnknownPageHashes", + "parameters": [ + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + }, + { + "description": "Sorting criteria in the format: property(,asc|desc). Default sort order is ascending. Multiple sort criteria are supported.", + "in": "query", + "name": "sort", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PagePageHashUnknownDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List unknown duplicates", + "tags": [ + "Duplicate Pages" + ] + } + }, + "/api/v1/page-hashes/unknown/{pageHash}/thumbnail": { + "get": { + "description": "Required role: **ADMIN**", + "operationId": "getUnknownPageHashThumbnail", + "parameters": [ + { + "in": "path", + "name": "pageHash", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "resize", + "required": false, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/jpeg": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "description": "default response" + } + }, + "summary": "Get unknown duplicate image thumbnail", + "tags": [ + "Duplicate Pages" + ] + } + }, + "/api/v1/page-hashes/{pageHash}": { + "get": { + "description": "Required role: **ADMIN**", + "operationId": "getPageHashMatches", + "parameters": [ + { + "in": "path", + "name": "pageHash", + "required": true, + "schema": { + "type": "string" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + }, + { + "description": "Sorting criteria in the format: property(,asc|desc). Default sort order is ascending. Multiple sort criteria are supported.", + "in": "query", + "name": "sort", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PagePageHashMatchDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List duplicate matches", + "tags": [ + "Duplicate Pages" + ] + } + }, + "/api/v1/page-hashes/{pageHash}/delete-all": { + "post": { + "description": "Required role: **ADMIN**", + "operationId": "deleteDuplicatePagesByPageHash", + "parameters": [ + { + "in": "path", + "name": "pageHash", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Delete all duplicate pages by hash", + "tags": [ + "Duplicate Pages" + ] + } + }, + "/api/v1/page-hashes/{pageHash}/delete-match": { + "post": { + "description": "Required role: **ADMIN**", + "operationId": "deleteSingleMatchByPageHash", + "parameters": [ + { + "in": "path", + "name": "pageHash", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageHashMatchDto" + } + } + }, + "required": true + }, + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Delete specific duplicate page", + "tags": [ + "Duplicate Pages" + ] + } + }, + "/api/v1/page-hashes/{pageHash}/thumbnail": { + "get": { + "description": "Required role: **ADMIN**", + "operationId": "getKnownPageHashThumbnail", + "parameters": [ + { + "in": "path", + "name": "pageHash", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/jpeg": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "description": "default response" + } + }, + "summary": "Get known duplicate image thumbnail", + "tags": [ + "Duplicate Pages" + ] + } + }, + "/api/v1/publishers": { + "get": { + "deprecated": true, + "description": "Use GET /v2/publishers instead. Deprecated since 1.26.0", + "operationId": "getPublishers_1", + "parameters": [ + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List publishers", + "tags": [ + "Deprecated", + "Referential metadata" + ] + } + }, + "/api/v1/readlists": { + "get": { + "operationId": "getReadLists", + "parameters": [ + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageReadListDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List readlists", + "tags": [ + "Readlists" + ] + }, + "post": { + "description": "Required role: **ADMIN**", + "operationId": "createReadList", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReadListCreationDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReadListDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Create readlist", + "tags": [ + "Readlists" + ] + } + }, + "/api/v1/readlists/match/comicrack": { + "post": { + "description": "Required role: **ADMIN**", + "operationId": "matchComicRackList", + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "file": { + "type": "string", + "format": "binary" + } + }, + "required": [ + "file" + ] + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReadListRequestMatchDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Match ComicRack list", + "tags": [ + "ComicRack" + ] + } + }, + "/api/v1/readlists/{id}": { + "delete": { + "description": "Required role: **ADMIN**", + "operationId": "deleteReadListById", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Delete readlist", + "tags": [ + "Readlists" + ] + }, + "get": { + "operationId": "getReadListById", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReadListDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Get readlist details", + "tags": [ + "Readlists" + ] + }, + "patch": { + "description": "Required role: **ADMIN**", + "operationId": "updateReadListById", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReadListUpdateDto" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Update readlist", + "tags": [ + "Readlists" + ] + } + }, + "/api/v1/readlists/{id}/books": { + "get": { + "operationId": "getBooksByReadListId", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "read_status", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "UNREAD", + "READ", + "IN_PROGRESS" + ] + } + } + }, + { + "in": "query", + "name": "tag", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "media_status", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "UNKNOWN", + "ERROR", + "READY", + "UNSUPPORTED", + "OUTDATED" + ] + } + } + }, + { + "in": "query", + "name": "deleted", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + }, + { + "description": "Author criteria in the format: name,role. Multiple author criteria are supported.", + "in": "query", + "name": "author", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageBookDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List readlist's books", + "tags": [ + "Readlist Books" + ] + } + }, + "/api/v1/readlists/{id}/books/{bookId}/next": { + "get": { + "operationId": "getBookSiblingNextInReadList", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BookDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Get next book in readlist", + "tags": [ + "Readlist Books" + ] + } + }, + "/api/v1/readlists/{id}/books/{bookId}/previous": { + "get": { + "operationId": "getBookSiblingPreviousInReadList", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "bookId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/BookDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Get previous book in readlist", + "tags": [ + "Readlist Books" + ] + } + }, + "/api/v1/readlists/{id}/file": { + "get": { + "description": "Download the whole readlist as a ZIP file.\n\nRequired role: **FILE_DOWNLOAD**", + "operationId": "downloadReadListAsZip", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StreamingResponseBody" + } + }, + "application/octet-stream": { + "schema": { + "$ref": "#/components/schemas/StreamingResponseBody" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Download readlist", + "tags": [ + "Readlists" + ] + } + }, + "/api/v1/readlists/{id}/read-progress/tachiyomi": { + "get": { + "description": "Mihon specific, due to how read progress is handled in Mihon.", + "operationId": "getMihonReadProgressByReadListId", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TachiyomiReadProgressDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Get readlist read progress (Mihon)", + "tags": [ + "Mihon" + ] + }, + "put": { + "description": "Mihon specific, due to how read progress is handled in Mihon.", + "operationId": "updateMihonReadProgressByReadListId", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TachiyomiReadProgressUpdateDto" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Update readlist read progress (Mihon)", + "tags": [ + "Mihon" + ] + } + }, + "/api/v1/readlists/{id}/thumbnail": { + "get": { + "operationId": "getReadListThumbnail", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/jpeg": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "description": "default response" + } + }, + "summary": "Get readlist's poster image", + "tags": [ + "Readlist Poster" + ] + } + }, + "/api/v1/readlists/{id}/thumbnails": { + "get": { + "operationId": "getReadListThumbnails", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ThumbnailReadListDto" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List readlist's posters", + "tags": [ + "Readlist Poster" + ] + }, + "post": { + "description": "Required role: **ADMIN**", + "operationId": "addUserUploadedReadListThumbnail", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "selected", + "required": false, + "schema": { + "type": "boolean" + } + } + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "file": { + "type": "string", + "format": "binary" + } + }, + "required": [ + "file" + ] + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ThumbnailReadListDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Add readlist poster", + "tags": [ + "Readlist Poster" + ] + } + }, + "/api/v1/readlists/{id}/thumbnails/{thumbnailId}": { + "delete": { + "description": "Required role: **ADMIN**", + "operationId": "deleteUserUploadedReadListThumbnail", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "thumbnailId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Delete readlist poster", + "tags": [ + "Readlist Poster" + ] + }, + "get": { + "operationId": "getReadListThumbnailById", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "thumbnailId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/jpeg": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "description": "default response" + } + }, + "summary": "Get readlist poster image", + "tags": [ + "Readlist Poster" + ] + } + }, + "/api/v1/readlists/{id}/thumbnails/{thumbnailId}/selected": { + "put": { + "description": "Required role: **ADMIN**", + "operationId": "markReadListThumbnailSelected", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "thumbnailId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Mark readlist poster as selected", + "tags": [ + "Readlist Poster" + ] + } + }, + "/api/v1/releases": { + "get": { + "description": "Required role: **ADMIN**", + "operationId": "getReleases", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ReleaseDto" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List releases", + "tags": [ + "Releases" + ] + } + }, + "/api/v1/series": { + "get": { + "deprecated": true, + "description": "Use POST /api/v1/series/list instead. Deprecated since 1.19.0.", + "operationId": "getSeriesDeprecated", + "parameters": [ + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "ENDED", + "ONGOING", + "ABANDONED", + "HIATUS" + ] + } + } + }, + { + "in": "query", + "name": "read_status", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "UNREAD", + "READ", + "IN_PROGRESS" + ] + } + } + }, + { + "in": "query", + "name": "publisher", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "language", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "genre", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "tag", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "age_rating", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "release_year", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "sharing_label", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "deleted", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "in": "query", + "name": "complete", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "in": "query", + "name": "oneshot", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Search by regex criteria, in the form: regex,field. Supported fields are TITLE and TITLE_SORT.", + "in": "query", + "name": "search_regex", + "schema": { + "type": "string" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + }, + { + "description": "Sorting criteria in the format: property(,asc|desc). Default sort order is ascending. Multiple sort criteria are supported.", + "in": "query", + "name": "sort", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "description": "Author criteria in the format: name,role. Multiple author criteria are supported.", + "in": "query", + "name": "author", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageSeriesDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List series", + "tags": [ + "Series", + "Deprecated" + ] + } + }, + "/api/v1/series/alphabetical-groups": { + "get": { + "deprecated": true, + "description": "Use POST /api/v1/series/list/alphabetical-groups instead. Deprecated since 1.19.0.", + "operationId": "getSeriesAlphabeticalGroupsDeprecated", + "parameters": [ + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "status", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "ENDED", + "ONGOING", + "ABANDONED", + "HIATUS" + ] + } + } + }, + { + "in": "query", + "name": "read_status", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "UNREAD", + "READ", + "IN_PROGRESS" + ] + } + } + }, + { + "in": "query", + "name": "publisher", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "language", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "genre", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "tag", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "age_rating", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "release_year", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "sharing_label", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "deleted", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "in": "query", + "name": "complete", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "in": "query", + "name": "oneshot", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Search by regex criteria, in the form: regex,field. Supported fields are TITLE and TITLE_SORT.", + "in": "query", + "name": "search_regex", + "schema": { + "type": "string" + } + }, + { + "description": "Author criteria in the format: name,role. Multiple author criteria are supported.", + "in": "query", + "name": "author", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GroupCountDto" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List series groups", + "tags": [ + "Series", + "Deprecated" + ] + } + }, + "/api/v1/series/latest": { + "get": { + "description": "Return recently added or updated series.", + "operationId": "getSeriesLatest", + "parameters": [ + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "deleted", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "in": "query", + "name": "oneshot", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageSeriesDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List latest series", + "tags": [ + "Series" + ] + } + }, + "/api/v1/series/list": { + "post": { + "operationId": "getSeries", + "parameters": [ + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + }, + { + "description": "Sorting criteria in the format: property(,asc|desc). Default sort order is ascending. Multiple sort criteria are supported.", + "in": "query", + "name": "sort", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SeriesSearch" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageSeriesDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List series", + "tags": [ + "Series" + ] + } + }, + "/api/v1/series/list/alphabetical-groups": { + "post": { + "description": "List series grouped by the first character of their sort title.", + "operationId": "getSeriesAlphabeticalGroups", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SeriesSearch" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/GroupCountDto" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List series groups", + "tags": [ + "Series" + ] + } + }, + "/api/v1/series/new": { + "get": { + "description": "Return newly added series.", + "operationId": "getSeriesNew", + "parameters": [ + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "deleted", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "in": "query", + "name": "oneshot", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageSeriesDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List new series", + "tags": [ + "Series" + ] + } + }, + "/api/v1/series/release-dates": { + "get": { + "deprecated": true, + "description": "Use GET /v2/series/release-years instead. Deprecated since 1.26.0", + "operationId": "getSeriesReleaseDates", + "parameters": [ + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List series release dates", + "tags": [ + "Deprecated", + "Referential metadata" + ] + } + }, + "/api/v1/series/updated": { + "get": { + "description": "Return recently updated series, but not newly added ones.", + "operationId": "getSeriesUpdated", + "parameters": [ + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "deleted", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "in": "query", + "name": "oneshot", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageSeriesDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List updated series", + "tags": [ + "Series" + ] + } + }, + "/api/v1/series/{seriesId}": { + "get": { + "operationId": "getSeriesById", + "parameters": [ + { + "in": "path", + "name": "seriesId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SeriesDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + }, + "404": { + "description": "Not Found" + } + }, + "summary": "Get series details", + "tags": [ + "Series" + ] + } + }, + "/api/v1/series/{seriesId}/analyze": { + "post": { + "description": "Required role: **ADMIN**", + "operationId": "seriesAnalyze", + "parameters": [ + { + "in": "path", + "name": "seriesId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Analyze series", + "tags": [ + "Series" + ] + } + }, + "/api/v1/series/{seriesId}/books": { + "get": { + "deprecated": true, + "description": "Use POST /api/v1/books/list instead. Deprecated since 1.19.0.", + "operationId": "getBooksBySeriesId", + "parameters": [ + { + "in": "path", + "name": "seriesId", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "media_status", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "UNKNOWN", + "ERROR", + "READY", + "UNSUPPORTED", + "OUTDATED" + ] + } + } + }, + { + "in": "query", + "name": "read_status", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "UNREAD", + "READ", + "IN_PROGRESS" + ] + } + } + }, + { + "in": "query", + "name": "tag", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "in": "query", + "name": "deleted", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + }, + { + "description": "Sorting criteria in the format: property(,asc|desc). Default sort order is ascending. Multiple sort criteria are supported.", + "in": "query", + "name": "sort", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + }, + { + "description": "Author criteria in the format: name,role. Multiple author criteria are supported.", + "in": "query", + "name": "author", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageBookDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List series' books", + "tags": [ + "Series", + "Deprecated" + ] + } + }, + "/api/v1/series/{seriesId}/collections": { + "get": { + "operationId": "getCollectionsBySeriesId", + "parameters": [ + { + "in": "path", + "name": "seriesId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CollectionDto" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List series' collections", + "tags": [ + "Series" + ] + } + }, + "/api/v1/series/{seriesId}/file": { + "delete": { + "description": "Delete all of the series' books files on disk.\n\nRequired role: **ADMIN**", + "operationId": "deleteSeriesFile", + "parameters": [ + { + "in": "path", + "name": "seriesId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Delete series files", + "tags": [ + "Series" + ] + }, + "get": { + "description": "Download the whole series as a ZIP file.\n\nRequired role: **FILE_DOWNLOAD**", + "operationId": "downloadSeriesAsZip", + "parameters": [ + { + "in": "path", + "name": "seriesId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/StreamingResponseBody" + } + }, + "application/octet-stream": { + "schema": { + "$ref": "#/components/schemas/StreamingResponseBody" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Download series", + "tags": [ + "Series" + ] + } + }, + "/api/v1/series/{seriesId}/metadata": { + "patch": { + "description": "Required role: **ADMIN**", + "operationId": "updateSeriesMetadata", + "parameters": [ + { + "in": "path", + "name": "seriesId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SeriesMetadataUpdateDto" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Update series metadata", + "tags": [ + "Series" + ] + } + }, + "/api/v1/series/{seriesId}/metadata/refresh": { + "post": { + "description": "Required role: **ADMIN**", + "operationId": "seriesRefreshMetadata", + "parameters": [ + { + "in": "path", + "name": "seriesId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Refresh series metadata", + "tags": [ + "Series" + ] + } + }, + "/api/v1/series/{seriesId}/read-progress": { + "delete": { + "description": "Mark all book for series as unread", + "operationId": "markSeriesAsUnread", + "parameters": [ + { + "in": "path", + "name": "seriesId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Mark series as unread", + "tags": [ + "Series" + ] + }, + "post": { + "description": "Mark all book for series as read", + "operationId": "markSeriesAsRead", + "parameters": [ + { + "in": "path", + "name": "seriesId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Mark series as read", + "tags": [ + "Series" + ] + } + }, + "/api/v1/series/{seriesId}/thumbnail": { + "get": { + "operationId": "getSeriesThumbnail", + "parameters": [ + { + "in": "path", + "name": "seriesId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/jpeg": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "description": "default response" + } + }, + "summary": "Get series' poster image", + "tags": [ + "Series Poster" + ] + } + }, + "/api/v1/series/{seriesId}/thumbnails": { + "get": { + "operationId": "getSeriesThumbnails", + "parameters": [ + { + "in": "path", + "name": "seriesId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ThumbnailSeriesDto" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List series posters", + "tags": [ + "Series Poster" + ] + }, + "post": { + "description": "Required role: **ADMIN**", + "operationId": "addUserUploadedSeriesThumbnail", + "parameters": [ + { + "in": "path", + "name": "seriesId", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "selected", + "required": false, + "schema": { + "type": "boolean" + } + } + ], + "requestBody": { + "content": { + "multipart/form-data": { + "schema": { + "type": "object", + "properties": { + "file": { + "type": "string", + "format": "binary" + } + }, + "required": [ + "file" + ] + } + } + } + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ThumbnailSeriesDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Add series poster", + "tags": [ + "Series Poster" + ] + } + }, + "/api/v1/series/{seriesId}/thumbnails/{thumbnailId}": { + "delete": { + "description": "Required role: **ADMIN**", + "operationId": "deleteUserUploadedSeriesThumbnail", + "parameters": [ + { + "in": "path", + "name": "seriesId", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "thumbnailId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Delete series poster", + "tags": [ + "Series Poster" + ] + }, + "get": { + "operationId": "getSeriesThumbnailById", + "parameters": [ + { + "in": "path", + "name": "seriesId", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "thumbnailId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + }, + "default": { + "content": { + "application/json": { + "schema": { + "type": "string", + "format": "binary" + } + }, + "image/jpeg": { + "schema": { + "type": "string", + "format": "binary" + } + } + }, + "description": "default response" + } + }, + "summary": "Get series poster image", + "tags": [ + "Series Poster" + ] + } + }, + "/api/v1/series/{seriesId}/thumbnails/{thumbnailId}/selected": { + "put": { + "description": "Required role: **ADMIN**", + "operationId": "markSeriesThumbnailSelected", + "parameters": [ + { + "in": "path", + "name": "seriesId", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "thumbnailId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Mark series poster as selected", + "tags": [ + "Series Poster" + ] + } + }, + "/api/v1/settings": { + "get": { + "description": "Required role: **ADMIN**", + "operationId": "getServerSettings", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SettingsDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Retrieve server settings", + "tags": [ + "Server settings" + ] + }, + "patch": { + "description": "You can omit fields you don't want to update\n\nRequired role: **ADMIN**", + "operationId": "updateServerSettings", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SettingsUpdateDto" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Update server settings", + "tags": [ + "Server settings" + ] + } + }, + "/api/v1/sharing-labels": { + "get": { + "deprecated": true, + "description": "Use GET /v2/sharing-labels instead. Deprecated since 1.26.0", + "operationId": "getSharingLabels_1", + "parameters": [ + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List sharing labels", + "tags": [ + "Deprecated", + "Referential metadata" + ] + } + }, + "/api/v1/syncpoints/me": { + "delete": { + "description": "If an API Key ID is passed, deletes only the sync points associated with that API Key. Deleting sync points will allow a Kobo to sync from scratch upon the next sync.", + "operationId": "deleteSyncPointsForCurrentUser", + "parameters": [ + { + "in": "query", + "name": "key_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Delete all sync points", + "tags": [ + "Sync points" + ] + } + }, + "/api/v1/tags": { + "get": { + "deprecated": true, + "description": "Use GET /v2/tags instead. Deprecated since 1.26.0", + "operationId": "getTags_1", + "parameters": [ + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List tags", + "tags": [ + "Deprecated", + "Referential metadata" + ] + } + }, + "/api/v1/tags/book": { + "get": { + "deprecated": true, + "description": "Use GET /v2/tags instead. Deprecated since 1.26.0", + "operationId": "getBookTags", + "parameters": [ + { + "in": "query", + "name": "series_id", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "readlist_id", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List book tags", + "tags": [ + "Deprecated", + "Referential metadata" + ] + } + }, + "/api/v1/tags/series": { + "get": { + "deprecated": true, + "description": "Use GET /v2/tags instead. Deprecated since 1.26.0", + "operationId": "getSeriesTags", + "parameters": [ + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List series tags", + "tags": [ + "Deprecated", + "Referential metadata" + ] + } + }, + "/api/v1/tasks": { + "delete": { + "description": "Cancel all tasks queued\n\nRequired role: **ADMIN**", + "operationId": "emptyTaskQueue", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "integer", + "format": "int32" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Clear task queue", + "tags": [ + "Tasks" + ] + } + }, + "/api/v1/transient-books": { + "post": { + "description": "Scan provided folder for transient books.\n\nRequired role: **ADMIN**", + "operationId": "scanTransientBooks", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ScanRequestDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TransientBookDto" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Scan folder for transient books", + "tags": [ + "Import" + ] + } + }, + "/api/v1/transient-books/{id}/analyze": { + "post": { + "description": "Required role: **ADMIN**", + "operationId": "analyzeTransientBook", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TransientBookDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Analyze transient book", + "tags": [ + "Import" + ] + } + }, + "/api/v1/transient-books/{id}/pages/{pageNumber}": { + "get": { + "description": "Required role: **ADMIN**", + "operationId": "getPageByTransientBookId", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "path", + "name": "pageNumber", + "required": true, + "schema": { + "type": "integer", + "format": "int32" + } + } + ], + "responses": { + "200": { + "content": { + "*/*": { + "schema": { + "type": "string", + "format": "byte" + } + }, + "application/json": { + "schema": { + "type": "string", + "format": "byte" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Get transient book page", + "tags": [ + "Import" + ] + } + }, + "/api/v2/age-ratings": { + "get": { + "description": "Can be filtered by various criteria", + "operationId": "getAgeRatings", + "parameters": [ + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageInteger" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List age ratings", + "tags": [ + "Referential metadata" + ] + } + }, + "/api/v2/authors": { + "get": { + "description": "Can be filtered by various criteria", + "operationId": "getAuthors", + "parameters": [ + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "role", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "series_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "readlist_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageAuthorDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List authors", + "tags": [ + "Referential metadata" + ] + } + }, + "/api/v2/authors/names": { + "get": { + "description": "Can be filtered by various criteria", + "operationId": "getAuthorsNames", + "parameters": [ + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "role", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "series_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "readlist_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageString" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List authors names", + "tags": [ + "Referential metadata" + ] + } + }, + "/api/v2/authors/roles": { + "get": { + "description": "Can be filtered by various criteria", + "operationId": "getAuthorsRoles", + "parameters": [ + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "series_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "readlist_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageString" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List authors roles", + "tags": [ + "Referential metadata" + ] + } + }, + "/api/v2/genres": { + "get": { + "description": "Can be filtered by various criteria", + "operationId": "getGenres", + "parameters": [ + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageString" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List genres", + "tags": [ + "Referential metadata" + ] + } + }, + "/api/v2/languages": { + "get": { + "description": "Can be filtered by various criteria", + "operationId": "getLanguages", + "parameters": [ + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageString" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List languages", + "tags": [ + "Referential metadata" + ] + } + }, + "/api/v2/publishers": { + "get": { + "description": "Can be filtered by various criteria", + "operationId": "getPublishers", + "parameters": [ + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageString" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List publishers", + "tags": [ + "Referential metadata" + ] + } + }, + "/api/v2/series/release-years": { + "get": { + "description": "Can be filtered by various criteria", + "operationId": "getSeriesReleaseYears", + "parameters": [ + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageString" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List series release years", + "tags": [ + "Referential metadata" + ] + } + }, + "/api/v2/series/{seriesId}/read-progress/tachiyomi": { + "get": { + "description": "Mihon specific, due to how read progress is handled in Mihon.", + "operationId": "getMihonReadProgressBySeriesId", + "parameters": [ + { + "in": "path", + "name": "seriesId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TachiyomiReadProgressV2Dto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Get series read progress (Mihon)", + "tags": [ + "Mihon" + ] + }, + "put": { + "description": "Mihon specific, due to how read progress is handled in Mihon.", + "operationId": "updateMihonReadProgressBySeriesId", + "parameters": [ + { + "in": "path", + "name": "seriesId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TachiyomiReadProgressUpdateV2Dto" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Update series read progress (Mihon)", + "tags": [ + "Mihon" + ] + } + }, + "/api/v2/sharing-labels": { + "get": { + "description": "Can be filtered by various criteria", + "operationId": "getSharingLabels", + "parameters": [ + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageString" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List sharing labels", + "tags": [ + "Referential metadata" + ] + } + }, + "/api/v2/tags": { + "get": { + "description": "Can be filtered by various criteria", + "operationId": "getTags", + "parameters": [ + { + "in": "query", + "name": "search", + "required": false, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "library_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "collection_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "series_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "readlist_id", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + { + "in": "query", + "name": "include", + "required": false, + "schema": { + "type": "string", + "enum": [ + "SERIES", + "BOOK", + "BOTH" + ] + } + }, + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer" + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageString" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List tags", + "tags": [ + "Referential metadata" + ] + } + }, + "/api/v2/users": { + "get": { + "description": "Required role: **ADMIN**", + "operationId": "getUsers", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/UserDto" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "List users", + "tags": [ + "Users" + ] + }, + "post": { + "description": "Required role: **ADMIN**", + "operationId": "addUser", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserCreationDto" + } + } + }, + "required": true + }, + "responses": { + "201": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserDto" + } + } + }, + "description": "Created" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Create user", + "tags": [ + "Users" + ] + } + }, + "/api/v2/users/authentication-activity": { + "get": { + "description": "Required role: **ADMIN**", + "operationId": "getAuthenticationActivity", + "parameters": [ + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer", + "default": 0 + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer", + "default": 20 + } + }, + { + "description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.", + "in": "query", + "name": "sort", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageAuthenticationActivityDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Retrieve authentication activity", + "tags": [ + "Users" + ] + } + }, + "/api/v2/users/me": { + "get": { + "operationId": "getCurrentUser", + "parameters": [ + { + "in": "query", + "name": "remember-me", + "required": false, + "schema": { + "type": "boolean" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Retrieve current user", + "tags": [ + "Current user" + ] + } + }, + "/api/v2/users/me/api-keys": { + "get": { + "operationId": "getApiKeysForCurrentUser", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ApiKeyDto" + } + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Retrieve API keys", + "tags": [ + "API Keys" + ] + }, + "post": { + "operationId": "createApiKeyForCurrentUser", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiKeyRequestDto" + } + } + }, + "required": true + }, + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ApiKeyDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Create API key", + "tags": [ + "API Keys" + ] + } + }, + "/api/v2/users/me/api-keys/{keyId}": { + "delete": { + "operationId": "deleteApiKeyByKeyId", + "parameters": [ + { + "in": "path", + "name": "keyId", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Delete API key", + "tags": [ + "API Keys" + ] + } + }, + "/api/v2/users/me/authentication-activity": { + "get": { + "operationId": "getAuthenticationActivityForCurrentUser", + "parameters": [ + { + "in": "query", + "name": "unpaged", + "required": false, + "schema": { + "type": "boolean" + } + }, + { + "description": "Zero-based page index (0..N)", + "in": "query", + "name": "page", + "schema": { + "type": "integer", + "default": 0 + } + }, + { + "description": "The size of the page to be returned", + "in": "query", + "name": "size", + "schema": { + "type": "integer", + "default": 20 + } + }, + { + "description": "Sorting criteria in the format: property,(asc|desc). Default sort order is ascending. Multiple sort criteria are supported.", + "in": "query", + "name": "sort", + "schema": { + "type": "array", + "items": { + "type": "string" + } + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PageAuthenticationActivityDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Retrieve authentication activity for the current user", + "tags": [ + "Current user" + ] + } + }, + "/api/v2/users/me/password": { + "patch": { + "operationId": "updatePasswordForCurrentUser", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PasswordUpdateDto" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Update current user's password", + "tags": [ + "Current user" + ] + } + }, + "/api/v2/users/{id}": { + "delete": { + "description": "Required role: **ADMIN**", + "operationId": "deleteUserById", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Delete user", + "tags": [ + "Users" + ] + }, + "patch": { + "description": "Required role: **ADMIN**", + "operationId": "updateUserById", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserUpdateDto" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Update user", + "tags": [ + "Users" + ] + } + }, + "/api/v2/users/{id}/authentication-activity/latest": { + "get": { + "description": "Required role: **ADMIN**", + "operationId": "getLatestAuthenticationActivityByUserId", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + }, + { + "in": "query", + "name": "apikey_id", + "required": false, + "schema": { + "type": "string" + } + } + ], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AuthenticationActivityDto" + } + } + }, + "description": "OK" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Retrieve latest authentication activity for a user", + "tags": [ + "Users" + ] + } + }, + "/api/v2/users/{id}/password": { + "patch": { + "description": "Required role: **ADMIN**", + "operationId": "updatePasswordByUserId", + "parameters": [ + { + "in": "path", + "name": "id", + "required": true, + "schema": { + "type": "string" + } + } + ], + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PasswordUpdateDto" + } + } + }, + "required": true + }, + "responses": { + "204": { + "description": "No Content" + }, + "400": { + "content": { + "*/*": { + "schema": { + "$ref": "#/components/schemas/ValidationErrorResponse" + } + } + }, + "description": "Bad Request" + } + }, + "summary": "Update user's password", + "tags": [ + "Users" + ] + } + } + }, + "components": { + "schemas": { + "AgeRestrictionDto": { + "type": "object", + "properties": { + "age": { + "type": "integer", + "format": "int32" + }, + "restriction": { + "type": "string", + "enum": [ + "ALLOW_ONLY", + "EXCLUDE" + ] + } + }, + "required": [ + "age", + "restriction" + ] + }, + "AgeRestrictionUpdateDto": { + "type": "object", + "properties": { + "age": { + "type": "integer", + "format": "int32" + }, + "restriction": { + "type": "string", + "enum": [ + "ALLOW_ONLY", + "EXCLUDE", + "NONE" + ] + } + }, + "required": [ + "age", + "restriction" + ] + }, + "AlternateTitleDto": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "title": { + "type": "string" + } + }, + "required": [ + "label", + "title" + ] + }, + "AlternateTitleUpdateDto": { + "type": "object", + "properties": { + "label": { + "type": "string", + "minLength": 1 + }, + "title": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "label", + "title" + ] + }, + "ApiKeyDto": { + "type": "object", + "properties": { + "comment": { + "type": "string" + }, + "createdDate": { + "type": "string", + "format": "date-time" + }, + "id": { + "type": "string" + }, + "key": { + "type": "string" + }, + "lastModifiedDate": { + "type": "string", + "format": "date-time" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "comment", + "createdDate", + "id", + "key", + "lastModifiedDate", + "userId" + ] + }, + "ApiKeyRequestDto": { + "type": "object", + "properties": { + "comment": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "comment" + ] + }, + "AuthenticationActivityDto": { + "type": "object", + "properties": { + "apiKeyComment": { + "type": "string" + }, + "apiKeyId": { + "type": "string" + }, + "dateTime": { + "type": "string", + "format": "date-time" + }, + "email": { + "type": "string" + }, + "error": { + "type": "string" + }, + "ip": { + "type": "string" + }, + "source": { + "type": "string" + }, + "success": { + "type": "boolean" + }, + "userAgent": { + "type": "string" + }, + "userId": { + "type": "string" + } + }, + "required": [ + "dateTime", + "success" + ] + }, + "AuthorDto": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "role": { + "type": "string" + } + }, + "required": [ + "name", + "role" + ] + }, + "AuthorUpdateDto": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "role": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "name", + "role" + ] + }, + "BookDto": { + "type": "object", + "properties": { + "created": { + "type": "string", + "format": "date-time" + }, + "deleted": { + "type": "boolean" + }, + "fileHash": { + "type": "string" + }, + "fileLastModified": { + "type": "string", + "format": "date-time" + }, + "id": { + "type": "string" + }, + "lastModified": { + "type": "string", + "format": "date-time" + }, + "libraryId": { + "type": "string" + }, + "media": { + "$ref": "#/components/schemas/MediaDto" + }, + "metadata": { + "$ref": "#/components/schemas/BookMetadataDto" + }, + "name": { + "type": "string" + }, + "number": { + "type": "integer", + "format": "int32" + }, + "oneshot": { + "type": "boolean" + }, + "readProgress": { + "$ref": "#/components/schemas/ReadProgressDto" + }, + "seriesId": { + "type": "string" + }, + "seriesTitle": { + "type": "string" + }, + "size": { + "type": "string" + }, + "sizeBytes": { + "type": "integer", + "format": "int64" + }, + "url": { + "type": "string" + } + }, + "required": [ + "created", + "deleted", + "fileHash", + "fileLastModified", + "id", + "lastModified", + "libraryId", + "media", + "metadata", + "name", + "number", + "oneshot", + "seriesId", + "seriesTitle", + "size", + "sizeBytes", + "url" + ] + }, + "BookImportBatchDto": { + "type": "object", + "properties": { + "books": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BookImportDto" + } + }, + "copyMode": { + "type": "string", + "enum": [ + "MOVE", + "COPY", + "HARDLINK" + ] + } + }, + "required": [ + "books", + "copyMode" + ] + }, + "BookImportDto": { + "type": "object", + "properties": { + "destinationName": { + "type": "string" + }, + "seriesId": { + "type": "string" + }, + "sourceFile": { + "type": "string" + }, + "upgradeBookId": { + "type": "string" + } + }, + "required": [ + "seriesId", + "sourceFile" + ] + }, + "BookMetadataAggregationDto": { + "type": "object", + "properties": { + "authors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AuthorDto" + } + }, + "created": { + "type": "string", + "format": "date-time" + }, + "lastModified": { + "type": "string", + "format": "date-time" + }, + "releaseDate": { + "type": "string", + "format": "date" + }, + "summary": { + "type": "string" + }, + "summaryNumber": { + "type": "string" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + "required": [ + "authors", + "created", + "lastModified", + "summary", + "summaryNumber", + "tags" + ] + }, + "BookMetadataDto": { + "type": "object", + "properties": { + "authors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AuthorDto" + } + }, + "authorsLock": { + "type": "boolean" + }, + "created": { + "type": "string", + "format": "date-time" + }, + "isbn": { + "type": "string" + }, + "isbnLock": { + "type": "boolean" + }, + "lastModified": { + "type": "string", + "format": "date-time" + }, + "links": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WebLinkDto" + } + }, + "linksLock": { + "type": "boolean" + }, + "number": { + "type": "string" + }, + "numberLock": { + "type": "boolean" + }, + "numberSort": { + "type": "number", + "format": "float" + }, + "numberSortLock": { + "type": "boolean" + }, + "releaseDate": { + "type": "string", + "format": "date" + }, + "releaseDateLock": { + "type": "boolean" + }, + "summary": { + "type": "string" + }, + "summaryLock": { + "type": "boolean" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "tagsLock": { + "type": "boolean" + }, + "title": { + "type": "string" + }, + "titleLock": { + "type": "boolean" + } + }, + "required": [ + "authors", + "authorsLock", + "created", + "isbn", + "isbnLock", + "lastModified", + "links", + "linksLock", + "number", + "numberLock", + "numberSort", + "numberSortLock", + "releaseDateLock", + "summary", + "summaryLock", + "tags", + "tagsLock", + "title", + "titleLock" + ] + }, + "BookMetadataUpdateDto": { + "type": "object", + "description": "Metadata fields to update. Set a field to null to unset the metadata. You can omit fields you don't want to update.", + "properties": { + "authors": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AuthorUpdateDto" + } + }, + "authorsLock": { + "type": "boolean" + }, + "isbn": { + "type": "string" + }, + "isbnLock": { + "type": "boolean" + }, + "links": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WebLinkUpdateDto" + } + }, + "linksLock": { + "type": "boolean" + }, + "number": { + "type": "string" + }, + "numberLock": { + "type": "boolean" + }, + "numberSort": { + "type": "number", + "format": "float" + }, + "numberSortLock": { + "type": "boolean" + }, + "releaseDate": { + "type": "string", + "format": "date" + }, + "releaseDateLock": { + "type": "boolean" + }, + "summary": { + "type": "string" + }, + "summaryLock": { + "type": "boolean" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "tagsLock": { + "type": "boolean" + }, + "title": { + "type": "string" + }, + "titleLock": { + "type": "boolean" + } + } + }, + "BookSearch": { + "type": "object", + "properties": { + "condition": { + "$ref": "#/components/schemas/SearchConditionBook" + }, + "fullTextSearch": { + "type": "string" + } + } + }, + "ClaimStatus": { + "type": "object", + "properties": { + "isClaimed": { + "type": "boolean" + } + }, + "required": [ + "isClaimed" + ] + }, + "ClientSettingDto": { + "type": "object", + "properties": { + "allowUnauthorized": { + "type": "boolean" + }, + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + "ClientSettingGlobalUpdateDto": { + "type": "object", + "properties": { + "allowUnauthorized": { + "type": "boolean" + }, + "value": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "allowUnauthorized", + "value" + ] + }, + "ClientSettingUserUpdateDto": { + "type": "object", + "properties": { + "value": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "value" + ] + }, + "CollectionCreationDto": { + "type": "object", + "properties": { + "name": { + "type": "string", + "minLength": 1 + }, + "ordered": { + "type": "boolean" + }, + "seriesIds": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1 + } + }, + "required": [ + "name", + "ordered", + "seriesIds" + ] + }, + "CollectionDto": { + "type": "object", + "properties": { + "createdDate": { + "type": "string", + "format": "date-time" + }, + "filtered": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "lastModifiedDate": { + "type": "string", + "format": "date-time" + }, + "name": { + "type": "string" + }, + "ordered": { + "type": "boolean" + }, + "seriesIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "createdDate", + "filtered", + "id", + "lastModifiedDate", + "name", + "ordered", + "seriesIds" + ] + }, + "CollectionUpdateDto": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "ordered": { + "type": "boolean" + }, + "seriesIds": { + "type": "array", + "items": { + "type": "string" + } + } + } + }, + "DirectoryListingDto": { + "type": "object", + "properties": { + "directories": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PathDto" + } + }, + "files": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PathDto" + } + }, + "parent": { + "type": "string" + } + }, + "required": [ + "directories", + "files" + ] + }, + "DirectoryRequestDto": { + "type": "object", + "properties": { + "path": { + "type": "string" + }, + "showFiles": { + "type": "boolean" + } + }, + "required": [ + "path", + "showFiles" + ] + }, + "GroupCountDto": { + "type": "object", + "properties": { + "count": { + "type": "integer", + "format": "int32" + }, + "group": { + "type": "string" + } + }, + "required": [ + "count", + "group" + ] + }, + "HistoricalEventDto": { + "type": "object", + "properties": { + "bookId": { + "type": "string" + }, + "id": { + "type": "string" + }, + "properties": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "seriesId": { + "type": "string" + }, + "timestamp": { + "type": "string", + "format": "date-time" + }, + "type": { + "type": "string" + } + }, + "required": [ + "id", + "properties", + "timestamp", + "type" + ] + }, + "ItemAuthorDto": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Author's name", + "example": "gotson" + }, + "url": { + "type": "string", + "description": "URL of a site owned by the author", + "example": "https://github.com/gotson" + } + } + }, + "ItemDto": { + "type": "object", + "properties": { + "_komga": { + "$ref": "#/components/schemas/KomgaExtensionDto", + "description": "Additional fields for the item" + }, + "author": { + "$ref": "#/components/schemas/ItemAuthorDto", + "description": "Author of the item" + }, + "content_html": { + "type": "string", + "description": "HTML of the item", + "example": "

A longer text…

" + }, + "date_modified": { + "type": "string", + "format": "date-time", + "description": "Modification date in RFC 3339 format", + "example": "2023-12-15T00:00:00Z" + }, + "id": { + "type": "string", + "description": "Unique for that item for that feed over time", + "example": "https://komga.org/blog/ebook-drop2" + }, + "summary": { + "type": "string", + "description": "A plain text sentence or two describing the item", + "example": "Version 1.9.0 contains the second feature drop for Ebooks support." + }, + "tags": { + "type": "array", + "description": "Tags describing the item", + "examples": [ + "upgrade", + "komga" + ], + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "title": { + "type": "string", + "description": "Plain text title", + "example": "eBook drop 2" + }, + "url": { + "type": "string", + "description": "URL of the resource described by the item", + "example": "https://komga.org/blog/ebook-drop2" + } + }, + "required": [ + "id", + "tags" + ] + }, + "JsonFeedDto": { + "type": "object", + "example": { + "version": "https://jsonfeed.org/version/1", + "title": "Announcements", + "home_page_url": "https://komga.org/blog", + "description": "Latest Komga announcements", + "items": [ + { + "id": "https://komga.org/blog/ebook-drop2", + "url": "https://komga.org/blog/ebook-drop2", + "title": "eBook drop 2", + "summary": "Version 1.9.0 contains the second feature drop for Ebooks support.", + "content_html": "

A longer text…

", + "date_modified": "2023-12-15T00:00:00Z", + "author": { + "name": "gotson", + "url": "https://github.com/gotson" + }, + "tags": [ + "upgrade", + "komga" + ], + "_komga": { + "read": false + } + }, + { + "id": "https://komga.org/blog/ebook-support", + "url": "https://komga.org/blog/ebook-support", + "title": "eBook support", + "summary": "Version 1.8.0 is bringing a long awaited feature: proper eBook support!", + "content_html": "

A longer text…

", + "date_modified": "2023-11-29T00:00:00Z", + "author": { + "name": "gotson", + "url": "https://github.com/gotson" + }, + "tags": [ + "upgrade", + "komga" + ], + "_komga": { + "read": true + } + } + ] + }, + "properties": { + "description": { + "type": "string", + "description": "Provides more detail on what the feed is about", + "example": "Latest Komga announcements" + }, + "home_page_url": { + "type": "string", + "description": "URL of the resource that the feed describes", + "example": "https://komga.org/blog" + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ItemDto" + } + }, + "title": { + "type": "string", + "description": "Name of the feed", + "example": "Announcements" + }, + "version": { + "type": "string", + "description": "URL of the version of the format the feed uses", + "example": "https://jsonfeed.org/version/1" + } + }, + "required": [ + "items", + "title", + "version" + ] + }, + "KomgaExtensionDto": { + "type": "object", + "properties": { + "read": { + "type": "boolean", + "description": "Whether the current item has been marked read by the current user", + "example": false + } + }, + "required": [ + "read" + ] + }, + "LibraryCreationDto": { + "type": "object", + "properties": { + "analyzeDimensions": { + "type": "boolean" + }, + "convertToCbz": { + "type": "boolean" + }, + "emptyTrashAfterScan": { + "type": "boolean" + }, + "hashFiles": { + "type": "boolean" + }, + "hashKoreader": { + "type": "boolean" + }, + "hashPages": { + "type": "boolean" + }, + "importBarcodeIsbn": { + "type": "boolean" + }, + "importComicInfoBook": { + "type": "boolean" + }, + "importComicInfoCollection": { + "type": "boolean" + }, + "importComicInfoReadList": { + "type": "boolean" + }, + "importComicInfoSeries": { + "type": "boolean" + }, + "importComicInfoSeriesAppendVolume": { + "type": "boolean" + }, + "importEpubBook": { + "type": "boolean" + }, + "importEpubSeries": { + "type": "boolean" + }, + "importLocalArtwork": { + "type": "boolean" + }, + "importMylarSeries": { + "type": "boolean" + }, + "name": { + "type": "string", + "minLength": 1 + }, + "oneshotsDirectory": { + "type": "string" + }, + "repairExtensions": { + "type": "boolean" + }, + "root": { + "type": "string", + "minLength": 1 + }, + "scanCbx": { + "type": "boolean" + }, + "scanDirectoryExclusions": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "scanEpub": { + "type": "boolean" + }, + "scanForceModifiedTime": { + "type": "boolean" + }, + "scanInterval": { + "type": "string", + "enum": [ + "DISABLED", + "HOURLY", + "EVERY_6H", + "EVERY_12H", + "DAILY", + "WEEKLY" + ] + }, + "scanOnStartup": { + "type": "boolean" + }, + "scanPdf": { + "type": "boolean" + }, + "seriesCover": { + "type": "string", + "enum": [ + "FIRST", + "FIRST_UNREAD_OR_FIRST", + "FIRST_UNREAD_OR_LAST", + "LAST" + ] + } + }, + "required": [ + "analyzeDimensions", + "convertToCbz", + "emptyTrashAfterScan", + "hashFiles", + "hashKoreader", + "hashPages", + "importBarcodeIsbn", + "importComicInfoBook", + "importComicInfoCollection", + "importComicInfoReadList", + "importComicInfoSeries", + "importComicInfoSeriesAppendVolume", + "importEpubBook", + "importEpubSeries", + "importLocalArtwork", + "importMylarSeries", + "name", + "repairExtensions", + "root", + "scanCbx", + "scanDirectoryExclusions", + "scanEpub", + "scanForceModifiedTime", + "scanInterval", + "scanOnStartup", + "scanPdf", + "seriesCover" + ] + }, + "LibraryDto": { + "type": "object", + "properties": { + "analyzeDimensions": { + "type": "boolean" + }, + "convertToCbz": { + "type": "boolean" + }, + "emptyTrashAfterScan": { + "type": "boolean" + }, + "hashFiles": { + "type": "boolean" + }, + "hashKoreader": { + "type": "boolean" + }, + "hashPages": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "importBarcodeIsbn": { + "type": "boolean" + }, + "importComicInfoBook": { + "type": "boolean" + }, + "importComicInfoCollection": { + "type": "boolean" + }, + "importComicInfoReadList": { + "type": "boolean" + }, + "importComicInfoSeries": { + "type": "boolean" + }, + "importComicInfoSeriesAppendVolume": { + "type": "boolean" + }, + "importEpubBook": { + "type": "boolean" + }, + "importEpubSeries": { + "type": "boolean" + }, + "importLocalArtwork": { + "type": "boolean" + }, + "importMylarSeries": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "oneshotsDirectory": { + "type": "string" + }, + "repairExtensions": { + "type": "boolean" + }, + "root": { + "type": "string" + }, + "scanCbx": { + "type": "boolean" + }, + "scanDirectoryExclusions": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "scanEpub": { + "type": "boolean" + }, + "scanForceModifiedTime": { + "type": "boolean" + }, + "scanInterval": { + "type": "string", + "enum": [ + "DISABLED", + "HOURLY", + "EVERY_6H", + "EVERY_12H", + "DAILY", + "WEEKLY" + ] + }, + "scanOnStartup": { + "type": "boolean" + }, + "scanPdf": { + "type": "boolean" + }, + "seriesCover": { + "type": "string", + "enum": [ + "FIRST", + "FIRST_UNREAD_OR_FIRST", + "FIRST_UNREAD_OR_LAST", + "LAST" + ] + }, + "unavailable": { + "type": "boolean" + } + }, + "required": [ + "analyzeDimensions", + "convertToCbz", + "emptyTrashAfterScan", + "hashFiles", + "hashKoreader", + "hashPages", + "id", + "importBarcodeIsbn", + "importComicInfoBook", + "importComicInfoCollection", + "importComicInfoReadList", + "importComicInfoSeries", + "importComicInfoSeriesAppendVolume", + "importEpubBook", + "importEpubSeries", + "importLocalArtwork", + "importMylarSeries", + "name", + "repairExtensions", + "root", + "scanCbx", + "scanDirectoryExclusions", + "scanEpub", + "scanForceModifiedTime", + "scanInterval", + "scanOnStartup", + "scanPdf", + "seriesCover", + "unavailable" + ] + }, + "LibraryUpdateDto": { + "type": "object", + "description": "Fields to update. You can omit fields you don't want to update.", + "properties": { + "analyzeDimensions": { + "type": "boolean" + }, + "convertToCbz": { + "type": "boolean" + }, + "emptyTrashAfterScan": { + "type": "boolean" + }, + "hashFiles": { + "type": "boolean" + }, + "hashKoreader": { + "type": "boolean" + }, + "hashPages": { + "type": "boolean" + }, + "importBarcodeIsbn": { + "type": "boolean" + }, + "importComicInfoBook": { + "type": "boolean" + }, + "importComicInfoCollection": { + "type": "boolean" + }, + "importComicInfoReadList": { + "type": "boolean" + }, + "importComicInfoSeries": { + "type": "boolean" + }, + "importComicInfoSeriesAppendVolume": { + "type": "boolean" + }, + "importEpubBook": { + "type": "boolean" + }, + "importEpubSeries": { + "type": "boolean" + }, + "importLocalArtwork": { + "type": "boolean" + }, + "importMylarSeries": { + "type": "boolean" + }, + "name": { + "type": "string" + }, + "oneshotsDirectory": { + "type": "string" + }, + "repairExtensions": { + "type": "boolean" + }, + "root": { + "type": "string" + }, + "scanCbx": { + "type": "boolean" + }, + "scanDirectoryExclusions": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "scanEpub": { + "type": "boolean" + }, + "scanForceModifiedTime": { + "type": "boolean" + }, + "scanInterval": { + "type": "string", + "enum": [ + "DISABLED", + "HOURLY", + "EVERY_6H", + "EVERY_12H", + "DAILY", + "WEEKLY" + ] + }, + "scanOnStartup": { + "type": "boolean" + }, + "scanPdf": { + "type": "boolean" + }, + "seriesCover": { + "type": "string", + "enum": [ + "FIRST", + "FIRST_UNREAD_OR_FIRST", + "FIRST_UNREAD_OR_LAST", + "LAST" + ] + } + } + }, + "Location": { + "type": "object", + "properties": { + "fragments": { + "type": "array", + "items": { + "type": "string" + } + }, + "position": { + "type": "integer", + "format": "int32" + }, + "progression": { + "type": "number", + "format": "float" + }, + "totalProgression": { + "type": "number", + "format": "float" + } + }, + "required": [ + "fragments" + ] + }, + "MediaDto": { + "type": "object", + "properties": { + "comment": { + "type": "string" + }, + "epubDivinaCompatible": { + "type": "boolean" + }, + "epubIsKepub": { + "type": "boolean" + }, + "mediaProfile": { + "type": "string" + }, + "mediaType": { + "type": "string" + }, + "pagesCount": { + "type": "integer", + "format": "int32" + }, + "status": { + "type": "string" + } + }, + "required": [ + "comment", + "epubDivinaCompatible", + "epubIsKepub", + "mediaProfile", + "mediaType", + "pagesCount", + "status" + ] + }, + "MediaType": { + "type": "object", + "properties": { + "charset": { + "type": "string" + }, + "concrete": { + "type": "boolean" + }, + "parameters": { + "type": "object", + "additionalProperties": { + "type": "string" + } + }, + "qualityValue": { + "type": "number", + "format": "double" + }, + "subtype": { + "type": "string" + }, + "subtypeSuffix": { + "type": "string" + }, + "type": { + "type": "string" + }, + "wildcardSubtype": { + "type": "boolean" + }, + "wildcardType": { + "type": "boolean" + } + } + }, + "OAuth2ClientDto": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "registrationId": { + "type": "string" + } + }, + "required": [ + "name", + "registrationId" + ] + }, + "PageAuthenticationActivityDto": { + "type": "object", + "properties": { + "content": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AuthenticationActivityDto" + } + }, + "empty": { + "type": "boolean" + }, + "first": { + "type": "boolean" + }, + "last": { + "type": "boolean" + }, + "number": { + "type": "integer", + "format": "int32" + }, + "numberOfElements": { + "type": "integer", + "format": "int32" + }, + "pageable": { + "$ref": "#/components/schemas/PageableObject" + }, + "size": { + "type": "integer", + "format": "int32" + }, + "sort": { + "$ref": "#/components/schemas/SortObject" + }, + "totalElements": { + "type": "integer", + "format": "int64" + }, + "totalPages": { + "type": "integer", + "format": "int32" + } + } + }, + "PageAuthorDto": { + "type": "object", + "properties": { + "content": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AuthorDto" + } + }, + "empty": { + "type": "boolean" + }, + "first": { + "type": "boolean" + }, + "last": { + "type": "boolean" + }, + "number": { + "type": "integer", + "format": "int32" + }, + "numberOfElements": { + "type": "integer", + "format": "int32" + }, + "pageable": { + "$ref": "#/components/schemas/PageableObject" + }, + "size": { + "type": "integer", + "format": "int32" + }, + "sort": { + "$ref": "#/components/schemas/SortObject" + }, + "totalElements": { + "type": "integer", + "format": "int64" + }, + "totalPages": { + "type": "integer", + "format": "int32" + } + } + }, + "PageBookDto": { + "type": "object", + "properties": { + "content": { + "type": "array", + "items": { + "$ref": "#/components/schemas/BookDto" + } + }, + "empty": { + "type": "boolean" + }, + "first": { + "type": "boolean" + }, + "last": { + "type": "boolean" + }, + "number": { + "type": "integer", + "format": "int32" + }, + "numberOfElements": { + "type": "integer", + "format": "int32" + }, + "pageable": { + "$ref": "#/components/schemas/PageableObject" + }, + "size": { + "type": "integer", + "format": "int32" + }, + "sort": { + "$ref": "#/components/schemas/SortObject" + }, + "totalElements": { + "type": "integer", + "format": "int64" + }, + "totalPages": { + "type": "integer", + "format": "int32" + } + } + }, + "PageCollectionDto": { + "type": "object", + "properties": { + "content": { + "type": "array", + "items": { + "$ref": "#/components/schemas/CollectionDto" + } + }, + "empty": { + "type": "boolean" + }, + "first": { + "type": "boolean" + }, + "last": { + "type": "boolean" + }, + "number": { + "type": "integer", + "format": "int32" + }, + "numberOfElements": { + "type": "integer", + "format": "int32" + }, + "pageable": { + "$ref": "#/components/schemas/PageableObject" + }, + "size": { + "type": "integer", + "format": "int32" + }, + "sort": { + "$ref": "#/components/schemas/SortObject" + }, + "totalElements": { + "type": "integer", + "format": "int64" + }, + "totalPages": { + "type": "integer", + "format": "int32" + } + } + }, + "PageDto": { + "type": "object", + "properties": { + "fileName": { + "type": "string" + }, + "height": { + "type": "integer", + "format": "int32" + }, + "mediaType": { + "type": "string" + }, + "number": { + "type": "integer", + "format": "int32" + }, + "size": { + "type": "string" + }, + "sizeBytes": { + "type": "integer", + "format": "int64" + }, + "width": { + "type": "integer", + "format": "int32" + } + }, + "required": [ + "fileName", + "mediaType", + "number", + "size" + ] + }, + "PageHashCreationDto": { + "type": "object", + "properties": { + "action": { + "type": "string", + "enum": [ + "DELETE_AUTO", + "DELETE_MANUAL", + "IGNORE" + ] + }, + "hash": { + "type": "string", + "minLength": 1 + }, + "size": { + "type": "integer", + "format": "int64" + } + }, + "required": [ + "action", + "hash" + ] + }, + "PageHashKnownDto": { + "type": "object", + "properties": { + "action": { + "type": "string", + "enum": [ + "DELETE_AUTO", + "DELETE_MANUAL", + "IGNORE" + ] + }, + "created": { + "type": "string", + "format": "date-time" + }, + "deleteCount": { + "type": "integer", + "format": "int32" + }, + "hash": { + "type": "string" + }, + "lastModified": { + "type": "string", + "format": "date-time" + }, + "matchCount": { + "type": "integer", + "format": "int32" + }, + "size": { + "type": "integer", + "format": "int64" + } + }, + "required": [ + "action", + "created", + "deleteCount", + "hash", + "lastModified", + "matchCount" + ] + }, + "PageHashMatchDto": { + "type": "object", + "properties": { + "bookId": { + "type": "string" + }, + "fileName": { + "type": "string" + }, + "fileSize": { + "type": "integer", + "format": "int64" + }, + "mediaType": { + "type": "string" + }, + "pageNumber": { + "type": "integer", + "format": "int32" + }, + "url": { + "type": "string" + } + }, + "required": [ + "bookId", + "fileName", + "fileSize", + "mediaType", + "pageNumber", + "url" + ] + }, + "PageHashUnknownDto": { + "type": "object", + "properties": { + "hash": { + "type": "string" + }, + "matchCount": { + "type": "integer", + "format": "int32" + }, + "size": { + "type": "integer", + "format": "int64" + } + }, + "required": [ + "hash", + "matchCount" + ] + }, + "PageHistoricalEventDto": { + "type": "object", + "properties": { + "content": { + "type": "array", + "items": { + "$ref": "#/components/schemas/HistoricalEventDto" + } + }, + "empty": { + "type": "boolean" + }, + "first": { + "type": "boolean" + }, + "last": { + "type": "boolean" + }, + "number": { + "type": "integer", + "format": "int32" + }, + "numberOfElements": { + "type": "integer", + "format": "int32" + }, + "pageable": { + "$ref": "#/components/schemas/PageableObject" + }, + "size": { + "type": "integer", + "format": "int32" + }, + "sort": { + "$ref": "#/components/schemas/SortObject" + }, + "totalElements": { + "type": "integer", + "format": "int64" + }, + "totalPages": { + "type": "integer", + "format": "int32" + } + } + }, + "PageInteger": { + "type": "object", + "properties": { + "content": { + "type": "array", + "items": { + "type": "integer", + "format": "int32" + } + }, + "empty": { + "type": "boolean" + }, + "first": { + "type": "boolean" + }, + "last": { + "type": "boolean" + }, + "number": { + "type": "integer", + "format": "int32" + }, + "numberOfElements": { + "type": "integer", + "format": "int32" + }, + "pageable": { + "$ref": "#/components/schemas/PageableObject" + }, + "size": { + "type": "integer", + "format": "int32" + }, + "sort": { + "$ref": "#/components/schemas/SortObject" + }, + "totalElements": { + "type": "integer", + "format": "int64" + }, + "totalPages": { + "type": "integer", + "format": "int32" + } + } + }, + "PagePageHashKnownDto": { + "type": "object", + "properties": { + "content": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PageHashKnownDto" + } + }, + "empty": { + "type": "boolean" + }, + "first": { + "type": "boolean" + }, + "last": { + "type": "boolean" + }, + "number": { + "type": "integer", + "format": "int32" + }, + "numberOfElements": { + "type": "integer", + "format": "int32" + }, + "pageable": { + "$ref": "#/components/schemas/PageableObject" + }, + "size": { + "type": "integer", + "format": "int32" + }, + "sort": { + "$ref": "#/components/schemas/SortObject" + }, + "totalElements": { + "type": "integer", + "format": "int64" + }, + "totalPages": { + "type": "integer", + "format": "int32" + } + } + }, + "PagePageHashMatchDto": { + "type": "object", + "properties": { + "content": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PageHashMatchDto" + } + }, + "empty": { + "type": "boolean" + }, + "first": { + "type": "boolean" + }, + "last": { + "type": "boolean" + }, + "number": { + "type": "integer", + "format": "int32" + }, + "numberOfElements": { + "type": "integer", + "format": "int32" + }, + "pageable": { + "$ref": "#/components/schemas/PageableObject" + }, + "size": { + "type": "integer", + "format": "int32" + }, + "sort": { + "$ref": "#/components/schemas/SortObject" + }, + "totalElements": { + "type": "integer", + "format": "int64" + }, + "totalPages": { + "type": "integer", + "format": "int32" + } + } + }, + "PagePageHashUnknownDto": { + "type": "object", + "properties": { + "content": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PageHashUnknownDto" + } + }, + "empty": { + "type": "boolean" + }, + "first": { + "type": "boolean" + }, + "last": { + "type": "boolean" + }, + "number": { + "type": "integer", + "format": "int32" + }, + "numberOfElements": { + "type": "integer", + "format": "int32" + }, + "pageable": { + "$ref": "#/components/schemas/PageableObject" + }, + "size": { + "type": "integer", + "format": "int32" + }, + "sort": { + "$ref": "#/components/schemas/SortObject" + }, + "totalElements": { + "type": "integer", + "format": "int64" + }, + "totalPages": { + "type": "integer", + "format": "int32" + } + } + }, + "PageReadListDto": { + "type": "object", + "properties": { + "content": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ReadListDto" + } + }, + "empty": { + "type": "boolean" + }, + "first": { + "type": "boolean" + }, + "last": { + "type": "boolean" + }, + "number": { + "type": "integer", + "format": "int32" + }, + "numberOfElements": { + "type": "integer", + "format": "int32" + }, + "pageable": { + "$ref": "#/components/schemas/PageableObject" + }, + "size": { + "type": "integer", + "format": "int32" + }, + "sort": { + "$ref": "#/components/schemas/SortObject" + }, + "totalElements": { + "type": "integer", + "format": "int64" + }, + "totalPages": { + "type": "integer", + "format": "int32" + } + } + }, + "PageSeriesDto": { + "type": "object", + "properties": { + "content": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SeriesDto" + } + }, + "empty": { + "type": "boolean" + }, + "first": { + "type": "boolean" + }, + "last": { + "type": "boolean" + }, + "number": { + "type": "integer", + "format": "int32" + }, + "numberOfElements": { + "type": "integer", + "format": "int32" + }, + "pageable": { + "$ref": "#/components/schemas/PageableObject" + }, + "size": { + "type": "integer", + "format": "int32" + }, + "sort": { + "$ref": "#/components/schemas/SortObject" + }, + "totalElements": { + "type": "integer", + "format": "int64" + }, + "totalPages": { + "type": "integer", + "format": "int32" + } + } + }, + "PageString": { + "type": "object", + "properties": { + "content": { + "type": "array", + "items": { + "type": "string" + } + }, + "empty": { + "type": "boolean" + }, + "first": { + "type": "boolean" + }, + "last": { + "type": "boolean" + }, + "number": { + "type": "integer", + "format": "int32" + }, + "numberOfElements": { + "type": "integer", + "format": "int32" + }, + "pageable": { + "$ref": "#/components/schemas/PageableObject" + }, + "size": { + "type": "integer", + "format": "int32" + }, + "sort": { + "$ref": "#/components/schemas/SortObject" + }, + "totalElements": { + "type": "integer", + "format": "int64" + }, + "totalPages": { + "type": "integer", + "format": "int32" + } + } + }, + "PageableObject": { + "type": "object", + "properties": { + "offset": { + "type": "integer", + "format": "int64" + }, + "pageNumber": { + "type": "integer", + "format": "int32" + }, + "pageSize": { + "type": "integer", + "format": "int32" + }, + "paged": { + "type": "boolean" + }, + "sort": { + "$ref": "#/components/schemas/SortObject" + }, + "unpaged": { + "type": "boolean" + } + } + }, + "PasswordUpdateDto": { + "type": "object", + "properties": { + "password": { + "type": "string", + "minLength": 1 + } + }, + "required": [ + "password" + ] + }, + "PathDto": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "path": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "name", + "path", + "type" + ] + }, + "R2Device": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "id", + "name" + ] + }, + "R2Locator": { + "type": "object", + "properties": { + "href": { + "type": "string" + }, + "koboSpan": { + "type": "string" + }, + "locations": { + "$ref": "#/components/schemas/Location" + }, + "text": { + "$ref": "#/components/schemas/Text" + }, + "title": { + "type": "string" + }, + "type": { + "type": "string" + } + }, + "required": [ + "href", + "type" + ] + }, + "R2Positions": { + "type": "object", + "properties": { + "positions": { + "type": "array", + "items": { + "$ref": "#/components/schemas/R2Locator" + } + }, + "total": { + "type": "integer", + "format": "int32" + } + }, + "required": [ + "positions", + "total" + ] + }, + "R2Progression": { + "type": "object", + "properties": { + "device": { + "$ref": "#/components/schemas/R2Device" + }, + "locator": { + "$ref": "#/components/schemas/R2Locator" + }, + "modified": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "device", + "locator", + "modified" + ] + }, + "ReadListCreationDto": { + "type": "object", + "properties": { + "bookIds": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1 + }, + "name": { + "type": "string", + "minLength": 1 + }, + "ordered": { + "type": "boolean" + }, + "summary": { + "type": "string" + } + }, + "required": [ + "bookIds", + "name", + "ordered", + "summary" + ] + }, + "ReadListDto": { + "type": "object", + "properties": { + "bookIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "createdDate": { + "type": "string", + "format": "date-time" + }, + "filtered": { + "type": "boolean" + }, + "id": { + "type": "string" + }, + "lastModifiedDate": { + "type": "string", + "format": "date-time" + }, + "name": { + "type": "string" + }, + "ordered": { + "type": "boolean" + }, + "summary": { + "type": "string" + } + }, + "required": [ + "bookIds", + "createdDate", + "filtered", + "id", + "lastModifiedDate", + "name", + "ordered", + "summary" + ] + }, + "ReadListMatchDto": { + "type": "object", + "properties": { + "errorCode": { + "type": "string" + }, + "name": { + "type": "string" + } + }, + "required": [ + "errorCode", + "name" + ] + }, + "ReadListRequestBookDto": { + "type": "object", + "properties": { + "number": { + "type": "string" + }, + "series": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + "required": [ + "number", + "series" + ] + }, + "ReadListRequestBookMatchBookDto": { + "type": "object", + "properties": { + "bookId": { + "type": "string" + }, + "number": { + "type": "string" + }, + "title": { + "type": "string" + } + }, + "required": [ + "bookId", + "number", + "title" + ] + }, + "ReadListRequestBookMatchDto": { + "type": "object", + "properties": { + "books": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ReadListRequestBookMatchBookDto" + } + }, + "series": { + "$ref": "#/components/schemas/ReadListRequestBookMatchSeriesDto" + } + }, + "required": [ + "books", + "series" + ] + }, + "ReadListRequestBookMatchSeriesDto": { + "type": "object", + "properties": { + "releaseDate": { + "type": "string", + "format": "date" + }, + "seriesId": { + "type": "string" + }, + "title": { + "type": "string" + } + }, + "required": [ + "seriesId", + "title" + ] + }, + "ReadListRequestBookMatchesDto": { + "type": "object", + "properties": { + "matches": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ReadListRequestBookMatchDto" + } + }, + "request": { + "$ref": "#/components/schemas/ReadListRequestBookDto" + } + }, + "required": [ + "matches", + "request" + ] + }, + "ReadListRequestMatchDto": { + "type": "object", + "properties": { + "errorCode": { + "type": "string" + }, + "readListMatch": { + "$ref": "#/components/schemas/ReadListMatchDto" + }, + "requests": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ReadListRequestBookMatchesDto" + } + } + }, + "required": [ + "errorCode", + "readListMatch", + "requests" + ] + }, + "ReadListUpdateDto": { + "type": "object", + "properties": { + "bookIds": { + "type": "array", + "items": { + "type": "string" + } + }, + "name": { + "type": "string" + }, + "ordered": { + "type": "boolean" + }, + "summary": { + "type": "string" + } + } + }, + "ReadProgressDto": { + "type": "object", + "properties": { + "completed": { + "type": "boolean" + }, + "created": { + "type": "string", + "format": "date-time" + }, + "deviceId": { + "type": "string" + }, + "deviceName": { + "type": "string" + }, + "lastModified": { + "type": "string", + "format": "date-time" + }, + "page": { + "type": "integer", + "format": "int32" + }, + "readDate": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "completed", + "created", + "deviceId", + "deviceName", + "lastModified", + "page", + "readDate" + ] + }, + "ReadProgressUpdateDto": { + "type": "object", + "description": "page can be omitted if completed is set to true. completed can be omitted, and will be set accordingly depending on the page passed and the total number of pages in the book.", + "properties": { + "completed": { + "type": "boolean" + }, + "page": { + "type": "integer", + "format": "int32" + } + } + }, + "ReleaseDto": { + "type": "object", + "properties": { + "description": { + "type": "string" + }, + "latest": { + "type": "boolean" + }, + "preRelease": { + "type": "boolean" + }, + "releaseDate": { + "type": "string", + "format": "date-time" + }, + "url": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "required": [ + "description", + "latest", + "preRelease", + "releaseDate", + "url", + "version" + ] + }, + "ScanRequestDto": { + "type": "object", + "properties": { + "path": { + "type": "string" + } + }, + "required": [ + "path" + ] + }, + "SearchConditionAgeRating": { + "properties": { + "ageRating": { + "$ref": "#/components/schemas/SearchOperatorNumericNullableInteger" + } + }, + "required": [ + "ageRating" + ] + }, + "SearchConditionAllOfBook": { + "properties": { + "allOf": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SearchConditionBook" + } + } + }, + "required": [ + "allOf" + ] + }, + "SearchConditionAllOfSeries": { + "properties": { + "allOf": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SearchConditionSeries" + } + } + }, + "required": [ + "allOf" + ] + }, + "SearchConditionAnyOfBook": { + "properties": { + "anyOf": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SearchConditionBook" + } + } + }, + "required": [ + "anyOf" + ] + }, + "SearchConditionAnyOfSeries": { + "properties": { + "anyOf": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SearchConditionSeries" + } + } + }, + "required": [ + "anyOf" + ] + }, + "SearchConditionAuthor": { + "properties": { + "author": { + "$ref": "#/components/schemas/SearchOperatorEqualityAuthorMatch" + } + }, + "required": [ + "author" + ] + }, + "SearchConditionBook": { + "oneOf": [ + { + "$ref": "#/components/schemas/SearchConditionAnyOfBook" + }, + { + "$ref": "#/components/schemas/SearchConditionAllOfBook" + }, + { + "$ref": "#/components/schemas/SearchConditionLibraryId" + }, + { + "$ref": "#/components/schemas/SearchConditionReadListId" + }, + { + "$ref": "#/components/schemas/SearchConditionSeriesId" + }, + { + "$ref": "#/components/schemas/SearchConditionDeleted" + }, + { + "$ref": "#/components/schemas/SearchConditionOneShot" + }, + { + "$ref": "#/components/schemas/SearchConditionTitle" + }, + { + "$ref": "#/components/schemas/SearchConditionReleaseDate" + }, + { + "$ref": "#/components/schemas/SearchConditionTag" + }, + { + "$ref": "#/components/schemas/SearchConditionNumberSort" + }, + { + "$ref": "#/components/schemas/SearchConditionReadStatus" + }, + { + "$ref": "#/components/schemas/SearchConditionMediaStatus" + }, + { + "$ref": "#/components/schemas/SearchConditionMediaProfile" + }, + { + "$ref": "#/components/schemas/SearchConditionAuthor" + }, + { + "$ref": "#/components/schemas/SearchConditionPoster" + } + ] + }, + "SearchConditionCollectionId": { + "properties": { + "collectionId": { + "$ref": "#/components/schemas/SearchOperatorEqualityString" + } + }, + "required": [ + "collectionId" + ] + }, + "SearchConditionComplete": { + "properties": { + "complete": { + "$ref": "#/components/schemas/SearchOperatorBoolean" + } + }, + "required": [ + "complete" + ] + }, + "SearchConditionDeleted": { + "properties": { + "deleted": { + "$ref": "#/components/schemas/SearchOperatorBoolean" + } + }, + "required": [ + "deleted" + ] + }, + "SearchConditionGenre": { + "properties": { + "genre": { + "$ref": "#/components/schemas/SearchOperatorEqualityNullableString" + } + }, + "required": [ + "genre" + ] + }, + "SearchConditionLanguage": { + "properties": { + "language": { + "$ref": "#/components/schemas/SearchOperatorEqualityString" + } + }, + "required": [ + "language" + ] + }, + "SearchConditionLibraryId": { + "properties": { + "libraryId": { + "$ref": "#/components/schemas/SearchOperatorEqualityString" + } + }, + "required": [ + "libraryId" + ] + }, + "SearchConditionMediaProfile": { + "properties": { + "mediaProfile": { + "$ref": "#/components/schemas/SearchOperatorEqualityMediaProfile" + } + }, + "required": [ + "mediaProfile" + ] + }, + "SearchConditionMediaStatus": { + "properties": { + "mediaStatus": { + "$ref": "#/components/schemas/SearchOperatorEqualityStatus" + } + }, + "required": [ + "mediaStatus" + ] + }, + "SearchConditionNumberSort": { + "properties": { + "numberSort": { + "$ref": "#/components/schemas/SearchOperatorNumericTFloat" + } + }, + "required": [ + "numberSort" + ] + }, + "SearchConditionOneShot": { + "properties": { + "oneShot": { + "$ref": "#/components/schemas/SearchOperatorBoolean" + } + }, + "required": [ + "oneShot" + ] + }, + "SearchConditionPoster": { + "properties": { + "poster": { + "$ref": "#/components/schemas/SearchOperatorEqualityPosterMatch" + } + }, + "required": [ + "poster" + ] + }, + "SearchConditionPublisher": { + "properties": { + "publisher": { + "$ref": "#/components/schemas/SearchOperatorEqualityString" + } + }, + "required": [ + "publisher" + ] + }, + "SearchConditionReadListId": { + "properties": { + "readListId": { + "$ref": "#/components/schemas/SearchOperatorEqualityString" + } + }, + "required": [ + "readListId" + ] + }, + "SearchConditionReadStatus": { + "properties": { + "readStatus": { + "$ref": "#/components/schemas/SearchOperatorEqualityReadStatus" + } + }, + "required": [ + "readStatus" + ] + }, + "SearchConditionReleaseDate": { + "properties": { + "releaseDate": { + "$ref": "#/components/schemas/SearchOperatorDate" + } + }, + "required": [ + "releaseDate" + ] + }, + "SearchConditionSeries": { + "oneOf": [ + { + "$ref": "#/components/schemas/SearchConditionAnyOfSeries" + }, + { + "$ref": "#/components/schemas/SearchConditionAllOfSeries" + }, + { + "$ref": "#/components/schemas/SearchConditionLibraryId" + }, + { + "$ref": "#/components/schemas/SearchConditionCollectionId" + }, + { + "$ref": "#/components/schemas/SearchConditionDeleted" + }, + { + "$ref": "#/components/schemas/SearchConditionComplete" + }, + { + "$ref": "#/components/schemas/SearchConditionOneShot" + }, + { + "$ref": "#/components/schemas/SearchConditionTitle" + }, + { + "$ref": "#/components/schemas/SearchConditionTitleSort" + }, + { + "$ref": "#/components/schemas/SearchConditionReleaseDate" + }, + { + "$ref": "#/components/schemas/SearchConditionTag" + }, + { + "$ref": "#/components/schemas/SearchConditionSharingLabel" + }, + { + "$ref": "#/components/schemas/SearchConditionPublisher" + }, + { + "$ref": "#/components/schemas/SearchConditionLanguage" + }, + { + "$ref": "#/components/schemas/SearchConditionGenre" + }, + { + "$ref": "#/components/schemas/SearchConditionAgeRating" + }, + { + "$ref": "#/components/schemas/SearchConditionReadStatus" + }, + { + "$ref": "#/components/schemas/SearchConditionSeriesStatus" + }, + { + "$ref": "#/components/schemas/SearchConditionAuthor" + } + ] + }, + "SearchConditionSeriesId": { + "properties": { + "seriesId": { + "$ref": "#/components/schemas/SearchOperatorEqualityString" + } + }, + "required": [ + "seriesId" + ] + }, + "SearchConditionSeriesStatus": { + "properties": { + "seriesStatus": { + "$ref": "#/components/schemas/SearchOperatorEqualityStatus" + } + }, + "required": [ + "seriesStatus" + ] + }, + "SearchConditionSharingLabel": { + "properties": { + "sharingLabel": { + "$ref": "#/components/schemas/SearchOperatorEqualityNullableString" + } + }, + "required": [ + "sharingLabel" + ] + }, + "SearchConditionTag": { + "properties": { + "tag": { + "$ref": "#/components/schemas/SearchOperatorEqualityNullableString" + } + }, + "required": [ + "tag" + ] + }, + "SearchConditionTitle": { + "properties": { + "title": { + "$ref": "#/components/schemas/SearchOperatorString" + } + }, + "required": [ + "title" + ] + }, + "SearchConditionTitleSort": { + "properties": { + "titleSort": { + "$ref": "#/components/schemas/SearchOperatorString" + } + }, + "required": [ + "titleSort" + ] + }, + "SearchOperatorAfter": { + "properties": { + "dateTime": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "dateTime" + ] + }, + "SearchOperatorBefore": { + "properties": { + "dateTime": { + "type": "string", + "format": "date-time" + } + }, + "required": [ + "dateTime" + ] + }, + "SearchOperatorBeginsWith": { + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + "SearchOperatorBoolean": { + "discriminator": { + "mapping": { + "isFalse": "#/components/schemas/SearchOperatorIsFalse", + "isTrue": "#/components/schemas/SearchOperatorIsTrue" + }, + "propertyName": "operator" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/SearchOperatorIsTrue" + }, + { + "$ref": "#/components/schemas/SearchOperatorIsFalse" + } + ], + "properties": { + "operator": { + "type": "string" + } + }, + "required": [ + "operator" + ] + }, + "SearchOperatorContains": { + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + "SearchOperatorDate": { + "discriminator": { + "mapping": { + "after": "#/components/schemas/SearchOperatorAfter", + "before": "#/components/schemas/SearchOperatorBefore", + "isInTheLast": "#/components/schemas/SearchOperatorIsInTheLast", + "isNotInTheLast": "#/components/schemas/SearchOperatorIsNotInTheLast", + "isNotNull": "#/components/schemas/SearchOperatorIsNotNull", + "isNull": "#/components/schemas/SearchOperatorIsNull" + }, + "propertyName": "operator" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/SearchOperatorBefore" + }, + { + "$ref": "#/components/schemas/SearchOperatorAfter" + }, + { + "$ref": "#/components/schemas/SearchOperatorIsInTheLast" + }, + { + "$ref": "#/components/schemas/SearchOperatorIsNotInTheLast" + }, + { + "$ref": "#/components/schemas/SearchOperatorIsNull" + }, + { + "$ref": "#/components/schemas/SearchOperatorIsNotNull" + } + ], + "properties": { + "operator": { + "type": "string" + } + }, + "required": [ + "operator" + ] + }, + "SearchOperatorDoesNotBeginWith": { + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + "SearchOperatorDoesNotContain": { + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + "SearchOperatorDoesNotEndWith": { + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + "SearchOperatorEndsWith": { + "properties": { + "value": { + "type": "string" + } + }, + "required": [ + "value" + ] + }, + "SearchOperatorEqualityAuthorMatch": { + "discriminator": { + "mapping": { + "is": "#/components/schemas/SearchOperatorIs", + "isNot": "#/components/schemas/SearchOperatorIsNot" + }, + "propertyName": "operator" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/SearchOperatorIs" + }, + { + "$ref": "#/components/schemas/SearchOperatorIsNot" + } + ], + "properties": { + "operator": { + "type": "string" + } + }, + "required": [ + "operator" + ] + }, + "SearchOperatorEqualityMediaProfile": { + "discriminator": { + "mapping": { + "is": "#/components/schemas/SearchOperatorIs", + "isNot": "#/components/schemas/SearchOperatorIsNot" + }, + "propertyName": "operator" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/SearchOperatorIs" + }, + { + "$ref": "#/components/schemas/SearchOperatorIsNot" + } + ], + "properties": { + "operator": { + "type": "string" + } + }, + "required": [ + "operator" + ] + }, + "SearchOperatorEqualityNullableString": { + "discriminator": { + "mapping": { + "is": "#/components/schemas/SearchOperatorIs", + "isNot": "#/components/schemas/SearchOperatorIsNot", + "isNotNull": "#/components/schemas/SearchOperatorIsNotNullT", + "isNull": "#/components/schemas/SearchOperatorIsNullT" + }, + "propertyName": "operator" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/SearchOperatorIs" + }, + { + "$ref": "#/components/schemas/SearchOperatorIsNot" + }, + { + "$ref": "#/components/schemas/SearchOperatorIsNullT" + }, + { + "$ref": "#/components/schemas/SearchOperatorIsNotNullT" + } + ], + "properties": { + "operator": { + "type": "string" + } + }, + "required": [ + "operator" + ] + }, + "SearchOperatorEqualityPosterMatch": { + "discriminator": { + "mapping": { + "is": "#/components/schemas/SearchOperatorIs", + "isNot": "#/components/schemas/SearchOperatorIsNot" + }, + "propertyName": "operator" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/SearchOperatorIs" + }, + { + "$ref": "#/components/schemas/SearchOperatorIsNot" + } + ], + "properties": { + "operator": { + "type": "string" + } + }, + "required": [ + "operator" + ] + }, + "SearchOperatorEqualityReadStatus": { + "discriminator": { + "mapping": { + "is": "#/components/schemas/SearchOperatorIs", + "isNot": "#/components/schemas/SearchOperatorIsNot" + }, + "propertyName": "operator" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/SearchOperatorIs" + }, + { + "$ref": "#/components/schemas/SearchOperatorIsNot" + } + ], + "properties": { + "operator": { + "type": "string" + } + }, + "required": [ + "operator" + ] + }, + "SearchOperatorEqualityStatus": { + "discriminator": { + "mapping": { + "is": "#/components/schemas/SearchOperatorIs", + "isNot": "#/components/schemas/SearchOperatorIsNot" + }, + "propertyName": "operator" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/SearchOperatorIs" + }, + { + "$ref": "#/components/schemas/SearchOperatorIsNot" + } + ], + "properties": { + "operator": { + "type": "string" + } + }, + "required": [ + "operator" + ] + }, + "SearchOperatorEqualityString": { + "discriminator": { + "mapping": { + "is": "#/components/schemas/SearchOperatorIs", + "isNot": "#/components/schemas/SearchOperatorIsNot" + }, + "propertyName": "operator" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/SearchOperatorIs" + }, + { + "$ref": "#/components/schemas/SearchOperatorIsNot" + } + ], + "properties": { + "operator": { + "type": "string" + } + }, + "required": [ + "operator" + ] + }, + "SearchOperatorGreaterThan": { + "properties": { + "value": {} + }, + "required": [ + "value" + ] + }, + "SearchOperatorIs": { + "properties": { + "value": {} + }, + "required": [ + "value" + ] + }, + "SearchOperatorIsFalse": { + "allOf": [ + { + "$ref": "#/components/schemas/SearchOperatorBoolean" + } + ] + }, + "SearchOperatorIsInTheLast": { + "properties": { + "duration": { + "type": "string" + } + }, + "required": [ + "duration" + ] + }, + "SearchOperatorIsNot": { + "properties": { + "value": {} + }, + "required": [ + "value" + ] + }, + "SearchOperatorIsNotInTheLast": { + "properties": { + "duration": { + "type": "string" + } + }, + "required": [ + "duration" + ] + }, + "SearchOperatorIsNotNull": { + "allOf": [ + { + "$ref": "#/components/schemas/SearchOperatorDate" + } + ] + }, + "SearchOperatorIsNotNullT": { + "allOf": [ + { + "$ref": "#/components/schemas/SearchOperatorNumericNullableInteger" + }, + { + "$ref": "#/components/schemas/SearchOperatorEqualityNullableString" + } + ] + }, + "SearchOperatorIsNull": { + "allOf": [ + { + "$ref": "#/components/schemas/SearchOperatorDate" + } + ] + }, + "SearchOperatorIsNullT": { + "allOf": [ + { + "$ref": "#/components/schemas/SearchOperatorNumericNullableInteger" + }, + { + "$ref": "#/components/schemas/SearchOperatorEqualityNullableString" + } + ] + }, + "SearchOperatorIsTrue": { + "allOf": [ + { + "$ref": "#/components/schemas/SearchOperatorBoolean" + } + ] + }, + "SearchOperatorLessThan": { + "properties": { + "value": {} + }, + "required": [ + "value" + ] + }, + "SearchOperatorNumericNullableInteger": { + "discriminator": { + "mapping": { + "greaterThan": "#/components/schemas/SearchOperatorGreaterThan", + "is": "#/components/schemas/SearchOperatorIs", + "isNot": "#/components/schemas/SearchOperatorIsNot", + "isNotNull": "#/components/schemas/SearchOperatorIsNotNullT", + "isNull": "#/components/schemas/SearchOperatorIsNullT", + "lessThan": "#/components/schemas/SearchOperatorLessThan" + }, + "propertyName": "operator" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/SearchOperatorGreaterThan" + }, + { + "$ref": "#/components/schemas/SearchOperatorLessThan" + }, + { + "$ref": "#/components/schemas/SearchOperatorIsNullT" + }, + { + "$ref": "#/components/schemas/SearchOperatorIsNotNullT" + }, + { + "$ref": "#/components/schemas/SearchOperatorIs" + }, + { + "$ref": "#/components/schemas/SearchOperatorIsNot" + } + ], + "properties": { + "operator": { + "type": "string" + } + }, + "required": [ + "operator" + ] + }, + "SearchOperatorNumericTFloat": { + "discriminator": { + "mapping": { + "greaterThan": "#/components/schemas/SearchOperatorGreaterThan", + "is": "#/components/schemas/SearchOperatorIs", + "isNot": "#/components/schemas/SearchOperatorIsNot", + "lessThan": "#/components/schemas/SearchOperatorLessThan" + }, + "propertyName": "operator" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/SearchOperatorGreaterThan" + }, + { + "$ref": "#/components/schemas/SearchOperatorLessThan" + }, + { + "$ref": "#/components/schemas/SearchOperatorIs" + }, + { + "$ref": "#/components/schemas/SearchOperatorIsNot" + } + ], + "properties": { + "operator": { + "type": "string" + } + }, + "required": [ + "operator" + ] + }, + "SearchOperatorString": { + "discriminator": { + "mapping": { + "beginsWith": "#/components/schemas/SearchOperatorBeginsWith", + "contains": "#/components/schemas/SearchOperatorContains", + "doesNotBeginWith": "#/components/schemas/SearchOperatorDoesNotBeginWith", + "doesNotContain": "#/components/schemas/SearchOperatorDoesNotContain", + "doesNotEndWith": "#/components/schemas/SearchOperatorDoesNotEndWith", + "endsWith": "#/components/schemas/SearchOperatorEndsWith", + "is": "#/components/schemas/SearchOperatorIs", + "isNot": "#/components/schemas/SearchOperatorIsNot" + }, + "propertyName": "operator" + }, + "oneOf": [ + { + "$ref": "#/components/schemas/SearchOperatorBeginsWith" + }, + { + "$ref": "#/components/schemas/SearchOperatorDoesNotBeginWith" + }, + { + "$ref": "#/components/schemas/SearchOperatorContains" + }, + { + "$ref": "#/components/schemas/SearchOperatorDoesNotContain" + }, + { + "$ref": "#/components/schemas/SearchOperatorEndsWith" + }, + { + "$ref": "#/components/schemas/SearchOperatorDoesNotEndWith" + }, + { + "$ref": "#/components/schemas/SearchOperatorIs" + }, + { + "$ref": "#/components/schemas/SearchOperatorIsNot" + } + ], + "properties": { + "operator": { + "type": "string" + } + }, + "required": [ + "operator" + ] + }, + "SeriesDto": { + "type": "object", + "properties": { + "booksCount": { + "type": "integer", + "format": "int32" + }, + "booksInProgressCount": { + "type": "integer", + "format": "int32" + }, + "booksMetadata": { + "$ref": "#/components/schemas/BookMetadataAggregationDto" + }, + "booksReadCount": { + "type": "integer", + "format": "int32" + }, + "booksUnreadCount": { + "type": "integer", + "format": "int32" + }, + "created": { + "type": "string", + "format": "date-time" + }, + "deleted": { + "type": "boolean" + }, + "fileLastModified": { + "type": "string", + "format": "date-time" + }, + "id": { + "type": "string" + }, + "lastModified": { + "type": "string", + "format": "date-time" + }, + "libraryId": { + "type": "string" + }, + "metadata": { + "$ref": "#/components/schemas/SeriesMetadataDto" + }, + "name": { + "type": "string" + }, + "oneshot": { + "type": "boolean" + }, + "url": { + "type": "string" + } + }, + "required": [ + "booksCount", + "booksInProgressCount", + "booksMetadata", + "booksReadCount", + "booksUnreadCount", + "created", + "deleted", + "fileLastModified", + "id", + "lastModified", + "libraryId", + "metadata", + "name", + "oneshot", + "url" + ] + }, + "SeriesMetadataDto": { + "type": "object", + "properties": { + "ageRating": { + "type": "integer", + "format": "int32" + }, + "ageRatingLock": { + "type": "boolean" + }, + "alternateTitles": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AlternateTitleDto" + } + }, + "alternateTitlesLock": { + "type": "boolean" + }, + "created": { + "type": "string", + "format": "date-time" + }, + "genres": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "genresLock": { + "type": "boolean" + }, + "language": { + "type": "string" + }, + "languageLock": { + "type": "boolean" + }, + "lastModified": { + "type": "string", + "format": "date-time" + }, + "links": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WebLinkDto" + } + }, + "linksLock": { + "type": "boolean" + }, + "publisher": { + "type": "string" + }, + "publisherLock": { + "type": "boolean" + }, + "readingDirection": { + "type": "string" + }, + "readingDirectionLock": { + "type": "boolean" + }, + "sharingLabels": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "sharingLabelsLock": { + "type": "boolean" + }, + "status": { + "type": "string" + }, + "statusLock": { + "type": "boolean" + }, + "summary": { + "type": "string" + }, + "summaryLock": { + "type": "boolean" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "tagsLock": { + "type": "boolean" + }, + "title": { + "type": "string" + }, + "titleLock": { + "type": "boolean" + }, + "titleSort": { + "type": "string" + }, + "titleSortLock": { + "type": "boolean" + }, + "totalBookCount": { + "type": "integer", + "format": "int32" + }, + "totalBookCountLock": { + "type": "boolean" + } + }, + "required": [ + "ageRatingLock", + "alternateTitles", + "alternateTitlesLock", + "created", + "genres", + "genresLock", + "language", + "languageLock", + "lastModified", + "links", + "linksLock", + "publisher", + "publisherLock", + "readingDirection", + "readingDirectionLock", + "sharingLabels", + "sharingLabelsLock", + "status", + "statusLock", + "summary", + "summaryLock", + "tags", + "tagsLock", + "title", + "titleLock", + "titleSort", + "titleSortLock", + "totalBookCountLock" + ] + }, + "SeriesMetadataUpdateDto": { + "type": "object", + "description": "Metadata fields to update. Set a field to null to unset the metadata. You can omit fields you don't want to update.", + "properties": { + "ageRating": { + "type": "integer", + "format": "int32" + }, + "ageRatingLock": { + "type": "boolean" + }, + "alternateTitles": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AlternateTitleUpdateDto" + } + }, + "alternateTitlesLock": { + "type": "boolean" + }, + "genres": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "genresLock": { + "type": "boolean" + }, + "language": { + "type": "string" + }, + "languageLock": { + "type": "boolean" + }, + "links": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WebLinkUpdateDto" + } + }, + "linksLock": { + "type": "boolean" + }, + "publisher": { + "type": "string" + }, + "publisherLock": { + "type": "boolean" + }, + "readingDirection": { + "type": "string", + "enum": [ + "LEFT_TO_RIGHT", + "RIGHT_TO_LEFT", + "VERTICAL", + "WEBTOON" + ] + }, + "readingDirectionLock": { + "type": "boolean" + }, + "sharingLabels": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "sharingLabelsLock": { + "type": "boolean" + }, + "status": { + "type": "string", + "enum": [ + "ENDED", + "ONGOING", + "ABANDONED", + "HIATUS" + ] + }, + "statusLock": { + "type": "boolean" + }, + "summary": { + "type": "string" + }, + "summaryLock": { + "type": "boolean" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "tagsLock": { + "type": "boolean" + }, + "title": { + "type": "string" + }, + "titleLock": { + "type": "boolean" + }, + "titleSort": { + "type": "string" + }, + "titleSortLock": { + "type": "boolean" + }, + "totalBookCount": { + "type": "integer", + "format": "int32" + }, + "totalBookCountLock": { + "type": "boolean" + } + } + }, + "SeriesSearch": { + "type": "object", + "properties": { + "condition": { + "$ref": "#/components/schemas/SearchConditionSeries" + }, + "fullTextSearch": { + "type": "string" + } + } + }, + "SettingMultiSourceInteger": { + "type": "object", + "properties": { + "configurationSource": { + "type": "integer", + "format": "int32" + }, + "databaseSource": { + "type": "integer", + "format": "int32" + }, + "effectiveValue": { + "type": "integer", + "format": "int32" + } + } + }, + "SettingMultiSourceString": { + "type": "object", + "properties": { + "configurationSource": { + "type": "string" + }, + "databaseSource": { + "type": "string" + }, + "effectiveValue": { + "type": "string" + } + } + }, + "SettingsDto": { + "type": "object", + "properties": { + "deleteEmptyCollections": { + "type": "boolean" + }, + "deleteEmptyReadLists": { + "type": "boolean" + }, + "kepubifyPath": { + "$ref": "#/components/schemas/SettingMultiSourceString" + }, + "koboPort": { + "type": "integer", + "format": "int32" + }, + "koboProxy": { + "type": "boolean" + }, + "rememberMeDurationDays": { + "type": "integer", + "format": "int64" + }, + "serverContextPath": { + "$ref": "#/components/schemas/SettingMultiSourceString" + }, + "serverPort": { + "$ref": "#/components/schemas/SettingMultiSourceInteger" + }, + "taskPoolSize": { + "type": "integer", + "format": "int32" + }, + "thumbnailSize": { + "type": "string", + "enum": [ + "DEFAULT", + "MEDIUM", + "LARGE", + "XLARGE" + ] + } + }, + "required": [ + "deleteEmptyCollections", + "deleteEmptyReadLists", + "kepubifyPath", + "koboProxy", + "rememberMeDurationDays", + "serverContextPath", + "serverPort", + "taskPoolSize", + "thumbnailSize" + ] + }, + "SettingsUpdateDto": { + "type": "object", + "description": "Fields to update. You can omit fields you don't want to update.", + "properties": { + "deleteEmptyCollections": { + "type": "boolean" + }, + "deleteEmptyReadLists": { + "type": "boolean" + }, + "kepubifyPath": { + "type": "string", + "deprecated": true, + "description": "Will be removed in a future version" + }, + "koboPort": { + "type": "integer", + "format": "int32", + "maximum": 65535 + }, + "koboProxy": { + "type": "boolean" + }, + "rememberMeDurationDays": { + "type": "integer", + "format": "int64" + }, + "renewRememberMeKey": { + "type": "boolean" + }, + "serverContextPath": { + "type": "string", + "pattern": "^/[\\w-/]*[a-zA-Z0-9]$" + }, + "serverPort": { + "type": "integer", + "format": "int32", + "maximum": 65535 + }, + "taskPoolSize": { + "type": "integer", + "format": "int32" + }, + "thumbnailSize": { + "type": "string", + "enum": [ + "DEFAULT", + "MEDIUM", + "LARGE", + "XLARGE" + ] + } + } + }, + "SharedLibrariesUpdateDto": { + "type": "object", + "properties": { + "all": { + "type": "boolean" + }, + "libraryIds": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + "required": [ + "all", + "libraryIds" + ] + }, + "SortObject": { + "type": "object", + "properties": { + "empty": { + "type": "boolean" + }, + "sorted": { + "type": "boolean" + }, + "unsorted": { + "type": "boolean" + } + } + }, + "StreamingResponseBody": {}, + "TachiyomiReadProgressDto": { + "type": "object", + "properties": { + "booksCount": { + "type": "integer", + "format": "int32" + }, + "booksInProgressCount": { + "type": "integer", + "format": "int32" + }, + "booksReadCount": { + "type": "integer", + "format": "int32" + }, + "booksUnreadCount": { + "type": "integer", + "format": "int32" + }, + "lastReadContinuousIndex": { + "type": "integer", + "format": "int32" + } + }, + "required": [ + "booksCount", + "booksInProgressCount", + "booksReadCount", + "booksUnreadCount", + "lastReadContinuousIndex" + ] + }, + "TachiyomiReadProgressUpdateDto": { + "type": "object", + "properties": { + "lastBookRead": { + "type": "integer", + "format": "int32" + } + }, + "required": [ + "lastBookRead" + ] + }, + "TachiyomiReadProgressUpdateV2Dto": { + "type": "object", + "properties": { + "lastBookNumberSortRead": { + "type": "number", + "format": "float" + } + }, + "required": [ + "lastBookNumberSortRead" + ] + }, + "TachiyomiReadProgressV2Dto": { + "type": "object", + "properties": { + "booksCount": { + "type": "integer", + "format": "int32" + }, + "booksInProgressCount": { + "type": "integer", + "format": "int32" + }, + "booksReadCount": { + "type": "integer", + "format": "int32" + }, + "booksUnreadCount": { + "type": "integer", + "format": "int32" + }, + "lastReadContinuousNumberSort": { + "type": "number", + "format": "float" + }, + "maxNumberSort": { + "type": "number", + "format": "float" + } + }, + "required": [ + "booksCount", + "booksInProgressCount", + "booksReadCount", + "booksUnreadCount", + "lastReadContinuousNumberSort", + "maxNumberSort" + ] + }, + "Text": { + "type": "object", + "properties": { + "after": { + "type": "string" + }, + "before": { + "type": "string" + }, + "highlight": { + "type": "string" + } + } + }, + "ThumbnailBookDto": { + "type": "object", + "properties": { + "bookId": { + "type": "string" + }, + "fileSize": { + "type": "integer", + "format": "int64" + }, + "height": { + "type": "integer", + "format": "int32" + }, + "id": { + "type": "string" + }, + "mediaType": { + "type": "string" + }, + "selected": { + "type": "boolean" + }, + "type": { + "type": "string" + }, + "width": { + "type": "integer", + "format": "int32" + } + }, + "required": [ + "bookId", + "fileSize", + "height", + "id", + "mediaType", + "selected", + "type", + "width" + ] + }, + "ThumbnailReadListDto": { + "type": "object", + "properties": { + "fileSize": { + "type": "integer", + "format": "int64" + }, + "height": { + "type": "integer", + "format": "int32" + }, + "id": { + "type": "string" + }, + "mediaType": { + "type": "string" + }, + "readListId": { + "type": "string" + }, + "selected": { + "type": "boolean" + }, + "type": { + "type": "string" + }, + "width": { + "type": "integer", + "format": "int32" + } + }, + "required": [ + "fileSize", + "height", + "id", + "mediaType", + "readListId", + "selected", + "type", + "width" + ] + }, + "ThumbnailSeriesCollectionDto": { + "type": "object", + "properties": { + "collectionId": { + "type": "string" + }, + "fileSize": { + "type": "integer", + "format": "int64" + }, + "height": { + "type": "integer", + "format": "int32" + }, + "id": { + "type": "string" + }, + "mediaType": { + "type": "string" + }, + "selected": { + "type": "boolean" + }, + "type": { + "type": "string" + }, + "width": { + "type": "integer", + "format": "int32" + } + }, + "required": [ + "collectionId", + "fileSize", + "height", + "id", + "mediaType", + "selected", + "type", + "width" + ] + }, + "ThumbnailSeriesDto": { + "type": "object", + "properties": { + "fileSize": { + "type": "integer", + "format": "int64" + }, + "height": { + "type": "integer", + "format": "int32" + }, + "id": { + "type": "string" + }, + "mediaType": { + "type": "string" + }, + "selected": { + "type": "boolean" + }, + "seriesId": { + "type": "string" + }, + "type": { + "type": "string" + }, + "width": { + "type": "integer", + "format": "int32" + } + }, + "required": [ + "fileSize", + "height", + "id", + "mediaType", + "selected", + "seriesId", + "type", + "width" + ] + }, + "TransientBookDto": { + "type": "object", + "properties": { + "comment": { + "type": "string" + }, + "fileLastModified": { + "type": "string", + "format": "date-time" + }, + "files": { + "type": "array", + "items": { + "type": "string" + } + }, + "id": { + "type": "string" + }, + "mediaType": { + "type": "string" + }, + "name": { + "type": "string" + }, + "number": { + "type": "number", + "format": "float" + }, + "pages": { + "type": "array", + "items": { + "$ref": "#/components/schemas/PageDto" + } + }, + "seriesId": { + "type": "string" + }, + "size": { + "type": "string" + }, + "sizeBytes": { + "type": "integer", + "format": "int64" + }, + "status": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "required": [ + "comment", + "fileLastModified", + "files", + "id", + "mediaType", + "name", + "pages", + "size", + "sizeBytes", + "status", + "url" + ] + }, + "UserCreationDto": { + "type": "object", + "properties": { + "ageRestriction": { + "$ref": "#/components/schemas/AgeRestrictionUpdateDto" + }, + "email": { + "type": "string" + }, + "labelsAllow": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "labelsExclude": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "password": { + "type": "string", + "minLength": 1 + }, + "roles": { + "type": "array", + "items": { + "type": "string" + } + }, + "sharedLibraries": { + "$ref": "#/components/schemas/SharedLibrariesUpdateDto" + } + }, + "required": [ + "email", + "password", + "roles" + ] + }, + "UserDto": { + "type": "object", + "properties": { + "ageRestriction": { + "$ref": "#/components/schemas/AgeRestrictionDto" + }, + "email": { + "type": "string" + }, + "id": { + "type": "string" + }, + "labelsAllow": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "labelsExclude": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "sharedAllLibraries": { + "type": "boolean" + }, + "sharedLibrariesIds": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + } + }, + "required": [ + "email", + "id", + "labelsAllow", + "labelsExclude", + "roles", + "sharedAllLibraries", + "sharedLibrariesIds" + ] + }, + "UserUpdateDto": { + "type": "object", + "properties": { + "ageRestriction": { + "$ref": "#/components/schemas/AgeRestrictionUpdateDto" + }, + "labelsAllow": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "labelsExclude": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "uniqueItems": true + }, + "sharedLibraries": { + "$ref": "#/components/schemas/SharedLibrariesUpdateDto" + } + } + }, + "ValidationErrorResponse": { + "type": "object", + "properties": { + "violations": { + "type": "array", + "items": { + "$ref": "#/components/schemas/Violation" + } + } + }, + "required": [ + "violations" + ] + }, + "Violation": { + "type": "object", + "properties": { + "fieldName": { + "type": "string" + }, + "message": { + "type": "string" + } + } + }, + "WPBelongsToDto": { + "type": "object", + "properties": { + "collection": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WPContributorDto" + } + }, + "series": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WPContributorDto" + } + } + }, + "required": [ + "collection", + "series" + ] + }, + "WPContributorDto": { + "type": "object", + "properties": { + "links": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WPLinkDto" + } + }, + "name": { + "type": "string" + }, + "position": { + "type": "number", + "format": "float" + } + }, + "required": [ + "links", + "name" + ] + }, + "WPLinkDto": { + "type": "object", + "properties": { + "height": { + "type": "integer", + "format": "int32" + }, + "href": { + "type": "string" + }, + "properties": { + "type": "object", + "additionalProperties": { + "type": "object", + "additionalProperties": {} + } + }, + "rel": { + "type": "string" + }, + "templated": { + "type": "boolean" + }, + "title": { + "type": "string" + }, + "type": { + "type": "string" + }, + "width": { + "type": "integer", + "format": "int32" + } + }, + "required": [ + "properties" + ] + }, + "WPMetadataDto": { + "type": "object", + "properties": { + "artist": { + "type": "array", + "items": { + "type": "string" + } + }, + "author": { + "type": "array", + "items": { + "type": "string" + } + }, + "belongsTo": { + "$ref": "#/components/schemas/WPBelongsToDto" + }, + "colorist": { + "type": "array", + "items": { + "type": "string" + } + }, + "conformsTo": { + "type": "string" + }, + "contributor": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": { + "type": "string" + }, + "editor": { + "type": "array", + "items": { + "type": "string" + } + }, + "identifier": { + "type": "string" + }, + "illustrator": { + "type": "array", + "items": { + "type": "string" + } + }, + "inker": { + "type": "array", + "items": { + "type": "string" + } + }, + "language": { + "type": "string" + }, + "letterer": { + "type": "array", + "items": { + "type": "string" + } + }, + "modified": { + "type": "string", + "format": "date-time" + }, + "numberOfPages": { + "type": "integer", + "format": "int32" + }, + "penciler": { + "type": "array", + "items": { + "type": "string" + } + }, + "published": { + "type": "string", + "format": "date" + }, + "publisher": { + "type": "array", + "items": { + "type": "string" + } + }, + "readingProgression": { + "type": "string", + "enum": [ + "rtl", + "ltr", + "ttb", + "btt", + "auto" + ] + }, + "rendition": { + "type": "object", + "additionalProperties": {} + }, + "sortAs": { + "type": "string" + }, + "subject": { + "type": "array", + "items": { + "type": "string" + } + }, + "subtitle": { + "type": "string" + }, + "title": { + "type": "string" + }, + "translator": { + "type": "array", + "items": { + "type": "string" + } + }, + "type": { + "type": "string" + } + }, + "required": [ + "artist", + "author", + "colorist", + "contributor", + "editor", + "illustrator", + "inker", + "letterer", + "penciler", + "publisher", + "rendition", + "subject", + "title", + "translator" + ] + }, + "WPPublicationDto": { + "type": "object", + "properties": { + "context": { + "type": "string" + }, + "images": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WPLinkDto" + } + }, + "landmarks": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WPLinkDto" + } + }, + "links": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WPLinkDto" + } + }, + "metadata": { + "$ref": "#/components/schemas/WPMetadataDto" + }, + "pageList": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WPLinkDto" + } + }, + "readingOrder": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WPLinkDto" + } + }, + "resources": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WPLinkDto" + } + }, + "toc": { + "type": "array", + "items": { + "$ref": "#/components/schemas/WPLinkDto" + } + } + }, + "required": [ + "images", + "landmarks", + "links", + "metadata", + "pageList", + "readingOrder", + "resources", + "toc" + ] + }, + "WebLinkDto": { + "type": "object", + "properties": { + "label": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "required": [ + "label", + "url" + ] + }, + "WebLinkUpdateDto": { + "type": "object", + "properties": { + "label": { + "type": "string", + "minLength": 1 + }, + "url": { + "type": "string" + } + }, + "required": [ + "label" + ] + } + }, + "securitySchemes": { + "apiKey": { + "in": "header", + "name": "X-API-Key", + "type": "apiKey" + }, + "basicAuth": { + "scheme": "basic", + "type": "http" + } + } + }, + "x-tagGroups": [ + { + "name": "Deprecation", + "tags": [ + "Deprecated" + ] + }, + { + "name": "Libraries", + "tags": [ + "Libraries" + ] + }, + { + "name": "Series", + "tags": [ + "Series", + "Series Poster" + ] + }, + { + "name": "Books", + "tags": [ + "Books", + "Book Pages", + "Book Poster", + "Import", + "Duplicate Pages", + "WebPub Manifest", + "Fonts" + ] + }, + { + "name": "Collections", + "tags": [ + "Collections", + "Collection Series", + "Collection Poster" + ] + }, + { + "name": "Readlists", + "tags": [ + "Readlists", + "Readlist Books", + "Readlist Poster" + ] + }, + { + "name": "Referential", + "tags": [ + "Referential metadata" + ] + }, + { + "name": "Users", + "tags": [ + "Current user", + "Users", + "API Keys", + "User session", + "OAuth2", + "Sync points" + ] + }, + { + "name": "Server", + "tags": [ + "Claim", + "Server settings", + "Tasks", + "History", + "File system", + "Releases", + "Announcements", + "Management" + ] + }, + { + "name": "Integrations", + "tags": [ + "Client settings", + "Mihon", + "ComicRack" + ] + } + ] +} diff --git a/scripts/build/docker-compose.build.yml b/scripts/build/docker-compose.build.yml index f97e3c15d..be73a64e0 100644 --- a/scripts/build/docker-compose.build.yml +++ b/scripts/build/docker-compose.build.yml @@ -229,8 +229,10 @@ services: gradle build -x test -x spotlessCheck -x spotlessJavaCheck fi cp cs/rest/bibliothek/build/libs/bibliothek-sut.jar /dist/ + cp cs/rest/komga/komga/build/libs/komga-sut.jar /dist/ if [ "$${BUILD_EVOMASTER:-false}" = "true" ]; then cp em/external/rest/bibliothek/build/libs/bibliothek-evomaster-runner.jar /dist/ + cp em/external/rest/komga/build/libs/komga-evomaster-runner.jar /dist/ fi echo 'JDK 17 Gradle build completed' diff --git a/scripts/dist-wb.py b/scripts/dist-wb.py index 8f7252fbb..9116843ba 100755 --- a/scripts/dist-wb.py +++ b/scripts/dist-wb.py @@ -380,6 +380,9 @@ def build_jdk_17_gradle(): copy(folder + "/cs/rest/bibliothek/build/libs/bibliothek-sut.jar", DIST) copy(folder + "/em/external/rest/bibliothek/build/libs/bibliothek-evomaster-runner.jar", DIST) + copy(folder + "/cs/rest/komga/komga/build/libs/komga-sut.jar", DIST) + copy(folder + "/em/external/rest/komga/build/libs/komga-evomaster-runner.jar", DIST) + # Building JavaScript projects # def buildJS(path, name): diff --git a/scripts/dockerize/data/sut.csv b/scripts/dockerize/data/sut.csv index b9b059b49..ab43efeb8 100644 --- a/scripts/dockerize/data/sut.csv +++ b/scripts/dockerize/data/sut.csv @@ -42,3 +42,4 @@ adoptme,TRUE,-Xmx1G,--server.port=8080 --spring.neo4j.uri=bolt://db:7687 --sprin arimaa,TRUE,,--server.port=8080 --spring.datasource.url=jdbc:mysql://db:3306/arimaadockermysqldb --spring.datasource.username=admin --spring.datasource.password=AdminPassword123! --spring.mongodb.uri=mongodb://mongodb:27017/arimaadb --spring.neo4j.uri=bolt://neo4j:7687 --spring.neo4j.authentication.username=neo4j --spring.neo4j.authentication.password=wfdNeo4jPass123,http://localhost:8080/v3/api-docs,http://localhost:8080,FALSE,db;mongodb;neo4j,"[{""image_name"": ""mysql:9.5.0"", ""tmp_fs"": """", ""environment"": ""MYSQL_DATABASE: arimaadockermysqldb;MYSQL_ROOT_PASSWORD: wfdRootPass123!"", ""volume"": ""../jdk_21_maven/cs/rest/arimaa/Database/mysql:/docker-entrypoint-initdb.d"", ""health_check_command"": ""mysqladmin ping -h localhost -u root -pwfdRootPass123! --silent""}, {""name"": ""mongodb"", ""image_name"": ""mongo:7"", ""tmp_fs"": """", ""environment"": """", ""volume"": ""./additional_files/arimaa/arimaa-mongo-seed.js:/docker-entrypoint-initdb.d/arimaa-mongo-seed.js"", ""health_check_command"": ""mongosh --quiet --eval \""db.adminCommand('ping')\""""}, {""name"": ""neo4j"", ""image_name"": ""neo4j:5.26"", ""tmp_fs"": """", ""environment"": ""NEO4J_AUTH: neo4j/wfdNeo4jPass123"", ""volume"": ""./additional_files/arimaa/arimaa-neo4j-seed.cypher:/seed.cypher"", ""health_check_command"": ""cypher-shell -u neo4j -p wfdNeo4jPass123 \""MATCH (:WfdSeedComplete) RETURN 1\"""", ""command"": ""[\""bash\"", \""-c\"", '/startup/docker-entrypoint.sh neo4j & pid=$!; until cypher-shell -u neo4j -p wfdNeo4jPass123 \""RETURN 1\"" >/dev/null 2>&1; do sleep 2; done; cypher-shell -u neo4j -p wfdNeo4jPass123 -f /seed.cypher; cypher-shell -u neo4j -p wfdNeo4jPass123 \""CREATE (:WfdSeedComplete)\""; wait $pid']""}]" joinus,TRUE,,--server.port=8080 --spring.mongodb.uri=mongodb://db:27017/joinUs --spring.neo4j.uri=bolt://neo4j:7687 --spring.neo4j.authentication.username=neo4j --spring.neo4j.authentication.password=wfdNeo4jPass123 --logging.level.org.mongodb.driver=INFO --logging.level.org.neo4j.driver=INFO --logging.level.org.springframework.security=INFO,http://localhost:8080/v3/api-docs,http://localhost:8080,FALSE,db;neo4j,"[{""image_name"": ""mongo:7"", ""tmp_fs"": """", ""environment"": """", ""volume"": ""./additional_files/joinus/joinus-mongo-seed.js:/docker-entrypoint-initdb.d/joinus-mongo-seed.js"", ""health_check_command"": ""mongosh --quiet --eval \""db.adminCommand('ping')\""""}, {""name"": ""neo4j"", ""image_name"": ""neo4j:5.26"", ""tmp_fs"": """", ""environment"": ""NEO4J_AUTH: neo4j/wfdNeo4jPass123"", ""volume"": ""./additional_files/joinus/joinus-neo4j-seed.cypher:/seed.cypher"", ""health_check_command"": ""cypher-shell -u neo4j -p wfdNeo4jPass123 \""MATCH (:WfdSeedComplete) RETURN 1\"""", ""command"": ""[\""bash\"", \""-c\"", '/startup/docker-entrypoint.sh neo4j & pid=$!; until cypher-shell -u neo4j -p wfdNeo4jPass123 \""RETURN 1\"" >/dev/null 2>&1; do sleep 2; done; cypher-shell -u neo4j -p wfdNeo4jPass123 -f /seed.cypher; cypher-shell -u neo4j -p wfdNeo4jPass123 \""CREATE (:WfdSeedComplete)\""; wait $pid']""}]" lovemining,TRUE,,--server.port=8080 --spring.data.mongodb.uri=mongodb://db:27017/LoveMining --spring.neo4j.uri=bolt://neo4j:7687 --spring.neo4j.authentication.username=neo4j --spring.neo4j.authentication.password=wfdNeo4jPass123,http://localhost:8080/v3/api-docs,http://localhost:8080,FALSE,db;neo4j,"[{""image_name"": ""mongo:7"", ""tmp_fs"": """", ""environment"": """", ""volume"": ""./additional_files/lovemining/lovemining-mongo-seed.js:/docker-entrypoint-initdb.d/lovemining-mongo-seed.js"", ""health_check_command"": ""mongosh --quiet --eval \""db.adminCommand('ping')\""""}, {""name"": ""neo4j"", ""image_name"": ""neo4j:5.26"", ""tmp_fs"": """", ""environment"": ""NEO4J_AUTH: neo4j/wfdNeo4jPass123"", ""volume"": ""./additional_files/lovemining/lovemining-neo4j-seed.cypher:/seed.cypher"", ""health_check_command"": ""cypher-shell -u neo4j -p wfdNeo4jPass123 \""MATCH (:WfdSeedComplete) RETURN 1\"""", ""command"": ""[\""bash\"", \""-c\"", '/startup/docker-entrypoint.sh neo4j & pid=$!; until cypher-shell -u neo4j -p wfdNeo4jPass123 \""RETURN 1\"" >/dev/null 2>&1; do sleep 2; done; cypher-shell -u neo4j -p wfdNeo4jPass123 -f /seed.cypher; cypher-shell -u neo4j -p wfdNeo4jPass123 \""CREATE (:WfdSeedComplete)\""; wait $pid']""}]" +komga,TRUE,,--server.port=8080 --komga.config-dir=/tmp/komga --komga.database.file=/komga-database.sqlite,http://localhost:8080/v3/api-docs,http://localhost:8080,TRUE,, diff --git a/statistics/data.csv b/statistics/data.csv index 6982fa4de..de69865ed 100644 --- a/statistics/data.csv +++ b/statistics/data.csv @@ -52,6 +52,7 @@ TRUE,redis-sample,REST,Java,JDK 21,Maven,18,1006,Redis,UNDEFINED,4,FALSE,https:/ TRUE,adoptme,REST,Java,JDK 21,Maven,41,6158,Neo4j,UNDEFINED,14,FALSE,https://github.com/daanimelian/Programacion3-TPO TRUE,arimaa,REST,Java,JDK 21,Maven,141,9460,MySQL;MongoDB;Neo4j,UNDEFINED,38,TRUE,https://github.com/KEAArimaaProject/arimaa-backend TRUE,lovemining,REST,Java,JDK 21,Maven,25,1793,MongoDB;Neo4j,UNDEFINED,18,TRUE,https://github.com/Andryd22/LoveMining +TRUE,komga,REST,Kotlin,JDK 17,Gradle,543,62303,SQLite,MIT,174,TRUE,https://github.com/gotson/komga FALSE,ind0,REST,Java,JDK 8,Gradle,103,17039,PostgreSQL,Proprietary,20,FALSE,UNDEFINED FALSE,ind1,REST,Java;Kotlin,JDK 11,Gradle,163,15240,PostgreSQL,Proprietary,53,FALSE,UNDEFINED diff --git a/statistics/table_emb.md b/statistics/table_emb.md index 0551bf1df..fc6e261f2 100644 --- a/statistics/table_emb.md +++ b/statistics/table_emb.md @@ -23,6 +23,7 @@ |REST|__http-patch-spring__|1450|30|6|Java|JDK 11|Maven||| |REST|__jasper__|46791|337|61|Java|JDK 25|Maven|PostgreSQL|✓| |REST|__joinus__|7906|101|37|Java|JDK 21|Maven|MongoDB, Neo4j|✓| +|REST|__komga__|62303|543|174|Kotlin|JDK 17|Gradle|SQLite|✓| |REST|__languagetool__|174781|1385|2|Java|JDK 8|Maven||| |REST|__lovemining__|1793|25|18|Java|JDK 21|Maven|MongoDB, Neo4j|✓| |REST|__market__|9861|124|13|Java|JDK 11|Maven|H2|✓| From 82b1a30d4126cf015664f545f5ceb5fc91a3cf1e Mon Sep 17 00:00:00 2001 From: Omur Sahin Date: Sun, 13 Sep 2026 10:59:47 +0300 Subject: [PATCH 2/2] git fix --- jdk_17_gradle/cs/rest/komga/komga/build.gradle.kts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/jdk_17_gradle/cs/rest/komga/komga/build.gradle.kts b/jdk_17_gradle/cs/rest/komga/komga/build.gradle.kts index 153f6478f..36390a08a 100644 --- a/jdk_17_gradle/cs/rest/komga/komga/build.gradle.kts +++ b/jdk_17_gradle/cs/rest/komga/komga/build.gradle.kts @@ -32,6 +32,11 @@ repositories { mavenCentral() } +// MODIFIED: the WFD Docker build mounts only this level, so there is no .git to read +gitProperties { + failOnNoGitDirectory = false +} + val benchmarkSourceSet = sourceSets.create("benchmark") { java {