From 4fbd6c816d5f0878fe62db684db6ef47de2f3e14 Mon Sep 17 00:00:00 2001 From: Paul Makles <paulmakles@gmail.com> Date: Sun, 12 Apr 2020 16:42:13 +0100 Subject: [PATCH] Add join / leave messages for groups. --- src/database/message.rs | 68 ++++++++++++++++- src/database/mutual.rs | 2 +- src/routes/channel.rs | 157 ++++++++++++++++++++-------------------- src/routes/mod.rs | 5 +- src/routes/root.rs | 2 +- 5 files changed, 149 insertions(+), 85 deletions(-) diff --git a/src/database/message.rs b/src/database/message.rs index dd273a7..e47be11 100644 --- a/src/database/message.rs +++ b/src/database/message.rs @@ -1,4 +1,8 @@ -use bson::UtcDateTime; +use super::get_collection; +use crate::guards::channel::ChannelRef; +use crate::routes::channel::ChannelType; + +use bson::{doc, to_bson, UtcDateTime}; use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] @@ -11,7 +15,7 @@ pub struct PreviousEntry { pub struct Message { #[serde(rename = "_id")] pub id: String, - // pub nonce: String, used internally + pub nonce: Option<String>, pub channel: String, pub author: String, @@ -24,3 +28,63 @@ pub struct Message { // ? TODO: write global send message // ? pub fn send_message(); // ? handle websockets? +impl Message { + pub fn send(&self, target: &ChannelRef) -> bool { + if get_collection("messages") + .insert_one(to_bson(&self).unwrap().as_document().unwrap().clone(), None) + .is_ok() + { + let short_content: String = self.content.chars().take(24).collect(); + + // !! this stuff can be async + if target.channel_type == ChannelType::DM as u8 + || target.channel_type == ChannelType::GROUPDM as u8 + { + let mut update = doc! { + "$set": { + "last_message": { + "id": &self.id, + "user_id": &self.author, + "short_content": short_content, + } + } + }; + + if target.channel_type == ChannelType::DM as u8 { + update + .get_document_mut("$set") + .unwrap() + .insert("active", true); + } + + if get_collection("channels") + .update_one(doc! { "_id": &target.id }, update, None) + .is_ok() + { + true + } else { + false + } + } else { + true + } + + /*websocket::queue_message( + get_recipients(&target), + json!({ + "type": "message", + "data": { + "id": id.clone(), + "nonce": nonce, + "channel": target.id, + "author": user.id, + "content": content, + }, + }) + .to_string(), + );*/ + } else { + false + } + } +} diff --git a/src/database/mutual.rs b/src/database/mutual.rs index 162dcc8..412cb1d 100644 --- a/src/database/mutual.rs +++ b/src/database/mutual.rs @@ -111,7 +111,7 @@ pub fn has_mutual_connection(user_id: &str, target_id: &str, with_permission: bo let permissions = guild.get_i32("default_permissions").unwrap() as u32; - if MemberPermissions([ permissions ]).get_send_direct_messages() { + if MemberPermissions([permissions]).get_send_direct_messages() { return true; } } diff --git a/src/routes/channel.rs b/src/routes/channel.rs index bbee4f5..07c12f4 100644 --- a/src/routes/channel.rs +++ b/src/routes/channel.rs @@ -183,7 +183,7 @@ pub fn add_member(user: UserRef, target: ChannelRef, member: UserRef) -> Option< with_permissions!(user, target); - let recp = target.recipients.unwrap(); + let recp = target.recipients.as_ref().unwrap(); if recp.len() == 50 { return Some(Response::BadRequest( json!({ "error": "Maximum group size is 50." }), @@ -201,7 +201,7 @@ pub fn add_member(user: UserRef, target: ChannelRef, member: UserRef) -> Option< Relationship::Friend => { if database::get_collection("channels") .update_one( - doc! { "_id": &target.id }, + doc! { "_id": target.id.clone() }, doc! { "$push": { "recipients": &member.id @@ -211,7 +211,23 @@ pub fn add_member(user: UserRef, target: ChannelRef, member: UserRef) -> Option< ) .is_ok() { - Some(Response::Result(super::Status::Ok)) + if (Message { + id: Ulid::new().to_string(), + nonce: None, + channel: target.id.clone(), + author: "system".to_string(), + content: format!("<@{}> added <@{}> to the group.", &user.id, &member.id), + edited: None, + previous_content: None, + }) + .send(&target) + { + Some(Response::Result(super::Status::Ok)) + } else { + Some(Response::PartialStatus( + json!({ "error": "Failed to send join message, but user has been added." }), + )) + } } else { Some(Response::InternalServerError( json!({ "error": "Failed to add user to group." }), @@ -243,7 +259,7 @@ pub fn remove_member(user: UserRef, target: ChannelRef, member: UserRef) -> Opti return Some(Response::LackingPermission(Permission::KickMembers)); } - let set = vec_to_set(&target.recipients.unwrap()); + let set = vec_to_set(target.recipients.as_ref().unwrap()); if set.get(&member.id).is_none() { return Some(Response::BadRequest( json!({ "error": "User not in group!" }), @@ -262,7 +278,23 @@ pub fn remove_member(user: UserRef, target: ChannelRef, member: UserRef) -> Opti ) .is_ok() { - Some(Response::Result(super::Status::Ok)) + if (Message { + id: Ulid::new().to_string(), + nonce: None, + channel: target.id.clone(), + author: "system".to_string(), + content: format!("<@{}> removed <@{}> from the group.", &user.id, &member.id), + edited: None, + previous_content: None, + }) + .send(&target) + { + Some(Response::Result(super::Status::Ok)) + } else { + Some(Response::PartialStatus( + json!({ "error": "Failed to send join message, but user has been removed." }), + )) + } } else { Some(Response::InternalServerError( json!({ "error": "Failed to add user to group." }), @@ -323,15 +355,19 @@ pub fn delete(user: UserRef, target: ChannelRef) -> Option<Response> { } } 1 => { - let mut recipients = - vec_to_set(&target.recipients.expect("Missing recipients on Group DM.")); - let owner = target.owner.expect("Missing owner on Group DM."); + let mut recipients = vec_to_set( + target + .recipients + .as_ref() + .expect("Missing recipients on Group DM."), + ); + let owner = target.owner.as_ref().expect("Missing owner on Group DM."); if recipients.len() == 1 { try_delete() } else { recipients.remove(&user.id); - let new_owner = if owner == user.id { + let new_owner = if owner == &user.id { recipients.iter().next().unwrap() } else { &owner @@ -352,7 +388,23 @@ pub fn delete(user: UserRef, target: ChannelRef) -> Option<Response> { ) .is_ok() { - Some(Response::Result(super::Status::Ok)) + if (Message { + id: Ulid::new().to_string(), + nonce: None, + channel: target.id.clone(), + author: "system".to_string(), + content: format!("<@{}> left the group.", &user.id), + edited: None, + previous_content: None, + }) + .send(&target) + { + Some(Response::Result(super::Status::Ok)) + } else { + Some(Response::PartialStatus( + json!({ "error": "Failed to send leave message, but you have left the group." }), + )) + } } else { Some(Response::InternalServerError( json!({ "error": "Failed to remove you from the group." }), @@ -453,76 +505,23 @@ pub fn send_message( } let id = Ulid::new().to_string(); - Some( - if col - .insert_one( - doc! { - "_id": &id, - "nonce": nonce, - "channel": &target.id, - "author": &user.id, - "content": &content, - }, - None, - ) - .is_ok() - { - let short_content: String = content.chars().take(24).collect(); - let col = database::get_collection("channels"); - - // !! this stuff can be async - if target.channel_type == ChannelType::DM as u8 - || target.channel_type == ChannelType::GROUPDM as u8 - { - let mut update = doc! { - "$set": { - "last_message": { - "id": &id, - "user_id": &user.id, - "short_content": short_content, - } - } - }; - - if target.channel_type == ChannelType::DM as u8 { - update - .get_document_mut("$set") - .unwrap() - .insert("active", true); - } - - if col - .update_one(doc! { "_id": &target.id }, update, None) - .is_ok() - { - Response::Success(json!({ "id": id })) - } else { - Response::InternalServerError(json!({ "error": "Failed to update channel." })) - } - } else { - Response::Success(json!({ "id": id })) - } + let message = Message { + id: id.clone(), + nonce: Some(nonce), + channel: target.id.clone(), + author: user.id, + content, + edited: None, + previous_content: None, + }; - /*websocket::queue_message( - get_recipients(&target), - json!({ - "type": "message", - "data": { - "id": id.clone(), - "nonce": nonce, - "channel": target.id, - "author": user.id, - "content": content, - }, - }) - .to_string(), - );*/ - } else { - Response::InternalServerError(json!({ - "error": "Failed database query." - })) - }, - ) + if message.send(&target) { + Some(Response::Success(json!({ "id": id }))) + } else { + Some(Response::BadRequest( + json!({ "error": "Failed to send message." }), + )) + } } /// get a message diff --git a/src/routes/mod.rs b/src/routes/mod.rs index aeeac18..ebb40d2 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -19,6 +19,8 @@ pub enum Response { Success(JsonValue), #[response()] Redirect(Redirect), + #[response(status = 207)] + PartialStatus(JsonValue), #[response(status = 400)] BadRequest(JsonValue), #[response(status = 401)] @@ -51,8 +53,7 @@ impl<'a> rocket::response::Responder<'a> for Permission { .header(ContentType::JSON) .sized_body(Cursor::new(format!( "{{\"error\":\"Lacking permission: {:?}.\",\"permission\":{}}}", - self, - self as u32, + self, self as u32, ))) .ok() } diff --git a/src/routes/root.rs b/src/routes/root.rs index 798d295..e9fc5b7 100644 --- a/src/routes/root.rs +++ b/src/routes/root.rs @@ -6,6 +6,6 @@ use bson::doc; #[get("/")] pub fn root() -> Response { Response::Success(json!({ - "revolt": "0.0.1" + "revolt": "0.1.0" })) } -- GitLab