tsk-170: API documentation (#178)

* tsk-170: Added utopia crates for API documentation

* tsk-170: Adding code to document API

* tsk-170: icarus_models version bump

Added schema capabilities

* tsk-170: crate changes

* tsk-170: Added documentation for song queue endpoint

* tsk-170: Swagger openapi docs are now up

Well, at least one

* tsk-170: Some documentation

* tsk-170: Code formatting

* tsk-170: Saving changes

* tsk-170: Added more documentation

* tsk-170: Added the rest of the documentation

* tsk-170: Formatting

* tsk-170: icarus_models version bump
This commit was merged in pull request #178.
This commit is contained in:
KD
2025-08-24 19:58:38 -04:00
committed by GitHub
parent 598996cb8d
commit 805df87f5b
6 changed files with 580 additions and 43 deletions
+193 -17
View File
@@ -7,8 +7,21 @@ pub mod request {
pub message: String,
}
pub mod song_queue {
#[derive(utoipa::ToSchema)]
pub struct SongQueueRequest {
/// Filename
pub file: String,
#[schema(rename = "type")]
/// File type. Should be a file and not a value
pub file_type: String,
/// Raw data of the flac file
pub value: Vec<u8>,
}
}
pub mod update_status {
#[derive(Default, serde::Deserialize, serde::Serialize)]
#[derive(Default, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
pub struct Request {
pub id: uuid::Uuid,
pub status: String,
@@ -16,7 +29,7 @@ pub mod request {
}
pub mod create_metadata {
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Debug, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
pub struct Request {
pub title: String,
pub artist: String,
@@ -79,14 +92,14 @@ pub mod request {
}
pub mod wipe_data_from_song_queue {
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Debug, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
pub struct Request {
pub song_queue_id: uuid::Uuid,
}
}
pub mod link_user_id {
#[derive(Debug, serde::Deserialize, serde::Serialize)]
#[derive(Debug, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
pub struct Request {
pub song_queue_id: uuid::Uuid,
pub user_id: uuid::Uuid,
@@ -94,7 +107,7 @@ pub mod request {
}
pub mod get_songs {
#[derive(Debug, Default, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Default, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
pub struct Params {
pub id: Option<uuid::Uuid>,
}
@@ -104,16 +117,18 @@ pub mod request {
pub mod response {
use serde::{Deserialize, Serialize};
#[derive(Default, Deserialize, Serialize)]
/// Song queue response
#[derive(Default, Deserialize, Serialize, utoipa::ToSchema)]
pub struct Response {
pub message: String,
/// Id of the queued song
pub data: Vec<uuid::Uuid>,
}
pub mod fetch_queue_song {
use serde::{Deserialize, Serialize};
#[derive(Default, Deserialize, Serialize)]
#[derive(Default, Deserialize, Serialize, utoipa::ToSchema)]
pub struct Response {
pub message: String,
pub data: Vec<crate::callers::song::song_queue::SongQueue>,
@@ -121,13 +136,13 @@ pub mod response {
}
pub mod update_status {
#[derive(serde::Deserialize, serde::Serialize)]
#[derive(serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
pub struct ChangedStatus {
pub old_status: String,
pub new_status: String,
}
#[derive(Default, serde::Deserialize, serde::Serialize)]
#[derive(Default, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
pub struct Response {
pub message: String,
pub data: Vec<ChangedStatus>,
@@ -135,7 +150,7 @@ pub mod response {
}
pub mod update_song_queue {
#[derive(Default, serde::Deserialize, serde::Serialize)]
#[derive(Default, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
pub struct Response {
pub message: String,
pub data: Vec<uuid::Uuid>,
@@ -143,7 +158,7 @@ pub mod response {
}
pub mod create_metadata {
#[derive(Debug, Default, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Default, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
pub struct Response {
pub message: String,
pub data: Vec<icarus_models::song::Song>,
@@ -151,7 +166,7 @@ pub mod response {
}
pub mod wipe_data_from_song_queue {
#[derive(Debug, Default, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Default, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
pub struct Response {
pub message: String,
pub data: Vec<uuid::Uuid>,
@@ -159,7 +174,7 @@ pub mod response {
}
pub mod link_user_id {
#[derive(Debug, Default, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Default, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
pub struct Response {
pub message: String,
pub data: Vec<uuid::Uuid>,
@@ -167,7 +182,7 @@ pub mod response {
}
pub mod get_songs {
#[derive(Debug, Default, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Default, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
pub struct Response {
pub message: String,
pub data: Vec<icarus_models::song::Song>,
@@ -175,13 +190,13 @@ pub mod response {
}
pub mod delete_song {
#[derive(Debug, Default, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Default, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
pub struct SongAndCoverArt {
pub song: icarus_models::song::Song,
pub coverart: icarus_models::coverart::CoverArt,
}
#[derive(Debug, Default, serde::Deserialize, serde::Serialize)]
#[derive(Debug, Default, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
pub struct Response {
pub message: String,
pub data: Vec<SongAndCoverArt>,
@@ -561,7 +576,8 @@ mod song_queue {
pub id: uuid::Uuid,
}
#[derive(Debug, serde::Deserialize, serde::Serialize, sqlx::FromRow)]
// TODO: Move this somewhere else at some point
#[derive(Debug, serde::Deserialize, serde::Serialize, sqlx::FromRow, utoipa::ToSchema)]
pub struct SongQueue {
pub id: uuid::Uuid,
pub filename: String,
@@ -854,12 +870,27 @@ mod song_queue {
}
}
/// Module for song related endpoints
pub mod endpoint {
use axum::{Json, http::StatusCode, response::IntoResponse};
use std::io::Write;
use crate::callers::song::song_queue;
/// Endpoint to queue a song. Starts the process and places the song in a queue
#[utoipa::path(
post,
path = super::super::endpoints::QUEUESONG,
request_body(
content = super::request::song_queue::SongQueueRequest,
description = "Multipart form data for uploading song",
content_type = "multipart/form-data"
),
responses(
(status = 200, description = "Song queued", body = super::response::Response)
)
)]
pub async fn queue_song(
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
mut multipart: axum::extract::Multipart,
@@ -908,6 +939,20 @@ pub mod endpoint {
(StatusCode::OK, Json(response))
}
/// Endpoint to link a user id to a queued song
#[utoipa::path(
patch,
path = super::super::endpoints::QUEUESONGLINKUSERID,
request_body(
content = super::request::link_user_id::Request,
description = "User Id and queued song id",
content_type = "application/json"
),
responses(
(status = 200, description = "Queued song linked", body = super::response::link_user_id::Response),
(status = 400, description = "Linkage failed", body = super::response::link_user_id::Response)
)
)]
pub async fn link_user_id(
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
axum::Json(payload): axum::Json<super::request::link_user_id::Request>,
@@ -939,6 +984,15 @@ pub mod endpoint {
}
}
/// Endpoint to fetch the next queued song as long as it is available
#[utoipa::path(
get,
path = super::super::endpoints::NEXTQUEUESONG,
responses(
(status = 200, description = "Queued song is present and available", body = super::response::fetch_queue_song::Response),
(status = 400, description = "Linkage failed", body = super::response::fetch_queue_song::Response)
)
)]
pub async fn fetch_queue_song(
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
) -> (
@@ -961,6 +1015,16 @@ pub mod endpoint {
}
// TODO: Rename
/// Endpoint to download the queued song
#[utoipa::path(
get,
path = super::super::endpoints::QUEUESONGDATA,
params(("id" = uuid::Uuid, Path, description = "Queued song Id")),
responses(
(status = 200, description = "Queued song linked", body = Vec<u8>),
(status = 400, description = "Linkage failed", body = Vec<u8>)
)
)]
pub async fn download_flac(
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
axum::extract::Path(id): axum::extract::Path<uuid::Uuid>,
@@ -989,6 +1053,20 @@ pub mod endpoint {
}
}
/// Endpoint to update the status of a queued song
#[utoipa::path(
patch,
path = super::super::endpoints::QUEUESONG,
request_body(
content = super::request::update_status::Request,
description = "Update the status of a queued song",
content_type = "application/json"
),
responses(
(status = 200, description = "Status has been updated", body = super::response::update_status::Response),
(status = 400, description = "Error updating status of queued song", body = super::response::update_status::Response)
)
)]
pub async fn update_song_queue_status(
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
axum::Json(payload): axum::Json<super::request::update_status::Request>,
@@ -1041,6 +1119,22 @@ pub mod endpoint {
}
}
/// Endpoint to update the queued song data
#[utoipa::path(
patch,
path = super::super::endpoints::QUEUESONGUPDATE,
request_body(
content = super::request::song_queue::SongQueueRequest,
description = "Multipart form data for uploading song",
content_type = "multipart/form-data"
),
params(("id" = uuid::Uuid, Path, description = "Queued song Id")),
responses(
(status = 200, description = "Queued song updated", body = super::response::update_song_queue::Response),
(status = 400, description = "Error updating queued song", body = super::response::update_song_queue::Response),
(status = 404, description = "Queued song not found", body = super::response::update_song_queue::Response)
)
)]
pub async fn update_song_queue(
axum::extract::Path(id): axum::extract::Path<uuid::Uuid>,
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
@@ -1087,6 +1181,21 @@ pub mod endpoint {
}
}
/// Endpoint to create song
#[utoipa::path(
post,
path = super::super::endpoints::QUEUEMETADATA,
request_body(
content = super::request::create_metadata::Request,
description = "Data needed to create the song and save it to the filesystem",
content_type = "application/json"
),
responses(
(status = 200, description = "Song created", body = super::response::create_metadata::Response),
(status = 400, description = "Error", body = super::response::create_metadata::Response),
(status = 505, description = "Error creating song", body = super::response::create_metadata::Response)
)
)]
pub async fn create_metadata(
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
axum::Json(payload): axum::Json<super::request::create_metadata::Request>,
@@ -1170,6 +1279,20 @@ pub mod endpoint {
}
}
/// Endpoint to wipe the data from a queued song
#[utoipa::path(
patch,
path = super::super::endpoints::QUEUESONGDATAWIPE,
request_body(
content = super::request::wipe_data_from_song_queue::Request,
description = "Pass the queued song Id to wipe the data",
content_type = "application/json"
),
responses(
(status = 200, description = "Queued song data wiped", body = super::response::wipe_data_from_song_queue::Response),
(status = 404, description = "Queued song cannot be found", body = super::response::wipe_data_from_song_queue::Response)
)
)]
pub async fn wipe_data_from_song_queue(
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
axum::Json(payload): axum::Json<super::request::wipe_data_from_song_queue::Request>,
@@ -1200,6 +1323,18 @@ pub mod endpoint {
}
}
// Endpoint to get songs
#[utoipa::path(
get,
path = super::super::endpoints::GETSONGS,
params(
("id" = uuid::Uuid, Path, description = "Id of song")
),
responses(
(status = 200, description = "Songs found", body = super::response::get_songs::Response),
(status = 400, description = "Error getting songs", body = super::response::get_songs::Response)
)
)]
pub async fn get_songs(
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
axum::extract::Query(params): axum::extract::Query<super::request::get_songs::Params>,
@@ -1228,6 +1363,15 @@ pub mod endpoint {
}
}
/// Endpoint to get all songs
#[utoipa::path(
get,
path = super::super::endpoints::GETALLSONGS,
responses(
(status = 200, description = "Getting all songs", body = super::response::get_songs::Response),
(status = 404, description = "Song not found", body = super::response::get_songs::Response)
)
)]
pub async fn get_all_songs(
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
) -> (
@@ -1249,6 +1393,16 @@ pub mod endpoint {
}
}
/// Ednpoint to stream song
#[utoipa::path(
get,
path = super::super::endpoints::STREAMSONG,
params(("id" = uuid::Uuid, Path, description = "Song Id")),
responses(
(status = 200, description = "Stream song", body = Vec<u8>),
(status = 500, description = "Error streaming song", body = (u64, String))
)
)]
pub async fn stream_song(
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
axum::extract::Path(id): axum::extract::Path<uuid::Uuid>,
@@ -1296,6 +1450,17 @@ pub mod endpoint {
}
}
/// Endpoint to download song
#[utoipa::path(
get,
path = super::super::endpoints::DOWNLOADSONG,
params(("id" = uuid::Uuid, Path, description = "Song Id")),
responses(
(status = 200, description = "Download song", body = (u64, Vec<u8>)),
(status = 404, description = "Song not found", body = (u64, Vec<u8>)),
(status = 400, description = "Error downloading song", body = (u64, Vec<u8>))
)
)]
pub async fn download_song(
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
axum::extract::Path(id): axum::extract::Path<uuid::Uuid>,
@@ -1331,6 +1496,17 @@ pub mod endpoint {
}
}
/// Endpoint to delete the song
#[utoipa::path(
delete,
path = super::super::endpoints::DELETESONG,
params(("id" = uuid::Uuid, Path, description = "Song Id")),
responses(
(status = 200, description = "Song deleted", body = super::response::delete_song::Response),
(status = 404, description = "Song not found", body = super::response::delete_song::Response),
(status = 500, description = "Error deleting song", body = super::response::delete_song::Response)
)
)]
pub async fn delete_song(
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
axum::extract::Path(id): axum::extract::Path<uuid::Uuid>,