- New /api/v1 endpoints: GET /soundtracks, /soundtracks/{uuid},
/songs/{uuid} and /songs/{uuid}/file (streams the song, Range support,
locked during sync)
- UUIDs added to every response with soundtracks or songs: queue info and
list (SoundtrackUuid, SongUuid) and statistics (soundtrack_uuid,
song_uuid). Existing fields stay for backward compatibility
- Play counts and broken-song removal use song UUIDs instead of
soundtrack ID + song name, so songs with the same name are counted
separately
- Statistics return an empty song list for soundtracks without songs
instead of a single empty entry
- The legacy .id file cleanup stays until Phase 4 (#31)
Closes #29
1781 lines
58 KiB
Go
1781 lines
58 KiB
Go
// Package docs Code generated by swaggo/swag. DO NOT EDIT
|
|
package docs
|
|
|
|
import "github.com/swaggo/swag"
|
|
|
|
const docTemplate = `{
|
|
"schemes": {{ marshal .Schemes }},
|
|
"swagger": "2.0",
|
|
"info": {
|
|
"description": "{{escape .Description}}",
|
|
"title": "{{.Title}}",
|
|
"termsOfService": "http://sanplex.xyz/terms/",
|
|
"contact": {
|
|
"name": "Sebastian Olsson",
|
|
"email": "zarnor91@gmail.com"
|
|
},
|
|
"license": {
|
|
"name": "MIT",
|
|
"url": "http://opensource.org/licenses/MIT"
|
|
},
|
|
"version": "{{.Version}}"
|
|
},
|
|
"host": "{{.Host}}",
|
|
"basePath": "{{.BasePath}}",
|
|
"paths": {
|
|
"/api/v1/songs/{uuid}": {
|
|
"get": {
|
|
"description": "Returns information about a song",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"library"
|
|
],
|
|
"summary": "Get song",
|
|
"parameters": [
|
|
{
|
|
"type": "string",
|
|
"description": "Song UUID",
|
|
"name": "uuid",
|
|
"in": "path",
|
|
"required": true
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"$ref": "#/definitions/backend.Song"
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "invalid uuid",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "not found",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/songs/{uuid}/file": {
|
|
"get": {
|
|
"description": "Returns the audio file of a song. Supports Range requests.",
|
|
"produces": [
|
|
"audio/mpeg"
|
|
],
|
|
"tags": [
|
|
"library"
|
|
],
|
|
"summary": "Stream song",
|
|
"parameters": [
|
|
{
|
|
"type": "string",
|
|
"description": "Song UUID",
|
|
"name": "uuid",
|
|
"in": "path",
|
|
"required": true
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "file"
|
|
}
|
|
},
|
|
"206": {
|
|
"description": "Partial Content",
|
|
"schema": {
|
|
"type": "file"
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "invalid uuid",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "not found",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"423": {
|
|
"description": "Syncing is in progress",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/soundtracks": {
|
|
"get": {
|
|
"description": "Returns all soundtracks with their UUIDs, sorted by name",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"library"
|
|
],
|
|
"summary": "List soundtracks",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/backend.Soundtrack"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/soundtracks/{uuid}": {
|
|
"get": {
|
|
"description": "Returns a soundtrack with its songs",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"library"
|
|
],
|
|
"summary": "Get soundtrack",
|
|
"parameters": [
|
|
{
|
|
"type": "string",
|
|
"description": "Soundtrack UUID",
|
|
"name": "uuid",
|
|
"in": "path",
|
|
"required": true
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"$ref": "#/definitions/backend.SoundtrackWithSongList"
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "invalid uuid",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "not found",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/statistics/songs/least-played": {
|
|
"get": {
|
|
"description": "Returns the top N least played songs with their soundtrack info",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"statistics"
|
|
],
|
|
"summary": "Get least played songs",
|
|
"parameters": [
|
|
{
|
|
"type": "integer",
|
|
"description": "Number of results (default: 10, max: 100)",
|
|
"name": "limit",
|
|
"in": "query"
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/backend.SongInfoForStats"
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Bad Request",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/statistics/songs/most-played": {
|
|
"get": {
|
|
"description": "Returns the top N most played songs with their soundtrack info",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"statistics"
|
|
],
|
|
"summary": "Get most played songs",
|
|
"parameters": [
|
|
{
|
|
"type": "integer",
|
|
"description": "Number of results (default: 10, max: 100)",
|
|
"name": "limit",
|
|
"in": "query"
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/backend.SongInfoForStats"
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Bad Request",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/statistics/soundtracks/last-played": {
|
|
"get": {
|
|
"description": "Returns the most recently played soundtracks with their songs",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"statistics"
|
|
],
|
|
"summary": "Get last played soundtracks",
|
|
"parameters": [
|
|
{
|
|
"type": "integer",
|
|
"description": "Number of results (default: 10, max: 100)",
|
|
"name": "limit",
|
|
"in": "query"
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/backend.SoundtrackWithSongs"
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Bad Request",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/statistics/soundtracks/least-played": {
|
|
"get": {
|
|
"description": "Returns the top N least played soundtracks with their songs",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"statistics"
|
|
],
|
|
"summary": "Get least played soundtracks",
|
|
"parameters": [
|
|
{
|
|
"type": "integer",
|
|
"description": "Number of results (default: 10, max: 100)",
|
|
"name": "limit",
|
|
"in": "query"
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/backend.SoundtrackWithSongs"
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Bad Request",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/statistics/soundtracks/most-played": {
|
|
"get": {
|
|
"description": "Returns the top N most played soundtracks with their songs",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"statistics"
|
|
],
|
|
"summary": "Get most played soundtracks",
|
|
"parameters": [
|
|
{
|
|
"type": "integer",
|
|
"description": "Number of results (default: 10, max: 100)",
|
|
"name": "limit",
|
|
"in": "query"
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/backend.SoundtrackWithSongs"
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Bad Request",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/statistics/soundtracks/never-played": {
|
|
"get": {
|
|
"description": "Returns all soundtracks that have never been played",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"statistics"
|
|
],
|
|
"summary": "Get never played soundtracks",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/backend.SoundtrackWithSongs"
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/statistics/soundtracks/oldest-played": {
|
|
"get": {
|
|
"description": "Returns the least recently played soundtracks with their songs",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"statistics"
|
|
],
|
|
"summary": "Get oldest played soundtracks",
|
|
"parameters": [
|
|
{
|
|
"type": "integer",
|
|
"description": "Number of results (default: 10, max: 100)",
|
|
"name": "limit",
|
|
"in": "query"
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/backend.SoundtrackWithSongs"
|
|
}
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Bad Request",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/statistics/summary": {
|
|
"get": {
|
|
"description": "Returns overall play statistics",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"statistics"
|
|
],
|
|
"summary": "Get statistics summary",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"$ref": "#/definitions/backend.StatisticsSummary"
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/token": {
|
|
"post": {
|
|
"description": "Returns a new session token for API access. Requires the API password when one is configured.",
|
|
"consumes": [
|
|
"application/json"
|
|
],
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"auth"
|
|
],
|
|
"summary": "Create session token",
|
|
"parameters": [
|
|
{
|
|
"description": "Password and client type",
|
|
"name": "request",
|
|
"in": "body",
|
|
"required": true,
|
|
"schema": {
|
|
"$ref": "#/definitions/server.TokenRequest"
|
|
}
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"$ref": "#/definitions/server.TokenResponse"
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "Bad Request",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthorized",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"429": {
|
|
"description": "Too Many Requests",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"delete": {
|
|
"description": "Deletes the current session token",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"auth"
|
|
],
|
|
"summary": "Invalidate session token",
|
|
"parameters": [
|
|
{
|
|
"type": "string",
|
|
"description": "Bearer token",
|
|
"name": "Authorization",
|
|
"in": "header",
|
|
"required": true
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthorized",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/api/v1/token/cleanup": {
|
|
"post": {
|
|
"description": "Removes all expired session tokens from the database",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"auth"
|
|
],
|
|
"summary": "Cleanup expired sessions",
|
|
"parameters": [
|
|
{
|
|
"type": "string",
|
|
"description": "Bearer token",
|
|
"name": "Authorization",
|
|
"in": "header",
|
|
"required": true
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"401": {
|
|
"description": "Unauthorized",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"500": {
|
|
"description": "Internal Server Error",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/character": {
|
|
"get": {
|
|
"description": "Returns the image for a specific character",
|
|
"produces": [
|
|
"image/png",
|
|
"image/jpeg"
|
|
],
|
|
"tags": [
|
|
"characters"
|
|
],
|
|
"summary": "Get character image",
|
|
"parameters": [
|
|
{
|
|
"type": "string",
|
|
"description": "Character file name",
|
|
"name": "name",
|
|
"in": "query",
|
|
"required": true
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "file"
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "invalid name",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "not found",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/characters": {
|
|
"get": {
|
|
"description": "Returns a list of all available characters",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"characters"
|
|
],
|
|
"summary": "Get list of characters",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/download": {
|
|
"get": {
|
|
"description": "Returns the latest version of the client application",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"download"
|
|
],
|
|
"summary": "Check for latest version",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"502": {
|
|
"description": "upstream service unavailable",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/download/linux": {
|
|
"get": {
|
|
"description": "Redirects to download the latest Linux version",
|
|
"tags": [
|
|
"download"
|
|
],
|
|
"summary": "Download latest Linux version",
|
|
"responses": {
|
|
"302": {
|
|
"description": "Found",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "not found",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"502": {
|
|
"description": "upstream service unavailable",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/download/list": {
|
|
"get": {
|
|
"description": "Lists all assets available for the latest version",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"download"
|
|
],
|
|
"summary": "List assets of latest version",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"502": {
|
|
"description": "upstream service unavailable",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/download/windows": {
|
|
"get": {
|
|
"description": "Redirects to download the latest Windows version",
|
|
"tags": [
|
|
"download"
|
|
],
|
|
"summary": "Download latest Windows version",
|
|
"responses": {
|
|
"302": {
|
|
"description": "Found",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "not found",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"502": {
|
|
"description": "upstream service unavailable",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/health": {
|
|
"get": {
|
|
"description": "Returns the health status of the server",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"health"
|
|
],
|
|
"summary": "Check server health",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/music": {
|
|
"get": {
|
|
"description": "Returns the song at the given position in the queue",
|
|
"produces": [
|
|
"audio/mpeg"
|
|
],
|
|
"tags": [
|
|
"music"
|
|
],
|
|
"summary": "Get a specific song",
|
|
"parameters": [
|
|
{
|
|
"type": "integer",
|
|
"description": "Song number in the queue",
|
|
"name": "song",
|
|
"in": "query",
|
|
"required": true
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "file"
|
|
}
|
|
},
|
|
"206": {
|
|
"description": "Partial Content",
|
|
"schema": {
|
|
"type": "file"
|
|
}
|
|
},
|
|
"400": {
|
|
"description": "song must be a number",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not Found",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"423": {
|
|
"description": "Syncing is in progress",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/music/addPlayed": {
|
|
"get": {
|
|
"description": "Marks the current song as played",
|
|
"tags": [
|
|
"music"
|
|
],
|
|
"summary": "Add latest to played",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK"
|
|
},
|
|
"423": {
|
|
"description": "Syncing is in progress",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/music/addQue": {
|
|
"get": {
|
|
"description": "Adds the latest song to the queue",
|
|
"tags": [
|
|
"music"
|
|
],
|
|
"summary": "Add latest to queue",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK"
|
|
},
|
|
"423": {
|
|
"description": "Syncing is in progress",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/music/all/order": {
|
|
"get": {
|
|
"description": "Returns a list of all soundtracks in order",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"music"
|
|
],
|
|
"summary": "Get all soundtracks",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"423": {
|
|
"description": "Syncing is in progress",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/music/all/random": {
|
|
"get": {
|
|
"description": "Returns a list of all soundtracks in random order",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"music"
|
|
],
|
|
"summary": "Get all soundtracks random",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"423": {
|
|
"description": "Syncing is in progress",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/music/info": {
|
|
"get": {
|
|
"description": "Returns information about the current song",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"music"
|
|
],
|
|
"summary": "Get current song info",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"$ref": "#/definitions/backend.SongInfo"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/music/list": {
|
|
"get": {
|
|
"description": "Returns a list of played songs",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"music"
|
|
],
|
|
"summary": "Get played songs list",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/backend.SongInfo"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/music/next": {
|
|
"get": {
|
|
"description": "Returns the next song in the queue",
|
|
"produces": [
|
|
"audio/mpeg"
|
|
],
|
|
"tags": [
|
|
"music"
|
|
],
|
|
"summary": "Get next song",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "file"
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not Found",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"423": {
|
|
"description": "Syncing is in progress",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/music/played": {
|
|
"put": {
|
|
"description": "Marks the song at the given queue position as played",
|
|
"tags": [
|
|
"music"
|
|
],
|
|
"summary": "Mark song as played",
|
|
"parameters": [
|
|
{
|
|
"type": "integer",
|
|
"description": "Song number in the queue",
|
|
"name": "song",
|
|
"in": "query",
|
|
"required": true
|
|
}
|
|
],
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK"
|
|
},
|
|
"400": {
|
|
"description": "Bad Request",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"423": {
|
|
"description": "Syncing is in progress",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/music/previous": {
|
|
"get": {
|
|
"description": "Returns the previous song in the queue",
|
|
"produces": [
|
|
"audio/mpeg"
|
|
],
|
|
"tags": [
|
|
"music"
|
|
],
|
|
"summary": "Get previous song",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "file"
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not Found",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"423": {
|
|
"description": "Syncing is in progress",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/music/rand": {
|
|
"get": {
|
|
"description": "Returns a random song",
|
|
"produces": [
|
|
"audio/mpeg"
|
|
],
|
|
"tags": [
|
|
"music"
|
|
],
|
|
"summary": "Get random song",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "file"
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not Found",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"423": {
|
|
"description": "Syncing is in progress",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/music/rand/classic": {
|
|
"get": {
|
|
"description": "Returns a random song where every song has the same chance",
|
|
"produces": [
|
|
"audio/mpeg"
|
|
],
|
|
"tags": [
|
|
"music"
|
|
],
|
|
"summary": "Get random classic song",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "file"
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not Found",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"423": {
|
|
"description": "Syncing is in progress",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/music/rand/low": {
|
|
"get": {
|
|
"description": "Returns a random song, favouring soundtracks that have been played less",
|
|
"produces": [
|
|
"audio/mpeg"
|
|
],
|
|
"tags": [
|
|
"music"
|
|
],
|
|
"summary": "Get random song with low chance",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "file"
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not Found",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"423": {
|
|
"description": "Syncing is in progress",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/music/reset": {
|
|
"get": {
|
|
"description": "Resets the music state",
|
|
"tags": [
|
|
"music"
|
|
],
|
|
"summary": "Reset music state",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK"
|
|
},
|
|
"423": {
|
|
"description": "Syncing is in progress",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/music/soundTest": {
|
|
"get": {
|
|
"description": "Returns the sound check song",
|
|
"produces": [
|
|
"audio/mpeg"
|
|
],
|
|
"tags": [
|
|
"music"
|
|
],
|
|
"summary": "Get sound check song",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "file"
|
|
}
|
|
},
|
|
"404": {
|
|
"description": "Not Found",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"423": {
|
|
"description": "Syncing is in progress",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/sync": {
|
|
"post": {
|
|
"description": "Starts syncing soundtracks that have changed",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"sync"
|
|
],
|
|
"summary": "Sync soundtracks with only changes",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Start syncing soundtracks",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"423": {
|
|
"description": "Syncing is in progress",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/sync/full": {
|
|
"post": {
|
|
"description": "Starts a full sync of all soundtracks",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"sync"
|
|
],
|
|
"summary": "Sync all soundtracks fully",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Start syncing soundtracks full",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"423": {
|
|
"description": "Syncing is in progress",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/sync/progress": {
|
|
"get": {
|
|
"description": "Returns the progress of the running sync, or the result of the last sync",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"sync"
|
|
],
|
|
"summary": "Get sync progress",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"$ref": "#/definitions/backend.SyncResponse"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/sync/reset": {
|
|
"post": {
|
|
"description": "Resets the soundtracks database by deleting all soundtracks and songs",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"sync"
|
|
],
|
|
"summary": "Reset soundtracks database",
|
|
"responses": {
|
|
"200": {
|
|
"description": "Soundtracks and songs are deleted from the database",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"423": {
|
|
"description": "Syncing is in progress",
|
|
"schema": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/version": {
|
|
"get": {
|
|
"description": "get latest version info",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"version"
|
|
],
|
|
"summary": "Getting the latest version of the backend",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"$ref": "#/definitions/backend.VersionData"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"/version/history": {
|
|
"get": {
|
|
"description": "get version history",
|
|
"produces": [
|
|
"application/json"
|
|
],
|
|
"tags": [
|
|
"version"
|
|
],
|
|
"summary": "Getting the version history of the backend",
|
|
"responses": {
|
|
"200": {
|
|
"description": "OK",
|
|
"schema": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/backend.VersionData"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"definitions": {
|
|
"backend.Song": {
|
|
"type": "object",
|
|
"properties": {
|
|
"file_name": {
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"soundtrack_name": {
|
|
"type": "string"
|
|
},
|
|
"soundtrack_uuid": {
|
|
"type": "string"
|
|
},
|
|
"times_played": {
|
|
"type": "integer"
|
|
},
|
|
"uuid": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"backend.SongInfo": {
|
|
"type": "object",
|
|
"properties": {
|
|
"CurrentlyPlaying": {
|
|
"type": "boolean"
|
|
},
|
|
"Song": {
|
|
"type": "string"
|
|
},
|
|
"SongNo": {
|
|
"type": "integer"
|
|
},
|
|
"SongPlayed": {
|
|
"type": "integer"
|
|
},
|
|
"SongUuid": {
|
|
"type": "string"
|
|
},
|
|
"Soundtrack": {
|
|
"type": "string"
|
|
},
|
|
"SoundtrackPlayed": {
|
|
"type": "integer"
|
|
},
|
|
"SoundtrackUuid": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"backend.SongInfoForStats": {
|
|
"type": "object",
|
|
"properties": {
|
|
"file_name": {
|
|
"type": "string"
|
|
},
|
|
"path": {
|
|
"type": "string"
|
|
},
|
|
"song_name": {
|
|
"type": "string"
|
|
},
|
|
"song_uuid": {
|
|
"type": "string"
|
|
},
|
|
"soundtrack_id": {
|
|
"type": "integer"
|
|
},
|
|
"soundtrack_name": {
|
|
"type": "string"
|
|
},
|
|
"soundtrack_uuid": {
|
|
"type": "string"
|
|
},
|
|
"times_played": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
},
|
|
"backend.Soundtrack": {
|
|
"type": "object",
|
|
"properties": {
|
|
"added": {
|
|
"type": "string"
|
|
},
|
|
"last_played": {
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"times_played": {
|
|
"type": "integer"
|
|
},
|
|
"uuid": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"backend.SoundtrackWithSongList": {
|
|
"type": "object",
|
|
"properties": {
|
|
"added": {
|
|
"type": "string"
|
|
},
|
|
"last_played": {
|
|
"type": "string"
|
|
},
|
|
"name": {
|
|
"type": "string"
|
|
},
|
|
"songs": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/backend.Song"
|
|
}
|
|
},
|
|
"times_played": {
|
|
"type": "integer"
|
|
},
|
|
"uuid": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"backend.SoundtrackWithSongs": {
|
|
"type": "object",
|
|
"properties": {
|
|
"songs": {
|
|
"type": "array",
|
|
"items": {
|
|
"$ref": "#/definitions/backend.SongInfoForStats"
|
|
}
|
|
},
|
|
"soundtrack_id": {
|
|
"type": "integer"
|
|
},
|
|
"soundtrack_last_played": {
|
|
"type": "string"
|
|
},
|
|
"soundtrack_name": {
|
|
"type": "string"
|
|
},
|
|
"soundtrack_played": {
|
|
"type": "integer"
|
|
},
|
|
"soundtrack_uuid": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"backend.StatisticsSummary": {
|
|
"type": "object",
|
|
"properties": {
|
|
"avg_soundtrack_plays": {
|
|
"type": "number"
|
|
},
|
|
"max_soundtrack_plays": {
|
|
"type": "integer"
|
|
},
|
|
"min_soundtrack_plays": {
|
|
"type": "integer"
|
|
},
|
|
"never_played_soundtracks": {
|
|
"type": "integer"
|
|
},
|
|
"played_soundtracks": {
|
|
"type": "integer"
|
|
},
|
|
"total_soundtrack_plays": {
|
|
"type": "integer"
|
|
},
|
|
"total_soundtracks": {
|
|
"type": "integer"
|
|
}
|
|
}
|
|
},
|
|
"backend.SyncResponse": {
|
|
"type": "object",
|
|
"properties": {
|
|
"catched_errors": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"soundtracks_added": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"soundtracks_changed_content": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"soundtracks_changed_title": {
|
|
"type": "object",
|
|
"additionalProperties": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"soundtracks_re_added": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"soundtracks_removed": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
}
|
|
},
|
|
"total_time": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"backend.VersionData": {
|
|
"type": "object",
|
|
"properties": {
|
|
"changelog": {
|
|
"type": "array",
|
|
"items": {
|
|
"type": "string"
|
|
},
|
|
"example": [
|
|
"[\"Initial release\"",
|
|
"\"Bug fixes\"]"
|
|
]
|
|
},
|
|
"version": {
|
|
"type": "string",
|
|
"example": "1.0.0"
|
|
}
|
|
}
|
|
},
|
|
"server.TokenRequest": {
|
|
"type": "object",
|
|
"properties": {
|
|
"client_type": {
|
|
"description": "Optional: \"web\", \"mobile\", \"api\"",
|
|
"type": "string"
|
|
},
|
|
"password": {
|
|
"description": "API password, required when API_PASSWORD is set",
|
|
"type": "string"
|
|
}
|
|
}
|
|
},
|
|
"server.TokenResponse": {
|
|
"type": "object",
|
|
"properties": {
|
|
"client_type": {
|
|
"type": "string"
|
|
},
|
|
"expires_at": {
|
|
"type": "string"
|
|
},
|
|
"token": {
|
|
"type": "string"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}`
|
|
|
|
// SwaggerInfo holds exported Swagger Info so clients can modify it
|
|
var SwaggerInfo = &swag.Spec{
|
|
Version: "1.0",
|
|
Host: "",
|
|
BasePath: "/",
|
|
Schemes: []string{},
|
|
Title: "MusicServer API",
|
|
Description: "API for the MusicServer application",
|
|
InfoInstanceName: "swagger",
|
|
SwaggerTemplate: docTemplate,
|
|
LeftDelim: "{{",
|
|
RightDelim: "}}",
|
|
}
|
|
|
|
func init() {
|
|
swag.Register(SwaggerInfo.InstanceName(), SwaggerInfo)
|
|
}
|