1
0
mirror of https://gitlab.com/comunic/comunicapiv3 synced 2025-06-21 00:45:18 +00:00

Can create group conversation

This commit is contained in:
2021-04-03 19:00:18 +02:00
parent 1fc6f08b19
commit 63c284c322
11 changed files with 202 additions and 43 deletions

View File

@ -6,10 +6,12 @@ use crate::constants::database_tables_names::{CONV_LIST_TABLE, CONV_MEMBERS_TABL
use crate::data::conversation::{Conversation, ConversationMember, ConvID, NewConversationSettings};
use crate::data::conversation_message::{ConversationMessage, ConversationMessageFile, ConversationServerMessageType, UserAddedAnotherUserToConversation, UserRemovedAnotherUserToConversation};
use crate::data::error::{ExecError, Res, ResultBoxError};
use crate::data::group_id::GroupID;
use crate::data::group_member::GroupMembershipLevel;
use crate::data::new_conversation::NewConversation;
use crate::data::new_conversation_message::NewConversationMessage;
use crate::data::user::{User, UserID};
use crate::helpers::{database, events_helper};
use crate::helpers::{database, events_helper, groups_helper};
use crate::helpers::database::{InsertQuery, UpdateInfo};
use crate::helpers::events_helper::Event;
use crate::utils::date_utils::time;
@ -26,25 +28,47 @@ pub fn create(conv: &NewConversation) -> Res<ConvID> {
.add_opt_str("logo", Option::from(&conv.logo))
.add_legacy_bool("can_everyone_add_members", conv.can_everyone_add_members)
.add_opt_group_id("group_id", conv.group_id.clone())
.add_opt_u32("min_group_membership_level",
conv.group_min_membership_level.as_ref().map(|s| s.to_db()))
.insert()?
.map(|i| ConvID::new(i))
.ok_or(ExecError::new("missing result conv id!"))?;
// Add the creator of the conversation
add_member(conv_id, &conv.owner_id, conv.owner_following, true, &conv.owner_id)?;
// Initialize the list of members of the group
if conv.group_id.is_some() {
update_members_list_for_group_conversation(conv_id)?;
} else {
// Add the creator of the conversation
add_member(conv_id, &conv.owner_id, conv.owner_following, true, Some(&conv.owner_id))?;
// Add other members to the conversation
for member in &conv.members {
if !member.eq(&conv.owner_id) {
add_member(conv_id, member, true, false, &conv.owner_id)?;
// Add other members to the conversation
for member in &conv.members {
if !member.eq(&conv.owner_id) {
add_member(conv_id, member, true, false, Some(&conv.owner_id))?;
}
}
}
Ok(conv_id)
}
/// Create a conversation for a group
pub fn create_conversation_for_group(group_id: GroupID, min_membership_level: GroupMembershipLevel, name: &String) -> Res<ConvID> {
create(&NewConversation {
owner_id: UserID::invalid(),
name: Some(name.to_string()),
group_id: Some(group_id),
group_min_membership_level: Some(min_membership_level),
color: None,
logo: None,
owner_following: false,
members: Default::default(),
can_everyone_add_members: false,
})
}
/// Add a member to a conversation
pub fn add_member(conv_id: ConvID, user_id: &UserID, following: bool, admin: bool, adder: &UserID) -> Res {
pub fn add_member(conv_id: ConvID, user_id: &UserID, following: bool, admin: bool, adder: Option<&UserID>) -> Res {
InsertQuery::new(CONV_MEMBERS_TABLE)
.add_conv_id("conv_id", conv_id)
.add_user_id("user_id", user_id)
@ -54,21 +78,25 @@ pub fn add_member(conv_id: ConvID, user_id: &UserID, following: bool, admin: boo
.add_u64("last_message_seen", 0)
.insert()?;
// Create a message
if adder != user_id {
send_message(
&NewConversationMessage::new_server_message(
conv_id,
ConversationServerMessageType::UserAddedAnotherUserToConversation(UserAddedAnotherUserToConversation {
user_who_added: adder.clone(),
user_added: user_id.clone(),
}),
)
)?;
} else {
send_message(&NewConversationMessage::new_server_message(
conv_id, ConversationServerMessageType::UserCreatedConversation(user_id.clone()),
))?;
// Send the messages (if possible, no messages are created for groups conversations)
if let Some(adder) = adder {
// Create a message
if adder != user_id {
send_message(
&NewConversationMessage::new_server_message(
conv_id,
ConversationServerMessageType::UserAddedAnotherUserToConversation(UserAddedAnotherUserToConversation {
user_who_added: adder.clone(),
user_added: user_id.clone(),
}),
)
)?;
} else {
send_message(&NewConversationMessage::new_server_message(
conv_id, ConversationServerMessageType::UserCreatedConversation(user_id.clone()),
))?;
}
}
Ok(())
@ -427,10 +455,50 @@ pub fn remove_user_from_conversation(user_id: &UserID, conv: &Conversation, remo
if conv.is_last_admin(user_id) {
delete_conversation(conv)
} else {
remove_member(user_id, conv.id, remover)
remove_member(user_id, conv.id, Some(remover))
}
}
/// Update the list of members for a group conversation
pub fn update_members_list_for_group_conversation(conv_id: ConvID) -> Res {
let conv = get_single(conv_id)?;
if !conv.is_linked_to_group() {
return Err(ExecError::boxed_new("Attempted to update members list for a non-group conversation!"));
}
let group_members = groups_helper::get_list_members(conv.group_id.as_ref().unwrap())?;
// Add missing memberships / Update existing invalid memberships
for member in &group_members {
let conv_member = conv.members.iter().filter(|f| f.user_id == member.user_id).next();
if let Some(conv_member) = conv_member {
// Update admin status, if required
if conv_member.is_admin != member.is_admin() {
set_admin(&conv_id, &member.user_id, member.is_admin())?;
}
}
// Create the member
else if conv.min_group_membership_level.as_ref().unwrap() >= &member.level {
add_member(conv_id, &member.user_id, true, member.is_admin(), None)?;
}
}
// Remove memberships that have to be removed
for conv_member in &conv.members {
let member = group_members.iter().filter(|m| m.user_id == conv_member.user_id).next();
// Remove the member, if required
if member.is_none() || conv.min_group_membership_level.as_ref().unwrap() < &member.unwrap().level {
remove_member(&conv_member.user_id, conv_id, None)?;
}
}
Ok(())
}
/// Remove permanently a conversation
pub fn delete_conversation(conv: &Conversation) -> ResultBoxError<()> {
// Delete all the messages of the conversations
@ -460,7 +528,7 @@ pub fn delete_conversation(conv: &Conversation) -> ResultBoxError<()> {
}
/// Delete a conversation membership
pub fn remove_member(user_id: &UserID, conv_id: ConvID, remover: &UserID) -> ResultBoxError<()> {
pub fn remove_member(user_id: &UserID, conv_id: ConvID, remover: Option<&UserID>) -> ResultBoxError<()> {
for msg in get_user_messages_for_conversations(conv_id, user_id)? {
delete_message(&msg)?;
}
@ -472,19 +540,21 @@ pub fn remove_member(user_id: &UserID, conv_id: ConvID, remover: &UserID) -> Res
.exec()?;
// Create a message
if remover == user_id {
send_message(&NewConversationMessage::new_server_message(
conv_id,
ConversationServerMessageType::UserLeftConversation(user_id.clone()),
))?;
} else {
send_message(&NewConversationMessage::new_server_message(
conv_id,
ConversationServerMessageType::UserRemovedFromConversation(UserRemovedAnotherUserToConversation {
user_who_removed: remover.clone(),
user_removed: user_id.clone(),
}),
))?;
if let Some(remover) = remover {
if remover == user_id {
send_message(&NewConversationMessage::new_server_message(
conv_id,
ConversationServerMessageType::UserLeftConversation(user_id.clone()),
))?;
} else {
send_message(&NewConversationMessage::new_server_message(
conv_id,
ConversationServerMessageType::UserRemovedFromConversation(UserRemovedAnotherUserToConversation {
user_who_removed: remover.clone(),
user_removed: user_id.clone(),
}),
))?;
}
}
// Propagate event
@ -537,6 +607,8 @@ fn db_to_conversation_info(row: &database::RowResult) -> ResultBoxError<Conversa
last_activity: row.get_u64("last_activity")?,
creation_time: row.get_u64("creation_time")?,
group_id: row.get_optional_group_id("group_id")?,
min_group_membership_level: row.get_optional_u32("min_group_membership_level")?
.map(GroupMembershipLevel::from_db),
})
}

View File

@ -325,6 +325,13 @@ impl<'a> RowResult<'a> {
}
}
pub fn get_optional_u32(&self, name: &str) -> ResultBoxError<Option<u32>> {
match self.is_null(name)? {
true => Ok(None),
false => Ok(Some(self.get_u32(name)?))
}
}
/// Get an optional unsigned number => Set to None if value is null / empty / 0
pub fn get_optional_positive_u64(&self, name: &str) -> ResultBoxError<Option<u64>> {
Ok(match self.get_optional_u64(name)? {
@ -615,6 +622,14 @@ impl InsertQuery {
self
}
/// Add an optional number. If None, Null will be inserted
pub fn add_opt_u32(mut self, key: &str, value: Option<u32>) -> InsertQuery {
self.values.insert(key.to_string(), value
.map(|u| Value::UInt(u as u64))
.unwrap_or(Value::NULL));
self
}
/// Add an optional user ID. If None, Null will be inserted
pub fn add_opt_user_id(self, key: &str, value: Option<UserID>) -> InsertQuery {
self.add_opt_u64(key, value.map(|u| u.id()))

View File

@ -487,6 +487,8 @@ pub fn delete(group_id: &GroupID) -> ResultBoxError {
// Delete all group related notifications
notifications_helper::delete_all_related_with_group(group_id)?;
// TODO : delete all conversations related with the group
// Delete all group members
database::DeleteQuery::new(GROUPS_MEMBERS_TABLE)
.cond_group_id("groups_id", group_id)