diff --git a/src/database/entities/channel.rs b/src/database/entities/channel.rs index 6cef965de94c234c37ef924d6d9381af47421fed..881afd25799e951f722a104b6daa9b27b2e3b3b4 100644 --- a/src/database/entities/channel.rs +++ b/src/database/entities/channel.rs @@ -115,6 +115,20 @@ impl Channel { let id = self.id(); let messages = get_collection("messages"); + // Delete any invites. + get_collection("invites") + .delete_many( + doc! { + "channel": id + }, + None, + ) + .await + .map_err(|_| Error::DatabaseError { + operation: "delete_many", + with: "invites", + })?; + // Check if there are any attachments we need to delete. let message_ids = messages .find( @@ -190,15 +204,45 @@ impl Channel { // Remove from server object. if let Channel::TextChannel { server, .. } = &self { + let server = Ref::from_unchecked(server.clone()).fetch_server().await?; + let mut unset = doc! {}; + + if let Some(sys) = &server.system_messages { + if let Some(cid) = &sys.user_joined { + if id == cid { + unset.insert("system_messages.user_joined", 1); + } + } + + if let Some(cid) = &sys.user_left { + if id == cid { + unset.insert("system_messages.user_left", 1); + } + } + + if let Some(cid) = &sys.user_kicked { + if id == cid { + unset.insert("system_messages.user_kicked", 1); + } + } + + if let Some(cid) = &sys.user_banned { + if id == cid { + unset.insert("system_messages.user_banned", 1); + } + } + } + get_collection("servers") .update_one( doc! { - "_id": server + "_id": server.id }, doc! { "$pull": { "channels": id - } + }, + "$unset": unset }, None, ) diff --git a/src/database/entities/message.rs b/src/database/entities/message.rs index 7d107ffe965057b47f08c4ae4e01c5a346039fe7..4de99ff9dba54ab866b8b6920998cff440ab56e1 100644 --- a/src/database/entities/message.rs +++ b/src/database/entities/message.rs @@ -26,8 +26,14 @@ pub enum SystemMessage { UserAdded { id: String, by: String }, #[serde(rename = "user_remove")] UserRemove { id: String, by: String }, + #[serde(rename = "user_joined")] + UserJoined { id: String }, #[serde(rename = "user_left")] UserLeft { id: String }, + #[serde(rename = "user_kicked")] + UserKicked { id: String }, + #[serde(rename = "user_banned")] + UserBanned { id: String }, #[serde(rename = "channel_renamed")] ChannelRenamed { name: String, by: String }, #[serde(rename = "channel_description_changed")] diff --git a/src/database/entities/server.rs b/src/database/entities/server.rs index 5f4eaf0cc18a7fe83b747485418503f08d658414..4984677e50b0f9b17b495a62678a6907625727ad 100644 --- a/src/database/entities/server.rs +++ b/src/database/entities/server.rs @@ -34,6 +34,20 @@ pub struct Ban { pub reason: Option<String>, } +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct SystemMessageChannels { + pub user_joined: Option<String>, + pub user_left: Option<String>, + pub user_kicked: Option<String>, + pub user_banned: Option<String> +} + +pub enum RemoveMember { + Leave, + Kick, + Ban +} + #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Server { #[serde(rename = "_id")] @@ -46,6 +60,8 @@ pub struct Server { #[serde(skip_serializing_if = "Option::is_none")] pub description: Option<String>, pub channels: Vec<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub system_messages: Option<SystemMessageChannels>, #[serde(skip_serializing_if = "Option::is_none")] pub icon: Option<File>, @@ -296,10 +312,19 @@ impl Server { } .publish(self.id.clone()); + if let Some(channels) = &self.system_messages { + if let Some(cid) = &channels.user_joined { + let channel = Ref::from_unchecked(cid.clone()).fetch_channel().await?; + Content::SystemMessage(SystemMessage::UserJoined { id: id.to_string() }) + .send_as_system(&channel) + .await?; + } + } + Ok(()) } - pub async fn remove_member(&self, id: &str) -> Result<()> { + pub async fn remove_member(&self, id: &str, removal: RemoveMember) -> Result<()> { let result = get_collection("server_members") .delete_one( doc! { @@ -322,6 +347,39 @@ impl Server { user: id.to_string(), } .publish(self.id.clone()); + + if let Some(channels) = &self.system_messages { + let message = match removal { + RemoveMember::Leave => { + if let Some(cid) = &channels.user_left { + Some((cid.clone(), SystemMessage::UserLeft { id: id.to_string() })) + } else { + None + } + } + RemoveMember::Kick => { + if let Some(cid) = &channels.user_kicked { + Some((cid.clone(), SystemMessage::UserKicked { id: id.to_string() })) + } else { + None + } + } + RemoveMember::Ban => { + if let Some(cid) = &channels.user_banned { + Some((cid.clone(), SystemMessage::UserBanned { id: id.to_string() })) + } else { + None + } + } + }; + + if let Some((cid, message)) = message { + let channel = Ref::from_unchecked(cid).fetch_channel().await?; + Content::SystemMessage(message) + .send_as_system(&channel) + .await?; + } + } } Ok(()) diff --git a/src/routes/servers/ban_create.rs b/src/routes/servers/ban_create.rs index b14a814b94dd2eeeaf8bf51f29a76b8a8702a586..b54d68ca845789380cdf46909e0aa242e9ee0ffe 100644 --- a/src/routes/servers/ban_create.rs +++ b/src/routes/servers/ban_create.rs @@ -49,5 +49,5 @@ pub async fn req(user: User, server: Ref, target: Ref, data: Json<Data>) -> Resu with: "server_ban", })?; - server.remove_member(&target.id).await + server.remove_member(&target.id, RemoveMember::Ban).await } diff --git a/src/routes/servers/member_remove.rs b/src/routes/servers/member_remove.rs index cac0807d3341743137373769dfd0b7a0d70cd171..fa2ba9c941d3a38984423d9e3cc1d9c6fe50c026 100644 --- a/src/routes/servers/member_remove.rs +++ b/src/routes/servers/member_remove.rs @@ -25,5 +25,5 @@ pub async fn req(user: User, target: Ref, member: String) -> Result<()> { return Err(Error::MissingPermission); } - target.remove_member(&member.id.user).await + target.remove_member(&member.id.user, RemoveMember::Kick).await } diff --git a/src/routes/servers/server_create.rs b/src/routes/servers/server_create.rs index 12cd741ac04cd94f21f4652ddb881baa2abc8017..55846d1a6d001984b864d4888c1c8918f5ddeaaf 100644 --- a/src/routes/servers/server_create.rs +++ b/src/routes/servers/server_create.rs @@ -52,6 +52,14 @@ pub async fn req(user: User, info: Json<Data>) -> Result<JsonValue> { name: info.name, description: info.description, channels: vec![cid.clone()], + system_messages: Some( + SystemMessageChannels { + user_joined: Some(cid.clone()), + user_left: Some(cid.clone()), + user_kicked: Some(cid.clone()), + user_banned: Some(cid.clone()) + } + ), icon: None, banner: None, diff --git a/src/routes/servers/server_delete.rs b/src/routes/servers/server_delete.rs index e558c4edd895d93a5a04fa1d5bffe74c70f0e4bf..e335b81c945a246c1ad903a4a833b804a2919f24 100644 --- a/src/routes/servers/server_delete.rs +++ b/src/routes/servers/server_delete.rs @@ -18,6 +18,6 @@ pub async fn req(user: User, target: Ref) -> Result<()> { if user.id == target.owner { target.delete().await } else { - target.remove_member(&user.id).await + target.remove_member(&user.id, RemoveMember::Leave).await } }