From 067afa3488875be31ef4d3b4ed597f5cac58299d Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Wed, 21 May 2025 18:32:51 -0400 Subject: [PATCH 1/6] Added endpoint --- src/callers/coverart.rs | 115 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 114 insertions(+), 1 deletion(-) diff --git a/src/callers/coverart.rs b/src/callers/coverart.rs index b0d760d..b9333fa 100644 --- a/src/callers/coverart.rs +++ b/src/callers/coverart.rs @@ -1,3 +1,9 @@ +#[derive(Debug, Default, serde::Deserialize, serde::Serialize)] +pub struct CoverArtQueue { + pub id: uuid::Uuid, + pub song_queue_id: uuid::Uuid, +} + pub mod request { pub mod link { @@ -7,6 +13,14 @@ pub mod request { pub song_queue_id: uuid::Uuid, } } + + pub mod fetch_coverart_no_data { + #[derive(Debug, Default, serde::Deserialize, serde::Serialize)] + pub struct Params { + pub id: Option, + pub song_queue_id: Option, + } + } } pub mod response { @@ -29,11 +43,20 @@ pub mod response { pub data: Vec, } } + + pub mod fetch_coverart_no_data { + #[derive(Debug, Default, serde::Deserialize, serde::Serialize)] + pub struct Response { + pub message: String, + pub data: Vec, + } + } } -mod db { +pub mod db { use sqlx::Row; + pub async fn insert(pool: &sqlx::PgPool, data: &Vec) -> Result { let result = sqlx::query( r#" @@ -79,6 +102,54 @@ mod db { Err(_err) => Err(sqlx::Error::RowNotFound), } } + + pub async fn get_coverart_queue_with_id(pool: &sqlx::PgPool, id: &uuid::Uuid) -> Result { + let result = sqlx::query( + r#" + SELECT id, song_queue_id FROM "coverartQueue" WHERE id = $1 RETURNING id, song_queue_id; + "# + ) + .bind(id) + .fetch_one(pool) + .await + .map_err(|e| { + eprintln!("Error querying data: {:?}", e); + }); + + match result { + Ok(row) => { + Ok(super::CoverArtQueue { + id: row.try_get("id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + song_queue_id: row.try_get("song_queue_id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + }) + } + Err(_) => Err(sqlx::Error::RowNotFound) + } + } + + pub async fn get_coverart_queue_with_song_queue_id(pool: &sqlx::PgPool, song_queue_id: &uuid::Uuid) -> Result { + let result = sqlx::query( + r#" + SELECT id, song_queue_id FROM "coverartQueue" WHERE song_queue_id = $1 RETURNING id, song_queue_id; + "# + ) + .bind(song_queue_id) + .fetch_one(pool) + .await + .map_err(|e| { + eprintln!("Error querying data: {:?}", e); + }); + + match result { + Ok(row) => { + Ok(super::CoverArtQueue { + id: row.try_get("id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + song_queue_id: row.try_get("song_queue_id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + }) + } + Err(_) => Err(sqlx::Error::RowNotFound) + } + } } pub mod endpoint { @@ -153,4 +224,46 @@ pub mod endpoint { } } } + + pub async fn fetch_coverart_no_data( + axum::Extension(pool): axum::Extension, + axum::extract::Query(params): axum::extract::Query, + ) -> (axum::http::StatusCode, axum::Json) { + let mut response = super::response::fetch_coverart_no_data::Response::default(); + + match params.id { + Some(id) => { + match super::db::get_coverart_queue_with_id(&pool, &id).await { + Ok(cover_art_queue) => { + response.message = String::from("Successful"); + response.data.push(cover_art_queue); + (axum::http::StatusCode::OK, axum::Json(response)) + } + Err(err) => { + response.message = err.to_string(); + (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) + } + } + } + _ => match params.song_queue_id { + Some(song_queue_id) => { + match super::db::get_coverart_queue_with_song_queue_id(&pool, &song_queue_id).await { + Ok(cover_art_queue) => { + response.message = String::from("Successful"); + response.data.push(cover_art_queue); + (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("No valid id provided"); + (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) + } + } + } + } } -- 2.47.3 From e92d970b4ecc266263afa9423bf41ebb7e97b9fd Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Wed, 21 May 2025 18:33:11 -0400 Subject: [PATCH 2/6] Endpoint is now accessible --- src/main.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main.rs b/src/main.rs index c68d9f0..e0d7eae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -93,6 +93,10 @@ pub mod init { crate::callers::endpoints::QUEUECOVERART, post(crate::callers::coverart::endpoint::queue), ) + .route( + crate::callers::endpoints::QUEUECOVERART, + get(crate::callers::coverart::endpoint::fetch_coverart_no_data) + ) .route( crate::callers::endpoints::QUEUECOVERARTLINK, patch(crate::callers::coverart::endpoint::link), -- 2.47.3 From 169c403556f9be9194ea72019260f96a8b10bfd8 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Wed, 21 May 2025 18:43:51 -0400 Subject: [PATCH 3/6] Moved request to its own function in tests --- src/main.rs | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/main.rs b/src/main.rs index e0d7eae..993b5b5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -302,6 +302,22 @@ mod tests { app.clone().oneshot(req).await } + async fn coverart_queue_song_queue_link_req(app: &axum::Router, coverart_id: &uuid::Uuid, song_queue_id: &uuid::Uuid) -> Result { + let payload = serde_json::json!( + { + "song_queue_id": song_queue_id, + "coverart_id" : coverart_id, + }); + let req = axum::http::Request::builder() + .method(axum::http::Method::PATCH) + .uri(crate::callers::endpoints::QUEUECOVERARTLINK) + .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 { @@ -702,23 +718,7 @@ mod tests { let coverart_id = resp.data[0]; assert_eq!(false, coverart_id.is_nil(), "Should not be empty"); - let payload = serde_json::json!( - { - "song_queue_id": song_queue_id, - "coverart_id" : coverart_id, - }); - - match app - .clone() - .oneshot( - axum::http::Request::builder() - .method(axum::http::Method::PATCH) - .uri(crate::callers::endpoints::QUEUECOVERARTLINK) - .header(axum::http::header::CONTENT_TYPE, "application/json") - .body(axum::body::Body::from(payload.to_string())) - .unwrap(), - ) - .await + match coverart_queue_song_queue_link_req(&app, &coverart_id, &song_queue_id).await { Ok(response) => { let resp = get_resp_data::< -- 2.47.3 From 2a62ba02ec66267ead5fcf1aaed9a0a1ae44b2ee Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Wed, 21 May 2025 19:03:22 -0400 Subject: [PATCH 4/6] Added test, but running into issues --- src/callers/coverart.rs | 5 ++- src/main.rs | 95 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 98 insertions(+), 2 deletions(-) diff --git a/src/callers/coverart.rs b/src/callers/coverart.rs index b9333fa..fe62409 100644 --- a/src/callers/coverart.rs +++ b/src/callers/coverart.rs @@ -106,7 +106,7 @@ pub mod db { pub async fn get_coverart_queue_with_id(pool: &sqlx::PgPool, id: &uuid::Uuid) -> Result { let result = sqlx::query( r#" - SELECT id, song_queue_id FROM "coverartQueue" WHERE id = $1 RETURNING id, song_queue_id; + SELECT id, song_queue_id FROM "coverartQueue" WHERE id = $1 RETURNING id; "# ) .bind(id) @@ -120,7 +120,8 @@ pub mod db { Ok(row) => { Ok(super::CoverArtQueue { id: row.try_get("id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - song_queue_id: row.try_get("song_queue_id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + // song_queue_id: row.try_get("song_queue_id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), + song_queue_id: uuid::Uuid::nil(), }) } Err(_) => Err(sqlx::Error::RowNotFound) diff --git a/src/main.rs b/src/main.rs index 993b5b5..a510eb9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -842,4 +842,99 @@ mod tests { let _ = db_mgr::drop_database(&tm_pool, &db_name).await; } + + #[tokio::test] + async fn test_fetch_coverart_queue_without_data() { + 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; + + 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"); + let song_queue_id = resp.data[0]; + assert_eq!(false, song_queue_id.is_nil(), "Should not be empty"); + + // Send request + 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"); + } + 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 dbb6a6068294a9ce3860c457498201f16c00ec99 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Wed, 21 May 2025 19:11:57 -0400 Subject: [PATCH 5/6] Fixing code causing test to fail --- src/callers/coverart.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/callers/coverart.rs b/src/callers/coverart.rs index fe62409..d31ecdc 100644 --- a/src/callers/coverart.rs +++ b/src/callers/coverart.rs @@ -106,22 +106,21 @@ pub mod db { pub async fn get_coverart_queue_with_id(pool: &sqlx::PgPool, id: &uuid::Uuid) -> Result { let result = sqlx::query( r#" - SELECT id, song_queue_id FROM "coverartQueue" WHERE id = $1 RETURNING id; + SELECT id, song_queue_id FROM "coverartQueue" WHERE id = $1; "# ) .bind(id) .fetch_one(pool) .await .map_err(|e| { - eprintln!("Error querying data: {:?}", e); + eprintln!("Error querying data: {:?}", e); }); match result { Ok(row) => { Ok(super::CoverArtQueue { id: row.try_get("id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - // song_queue_id: row.try_get("song_queue_id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - song_queue_id: uuid::Uuid::nil(), + song_queue_id: row.try_get("song_queue_id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), }) } Err(_) => Err(sqlx::Error::RowNotFound) @@ -131,7 +130,7 @@ pub mod db { pub async fn get_coverart_queue_with_song_queue_id(pool: &sqlx::PgPool, song_queue_id: &uuid::Uuid) -> Result { let result = sqlx::query( r#" - SELECT id, song_queue_id FROM "coverartQueue" WHERE song_queue_id = $1 RETURNING id, song_queue_id; + SELECT id, song_queue_id FROM "coverartQueue" WHERE song_queue_id = $1; "# ) .bind(song_queue_id) -- 2.47.3 From 08545221359ae718f2e1d4335dda1b7749324995 Mon Sep 17 00:00:00 2001 From: kdeng00 Date: Wed, 21 May 2025 19:15:33 -0400 Subject: [PATCH 6/6] Code formatting --- src/callers/coverart.rs | 116 +++++++++++++++++++++++----------------- src/main.rs | 61 ++++++++++++++------- 2 files changed, 108 insertions(+), 69 deletions(-) diff --git a/src/callers/coverart.rs b/src/callers/coverart.rs index d31ecdc..e2c918c 100644 --- a/src/callers/coverart.rs +++ b/src/callers/coverart.rs @@ -56,7 +56,6 @@ pub mod response { pub mod db { use sqlx::Row; - pub async fn insert(pool: &sqlx::PgPool, data: &Vec) -> Result { let result = sqlx::query( r#" @@ -103,51 +102,65 @@ pub mod db { } } - pub async fn get_coverart_queue_with_id(pool: &sqlx::PgPool, id: &uuid::Uuid) -> Result { + pub async fn get_coverart_queue_with_id( + pool: &sqlx::PgPool, + id: &uuid::Uuid, + ) -> Result { let result = sqlx::query( r#" SELECT id, song_queue_id FROM "coverartQueue" 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); + }); match result { - Ok(row) => { - Ok(super::CoverArtQueue { - id: row.try_get("id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - song_queue_id: row.try_get("song_queue_id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - }) - } - Err(_) => Err(sqlx::Error::RowNotFound) + Ok(row) => Ok(super::CoverArtQueue { + id: row + .try_get("id") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + song_queue_id: row + .try_get("song_queue_id") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + }), + Err(_) => Err(sqlx::Error::RowNotFound), } } - pub async fn get_coverart_queue_with_song_queue_id(pool: &sqlx::PgPool, song_queue_id: &uuid::Uuid) -> Result { + pub async fn get_coverart_queue_with_song_queue_id( + pool: &sqlx::PgPool, + song_queue_id: &uuid::Uuid, + ) -> Result { let result = sqlx::query( r#" SELECT id, song_queue_id FROM "coverartQueue" WHERE song_queue_id = $1; - "# - ) - .bind(song_queue_id) - .fetch_one(pool) - .await - .map_err(|e| { - eprintln!("Error querying data: {:?}", e); - }); + "#, + ) + .bind(song_queue_id) + .fetch_one(pool) + .await + .map_err(|e| { + eprintln!("Error querying data: {:?}", e); + }); match result { - Ok(row) => { - Ok(super::CoverArtQueue { - id: row.try_get("id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - song_queue_id: row.try_get("song_queue_id").map_err(|_e| sqlx::Error::RowNotFound).unwrap(), - }) - } - Err(_) => Err(sqlx::Error::RowNotFound) + Ok(row) => Ok(super::CoverArtQueue { + id: row + .try_get("id") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + song_queue_id: row + .try_get("song_queue_id") + .map_err(|_e| sqlx::Error::RowNotFound) + .unwrap(), + }), + Err(_) => Err(sqlx::Error::RowNotFound), } } } @@ -227,27 +240,32 @@ pub mod endpoint { pub async fn fetch_coverart_no_data( axum::Extension(pool): axum::Extension, - axum::extract::Query(params): axum::extract::Query, - ) -> (axum::http::StatusCode, axum::Json) { + axum::extract::Query(params): axum::extract::Query< + super::request::fetch_coverart_no_data::Params, + >, + ) -> ( + axum::http::StatusCode, + axum::Json, + ) { let mut response = super::response::fetch_coverart_no_data::Response::default(); match params.id { - Some(id) => { - match super::db::get_coverart_queue_with_id(&pool, &id).await { - Ok(cover_art_queue) => { - response.message = String::from("Successful"); - response.data.push(cover_art_queue); - (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::db::get_coverart_queue_with_id(&pool, &id).await { + Ok(cover_art_queue) => { + response.message = String::from("Successful"); + response.data.push(cover_art_queue); + (axum::http::StatusCode::OK, axum::Json(response)) } - } + Err(err) => { + response.message = err.to_string(); + (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) + } + }, _ => match params.song_queue_id { Some(song_queue_id) => { - match super::db::get_coverart_queue_with_song_queue_id(&pool, &song_queue_id).await { + match super::db::get_coverart_queue_with_song_queue_id(&pool, &song_queue_id) + .await + { Ok(cover_art_queue) => { response.message = String::from("Successful"); response.data.push(cover_art_queue); @@ -263,7 +281,7 @@ pub mod endpoint { response.message = String::from("No valid id provided"); (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)) } - } + }, } } } diff --git a/src/main.rs b/src/main.rs index a510eb9..67feca9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -95,8 +95,8 @@ pub mod init { ) .route( crate::callers::endpoints::QUEUECOVERART, - get(crate::callers::coverart::endpoint::fetch_coverart_no_data) - ) + get(crate::callers::coverart::endpoint::fetch_coverart_no_data), + ) .route( crate::callers::endpoints::QUEUECOVERARTLINK, patch(crate::callers::coverart::endpoint::link), @@ -302,18 +302,22 @@ mod tests { app.clone().oneshot(req).await } - async fn coverart_queue_song_queue_link_req(app: &axum::Router, coverart_id: &uuid::Uuid, song_queue_id: &uuid::Uuid) -> Result { + async fn coverart_queue_song_queue_link_req( + app: &axum::Router, + coverart_id: &uuid::Uuid, + song_queue_id: &uuid::Uuid, + ) -> Result { let payload = serde_json::json!( { "song_queue_id": song_queue_id, "coverart_id" : coverart_id, }); let req = axum::http::Request::builder() - .method(axum::http::Method::PATCH) - .uri(crate::callers::endpoints::QUEUECOVERARTLINK) - .header(axum::http::header::CONTENT_TYPE, "application/json") - .body(axum::body::Body::from(payload.to_string())) - .unwrap(); + .method(axum::http::Method::PATCH) + .uri(crate::callers::endpoints::QUEUECOVERARTLINK) + .header(axum::http::header::CONTENT_TYPE, "application/json") + .body(axum::body::Body::from(payload.to_string())) + .unwrap(); app.clone().oneshot(req).await } @@ -718,7 +722,8 @@ mod tests { 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 + match coverart_queue_song_queue_link_req(&app, &coverart_id, &song_queue_id) + .await { Ok(response) => { let resp = get_resp_data::< @@ -880,7 +885,8 @@ mod tests { 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 + match coverart_queue_song_queue_link_req(&app, &coverart_id, &song_queue_id) + .await { Ok(response) => { let resp = get_resp_data::< @@ -898,22 +904,37 @@ mod tests { "Should not be empty" ); - let uri = format!("{}?id={}", crate::callers::endpoints::QUEUECOVERART, resp_coverart_id); + 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 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"); + assert_eq!( + false, + resp.data.is_empty(), + "Should not be empty" + ); } Err(err) => { assert!(false, "Error: {:?}", err); -- 2.47.3