diff --git a/API/Services/Tasks/ScannerService.cs b/API/Services/Tasks/ScannerService.cs index 5f7c1695a..7156ba4ad 100644 --- a/API/Services/Tasks/ScannerService.cs +++ b/API/Services/Tasks/ScannerService.cs @@ -489,8 +489,6 @@ public class ScannerService : IScannerService // We don't need to send SignalR event as this is a background job that user doesn't need insight into _logger.LogInformation("[ScannerService] Scan library invoked via nightly scan job but a task is already running for {LibraryName}. Rescheduling for 4 hours", lib.Name); await Task.Delay(TimeSpan.FromHours(4)); - //BackgroundJob.Schedule(() => ScanLibraries(forceUpdate), TimeSpan.FromHours(4)); - //return; } await ScanLibrary(lib.Id, forceUpdate, true); diff --git a/API/Startup.cs b/API/Startup.cs index 6a5424303..7e3857c0b 100644 --- a/API/Startup.cs +++ b/API/Startup.cs @@ -137,7 +137,7 @@ public class Startup { c.SwaggerDoc("v1", new OpenApiInfo { - Version = "2.0", + Version = "3.1.0", Title = "Kavita", Description = $"Kavita provides a set of APIs that are authenticated by JWT. JWT token can be copied from local storage. Assume all fields of a payload are required. Built against v{BuildInfo.Version.ToString()}", License = new OpenApiLicense @@ -176,7 +176,7 @@ public class Startup Url = "{protocol}://{hostpath}", Variables = new Dictionary { - { "protocol", new OpenApiServerVariable { Default = "http", Enum = new List { "http", "https" } } }, + { "protocol", new OpenApiServerVariable { Default = "http", Enum = ["http", "https"]} }, { "hostpath", new OpenApiServerVariable { Default = "localhost:5000" } } } }); @@ -207,7 +207,7 @@ public class Startup .UseSimpleAssemblyNameTypeSerializer() .UseRecommendedSerializerSettings() .UseInMemoryStorage()); - //.UseSQLiteStorage("config/Hangfire.db")); // UseSQLiteStorage - SQLite has some issues around resuming jobs when aborted (and locking can cause high utilization) + //.UseSQLiteStorage("config/Hangfire.db")); // UseSQLiteStorage - SQLite has some issues around resuming jobs when aborted (and locking can cause high utilization) (NOTE: There is code to clear jobs on startup a redditor gave me) // Add the processing server as IHostedService services.AddHangfireServer(options => diff --git a/UI/Web/src/app/manga-reader/_components/infinite-scroller/infinite-scroller.component.html b/UI/Web/src/app/manga-reader/_components/infinite-scroller/infinite-scroller.component.html index 169e22803..1994591f4 100644 --- a/UI/Web/src/app/manga-reader/_components/infinite-scroller/infinite-scroller.component.html +++ b/UI/Web/src/app/manga-reader/_components/infinite-scroller/infinite-scroller.component.html @@ -1,39 +1,49 @@ -
- Captures Scroll Events: {{!this.isScrolling && this.allImagesLoaded}} - Is Scrolling: {{isScrollingForwards() ? 'Forwards' : 'Backwards'}} {{this.isScrolling}} - All Images Loaded: {{this.allImagesLoaded}} - Prefetched {{minPageLoaded}}-{{maxPageLoaded}} - Pages: {{pageNum}} / {{totalPages - 1}} - At Top: {{atTop}} - At Bottom: {{atBottom}} - Total Height: {{getTotalHeight()}} - Total Scroll: {{getTotalScroll()}} - Scroll Top: {{getScrollTop()}} -
- -
diff --git a/UI/Web/src/app/manga-reader/_components/infinite-scroller/infinite-scroller.component.scss b/UI/Web/src/app/manga-reader/_components/infinite-scroller/infinite-scroller.component.scss index 3f0b243c5..b627c84e2 100644 --- a/UI/Web/src/app/manga-reader/_components/infinite-scroller/infinite-scroller.component.scss +++ b/UI/Web/src/app/manga-reader/_components/infinite-scroller/infinite-scroller.component.scss @@ -21,8 +21,12 @@ .text { z-index: 101; - + } + + .empty-space { + height: 200px; + } } diff --git a/UI/Web/src/app/manga-reader/_components/infinite-scroller/infinite-scroller.component.ts b/UI/Web/src/app/manga-reader/_components/infinite-scroller/infinite-scroller.component.ts index b2dcf497b..802d0d3fa 100644 --- a/UI/Web/src/app/manga-reader/_components/infinite-scroller/infinite-scroller.component.ts +++ b/UI/Web/src/app/manga-reader/_components/infinite-scroller/infinite-scroller.component.ts @@ -1,4 +1,4 @@ -import { DOCUMENT, NgIf, NgFor, AsyncPipe } from '@angular/common'; +import {DOCUMENT, AsyncPipe, NgStyle} from '@angular/common'; import { AfterViewInit, ChangeDetectionStrategy, @@ -16,7 +16,7 @@ import { Renderer2, SimpleChanges, ViewChild } from '@angular/core'; -import {BehaviorSubject, filter, fromEvent, map, Observable, of, ReplaySubject} from 'rxjs'; +import {BehaviorSubject, fromEvent, map, Observable, of, ReplaySubject} from 'rxjs'; import { debounceTime } from 'rxjs/operators'; import { ScrollService } from 'src/app/_services/scroll.service'; import { ReaderService } from '../../../_services/reader.service'; @@ -62,7 +62,7 @@ const enum DEBUG_MODES { styleUrls: ['./infinite-scroller.component.scss'], changeDetection: ChangeDetectionStrategy.OnPush, standalone: true, - imports: [NgIf, NgFor, AsyncPipe, TranslocoDirective, InfiniteScrollModule, SafeStylePipe] + imports: [AsyncPipe, TranslocoDirective, InfiniteScrollModule, SafeStylePipe, NgStyle] }) export class InfiniteScrollerComponent implements OnInit, OnChanges, OnDestroy, AfterViewInit { diff --git a/UI/Web/src/app/manga-reader/_components/manga-reader/manga-reader.component.ts b/UI/Web/src/app/manga-reader/_components/manga-reader/manga-reader.component.ts index 87467dbde..c9d10881a 100644 --- a/UI/Web/src/app/manga-reader/_components/manga-reader/manga-reader.component.ts +++ b/UI/Web/src/app/manga-reader/_components/manga-reader/manga-reader.component.ts @@ -19,6 +19,7 @@ import { BehaviorSubject, debounceTime, distinctUntilChanged, + filter, forkJoin, fromEvent, map, @@ -399,7 +400,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy { */ debugMode: boolean = false; /** - * Width override label for maunal width control + * Width override label for manual width control */ widthOverrideLabel$ : Observable = new Observable(); @@ -554,55 +555,7 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy { takeUntilDestroyed(this.destroyRef) ).subscribe(() => {}); - //only enable the width override slider under certain conditions - // width mode selected - // splitting is set to fit to screen, otherwise disable - // when disable set the value to 0 - // to use the default of the current single page reader - this.generalSettingsForm.get('pageSplitOption')?.valueChanges.pipe( - tap(val => { - const fitting = this.generalSettingsForm.get('fittingOption')?.value; - const widthOverrideControl = this.generalSettingsForm.get('widthSlider')!; - - if (PageSplitOption.FitSplit == val && FITTING_OPTION.WIDTH == fitting) { - widthOverrideControl?.enable(); - } else { - widthOverrideControl?.setValue(0); - widthOverrideControl?.disable(); - } - }), - takeUntilDestroyed(this.destroyRef) - ).subscribe(() => {}); - - //only enable the width override slider under certain conditions - // width mode selected - // splitting is set to fit to screen, otherwise disable - // when disable set the value to 0 - // to use the default of the current single page reader - this.generalSettingsForm.get('fittingOption')?.valueChanges.pipe( - tap(val => { - const splitting = this.generalSettingsForm.get('pageSplitOption')?.value; - const widthOverrideControl = this.generalSettingsForm.get('widthSlider')!; - - if (PageSplitOption.FitSplit == splitting && FITTING_OPTION.WIDTH == val){ - widthOverrideControl?.enable(); - } else { - widthOverrideControl?.setValue(0); - widthOverrideControl?.disable(); - } - }), - takeUntilDestroyed(this.destroyRef) - ).subscribe(() => {}); - - //sets the default override to 0, fixing the none% bug - this.generalSettingsForm.get('widthSlider')!.setValue(0); - - //send the current width override value to the label - this.widthOverrideLabel$ = this.readerSettings$?.pipe( - map(values => (parseInt(values.widthSlider) <= 0) ? '' : values.widthSlider + '%'), - takeUntilDestroyed(this.destroyRef) - ); - + this.setupWidthOverrideTriggers(); this.generalSettingsForm.get('layoutMode')?.valueChanges.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(val => { @@ -746,6 +699,68 @@ export class MangaReaderComponent implements OnInit, AfterViewInit, OnDestroy { } } + /** + * Width override is only valid under the following conditions: + * Image Scaling is Width + * Reader Mode is Webtoon + * + * In all other cases, the form will be disabled and set to 0 which indicates default/off state. + */ + setupWidthOverrideTriggers() { + const widthOverrideControl = this.generalSettingsForm.get('widthSlider')!; + + const enableWidthOverride = () => { + widthOverrideControl.enable(); + }; + + const disableWidthOverride = () => { + widthOverrideControl.setValue(0); + widthOverrideControl.disable(); + }; + + const handleControlChanges = () => { + const fitting = this.generalSettingsForm.get('fittingOption')?.value; + const splitting = this.generalSettingsForm.get('pageSplitOption')?.value; + + if ((PageSplitOption.FitSplit == splitting && FITTING_OPTION.WIDTH == fitting) || this.readerMode === ReaderMode.Webtoon) { + enableWidthOverride(); + } else { + disableWidthOverride(); + } + }; + + // Reader mode changes + this.readerModeSubject.asObservable() + .pipe( + filter(v => v === ReaderMode.Webtoon), + tap(enableWidthOverride), + takeUntilDestroyed(this.destroyRef) + ) + .subscribe(); + + // Page split option changes + this.generalSettingsForm.get('pageSplitOption')?.valueChanges.pipe( + distinctUntilChanged(), + tap(handleControlChanges), + takeUntilDestroyed(this.destroyRef) + ).subscribe(); + + // Fitting option changes + this.generalSettingsForm.get('fittingOption')?.valueChanges.pipe( + tap(handleControlChanges), + takeUntilDestroyed(this.destroyRef) + ).subscribe(); + + // Set the default override to 0 + widthOverrideControl.setValue(0); + + //send the current width override value to the label + this.widthOverrideLabel$ = this.readerSettings$?.pipe( + map(values => (parseInt(values.widthSlider) <= 0) ? '' : values.widthSlider + '%'), + takeUntilDestroyed(this.destroyRef) + ); + } + createReaderSettingsUpdate() { return { pageSplit: parseInt(this.generalSettingsForm.get('pageSplitOption')?.value, 10), diff --git a/openapi.json b/openapi.json index d22973612..11956030d 100644 --- a/openapi.json +++ b/openapi.json @@ -2,12 +2,12 @@ "openapi": "3.0.1", "info": { "title": "Kavita", - "description": "Kavita provides a set of APIs that are authenticated by JWT. JWT token can be copied from local storage. Assume all fields of a payload are required. Built against v0.8.1.17", + "description": "Kavita provides a set of APIs that are authenticated by JWT. JWT token can be copied from local storage. Assume all fields of a payload are required. Built against v0.8.1.18", "license": { "name": "GPL-3.0", "url": "https://github.com/Kareadita/Kavita/blob/develop/LICENSE" }, - "version": "2.0" + "version": "3.1.0" }, "servers": [ { @@ -22251,2074 +22251,4 @@ "description": "Responsible for all things Want To Read" } ] -} } - }, - "security": [ - { - "Bearer": [ ] - } - ], - "tags": [ - { - "name": "Account", - "description": "All Account matters" - }, - { - "name": "Cbl", - "description": "Responsible for the CBL import flow" - }, - { - "name": "Collection", - "description": "APIs for Collections" - }, - { - "name": "Device", - "description": "Responsible interacting and creating Devices" - }, - { - "name": "Download", - "description": "All APIs related to downloading entities from the system. Requires Download Role or Admin Role." - }, - { - "name": "Filter", - "description": "This is responsible for Filter caching" - }, - { - "name": "Image", - "description": "Responsible for servicing up images stored in Kavita for entities" - }, - { - "name": "OPDS2", - "description": "All APIs for the OPDS 2.0 Implementation" - }, - { - "name": "Panels", - "description": "For the Panels app explicitly" - }, - { - "name": "Rating", - "description": "Responsible for providing external ratings for Series" - }, - { - "name": "Reader", - "description": "For all things regarding reading, mainly focusing on non-Book related entities" - }, - { - "name": "Search", - "description": "Responsible for the Search interface from the UI" - }, - { - "name": "Stream", - "description": "Responsible for anything that deals with Streams (SmartFilters, ExternalSource, DashboardStream, SideNavStream)" - }, - { - "name": "Tachiyomi", - "description": "All APIs are for Tachiyomi extension and app. They have hacks for our implementation and should not be used for any\r\nother purposes." - }, - { - "name": "Upload", - "description": "" - }, - { - "name": "WantToRead", - "description": "Responsible for all things Want To Read" - } - ] -} }, - "token": { - "type": "string", - "nullable": true - }, - "refreshToken": { - "type": "string", - "nullable": true - }, - "apiKey": { - "type": "string", - "nullable": true - }, - "preferences": { - "$ref": "#/components/schemas/UserPreferencesDto" - }, - "ageRestriction": { - "$ref": "#/components/schemas/AgeRestrictionDto" - }, - "kavitaVersion": { - "type": "string", - "nullable": true - } - }, - "additionalProperties": false - }, - "UserDtoICount": { - "type": "object", - "properties": { - "value": { - "$ref": "#/components/schemas/UserDto" - }, - "count": { - "type": "integer", - "format": "int64" - } - }, - "additionalProperties": false - }, - "UserPreferencesDto": { - "required": [ - "autoCloseMenu", - "backgroundColor", - "blurUnreadSummaries", - "bookReaderFontFamily", - "bookReaderFontSize", - "bookReaderImmersiveMode", - "bookReaderLayoutMode", - "bookReaderLineSpacing", - "bookReaderMargin", - "bookReaderReadingDirection", - "bookReaderTapToPaginate", - "bookReaderThemeName", - "bookReaderWritingStyle", - "collapseSeriesRelationships", - "emulateBook", - "globalPageLayoutMode", - "layoutMode", - "locale", - "noTransitions", - "pageSplitOption", - "pdfLayoutMode", - "pdfScrollMode", - "pdfSpreadMode", - "pdfTheme", - "promptForDownloadSize", - "readerMode", - "readingDirection", - "scalingOption", - "shareReviews", - "showScreenHints", - "swipeToPaginate", - "theme" - ], - "type": "object", - "properties": { - "readingDirection": { - "enum": [ - 0, - 1 - ], - "type": "integer", - "description": "Manga Reader Option: What direction should the next/prev page buttons go", - "format": "int32" - }, - "scalingOption": { - "enum": [ - 0, - 1, - 2, - 3 - ], - "type": "integer", - "description": "Manga Reader Option: How should the image be scaled to screen", - "format": "int32" - }, - "pageSplitOption": { - "enum": [ - 0, - 1, - 2, - 3 - ], - "type": "integer", - "description": "Manga Reader Option: Which side of a split image should we show first", - "format": "int32" - }, - "readerMode": { - "enum": [ - 0, - 1, - 2 - ], - "type": "integer", - "description": "Manga Reader Option: How the manga reader should perform paging or reading of the file\r\n\r\nWebtoon uses scrolling to page, LeftRight uses paging by clicking left/right side of reader, UpDown uses paging\r\nby clicking top/bottom sides of reader.\r\n", - "format": "int32" - }, - "layoutMode": { - "enum": [ - 1, - 2, - 3 - ], - "type": "integer", - "description": "Manga Reader Option: How many pages to display in the reader at once", - "format": "int32" - }, - "emulateBook": { - "type": "boolean", - "description": "Manga Reader Option: Emulate a book by applying a shadow effect on the pages" - }, - "backgroundColor": { - "minLength": 1, - "type": "string", - "description": "Manga Reader Option: Background color of the reader" - }, - "swipeToPaginate": { - "type": "boolean", - "description": "Manga Reader Option: Should swiping trigger pagination" - }, - "autoCloseMenu": { - "type": "boolean", - "description": "Manga Reader Option: Allow the menu to close after 6 seconds without interaction" - }, - "showScreenHints": { - "type": "boolean", - "description": "Manga Reader Option: Show screen hints to the user on some actions, ie) pagination direction change" - }, - "bookReaderMargin": { - "type": "integer", - "description": "Book Reader Option: Override extra Margin", - "format": "int32" - }, - "bookReaderLineSpacing": { - "type": "integer", - "description": "Book Reader Option: Override line-height", - "format": "int32" - }, - "bookReaderFontSize": { - "type": "integer", - "description": "Book Reader Option: Override font size", - "format": "int32" - }, - "bookReaderFontFamily": { - "minLength": 1, - "type": "string", - "description": "Book Reader Option: Maps to the default Kavita font-family (inherit) or an override" - }, - "bookReaderTapToPaginate": { - "type": "boolean", - "description": "Book Reader Option: Allows tapping on side of screens to paginate" - }, - "bookReaderReadingDirection": { - "enum": [ - 0, - 1 - ], - "type": "integer", - "description": "Book Reader Option: What direction should the next/prev page buttons go", - "format": "int32" - }, - "bookReaderWritingStyle": { - "enum": [ - 0, - 1 - ], - "type": "integer", - "description": "Book Reader Option: What writing style should be used, horizontal or vertical.", - "format": "int32" - }, - "theme": { - "$ref": "#/components/schemas/SiteThemeDto" - }, - "bookReaderThemeName": { - "minLength": 1, - "type": "string" - }, - "bookReaderLayoutMode": { - "enum": [ - 0, - 1, - 2 - ], - "type": "integer", - "format": "int32" - }, - "bookReaderImmersiveMode": { - "type": "boolean", - "description": "Book Reader Option: A flag that hides the menu-ing system behind a click on the screen. This should be used with tap to paginate, but the app doesn't enforce this." - }, - "globalPageLayoutMode": { - "enum": [ - 0, - 1 - ], - "type": "integer", - "description": "Global Site Option: If the UI should layout items as Cards or List items", - "format": "int32" - }, - "blurUnreadSummaries": { - "type": "boolean", - "description": "UI Site Global Setting: If unread summaries should be blurred until expanded or unless user has read it already" - }, - "promptForDownloadSize": { - "type": "boolean", - "description": "UI Site Global Setting: Should Kavita prompt user to confirm downloads that are greater than 100 MB." - }, - "noTransitions": { - "type": "boolean", - "description": "UI Site Global Setting: Should Kavita disable CSS transitions" - }, - "collapseSeriesRelationships": { - "type": "boolean", - "description": "When showing series, only parent series or series with no relationships will be returned" - }, - "shareReviews": { - "type": "boolean", - "description": "UI Site Global Setting: Should series reviews be shared with all users in the server" - }, - "locale": { - "minLength": 1, - "type": "string", - "description": "UI Site Global Setting: The language locale that should be used for the user" - }, - "pdfTheme": { - "enum": [ - 0, - 1 - ], - "type": "integer", - "description": "PDF Reader: Theme of the Reader", - "format": "int32" - }, - "pdfScrollMode": { - "enum": [ - 0, - 1, - 3 - ], - "type": "integer", - "description": "PDF Reader: Scroll mode of the reader", - "format": "int32" - }, - "pdfLayoutMode": { - "enum": [ - 0, - 2 - ], - "type": "integer", - "description": "PDF Reader: Layout Mode of the reader", - "format": "int32" - }, - "pdfSpreadMode": { - "enum": [ - 0, - 1, - 2 - ], - "type": "integer", - "description": "PDF Reader: Spread Mode of the reader", - "format": "int32" - } - }, - "additionalProperties": false - }, - "UserReadStatistics": { - "type": "object", - "properties": { - "totalPagesRead": { - "type": "integer", - "description": "Total number of pages read", - "format": "int64" - }, - "totalWordsRead": { - "type": "integer", - "description": "Total number of words read", - "format": "int64" - }, - "timeSpentReading": { - "type": "integer", - "description": "Total time spent reading based on estimates", - "format": "int64" - }, - "chaptersRead": { - "type": "integer", - "format": "int64" - }, - "lastActive": { - "type": "string", - "format": "date-time" - }, - "avgHoursPerWeekSpentReading": { - "type": "number", - "format": "double" - }, - "percentReadPerLibrary": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SingleStatCount" - }, - "nullable": true - } - }, - "additionalProperties": false - }, - "UserReviewDto": { - "type": "object", - "properties": { - "tagline": { - "type": "string", - "description": "A tagline for the review", - "nullable": true - }, - "body": { - "type": "string", - "description": "The main review", - "nullable": true - }, - "bodyJustText": { - "type": "string", - "description": "The main body with just text, for review preview", - "nullable": true - }, - "seriesId": { - "type": "integer", - "description": "The series this is for", - "format": "int32" - }, - "libraryId": { - "type": "integer", - "description": "The library this series belongs in", - "format": "int32" - }, - "username": { - "type": "string", - "description": "The user who wrote this", - "nullable": true - }, - "totalVotes": { - "type": "integer", - "format": "int32" - }, - "rating": { - "type": "number", - "format": "float" - }, - "rawBody": { - "type": "string", - "nullable": true - }, - "score": { - "type": "integer", - "description": "How many upvotes this review has gotten", - "format": "int32" - }, - "siteUrl": { - "type": "string", - "description": "If External, the url of the review", - "nullable": true - }, - "isExternal": { - "type": "boolean", - "description": "Does this review come from an external Source" - }, - "provider": { - "enum": [ - 0, - 1, - 2 - ], - "type": "integer", - "description": "If this review is External, which Provider did it come from", - "format": "int32" - } - }, - "additionalProperties": false, - "description": "Represents a User Review for a given Series" - }, - "Volume": { - "required": [ - "maxNumber", - "minNumber", - "name" - ], - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "name": { - "type": "string", - "description": "A String representation of the volume number. Allows for floats. Can also include a range (1-2).", - "nullable": true - }, - "lookupName": { - "type": "string", - "description": "This is just the original Parsed volume number for lookups", - "nullable": true - }, - "number": { - "type": "integer", - "description": "The minimum number in the Name field in Int form", - "format": "int32", - "deprecated": true - }, - "minNumber": { - "type": "number", - "description": "The minimum number in the Name field", - "format": "float" - }, - "maxNumber": { - "type": "number", - "description": "The maximum number in the Name field (same as Minimum if Name isn't a range)", - "format": "float" - }, - "chapters": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Chapter" - }, - "nullable": true - }, - "created": { - "type": "string", - "format": "date-time" - }, - "lastModified": { - "type": "string", - "format": "date-time" - }, - "createdUtc": { - "type": "string", - "format": "date-time" - }, - "lastModifiedUtc": { - "type": "string", - "format": "date-time" - }, - "coverImage": { - "type": "string", - "description": "Absolute path to the (managed) image file", - "nullable": true - }, - "pages": { - "type": "integer", - "description": "Total pages of all chapters in this volume", - "format": "int32" - }, - "wordCount": { - "type": "integer", - "description": "Total Word count of all chapters in this volume.", - "format": "int64" - }, - "minHoursToRead": { - "type": "integer", - "format": "int32" - }, - "maxHoursToRead": { - "type": "integer", - "format": "int32" - }, - "avgHoursToRead": { - "type": "integer", - "format": "int32" - }, - "series": { - "$ref": "#/components/schemas/Series" - }, - "seriesId": { - "type": "integer", - "format": "int32" - } - }, - "additionalProperties": false - }, - "VolumeDto": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "minNumber": { - "type": "number", - "format": "float" - }, - "maxNumber": { - "type": "number", - "format": "float" - }, - "name": { - "type": "string", - "nullable": true - }, - "number": { - "type": "integer", - "description": "This will map to MinNumber. Number was removed in v0.7.13.8/v0.7.14", - "format": "int32", - "deprecated": true - }, - "pages": { - "type": "integer", - "format": "int32" - }, - "pagesRead": { - "type": "integer", - "format": "int32" - }, - "lastModifiedUtc": { - "type": "string", - "format": "date-time" - }, - "createdUtc": { - "type": "string", - "format": "date-time" - }, - "created": { - "type": "string", - "description": "When chapter was created in local server time", - "format": "date-time" - }, - "lastModified": { - "type": "string", - "description": "When chapter was last modified in local server time", - "format": "date-time" - }, - "seriesId": { - "type": "integer", - "format": "int32" - }, - "chapters": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ChapterDto" - }, - "nullable": true - }, - "minHoursToRead": { - "type": "integer", - "format": "int32" - }, - "maxHoursToRead": { - "type": "integer", - "format": "int32" - }, - "avgHoursToRead": { - "type": "integer", - "format": "int32" - } - }, - "additionalProperties": false - } - }, - "securitySchemes": { - "Bearer": { - "type": "apiKey", - "description": "Please insert JWT with Bearer into field", - "name": "Authorization", - "in": "header" - } - } - }, - "security": [ - { - "Bearer": [ ] - } - ], - "tags": [ - { - "name": "Account", - "description": "All Account matters" - }, - { - "name": "Cbl", - "description": "Responsible for the CBL import flow" - }, - { - "name": "Collection", - "description": "APIs for Collections" - }, - { - "name": "Device", - "description": "Responsible interacting and creating Devices" - }, - { - "name": "Download", - "description": "All APIs related to downloading entities from the system. Requires Download Role or Admin Role." - }, - { - "name": "Filter", - "description": "This is responsible for Filter caching" - }, - { - "name": "Image", - "description": "Responsible for servicing up images stored in Kavita for entities" - }, - { - "name": "Panels", - "description": "For the Panels app explicitly" - }, - { - "name": "Rating", - "description": "Responsible for providing external ratings for Series" - }, - { - "name": "Reader", - "description": "For all things regarding reading, mainly focusing on non-Book related entities" - }, - { - "name": "Search", - "description": "Responsible for the Search interface from the UI" - }, - { - "name": "Stream", - "description": "Responsible for anything that deals with Streams (SmartFilters, ExternalSource, DashboardStream, SideNavStream)" - }, - { - "name": "Tachiyomi", - "description": "All APIs are for Tachiyomi extension and app. They have hacks for our implementation and should not be used for any\r\nother purposes." - }, - { - "name": "Upload", - "description": "" - }, - { - "name": "WantToRead", - "description": "Responsible for all things Want To Read" - } - ] -} "object", - "properties": { - "seriesId": { - "type": "integer", - "format": "int32" - }, - "body": { - "type": "string", - "nullable": true - } - }, - "additionalProperties": false - }, - "UpdateWantToReadDto": { - "type": "object", - "properties": { - "seriesIds": { - "type": "array", - "items": { - "type": "integer", - "format": "int32" - }, - "description": "List of Series Ids that will be Added/Removed", - "nullable": true - } - }, - "additionalProperties": false, - "description": "A list of Series to pass when working with Want To Read APIs" - }, - "UploadFileDto": { - "required": [ - "id", - "url" - ], - "type": "object", - "properties": { - "id": { - "type": "integer", - "description": "Id of the Entity", - "format": "int32" - }, - "url": { - "type": "string", - "description": "Base Url encoding of the file to upload from (can be null)", - "nullable": true - } - }, - "additionalProperties": false - }, - "UploadUrlDto": { - "required": [ - "url" - ], - "type": "object", - "properties": { - "url": { - "minLength": 1, - "type": "string", - "description": "External url" - } - }, - "additionalProperties": false - }, - "UserDto": { - "type": "object", - "properties": { - "username": { - "type": "string", - "nullable": true - }, - "email": { - "type": "string", - "nullable": true - }, - "token": { - "type": "string", - "nullable": true - }, - "refreshToken": { - "type": "string", - "nullable": true - }, - "apiKey": { - "type": "string", - "nullable": true - }, - "preferences": { - "$ref": "#/components/schemas/UserPreferencesDto" - }, - "ageRestriction": { - "$ref": "#/components/schemas/AgeRestrictionDto" - }, - "kavitaVersion": { - "type": "string", - "nullable": true - } - }, - "additionalProperties": false - }, - "UserDtoICount": { - "type": "object", - "properties": { - "value": { - "$ref": "#/components/schemas/UserDto" - }, - "count": { - "type": "integer", - "format": "int64" - } - }, - "additionalProperties": false - }, - "UserPreferencesDto": { - "required": [ - "autoCloseMenu", - "backgroundColor", - "blurUnreadSummaries", - "bookReaderFontFamily", - "bookReaderFontSize", - "bookReaderImmersiveMode", - "bookReaderLayoutMode", - "bookReaderLineSpacing", - "bookReaderMargin", - "bookReaderReadingDirection", - "bookReaderTapToPaginate", - "bookReaderThemeName", - "bookReaderWritingStyle", - "collapseSeriesRelationships", - "emulateBook", - "globalPageLayoutMode", - "layoutMode", - "locale", - "noTransitions", - "pageSplitOption", - "pdfLayoutMode", - "pdfScrollMode", - "pdfSpreadMode", - "pdfTheme", - "promptForDownloadSize", - "readerMode", - "readingDirection", - "scalingOption", - "shareReviews", - "showScreenHints", - "swipeToPaginate", - "theme" - ], - "type": "object", - "properties": { - "readingDirection": { - "enum": [ - 0, - 1 - ], - "type": "integer", - "description": "Manga Reader Option: What direction should the next/prev page buttons go", - "format": "int32" - }, - "scalingOption": { - "enum": [ - 0, - 1, - 2, - 3 - ], - "type": "integer", - "description": "Manga Reader Option: How should the image be scaled to screen", - "format": "int32" - }, - "pageSplitOption": { - "enum": [ - 0, - 1, - 2, - 3 - ], - "type": "integer", - "description": "Manga Reader Option: Which side of a split image should we show first", - "format": "int32" - }, - "readerMode": { - "enum": [ - 0, - 1, - 2 - ], - "type": "integer", - "description": "Manga Reader Option: How the manga reader should perform paging or reading of the file\r\n\r\nWebtoon uses scrolling to page, LeftRight uses paging by clicking left/right side of reader, UpDown uses paging\r\nby clicking top/bottom sides of reader.\r\n", - "format": "int32" - }, - "layoutMode": { - "enum": [ - 1, - 2, - 3 - ], - "type": "integer", - "description": "Manga Reader Option: How many pages to display in the reader at once", - "format": "int32" - }, - "emulateBook": { - "type": "boolean", - "description": "Manga Reader Option: Emulate a book by applying a shadow effect on the pages" - }, - "backgroundColor": { - "minLength": 1, - "type": "string", - "description": "Manga Reader Option: Background color of the reader" - }, - "swipeToPaginate": { - "type": "boolean", - "description": "Manga Reader Option: Should swiping trigger pagination" - }, - "autoCloseMenu": { - "type": "boolean", - "description": "Manga Reader Option: Allow the menu to close after 6 seconds without interaction" - }, - "showScreenHints": { - "type": "boolean", - "description": "Manga Reader Option: Show screen hints to the user on some actions, ie) pagination direction change" - }, - "bookReaderMargin": { - "type": "integer", - "description": "Book Reader Option: Override extra Margin", - "format": "int32" - }, - "bookReaderLineSpacing": { - "type": "integer", - "description": "Book Reader Option: Override line-height", - "format": "int32" - }, - "bookReaderFontSize": { - "type": "integer", - "description": "Book Reader Option: Override font size", - "format": "int32" - }, - "bookReaderFontFamily": { - "minLength": 1, - "type": "string", - "description": "Book Reader Option: Maps to the default Kavita font-family (inherit) or an override" - }, - "bookReaderTapToPaginate": { - "type": "boolean", - "description": "Book Reader Option: Allows tapping on side of screens to paginate" - }, - "bookReaderReadingDirection": { - "enum": [ - 0, - 1 - ], - "type": "integer", - "description": "Book Reader Option: What direction should the next/prev page buttons go", - "format": "int32" - }, - "bookReaderWritingStyle": { - "enum": [ - 0, - 1 - ], - "type": "integer", - "description": "Book Reader Option: What writing style should be used, horizontal or vertical.", - "format": "int32" - }, - "theme": { - "$ref": "#/components/schemas/SiteThemeDto" - }, - "bookReaderThemeName": { - "minLength": 1, - "type": "string" - }, - "bookReaderLayoutMode": { - "enum": [ - 0, - 1, - 2 - ], - "type": "integer", - "format": "int32" - }, - "bookReaderImmersiveMode": { - "type": "boolean", - "description": "Book Reader Option: A flag that hides the menu-ing system behind a click on the screen. This should be used with tap to paginate, but the app doesn't enforce this." - }, - "globalPageLayoutMode": { - "enum": [ - 0, - 1 - ], - "type": "integer", - "description": "Global Site Option: If the UI should layout items as Cards or List items", - "format": "int32" - }, - "blurUnreadSummaries": { - "type": "boolean", - "description": "UI Site Global Setting: If unread summaries should be blurred until expanded or unless user has read it already" - }, - "promptForDownloadSize": { - "type": "boolean", - "description": "UI Site Global Setting: Should Kavita prompt user to confirm downloads that are greater than 100 MB." - }, - "noTransitions": { - "type": "boolean", - "description": "UI Site Global Setting: Should Kavita disable CSS transitions" - }, - "collapseSeriesRelationships": { - "type": "boolean", - "description": "When showing series, only parent series or series with no relationships will be returned" - }, - "shareReviews": { - "type": "boolean", - "description": "UI Site Global Setting: Should series reviews be shared with all users in the server" - }, - "locale": { - "minLength": 1, - "type": "string", - "description": "UI Site Global Setting: The language locale that should be used for the user" - }, - "pdfTheme": { - "enum": [ - 0, - 1 - ], - "type": "integer", - "description": "PDF Reader: Theme of the Reader", - "format": "int32" - }, - "pdfScrollMode": { - "enum": [ - 0, - 1, - 3 - ], - "type": "integer", - "description": "PDF Reader: Scroll mode of the reader", - "format": "int32" - }, - "pdfLayoutMode": { - "enum": [ - 0, - 2 - ], - "type": "integer", - "description": "PDF Reader: Layout Mode of the reader", - "format": "int32" - }, - "pdfSpreadMode": { - "enum": [ - 0, - 1, - 2 - ], - "type": "integer", - "description": "PDF Reader: Spread Mode of the reader", - "format": "int32" - } - }, - "additionalProperties": false - }, - "UserReadStatistics": { - "type": "object", - "properties": { - "totalPagesRead": { - "type": "integer", - "description": "Total number of pages read", - "format": "int64" - }, - "totalWordsRead": { - "type": "integer", - "description": "Total number of words read", - "format": "int64" - }, - "timeSpentReading": { - "type": "integer", - "description": "Total time spent reading based on estimates", - "format": "int64" - }, - "chaptersRead": { - "type": "integer", - "format": "int64" - }, - "lastActive": { - "type": "string", - "format": "date-time" - }, - "avgHoursPerWeekSpentReading": { - "type": "number", - "format": "double" - }, - "percentReadPerLibrary": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SingleStatCount" - }, - "nullable": true - } - }, - "additionalProperties": false - }, - "UserReviewDto": { - "type": "object", - "properties": { - "tagline": { - "type": "string", - "description": "A tagline for the review", - "nullable": true - }, - "body": { - "type": "string", - "description": "The main review", - "nullable": true - }, - "bodyJustText": { - "type": "string", - "description": "The main body with just text, for review preview", - "nullable": true - }, - "seriesId": { - "type": "integer", - "description": "The series this is for", - "format": "int32" - }, - "libraryId": { - "type": "integer", - "description": "The library this series belongs in", - "format": "int32" - }, - "username": { - "type": "string", - "description": "The user who wrote this", - "nullable": true - }, - "totalVotes": { - "type": "integer", - "format": "int32" - }, - "rating": { - "type": "number", - "format": "float" - }, - "rawBody": { - "type": "string", - "nullable": true - }, - "score": { - "type": "integer", - "description": "How many upvotes this review has gotten", - "format": "int32" - }, - "siteUrl": { - "type": "string", - "description": "If External, the url of the review", - "nullable": true - }, - "isExternal": { - "type": "boolean", - "description": "Does this review come from an external Source" - }, - "provider": { - "enum": [ - 0, - 1, - 2 - ], - "type": "integer", - "description": "If this review is External, which Provider did it come from", - "format": "int32" - } - }, - "additionalProperties": false, - "description": "Represents a User Review for a given Series" - }, - "Volume": { - "required": [ - "maxNumber", - "minNumber", - "name" - ], - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "name": { - "type": "string", - "description": "A String representation of the volume number. Allows for floats. Can also include a range (1-2).", - "nullable": true - }, - "lookupName": { - "type": "string", - "description": "This is just the original Parsed volume number for lookups", - "nullable": true - }, - "number": { - "type": "integer", - "description": "The minimum number in the Name field in Int form", - "format": "int32", - "deprecated": true - }, - "minNumber": { - "type": "number", - "description": "The minimum number in the Name field", - "format": "float" - }, - "maxNumber": { - "type": "number", - "description": "The maximum number in the Name field (same as Minimum if Name isn't a range)", - "format": "float" - }, - "chapters": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Chapter" - }, - "nullable": true - }, - "created": { - "type": "string", - "format": "date-time" - }, - "lastModified": { - "type": "string", - "format": "date-time" - }, - "createdUtc": { - "type": "string", - "format": "date-time" - }, - "lastModifiedUtc": { - "type": "string", - "format": "date-time" - }, - "coverImage": { - "type": "string", - "description": "Absolute path to the (managed) image file", - "nullable": true - }, - "pages": { - "type": "integer", - "description": "Total pages of all chapters in this volume", - "format": "int32" - }, - "wordCount": { - "type": "integer", - "description": "Total Word count of all chapters in this volume.", - "format": "int64" - }, - "minHoursToRead": { - "type": "integer", - "format": "int32" - }, - "maxHoursToRead": { - "type": "integer", - "format": "int32" - }, - "avgHoursToRead": { - "type": "integer", - "format": "int32" - }, - "series": { - "$ref": "#/components/schemas/Series" - }, - "seriesId": { - "type": "integer", - "format": "int32" - } - }, - "additionalProperties": false - }, - "VolumeDto": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "minNumber": { - "type": "number", - "format": "float" - }, - "maxNumber": { - "type": "number", - "format": "float" - }, - "name": { - "type": "string", - "nullable": true - }, - "number": { - "type": "integer", - "description": "This will map to MinNumber. Number was removed in v0.7.13.8/v0.7.14", - "format": "int32", - "deprecated": true - }, - "pages": { - "type": "integer", - "format": "int32" - }, - "pagesRead": { - "type": "integer", - "format": "int32" - }, - "lastModifiedUtc": { - "type": "string", - "format": "date-time" - }, - "createdUtc": { - "type": "string", - "format": "date-time" - }, - "created": { - "type": "string", - "description": "When chapter was created in local server time", - "format": "date-time" - }, - "lastModified": { - "type": "string", - "description": "When chapter was last modified in local server time", - "format": "date-time" - }, - "seriesId": { - "type": "integer", - "format": "int32" - }, - "chapters": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ChapterDto" - }, - "nullable": true - }, - "minHoursToRead": { - "type": "integer", - "format": "int32" - }, - "maxHoursToRead": { - "type": "integer", - "format": "int32" - }, - "avgHoursToRead": { - "type": "integer", - "format": "int32" - } - }, - "additionalProperties": false - } - }, - "securitySchemes": { - "Bearer": { - "type": "apiKey", - "description": "Please insert JWT with Bearer into field", - "name": "Authorization", - "in": "header" - } - } - }, - "security": [ - { - "Bearer": [ ] - } - ], - "tags": [ - { - "name": "Account", - "description": "All Account matters" - }, - { - "name": "Cbl", - "description": "Responsible for the CBL import flow" - }, - { - "name": "Collection", - "description": "APIs for Collections" - }, - { - "name": "Device", - "description": "Responsible interacting and creating Devices" - }, - { - "name": "Download", - "description": "All APIs related to downloading entities from the system. Requires Download Role or Admin Role." - }, - { - "name": "Filter", - "description": "This is responsible for Filter caching" - }, - { - "name": "Image", - "description": "Responsible for servicing up images stored in Kavita for entities" - }, - { - "name": "Panels", - "description": "For the Panels app explicitly" - }, - { - "name": "Rating", - "description": "Responsible for providing external ratings for Series" - }, - { - "name": "Reader", - "description": "For all things regarding reading, mainly focusing on non-Book related entities" - }, - { - "name": "Search", - "description": "Responsible for the Search interface from the UI" - }, - { - "name": "Stream", - "description": "Responsible for anything that deals with Streams (SmartFilters, ExternalSource, DashboardStream, SideNavStream)" - }, - { - "name": "Tachiyomi", - "description": "All APIs are for Tachiyomi extension and app. They have hacks for our implementation and should not be used for any\r\nother purposes." - }, - { - "name": "Upload", - "description": "" - }, - { - "name": "WantToRead", - "description": "Responsible for all things Want To Read" - } - ] -} "nullable": true - } - }, - "additionalProperties": false - }, - "UserDtoICount": { - "type": "object", - "properties": { - "value": { - "$ref": "#/components/schemas/UserDto" - }, - "count": { - "type": "integer", - "format": "int64" - } - }, - "additionalProperties": false - }, - "UserPreferencesDto": { - "required": [ - "autoCloseMenu", - "backgroundColor", - "blurUnreadSummaries", - "bookReaderFontFamily", - "bookReaderFontSize", - "bookReaderImmersiveMode", - "bookReaderLayoutMode", - "bookReaderLineSpacing", - "bookReaderMargin", - "bookReaderReadingDirection", - "bookReaderTapToPaginate", - "bookReaderThemeName", - "bookReaderWritingStyle", - "collapseSeriesRelationships", - "emulateBook", - "globalPageLayoutMode", - "layoutMode", - "locale", - "noTransitions", - "pageSplitOption", - "pdfLayoutMode", - "pdfScrollMode", - "pdfSpreadMode", - "pdfTheme", - "promptForDownloadSize", - "readerMode", - "readingDirection", - "scalingOption", - "shareReviews", - "showScreenHints", - "swipeToPaginate", - "theme" - ], - "type": "object", - "properties": { - "readingDirection": { - "enum": [ - 0, - 1 - ], - "type": "integer", - "description": "Manga Reader Option: What direction should the next/prev page buttons go", - "format": "int32" - }, - "scalingOption": { - "enum": [ - 0, - 1, - 2, - 3 - ], - "type": "integer", - "description": "Manga Reader Option: How should the image be scaled to screen", - "format": "int32" - }, - "pageSplitOption": { - "enum": [ - 0, - 1, - 2, - 3 - ], - "type": "integer", - "description": "Manga Reader Option: Which side of a split image should we show first", - "format": "int32" - }, - "readerMode": { - "enum": [ - 0, - 1, - 2 - ], - "type": "integer", - "description": "Manga Reader Option: How the manga reader should perform paging or reading of the file\r\n\r\nWebtoon uses scrolling to page, LeftRight uses paging by clicking left/right side of reader, UpDown uses paging\r\nby clicking top/bottom sides of reader.\r\n", - "format": "int32" - }, - "layoutMode": { - "enum": [ - 1, - 2, - 3 - ], - "type": "integer", - "description": "Manga Reader Option: How many pages to display in the reader at once", - "format": "int32" - }, - "emulateBook": { - "type": "boolean", - "description": "Manga Reader Option: Emulate a book by applying a shadow effect on the pages" - }, - "backgroundColor": { - "minLength": 1, - "type": "string", - "description": "Manga Reader Option: Background color of the reader" - }, - "swipeToPaginate": { - "type": "boolean", - "description": "Manga Reader Option: Should swiping trigger pagination" - }, - "autoCloseMenu": { - "type": "boolean", - "description": "Manga Reader Option: Allow the menu to close after 6 seconds without interaction" - }, - "showScreenHints": { - "type": "boolean", - "description": "Manga Reader Option: Show screen hints to the user on some actions, ie) pagination direction change" - }, - "bookReaderMargin": { - "type": "integer", - "description": "Book Reader Option: Override extra Margin", - "format": "int32" - }, - "bookReaderLineSpacing": { - "type": "integer", - "description": "Book Reader Option: Override line-height", - "format": "int32" - }, - "bookReaderFontSize": { - "type": "integer", - "description": "Book Reader Option: Override font size", - "format": "int32" - }, - "bookReaderFontFamily": { - "minLength": 1, - "type": "string", - "description": "Book Reader Option: Maps to the default Kavita font-family (inherit) or an override" - }, - "bookReaderTapToPaginate": { - "type": "boolean", - "description": "Book Reader Option: Allows tapping on side of screens to paginate" - }, - "bookReaderReadingDirection": { - "enum": [ - 0, - 1 - ], - "type": "integer", - "description": "Book Reader Option: What direction should the next/prev page buttons go", - "format": "int32" - }, - "bookReaderWritingStyle": { - "enum": [ - 0, - 1 - ], - "type": "integer", - "description": "Book Reader Option: What writing style should be used, horizontal or vertical.", - "format": "int32" - }, - "theme": { - "$ref": "#/components/schemas/SiteThemeDto" - }, - "bookReaderThemeName": { - "minLength": 1, - "type": "string" - }, - "bookReaderLayoutMode": { - "enum": [ - 0, - 1, - 2 - ], - "type": "integer", - "format": "int32" - }, - "bookReaderImmersiveMode": { - "type": "boolean", - "description": "Book Reader Option: A flag that hides the menu-ing system behind a click on the screen. This should be used with tap to paginate, but the app doesn't enforce this." - }, - "globalPageLayoutMode": { - "enum": [ - 0, - 1 - ], - "type": "integer", - "description": "Global Site Option: If the UI should layout items as Cards or List items", - "format": "int32" - }, - "blurUnreadSummaries": { - "type": "boolean", - "description": "UI Site Global Setting: If unread summaries should be blurred until expanded or unless user has read it already" - }, - "promptForDownloadSize": { - "type": "boolean", - "description": "UI Site Global Setting: Should Kavita prompt user to confirm downloads that are greater than 100 MB." - }, - "noTransitions": { - "type": "boolean", - "description": "UI Site Global Setting: Should Kavita disable CSS transitions" - }, - "collapseSeriesRelationships": { - "type": "boolean", - "description": "When showing series, only parent series or series with no relationships will be returned" - }, - "shareReviews": { - "type": "boolean", - "description": "UI Site Global Setting: Should series reviews be shared with all users in the server" - }, - "locale": { - "minLength": 1, - "type": "string", - "description": "UI Site Global Setting: The language locale that should be used for the user" - }, - "pdfTheme": { - "enum": [ - 0, - 1 - ], - "type": "integer", - "description": "PDF Reader: Theme of the Reader", - "format": "int32" - }, - "pdfScrollMode": { - "enum": [ - 0, - 1, - 3 - ], - "type": "integer", - "description": "PDF Reader: Scroll mode of the reader", - "format": "int32" - }, - "pdfLayoutMode": { - "enum": [ - 0, - 2 - ], - "type": "integer", - "description": "PDF Reader: Layout Mode of the reader", - "format": "int32" - }, - "pdfSpreadMode": { - "enum": [ - 0, - 1, - 2 - ], - "type": "integer", - "description": "PDF Reader: Spread Mode of the reader", - "format": "int32" - } - }, - "additionalProperties": false - }, - "UserReadStatistics": { - "type": "object", - "properties": { - "totalPagesRead": { - "type": "integer", - "description": "Total number of pages read", - "format": "int64" - }, - "totalWordsRead": { - "type": "integer", - "description": "Total number of words read", - "format": "int64" - }, - "timeSpentReading": { - "type": "integer", - "description": "Total time spent reading based on estimates", - "format": "int64" - }, - "chaptersRead": { - "type": "integer", - "format": "int64" - }, - "lastActive": { - "type": "string", - "format": "date-time" - }, - "avgHoursPerWeekSpentReading": { - "type": "number", - "format": "double" - }, - "percentReadPerLibrary": { - "type": "array", - "items": { - "$ref": "#/components/schemas/SingleStatCount" - }, - "nullable": true - } - }, - "additionalProperties": false - }, - "UserReviewDto": { - "type": "object", - "properties": { - "tagline": { - "type": "string", - "description": "A tagline for the review", - "nullable": true - }, - "body": { - "type": "string", - "description": "The main review", - "nullable": true - }, - "bodyJustText": { - "type": "string", - "description": "The main body with just text, for review preview", - "nullable": true - }, - "seriesId": { - "type": "integer", - "description": "The series this is for", - "format": "int32" - }, - "libraryId": { - "type": "integer", - "description": "The library this series belongs in", - "format": "int32" - }, - "username": { - "type": "string", - "description": "The user who wrote this", - "nullable": true - }, - "totalVotes": { - "type": "integer", - "format": "int32" - }, - "rating": { - "type": "number", - "format": "float" - }, - "rawBody": { - "type": "string", - "nullable": true - }, - "score": { - "type": "integer", - "description": "How many upvotes this review has gotten", - "format": "int32" - }, - "siteUrl": { - "type": "string", - "description": "If External, the url of the review", - "nullable": true - }, - "isExternal": { - "type": "boolean", - "description": "Does this review come from an external Source" - }, - "provider": { - "enum": [ - 0, - 1, - 2 - ], - "type": "integer", - "description": "If this review is External, which Provider did it come from", - "format": "int32" - } - }, - "additionalProperties": false, - "description": "Represents a User Review for a given Series" - }, - "Volume": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "name": { - "type": "string", - "description": "A String representation of the volume number. Allows for floats. Can also include a range (1-2).", - "nullable": true - }, - "lookupName": { - "type": "string", - "description": "This is just the original Parsed volume number for lookups", - "nullable": true - }, - "number": { - "type": "integer", - "description": "The minimum number in the Name field in Int form", - "format": "int32", - "deprecated": true - }, - "minNumber": { - "type": "number", - "description": "The minimum number in the Name field", - "format": "float" - }, - "maxNumber": { - "type": "number", - "description": "The maximum number in the Name field (same as Minimum if Name isn't a range)", - "format": "float" - }, - "chapters": { - "type": "array", - "items": { - "$ref": "#/components/schemas/Chapter" - }, - "nullable": true - }, - "created": { - "type": "string", - "format": "date-time" - }, - "lastModified": { - "type": "string", - "format": "date-time" - }, - "createdUtc": { - "type": "string", - "format": "date-time" - }, - "lastModifiedUtc": { - "type": "string", - "format": "date-time" - }, - "coverImage": { - "type": "string", - "description": "Absolute path to the (managed) image file", - "nullable": true - }, - "pages": { - "type": "integer", - "description": "Total pages of all chapters in this volume", - "format": "int32" - }, - "wordCount": { - "type": "integer", - "description": "Total Word count of all chapters in this volume.", - "format": "int64" - }, - "minHoursToRead": { - "type": "integer", - "format": "int32" - }, - "maxHoursToRead": { - "type": "integer", - "format": "int32" - }, - "avgHoursToRead": { - "type": "integer", - "format": "int32" - }, - "series": { - "$ref": "#/components/schemas/Series" - }, - "seriesId": { - "type": "integer", - "format": "int32" - } - }, - "additionalProperties": false - }, - "VolumeDto": { - "type": "object", - "properties": { - "id": { - "type": "integer", - "format": "int32" - }, - "minNumber": { - "type": "number", - "format": "float" - }, - "maxNumber": { - "type": "number", - "format": "float" - }, - "name": { - "type": "string", - "nullable": true - }, - "number": { - "type": "integer", - "description": "This will map to MinNumber. Number was removed in v0.7.13.8/v0.7.14", - "format": "int32", - "deprecated": true - }, - "pages": { - "type": "integer", - "format": "int32" - }, - "pagesRead": { - "type": "integer", - "format": "int32" - }, - "lastModifiedUtc": { - "type": "string", - "format": "date-time" - }, - "createdUtc": { - "type": "string", - "format": "date-time" - }, - "created": { - "type": "string", - "description": "When chapter was created in local server time", - "format": "date-time" - }, - "lastModified": { - "type": "string", - "description": "When chapter was last modified in local server time", - "format": "date-time" - }, - "seriesId": { - "type": "integer", - "format": "int32" - }, - "chapters": { - "type": "array", - "items": { - "$ref": "#/components/schemas/ChapterDto" - }, - "nullable": true - }, - "minHoursToRead": { - "type": "integer", - "format": "int32" - }, - "maxHoursToRead": { - "type": "integer", - "format": "int32" - }, - "avgHoursToRead": { - "type": "integer", - "format": "int32" - } - }, - "additionalProperties": false - } - }, - "securitySchemes": { - "Bearer": { - "type": "apiKey", - "description": "Please insert JWT with Bearer into field", - "name": "Authorization", - "in": "header" - } - } - }, - "security": [ - { - "Bearer": [ ] - } - ], - "tags": [ - { - "name": "Account", - "description": "All Account matters" - }, - { - "name": "Cbl", - "description": "Responsible for the CBL import flow" - }, - { - "name": "Collection", - "description": "APIs for Collections" - }, - { - "name": "Device", - "description": "Responsible interacting and creating Devices" - }, - { - "name": "Download", - "description": "All APIs related to downloading entities from the system. Requires Download Role or Admin Role." - }, - { - "name": "Filter", - "description": "This is responsible for Filter caching" - }, - { - "name": "Image", - "description": "Responsible for servicing up images stored in Kavita for entities" - }, - { - "name": "Panels", - "description": "For the Panels app explicitly" - }, - { - "name": "Rating", - "description": "Responsible for providing external ratings for Series" - }, - { - "name": "Reader", - "description": "For all things regarding reading, mainly focusing on non-Book related entities" - }, - { - "name": "Search", - "description": "Responsible for the Search interface from the UI" - }, - { - "name": "Stream", - "description": "Responsible for anything that deals with Streams (SmartFilters, ExternalSource, DashboardStream, SideNavStream)" - }, - { - "name": "Tachiyomi", - "description": "All APIs are for Tachiyomi extension and app. They have hacks for our implementation and should not be used for any\r\nother purposes." - }, - { - "name": "Upload", - "description": "" - }, - { - "name": "WantToRead", - "description": "Responsible for all things Want To Read" - } - ] } \ No newline at end of file