Closes #38, #39 and #40; adds the client side of #41. - Every request goes to /api/v1. MusicServerClient gets a token with Settings.api_password the first time one is needed, reuses it, and on a 401 gets a new one and sends the request once more. Switching server gets a new token too. Callers never see the token. - Sync is started with POST, as MusicServer 5.0 requires. - The client has every endpoint in the server's OpenAPI spec, including statistics, soundtracks and songs by UUID, version, downloads and tokens. - tools/generate_api_types.gd generates a typed class per schema in server/openapi.json into server/generated/. Song info, statistics and versions are passed to callers as these classes. A list the server sends as null is an empty list. - FakeHttpTransport hands out tokens and answers 401 without one, so every test goes through the token flow. New tests cover the token handling, every endpoint and each generated class.
3286 lines
85 KiB
JSON
3286 lines
85 KiB
JSON
{
|
|
"components": {
|
|
"schemas": {
|
|
"APIError": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"error": {
|
|
"description": "What went wrong",
|
|
"examples": [
|
|
"Not Found"
|
|
],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"error"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"ProgressResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"progress": {
|
|
"type": "string"
|
|
},
|
|
"time_spent": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"progress",
|
|
"time_spent"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"Song": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"file_name": {
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"soundtrack_name": {
|
|
"type": "string"
|
|
},
|
|
"soundtrack_uuid": {
|
|
"type": "string"
|
|
},
|
|
"times_played": {
|
|
"format": "int32",
|
|
"type": "integer"
|
|
},
|
|
"uuid": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"uuid",
|
|
"name",
|
|
"times_played",
|
|
"soundtrack_uuid",
|
|
"soundtrack_name"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"SongInfo": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"CurrentlyPlaying": {
|
|
"type": "boolean"
|
|
},
|
|
"Song": {
|
|
"type": "string"
|
|
},
|
|
"SongNo": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"SongPlayed": {
|
|
"format": "int32",
|
|
"type": "integer"
|
|
},
|
|
"SongUuid": {
|
|
"type": "string"
|
|
},
|
|
"Soundtrack": {
|
|
"type": "string"
|
|
},
|
|
"SoundtrackPlayed": {
|
|
"format": "int32",
|
|
"type": "integer"
|
|
},
|
|
"SoundtrackUuid": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"SoundtrackUuid",
|
|
"Soundtrack",
|
|
"SoundtrackPlayed",
|
|
"SongUuid",
|
|
"Song",
|
|
"SongPlayed",
|
|
"CurrentlyPlaying",
|
|
"SongNo"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"SongInfoForStats": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"file_name": {
|
|
"type": "string"
|
|
},
|
|
"path": {
|
|
"type": "string"
|
|
},
|
|
"song_name": {
|
|
"type": "string"
|
|
},
|
|
"song_uuid": {
|
|
"type": "string"
|
|
},
|
|
"soundtrack_id": {
|
|
"format": "int32",
|
|
"type": "integer"
|
|
},
|
|
"soundtrack_name": {
|
|
"type": "string"
|
|
},
|
|
"soundtrack_uuid": {
|
|
"type": "string"
|
|
},
|
|
"times_played": {
|
|
"format": "int32",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"soundtrack_id",
|
|
"soundtrack_uuid",
|
|
"song_uuid",
|
|
"soundtrack_name",
|
|
"song_name",
|
|
"path",
|
|
"times_played"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"Soundtrack": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"added": {
|
|
"format": "date-time",
|
|
"type": "string"
|
|
},
|
|
"last_played": {
|
|
"format": "date-time",
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"times_played": {
|
|
"format": "int32",
|
|
"type": "integer"
|
|
},
|
|
"uuid": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"uuid",
|
|
"name",
|
|
"times_played",
|
|
"added"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"SoundtrackWithSongList": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"added": {
|
|
"format": "date-time",
|
|
"type": "string"
|
|
},
|
|
"last_played": {
|
|
"format": "date-time",
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"songs": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/Song"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"times_played": {
|
|
"format": "int32",
|
|
"type": "integer"
|
|
},
|
|
"uuid": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"songs",
|
|
"uuid",
|
|
"name",
|
|
"times_played",
|
|
"added"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"SoundtrackWithSongs": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"songs": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/SongInfoForStats"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"soundtrack_id": {
|
|
"format": "int32",
|
|
"type": "integer"
|
|
},
|
|
"soundtrack_last_played": {
|
|
"format": "date-time",
|
|
"type": "string"
|
|
},
|
|
"soundtrack_name": {
|
|
"type": "string"
|
|
},
|
|
"soundtrack_played": {
|
|
"format": "int32",
|
|
"type": "integer"
|
|
},
|
|
"soundtrack_uuid": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"soundtrack_id",
|
|
"soundtrack_uuid",
|
|
"soundtrack_name",
|
|
"soundtrack_played",
|
|
"songs"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"StatisticsSummary": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"avg_soundtrack_plays": {
|
|
"format": "double",
|
|
"type": "number"
|
|
},
|
|
"max_soundtrack_plays": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"min_soundtrack_plays": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"never_played_soundtracks": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"played_soundtracks": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"total_soundtrack_plays": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
},
|
|
"total_soundtracks": {
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
},
|
|
"required": [
|
|
"total_soundtracks",
|
|
"played_soundtracks",
|
|
"never_played_soundtracks",
|
|
"total_soundtrack_plays",
|
|
"avg_soundtrack_plays",
|
|
"max_soundtrack_plays",
|
|
"min_soundtrack_plays"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"StatusMessage": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"status": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"status"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"SyncResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"catched_errors": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"soundtracks_added": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"soundtracks_changed_content": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"soundtracks_changed_title": {
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
},
|
|
"type": "object"
|
|
},
|
|
"soundtracks_re_added": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"soundtracks_removed": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"total_time": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"soundtracks_added",
|
|
"soundtracks_re_added",
|
|
"soundtracks_changed_title",
|
|
"soundtracks_changed_content",
|
|
"soundtracks_removed",
|
|
"catched_errors",
|
|
"total_time"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"TokenRequest": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"client_type": {
|
|
"default": "web",
|
|
"description": "Kind of client, for example web, godot or api",
|
|
"type": "string"
|
|
},
|
|
"password": {
|
|
"description": "API password, required when the server has one configured",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"type": "object"
|
|
},
|
|
"TokenResponse": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"client_type": {
|
|
"type": "string"
|
|
},
|
|
"expires_at": {
|
|
"format": "date-time",
|
|
"type": "string"
|
|
},
|
|
"token": {
|
|
"description": "Send as Authorization: Bearer <token>",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"token",
|
|
"expires_at",
|
|
"client_type"
|
|
],
|
|
"type": "object"
|
|
},
|
|
"VersionData": {
|
|
"additionalProperties": false,
|
|
"properties": {
|
|
"changelog": {
|
|
"examples": [
|
|
[
|
|
"Initial release",
|
|
"Bug fixes"
|
|
]
|
|
],
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
},
|
|
"version": {
|
|
"examples": [
|
|
"1.0.0"
|
|
],
|
|
"type": "string"
|
|
}
|
|
},
|
|
"required": [
|
|
"version",
|
|
"changelog"
|
|
],
|
|
"type": "object"
|
|
}
|
|
},
|
|
"securitySchemes": {
|
|
"bearer": {
|
|
"description": "Token from POST /api/v1/token",
|
|
"scheme": "bearer",
|
|
"type": "http"
|
|
}
|
|
}
|
|
},
|
|
"info": {
|
|
"description": "API for the MusicServer application.\n\nGet a token with `POST /api/v1/token` and send it as `Authorization: Bearer <token>`.\n\nThe same endpoints without the `/api/v1` prefix (legacy routes) are deprecated, need no token and are not documented here. They will be removed.",
|
|
"title": "MusicServer API",
|
|
"version": "5.0.0"
|
|
},
|
|
"openapi": "3.1.0",
|
|
"paths": {
|
|
"/api/v1/character": {
|
|
"get": {
|
|
"description": "Returns a character image.",
|
|
"operationId": "get-character",
|
|
"parameters": [
|
|
{
|
|
"description": "File name of the character image, from the character list",
|
|
"explode": false,
|
|
"in": "query",
|
|
"name": "name",
|
|
"required": true,
|
|
"schema": {
|
|
"description": "File name of the character image, from the character list",
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"image/jpeg": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"image/png": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "The image"
|
|
},
|
|
"206": {
|
|
"content": {
|
|
"image/jpeg": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
},
|
|
"image/png": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "Part of the file, for a Range request"
|
|
},
|
|
"400": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Bad Request"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"404": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Not Found"
|
|
},
|
|
"422": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unprocessable Entity"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Character image",
|
|
"tags": [
|
|
"characters"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/character/list": {
|
|
"get": {
|
|
"description": "Returns the file names of all character images.",
|
|
"operationId": "list-characters",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "List characters",
|
|
"tags": [
|
|
"characters"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/download": {
|
|
"get": {
|
|
"description": "Returns the name of the latest MusicPlayer release.",
|
|
"operationId": "get-latest-client-version",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
},
|
|
"502": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Bad Gateway"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Latest client version",
|
|
"tags": [
|
|
"download"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/download/linux": {
|
|
"get": {
|
|
"description": "Redirects to the download URL of the latest MusicPlayer release for Linux.",
|
|
"operationId": "download-client-linux",
|
|
"responses": {
|
|
"302": {
|
|
"description": "Found",
|
|
"headers": {
|
|
"Location": {
|
|
"schema": {
|
|
"description": "Download URL of the asset",
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"404": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Not Found"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
},
|
|
"502": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Bad Gateway"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Download the latest client for Linux",
|
|
"tags": [
|
|
"download"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/download/list": {
|
|
"get": {
|
|
"description": "Returns the file names of the latest MusicPlayer release.",
|
|
"operationId": "list-client-assets",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
},
|
|
"502": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Bad Gateway"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Latest client assets",
|
|
"tags": [
|
|
"download"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/download/windows": {
|
|
"get": {
|
|
"description": "Redirects to the download URL of the latest MusicPlayer release for Windows.",
|
|
"operationId": "download-client-windows",
|
|
"responses": {
|
|
"302": {
|
|
"description": "Found",
|
|
"headers": {
|
|
"Location": {
|
|
"schema": {
|
|
"description": "Download URL of the asset",
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"404": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Not Found"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
},
|
|
"502": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Bad Gateway"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Download the latest client for Windows",
|
|
"tags": [
|
|
"download"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/health": {
|
|
"get": {
|
|
"description": "Returns {\"status\": \"up\"} when the server and database work, otherwise status \"down\" and an error.",
|
|
"operationId": "get-health",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
},
|
|
"type": "object"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"default": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Error"
|
|
}
|
|
},
|
|
"summary": "Health check",
|
|
"tags": [
|
|
"server"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/music": {
|
|
"get": {
|
|
"description": "Jumps to the song at the given queue position (clamped to the queue) and returns it.",
|
|
"operationId": "get-queue-song",
|
|
"parameters": [
|
|
{
|
|
"description": "Position of the song in the queue (SongNo)",
|
|
"explode": false,
|
|
"in": "query",
|
|
"name": "song",
|
|
"required": true,
|
|
"schema": {
|
|
"description": "Position of the song in the queue (SongNo)",
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"audio/mpeg": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "The song (MP3)"
|
|
},
|
|
"206": {
|
|
"content": {
|
|
"audio/mpeg": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "Part of the file, for a Range request"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"404": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Not Found"
|
|
},
|
|
"422": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unprocessable Entity"
|
|
},
|
|
"423": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Locked"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Play a song from the queue",
|
|
"tags": [
|
|
"music"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/music/addPlayed": {
|
|
"get": {
|
|
"description": "Increments the play counters of the current song and its soundtrack.",
|
|
"operationId": "mark-current-played",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"423": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Locked"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Mark the current song as played",
|
|
"tags": [
|
|
"music"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/music/addQue": {
|
|
"get": {
|
|
"description": "Adds the song returned by the last random song request to the end of the queue.",
|
|
"operationId": "add-latest-to-queue",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"423": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Locked"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Add the last random song to the queue",
|
|
"tags": [
|
|
"music"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/music/all": {
|
|
"get": {
|
|
"description": "Returns the names of all soundtracks in random order.",
|
|
"operationId": "get-soundtrack-names-random",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"423": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Locked"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Soundtrack names, random order",
|
|
"tags": [
|
|
"music"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/music/all/order": {
|
|
"get": {
|
|
"description": "Returns the names of all soundtracks in alphabetical order.",
|
|
"operationId": "get-soundtrack-names",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"423": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Locked"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Soundtrack names, sorted",
|
|
"tags": [
|
|
"music"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/music/all/random": {
|
|
"get": {
|
|
"description": "Same as /music/all.",
|
|
"operationId": "get-soundtrack-names-random-alias",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"423": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Locked"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Soundtrack names, random order",
|
|
"tags": [
|
|
"music"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/music/info": {
|
|
"get": {
|
|
"description": "Returns the current song in the queue.",
|
|
"operationId": "get-song-info",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/SongInfo"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Current song",
|
|
"tags": [
|
|
"music"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/music/list": {
|
|
"get": {
|
|
"description": "Returns all songs in the queue.",
|
|
"operationId": "get-played-songs",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/SongInfo"
|
|
},
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Queue",
|
|
"tags": [
|
|
"music"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/music/next": {
|
|
"get": {
|
|
"description": "Moves to the next song in the queue and returns it. Stays on the last song at the end.",
|
|
"operationId": "get-next-song",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"audio/mpeg": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "The song (MP3)"
|
|
},
|
|
"206": {
|
|
"content": {
|
|
"audio/mpeg": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "Part of the file, for a Range request"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"404": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Not Found"
|
|
},
|
|
"423": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Locked"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Next song in the queue",
|
|
"tags": [
|
|
"music"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/music/played": {
|
|
"put": {
|
|
"description": "Increments the play counters of the song at the given queue position. Positions outside the queue are ignored.",
|
|
"operationId": "mark-song-played",
|
|
"parameters": [
|
|
{
|
|
"description": "Position of the song in the queue (SongNo)",
|
|
"explode": false,
|
|
"in": "query",
|
|
"name": "song",
|
|
"required": true,
|
|
"schema": {
|
|
"description": "Position of the song in the queue (SongNo)",
|
|
"format": "int64",
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"422": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unprocessable Entity"
|
|
},
|
|
"423": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Locked"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Mark a queued song as played",
|
|
"tags": [
|
|
"music"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/music/previous": {
|
|
"get": {
|
|
"description": "Moves to the previous song in the queue and returns it. Stays on the first song at the start.",
|
|
"operationId": "get-previous-song",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"audio/mpeg": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "The song (MP3)"
|
|
},
|
|
"206": {
|
|
"content": {
|
|
"audio/mpeg": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "Part of the file, for a Range request"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"404": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Not Found"
|
|
},
|
|
"423": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Locked"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Previous song in the queue",
|
|
"tags": [
|
|
"music"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/music/rand": {
|
|
"get": {
|
|
"description": "Picks a random song from a random soundtrack. Add it to the queue with /music/addQue.",
|
|
"operationId": "get-random-song",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"audio/mpeg": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "The song (MP3)"
|
|
},
|
|
"206": {
|
|
"content": {
|
|
"audio/mpeg": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "Part of the file, for a Range request"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"404": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Not Found"
|
|
},
|
|
"423": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Locked"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Random song",
|
|
"tags": [
|
|
"music"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/music/rand/classic": {
|
|
"get": {
|
|
"description": "Picks a random song where every song has the same chance, regardless of soundtrack.",
|
|
"operationId": "get-random-song-classic",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"audio/mpeg": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "The song (MP3)"
|
|
},
|
|
"206": {
|
|
"content": {
|
|
"audio/mpeg": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "Part of the file, for a Range request"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"404": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Not Found"
|
|
},
|
|
"423": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Locked"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Random song, every song equal",
|
|
"tags": [
|
|
"music"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/music/rand/low": {
|
|
"get": {
|
|
"description": "Picks a random song, favouring soundtracks that have been played less than average.",
|
|
"operationId": "get-random-song-low-chance",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"audio/mpeg": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "The song (MP3)"
|
|
},
|
|
"206": {
|
|
"content": {
|
|
"audio/mpeg": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "Part of the file, for a Range request"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"404": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Not Found"
|
|
},
|
|
"423": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Locked"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Random song, favouring rarely played",
|
|
"tags": [
|
|
"music"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/music/reset": {
|
|
"get": {
|
|
"description": "Clears the queue and reloads the soundtrack list.",
|
|
"operationId": "reset-queue",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"423": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Locked"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Reset the queue",
|
|
"tags": [
|
|
"music"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/music/soundTest": {
|
|
"get": {
|
|
"description": "Returns a random song for checking the volume.",
|
|
"operationId": "get-sound-test-song",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"audio/mpeg": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "The song (MP3)"
|
|
},
|
|
"206": {
|
|
"content": {
|
|
"audio/mpeg": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "Part of the file, for a Range request"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"404": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Not Found"
|
|
},
|
|
"423": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Locked"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Sound check song",
|
|
"tags": [
|
|
"music"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/songs/{uuid}": {
|
|
"get": {
|
|
"description": "Returns information about a song.",
|
|
"operationId": "get-song",
|
|
"parameters": [
|
|
{
|
|
"description": "UUID of the soundtrack or song",
|
|
"in": "path",
|
|
"name": "uuid",
|
|
"required": true,
|
|
"schema": {
|
|
"description": "UUID of the soundtrack or song",
|
|
"format": "uuid",
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/Song"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"404": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Not Found"
|
|
},
|
|
"422": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unprocessable Entity"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Get song",
|
|
"tags": [
|
|
"library"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/songs/{uuid}/file": {
|
|
"get": {
|
|
"description": "Returns the audio file of a song.",
|
|
"operationId": "get-song-file",
|
|
"parameters": [
|
|
{
|
|
"description": "UUID of the soundtrack or song",
|
|
"in": "path",
|
|
"name": "uuid",
|
|
"required": true,
|
|
"schema": {
|
|
"description": "UUID of the soundtrack or song",
|
|
"format": "uuid",
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"audio/mpeg": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "The song (MP3)"
|
|
},
|
|
"206": {
|
|
"content": {
|
|
"audio/mpeg": {
|
|
"schema": {
|
|
"contentMediaType": "application/octet-stream",
|
|
"format": "binary",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "Part of the file, for a Range request"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"404": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Not Found"
|
|
},
|
|
"422": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unprocessable Entity"
|
|
},
|
|
"423": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Locked"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Stream song",
|
|
"tags": [
|
|
"library"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/soundtracks": {
|
|
"get": {
|
|
"description": "Returns all soundtracks, sorted by name.",
|
|
"operationId": "list-soundtracks",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/Soundtrack"
|
|
},
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "List soundtracks",
|
|
"tags": [
|
|
"library"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/soundtracks/{uuid}": {
|
|
"get": {
|
|
"description": "Returns a soundtrack with its songs, sorted by name.",
|
|
"operationId": "get-soundtrack",
|
|
"parameters": [
|
|
{
|
|
"description": "UUID of the soundtrack or song",
|
|
"in": "path",
|
|
"name": "uuid",
|
|
"required": true,
|
|
"schema": {
|
|
"description": "UUID of the soundtrack or song",
|
|
"format": "uuid",
|
|
"type": "string"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/SoundtrackWithSongList"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"404": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Not Found"
|
|
},
|
|
"422": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unprocessable Entity"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Get soundtrack",
|
|
"tags": [
|
|
"library"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/statistics/songs/least-played": {
|
|
"get": {
|
|
"description": "Returns the least played songs with their soundtrack.",
|
|
"operationId": "get-least-played-songs",
|
|
"parameters": [
|
|
{
|
|
"description": "Number of results. Values above 100 are capped to 100.",
|
|
"explode": false,
|
|
"in": "query",
|
|
"name": "limit",
|
|
"schema": {
|
|
"default": 10,
|
|
"description": "Number of results. Values above 100 are capped to 100.",
|
|
"format": "int64",
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/SongInfoForStats"
|
|
},
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"422": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unprocessable Entity"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Least played songs",
|
|
"tags": [
|
|
"statistics"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/statistics/songs/most-played": {
|
|
"get": {
|
|
"description": "Returns the most played songs with their soundtrack.",
|
|
"operationId": "get-most-played-songs",
|
|
"parameters": [
|
|
{
|
|
"description": "Number of results. Values above 100 are capped to 100.",
|
|
"explode": false,
|
|
"in": "query",
|
|
"name": "limit",
|
|
"schema": {
|
|
"default": 10,
|
|
"description": "Number of results. Values above 100 are capped to 100.",
|
|
"format": "int64",
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/SongInfoForStats"
|
|
},
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"422": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unprocessable Entity"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Most played songs",
|
|
"tags": [
|
|
"statistics"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/statistics/soundtracks/last-played": {
|
|
"get": {
|
|
"description": "Returns the most recently played soundtracks with their songs.",
|
|
"operationId": "get-last-played-soundtracks",
|
|
"parameters": [
|
|
{
|
|
"description": "Number of results. Values above 100 are capped to 100.",
|
|
"explode": false,
|
|
"in": "query",
|
|
"name": "limit",
|
|
"schema": {
|
|
"default": 10,
|
|
"description": "Number of results. Values above 100 are capped to 100.",
|
|
"format": "int64",
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/SoundtrackWithSongs"
|
|
},
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"422": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unprocessable Entity"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Recently played soundtracks",
|
|
"tags": [
|
|
"statistics"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/statistics/soundtracks/least-played": {
|
|
"get": {
|
|
"description": "Returns the least played soundtracks with their songs.",
|
|
"operationId": "get-least-played-soundtracks",
|
|
"parameters": [
|
|
{
|
|
"description": "Number of results. Values above 100 are capped to 100.",
|
|
"explode": false,
|
|
"in": "query",
|
|
"name": "limit",
|
|
"schema": {
|
|
"default": 10,
|
|
"description": "Number of results. Values above 100 are capped to 100.",
|
|
"format": "int64",
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/SoundtrackWithSongs"
|
|
},
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"422": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unprocessable Entity"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Least played soundtracks",
|
|
"tags": [
|
|
"statistics"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/statistics/soundtracks/most-played": {
|
|
"get": {
|
|
"description": "Returns the most played soundtracks with their songs.",
|
|
"operationId": "get-most-played-soundtracks",
|
|
"parameters": [
|
|
{
|
|
"description": "Number of results. Values above 100 are capped to 100.",
|
|
"explode": false,
|
|
"in": "query",
|
|
"name": "limit",
|
|
"schema": {
|
|
"default": 10,
|
|
"description": "Number of results. Values above 100 are capped to 100.",
|
|
"format": "int64",
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/SoundtrackWithSongs"
|
|
},
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"422": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unprocessable Entity"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Most played soundtracks",
|
|
"tags": [
|
|
"statistics"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/statistics/soundtracks/never-played": {
|
|
"get": {
|
|
"description": "Returns all soundtracks that have never been played, with their songs.",
|
|
"operationId": "get-never-played-soundtracks",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/SoundtrackWithSongs"
|
|
},
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Never played soundtracks",
|
|
"tags": [
|
|
"statistics"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/statistics/soundtracks/oldest-played": {
|
|
"get": {
|
|
"description": "Returns the soundtracks played longest ago (played at least once) with their songs.",
|
|
"operationId": "get-oldest-played-soundtracks",
|
|
"parameters": [
|
|
{
|
|
"description": "Number of results. Values above 100 are capped to 100.",
|
|
"explode": false,
|
|
"in": "query",
|
|
"name": "limit",
|
|
"schema": {
|
|
"default": 10,
|
|
"description": "Number of results. Values above 100 are capped to 100.",
|
|
"format": "int64",
|
|
"minimum": 1,
|
|
"type": "integer"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/SoundtrackWithSongs"
|
|
},
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"422": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unprocessable Entity"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Least recently played soundtracks",
|
|
"tags": [
|
|
"statistics"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/statistics/summary": {
|
|
"get": {
|
|
"description": "Returns overall play statistics.",
|
|
"operationId": "get-statistics-summary",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/StatisticsSummary"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Statistics summary",
|
|
"tags": [
|
|
"statistics"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/sync": {
|
|
"post": {
|
|
"description": "Starts syncing the music folder in the background, skipping soundtracks that have not changed. Poll /sync/progress for the result.",
|
|
"operationId": "start-sync",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"423": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Locked"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Sync changed soundtracks",
|
|
"tags": [
|
|
"sync"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/sync/full": {
|
|
"post": {
|
|
"description": "Starts a full sync in the background that re-reads every soundtrack and removes songs whose files are gone. Poll /sync/progress for the result.",
|
|
"operationId": "start-full-sync",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"423": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Locked"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Sync all soundtracks",
|
|
"tags": [
|
|
"sync"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/sync/progress": {
|
|
"get": {
|
|
"description": "While a sync is running, returns its progress. Otherwise returns the result of the last sync.",
|
|
"operationId": "get-sync-progress",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"oneOf": [
|
|
{
|
|
"$ref": "#/components/schemas/ProgressResponse"
|
|
},
|
|
{
|
|
"$ref": "#/components/schemas/SyncResponse"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
},
|
|
"description": "Progress of the running sync, or the result of the last sync"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Sync progress or result",
|
|
"tags": [
|
|
"sync"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/token": {
|
|
"delete": {
|
|
"description": "Deletes the token used for this request.",
|
|
"operationId": "delete-token",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/StatusMessage"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Invalidate session token",
|
|
"tags": [
|
|
"auth"
|
|
]
|
|
},
|
|
"post": {
|
|
"description": "Returns a token for the other /api/v1 endpoints, valid for 24 hours. Requires the API password when the server has one. Limited to 10 requests per minute per client.",
|
|
"operationId": "create-token",
|
|
"requestBody": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/TokenRequest"
|
|
}
|
|
}
|
|
},
|
|
"required": true
|
|
},
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/TokenResponse"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"422": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unprocessable Entity"
|
|
},
|
|
"429": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Too Many Requests"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"summary": "Create session token",
|
|
"tags": [
|
|
"auth"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/token/cleanup": {
|
|
"post": {
|
|
"description": "Deletes all expired session tokens.",
|
|
"operationId": "cleanup-tokens",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/StatusMessage"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Remove expired tokens",
|
|
"tags": [
|
|
"auth"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/version": {
|
|
"get": {
|
|
"description": "Returns the server version and its changelog.",
|
|
"operationId": "get-version",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/VersionData"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Latest server version",
|
|
"tags": [
|
|
"server"
|
|
]
|
|
}
|
|
},
|
|
"/api/v1/version/history": {
|
|
"get": {
|
|
"description": "Returns all server versions with their changelogs, newest first.",
|
|
"operationId": "get-version-history",
|
|
"responses": {
|
|
"200": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"items": {
|
|
"$ref": "#/components/schemas/VersionData"
|
|
},
|
|
"type": "array"
|
|
}
|
|
}
|
|
},
|
|
"description": "OK"
|
|
},
|
|
"401": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Unauthorized"
|
|
},
|
|
"500": {
|
|
"content": {
|
|
"application/json": {
|
|
"schema": {
|
|
"$ref": "#/components/schemas/APIError"
|
|
}
|
|
}
|
|
},
|
|
"description": "Internal Server Error"
|
|
}
|
|
},
|
|
"security": [
|
|
{
|
|
"bearer": []
|
|
}
|
|
],
|
|
"summary": "Version history",
|
|
"tags": [
|
|
"server"
|
|
]
|
|
}
|
|
}
|
|
}
|
|
}
|