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:
+129
-15
@@ -1,14 +1,26 @@
|
||||
// TODO: Separate queue and coverart endpoints
|
||||
#[derive(Debug, Default, serde::Deserialize, serde::Serialize)]
|
||||
#[derive(Debug, Default, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
|
||||
pub struct CoverArtQueue {
|
||||
pub id: uuid::Uuid,
|
||||
pub song_queue_id: uuid::Uuid,
|
||||
}
|
||||
|
||||
pub mod request {
|
||||
pub mod queue {
|
||||
#[derive(utoipa::ToSchema)]
|
||||
pub struct Request {
|
||||
/// 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 cover art file
|
||||
pub value: Vec<u8>,
|
||||
}
|
||||
}
|
||||
|
||||
pub mod link {
|
||||
#[derive(Debug, Default, serde::Deserialize, serde::Serialize)]
|
||||
#[derive(Debug, Default, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
|
||||
pub struct Request {
|
||||
pub coverart_id: uuid::Uuid,
|
||||
pub song_queue_id: uuid::Uuid,
|
||||
@@ -16,7 +28,7 @@ pub mod request {
|
||||
}
|
||||
|
||||
pub mod fetch_coverart_no_data {
|
||||
#[derive(Debug, Default, serde::Deserialize, serde::Serialize)]
|
||||
#[derive(Debug, Default, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
|
||||
pub struct Params {
|
||||
pub id: Option<uuid::Uuid>,
|
||||
pub song_queue_id: Option<uuid::Uuid>,
|
||||
@@ -24,7 +36,7 @@ pub mod request {
|
||||
}
|
||||
|
||||
pub mod fetch_coverart_with_data {
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
|
||||
pub struct Params {
|
||||
pub id: Option<uuid::Uuid>,
|
||||
pub song_queue_id: Option<uuid::Uuid>,
|
||||
@@ -32,7 +44,7 @@ pub mod request {
|
||||
}
|
||||
|
||||
pub mod create_coverart {
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
|
||||
pub struct Request {
|
||||
pub song_id: uuid::Uuid,
|
||||
pub coverart_queue_id: uuid::Uuid,
|
||||
@@ -40,14 +52,14 @@ pub mod request {
|
||||
}
|
||||
|
||||
pub mod wipe_data_from_coverart_queue {
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
|
||||
pub struct Request {
|
||||
pub coverart_queue_id: uuid::Uuid,
|
||||
}
|
||||
}
|
||||
|
||||
pub mod get_coverart {
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
|
||||
pub struct Params {
|
||||
pub id: Option<uuid::Uuid>,
|
||||
}
|
||||
@@ -55,20 +67,20 @@ pub mod request {
|
||||
}
|
||||
|
||||
pub mod response {
|
||||
#[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>,
|
||||
}
|
||||
|
||||
pub mod link {
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize)]
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, utoipa::ToSchema)]
|
||||
pub struct Id {
|
||||
pub coverart_id: uuid::Uuid,
|
||||
pub song_queue_id: uuid::Uuid,
|
||||
}
|
||||
|
||||
#[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<Id>,
|
||||
@@ -76,7 +88,7 @@ pub mod response {
|
||||
}
|
||||
|
||||
pub mod fetch_coverart_no_data {
|
||||
#[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<super::super::CoverArtQueue>,
|
||||
@@ -84,7 +96,7 @@ pub mod response {
|
||||
}
|
||||
|
||||
pub mod fetch_coverart_with_data {
|
||||
#[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<Vec<u8>>,
|
||||
@@ -92,7 +104,7 @@ pub mod response {
|
||||
}
|
||||
|
||||
pub mod create_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<icarus_models::coverart::CoverArt>,
|
||||
@@ -100,7 +112,7 @@ pub mod response {
|
||||
}
|
||||
|
||||
pub mod wipe_data_from_coverart_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>,
|
||||
@@ -108,7 +120,7 @@ pub mod response {
|
||||
}
|
||||
|
||||
pub mod get_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<icarus_models::coverart::CoverArt>,
|
||||
@@ -465,6 +477,18 @@ pub mod endpoint {
|
||||
|
||||
use axum::response::IntoResponse;
|
||||
|
||||
/// Endpoint to queue cover art
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = super::super::endpoints::QUEUECOVERART,
|
||||
request_body(
|
||||
content = super::request::queue::Request,
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Successful", body = super::response::Response),
|
||||
(status = 400, description = "Error queueing cover art", body = super::response::Response)
|
||||
)
|
||||
)]
|
||||
pub async fn queue(
|
||||
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
|
||||
mut multipart: axum::extract::Multipart,
|
||||
@@ -510,6 +534,20 @@ pub mod endpoint {
|
||||
}
|
||||
}
|
||||
|
||||
/// Endpoint to link queued cover art
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = super::super::endpoints::QUEUECOVERARTLINK,
|
||||
request_body(
|
||||
content = super::request::link::Request,
|
||||
description = "Linking queued cover art to queued song",
|
||||
content_type = "application/json"
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Queued cover art linked", body = super::response::link::Response),
|
||||
(status = 400, description = "Linkage failed", body = super::response::link::Response)
|
||||
)
|
||||
)]
|
||||
pub async fn link(
|
||||
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
|
||||
axum::Json(payload): axum::Json<super::request::link::Request>,
|
||||
@@ -537,6 +575,19 @@ pub mod endpoint {
|
||||
}
|
||||
}
|
||||
|
||||
/// Endpoint to fetch cover art details
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = super::super::endpoints::QUEUECOVERART,
|
||||
params(
|
||||
("id" = uuid::Uuid, Path, description = "Queued cover art Id"),
|
||||
("song_queue_id" = uuid::Uuid, Path, description = "Queued song Id")
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Queued song linked", body = super::response::fetch_coverart_no_data::Response),
|
||||
(status = 400, description = "Linkage failed", body = super::response::fetch_coverart_no_data::Response)
|
||||
)
|
||||
)]
|
||||
pub async fn fetch_coverart_no_data(
|
||||
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
|
||||
axum::extract::Query(params): axum::extract::Query<
|
||||
@@ -584,6 +635,16 @@ pub mod endpoint {
|
||||
}
|
||||
}
|
||||
|
||||
/// Endpoint to fetch the queued cover art data
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = super::super::endpoints::QUEUECOVERARTDATA,
|
||||
params(("id" = uuid::Uuid, Path, description = "Queued cover art Id")),
|
||||
responses(
|
||||
(status = 200, description = "Queued cover art data", body = Vec<u8>),
|
||||
(status = 400, description = "Error fetching queued cover art data", body = Vec<u8>)
|
||||
)
|
||||
)]
|
||||
pub async fn fetch_coverart_with_data(
|
||||
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
|
||||
axum::extract::Path(id): axum::extract::Path<uuid::Uuid>,
|
||||
@@ -612,6 +673,20 @@ pub mod endpoint {
|
||||
}
|
||||
}
|
||||
|
||||
/// Endpoint to create cover art
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = super::super::endpoints::CREATECOVERART,
|
||||
request_body(
|
||||
content = super::request::create_coverart::Request,
|
||||
description = "Data required to create cover art",
|
||||
content_type = "application/json"
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Cover art created", body = super::response::create_coverart::Response),
|
||||
(status = 400, description = "Failure in creating cover art", body = super::response::create_coverart::Response)
|
||||
)
|
||||
)]
|
||||
pub async fn create_coverart(
|
||||
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
|
||||
axum::Json(payload): axum::Json<super::request::create_coverart::Request>,
|
||||
@@ -672,6 +747,21 @@ pub mod endpoint {
|
||||
}
|
||||
}
|
||||
|
||||
/// Endpoint to wipe data from the cover art queue
|
||||
#[utoipa::path(
|
||||
patch,
|
||||
path = super::super::endpoints::QUEUECOVERARTDATAWIPE,
|
||||
request_body(
|
||||
content = super::request::wipe_data_from_coverart_queue::Request,
|
||||
description = "Data required to wipe the data from the cover art queue",
|
||||
content_type = "application/json"
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Data wiped from cover art queue", body = super::response::wipe_data_from_coverart_queue::Response),
|
||||
(status = 400, description = "Error wiping the data", body = super::response::wipe_data_from_coverart_queue::Response),
|
||||
(status = 404, description = "Cover art not found", body = super::response::wipe_data_from_coverart_queue::Response)
|
||||
)
|
||||
)]
|
||||
pub async fn wipe_data_from_coverart_queue(
|
||||
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
|
||||
axum::Json(payload): axum::Json<super::request::wipe_data_from_coverart_queue::Request>,
|
||||
@@ -701,6 +791,18 @@ pub mod endpoint {
|
||||
}
|
||||
}
|
||||
|
||||
/// Endpoint to get cover art with criteria
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = super::super::endpoints::GETCOVERART,
|
||||
params(
|
||||
("id" = uuid::Uuid, Path, description = "Cover art Id")
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Cover art retrieved", body = super::response::get_coverart::Response),
|
||||
(status = 400, description = "Error retrieving cover art", body = super::response::get_coverart::Response)
|
||||
)
|
||||
)]
|
||||
pub async fn get_coverart(
|
||||
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
|
||||
axum::extract::Query(params): axum::extract::Query<super::request::get_coverart::Params>,
|
||||
@@ -729,6 +831,18 @@ pub mod endpoint {
|
||||
}
|
||||
}
|
||||
|
||||
/// Endpoint to download cover art
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = super::super::endpoints::DOWNLOADCOVERART,
|
||||
params(
|
||||
("id" = uuid::Uuid, Path, description = "Cover art Id")
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Cover art downloading", body = Vec<u8>),
|
||||
(status = 404, description = "Cover art not found", body = Vec<u8>)
|
||||
)
|
||||
)]
|
||||
pub async fn download_coverart(
|
||||
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
|
||||
axum::extract::Path(id): axum::extract::Path<uuid::Uuid>,
|
||||
|
||||
+40
-8
@@ -1,10 +1,9 @@
|
||||
// TODO: Explicitly make this module target queueing a song's metadata
|
||||
pub mod request {
|
||||
|
||||
pub mod queue_metadata {
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Default, Deserialize, Serialize, sqlx::FromRow)]
|
||||
#[derive(Debug, Default, Deserialize, Serialize, sqlx::FromRow, utoipa::ToSchema)]
|
||||
pub struct Request {
|
||||
pub song_queue_id: uuid::Uuid,
|
||||
pub album: String,
|
||||
@@ -43,7 +42,13 @@ pub mod request {
|
||||
|
||||
pub mod fetch_metadata {
|
||||
#[derive(
|
||||
Debug, Default, serde::Deserialize, serde::Serialize, sqlx::FromRow, sqlx::Decode,
|
||||
Debug,
|
||||
Default,
|
||||
serde::Deserialize,
|
||||
serde::Serialize,
|
||||
sqlx::FromRow,
|
||||
sqlx::Decode,
|
||||
utoipa::ToSchema,
|
||||
)]
|
||||
pub struct Params {
|
||||
pub id: Option<uuid::Uuid>,
|
||||
@@ -53,11 +58,10 @@ pub mod request {
|
||||
}
|
||||
|
||||
pub mod response {
|
||||
|
||||
pub mod queue_metadata {
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Default, Deserialize, Serialize)]
|
||||
#[derive(Default, Deserialize, Serialize, utoipa::ToSchema)]
|
||||
pub struct Response {
|
||||
pub message: String,
|
||||
pub data: Vec<uuid::Uuid>,
|
||||
@@ -67,7 +71,7 @@ pub mod response {
|
||||
pub mod fetch_metadata {
|
||||
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::metadata::metadata_queue::MetadataQueue>,
|
||||
@@ -83,7 +87,7 @@ pub mod metadata_queue {
|
||||
pub id: uuid::Uuid,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, sqlx::FromRow)]
|
||||
#[derive(Debug, serde::Deserialize, serde::Serialize, sqlx::FromRow, utoipa::ToSchema)]
|
||||
pub struct MetadataQueue {
|
||||
pub id: uuid::Uuid,
|
||||
pub metadata: serde_json::Value,
|
||||
@@ -204,9 +208,24 @@ pub mod metadata_queue {
|
||||
}
|
||||
}
|
||||
|
||||
/// Module for metadata related endpoints
|
||||
pub mod endpoint {
|
||||
use axum::{Json, http::StatusCode};
|
||||
|
||||
/// Endpoint to create queued metadata
|
||||
#[utoipa::path(
|
||||
post,
|
||||
path = super::super::endpoints::QUEUEMETADATA,
|
||||
request_body(
|
||||
content = super::request::queue_metadata::Request,
|
||||
description = "Data required to create queued metadata",
|
||||
content_type = "application/json"
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Queued metadata created", body = super::response::queue_metadata::Response),
|
||||
(status = 400, description = "Error creating queued metadata", body = super::response::queue_metadata::Response)
|
||||
)
|
||||
)]
|
||||
pub async fn queue_metadata(
|
||||
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
|
||||
Json(payload): Json<super::request::queue_metadata::Request>,
|
||||
@@ -221,7 +240,7 @@ pub mod endpoint {
|
||||
response.message = if response.data.is_empty() {
|
||||
String::from("Error")
|
||||
} else {
|
||||
String::from("Success")
|
||||
String::from(super::super::response::SUCCESSFUL)
|
||||
};
|
||||
|
||||
(StatusCode::OK, Json(response))
|
||||
@@ -233,6 +252,19 @@ pub mod endpoint {
|
||||
}
|
||||
}
|
||||
|
||||
/// Endpoint to get queued metadata
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = super::super::endpoints::QUEUEMETADATA,
|
||||
params(
|
||||
("id" = uuid::Uuid, Path, description = "Id of queued metadata"),
|
||||
("song_queue_id" = uuid::Uuid, Path, description = "Id of queued song")
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "Queued metadata retrieved", body = super::response::fetch_metadata::Response),
|
||||
(status = 400, description = "Error retrieving queued metadata", body = super::response::fetch_metadata::Response)
|
||||
)
|
||||
)]
|
||||
pub async fn fetch_metadata(
|
||||
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
|
||||
axum::extract::Query(params): axum::extract::Query<super::request::fetch_metadata::Params>,
|
||||
|
||||
+193
-17
@@ -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>,
|
||||
|
||||
+36
@@ -48,12 +48,44 @@ pub mod init {
|
||||
use axum::routing::{delete, get, patch, post};
|
||||
use std::time::Duration;
|
||||
use tower_http::timeout::TimeoutLayer;
|
||||
use utoipa::OpenApi;
|
||||
|
||||
use axum::http::{
|
||||
HeaderValue, Method,
|
||||
header::{ACCEPT, AUTHORIZATION, CONTENT_TYPE},
|
||||
};
|
||||
|
||||
use crate::callers::coverart as coverart_caller;
|
||||
use crate::callers::metadata as metadata_caller;
|
||||
use crate::callers::song as song_caller;
|
||||
use coverart_caller::endpoint as coverart_endpoints;
|
||||
use coverart_caller::response as coverart_responses;
|
||||
use metadata_caller::endpoint as metadata_endpoints;
|
||||
use metadata_caller::response as metadata_responses;
|
||||
use song_caller::endpoint as song_endpoints;
|
||||
use song_caller::response as song_responses;
|
||||
|
||||
#[derive(utoipa::OpenApi)]
|
||||
#[openapi(
|
||||
paths(song_endpoints::queue_song, song_endpoints::link_user_id, song_endpoints::fetch_queue_song, song_endpoints::download_flac,
|
||||
song_endpoints::update_song_queue_status, song_endpoints::update_song_queue, song_endpoints::create_metadata, song_endpoints::wipe_data_from_song_queue, song_endpoints::get_songs, song_endpoints::get_all_songs, song_endpoints::stream_song, song_endpoints::download_song,
|
||||
song_endpoints::delete_song, coverart_endpoints::queue, coverart_endpoints::link, coverart_endpoints::fetch_coverart_no_data,
|
||||
coverart_endpoints::fetch_coverart_with_data, coverart_endpoints::create_coverart, coverart_endpoints::wipe_data_from_coverart_queue,
|
||||
coverart_endpoints::get_coverart, coverart_endpoints::download_coverart,
|
||||
metadata_endpoints::queue_metadata, metadata_endpoints::fetch_metadata),
|
||||
components(schemas(song_responses::Response, song_responses::link_user_id::Response, song_responses::fetch_queue_song::Response,
|
||||
song_responses::update_status::Response, song_responses::update_song_queue::Response, song_responses::create_metadata::Response,
|
||||
song_responses::wipe_data_from_song_queue::Response, song_responses::get_songs::Response, song_responses::delete_song::Response,
|
||||
coverart_responses::Response, coverart_responses::link::Response, coverart_responses::fetch_coverart_no_data::Response,
|
||||
coverart_responses::fetch_coverart_with_data::Response, coverart_responses::create_coverart::Response,
|
||||
coverart_responses::wipe_data_from_coverart_queue::Response, coverart_responses::get_coverart::Response,
|
||||
metadata_responses::queue_metadata::Response, metadata_responses::fetch_metadata::Response)),
|
||||
tags(
|
||||
(name = "Icarus API", description = "Web API to manage music")
|
||||
)
|
||||
)]
|
||||
struct ApiDoc;
|
||||
|
||||
pub async fn routes() -> axum::Router {
|
||||
axum::Router::new()
|
||||
.route(crate::ROOT, get(crate::root))
|
||||
@@ -211,6 +243,10 @@ pub mod init {
|
||||
|
||||
routes()
|
||||
.await
|
||||
.merge(
|
||||
utoipa_swagger_ui::SwaggerUi::new("/swagger-ui")
|
||||
.url("/api-docs/openapi.json", ApiDoc::openapi()),
|
||||
)
|
||||
.layer(axum::Extension(pool))
|
||||
.layer(axum::extract::DefaultBodyLimit::max(1024 * 1024 * 1024))
|
||||
.layer(TimeoutLayer::new(Duration::from_secs(300)))
|
||||
|
||||
Reference in New Issue
Block a user