From 11f7092fcdb0f1fecdf5007185122d55d65bf095 Mon Sep 17 00:00:00 2001
From: Paul Makles <paulmakles@gmail.com>
Date: Sun, 24 Jan 2021 10:24:44 +0000
Subject: [PATCH] Add last_message to channels, mark DMs as active.

---
 src/database/entities/channel.rs           | 12 ++++++
 src/database/entities/message.rs           | 50 ++++++++++++++++++++--
 src/routes/channels/delete_channel.rs      |  2 +-
 src/routes/channels/group_add_member.rs    |  6 +--
 src/routes/channels/group_create.rs        |  1 +
 src/routes/channels/group_remove_member.rs |  8 ++--
 src/routes/channels/message_send.rs        |  2 +-
 src/routes/users/open_dm.rs                |  1 +
 8 files changed, 69 insertions(+), 13 deletions(-)

diff --git a/src/database/entities/channel.rs b/src/database/entities/channel.rs
index 2e2cfcc..63759f8 100644
--- a/src/database/entities/channel.rs
+++ b/src/database/entities/channel.rs
@@ -5,6 +5,14 @@ use mongodb::bson::{doc, to_document};
 use rocket_contrib::json::JsonValue;
 use serde::{Deserialize, Serialize};
 
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct LastMessage {
+    #[serde(rename = "_id")]
+    id: String,
+    author: String,
+    short: String,
+}
+
 #[derive(Serialize, Deserialize, Debug, Clone)]
 #[serde(tag = "channel_type")]
 pub enum Channel {
@@ -18,6 +26,8 @@ pub enum Channel {
         id: String,
         active: bool,
         recipients: Vec<String>,
+        #[serde(skip_serializing_if = "Option::is_none")]
+        last_message: Option<LastMessage>,
     },
     Group {
         #[serde(rename = "_id")]
@@ -28,6 +38,8 @@ pub enum Channel {
         owner: String,
         description: String,
         recipients: Vec<String>,
+        #[serde(skip_serializing_if = "Option::is_none")]
+        last_message: Option<LastMessage>,
     },
 }
 
diff --git a/src/database/entities/message.rs b/src/database/entities/message.rs
index f03e29d..e51efb5 100644
--- a/src/database/entities/message.rs
+++ b/src/database/entities/message.rs
@@ -35,18 +35,60 @@ impl Message {
         }
     }
 
-    pub async fn publish(self) -> Result<()> {
+    pub async fn publish(self, channel: &Channel) -> Result<()> {
         get_collection("messages")
             .insert_one(to_bson(&self).unwrap().as_document().unwrap().clone(), None)
             .await
             .map_err(|_| Error::DatabaseError {
                 operation: "insert_one",
-                with: "messages",
+                with: "message",
             })?;
 
-        let channel = self.channel.clone();
+        // ! temp code
+        let channels = get_collection("channels");
+        match channel {
+            Channel::DirectMessage { id, .. } => {
+                channels.update_one(
+                    doc! { "_id": id },
+                    doc! {
+                        "active": true,
+                        "last_message": {
+                            "_id": self.id.clone(),
+                            "author": self.author.clone(),
+                            "short": self.content.chars().take(24).collect::<String>()
+                        }
+                    },
+                    None
+                )
+                .await
+                .map_err(|_| Error::DatabaseError {
+                    operation: "update_one",
+                    with: "channel",
+                })?;
+            },
+            Channel::Group { id, .. } => {
+                channels.update_one(
+                    doc! { "_id": id },
+                    doc! {
+                        "last_message": {
+                            "_id": self.id.clone(),
+                            "author": self.author.clone(),
+                            "short": self.content.chars().take(24).collect::<String>()
+                        }
+                    },
+                    None
+                )
+                .await
+                .map_err(|_| Error::DatabaseError {
+                    operation: "update_one",
+                    with: "channel",
+                })?;
+            },
+            _ => {}
+        }
+
         ClientboundNotification::Message(self)
-            .publish(channel)
+            .publish(channel.id().to_string())
             .await
             .ok();
 
diff --git a/src/routes/channels/delete_channel.rs b/src/routes/channels/delete_channel.rs
index b328b5d..0b8e30f 100644
--- a/src/routes/channels/delete_channel.rs
+++ b/src/routes/channels/delete_channel.rs
@@ -101,7 +101,7 @@ pub async fn req(user: User, target: Ref) -> Result<()> {
                 id.clone(),
                 format!("<@{}> left the group.", user.id),
             )
-            .publish()
+            .publish(&target)
             .await
             .ok();
 
diff --git a/src/routes/channels/group_add_member.rs b/src/routes/channels/group_add_member.rs
index 677fdd8..cbb9756 100644
--- a/src/routes/channels/group_add_member.rs
+++ b/src/routes/channels/group_add_member.rs
@@ -17,7 +17,7 @@ pub async fn req(user: User, target: Ref, member: Ref) -> Result<()> {
         Err(Error::LabelMe)?
     }
 
-    if let Channel::Group { id, recipients, .. } = channel {
+    if let Channel::Group { id, recipients, .. } = &channel {
         if recipients.len() >= *MAX_GROUP_SIZE {
             Err(Error::GroupTooLarge {
                 max: *MAX_GROUP_SIZE,
@@ -56,10 +56,10 @@ pub async fn req(user: User, target: Ref, member: Ref) -> Result<()> {
 
         Message::create(
             "00000000000000000000000000".to_string(),
-            id,
+            id.clone(),
             format!("<@{}> added <@{}> to the group.", user.id, member.id),
         )
-        .publish()
+        .publish(&channel)
         .await
         .ok();
 
diff --git a/src/routes/channels/group_create.rs b/src/routes/channels/group_create.rs
index 54075a6..65d6a16 100644
--- a/src/routes/channels/group_create.rs
+++ b/src/routes/channels/group_create.rs
@@ -70,6 +70,7 @@ pub async fn req(user: User, info: Json<Data>) -> Result<JsonValue> {
             .unwrap_or_else(|| "A group.".to_string()),
         owner: user.id,
         recipients: set.into_iter().collect::<Vec<String>>(),
+        last_message: None
     };
 
     channel.clone().publish().await?;
diff --git a/src/routes/channels/group_remove_member.rs b/src/routes/channels/group_remove_member.rs
index 438756d..08bd4e3 100644
--- a/src/routes/channels/group_remove_member.rs
+++ b/src/routes/channels/group_remove_member.rs
@@ -16,9 +16,9 @@ pub async fn req(user: User, target: Ref, member: Ref) -> Result<()> {
         owner,
         recipients,
         ..
-    } = channel
+    } = &channel
     {
-        if &user.id != &owner {
+        if &user.id != owner {
             // figure out if we want to use perm system here
             Err(Error::LabelMe)?
         }
@@ -55,10 +55,10 @@ pub async fn req(user: User, target: Ref, member: Ref) -> Result<()> {
 
         Message::create(
             "00000000000000000000000000".to_string(),
-            id,
+            id.clone(),
             format!("<@{}> removed <@{}> from the group.", user.id, member.id),
         )
-        .publish()
+        .publish(&channel)
         .await
         .ok();
 
diff --git a/src/routes/channels/message_send.rs b/src/routes/channels/message_send.rs
index ae06890..71a0f93 100644
--- a/src/routes/channels/message_send.rs
+++ b/src/routes/channels/message_send.rs
@@ -56,7 +56,7 @@ pub async fn req(user: User, target: Ref, message: Json<Data>) -> Result<JsonVal
         edited: None,
     };
 
-    msg.clone().publish().await?;
+    msg.clone().publish(&target).await?;
 
     Ok(json!(msg))
 }
diff --git a/src/routes/users/open_dm.rs b/src/routes/users/open_dm.rs
index 7066534..d36b664 100644
--- a/src/routes/users/open_dm.rs
+++ b/src/routes/users/open_dm.rs
@@ -40,6 +40,7 @@ pub async fn req(user: User, target: Ref) -> Result<JsonValue> {
                 id,
                 active: false,
                 recipients: vec![user.id, target.id],
+                last_message: None
             }
         };
 
-- 
GitLab