From de2448d4961ba78622a131f5a9799738cb00de52 Mon Sep 17 00:00:00 2001 From: Pierre HUBERT Date: Sat, 6 Feb 2021 09:41:56 +0100 Subject: [PATCH] Send message through WebSocket fro new conversation messages --- src/controllers/conversations_controller.rs | 26 +++++++++++++++++- src/controllers/user_ws_controller.rs | 25 +++++++++++++++++ src/data/user_ws_message.rs | 13 +++++++++ src/helpers/conversations_helper.rs | 17 +++++++----- src/helpers/events_helper.rs | 30 +++++++++++++++++++++ src/helpers/mod.rs | 3 ++- 6 files changed, 106 insertions(+), 8 deletions(-) create mode 100644 src/helpers/events_helper.rs diff --git a/src/controllers/conversations_controller.rs b/src/controllers/conversations_controller.rs index 0c7782a..e6fcfb5 100644 --- a/src/controllers/conversations_controller.rs +++ b/src/controllers/conversations_controller.rs @@ -12,12 +12,17 @@ use crate::api_data::res_count_unread_conversations::ResultCountUnreadConversati use crate::api_data::res_create_conversation::ResCreateConversation; use crate::api_data::res_find_private_conversations::ResFindPrivateConversations; use crate::controllers::routes::RequestResult; +use crate::controllers::user_ws_controller; +use crate::controllers::user_ws_controller::WsConnection; use crate::data::base_request_handler::BaseRequestHandler; +use crate::data::error::Res; use crate::data::http_request_handler::HttpRequestHandler; use crate::data::new_conversation::NewConversation; use crate::data::new_conversation_message::NewConversationMessage; use crate::data::user::UserID; -use crate::helpers::{conversations_helper, user_helper}; +use crate::data::user_ws_message::UserWsMessage; +use crate::helpers::{conversations_helper, events_helper, user_helper}; +use crate::helpers::events_helper::Event; use crate::utils::string_utils::remove_html_nodes; /// Create a new conversation @@ -334,4 +339,23 @@ pub fn delete_message(r: &mut HttpRequestHandler) -> RequestResult { conversations_helper::delete_message_by_id(msg_id)?; r.success("The message has been successfully deleted!") +} + +/// Events handler +pub fn handle_event(e: &events_helper::Event) -> Res { + match e { + Event::NewConversationMessage(msg) => { + user_ws_controller::send_message_to_specific_connections( + |f| f.conversations.contains(&msg.conv_id), + |_| UserWsMessage::no_id_message("new_conv_message", ConversationMessageAPI::new(msg)), + Some(|conn: &WsConnection| conversations_helper::mark_user_seen(msg.conv_id, &conn.user_id)), + )?; + } + + Event::UpdatedConversationMessage(msg) => {} + Event::DeleteConversationMessage(msg) => {} + _ => {} + } + + Ok(()) } \ No newline at end of file diff --git a/src/controllers/user_ws_controller.rs b/src/controllers/user_ws_controller.rs index 263b4b1..9074296 100644 --- a/src/controllers/user_ws_controller.rs +++ b/src/controllers/user_ws_controller.rs @@ -483,6 +483,31 @@ pub fn send_message_to_users(msg: &UserWsMessage, users: &Vec) -> Res { Ok(()) } +/// Send a message to specific users +pub fn send_message_to_specific_connections(filter: F, msg_generator: M, after_send: Option) -> Res + where F: Fn(&WsConnection) -> bool, + M: Fn(&WsConnection) -> Res, + A: Fn(&WsConnection) -> Res +{ + let connections = get_ws_connections_list() + .lock() + .unwrap() + .iter() + .filter(|f| filter(f)) + .map(|f| f.clone()) + .collect::>(); + + for con in connections { + send_message(con.session.clone(), &msg_generator(&con)?)?; + + if let Some(cb) = &after_send { + cb(&con)?; + } + } + + Ok(()) +} + /// Check out whether user is connected or not pub fn is_user_connected(user_id: &UserID) -> bool { get_ws_connections_list().lock().unwrap().iter().any(|c| &c.user_id == user_id) diff --git a/src/data/user_ws_message.rs b/src/data/user_ws_message.rs index 01c1147..d84aecd 100644 --- a/src/data/user_ws_message.rs +++ b/src/data/user_ws_message.rs @@ -4,9 +4,22 @@ use serde::{Deserialize, Serialize}; +use crate::data::error::Res; + #[derive(Clone, Serialize, Deserialize)] pub struct UserWsMessage { pub id: Option, pub title: String, pub data: serde_json::Value, +} + +impl UserWsMessage { + /// Construct a new WebSocket message with no ID + pub fn no_id_message(title: &str, data: T) -> Res { + Ok(UserWsMessage { + id: None, + title: title.to_string(), + data: serde_json::to_value(data)?, + }) + } } \ No newline at end of file diff --git a/src/helpers/conversations_helper.rs b/src/helpers/conversations_helper.rs index 4555476..f10ded4 100644 --- a/src/helpers/conversations_helper.rs +++ b/src/helpers/conversations_helper.rs @@ -10,8 +10,9 @@ use crate::data::new_conversation::NewConversation; use crate::data::new_conversation_message::NewConversationMessage; use crate::data::unread_conversation::UnreadConversation; use crate::data::user::UserID; -use crate::helpers::database; +use crate::helpers::{database, events_helper}; use crate::helpers::database::InsertQuery; +use crate::helpers::events_helper::Event; use crate::utils::date_utils::time; use crate::utils::user_data_utils::user_data_path; @@ -297,13 +298,13 @@ pub fn send_message(msg: &NewConversationMessage) -> ResultBoxError<()> { let t = time(); // Insert the message in the database - database::InsertQuery::new(CONV_MESSAGES_TABLE) + let msg_id = database::InsertQuery::new(CONV_MESSAGES_TABLE) .add_u64("conv_id", msg.conv_id) .add_user_id("user_id", &msg.user_id) .add_u64("time_insert", t) .add_str("message", msg.message.as_str()) .add_opt_str("image_path", msg.image_path.as_ref()) - .insert()?; + .insert_expect_result()?; // Update the last activity of the conversation database::UpdateInfo::new(CONV_LIST_TABLE) @@ -323,7 +324,9 @@ pub fn send_message(msg: &NewConversationMessage) -> ResultBoxError<()> { .exec()?; // TODO : send an event (updated_number_unread_conversations) - // TODO : send an event (sent_conversation_message) + + // Send an event (sent_conversation_message) + events_helper::propagate_event(&Event::NewConversationMessage(&get_single_message(msg_id)?))?; Ok(()) } @@ -335,7 +338,8 @@ pub fn update_message_content(msg_id: u64, new_content: &str) -> ResultBoxError< .set_str("message", new_content) .exec()?; - // TODO : send an event (conv_message_updated) + // Send an event (conv_message_updated) + events_helper::propagate_event(&Event::UpdatedConversationMessage(&get_single_message(msg_id)?))?; Ok(()) } @@ -355,7 +359,8 @@ pub fn delete_message(msg: &ConversationMessage) -> ResultBoxError<()> { .cond_u64("ID", msg.id) .exec()?; - // TODO : send en event (conv_message_deleted) + // Send en event (conv_message_deleted) + events_helper::propagate_event(&Event::DeleteConversationMessage(msg))?; Ok(()) } diff --git a/src/helpers/events_helper.rs b/src/helpers/events_helper.rs new file mode 100644 index 0000000..b7e8a98 --- /dev/null +++ b/src/helpers/events_helper.rs @@ -0,0 +1,30 @@ +//! # Events helper +//! +//! @author Pierre Hubert + + + +use crate::data::error::Res; +use crate::data::conversation_message::ConversationMessage; +use crate::controllers::conversations_controller; + +pub enum Event<'a> { + + /// Created a new conversation message + NewConversationMessage(&'a ConversationMessage), + + /// Updated conversation message + UpdatedConversationMessage(&'a ConversationMessage), + + /// Deleted a conversation message + DeleteConversationMessage(&'a ConversationMessage), + + /// No event + None, +} + +/// Propagate an event through the different components of the application +pub fn propagate_event(e: &Event) -> Res { + conversations_controller::handle_event(e)?; + Ok(()) +} \ No newline at end of file diff --git a/src/helpers/mod.rs b/src/helpers/mod.rs index 8087fe1..f78db4c 100644 --- a/src/helpers/mod.rs +++ b/src/helpers/mod.rs @@ -16,4 +16,5 @@ pub mod survey_helper; pub mod comments_helper; pub mod notifications_helper; pub mod webapp_helper; -pub mod requests_limit_helper; \ No newline at end of file +pub mod requests_limit_helper; +pub mod events_helper; \ No newline at end of file