From 4b31533320a103a3d020501eaa3195a64c5458a2 Mon Sep 17 00:00:00 2001
From: Paul Makles <paulmakles@gmail.com>
Date: Sat, 8 Feb 2020 17:19:22 +0000
Subject: [PATCH] Implement websocket events.

See https://trello.com/c/xjQeLsd4/19-websocket-notification-portal-%F0%9F%94%94
---
 src/routes/channel.rs | 65 +++++++++++++++++++++++++++++++++++--------
 src/websocket/mod.rs  | 22 +++++++++++----
 2 files changed, 70 insertions(+), 17 deletions(-)

diff --git a/src/routes/channel.rs b/src/routes/channel.rs
index 5501ef5..7a0d3c1 100644
--- a/src/routes/channel.rs
+++ b/src/routes/channel.rs
@@ -1,4 +1,5 @@
 use crate::database::{ self, user::User, channel::Channel, message::Message };
+use crate::websocket;
 
 use bson::{ bson, doc, from_bson, Bson::UtcDatetime };
 use rocket_contrib::json::{ JsonValue, Json };
@@ -35,6 +36,13 @@ fn has_permission(user: &User, target: &Channel) -> bool {
 	}
 }
 
+fn get_recipients(target: &Channel) -> Vec<String> {
+	match target.channel_type {
+		0..=1 => target.recipients.clone().unwrap(),
+		_ => vec![]
+	}
+}
+
 /// fetch channel information
 #[get("/<target>")]
 pub fn channel(user: User, target: Channel) -> Option<JsonValue> {
@@ -139,17 +147,29 @@ pub fn send_message(user: User, target: Channel, message: Json<SendMessage>) ->
 	Some(match col.insert_one(
 		doc! {
 			"_id": id.clone(),
-			"channel": target.id,
-			"author": user.id,
+			"channel": target.id.clone(),
+			"author": user.id.clone(),
 			"content": message.content.clone(),
 		},
 		None
 	) {
-		Ok(_) =>
+		Ok(_) => {
+			websocket::queue_message(
+				get_recipients(&target),
+				json!({
+					"type": "message",
+					"id": id.clone(),
+					"channel": target.id,
+					"author": user.id,
+					"content": message.content.clone(),
+				}).to_string()
+			);
+
 			json!({
 				"success": true,
 				"id": id
-			}),
+			})
+		},
 		Err(_) =>
 			json!({
 				"success": false,
@@ -179,20 +199,33 @@ pub fn edit_message(user: User, target: Channel, message: Message, edit: Json<Se
 		} else {
 			let col = database::get_collection("messages");
 
+			let edited = UtcDatetime(Utc::now());
 			match col.update_one(
-				doc! { "_id": message.id },
+				doc! { "_id": message.id.clone() },
 				doc! {
 					"$set": {
 						"content": edit.content.clone(),
-						"edited": UtcDatetime(Utc::now())
+						"edited": edited.clone()
 					}
 				},
 				None
 			) {
-				Ok(_) =>
+				Ok(_) => {
+					websocket::queue_message(
+						get_recipients(&target),
+						json!({
+							"type": "message_update",
+							"id": message.id,
+							"channel": target.id,
+							"content": message.content.clone(),
+							"edited": edited
+						}).to_string()
+					);
+
 					json!({
 						"success": true
-					}),
+					})
+				},
 				Err(_) =>
 					json!({
 						"success": false,
@@ -220,13 +253,23 @@ pub fn delete_message(user: User, target: Channel, message: Message) -> Option<J
 			let col = database::get_collection("messages");
 
 			match col.delete_one(
-				doc! { "_id": message.id },
+				doc! { "_id": message.id.clone() },
 				None
 			) {
-				Ok(_) =>
+				Ok(_) => {
+					websocket::queue_message(
+						get_recipients(&target),
+						json!({
+							"type": "message_delete",
+							"id": message.id,
+							"channel": target.id
+						}).to_string()
+					);
+
 					json!({
 						"success": true
-					}),
+					})
+				},
 				Err(_) =>
 					json!({
 						"success": false,
diff --git a/src/websocket/mod.rs b/src/websocket/mod.rs
index bcc35f6..5204050 100644
--- a/src/websocket/mod.rs
+++ b/src/websocket/mod.rs
@@ -147,15 +147,25 @@ pub fn launch_server() {
 pub fn send_message(id: String, message: String) -> std::result::Result<(), ()> {
 	unsafe {
 		let map = CLIENTS.get().unwrap().read().unwrap();
-		let arr = map.get(&id).unwrap();
+		if map.contains_key(&id) {
+			let arr = map.get(&id).unwrap();
 
-		Ok(for item in arr {
-			match item.out.send(message.clone()) {
-				Ok(_) => (),
-				Err(_) => {
+			for item in arr {
+				if let Err(_) = item.out.send(message.clone()) {
 					return Err(());
 				}
 			}
-		})
+		}
+
+		Ok(())
+	}
+}
+
+// ! TODO: WRITE THREADED QUEUE SYSTEM
+// ! FETCH RECIPIENTS HERE INSTEAD OF IN METHOD
+
+pub fn queue_message(ids: Vec<String>, message: String) {
+	for id in ids {
+		send_message(id, message.clone()).expect("uhhhhhhhhhh can i get uhhhhhhhhhhhhhhhhhh mcdonald cheese burger with fries");
 	}
 }
-- 
GitLab