//! # Push notifications helper //! //! @author Pierre Hubert use crate::controllers::user_ws_controller; use crate::data::conversation::ConvID; use crate::data::conversation_message::ConversationMessage; use crate::data::error::Res; use crate::data::push_notification::PushNotification; use crate::data::user::UserID; use crate::data::user_token::{PushNotificationToken, UserAccessToken}; use crate::helpers::{account_helper, conversations_helper, independent_push_notifications_service_helper, user_helper}; use crate::helpers::events_helper::Event; /// Un-register for previous push notifications service pub fn un_register_from_previous_service(client: &UserAccessToken) -> Res { // This method must not fail in case of error if let PushNotificationToken::INDEPENDENT(old_token) = &client.push_notifications_token { if let Err(e) = independent_push_notifications_service_helper::remove_token(old_token) { eprintln!("Failed to un-register from independent push notifications service! {}", e); } } Ok(()) } /// Push a notification to specific tokens fn push_notification(n: &PushNotification, targets: Vec) -> Res { // TODO : implement println!("* Push notification: {:#?} \n* To {:?}", n, targets); Ok(()) } /// Cancel a notification for specific tokens (optional) fn cancel_notification(id: String, targets: Vec) -> Res { // TODO : implement println!("* Cancel push notification: {:#?} \n* For {:?}", id, targets); Ok(()) } /// Push a notification to specific users, only if they are not connected fn push_notification_to_users(n: &PushNotification, users: Vec) -> Res { let dest_users: Vec = users.into_iter() .filter(|u| !user_ws_controller::is_user_connected(u)) .collect(); let mut dest_tokens = vec![]; for user in dest_users { for token in account_helper::get_all_login_tokens(&user)? { dest_tokens.push(token.push_notifications_token); } } push_notification(n, dest_tokens) } /// Cancel a notification for one or more users fn cancel_notification_for_users(id: String, users: Vec) -> Res { let mut dest_tokens = vec![]; for user in users { for token in account_helper::get_all_login_tokens(&user)? { dest_tokens.push(token.push_notifications_token); } } cancel_notification(id, dest_tokens) } /// Create a conversation notification pub fn create_conversation_notification(msg: &ConversationMessage) -> Res { let user_id = match &msg.user_id { Some(id) => id, None => { // Do no create notifications for server messages return Ok(()); } }; let user = user_helper::find_user_by_id(user_id)?; let conv = conversations_helper::get_single(msg.conv_id)?; let notif_title = match conv.name { None => user.full_name(), Some(name) => format!("{} ({})", user.full_name(), name) }; let notif_message = match &msg.message { None => "Shared file".to_string(), Some(msg) => msg.to_string() }; let notif = PushNotification { id: format!("conv-{}", msg.conv_id.id()), title: notif_title, body: notif_message, image: None, timeout: None, }; let list = conversations_helper::get_list_members(msg.conv_id)? .into_iter() .filter(|m| m.following && m.user_id != user_id) .map(|m| m.user_id) .collect(); push_notification_to_users(¬if, list) } /// Dismiss a conversation notification pub fn cancel_conversation_notification(conv_id: ConvID, users: Option>) -> Res { let notif_id = format!("conv-{}", conv_id.id()); let list = match users { Some(users) => users, None => conversations_helper::get_list_members(conv_id)? .into_iter().map(|m| m.user_id).collect() }; cancel_notification_for_users(notif_id, list) } /// Handle event. This method NEVER returns Err pub fn handle_event(e: &Event) -> Res { if let Err(e) = handle_event_internal(e) { eprintln!("Failed to create push notifications associated with event! {}", e); } Ok(()) } fn handle_event_internal(e: &Event) -> Res { match e { Event::NewConversationMessage(msg) => { create_conversation_notification(msg)?; } Event::SeenLastConversationMessage(user_id, conv_id) => { cancel_conversation_notification(*conv_id, Some(vec![user_id.as_owned()]))?; } _ => {} } Ok(()) }