From 7227a260a43876063e7eea846e3d015819439078 Mon Sep 17 00:00:00 2001 From: phoenix Date: Thu, 18 Jun 2026 13:42:09 -0400 Subject: [PATCH 01/10] Adding repo::scheduling module --- src/repo/scheduling.rs | 73 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+) diff --git a/src/repo/scheduling.rs b/src/repo/scheduling.rs index b03e93c..16baae5 100644 --- a/src/repo/scheduling.rs +++ b/src/repo/scheduling.rs @@ -25,3 +25,76 @@ pub async fn insert( Err(_) => Err(sqlx::Error::RowNotFound), } } + +pub async fn get( + pool: &sqlx::PgPool, + id: &uuid::Uuid, +) -> Result { + match sqlx::query( + r#" + SELECT id, scheduled, created, status, user_id FROM "scheduled_messages" + WHERE + id = $1; + "#, + ) + .bind(id) + .fetch_one(pool) + .await + { + Ok(row) => { + let id: uuid::Uuid = row.try_get("id")?; + let scheduled: time::OffsetDateTime = row.try_get("scheduled")?; + let status: String = row.try_get("status")?; + let created: time::OffsetDateTime = row.try_get("created")?; + let user_id: uuid::Uuid = row.try_get("user_id")?; + Ok(textsender_models::message::scheduling::ScheduledMessage { + id, + scheduled: Some(scheduled), + created: Some(created), + status, + user_id, + }) + } + Err(_) => Err(sqlx::Error::RowNotFound), + } +} + +pub async fn get_with_user_id( + pool: &sqlx::PgPool, + user_id: &uuid::Uuid, +) -> Result, sqlx::Error> { + match sqlx::query( + r#" + SELECT id, scheduled, created, status, user_id FROM "scheduled_messages" + WHERE + user_id = $1; + "#, + ) + .bind(user_id) + .fetch_all(pool) + .await + { + Ok(rows) => { + let mut messages: Vec = Vec::new(); + for row in rows { + let id: uuid::Uuid = row.try_get("id")?; + let scheduled: time::OffsetDateTime = row.try_get("scheduled")?; + let status: String = row.try_get("status")?; + let created: time::OffsetDateTime = row.try_get("created")?; + let user_id: uuid::Uuid = row.try_get("user_id")?; + + let message = textsender_models::message::scheduling::ScheduledMessage { + id, + scheduled: Some(scheduled), + created: Some(created), + status, + user_id, + }; + messages.push(message); + } + + Ok(messages) + } + Err(_) => Err(sqlx::Error::RowNotFound), + } +} -- 2.47.3 From 196b9aa027e2b40d3c9331dd0f2646a22f3e18ef Mon Sep 17 00:00:00 2001 From: phoenix Date: Thu, 18 Jun 2026 13:52:03 -0400 Subject: [PATCH 02/10] Added code to get scheduled message --- src/caller/message/scheduling.rs | 71 ++++++++++++++++++++++++++++++++ src/caller/mod.rs | 2 + 2 files changed, 73 insertions(+) diff --git a/src/caller/message/scheduling.rs b/src/caller/message/scheduling.rs index de9f85e..10b2e7c 100644 --- a/src/caller/message/scheduling.rs +++ b/src/caller/message/scheduling.rs @@ -15,6 +15,12 @@ pub mod request { self.scheduled.is_some() || !self.status.is_empty() || !self.user_id.is_nil() } } + + #[derive(Debug, Default, serde::Deserialize, serde::Serialize, utoipa::ToSchema)] + pub struct GetScheduledMessageParams { + pub id: Option, + pub user_id: Option, + } } pub mod response { @@ -26,6 +32,12 @@ pub mod response { pub message: String, pub data: Vec, } + + #[derive(Debug, Default, Deserialize, Serialize, ToSchema)] + pub struct GetScheduledMessageResponse { + pub message: String, + pub data: Vec + } } pub mod endpoint { @@ -97,6 +109,65 @@ pub mod endpoint { } } + /// Endpoint to get Scheduled Message + #[utoipa::path( + get, + path = crate::caller::endpoints::GET_SCHEDULE_MESSAGE, + params( + ("id" = uuid::Uuid, Path, description = "Id of Scheduled Message"), + ("user_id" = uuid::Uuid, Path, description = "User Id associated with the Scheduled Message") + ), + responses( + (status = 200, description = "Scheduled Message found", body = super::response::GetScheduledMessageResponse), + (status = 400, description = "Error getting Scheduled Message", body = super::response::GetScheduledMessageResponse) + ) + )] + pub async fn get_scheduled_message( + axum::Extension(pool): axum::Extension, + axum::extract::Query(params): axum::extract::Query, + ) -> ( + axum::http::StatusCode, + axum::Json, + ) { + let mut response = super::response::GetScheduledMessageResponse::default(); + + let scheduled_messages = match params.id { + Some(id) => match scheduling_repo::get(&pool, &id).await { + Ok(scheduled_message) => { + vec![scheduled_message] + } + Err(err) => { + eprintln!("Error: {err:?}"); + return ( + axum::http::StatusCode::INTERNAL_SERVER_ERROR, + axum::Json(response), + ); + } + }, + None => match params.user_id { + Some(user_id) => match scheduling_repo::get_with_user_id(&pool, &user_id).await { + Ok(scheduled_messages) => scheduled_messages, + Err(err) => { + eprintln!("Error: {err:?}"); + return ( + axum::http::StatusCode::INTERNAL_SERVER_ERROR, + axum::Json(response), + ); + } + }, + None => { + response.message = String::from("Invalid parameter"); + return (axum::http::StatusCode::BAD_REQUEST, axum::Json(response)); + } + }, + }; + + response.data = scheduled_messages; + response.message = String::from(super::super::super::response::SUCCESSFUL); + + (axum::http::StatusCode::OK, axum::Json(response)) + } + fn can_schedule(scheduled_time: &Option) -> bool { scheduled_time .is_some_and(|t| t - time::OffsetDateTime::now_utc() >= time::Duration::minutes(10)) diff --git a/src/caller/mod.rs b/src/caller/mod.rs index d436f86..11dff9c 100644 --- a/src/caller/mod.rs +++ b/src/caller/mod.rs @@ -16,6 +16,8 @@ pub mod endpoints { pub const GET_MESSAGE: &str = "/api/v1/message"; /// Constant for scheduling message endpoint pub const SCHEDULE_MESSAGE: &str = "/api/v1/schedule/message"; + /// Constant for getting scheduled message endpoint + pub const GET_SCHEDULE_MESSAGE: &str = "/api/v1/schedule/message"; } pub mod response { -- 2.47.3 From df97d73d4fa60014a87f2e08e2c82ed9284ca895 Mon Sep 17 00:00:00 2001 From: phoenix Date: Thu, 18 Jun 2026 13:53:53 -0400 Subject: [PATCH 03/10] Fixing function name --- src/caller/message/scheduling.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/caller/message/scheduling.rs b/src/caller/message/scheduling.rs index 10b2e7c..8eb49d0 100644 --- a/src/caller/message/scheduling.rs +++ b/src/caller/message/scheduling.rs @@ -122,7 +122,7 @@ pub mod endpoint { (status = 400, description = "Error getting Scheduled Message", body = super::response::GetScheduledMessageResponse) ) )] - pub async fn get_scheduled_message( + pub async fn get_scheduled_messages( axum::Extension(pool): axum::Extension, axum::extract::Query(params): axum::extract::Query, ) -> ( -- 2.47.3 From 1fec37b09a8993a63d5beaa53a14c7bb06d332c8 Mon Sep 17 00:00:00 2001 From: phoenix Date: Thu, 18 Jun 2026 13:53:58 -0400 Subject: [PATCH 04/10] Route fix --- src/config/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/config/mod.rs b/src/config/mod.rs index 7199ff2..06d6ee9 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -130,6 +130,12 @@ pub mod init { axum::middleware::from_fn(crate::auth::auth::), ), ) + .route( + crate::caller::endpoints::GET_SCHEDULE_MESSAGE, + post(scheduling_endpoints::get_scheduled_messages).route_layer( + axum::middleware::from_fn(crate::auth::auth::), + ), + ) .layer(cors::configure_cors().await) } -- 2.47.3 From af214681804f8e65686674c5d4b6c9b0c5b0bdbd Mon Sep 17 00:00:00 2001 From: phoenix Date: Thu, 18 Jun 2026 13:58:21 -0400 Subject: [PATCH 05/10] Fixing routing issue --- src/config/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config/mod.rs b/src/config/mod.rs index 06d6ee9..ce2e588 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -132,7 +132,7 @@ pub mod init { ) .route( crate::caller::endpoints::GET_SCHEDULE_MESSAGE, - post(scheduling_endpoints::get_scheduled_messages).route_layer( + get(scheduling_endpoints::get_scheduled_messages).route_layer( axum::middleware::from_fn(crate::auth::auth::), ), ) -- 2.47.3 From ad04ac81fbee61d0121c1631c540597519b802d6 Mon Sep 17 00:00:00 2001 From: phoenix Date: Thu, 18 Jun 2026 14:07:51 -0400 Subject: [PATCH 06/10] Added test --- tests/test.rs | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/tests/test.rs b/tests/test.rs index 90e8749..1ccbd75 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -354,6 +354,22 @@ mod request { Err(err) => Err(err), } } + + pub async fn get_scheduled_messages(app: &axum::Router, id: &uuid::Uuid) -> Result { + let uri = format!( + "{}?id={}", + textsender_api::caller::endpoints::GET_SCHEDULE_MESSAGE, + id + ); + + match super::super::run_post(None, &uri, axum::http::Method::GET, false).await { + Ok(req) => match app.clone().oneshot(req).await { + Ok(response) => Ok(response), + Err(err) => Err(axum::http::Error::from(err)), + }, + Err(err) => Err(err), + } + } } } @@ -624,3 +640,47 @@ async fn test_schedule_message() { let _ = db_mgr::drop_database(&tm_pool, &db_name).await; } + +#[tokio::test] +async fn test_get_scheduled_message() { + let (tm_pool, db_name, pool) = db_mgr::get_database_ready().await; + let app = init::app(pool).await; + + let mut id: Option = None; + + match request::message::scheduling::create_scheduled_message(&app).await { + Ok(response) => { + eprintln!("Response: {response:?}"); + println!("Response: {response:?}"); + let resp = util::get_resp_data::< + textsender_api::caller::message::scheduling::response::ScheduleMessageResponse, + >(response) + .await; + assert_eq!(false, resp.data.is_empty(), "Should not be empty"); + let scheduled_message = &resp.data[0]; + id = Some(scheduled_message.id); + } + Err(err) => { + assert!(false, "Error: {err:?}"); + } + } + + if let Some(parsed_id) = id { + match request::message::scheduling::get_scheduled_messages(&app, &parsed_id).await { + Ok(response) => { + let resp = util::get_resp_data::< + textsender_api::caller::message::scheduling::response::GetScheduledMessageResponse, + >(response) + .await; + assert_eq!(false, resp.data.is_empty(), "Should not be empty"); + } + Err(err) => { + assert!(false, "Error: {err:?}"); + } + } + } else { + assert!(false, "Scheduled Message Id could not be retrieved"); + } + + let _ = db_mgr::drop_database(&tm_pool, &db_name).await; +} -- 2.47.3 From 556283266348df41af74eeb41d8e86604d7c38e6 Mon Sep 17 00:00:00 2001 From: phoenix Date: Thu, 18 Jun 2026 14:08:09 -0400 Subject: [PATCH 07/10] cargo fmt --- src/caller/message/scheduling.rs | 6 ++++-- src/repo/scheduling.rs | 13 +++++++------ tests/test.rs | 9 ++++++--- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/src/caller/message/scheduling.rs b/src/caller/message/scheduling.rs index 8eb49d0..29f310a 100644 --- a/src/caller/message/scheduling.rs +++ b/src/caller/message/scheduling.rs @@ -36,7 +36,7 @@ pub mod response { #[derive(Debug, Default, Deserialize, Serialize, ToSchema)] pub struct GetScheduledMessageResponse { pub message: String, - pub data: Vec + pub data: Vec, } } @@ -124,7 +124,9 @@ pub mod endpoint { )] pub async fn get_scheduled_messages( axum::Extension(pool): axum::Extension, - axum::extract::Query(params): axum::extract::Query, + axum::extract::Query(params): axum::extract::Query< + super::request::GetScheduledMessageParams, + >, ) -> ( axum::http::StatusCode, axum::Json, diff --git a/src/repo/scheduling.rs b/src/repo/scheduling.rs index 16baae5..066f4eb 100644 --- a/src/repo/scheduling.rs +++ b/src/repo/scheduling.rs @@ -75,13 +75,14 @@ pub async fn get_with_user_id( .await { Ok(rows) => { - let mut messages: Vec = Vec::new(); + let mut messages: Vec = + Vec::new(); for row in rows { - let id: uuid::Uuid = row.try_get("id")?; - let scheduled: time::OffsetDateTime = row.try_get("scheduled")?; - let status: String = row.try_get("status")?; - let created: time::OffsetDateTime = row.try_get("created")?; - let user_id: uuid::Uuid = row.try_get("user_id")?; + let id: uuid::Uuid = row.try_get("id")?; + let scheduled: time::OffsetDateTime = row.try_get("scheduled")?; + let status: String = row.try_get("status")?; + let created: time::OffsetDateTime = row.try_get("created")?; + let user_id: uuid::Uuid = row.try_get("user_id")?; let message = textsender_models::message::scheduling::ScheduledMessage { id, diff --git a/tests/test.rs b/tests/test.rs index 1ccbd75..0660fee 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -355,7 +355,10 @@ mod request { } } - pub async fn get_scheduled_messages(app: &axum::Router, id: &uuid::Uuid) -> Result { + pub async fn get_scheduled_messages( + app: &axum::Router, + id: &uuid::Uuid, + ) -> Result { let uri = format!( "{}?id={}", textsender_api::caller::endpoints::GET_SCHEDULE_MESSAGE, @@ -668,11 +671,11 @@ async fn test_get_scheduled_message() { if let Some(parsed_id) = id { match request::message::scheduling::get_scheduled_messages(&app, &parsed_id).await { Ok(response) => { - let resp = util::get_resp_data::< + let resp = util::get_resp_data::< textsender_api::caller::message::scheduling::response::GetScheduledMessageResponse, >(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 From 103604cd01d1555e55b75c9273b2b80ab2e7b300 Mon Sep 17 00:00:00 2001 From: phoenix Date: Thu, 18 Jun 2026 14:15:16 -0400 Subject: [PATCH 08/10] Refactoring code --- src/repo/scheduling.rs | 43 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/repo/scheduling.rs b/src/repo/scheduling.rs index 066f4eb..b61a5df 100644 --- a/src/repo/scheduling.rs +++ b/src/repo/scheduling.rs @@ -42,18 +42,18 @@ pub async fn get( .await { Ok(row) => { + /* let id: uuid::Uuid = row.try_get("id")?; let scheduled: time::OffsetDateTime = row.try_get("scheduled")?; let status: String = row.try_get("status")?; let created: time::OffsetDateTime = row.try_get("created")?; let user_id: uuid::Uuid = row.try_get("user_id")?; - Ok(textsender_models::message::scheduling::ScheduledMessage { - id, - scheduled: Some(scheduled), - created: Some(created), - status, - user_id, - }) + */ + + match parse_row(&row).await { + Ok(scheduled_message) => Ok(scheduled_message), + Err(err) => Err(err), + } } Err(_) => Err(sqlx::Error::RowNotFound), } @@ -78,6 +78,7 @@ pub async fn get_with_user_id( let mut messages: Vec = Vec::new(); for row in rows { + /* let id: uuid::Uuid = row.try_get("id")?; let scheduled: time::OffsetDateTime = row.try_get("scheduled")?; let status: String = row.try_get("status")?; @@ -91,7 +92,15 @@ pub async fn get_with_user_id( status, user_id, }; - messages.push(message); + */ + match parse_row(&row).await { + Ok(scheduled_message) => { + messages.push(scheduled_message); + } + Err(err) => { + return Err(err); + } + } } Ok(messages) @@ -99,3 +108,21 @@ pub async fn get_with_user_id( Err(_) => Err(sqlx::Error::RowNotFound), } } + +async fn parse_row( + row: &sqlx::postgres::PgRow, +) -> Result { + let id: uuid::Uuid = row.try_get("id")?; + let scheduled: time::OffsetDateTime = row.try_get("scheduled")?; + let status: String = row.try_get("status")?; + let created: time::OffsetDateTime = row.try_get("created")?; + let user_id: uuid::Uuid = row.try_get("user_id")?; + + Ok(textsender_models::message::scheduling::ScheduledMessage { + id, + scheduled: Some(scheduled), + created: Some(created), + status, + user_id, + }) +} -- 2.47.3 From 837b5596567b38b804ab2ba41cc3bad2dcccbd4a Mon Sep 17 00:00:00 2001 From: phoenix Date: Thu, 18 Jun 2026 14:18:06 -0400 Subject: [PATCH 09/10] Code cleanup --- src/repo/scheduling.rs | 33 ++++----------------------------- 1 file changed, 4 insertions(+), 29 deletions(-) diff --git a/src/repo/scheduling.rs b/src/repo/scheduling.rs index b61a5df..97af52c 100644 --- a/src/repo/scheduling.rs +++ b/src/repo/scheduling.rs @@ -41,20 +41,10 @@ pub async fn get( .fetch_one(pool) .await { - Ok(row) => { - /* - let id: uuid::Uuid = row.try_get("id")?; - let scheduled: time::OffsetDateTime = row.try_get("scheduled")?; - let status: String = row.try_get("status")?; - let created: time::OffsetDateTime = row.try_get("created")?; - let user_id: uuid::Uuid = row.try_get("user_id")?; - */ - - match parse_row(&row).await { - Ok(scheduled_message) => Ok(scheduled_message), - Err(err) => Err(err), - } - } + Ok(row) => match parse_row(&row).await { + Ok(scheduled_message) => Ok(scheduled_message), + Err(err) => Err(err), + }, Err(_) => Err(sqlx::Error::RowNotFound), } } @@ -78,21 +68,6 @@ pub async fn get_with_user_id( let mut messages: Vec = Vec::new(); for row in rows { - /* - let id: uuid::Uuid = row.try_get("id")?; - let scheduled: time::OffsetDateTime = row.try_get("scheduled")?; - let status: String = row.try_get("status")?; - let created: time::OffsetDateTime = row.try_get("created")?; - let user_id: uuid::Uuid = row.try_get("user_id")?; - - let message = textsender_models::message::scheduling::ScheduledMessage { - id, - scheduled: Some(scheduled), - created: Some(created), - status, - user_id, - }; - */ match parse_row(&row).await { Ok(scheduled_message) => { messages.push(scheduled_message); -- 2.47.3 From a5825a30033859e565e285c943226ccdb562861f Mon Sep 17 00:00:00 2001 From: phoenix Date: Thu, 18 Jun 2026 14:18:15 -0400 Subject: [PATCH 10/10] bump: textsender_api --- Cargo.lock | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3989e6f..b600799 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2293,7 +2293,7 @@ dependencies = [ [[package]] name = "textsender_api" -version = "0.1.10" +version = "0.1.11" dependencies = [ "axum", "axum-extra", diff --git a/Cargo.toml b/Cargo.toml index c5beac2..c11c93b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "textsender_api" -version = "0.1.10" +version = "0.1.11" edition = "2024" rust-version = "1.96" -- 2.47.3