From 9e39757d602bc10188e64a953af79759edd29b87 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 24 May 2025 17:03:30 -0400 Subject: [PATCH 01/12] Added migrations for coverart --- migrations/20250420185217_init_migration.sql | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/migrations/20250420185217_init_migration.sql b/migrations/20250420185217_init_migration.sql index 22d78b0..09fde2f 100644 --- a/migrations/20250420185217_init_migration.sql +++ b/migrations/20250420185217_init_migration.sql @@ -48,4 +48,14 @@ CREATE TABLE IF NOT EXISTS "song" ( filename TEXT NOT NULL, directory TEXT NOT NULL, user_id UUID NULL + -- TODO: Add coverart id later. This will allow multiple songs to be linked to a single cover art +); + +CREATE TABLE IF NOT EXISTS "coverart" ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + title TEXT NOT NULL, + -- TODO: Separate path later + path TEXT NOT NULL, + song_id UUID NOT NULL + -- TODO: Add type later ); -- 2.47.3 From 751be77d7eaf7a14b863ba211b4d41c6aefda8bb Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 24 May 2025 17:18:55 -0400 Subject: [PATCH 02/12] Test refactor --- src/main.rs | 62 +++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 33 deletions(-) diff --git a/src/main.rs b/src/main.rs index d9d4892..aa828e5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -360,6 +360,34 @@ mod tests { app.clone().oneshot(req).await } + async fn create_song_req(app: &axum::Router, song_queue_id: &uuid::Uuid) -> Result { + let payload = serde_json::json!({ + "title": "Power of Soul", + "artist": "Jimmi Hendrix", + "album_artist": "Jimmi Hendrix", + "album": "Machine Gun", + "genre": "Psychadelic Rock", + "date": "2016-01-01", + "track": 1, + "disc": 1, + "track_count": 11, + "disc_count": 1, + "duration": 330, + "audio_type": "flac", + "user_id": "d6e159c1-9648-4c85-81e5-52f502ff53e4", + "song_queue_id": song_queue_id + }); + + let req = axum::http::Request::builder() + .method(axum::http::Method::POST) + .uri(crate::callers::endpoints::CREATESONG) + .header(axum::http::header::CONTENT_TYPE, "application/json") + .body(axum::body::Body::from(payload.to_string())) + .unwrap(); + + app.clone().oneshot(req).await + } + pub async fn resp_to_bytes( response: axum::response::Response, ) -> Result { @@ -1237,39 +1265,7 @@ mod tests { assert_eq!(false, resp.data.is_empty(), "Data should not be empty"); let song_q_id = resp.data[0].song_queue_id; - let payload = serde_json::json!({ - "title": "Power of Soul", - "artist": "Jimmi Hendrix", - "album_artist": "Jimmi Hendrix", - "album": "Machine Gun", - "genre": "Psychadelic Rock", - "date": "2016-01-01", - "track": 1, - "disc": 1, - "track_count": 11, - "disc_count": 1, - "duration": 330, - "audio_type": "flac", - "user_id": "d6e159c1-9648-4c85-81e5-52f502ff53e4", - "song_queue_id": song_q_id - }); - - eprintln!("Payload: {:?}", payload); - - match app - .clone() - .oneshot( - axum::http::Request::builder() - .method(axum::http::Method::POST) - .uri(crate::callers::endpoints::CREATESONG) - .header( - axum::http::header::CONTENT_TYPE, - "application/json", - ) - .body(axum::body::Body::from(payload.to_string())) - .unwrap(), - ) - .await + match create_song_req(&app, &song_q_id).await { Ok(response) => { let resp = get_resp_data::(response).await; -- 2.47.3 From bb6e3b4284b8efbaf9581154d741ff0ae4adceda Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 24 May 2025 17:19:12 -0400 Subject: [PATCH 03/12] Code formatting --- src/main.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main.rs b/src/main.rs index aa828e5..6032046 100644 --- a/src/main.rs +++ b/src/main.rs @@ -360,7 +360,10 @@ mod tests { app.clone().oneshot(req).await } - async fn create_song_req(app: &axum::Router, song_queue_id: &uuid::Uuid) -> Result { + async fn create_song_req( + app: &axum::Router, + song_queue_id: &uuid::Uuid, + ) -> Result { let payload = serde_json::json!({ "title": "Power of Soul", "artist": "Jimmi Hendrix", @@ -1265,8 +1268,7 @@ mod tests { assert_eq!(false, resp.data.is_empty(), "Data should not be empty"); let song_q_id = resp.data[0].song_queue_id; - match create_song_req(&app, &song_q_id).await - { + match create_song_req(&app, &song_q_id).await { Ok(response) => { let resp = get_resp_data::(response).await; assert_eq!( -- 2.47.3 From 5675bb48b626f6e36d034931097c08961aa3be24 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 24 May 2025 18:14:53 -0400 Subject: [PATCH 04/12] Added endpoint to create coverart --- src/callers/coverart.rs | 99 +++++++++++++++++++++++++++++++++++++++++ src/callers/mod.rs | 1 + src/callers/song.rs | 47 ++++++++++++++++++- 3 files changed, 146 insertions(+), 1 deletion(-) diff --git a/src/callers/coverart.rs b/src/callers/coverart.rs index 2972dfc..11f7744 100644 --- a/src/callers/coverart.rs +++ b/src/callers/coverart.rs @@ -29,6 +29,14 @@ pub mod request { pub song_queue_id: Option, } } + + pub mod create_coverart { + #[derive(Debug, serde::Deserialize, serde::Serialize)] + pub struct Request { + pub song_id: uuid::Uuid, + pub coverart_queue_id: uuid::Uuid + } + } } pub mod response { @@ -67,6 +75,14 @@ pub mod response { pub data: Vec>, } } + + pub mod create_coverart { + #[derive(Debug, Default, serde::Deserialize, serde::Serialize)] + pub struct Response { + pub message: String, + pub data: Vec + } + } } pub mod db { @@ -231,7 +247,40 @@ pub mod db { } } +pub mod cov_db { + use sqlx::Row; + + pub async fn create(pool: &sqlx::PgPool, coverart: &icarus_models::coverart::CoverArt, song_id: &uuid::Uuid) -> Result { + let result = sqlx::query( + r#" + INSERT INTO "coverart" (title, path, song_id) VALUES($1, $2, $3) RETURNING id; + "#, + ) + .bind(&coverart.title) + .bind(&coverart.path) + .bind(&song_id) + .fetch_one(pool) + .await + .map_err(|e| { + eprintln!("Error inserting: {}", e); + }); + + match result { + Ok(row) => { + let id: uuid::Uuid = row + .try_get("id") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(); + Ok(id) + } + Err(_err) => Err(sqlx::Error::RowNotFound), + } + } +} + pub mod endpoint { + use std::io::Write; + pub async fn queue( axum::Extension(pool): axum::Extension, mut multipart: axum::extract::Multipart, @@ -398,4 +447,54 @@ pub mod endpoint { }, } } + + pub async fn create_coverart(axum::Extension(pool): axum::Extension, + axum::Json(payload): axum::Json) -> (axum::http::StatusCode, axum::Json) { + let mut response = super::response::create_coverart::Response::default(); + let id = payload.coverart_queue_id; + + match super::db::get_coverart_queue_data_with_id(&pool, &id).await { + Ok(data) => { + let song_id = payload.song_id; + match crate::callers::song::song_db::get_song(&pool, &song_id).await { + Ok(song) => { + let directory = crate::environment::get_root_directory().await.unwrap(); + let dir = std::path::Path::new(&directory); + + // TODO: Make this random and the file extension should not be hard coded + let filename = format!("{}-coverart.jpeg", &song.filename[..8]); + let save_path = dir.join(&filename); + let path = String::from(save_path.to_str().unwrap()); + let mut coverart = icarus_models::coverart::init::init_coverart_only_path(path); + coverart.title = song.album.clone(); + coverart.data = data; + + let mut file = std::fs::File::create(&save_path).unwrap(); + file.write_all(&coverart.data).unwrap(); + + match super::cov_db::create(&pool, &coverart, &song.id).await { + Ok(id) => { + coverart.id = id; + response.data.push(coverart); + + (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)) + } + } + } } diff --git a/src/callers/mod.rs b/src/callers/mod.rs index 99e918a..5427afe 100644 --- a/src/callers/mod.rs +++ b/src/callers/mod.rs @@ -13,4 +13,5 @@ pub mod endpoints { pub const QUEUECOVERARTLINK: &str = "/api/v2/coverart/queue/link"; pub const CREATESONG: &str = "/api/v2/song"; + pub const CREATECOVERART: &str = "/api/v2/coverart"; } diff --git a/src/callers/song.rs b/src/callers/song.rs index 66731c2..9fe6b90 100644 --- a/src/callers/song.rs +++ b/src/callers/song.rs @@ -140,7 +140,7 @@ pub mod status { } } -mod song_db { +pub mod song_db { use sqlx::Row; // TODO: Change first parameter of return value from string to a time type @@ -192,6 +192,51 @@ mod song_db { Err(_) => Err(sqlx::Error::RowNotFound), } } + + pub async fn get_song(pool: &sqlx::PgPool, id: &uuid::Uuid) -> Result { + let result = sqlx::query( + r#" + SELECT * FROM "song" WHERE id = $1 + "# + ) + .bind(id) + .fetch_one(pool) + .await + .map_err(|e| { + eprintln!("Error querying data: {:?}", e); + }); + + match result { + Ok(row) => { + let date_created_time: time::OffsetDateTime = row + .try_get("date_created") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(); + + Ok(icarus_models::song::Song { + id: row.try_get("id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + title: row.try_get("title").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + artist: row.try_get("artist").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + album_artist: row.try_get("album_artist").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + album: row.try_get("album").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + genre: row.try_get("genre").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + year: row.try_get("year").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + track: row.try_get("track").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + disc: row.try_get("disc").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + track_count: row.try_get("track_count").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + disc_count: row.try_get("disc_count").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + duration: row.try_get("duration").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + audio_type: row.try_get("audio_type").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + filename: row.try_get("filename").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + directory: row.try_get("directory").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + date_created: date_created_time.to_string(), + user_id: row.try_get("user_id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + data: Vec::new(), + }) + } + Err(_) => Err(sqlx::Error::RowNotFound) + } + } } mod song_queue { -- 2.47.3 From 6f403b11203744bf72d5524ad7c75681903db4d0 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 24 May 2025 18:16:19 -0400 Subject: [PATCH 05/12] Endpoint is available --- src/main.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main.rs b/src/main.rs index 6032046..067d4f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -101,6 +101,10 @@ pub mod init { crate::callers::endpoints::CREATESONG, post(crate::callers::song::endpoint::create_metadata), ) + .route( + crate::callers::endpoints::CREATECOVERART, + post(crate::callers::coverart::endpoint::create_coverart), + ) } pub async fn app() -> axum::Router { -- 2.47.3 From 32294b3c9416568b9b677a9493b3b69ada0b1a43 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 24 May 2025 18:46:38 -0400 Subject: [PATCH 06/12] Migration changes to song table --- migrations/20250420185217_init_migration.sql | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/migrations/20250420185217_init_migration.sql b/migrations/20250420185217_init_migration.sql index 09fde2f..6415f2a 100644 --- a/migrations/20250420185217_init_migration.sql +++ b/migrations/20250420185217_init_migration.sql @@ -38,10 +38,10 @@ CREATE TABLE IF NOT EXISTS "song" ( -- TODO: Address discrepancy of date and year at some point -- date TEXT NOT NULL, year INT NOT NULL, - track SMALLINT NOT NULL, - disc SMALLINT NOT NULL, - track_count SMALLINT NOT NULL, - disc_count SMALLINT NOT NULL, + track INT NOT NULL, + disc INT NOT NULL, + track_count INT NOT NULL, + disc_count INT NOT NULL, duration INT NOT NULL, audio_type TEXT NOT NULL, date_created timestamptz DEFAULT now(), -- 2.47.3 From b033b721242f8c7d52f71c2aa2bc3f66e5e93f1e Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 24 May 2025 18:46:51 -0400 Subject: [PATCH 07/12] some fixes --- src/callers/coverart.rs | 2 ++ src/callers/song.rs | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/src/callers/coverart.rs b/src/callers/coverart.rs index 11f7744..057187f 100644 --- a/src/callers/coverart.rs +++ b/src/callers/coverart.rs @@ -456,8 +456,10 @@ pub mod endpoint { match super::db::get_coverart_queue_data_with_id(&pool, &id).await { Ok(data) => { let song_id = payload.song_id; + eprintln!("One song_id {:?}", song_id); match crate::callers::song::song_db::get_song(&pool, &song_id).await { Ok(song) => { + eprintln!("Two"); let directory = crate::environment::get_root_directory().await.unwrap(); let dir = std::path::Path::new(&directory); diff --git a/src/callers/song.rs b/src/callers/song.rs index 9fe6b90..08d97b1 100644 --- a/src/callers/song.rs +++ b/src/callers/song.rs @@ -194,6 +194,7 @@ pub mod song_db { } pub async fn get_song(pool: &sqlx::PgPool, id: &uuid::Uuid) -> Result { + eprintln!("Fetching song"); let result = sqlx::query( r#" SELECT * FROM "song" WHERE id = $1 @@ -206,12 +207,16 @@ pub mod song_db { eprintln!("Error querying data: {:?}", e); }); + eprintln!("Result {:?}", result); + match result { Ok(row) => { + eprintln!("Row found {:?}", row); let date_created_time: time::OffsetDateTime = row .try_get("date_created") .map_err(|_e| sqlx::Error::RowNotFound) .unwrap(); + eprintln!("date_created {:?}", date_created_time); Ok(icarus_models::song::Song { id: row.try_get("id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), -- 2.47.3 From 795f74639741de14bc8b4ffc9f716f40c17f80b0 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 24 May 2025 18:47:00 -0400 Subject: [PATCH 08/12] Added test --- src/main.rs | 195 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) diff --git a/src/main.rs b/src/main.rs index 067d4f5..df8f496 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1312,4 +1312,199 @@ mod tests { let _ = db_mgr::drop_database(&tm_pool, &db_name).await; } + + #[tokio::test] + async fn test_create_coverart() { + let tm_pool = db_mgr::get_pool().await.unwrap(); + let db_name = db_mgr::generate_db_name().await; + + match db_mgr::create_database(&tm_pool, &db_name).await { + Ok(_) => { + println!("Success"); + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + } + + let pool = db_mgr::connect_to_db(&db_name).await.unwrap(); + db::migrations(&pool).await; + + let app = init::app(pool).await; + + // Send request + match song_queue_req(&app).await { + Ok(response) => { + let resp = + get_resp_data::(response).await; + assert_eq!(false, resp.data.is_empty(), "Should not be empty"); + assert_eq!(false, resp.data[0].is_nil(), "Should not be empty"); + let song_queue_id = resp.data[0]; + assert_eq!(false, song_queue_id.is_nil(), "Should not be empty"); + + match queue_metadata_req(&app, &resp.data[0]).await { + Ok(response) => { + let resp = + get_resp_data::(response) + .await; + assert_eq!(false, resp.data.is_empty(), "Should not be empty"); + + let id = resp.data[0]; + + match fetch_metadata_queue_req(&app, &id).await { + Ok(response) => { + let resp = get_resp_data::< + crate::callers::metadata::response::fetch_metadata::Response, + >(response) + .await; + assert_eq!(false, resp.data.is_empty(), "Data should not be empty"); + let song_q_id = resp.data[0].song_queue_id; + + match create_song_req(&app, &song_q_id).await { + Ok(response) => { + let resp = get_resp_data::(response).await; + assert_eq!( + false, + resp.data.is_empty(), + "No songs found, Response {:?}", + resp + ); + let song = &resp.data[0]; + let song_id = song.id; + assert_eq!( + false, + song_id.is_nil(), + "Song id should not be nil {:?}", + song + ); + + eprintln!("Song: {:?}", song); + + + match upload_coverart_queue_req(&app).await { + Ok(response) => { + let resp = + get_resp_data::(response) + .await; + assert_eq!(false, resp.data.is_empty(), "Should not be empty"); + let coverart_id = resp.data[0]; + assert_eq!(false, coverart_id.is_nil(), "Should not be empty"); + + match coverart_queue_song_queue_link_req(&app, &coverart_id, &song_queue_id) + .await + { + Ok(response) => { + let resp = get_resp_data::< + crate::callers::coverart::response::link::Response, + >(response) + .await; + assert_eq!(false, resp.data.is_empty(), "Should not be empty"); + let resp_coverart_id = resp.data[0].coverart_id; + let resp_song_queue_id = resp.data[0].song_queue_id; + + assert_eq!(false, resp_coverart_id.is_nil(), "Should not be empty"); + assert_eq!( + false, + resp_song_queue_id.is_nil(), + "Should not be empty" + ); + + let uri = format!( + "{}?id={}", + crate::callers::endpoints::QUEUECOVERART, + resp_coverart_id + ); + + match app + .clone() + .oneshot( + axum::http::Request::builder() + .method(axum::http::Method::GET) + .uri(uri) + .header( + axum::http::header::CONTENT_TYPE, + "application/json", + ) + .body(axum::body::Body::empty()) + .unwrap(), + ) + .await + { + Ok(response) => { + let resp = get_resp_data::< + crate::callers::coverart::response::fetch_coverart_no_data::Response, + >(response) + .await; + assert_eq!( + false, + resp.data.is_empty(), + "Should not be empty" + ); + + let payload = serde_json::json!({ + "song_id": song_id, + "coverart_queue_id": resp_coverart_id, + }); + + match app.clone().oneshot( + axum::http::Request::builder() + .method(axum::http::Method::POST) + .uri(crate::callers::endpoints::CREATECOVERART) + .header(axum::http::header::CONTENT_TYPE, "application/json") + .body(axum::body::Body::from(payload.to_string())) + .unwrap() + ).await { + Ok(response) => { + let resp = get_resp_data::< + crate::callers::coverart::response::create_coverart::Response, + >(response) + .await; + assert_eq!( + false, + resp.data.is_empty(), + "Should not be empty" + ); + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + } + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + } + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + } + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + } + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + } + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + } + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + } + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + }; + + let _ = db_mgr::drop_database(&tm_pool, &db_name).await; + } } -- 2.47.3 From 24666c29ffa975ca54f2a33ff1636efdc8bc365f Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 24 May 2025 18:55:21 -0400 Subject: [PATCH 09/12] Test refactor --- src/main.rs | 59 +++++++++++++++++------------------------------------ 1 file changed, 19 insertions(+), 40 deletions(-) diff --git a/src/main.rs b/src/main.rs index df8f496..3b16d9d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -395,6 +395,23 @@ mod tests { app.clone().oneshot(req).await } + async fn get_queued_coverart(app: &axum::Router, coverart_queue_id: &uuid::Uuid) -> Result { + let uri = format!( + "{}?id={}", + crate::callers::endpoints::QUEUECOVERART, + coverart_queue_id + ); + + let req = axum::http::Request::builder() + .method(axum::http::Method::GET) + .uri(uri) + .header(axum::http::header::CONTENT_TYPE, "application/json") + .body(axum::body::Body::empty()) + .unwrap(); + + app.clone().oneshot(req).await + } + pub async fn resp_to_bytes( response: axum::response::Response, ) -> Result { @@ -941,26 +958,7 @@ mod tests { "Should not be empty" ); - let uri = format!( - "{}?id={}", - crate::callers::endpoints::QUEUECOVERART, - resp_coverart_id - ); - - match app - .clone() - .oneshot( - axum::http::Request::builder() - .method(axum::http::Method::GET) - .uri(uri) - .header( - axum::http::header::CONTENT_TYPE, - "application/json", - ) - .body(axum::body::Body::empty()) - .unwrap(), - ) - .await + match get_queued_coverart(&app, &resp_coverart_id).await { Ok(response) => { let resp = get_resp_data::< @@ -1409,26 +1407,7 @@ mod tests { "Should not be empty" ); - let uri = format!( - "{}?id={}", - crate::callers::endpoints::QUEUECOVERART, - resp_coverart_id - ); - - match app - .clone() - .oneshot( - axum::http::Request::builder() - .method(axum::http::Method::GET) - .uri(uri) - .header( - axum::http::header::CONTENT_TYPE, - "application/json", - ) - .body(axum::body::Body::empty()) - .unwrap(), - ) - .await + match get_queued_coverart(&app, &resp_coverart_id).await { Ok(response) => { let resp = get_resp_data::< -- 2.47.3 From 2ab3ac7799411222995ca89d36dda959d4b0d8af Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 24 May 2025 18:55:53 -0400 Subject: [PATCH 10/12] Code formatting --- src/callers/coverart.rs | 22 ++++++--- src/callers/song.rs | 103 ++++++++++++++++++++++++++++++---------- src/main.rs | 64 ++++++++++++++++++------- 3 files changed, 140 insertions(+), 49 deletions(-) diff --git a/src/callers/coverart.rs b/src/callers/coverart.rs index 057187f..5f4ba52 100644 --- a/src/callers/coverart.rs +++ b/src/callers/coverart.rs @@ -34,7 +34,7 @@ pub mod request { #[derive(Debug, serde::Deserialize, serde::Serialize)] pub struct Request { pub song_id: uuid::Uuid, - pub coverart_queue_id: uuid::Uuid + pub coverart_queue_id: uuid::Uuid, } } } @@ -80,7 +80,7 @@ pub mod response { #[derive(Debug, Default, serde::Deserialize, serde::Serialize)] pub struct Response { pub message: String, - pub data: Vec + pub data: Vec, } } } @@ -250,7 +250,11 @@ pub mod db { pub mod cov_db { use sqlx::Row; - pub async fn create(pool: &sqlx::PgPool, coverart: &icarus_models::coverart::CoverArt, song_id: &uuid::Uuid) -> Result { + pub async fn create( + pool: &sqlx::PgPool, + coverart: &icarus_models::coverart::CoverArt, + song_id: &uuid::Uuid, + ) -> Result { let result = sqlx::query( r#" INSERT INTO "coverart" (title, path, song_id) VALUES($1, $2, $3) RETURNING id; @@ -448,8 +452,13 @@ pub mod endpoint { } } - pub async fn create_coverart(axum::Extension(pool): axum::Extension, - axum::Json(payload): axum::Json) -> (axum::http::StatusCode, axum::Json) { + pub async fn create_coverart( + axum::Extension(pool): axum::Extension, + axum::Json(payload): axum::Json, + ) -> ( + axum::http::StatusCode, + axum::Json, + ) { let mut response = super::response::create_coverart::Response::default(); let id = payload.coverart_queue_id; @@ -467,7 +476,8 @@ pub mod endpoint { let filename = format!("{}-coverart.jpeg", &song.filename[..8]); let save_path = dir.join(&filename); let path = String::from(save_path.to_str().unwrap()); - let mut coverart = icarus_models::coverart::init::init_coverart_only_path(path); + let mut coverart = + icarus_models::coverart::init::init_coverart_only_path(path); coverart.title = song.album.clone(); coverart.data = data; diff --git a/src/callers/song.rs b/src/callers/song.rs index 08d97b1..bd0a1e4 100644 --- a/src/callers/song.rs +++ b/src/callers/song.rs @@ -193,19 +193,22 @@ pub mod song_db { } } - pub async fn get_song(pool: &sqlx::PgPool, id: &uuid::Uuid) -> Result { + pub async fn get_song( + pool: &sqlx::PgPool, + id: &uuid::Uuid, + ) -> Result { eprintln!("Fetching song"); let result = sqlx::query( r#" SELECT * FROM "song" WHERE id = $1 - "# - ) - .bind(id) - .fetch_one(pool) - .await - .map_err(|e| { - eprintln!("Error querying data: {:?}", e); - }); + "#, + ) + .bind(id) + .fetch_one(pool) + .await + .map_err(|e| { + eprintln!("Error querying data: {:?}", e); + }); eprintln!("Result {:?}", result); @@ -219,27 +222,75 @@ pub mod song_db { eprintln!("date_created {:?}", date_created_time); Ok(icarus_models::song::Song { - id: row.try_get("id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - title: row.try_get("title").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - artist: row.try_get("artist").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - album_artist: row.try_get("album_artist").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - album: row.try_get("album").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - genre: row.try_get("genre").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - year: row.try_get("year").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - track: row.try_get("track").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - disc: row.try_get("disc").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - track_count: row.try_get("track_count").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - disc_count: row.try_get("disc_count").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - duration: row.try_get("duration").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - audio_type: row.try_get("audio_type").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - filename: row.try_get("filename").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - directory: row.try_get("directory").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + id: row + .try_get("id") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + title: row + .try_get("title") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + artist: row + .try_get("artist") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + album_artist: row + .try_get("album_artist") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + album: row + .try_get("album") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + genre: row + .try_get("genre") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + year: row + .try_get("year") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + track: row + .try_get("track") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + disc: row + .try_get("disc") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + track_count: row + .try_get("track_count") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + disc_count: row + .try_get("disc_count") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + duration: row + .try_get("duration") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + audio_type: row + .try_get("audio_type") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + filename: row + .try_get("filename") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + directory: row + .try_get("directory") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), date_created: date_created_time.to_string(), - user_id: row.try_get("user_id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + user_id: row + .try_get("user_id") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), data: Vec::new(), }) } - Err(_) => Err(sqlx::Error::RowNotFound) + Err(_) => Err(sqlx::Error::RowNotFound), } } } diff --git a/src/main.rs b/src/main.rs index 3b16d9d..bc1e04b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -104,7 +104,7 @@ pub mod init { .route( crate::callers::endpoints::CREATECOVERART, post(crate::callers::coverart::endpoint::create_coverart), - ) + ) } pub async fn app() -> axum::Router { @@ -395,7 +395,10 @@ mod tests { app.clone().oneshot(req).await } - async fn get_queued_coverart(app: &axum::Router, coverart_queue_id: &uuid::Uuid) -> Result { + async fn get_queued_coverart( + app: &axum::Router, + coverart_queue_id: &uuid::Uuid, + ) -> Result { let uri = format!( "{}?id={}", crate::callers::endpoints::QUEUECOVERART, @@ -958,8 +961,7 @@ mod tests { "Should not be empty" ); - match get_queued_coverart(&app, &resp_coverart_id).await - { + match get_queued_coverart(&app, &resp_coverart_id).await { Ok(response) => { let resp = get_resp_data::< crate::callers::coverart::response::fetch_coverart_no_data::Response, @@ -1378,36 +1380,64 @@ mod tests { eprintln!("Song: {:?}", song); - match upload_coverart_queue_req(&app).await { Ok(response) => { - let resp = - get_resp_data::(response) - .await; - assert_eq!(false, resp.data.is_empty(), "Should not be empty"); + let resp = get_resp_data::< + crate::callers::coverart::response::Response, + >( + response + ) + .await; + assert_eq!( + false, + resp.data.is_empty(), + "Should not be empty" + ); let coverart_id = resp.data[0]; - assert_eq!(false, coverart_id.is_nil(), "Should not be empty"); + assert_eq!( + false, + coverart_id.is_nil(), + "Should not be empty" + ); - match coverart_queue_song_queue_link_req(&app, &coverart_id, &song_queue_id) - .await + match coverart_queue_song_queue_link_req( + &app, + &coverart_id, + &song_queue_id, + ) + .await { Ok(response) => { let resp = get_resp_data::< crate::callers::coverart::response::link::Response, >(response) .await; - assert_eq!(false, resp.data.is_empty(), "Should not be empty"); - let resp_coverart_id = resp.data[0].coverart_id; - let resp_song_queue_id = resp.data[0].song_queue_id; + assert_eq!( + false, + resp.data.is_empty(), + "Should not be empty" + ); + let resp_coverart_id = + resp.data[0].coverart_id; + let resp_song_queue_id = + resp.data[0].song_queue_id; - assert_eq!(false, resp_coverart_id.is_nil(), "Should not be empty"); + assert_eq!( + false, + resp_coverart_id.is_nil(), + "Should not be empty" + ); assert_eq!( false, resp_song_queue_id.is_nil(), "Should not be empty" ); - match get_queued_coverart(&app, &resp_coverart_id).await + match get_queued_coverart( + &app, + &resp_coverart_id, + ) + .await { Ok(response) => { let resp = get_resp_data::< -- 2.47.3 From 0e4afa042ad84cf191856562899ea658ba21b2de Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 24 May 2025 18:56:49 -0400 Subject: [PATCH 11/12] Clippy warning fixes --- src/callers/coverart.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/callers/coverart.rs b/src/callers/coverart.rs index 5f4ba52..3b41814 100644 --- a/src/callers/coverart.rs +++ b/src/callers/coverart.rs @@ -262,7 +262,7 @@ pub mod cov_db { ) .bind(&coverart.title) .bind(&coverart.path) - .bind(&song_id) + .bind(song_id) .fetch_one(pool) .await .map_err(|e| { -- 2.47.3 From 9b2627b6162acb7746921644eeb744e4c960d1c4 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 24 May 2025 18:59:21 -0400 Subject: [PATCH 12/12] Code cleanup --- src/callers/coverart.rs | 2 -- src/callers/song.rs | 5 ----- 2 files changed, 7 deletions(-) diff --git a/src/callers/coverart.rs b/src/callers/coverart.rs index 3b41814..03f9102 100644 --- a/src/callers/coverart.rs +++ b/src/callers/coverart.rs @@ -465,10 +465,8 @@ pub mod endpoint { match super::db::get_coverart_queue_data_with_id(&pool, &id).await { Ok(data) => { let song_id = payload.song_id; - eprintln!("One song_id {:?}", song_id); match crate::callers::song::song_db::get_song(&pool, &song_id).await { Ok(song) => { - eprintln!("Two"); let directory = crate::environment::get_root_directory().await.unwrap(); let dir = std::path::Path::new(&directory); diff --git a/src/callers/song.rs b/src/callers/song.rs index bd0a1e4..93313f8 100644 --- a/src/callers/song.rs +++ b/src/callers/song.rs @@ -197,7 +197,6 @@ pub mod song_db { pool: &sqlx::PgPool, id: &uuid::Uuid, ) -> Result { - eprintln!("Fetching song"); let result = sqlx::query( r#" SELECT * FROM "song" WHERE id = $1 @@ -210,16 +209,12 @@ pub mod song_db { eprintln!("Error querying data: {:?}", e); }); - eprintln!("Result {:?}", result); - match result { Ok(row) => { - eprintln!("Row found {:?}", row); let date_created_time: time::OffsetDateTime = row .try_get("date_created") .map_err(|_e| sqlx::Error::RowNotFound) .unwrap(); - eprintln!("date_created {:?}", date_created_time); Ok(icarus_models::song::Song { id: row -- 2.47.3