From ad037472836a32248a9d173bb6ea96e20548dd3a Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 26 Jul 2025 12:27:40 -0400 Subject: [PATCH 1/7] Added initial code to get coverart endpoint --- src/callers/coverart.rs | 72 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/callers/coverart.rs b/src/callers/coverart.rs index 8bbcd49..2d1a4bf 100644 --- a/src/callers/coverart.rs +++ b/src/callers/coverart.rs @@ -45,6 +45,13 @@ pub mod request { pub coverart_queue_id: uuid::Uuid, } } + + pub mod get_coverart { + #[derive(Debug, serde::Deserialize, serde::Serialize)] + pub struct Params { + pub id: Option, + } + } } pub mod response { @@ -99,6 +106,14 @@ pub mod response { pub data: Vec, } } + + pub mod get_coverart { + #[derive(Debug, Default, serde::Deserialize, serde::Serialize)] + pub struct Response { + pub message: String, + pub data: Vec + } + } } pub mod db { @@ -321,6 +336,36 @@ pub mod cov_db { Err(_err) => Err(sqlx::Error::RowNotFound), } } + + pub async fn get_coverart(pool: &sqlx::PgPool, id: &uuid::Uuid) -> Result { + let result = sqlx::query( + r#" + SELECT id, title, path, song_id FROM "coverart" WHERE id = $1; + "#, + ) + .bind(id) + .fetch_one(pool) + .await + .map_err(|e| { + eprintln!("Error querying data: {e:?}"); + }); + + match result { + Ok(row) => Ok(icarus_models::coverart::CoverArt { + id: row + .try_get("id") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + title: row + .try_get("title") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + path: row.try_get("path").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + song_id: row.try_get("song_id").map_err(|_e| sqlx::Error::RowNotFound).unwrap() + }), + Err(_) => Err(sqlx::Error::RowNotFound), + } + } } pub mod endpoint { @@ -560,4 +605,31 @@ pub mod endpoint { } } } + + pub async fn get_coverart( + axum::Extension(pool): axum::Extension, + axum::extract::Query(params): axum::extract::Query + ) -> (axum::http::StatusCode, axum::Json) { + let mut response = super::response::get_coverart::Response::default(); + + match params.id { + Some(id) => { + match super::cov_db::get_coverart(&pool, &id).await { + Ok(coverart) => { + response.data.push(coverart); + response.message = String::from(super::super::response::SUCCESSFUL); + (axum::http::StatusCode::OK, axum::Json(response)) + } + Err(err) => { + response.message = err.to_string(); + (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) + } + } + } + None => { + response.message = String::from("Invalid parameters"); + (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) + } + } + } } -- 2.47.3 From 7c40617f570770a8f22b31a6e42429db23483c40 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 26 Jul 2025 12:37:38 -0400 Subject: [PATCH 2/7] Test migration cleanup --- test_migrations/20250725213944_init.sql | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test_migrations/20250725213944_init.sql b/test_migrations/20250725213944_init.sql index 0c78fc4..358829e 100644 --- a/test_migrations/20250725213944_init.sql +++ b/test_migrations/20250725213944_init.sql @@ -56,7 +56,3 @@ CREATE TABLE IF NOT EXISTS "coverart" ( path TEXT NOT NULL, song_id UUID NOT NULL ); - --- Might not to disable constraints on fields --- INSERT INTO "song" (id, title, artist, album_artist, album, genre, year, track, disc, track_count, disc_count, duration, audio_type, date_created, filename, directory, user_id) VALUES('44cf7940-34ff-489f-9124-d0ec90a55af9', 'Hypocrite Like The Rest', 'Kuoth', 'Kuoth', 'I', 'Alternative Hip-Hop', 2020, 1, 1, 9, 1, 139, 'flac', '2020-01-01 13:00:00-05', 'track01.flac', 'tests/I', '47491f9b-725a-4ba4-b9a5-711e1be46670'); --- Re-enable the constraints on the fields -- 2.47.3 From fd7a88b6d0d7a4ff383f2a9b8af6d5e28afccb00 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 26 Jul 2025 12:38:12 -0400 Subject: [PATCH 3/7] Updated icarus_models --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 306c757..1ae9480 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -793,8 +793,8 @@ dependencies = [ [[package]] name = "icarus_models" -version = "0.4.5" -source = "git+ssh://git@git.kundeng.us/phoenix/icarus_models.git?tag=v0.4.5-devel-655d05dabb-111#655d05dabbdadb9b28940564a1eb82470aa4f166" +version = "0.5.1" +source = "git+ssh://git@git.kundeng.us/phoenix/icarus_models.git?tag=v0.5.1-devel-1c5de9dc26-111#1c5de9dc26099ac5f21e1dc7a1f7d0dbb892b34b" dependencies = [ "rand 0.9.1", "serde", diff --git a/Cargo.toml b/Cargo.toml index 80dff0f..1911308 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ uuid = { version = "1.17.0", features = ["v4", "serde"] } sqlx = { version = "0.8.6", features = ["postgres", "runtime-tokio-native-tls", "time", "uuid"] } time = { version = "0.3.41", features = ["formatting", "macros", "parsing", "serde"] } icarus_meta = { git = "ssh://git@git.kundeng.us/phoenix/icarus_meta.git", tag = "v0.3.0-devel-f4b71de969-680" } -icarus_models = { git = "ssh://git@git.kundeng.us/phoenix/icarus_models.git", tag = "v0.4.5-devel-655d05dabb-111" } +icarus_models = { git = "ssh://git@git.kundeng.us/phoenix/icarus_models.git", tag = "v0.5.1-devel-1c5de9dc26-111" } icarus_envy = { git = "ssh://git@git.kundeng.us/phoenix/icarus_envy.git", tag = "v0.3.0-devel-d73fba9899-006" } [dev-dependencies] -- 2.47.3 From d796cbcc16473e220536ae3604d3fb1eb50e351f Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 26 Jul 2025 12:40:13 -0400 Subject: [PATCH 4/7] Made endpoint evailable --- src/callers/coverart.rs | 1 + src/callers/mod.rs | 1 + src/main.rs | 4 ++++ 3 files changed, 6 insertions(+) diff --git a/src/callers/coverart.rs b/src/callers/coverart.rs index 2d1a4bf..08b9f43 100644 --- a/src/callers/coverart.rs +++ b/src/callers/coverart.rs @@ -361,6 +361,7 @@ pub mod cov_db { .map_err(|_e| sqlx::Error::RowNotFound) .unwrap(), path: row.try_get("path").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + data: Vec::new(), song_id: row.try_get("song_id").map_err(|_e| sqlx::Error::RowNotFound).unwrap() }), Err(_) => Err(sqlx::Error::RowNotFound), diff --git a/src/callers/mod.rs b/src/callers/mod.rs index 6e31042..d81789b 100644 --- a/src/callers/mod.rs +++ b/src/callers/mod.rs @@ -18,6 +18,7 @@ pub mod endpoints { pub const CREATESONG: &str = "/api/v2/song"; pub const GETSONGS: &str = "/api/v2/song"; pub const CREATECOVERART: &str = "/api/v2/coverart"; + pub const GETCOVERART: &str = "/api/v2/coverart"; } pub mod response { diff --git a/src/main.rs b/src/main.rs index a122e09..c4fe0e4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -119,6 +119,10 @@ pub mod init { crate::callers::endpoints::GETSONGS, get(crate::callers::song::endpoint::get_songs), ) + .route( + crate::callers::endpoints::GETCOVERART, + get(crate::callers::coverart::endpoint::get_coverart) + ) } pub async fn app() -> axum::Router { -- 2.47.3 From 26444de6e8d7b73e545d204cfb784fbd1cc75a8c Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 26 Jul 2025 14:05:14 -0400 Subject: [PATCH 5/7] Added test --- src/main.rs | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/src/main.rs b/src/main.rs index c4fe0e4..3320c30 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1881,5 +1881,67 @@ mod tests { let _ = super::db_mgr::drop_database(&tm_pool, &db_name).await; } + + #[tokio::test] + async fn test_get_coverart() { + let tm_pool = super::db_mgr::get_pool().await.unwrap(); + let db_name = super::db_mgr::generate_db_name().await; + + match super::db_mgr::create_database(&tm_pool, &db_name).await { + Ok(_) => { + println!("Success"); + } + Err(err) => { + assert!(false, "Error: {:?}", err); + } + } + + let pool = super::db_mgr::connect_to_db(&db_name).await.unwrap(); + super::db_mgr::migrations(&pool).await; + + let app = super::init::app(pool).await; + + let mut id = uuid::Uuid::nil(); + + match uuid::Uuid::parse_str("996122cd-5ae9-4013-9934-60768d3006ed") { + Ok(val) => { + id = val; + } + Err(err) => { + assert!(false, "Error: {err:?}"); + } + }; + + let uri = format!("{}?id={id}", crate::callers::endpoints::GETCOVERART); + + 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 = super::get_resp_data::< + crate::callers::coverart::response::get_coverart::Response, + >(response) + .await; + assert_eq!(false, resp.data.is_empty(), "Should not be empty"); + + let coverart = resp.data[0].clone(); + assert_eq!(id, coverart.id, "Id does not match {coverart:?}"); + } + Err(err) => { + assert!(false, "Error: {err:?}"); + } + } + + let _ = super::db_mgr::drop_database(&tm_pool, &db_name).await; + } } } -- 2.47.3 From 4dd9a3ba16a55a3c5135672a1d1eeb17ccf9b49a Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 26 Jul 2025 14:06:34 -0400 Subject: [PATCH 6/7] Version bump --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1ae9480..be020e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -752,7 +752,7 @@ dependencies = [ [[package]] name = "icarus" -version = "0.1.94" +version = "0.1.95" dependencies = [ "axum", "common-multipart-rfc7578", diff --git a/Cargo.toml b/Cargo.toml index 1911308..fd0eb73 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "icarus" -version = "0.1.94" +version = "0.1.95" edition = "2024" rust-version = "1.88" -- 2.47.3 From 84c0bc2d08b011ba96e04ccf3fdb1d2628ad4cc1 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Sat, 26 Jul 2025 14:08:06 -0400 Subject: [PATCH 7/7] Code formatting --- src/callers/coverart.rs | 46 +++++++++++++++++++++++++---------------- src/main.rs | 6 +++--- 2 files changed, 31 insertions(+), 21 deletions(-) diff --git a/src/callers/coverart.rs b/src/callers/coverart.rs index 08b9f43..31f8045 100644 --- a/src/callers/coverart.rs +++ b/src/callers/coverart.rs @@ -111,7 +111,7 @@ pub mod response { #[derive(Debug, Default, serde::Deserialize, serde::Serialize)] pub struct Response { pub message: String, - pub data: Vec + pub data: Vec, } } } @@ -337,7 +337,10 @@ pub mod cov_db { } } - pub async fn get_coverart(pool: &sqlx::PgPool, id: &uuid::Uuid) -> Result { + pub async fn get_coverart( + pool: &sqlx::PgPool, + id: &uuid::Uuid, + ) -> Result { let result = sqlx::query( r#" SELECT id, title, path, song_id FROM "coverart" WHERE id = $1; @@ -360,9 +363,15 @@ pub mod cov_db { .try_get("title") .map_err(|_e| sqlx::Error::RowNotFound) .unwrap(), - path: row.try_get("path").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + path: row + .try_get("path") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), data: Vec::new(), - song_id: row.try_get("song_id").map_err(|_e| sqlx::Error::RowNotFound).unwrap() + song_id: row + .try_get("song_id") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), }), Err(_) => Err(sqlx::Error::RowNotFound), } @@ -609,24 +618,25 @@ pub mod endpoint { pub async fn get_coverart( axum::Extension(pool): axum::Extension, - axum::extract::Query(params): axum::extract::Query - ) -> (axum::http::StatusCode, axum::Json) { + axum::extract::Query(params): axum::extract::Query, + ) -> ( + axum::http::StatusCode, + axum::Json, + ) { let mut response = super::response::get_coverart::Response::default(); match params.id { - Some(id) => { - match super::cov_db::get_coverart(&pool, &id).await { - Ok(coverart) => { - response.data.push(coverart); - response.message = String::from(super::super::response::SUCCESSFUL); - (axum::http::StatusCode::OK, axum::Json(response)) - } - Err(err) => { - response.message = err.to_string(); - (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) - } + Some(id) => match super::cov_db::get_coverart(&pool, &id).await { + Ok(coverart) => { + response.data.push(coverart); + response.message = String::from(super::super::response::SUCCESSFUL); + (axum::http::StatusCode::OK, axum::Json(response)) } - } + Err(err) => { + response.message = err.to_string(); + (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) + } + }, None => { response.message = String::from("Invalid parameters"); (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) diff --git a/src/main.rs b/src/main.rs index 3320c30..4e8798e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -121,8 +121,8 @@ pub mod init { ) .route( crate::callers::endpoints::GETCOVERART, - get(crate::callers::coverart::endpoint::get_coverart) - ) + get(crate::callers::coverart::endpoint::get_coverart), + ) } pub async fn app() -> axum::Router { @@ -1902,7 +1902,7 @@ mod tests { let app = super::init::app(pool).await; let mut id = uuid::Uuid::nil(); - + match uuid::Uuid::parse_str("996122cd-5ae9-4013-9934-60768d3006ed") { Ok(val) => { id = val; -- 2.47.3