1
0
mirror of https://gitlab.com/comunic/comunicapiv3 synced 2025-01-08 11:42:35 +00:00
comunicapiv3/src/controllers/conversations_controller.rs

384 lines
13 KiB
Rust
Raw Normal View History

//! # Conversations controller
//!
//! @author Pierre Hubert
2020-06-18 12:15:17 +00:00
2020-06-15 12:42:02 +00:00
use crate::api_data::conversation_api::ConversationAPI;
use crate::api_data::conversation_message_api::ConversationMessageAPI;
2020-06-22 17:02:34 +00:00
use crate::api_data::list_unread_conversations_api::UnreadConversationAPI;
2020-06-22 12:41:14 +00:00
use crate::api_data::res_count_unread_conversations::ResultCountUnreadConversations;
2020-06-15 12:42:02 +00:00
use crate::api_data::res_create_conversation::ResCreateConversation;
use crate::api_data::res_find_private_conversations::ResFindPrivateConversations;
2021-03-04 17:51:52 +00:00
use crate::constants::MIN_CONVERSATION_MESSAGE_LENGTH;
use crate::controllers::user_ws_controller;
2021-02-05 08:11:30 +00:00
use crate::data::base_request_handler::BaseRequestHandler;
2021-03-04 17:51:52 +00:00
use crate::data::conversation::{ConversationMemberSetting, NewConversationSettings};
use crate::data::conversation_message::ConversationMessageFile;
use crate::data::error::Res;
2020-06-15 12:42:02 +00:00
use crate::data::http_request_handler::HttpRequestHandler;
use crate::data::new_conversation::NewConversation;
2020-06-22 12:16:52 +00:00
use crate::data::new_conversation_message::NewConversationMessage;
2020-06-25 08:08:34 +00:00
use crate::data::user::UserID;
2021-02-10 16:16:52 +00:00
use crate::data::user_ws_connection::UserWsConnection;
use crate::data::user_ws_message::UserWsMessage;
use crate::helpers::{conversations_helper, events_helper, user_helper};
use crate::helpers::events_helper::Event;
2021-03-04 17:51:52 +00:00
use crate::routes::RequestResult;
2020-06-15 12:42:02 +00:00
use crate::utils::string_utils::remove_html_nodes;
/// Create a new conversation
pub fn create(r: &mut HttpRequestHandler) -> RequestResult {
let name = r.post_string("name")?;
2020-06-25 08:08:34 +00:00
let mut members = r.post_numbers_list("users", 1)?
.iter()
.map(|f| UserID::new(f.clone()))
.collect::<Vec<UserID>>();
// Adapt name
let name = match name.as_str() {
"false" => None,
s => Some(s.to_string())
};
// Check if members exists
for user in &members {
2020-06-25 08:08:34 +00:00
if !user_helper::exists(user)? {
r.not_found(format!("User {} not found!", user.id()))?;
}
}
// Add current user ID if required
2020-06-25 08:08:34 +00:00
let curr_user_id = r.user_id()?;
if !members.contains(&curr_user_id) {
members.push(curr_user_id);
}
let conv = NewConversation {
owner_id: r.user_id()?,
name,
owner_following: r.post_bool("follow")?,
members,
can_everyone_add_members: r.post_bool_opt("canEveryoneAddMembers", true),
2021-03-04 17:51:52 +00:00
color: r.post_color_opt("color")?,
group_id: None,
background: None,// TODO : add support for background
};
// Create the conversation
2020-06-04 11:36:57 +00:00
let conv_id = conversations_helper::create(&conv)?;
r.set_response(ResCreateConversation::new(conv_id))
2020-06-04 15:51:22 +00:00
}
/// Get the list of conversations of a user
pub fn get_list(r: &mut HttpRequestHandler) -> RequestResult {
2020-06-25 08:08:34 +00:00
let list = conversations_helper::get_list_user(&r.user_id()?)?;
r.set_response(list.iter().map(|c| ConversationAPI::new(c)).collect::<Vec<ConversationAPI>>())
2020-06-12 06:50:09 +00:00
}
/// Get information about a single conversation
pub fn get_single(r: &mut HttpRequestHandler) -> RequestResult {
2021-03-04 17:51:52 +00:00
let conv = r.post_conv("conversationID")?;
let conv = conversations_helper::get_single(conv.conv_id)?;
r.set_response(ConversationAPI::new(&conv))
2020-06-12 07:23:02 +00:00
}
/// Update the settings of a conversation
pub fn update_settings(r: &mut HttpRequestHandler) -> RequestResult {
2021-03-04 17:51:52 +00:00
let conv_membership = r.post_conv("conversationID")?;
let conv = conversations_helper::get_single(conv_membership.conv_id)?;
// Update following state, if required
if r.has_post_parameter("following") {
conversations_helper::set_following(
2020-06-25 08:08:34 +00:00
&r.user_id()?,
2021-03-05 10:58:31 +00:00
conv_membership.conv_id,
r.post_bool("following")?,
)?;
}
// Update members list
2021-03-04 17:51:52 +00:00
if r.has_post_parameter("members") && !conv.is_managed() {
let mut members = r.post_users_id("members")?
.into_iter()
.map(|user_id| ConversationMemberSetting { user_id, set_admin: false })
.collect::<Vec<ConversationMemberSetting>>();
let admins = r.post_users_id("admins")?;
2020-06-25 08:08:34 +00:00
2021-03-04 17:51:52 +00:00
let can_everyone_add_members = conversations_helper::can_everyone_add_members(conv_membership.conv_id)?;
2021-03-04 17:51:52 +00:00
if !conv_membership.is_admin && !can_everyone_add_members {
r.forbidden("You can not update the list of members of this conversation!".to_string())?;
}
2021-03-04 17:51:52 +00:00
// Set same admin status as earlier
if !conv_membership.is_admin {
members = members
.into_iter()
.map(|mut n| {
n.set_admin = conv.is_admin(&n.user_id);
n
})
.collect()
}
2021-03-04 17:51:52 +00:00
// If the user is an admin, use the values he gave
else {
members = members
.into_iter()
.map(|mut n| {
n.set_admin = admins.contains(&n.user_id);
n
})
.collect()
}
2021-03-04 17:51:52 +00:00
// Current user can not touch his own membership, so revert it back forcefully
members = members
.into_iter()
.filter(|m| !m.user_id.eq(&conv_membership.user_id))
.collect::<Vec<ConversationMemberSetting>>();
members.push(ConversationMemberSetting {
user_id: r.user_id()?,
set_admin: conv_membership.is_admin,
});
conversations_helper::set_members(conv_membership.conv_id, &members, conv_membership.is_admin)?;
}
2020-06-15 12:30:01 +00:00
// Change moderator settings
2021-03-04 17:51:52 +00:00
if r.has_post_parameter("name")
&& r.has_post_parameter("canEveryoneAddMembers")
&& r.has_post_parameter("color") {
if !conv_membership.is_admin {
2020-06-15 12:30:01 +00:00
r.forbidden("You are not allowed to perform changes on this conversation!".to_string())?;
}
2021-03-04 17:51:52 +00:00
let new_settings = NewConversationSettings {
conv_id: conv_membership.conv_id,
name: r.post_string_optional("name").map(|s| remove_html_nodes(&s)),
color: r.post_color_opt("color")?,
can_everyone_add_members: r.post_bool("canEveryoneAddMembers")?,
};
2021-03-04 17:51:52 +00:00
conversations_helper::set_settings(new_settings)?;
2020-06-15 12:30:01 +00:00
}
r.success("Conversation information successfully updated!")
}
/// Find a private conversation
pub fn find_private(r: &mut HttpRequestHandler) -> RequestResult {
let other_user = r.post_user_id("otherUser")?;
let allow_create = r.post_bool_opt("allowCreate", false);
// Query the database
2020-06-25 08:08:34 +00:00
let mut list = conversations_helper::find_private(&r.user_id()?, &other_user)?;
if list.is_empty() {
if !allow_create {
return r.not_found(format!("Not any private conversation was found. The server was not allowed to create a new one..."));
}
2020-06-18 07:44:34 +00:00
let new_conv = NewConversation {
owner_id: r.user_id()?,
name: None,
owner_following: true,
members: vec![r.user_id()?, other_user],
can_everyone_add_members: true,
2021-03-04 17:51:52 +00:00
color: r.post_color_opt("color")?,
background: None,
group_id: None,
2020-06-18 07:44:34 +00:00
};
let conv_id = conversations_helper::create(&new_conv)?;
list.push(conv_id);
}
r.set_response(ResFindPrivateConversations::new(list))
2020-06-18 07:55:02 +00:00
}
2020-06-20 05:42:18 +00:00
/// Refresh a single conversation
pub fn refresh_single(r: &mut HttpRequestHandler) -> RequestResult {
2021-03-04 17:51:52 +00:00
let conv = r.post_conv("conversationID")?;
let last_message_id = r.post_u64("last_message_id")?;
let messages = match last_message_id {
// Get latest messages of the conversation
2021-03-05 10:58:31 +00:00
0 => conversations_helper::get_last_messages(conv.conv_id, 10)?,
// Get new messages
2021-03-05 10:58:31 +00:00
_ => conversations_helper::get_new_messages(conv.conv_id, last_message_id)?,
};
2021-03-05 10:58:31 +00:00
if messages.len() > 0 {
conversations_helper::mark_user_seen(
conv.conv_id,
r.user_id_ref()?,
messages.iter().map(|m| m.id).max().unwrap(),
)?;
}
r.set_response(ConversationMessageAPI::for_list(&messages))
2020-06-20 09:55:39 +00:00
}
2020-06-22 12:16:52 +00:00
/// Get older messages of a conversation
pub fn get_older_messages(r: &mut HttpRequestHandler) -> RequestResult {
2021-03-04 17:51:52 +00:00
let conv = r.post_conv("conversationID")?;
2020-06-22 12:16:52 +00:00
let max_id = r.post_u64("oldest_message_id")? - 1;
// Determine limit
let limit = r.post_u64("limit")?;
let limit = match limit {
0 => 1,
1..=60 => limit,
_ => 60
};
2021-03-05 10:58:31 +00:00
let messages = conversations_helper::get_older_messages(conv.conv_id, max_id, limit)?;
2020-06-22 12:16:52 +00:00
r.set_response(ConversationMessageAPI::for_list(&messages))
}
2020-06-20 09:55:39 +00:00
/// Send a new message
pub fn send_message(r: &mut HttpRequestHandler) -> RequestResult {
2021-03-04 17:51:52 +00:00
let conv = r.post_conv("conversationID")?;
// TODO : add support for other files type
2020-06-22 10:19:13 +00:00
// Get image
2021-03-04 17:51:52 +00:00
let file = match r.has_file("image") {
2020-06-22 10:19:13 +00:00
false => None,
2021-03-04 17:51:52 +00:00
true => {
let path = r.save_post_image("image", "conversations", 1200, 1200)?;
Some(ConversationMessageFile {
path: path.clone(),
size: std::fs::metadata(&path)?.len(),
name: "picture.png".to_string(),
thumbnail: Some(r.save_post_image("image", "conversations", 50, 50)?),
r#type: "image/png".to_string(),
})
}
2020-06-22 10:19:13 +00:00
};
2021-03-04 17:51:52 +00:00
let message = if let None = file {
Some(r.post_string_without_html("message", MIN_CONVERSATION_MESSAGE_LENGTH, true)?)
} else {
None
};
2020-06-22 10:19:13 +00:00
conversations_helper::send_message(&NewConversationMessage {
2021-03-04 17:51:52 +00:00
user_id: Some(r.user_id()?),
conv_id: conv.conv_id,
2020-06-22 10:19:13 +00:00
message,
2021-03-04 17:51:52 +00:00
file,
server_message: None,
2020-06-22 10:19:13 +00:00
})?;
2020-06-20 13:22:41 +00:00
2020-06-22 10:19:13 +00:00
r.success("Conversation message was successfully sent!")
}
/// Count the number of unread conversation of the user
pub fn count_unread(r: &mut HttpRequestHandler) -> RequestResult {
2020-06-25 08:08:34 +00:00
let num = conversations_helper::count_unread_for_user(&r.user_id()?)?;
r.set_response(ResultCountUnreadConversations::new(num))
2020-06-22 12:41:14 +00:00
}
/// Get the list of unread conversations of a user
pub fn list_unread(r: &mut HttpRequestHandler) -> RequestResult {
2020-06-25 08:08:34 +00:00
let list = conversations_helper::get_list_unread(&r.user_id()?)?;
2020-06-22 16:55:24 +00:00
2021-03-05 10:58:31 +00:00
r.set_response(UnreadConversationAPI::for_list(&list)?)
2020-06-22 17:02:34 +00:00
}
/// Delete a conversation
pub fn delete_conversation(r: &mut HttpRequestHandler) -> RequestResult {
2021-03-04 17:51:52 +00:00
let conv_membership = r.post_conv("conversationID")?;
let conv = conversations_helper::get_single(conv_membership.conv_id)?;
if conv.is_managed() {
r.bad_request("This conversation is managed, it can not be deleted by this way!".to_string())?;
}
2021-03-04 17:51:52 +00:00
conversations_helper::remove_user_from_conversation(&r.user_id()?, &conv, r.user_id_ref()?)?;
r.success("The conversation has been deleted")
}
/// Update a single conversation message
pub fn update_message(r: &mut HttpRequestHandler) -> RequestResult {
let msg_id = r.post_u64("messageID")?;
let new_content = r.post_string_opt("content", 3, true)?;
2020-06-25 08:08:34 +00:00
if !conversations_helper::is_message_owner(&r.user_id()?, msg_id)? {
r.forbidden("You are not the owner of this message!".to_string())?;
}
conversations_helper::update_message_content(msg_id, &new_content)?;
r.success("Conversation message content successfully updated")
}
/// Delete a conversation message
pub fn delete_message(r: &mut HttpRequestHandler) -> RequestResult {
let msg_id = r.post_u64("messageID")?;
2020-06-25 08:08:34 +00:00
if !conversations_helper::is_message_owner(&r.user_id()?, msg_id)? {
r.forbidden("You are not the owner of this message!".to_string())?;
}
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::UpdatedNumberUnreadConversations(users) => {
for user in users.iter() {
if user_ws_controller::is_user_connected(user) {
user_ws_controller::send_message_to_user(
&UserWsMessage::no_id_message(
"number_unread_conversations",
conversations_helper::count_unread_for_user(user)?,
)?,
user,
)?;
}
}
}
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)),
2021-03-04 17:51:52 +00:00
Some(|conn: &UserWsConnection| conversations_helper::mark_user_seen(msg.conv_id, conn.user_id(), msg.id)),
)?;
}
Event::UpdatedConversationMessage(msg) => {
user_ws_controller::send_message_to_specific_connections(
|f| f.conversations.contains(&msg.conv_id),
|_| UserWsMessage::no_id_message("updated_conv_message", ConversationMessageAPI::new(msg)),
None::<fn(&_) -> _>,
)?;
}
Event::DeleteConversationMessage(msg) => {
user_ws_controller::send_message_to_specific_connections(
|f| f.conversations.contains(&msg.conv_id),
|_| UserWsMessage::no_id_message("deleted_conv_message", ConversationMessageAPI::new(msg)),
None::<fn(&_) -> _>,
)?;
}
_ => {}
}
Ok(())
}