From bb2201c00e7ae6b398e9c7a285f86579809ade65 Mon Sep 17 00:00:00 2001 From: shockrah Date: Sat, 17 Apr 2021 15:55:10 -0700 Subject: [PATCH] ! First pass base implementation for /messages/recent This api method is made for clients to easily say "give me the n[1,100] latest messages in some channel This commit contains code that is largely untested but contains some base code such that I can correct issues in the next _tested_ commit --- json-api/db/src/messages.rs | 24 ++++++++++++++++++++++++ json-api/src/main.rs | 1 + json-api/src/messages.rs | 29 +++++++++++++++++++++++++++++ json-api/src/routes.rs | 3 ++- 4 files changed, 56 insertions(+), 1 deletion(-) diff --git a/json-api/db/src/messages.rs b/json-api/db/src/messages.rs index c5b9739..0a9b11b 100644 --- a/json-api/db/src/messages.rs +++ b/json-api/db/src/messages.rs @@ -203,5 +203,29 @@ impl Message { Ok(Response::Set(messages)) } + + /// On success Response::Set + /// On user failure Response::RestrictedInput + /// On error Err + pub async fn last_n(p: &Pool, limit: i32, channel_id: u64) -> Result, SqlError> { + if limit <= 0 || limit > 100 { + return Ok(Response::RestrictedInput("Invalid \"limit\" value".into())) + } else { + // Reminder: if content_type is not text/plain then content will be empty + let q = " SELECT mem.name, msg.id, msg.time, msg.content, msg.content_type, msg.author_id + FROM messages as msg + JOIN members as mem ON mem.id = msg.author_id + WHERE channel_id = :channel + ORDER BY id DESC LIMIT :limit"; + let params = params!{"limit" => limit, "channel" => channel_id}; + let mut conn = p.get_conn().await?; + let messages = conn.exec_map(q, params, |(name, id, time, content, content_type, author_id)| { + UserMessage { + name, id, time, content, content_type, author_id, channel_id + } + }).await?; + return Ok(Response::Set(messages)) + } + } } diff --git a/json-api/src/main.rs b/json-api/src/main.rs index fb70cc4..20ed211 100644 --- a/json-api/src/main.rs +++ b/json-api/src/main.rs @@ -77,6 +77,7 @@ async fn route_dispatcher( (POST, routes::MESSAGE_SEND) => messages::send_message(pool, resp, body, headers, params).await, (GET, routes::MESSAGE_TIME_RANGE) => messages::get_by_time(pool, resp, params).await, (GET, routes::MESSAGE_FROM_ID) =>messages::from_id(pool, resp, params).await, + (GET, routes::MESSAGE_LAST_N) => messages::recent_messages(pool, resp, params).await, /* ADMIN */ (POST, routes::SET_PERMS_BY_ADMIN) => admin::set_permissions(pool, resp, params).await, /* MEMBERS */ diff --git a/json-api/src/messages.rs b/json-api/src/messages.rs index 402413c..71a621d 100644 --- a/json-api/src/messages.rs +++ b/json-api/src/messages.rs @@ -172,3 +172,32 @@ pub async fn from_id(pool: &Pool, response: &mut Response, params: HashMap *response.status_mut() = StatusCode::BAD_REQUEST; } } + +pub async fn recent_messages(pool: &Pool, response: &mut Response, params: HashMap) { + let limit = qs_param!(params, "limit", i32); + let channel_id = qs_param!(params, "channel_id", u64); + + if channel_id.is_some() && limit.is_some() { + // NOTE: using match here to capture+log the error from the database + match Message::last_n(pool, limit.unwrap(), channel_id.unwrap()).await { + Ok(dbresp) => { + match dbresp { + // 200 + db::Response::Set(messages) => + set_json_body(response, json!({"messages": messages})), + // 400 + db::Response::RestrictedInput(msg) => { + *response.status_mut() = StatusCode::BAD_REQUEST; + set_json_body(response, json!({"error": msg})); + }, + // unreachable branch + _ => {} + } + }, + Err(e) => { + eprintln!("{}", e); + } + } + } else { + } +} diff --git a/json-api/src/routes.rs b/json-api/src/routes.rs index f8b7d7d..e4c484c 100644 --- a/json-api/src/routes.rs +++ b/json-api/src/routes.rs @@ -12,7 +12,8 @@ pub const CHANNELS_DELETE: Rstr = "/channels/delete"; // requires @name perms: pub const MESSAGE_SEND: Rstr = "/message/send"; // requires @content perms::MESSAGE_SEND pub const MESSAGE_TIME_RANGE: Rstr = "/message/get_range"; // requires @channel(id) @start-time @end-time -pub const MESSAGE_FROM_ID: Rstr = "/message/from_id"; // requires @channel(id) requires @start(id) @limit(1..1000) +pub const MESSAGE_FROM_ID: Rstr = "/message/from_id"; // requires @channel_id requires @start(id) @limit(1..1000) +pub const MESSAGE_LAST_N: Rstr = "/message/recent"; // requires @channel_id requires @limit(1..100) pub const GET_ONLINE_MEMBERS: Rstr = "/members/get_online"; // requires none pub const GET_MEMBER: Rstr = "/members/single"; // requires @member_id