From f0736da861c8b4e557ad55643654031f8e7e05a5 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Fri, 23 May 2025 17:43:30 -0400 Subject: [PATCH] Added endpoint to create song --- src/callers/song.rs | 116 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 1 deletion(-) diff --git a/src/callers/song.rs b/src/callers/song.rs index 98f0100..38a35cc 100644 --- a/src/callers/song.rs +++ b/src/callers/song.rs @@ -30,6 +30,7 @@ pub mod request { pub duration: i32, pub audio_type: String, pub user_id: uuid::Uuid, + pub song_queue_id: uuid::Uuid, } impl Request { @@ -38,6 +39,31 @@ pub mod request { || !self.album.is_empty() || !self.genre.is_empty() || !self.date.is_empty() || self.track > 0 || self.disc > 0 || self.track_count > 0 || self.disc_count > 0 || self.duration > 0 || !self.audio_type.is_empty() || !self.user_id.is_nil() + || !self.song_queue_id.is_nil() + } + + pub fn to_song(&self) -> icarus_models::song::Song { + icarus_models::song::Song { + id: uuid::Uuid::nil(), + title: self.title.clone(), + artist: self.artist.clone(), + album_artist: self.album_artist.clone(), + album: self.album.clone(), + genre: self.genre.clone(), + year: self.date[..3].parse().unwrap(), + track: self.track.clone(), + disc: self.disc.clone(), + track_count: self.track_count.clone(), + disc_count: self.disc_count.clone(), + duration: self.duration.clone(), + audio_type: self.audio_type.clone(), + user_id: self.user_id.clone(), + // TODO: Change the type of this in icarus_models lib + date_created: String::new(), + filename: String::new(), + data: Vec::new(), + directory: String::new(), + } } } } @@ -88,6 +114,7 @@ pub mod response { #[derive(Default, serde::Deserialize, serde::Serialize)] pub struct Response { pub message: String, + pub data: Vec } } } @@ -104,6 +131,57 @@ pub mod status { } } +mod song { + use sqlx::Row; + + // TODO: Change first parameter of return value from string to a time type + pub async fn insert(pool: &sqlx::PgPool, song: &icarus_models::song::Song) -> Result<(String, uuid::Uuid), sqlx::Error> { + let result = sqlx::query( + r#" + INSERT INTO "song" (title, artist, album_artist, album, genre, year, + track, disc, track_count, disc_count, duration, audio_type, filename, + directory, user_id) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, + $11, $12, $13, $14, $15) RETURNING date_created, id; + "# + ) + .bind(song.title.clone()) + .bind(song.artist.clone()) + .bind(song.album_artist.clone()) + .bind(song.album.clone()) + .bind(song.genre.clone()) + .bind(song.year) + .bind(song.track) + .bind(song.disc) + .bind(song.track_count) + .bind(song.disc_count) + .bind(song.duration) + .bind(song.audio_type.clone()) + .bind(song.filename.clone()) + .bind(song.directory.clone()) + .bind(song.user_id) + .fetch_one(pool) + .await + .map_err(|e| { + eprintln!("Error inserting query: {:?}", e); + }); + + match result { + Ok(row) => { + let id: uuid::Uuid = row + .try_get("id") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(); + let date_created = row.try_get("date_created").map_err(|_e| sqlx::Error::RowNotFound).unwrap(); + + Ok((date_created, id)) + } + Err(_) => { + Err(sqlx::Error::RowNotFound) + } + } + } +} + mod song_queue { use sqlx::Row; @@ -502,7 +580,43 @@ pub mod endpoint { let mut response = super::response::create_metadata::Response::default(); if payload.is_valid() { - (axum::http::StatusCode::OK, axum::Json(response)) + let mut song = payload.to_song(); + song.filename = song.generate_filename(icarus_models::types::MusicTypes::FlacExtension, true); + song.directory = crate::environment::get_root_directory().await.unwrap(); + match song_queue::get_data(&pool, &payload.song_queue_id).await { + Ok(data) => { + song.data = data; + let dir = std::path::Path::new(&song.directory); + let save_path = dir.join(&song.filename); + let mut file = std::fs::File::create(&save_path).unwrap(); + file.write_all(&song.data).unwrap(); + + match song.song_path() { + Ok(_) => { + match super::song::insert(&pool, &song).await { + Ok((date_created, id)) => { + song.id = id; + song.date_created = date_created; + // response.data.push(returned_song); + (axum::http::StatusCode::OK, axum::Json(response)) + } + Err(err) => { + response.message = err.to_string(); + (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) + } + } + } + Err(err) => { + response.message = err.to_string(); + (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) + } + } + } + Err(err) => { + response.message = err.to_string(); + (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) + } + } } else { response.message = String::from("Request body is not valid"); (axum::http::StatusCode::BAD_REQUEST, axum::Json(response))