diff --git a/docs/bundled.yaml b/docs/bundled.yaml new file mode 100644 index 0000000000..97778b05a0 Binary files /dev/null and b/docs/bundled.yaml differ diff --git a/docs/controllers/AuthController.yaml b/docs/controllers/AuthController.yaml new file mode 100644 index 0000000000..0b148feea8 --- /dev/null +++ b/docs/controllers/AuthController.yaml @@ -0,0 +1,70 @@ +paths: + /login: + post: + summary: Login to the server + description: Logs in a client to the server, returning information about the user and server. + operationId: login + tags: + - Auth + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + username: + $ref: '../objects/entities/User.yaml#/components/schemas/username' + password: + $ref: '../objects/entities/User.yaml#/components/schemas/password' + responses: + '200': + description: Success + content: + application/json: + schema: + type: object + properties: + user: + $ref: '../objects/entities/User.yaml#/components/schemas/user' + '401': + description: Unauthorized - Invalid username or password. + content: + text/html: + schema: + type: string + example: Unauthorized + /logout: + post: + summary: Logout from the server + description: Logs out a client from the server. If the socketId parameter is provided, the server removes the socket from the client list. + operationId: logout + tags: + - Auth + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + socketId: + $ref: '../objects/entities/User.yaml#/components/schemas/socketId' + responses: + '200': + description: Success + content: + application/json: + schema: + type: object + properties: + message: + type: string + example: Success + '401': + description: Unauthorized + content: + text/html: + schema: + type: string + example: Unauthorized diff --git a/docs/controllers/LibraryController.yaml b/docs/controllers/LibraryController.yaml index b985c05ecd..f1a8a36301 100644 --- a/docs/controllers/LibraryController.yaml +++ b/docs/controllers/LibraryController.yaml @@ -167,6 +167,7 @@ paths: parameters: - in: query name: include + description: A comma separated list of what to include with the library item. The only current option is filterdata. schema: type: string - $ref: '../schemas.yaml#/components/parameters/minified' diff --git a/docs/controllers/LibraryItemController.yaml b/docs/controllers/LibraryItemController.yaml new file mode 100644 index 0000000000..587bc1ec68 --- /dev/null +++ b/docs/controllers/LibraryItemController.yaml @@ -0,0 +1,163 @@ +components: + schemas: + parameters: + include: + in: query + name: include + description: A comma separated list of what to include with the library item. The options are progress, rssfeed, authors (for books), and downloads (for podcasts). expanded must be 1 for include to have an effect. + allowReserved: true + schema: + type: string + expanded: + in: query + name: expanded + description: Whether to return Library Item Expanded instead. 0 for false, 1 for true. + schema: + type: integer + example: 1 + episode: + in: query + name: episode + description: If requesting progress for a podcast, the episode ID to get progress for. + schema: + $ref: '../objects/mediaTypes/Podcast.yaml#/components/schemas/podcastId' + forceDirectPlay: + description: Whether to force direct play of the library item. + type: boolean + example: false + forceTranscode: + description: Whether to force transcoding of the library item. + type: boolean + example: false + supportedMimeTypes: + description: The supported mime types for the device. + type: array + items: + type: string + mediaPlayer: + description: The media player to use. + type: string + responses: + libraryItem404: + description: Not Found + content: + text/html: + schema: + type: string + description: The library item does not exist. + example: Not Found +paths: + /api/items/{id}: + parameters: + - name: id + in: path + description: The ID of the library item. + required: true + schema: + $ref: '../objects/LibraryItem.yaml#/components/schemas/libraryItemId' + get: + operationId: getLibraryItem + summary: Get a single library item by ID on server. + description: Get a single library item by ID on server. + tags: + - LibraryItem + parameters: + - $ref: '#/components/schemas/parameters/include' + - $ref: '#/components/schemas/parameters/expanded' + - $ref: '#/components/schemas/parameters/episode' + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + description: TODO + oneOf: + - $ref: '../objects/LibraryItem.yaml#/components/schemas/libraryItem' + '404': + $ref: '#/components/responses/libraryItem404' + /api/items/{id}/play: + parameters: + - name: id + in: path + description: The ID of the library item. + required: true + schema: + $ref: '../objects/LibraryItem.yaml#/components/schemas/libraryItemId' + post: + operationId: playLibraryItem + summary: Play a library item + description: Play a library item by ID. + tags: + - LibraryItem + requestBody: + required: true + content: + application/json: + schema: + properties: + deviceInfo: + $ref: '../objects/entities/Device.yaml#/components/schemas/deviceInfo' + forceDirectPlay: + $ref: '#/components/schemas/forceDirectPlay' + forceTranscode: + $ref: '#/components/schemas/forceTranscode' + supportedMimeTypes: + $ref: '#/components/schemas/supportedMimeTypes' + mediaPlayer: + $ref: '#/components/schemas/mediaPlayer' + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '../objects/entities/PlaybackSession.yaml#/components/schemas/playbackSessionExpanded' + '404': + $ref: '#/components/responses/libraryItem404' + /api/items/{id}/play/{episodeId}: + parameters: + - name: id + in: path + description: The ID of the library item. + required: true + schema: + $ref: '../objects/LibraryItem.yaml#/components/schemas/libraryItemId' + - name: episodeId + in: path + description: The ID of the episode to play. + required: true + schema: + $ref: '../objects/mediaTypes/Podcast.yaml#/components/schemas/podcastId' + post: + operationId: playLibraryItemPodcastEpisode + summary: Play a podcast episode + description: Play a podcast by library item ID and episode ID. + tags: + - LibraryItem + requestBody: + required: true + content: + application/json: + schema: + properties: + deviceInfo: + $ref: '../objects/entities/Device.yaml#/components/schemas/deviceInfo' + forceDirectPlay: + $ref: '#/components/schemas/forceDirectPlay' + forceTranscode: + $ref: '#/components/schemas/forceTranscode' + supportedMimeTypes: + $ref: '#/components/schemas/supportedMimeTypes' + mediaPlayer: + $ref: '#/components/schemas/mediaPlayer' + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '../objects/entities/PlaybackSession.yaml#/components/schemas/playbackSessionExpanded' + '404': + $ref: '#/components/responses/libraryItem404' diff --git a/docs/controllers/MeController.yaml b/docs/controllers/MeController.yaml new file mode 100644 index 0000000000..edf7efcae6 --- /dev/null +++ b/docs/controllers/MeController.yaml @@ -0,0 +1,205 @@ +components: + schemas: + totalTime: + description: The total time listened in seconds. + type: number + example: 123456 + responses: + me404: + description: Not Found + content: + html/text: + schema: + type: string + example: Not Found +paths: + /api/me: + get: + operationId: getMe + summary: Get the current user. + description: Get the current user. + tags: + - Me + responses: + '200': + description: Success + content: + application/json: + schema: + $ref: '../objects/entities/User.yaml#/components/schemas/user' + /api/me/progress/{libraryItemId}: + parameters: + - name: libraryItemId + in: path + description: The ID of the library item. + required: true + schema: + $ref: '../objects/LibraryItem.yaml#/components/schemas/libraryItemId' + get: + operationId: getProgressLibraryItem + summary: Get the user's progress for a library item. + description: Get the user's progress for a library item. + tags: + - Me + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '../objects/Media.yaml#/components/schemas/mediaProgress' + '404': + $ref: '#/components/responses/me404' + /api/me/progress/{libraryItemId}/{episodeId}: + parameters: + - name: libraryItemId + in: path + description: The ID of the library item. + required: true + schema: + $ref: '../objects/LibraryItem.yaml#/components/schemas/libraryItemId' + - name: episodeId + in: path + description: The ID of the episode to get progress for. + required: true + schema: + $ref: '../objects/mediaTypes/Podcast.yaml#/components/schemas/podcastId' + get: + operationId: getProgressPodcastEpisode + summary: Get the user's progress for a podcast episode. + description: Get the user's progress for a podcast episode. + tags: + - Me + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '../objects/Media.yaml#/components/schemas/mediaProgressPodcastEpisode' + '404': + $ref: '#/components/responses/me404' + /api/me/listening-sessions: + get: + operationId: getListeningSessions + summary: Get all listening sessions for the current user. + description: Get all listening sessions for the current user. + tags: + - Me + parameters: + - name: itemsPerPage + in: query + description: The number of items per page. + required: true + schema: + $ref: '../schemas.yaml#/components/schemas/limit' + - name: page + in: query + description: The page number (zero indexed) to return. + required: true + schema: + $ref: '../schemas.yaml#/components/schemas/page' + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + total: + $ref: '../schemas.yaml#/components/schemas/total' + numPages: + description: The number of pages. + type: integer + itemsPerPage: + $ref: '../schemas.yaml#/components/schemas/limit' + sessions: + type: array + items: + $ref: '../objects/entities/PlaybackSession.yaml#/components/schemas/playbackSession' + /api/me/items-in-progress: + get: + operationId: getItemsInProgress + summary: Get all items in progress for the current user. + description: Get all items in progress for the current user. + tags: + - Me + parameters: + - name: limit + in: query + description: The number of items to return. + required: false + schema: + $ref: '../schemas.yaml#/components/schemas/limit' + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + total: + $ref: '../schemas.yaml#/components/schemas/total' + numPages: + description: The number of pages. + type: integer + itemsPerPage: + $ref: '../schemas.yaml#/components/schemas/limit' + items: + type: array + items: + $ref: '../objects/LibraryItem.yaml#/components/schemas/libraryItemMinified' + /api/me/listening-stats: + get: + operationId: getListeningStats + summary: Get listening stats for the current user. + description: Get listening stats for the current user. + tags: + - Me + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + totalTime: + $ref: '#/components/schemas/totalTime' + items: + type: object + description: A list of library items the user has listened to, keyed by their item IDs. + additionalProperties: + type: object + properties: + id: + type: string + description: The ID of the library item. + timeListening: + type: number + description: The time (in seconds) the user listened to this library item. + mediaMetadata: + oneOf: + - $ref: '../objects/metadata/BookMetadata.yaml#/components/schemas/bookMetadata' + + days: + type: object + description: A mapping of days to total listening times. + additionalProperties: + type: number + description: The total time (in seconds) listened to on that day. + dayOfWeek: + type: object + description: A mapping of days of the week to total listening times. + additionalProperties: + type: number + description: The total time (in seconds) listened to on that day of the week. + today: + type: number + description: The time (in seconds) the user has listened to library items today. + recentSessions: + type: array + items: + $ref: '../objects/entities/PlaybackSession.yaml#/components/schemas/playbackSession' diff --git a/docs/controllers/SessionController.yaml b/docs/controllers/SessionController.yaml new file mode 100644 index 0000000000..9e43dfb629 --- /dev/null +++ b/docs/controllers/SessionController.yaml @@ -0,0 +1,278 @@ +paths: + /api/session/{id}/sync: + post: + operationId: syncOpenSession + summary: Sync an open session. + description: Sync an open session. + tags: + - Session + parameters: + - name: id + in: path + description: The ID of the session. + required: true + schema: + $ref: '../objects/entities/PlaybackSession.yaml#/components/schemas/playbackSessionId' + requestBody: + required: true + content: + application/json: + schema: + properties: + id: + $ref: '../objects/entities/PlaybackSession.yaml#/components/schemas/playbackSessionId' + currentTime: + $ref: '../schemas.yaml#/components/schemas/durationSec' + timeListened: + $ref: '../schemas.yaml#/components/schemas/durationSec' + duration: + $ref: '../schemas.yaml#/components/schemas/durationSec' + responses: + '200': + description: OK + content: + html/text: + schema: + type: string + example: OK + '404': + description: No listening session with the provided ID is open, or the session belongs to another user. + content: + html/text: + schema: + type: string + example: Not Found + '500': + description: There was an error syncing the session. + content: + html/text: + schema: + type: string + example: Internal Server Error + /api/sessions/{id}: + delete: + operationId: deleteSession + summary: Delets a listening session. + description: Deletes a listening session. + tags: + - Session + parameters: + - name: id + in: path + description: The ID of the session. + required: true + schema: + $ref: '../objects/entities/PlaybackSession.yaml#/components/schemas/playbackSessionId' + responses: + '200': + description: OK + content: + html/text: + schema: + type: string + example: OK + '403': + description: A user with delete permissions is required to delete sessions. + content: + html/text: + schema: + type: string + example: Forbidden + '404': + description: No listening session with the provided ID was found. + content: + html/text: + schema: + type: string + example: Not Found + /api/session/{id}/close: + post: + operationId: closeSession + summary: Close a listening session. + description: Close a listening session. + tags: + - Session + parameters: + - name: id + in: path + description: The ID of the session. + required: true + schema: + $ref: '../objects/entities/PlaybackSession.yaml#/components/schemas/playbackSessionId' + - name: currentTime + in: query + description: The current time of the session. + required: false + schema: + $ref: '../schemas.yaml#/components/schemas/durationSec' + - name: timeListened + in: query + description: The time listened to the session. + required: false + schema: + $ref: '../schemas.yaml#/components/schemas/durationSec' + - name: duration + in: query + description: The duration of the session. + required: false + schema: + $ref: '../schemas.yaml#/components/schemas/durationSec' + responses: + '200': + description: OK + content: + html/text: + schema: + type: string + example: OK + '404': + description: No listening session with the provided ID is open, or the session belongs to another user. + content: + html/text: + schema: + type: string + example: Not Found + /api/session/{id}: + get: + operationId: getSession + summary: Get a listening session. + description: Get a listening session. + tags: + - Session + parameters: + - name: id + in: path + description: The ID of the session. + required: true + schema: + $ref: '../objects/entities/PlaybackSession.yaml#/components/schemas/playbackSessionId' + responses: + '200': + description: OK + content: + application/json: + schema: + $ref: '../objects/entities/PlaybackSession.yaml#/components/schemas/playbackSessionExpanded' + '404': + description: No listening session with the provided ID was found. + content: + html/text: + schema: + type: string + example: Not Found + /api/sessions: + get: + operationId: getSessions + summary: Get all listening sessions. + description: Get all listening sessions. + tags: + - Session + parameters: + - name: user + in: query + description: The ID of the user to filter listening sessions by. + required: false + schema: + $ref: '../objects/entities/User.yaml#/components/schemas/userId' + - name: itemsPerPage + in: query + description: The number of items to return. + required: false + schema: + $ref: '../schemas.yaml#/components/schemas/limit' + - name: page + in: query + description: The page number (zero indexed) to return. + required: false + schema: + $ref: '../schemas.yaml#/components/schemas/page' + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + properties: + results: + type: array + items: + $ref: '../objects/LibraryItem.yaml#/components/schemas/libraryItemBase' + total: + $ref: '../schemas.yaml#/components/schemas/total' + itemsPerPage: + $ref: '../schemas.yaml#/components/schemas/limit' + numPages: + description: The number of pages. + type: integer + example: 10 + userFilter: + description: If provided, the `user` parameter. + sessions: + type: array + items: + $ref: '../objects/entities/PlaybackSession.yaml#/components/schemas/playbackSession' + '404': + description: No listening sessions were found. + content: + html/text: + schema: + type: string + example: Not Found + /api/session/local: + post: + operationId: createLocalSession + summary: Create a local session. + description: Create a local session. + tags: + - Session + requestBody: + required: true + content: + application/json: + schema: + $ref: '../objects/entities/PlaybackSession.yaml#/components/schemas/playbackSession' + responses: + '200': + description: OK + content: + html/text: + schema: + type: string + example: OK + '500': + description: There was an error creating the session. + content: + html/text: + schema: + type: string + example: Internal Server Error + /api/local/session/local-all: + post: + operationId: createLocalSessionAll + summary: Create a local session for all users. + description: Create a local session for all users. + tags: + - Session + requestBody: + required: true + content: + application/json: + schema: + items: + $ref: '../objects/entities/PlaybackSession.yaml#/components/schemas/playbackSession' + responses: + '200': + description: OK + content: + html/text: + schema: + type: string + example: OK + '500': + description: There was an error creating the session. + content: + html/text: + schema: + type: string + example: Internal Server Error diff --git a/docs/objects/Bookmarks.yaml b/docs/objects/Bookmarks.yaml new file mode 100644 index 0000000000..07fd3256ba --- /dev/null +++ b/docs/objects/Bookmarks.yaml @@ -0,0 +1,18 @@ +components: + schemas: + time: + type: integer + description: The time (in ms since POSIX epoch) when the bookmark was created. + example: 1616239000 + bookmark: + properties: + libraryItemId: + $ref: './LibraryItem.yaml#/components/schemas/libraryItemId' + title: + type: string + description: The title of the bookmark. + example: Chapter 1 + time: + $ref: '#/components/schemas/time' + createdAt: + $ref: '../schemas.yaml#/components/schemas/createdAt' diff --git a/docs/objects/LibraryItem.yaml b/docs/objects/LibraryItem.yaml index 107ba9f3f9..51eb25623b 100644 --- a/docs/objects/LibraryItem.yaml +++ b/docs/objects/LibraryItem.yaml @@ -55,6 +55,8 @@ components: type: boolean mediaType: $ref: './mediaTypes/media.yaml#/components/schemas/mediaType' + media: + $ref: './mediaTypes/Book.yaml#/components/schemas/book' libraryItemMinified: type: object description: A single item on the server, like a book or podcast. Minified media format. @@ -64,6 +66,17 @@ components: properties: media: $ref: './mediaTypes/media.yaml#/components/schemas/mediaMinified' + libraryItem: + type: object + description: A single item on the server, like a book or podcast. + allOf: + - $ref: '#/components/schemas/libraryItemBase' + - type: object + properties: + libraryFiles: + type: array + items: + $ref: './files/AudioFile.yaml#/components/schemas/libraryFile' libraryItemSequence: type: object description: A single item on the server, like a book or podcast. Includes series sequence information. diff --git a/docs/objects/Media.yaml b/docs/objects/Media.yaml new file mode 100644 index 0000000000..f1414b5939 --- /dev/null +++ b/docs/objects/Media.yaml @@ -0,0 +1,76 @@ +components: + schemas: + mediaProgressId: + type: string + description: The ID of the media progress. + example: e4bb1afb-4a4f-4dd6-8be0-e615d233185b + format: uuid + progress: + type: number + description: The user's progress in the media item. + example: 0.5 + currentTime: + type: number + description: The user's current time in the media item. + example: 0.5 + isFinished: + type: boolean + description: Whether the user has finished the media item. + example: false + hideFromContinueListening: + type: boolean + description: Whether the media item should be hidden from the continue listening section. + example: false + finishedAt: + type: integer + nullable: true + description: The time (in ms since POSIX epoch) when the media was finished. Will be null if the media has is not finished. + example: 1616239000 + mediaProgress: + type: object + properties: + id: + $ref: '#/components/schemas/mediaProgressId' + libraryItemId: + $ref: './LibraryItem.yaml#/components/schemas/libraryItemId' + duration: + $ref: '../schemas.yaml#/components/schemas/durationSec' + progress: + $ref: '#/components/schemas/progress' + currentTime: + $ref: '#/components/schemas/currentTime' + isFinished: + $ref: '#/components/schemas/isFinished' + hideFromContinueListening: + $ref: '#/components/schemas/hideFromContinueListening' + lastUpdate: + $ref: '../schemas.yaml#/components/schemas/updatedAt' + startedAt: + $ref: '../schemas.yaml#/components/schemas/createdAt' + finishedAt: + $ref: '#/components/schemas/finishedAt' + mediaProgressPodcastEpisode: + type: object + properties: + id: + $ref: '#/components/schemas/mediaProgressId' + libraryItemId: + $ref: './LibraryItem.yaml#/components/schemas/libraryItemId' + episodeId: + $ref: './mediaTypes/Podcast.yaml#/components/schemas/podcastId' + duration: + $ref: '../schemas.yaml#/components/schemas/durationSec' + progress: + $ref: '#/components/schemas/progress' + currentTime: + $ref: '#/components/schemas/currentTime' + isFinished: + $ref: '#/components/schemas/isFinished' + hideFromContinueListening: + $ref: '#/components/schemas/hideFromContinueListening' + lastUpdate: + $ref: '../schemas.yaml#/components/schemas/updatedAt' + startedAt: + $ref: '../schemas.yaml#/components/schemas/createdAt' + finishedAt: + $ref: '#/components/schemas/finishedAt' diff --git a/docs/objects/Permissions.yaml b/docs/objects/Permissions.yaml new file mode 100644 index 0000000000..8a1b91543f --- /dev/null +++ b/docs/objects/Permissions.yaml @@ -0,0 +1,55 @@ +components: + schemas: + download: + type: boolean + description: Whether the user has permission to download media. + example: true + update: + type: boolean + description: Whether the user has permission to update media. + example: true + delete: + type: boolean + description: Whether the user has permission to delete media. + example: true + upload: + type: boolean + description: Whether the user has permission to upload media. + example: true + accessAllLibraries: + type: boolean + description: Whether the user has permission to access all libraries. + example: true + accessAllTags: + type: boolean + description: Whether the user has permission to access all tags. + example: true + accessExplicitContent: + type: boolean + description: Whether the user has permission to access explicit content. + example: true + permissions: + type: object + properties: + download: + $ref: '#/components/schemas/download' + update: + $ref: '#/components/schemas/update' + delete: + $ref: '#/components/schemas/delete' + upload: + $ref: '#/components/schemas/upload' + accessAllLibraries: + $ref: '#/components/schemas/accessAllLibraries' + accessAllTags: + $ref: '#/components/schemas/accessAllTags' + accessExplicitContent: + $ref: '#/components/schemas/accessExplicitContent' + required: + - download + - update + - delete + - upload + - accessAllLibraries + - accessAllTags + - accessExplicitContent diff --git a/docs/objects/entities/Device.yaml b/docs/objects/entities/Device.yaml new file mode 100644 index 0000000000..f32af63323 --- /dev/null +++ b/docs/objects/entities/Device.yaml @@ -0,0 +1,42 @@ +components: + schemas: + deviceId: + description: The client device identifier. + type: string + example: 1 + clientVersion: + description: The client version. + type: string + example: 1.0.0 + clientName: + description: The client name. + type: string + example: 'Audible' + manufacturer: + description: The manufacturer of the device. + type: string + example: 'Apple' + model: + description: The model of the device. + type: string + example: 'iPhone 12' + sdkVersion: + description: For an Android client, the Android SDK version of the client. + type: string + example: 49 + deviceInfo: + description: The device information to send to the server. + type: object + properties: + deviceId: + $ref: '#/components/schemas/deviceId' + clientVersion: + $ref: '#/components/schemas/clientVersion' + clientName: + $ref: '#/components/schemas/clientName' + manufacturer: + $ref: '#/components/schemas/manufacturer' + model: + $ref: '#/components/schemas/model' + sdkVersion: + $ref: '#/components/schemas/sdkVersion' diff --git a/docs/objects/entities/PlaybackSession.yaml b/docs/objects/entities/PlaybackSession.yaml new file mode 100644 index 0000000000..a43d38b5b2 --- /dev/null +++ b/docs/objects/entities/PlaybackSession.yaml @@ -0,0 +1,131 @@ +components: + schemas: + playbackSessionId: + description: The playback session identifier. + type: string + format: uuid + playbackSession: + type: object + description: A playback session object. + oneOf: + - $ref: '#/components/schemas/playbackSessionBook' + - $ref: '#/components/schemas/playbackSessionPodcast' + discriminator: + propertyName: mediaType + mapping: + book: '#/components/schemas/playbackSessionBook' + podcast: '#/components/schemas/playbackSessionPodcast' + playbackSessionBase: + type: object + description: Base playback session object. + properties: + id: + $ref: '#/components/schemas/playbackSessionId' + userId: + $ref: './User.yaml#/components/schemas/userId' + libraryId: + $ref: '../Library.yaml#/components/schemas/libraryId' + libraryItemId: + $ref: '../LibraryItem.yaml#/components/schemas/libraryItemId' + mediaType: + $ref: '../mediaTypes/media.yaml#/components/schemas/mediaType' + displayTitle: + description: The display title of the media. + type: string + displayAuthor: + description: The display author of the media. + type: string + coverPath: + $ref: '../mediaTypes/Book.yaml#/components/schemas/bookCoverPath' + duration: + $ref: '../../schemas.yaml#/components/schemas/durationSec' + playMethod: + type: integer + description: The method used to play the media. 0 = Direct play, 1 = Direct Stream, 2 = Transcode, 3 = Local + mediaPlayer: + type: string + description: The media player used to play the media. + deviceInfo: + $ref: './Device.yaml#/components/schemas/deviceInfo' + serverVersion: + $ref: '../../schemas.yaml#/components/schemas/serverVersion' + date: + description: TODO + type: string + dayOfWeek: + description: TODO + type: string + timeListening: + $ref: '../../schemas.yaml#/components/schemas/durationSec' + startTime: + $ref: '../../schemas.yaml#/components/schemas/durationSec' + currentTime: + $ref: '../../schemas.yaml#/components/schemas/durationSec' + createdAt: + $ref: '../../schemas.yaml#/components/schemas/createdAt' + updatedAt: + $ref: '../../schemas.yaml#/components/schemas/updatedAt' + playbackSessionBook: + description: Book playback session schema. + allOf: + - $ref: '#/components/schemas/playbackSessionBase' + - properties: + mediaMetadata: + $ref: '../metadata/BookMetadata.yaml#/components/schemas/bookMetadata' + chapters: + description: The chapters of the media. + type: array + items: + $ref: '../metadata/BookMetadata.yaml#/components/schemas/bookChapter' + playbackSessionPodcast: + description: Podcast playback session schema. + allOf: + - $ref: '#/components/schemas/playbackSessionBase' + - properties: + mediaMetadata: + $ref: '../metadata/PodcastMetadata.yaml#/components/schemas/PodcastMetadata' + episodeId: + $ref: '../mediaTypes/Podcast.yaml#/components/schemas/podcastId' + playbackSessionExpanded: + type: object + description: A playback session object. + oneOf: + - $ref: '#/components/schemas/playbackSessionBookExpanded' + - $ref: '#/components/schemas/playbackSessionPodcastExpanded' + discriminator: + propertyName: mediaType + mapping: + book: '#/components/schemas/playbackSessionBookExpanded' + podcast: '#/components/schemas/playbackSessionPodcastExpanded' + playbackSessionBookExpanded: + description: Expanded book playback session schema. + allOf: + - $ref: '#/components/schemas/playbackSessionBook' + - properties: + audioTracks: + description: The audio tracks of the media. + type: array + items: + $ref: '../files/AudioTrack.yaml#/components/schemas/AudioTrack' + videoTrack: + description: The video track of the media. TODO + type: object + nullable: true + libraryItem: + $ref: '../LibraryItem.yaml#/components/schemas/libraryItem' + playbackSessionPodcastExpanded: + description: Expanded podcast playback session schema. + allOf: + - $ref: '#/components/schemas/playbackSessionPodcast' + - properties: + audioTracks: + description: The audio tracks of the media. + type: array + items: + $ref: '../files/AudioTrack.yaml#/components/schemas/AudioTrack' + videoTrack: + description: The video track of the media. TODO + type: object + nullable: true + libraryItem: + $ref: '../LibraryItem.yaml#/components/schemas/libraryItem' diff --git a/docs/objects/entities/User.yaml b/docs/objects/entities/User.yaml new file mode 100644 index 0000000000..6d0ca074d4 --- /dev/null +++ b/docs/objects/entities/User.yaml @@ -0,0 +1,85 @@ +components: + schemas: + username: + type: string + description: The username to log in with. + example: testuser + password: + type: string + description: The password of the user. + example: password + userId: + type: string + description: The ID of the user. + example: e4bb1afb-4a4f-4dd6-8be0-e615d233185b + format: uuid + userType: + type: string + description: The type of the user. + example: root + token: + type: string + description: The token of the user. + example: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InRlc3R1c2VyIiwiaWF0IjoxNTE2MjM5MDIyfQ.4k1jJ9 + socketId: + type: string + description: The socket ID of the user. + example: AFcTcb7xBLsSPnIzAAAV + isActive: + type: boolean + description: Whether the user is active. + example: true + isLocked: + type: boolean + description: Whether the user is locked. + example: false + lastSeen: + type: integer + description: The time (in ms since POSIX epoch) when the user was last seen. + example: 1616239000 + user: + type: object + description: A user object which includes the user's ID, username, type, token, and media progress. + properties: + id: + $ref: '#/components/schemas/userId' + username: + $ref: '#/components/schemas/username' + type: + $ref: '#/components/schemas/userType' + token: + $ref: '#/components/schemas/token' + mediaProgress: + description: The user's progress of media. + type: array + items: + $ref: '../Media.yaml#/components/schemas/mediaProgress' + seriesHideFromContinueListening: + description: The IDs of series to hide from the user's "Continue Series" shelf. + type: array + items: + $ref: '../LibraryItem.yaml#/components/schemas/libraryItemId' + bookmarks: + description: The user's bookmarks. + type: array + items: + $ref: '../Bookmarks.yaml#/components/schemas/bookmark' + lastSeen: + $ref: '#/components/schemas/lastSeen' + isActive: + $ref: '#/components/schemas/isActive' + isLocked: + $ref: '#/components/schemas/isLocked' + createdAt: + $ref: '../../schemas.yaml#/components/schemas/createdAt' + permissions: + $ref: '../Permissions.yaml#/components/schemas/permissions' + librariesAccessible: + description: The IDs of libraries the user has access to. + type: array + items: + $ref: '../Library.yaml#/components/schemas/libraryId' + itemTagsSelected: + $ref: '../../schemas.yaml#/components/schemas/tags' + + diff --git a/docs/objects/files/AudioFile.yaml b/docs/objects/files/AudioFile.yaml index 20994438fa..6ffa3affc0 100644 --- a/docs/objects/files/AudioFile.yaml +++ b/docs/objects/files/AudioFile.yaml @@ -92,3 +92,19 @@ components: description: The MIME type of the audio file. type: string example: audio/mpeg + libraryFile: + type: object + description: A library file. Includes the path and metadata of the file. + properties: + ino: + $ref: '../../schemas.yaml#/components/schemas/inode' + addedAt: + $ref: '../../schemas.yaml#/components/schemas/addedAt' + updatedAt: + $ref: '../../schemas.yaml#/components/schemas/updatedAt' + fileType: + description: The type of file. + type: string + example: audio + metadata: + $ref: '../metadata/FileMetadata.yaml#/components/schemas/fileMetadata' diff --git a/docs/objects/mediaTypes/Book.yaml b/docs/objects/mediaTypes/Book.yaml index ebe2b63d9d..c4f891fbad 100644 --- a/docs/objects/mediaTypes/Book.yaml +++ b/docs/objects/mediaTypes/Book.yaml @@ -9,6 +9,11 @@ components: type: object description: Base book schema properties: + id: + description: TODO + type: string + format: uuid + example: e4bb1afb-4a4f-4dd6-8be0-e615d233185b libraryItemId: $ref: '../LibraryItem.yaml#/components/schemas/libraryItemId' coverPath: @@ -21,6 +26,7 @@ components: $ref: '../files/AudioFile.yaml#/components/schemas/audioFile' chapters: type: array + nullable: true items: $ref: '../metadata/BookMetadata.yaml#/components/schemas/bookChapter' missingParts: @@ -68,3 +74,11 @@ components: description: The format of ebook of the book. Will be null if the book is an audiobook. type: string nullable: true + book: + allOf: + - $ref: '#/components/schemas/bookBase' + - type: object + properties: + metadata: + $ref: '../metadata/BookMetadata.yaml#/components/schemas/bookMetadata' + diff --git a/docs/objects/metadata/BookMetadata.yaml b/docs/objects/metadata/BookMetadata.yaml index faa054ac3c..0fed0a9191 100644 --- a/docs/objects/metadata/BookMetadata.yaml +++ b/docs/objects/metadata/BookMetadata.yaml @@ -24,7 +24,7 @@ components: type: array items: type: string - example: ["Fantasy", "Sci-Fi", "Nonfiction: History"] + example: ['Fantasy', 'Sci-Fi', 'Nonfiction: History'] publishedYear: description: The year the book was published. Will be null if unknown. type: string @@ -44,23 +44,9 @@ components: type: string nullable: true example: >- - The masterpiece that started Terry Goodkind's New York Times bestselling - epic Sword of Truth In the aftermath of the brutal murder of his father, - a mysterious woman, Kahlan Amnell, appears in Richard Cypher's forest - sanctuary seeking help...and more. His world, his very beliefs, are - shattered when ancient debts come due with thundering violence. In a - dark age it takes courage to live, and more than mere courage to - challenge those who hold dominion, Richard and Kahlan must take up that - challenge or become the next victims. Beyond awaits a bewitching land - where even the best of their hearts could betray them. Yet, Richard - fears nothing so much as what secrets his sword might reveal about his - own soul. Falling in love would destroy them - for reasons Richard can't - imagine and Kahlan dare not say. In their darkest hour, hunted - relentlessly, tormented by treachery and loss, Kahlan calls upon Richard - to reach beyond his sword - to invoke within himself something more - noble. Neither knows that the rules of battle have just changed...or - that their time has run out. Wizard's First Rule is the beginning. One - book. One Rule. Witness the birth of a legend. + The masterpiece that started Terry Goodkind's New York Times bestselling epic Sword of Truth In the aftermath of the brutal murder of his father, a mysterious woman, Kahlan Amnell, appears in Richard Cypher's forest sanctuary seeking help...and more. His world, his very beliefs, are shattered when ancient debts come due with thundering violence. In a dark age it takes courage to live, and more than mere courage to challenge those who hold dominion, Richard and Kahlan must take up that challenge or become the next victims. Beyond awaits a bewitching land where even the best of their hearts could betray them. Yet, Richard fears nothing so much as what secrets his sword might reveal about his own soul. Falling in love would destroy them - for reasons Richard can't imagine and Kahlan dare not say. In their darkest hour, hunted relentlessly, tormented by treachery and loss, Kahlan calls upon Richard to reach beyond his sword - to invoke within himself something more noble. Neither knows that the rules of battle have just changed...or that their time has run out. Wizard's First Rule is the beginning. One book. One Rule. Witness the birth of a legend. + + isbn: description: The ISBN of the book. Will be null if unknown. type: string @@ -78,11 +64,15 @@ components: description: Whether the book has been marked as explicit. type: boolean example: false + abridged: + description: Whether the book is abridged. + type: boolean + example: false bookMetadataMinified: type: object description: The minified metadata for a book in the database. allOf: - - $ref : '#/components/schemas/bookMetadataBase' + - $ref: '#/components/schemas/bookMetadataBase' - type: object properties: titleIgnorePrefix: @@ -107,6 +97,7 @@ components: bookChapter: type: object description: A book chapter. Includes the title and timestamps. + nullable: true properties: id: description: The ID of the book chapter. @@ -114,7 +105,7 @@ components: example: 0 start: description: When in the book (in seconds) the chapter starts. - type: integer + type: number example: 0 end: description: When in the book (in seconds) the chapter ends. @@ -124,3 +115,21 @@ components: description: The title of the chapter. type: string example: Wizards First Rule 01 Chapter 1 + bookMetadata: + allOf: + - $ref: '#/components/schemas/bookMetadataBase' + - type: object + properties: + authors: + type: array + items: + $ref: '../entities/Author.yaml#/components/schemas/authorMinified' + narrators: + type: array + items: + type: string + example: Sam Tsoutsouvas + series: + type: array + items: + $ref: '../entities/Series.yaml#/components/schemas/seriesSequence' diff --git a/docs/openapi.json b/docs/openapi.json index 9767f57960..69b538137e 100644 Binary files a/docs/openapi.json and b/docs/openapi.json differ diff --git a/docs/root.yaml b/docs/root.yaml index 4d6c055db7..384a6242c6 100644 --- a/docs/root.yaml +++ b/docs/root.yaml @@ -77,6 +77,40 @@ paths: $ref: './controllers/PodcastController.yaml#/paths/~1api~1podcasts~1{id}~1episode~1{episodeId}' /api/series/{id}: $ref: './controllers/SeriesController.yaml#/paths/~1api~1series~1{id}' + /login: + $ref: './controllers/AuthController.yaml#/paths/~1login' + /logout: + $ref: './controllers/AuthController.yaml#/paths/~1logout' + /api/items/{id}: + $ref: './controllers/LibraryItemController.yaml#/paths/~1api~1items~1{id}' + /api/items/{id}/play: + $ref: './controllers/LibraryItemController.yaml#/paths/~1api~1items~1{id}~1play' + /api/items/{id}/play/{episodeId}: + $ref: './controllers/LibraryItemController.yaml#/paths/~1api~1items~1{id}~1play~1{episodeId}' + /api/me: + $ref: './controllers/MeController.yaml#/paths/~1api~1me' + /api/me/progress/{libraryItemId}: + $ref: './controllers/MeController.yaml#/paths/~1api~1me~1progress~1{libraryItemId}' + /api/me/progress/{libraryItemId}/{episodeId}: + $ref: './controllers/MeController.yaml#/paths/~1api~1me~1progress~1{libraryItemId}~1{episodeId}' + /api/session/{id}/sync: + $ref: './controllers/SessionController.yaml#/paths/~1api~1session~1{id}~1sync' + /api/sessions/{id}: + $ref: './controllers/SessionController.yaml#/paths/~1api~1sessions~1{id}' + /api/session/{id}/close: + $ref: './controllers/SessionController.yaml#/paths/~1api~1session~1{id}~1close' + /api/session/{id}: + $ref: './controllers/SessionController.yaml#/paths/~1api~1session~1{id}' + /api/sessions: + $ref: './controllers/SessionController.yaml#/paths/~1api~1sessions' + /api/me/listening-sessions: + $ref: './controllers/MeController.yaml#/paths/~1api~1me~1listening-sessions' + /api/me/listening-stats: + $ref: './controllers/MeController.yaml#/paths/~1api~1me~1listening-stats' + /api/session/local: + $ref: './controllers/SessionController.yaml#/paths/~1api~1session~1local' + /api/local/session/local-all: + $ref: './controllers/SessionController.yaml#/paths/~1api~1local~1session~1local-all' tags: - name: Authors description: Author endpoints @@ -90,3 +124,9 @@ tags: description: Notifications endpoints - name: Podcasts description: Podcast endpoints + - name: Auth + description: Authentication endpoints + - name: Me + description: User endpoints + - name: Session + description: Session endpoints diff --git a/docs/schemas.yaml b/docs/schemas.yaml index e4e05e8090..ee97e31245 100644 --- a/docs/schemas.yaml +++ b/docs/schemas.yaml @@ -59,6 +59,9 @@ components: type: boolean example: true default: false + serverVersion: + type: string + description: The server version region: description: The region used to search. type: string diff --git a/unicode.dll b/unicode.dll new file mode 100644 index 0000000000..7ad46dd553 Binary files /dev/null and b/unicode.dll differ