diff --git a/Cargo.toml b/Cargo.toml
index 3a6e24f74291b450d5af8f6ecf9c2444ff2f7bf8..a1b03c36484e1cb235acc7b5f4462952e801510f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "revolt"
-version = "0.1.0"
+version = "0.2.0"
 authors = ["Paul Makles <paulmakles@gmail.com>"]
 edition = "2018"
 
diff --git a/src/database/message.rs b/src/database/message.rs
index c48c71ae87932f55d62c9abdeb02cdd4d0afed1a..96d671bfe649045d2d3cd8fe59fb19c0cce84373 100644
--- a/src/database/message.rs
+++ b/src/database/message.rs
@@ -2,7 +2,7 @@ use super::get_collection;
 use crate::guards::channel::ChannelRef;
 use crate::notifications;
 use crate::notifications::events::message::Create;
-use crate::notifications::events::Notification::MessageCreate;
+use crate::notifications::events::Notification;
 use crate::routes::channel::ChannelType;
 
 use bson::{doc, to_bson, UtcDateTime};
@@ -25,7 +25,7 @@ pub struct Message {
     pub content: String,
     pub edited: Option<UtcDateTime>,
 
-    pub previous_content: Option<Vec<PreviousEntry>>,
+    pub previous_content: Vec<PreviousEntry>,
 }
 
 // ? TODO: write global send message
@@ -37,19 +37,16 @@ impl Message {
             .insert_one(to_bson(&self).unwrap().as_document().unwrap().clone(), None)
             .is_ok()
         {
-            let data = MessageCreate(Create {
-                id: self.id.clone(),
-                nonce: self.nonce.clone(),
-                channel: self.channel.clone(),
-                author: self.author.clone(),
-                content: self.content.clone(),
-            });
-
-            match target.channel_type {
-                0..=1 => notifications::send_message_threaded(target.recipients.clone(), None, data),
-                2 => notifications::send_message_threaded(None, target.guild.clone(), data),
-                _ => unreachable!(),
-            };
+            notifications::send_message_given_channel(
+                Notification::message_create(Create {
+                    id: self.id.clone(),
+                    nonce: self.nonce.clone(),
+                    channel: self.channel.clone(),
+                    author: self.author.clone(),
+                    content: self.content.clone(),
+                }),
+                &target,
+            );
 
             let short_content: String = self.content.chars().take(24).collect();
 
diff --git a/src/notifications/events/groups.rs b/src/notifications/events/groups.rs
new file mode 100644
index 0000000000000000000000000000000000000000..876f13d163faa0a0b8545a6196301038926fb064
--- /dev/null
+++ b/src/notifications/events/groups.rs
@@ -0,0 +1,13 @@
+use serde::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct UserJoin {
+    pub id: String,
+    pub user: String,
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct UserLeave {
+    pub id: String,
+    pub user: String,
+}
diff --git a/src/notifications/events/guilds.rs b/src/notifications/events/guilds.rs
new file mode 100644
index 0000000000000000000000000000000000000000..3b1b95d2052ca750b17aa1f89d6b7151e8c31acb
--- /dev/null
+++ b/src/notifications/events/guilds.rs
@@ -0,0 +1,33 @@
+use serde::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct UserJoin {
+    pub id: String,
+    pub user: String,
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct UserLeave {
+    pub id: String,
+    pub user: String,
+    pub banned: bool,
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct ChannelCreate {
+    pub id: String,
+    pub channel: String,
+    pub name: String,
+    pub description: String,
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct ChannelDelete {
+    pub id: String,
+    pub channel: String,
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct Delete {
+    pub id: String,
+}
diff --git a/src/notifications/events/message.rs b/src/notifications/events/message.rs
index b668150b3845fe3c905c2da8afcbb158def84452..6398bae43a875916d87ceabd8645e1588f508581 100644
--- a/src/notifications/events/message.rs
+++ b/src/notifications/events/message.rs
@@ -8,3 +8,14 @@ pub struct Create {
     pub author: String,
     pub content: String,
 }
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct Edit {
+    pub id: String,
+    pub content: String,
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct Delete {
+    pub id: String,
+}
diff --git a/src/notifications/events/mod.rs b/src/notifications/events/mod.rs
index 70aa92da9c7e3350eb21f3663fafc602441a3db2..ec079fb1a51c2e313cae420469584c869f8f84aa 100644
--- a/src/notifications/events/mod.rs
+++ b/src/notifications/events/mod.rs
@@ -1,11 +1,25 @@
 use serde::{Deserialize, Serialize};
 use serde_json::{json, Value};
 
+pub mod groups;
+pub mod guilds;
 pub mod message;
+pub mod users;
 
+#[allow(non_camel_case_types)]
 #[derive(Serialize, Deserialize, Debug, Clone)]
 pub enum Notification {
-    MessageCreate(message::Create),
+    message_create(message::Create),
+    message_edit(message::Edit),
+    message_delete(message::Delete),
+    group_user_join(groups::UserJoin),
+    group_user_leave(groups::UserLeave),
+    guild_user_join(guilds::UserJoin),
+    guild_user_leave(guilds::UserLeave),
+    guild_channel_create(guilds::ChannelCreate),
+    guild_channel_delete(guilds::ChannelDelete),
+    guild_delete(guilds::Delete),
+    user_friend_status(users::FriendStatus),
 }
 
 impl Notification {
diff --git a/src/notifications/events/users.rs b/src/notifications/events/users.rs
new file mode 100644
index 0000000000000000000000000000000000000000..88617ebced6490c301fb21bbc937c28a304bc91f
--- /dev/null
+++ b/src/notifications/events/users.rs
@@ -0,0 +1,7 @@
+use serde::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct FriendStatus {
+    pub id: String,
+    pub status: i32,
+}
diff --git a/src/notifications/mod.rs b/src/notifications/mod.rs
index 4a2cb9a36eb67bfebdd2d5c39d9dc912ad6f072b..ae911814b26ec0111a95444b0fd5ad84ed7e7dd4 100644
--- a/src/notifications/mod.rs
+++ b/src/notifications/mod.rs
@@ -1,3 +1,5 @@
+use crate::guards::channel::ChannelRef;
+
 use once_cell::sync::OnceCell;
 use std::sync::mpsc::{channel, Sender};
 use std::thread;
@@ -62,3 +64,11 @@ pub fn send_message_threaded<U: Into<Option<Vec<String>>>, G: Into<Option<String
             .is_ok()
     }
 }
+
+pub fn send_message_given_channel(data: events::Notification, channel: &ChannelRef) {
+    match channel.channel_type {
+        0..=1 => send_message_threaded(channel.recipients.clone(), None, data),
+        2 => send_message_threaded(None, channel.guild.clone(), data),
+        _ => unreachable!(),
+    };
+}
diff --git a/src/notifications/pubsub.rs b/src/notifications/pubsub.rs
index 06d516be396be1160b656ca4a92d9dd3f8973c61..03e32111aaf3bee8b7946f794f6a6aec18b2d680 100644
--- a/src/notifications/pubsub.rs
+++ b/src/notifications/pubsub.rs
@@ -18,8 +18,6 @@ pub struct PubSubMessage {
 
     user_recipients: Option<Vec<String>>,
     target_guild: Option<String>,
-
-    notification_type: String,
     data: Notification,
 }
 
@@ -29,10 +27,6 @@ pub fn send_message(users: Option<Vec<String>>, guild: Option<String>, data: Not
         source: SOURCEID.get().unwrap().to_string(),
         user_recipients: users.into(),
         target_guild: guild.into(),
-        notification_type: match data {
-            Notification::MessageCreate(_) => "message_create",
-        }
-        .to_string(),
         data,
     };
 
diff --git a/src/routes/channel.rs b/src/routes/channel.rs
index 07c12f4dbc2e3dd50f1f1d12ea1a299885494e53..eb134e7f53e51361cbdd8d5ec24d271802cdd38f 100644
--- a/src/routes/channel.rs
+++ b/src/routes/channel.rs
@@ -5,6 +5,10 @@ use crate::database::{
 };
 use crate::guards::auth::UserRef;
 use crate::guards::channel::ChannelRef;
+use crate::notifications::{
+    self,
+    events::{groups::*, guilds::ChannelDelete, message::*, Notification},
+};
 use crate::util::vec_to_set;
 
 use bson::{doc, from_bson, Bson, Bson::UtcDatetime};
@@ -218,10 +222,18 @@ pub fn add_member(user: UserRef, target: ChannelRef, member: UserRef) -> Option<
                     author: "system".to_string(),
                     content: format!("<@{}> added <@{}> to the group.", &user.id, &member.id),
                     edited: None,
-                    previous_content: None,
+                    previous_content: vec![],
                 })
                 .send(&target)
                 {
+                    notifications::send_message_given_channel(
+                        Notification::group_user_join(UserJoin {
+                            id: target.id.clone(),
+                            user: member.id.clone(),
+                        }),
+                        &target,
+                    );
+
                     Some(Response::Result(super::Status::Ok))
                 } else {
                     Some(Response::PartialStatus(
@@ -285,10 +297,18 @@ pub fn remove_member(user: UserRef, target: ChannelRef, member: UserRef) -> Opti
             author: "system".to_string(),
             content: format!("<@{}> removed <@{}> from the group.", &user.id, &member.id),
             edited: None,
-            previous_content: None,
+            previous_content: vec![],
         })
         .send(&target)
         {
+            notifications::send_message_given_channel(
+                Notification::group_user_leave(UserLeave {
+                    id: target.id.clone(),
+                    user: member.id.clone(),
+                }),
+                &target,
+            );
+
             Some(Response::Result(super::Status::Ok))
         } else {
             Some(Response::PartialStatus(
@@ -327,7 +347,7 @@ pub fn delete(user: UserRef, target: ChannelRef) -> Option<Response> {
                 Some(Response::Result(super::Status::Ok))
             } else {
                 Some(Response::InternalServerError(
-                    json!({ "error": "Failed to delete group." }),
+                    json!({ "error": "Failed to delete channel." }),
                 ))
             }
         } else {
@@ -395,10 +415,18 @@ pub fn delete(user: UserRef, target: ChannelRef) -> Option<Response> {
                         author: "system".to_string(),
                         content: format!("<@{}> left the group.", &user.id),
                         edited: None,
-                        previous_content: None,
+                        previous_content: vec![],
                     })
                     .send(&target)
                     {
+                        notifications::send_message_given_channel(
+                            Notification::group_user_leave(UserLeave {
+                                id: target.id.clone(),
+                                user: user.id.clone(),
+                            }),
+                            &target,
+                        );
+
                         Some(Response::Result(super::Status::Ok))
                     } else {
                         Some(Response::PartialStatus(
@@ -413,9 +441,10 @@ pub fn delete(user: UserRef, target: ChannelRef) -> Option<Response> {
             }
         }
         2 => {
+            let guild_id = target.guild.unwrap();
             if database::get_collection("guilds")
                 .update_one(
-                    doc! { "_id": target.guild.unwrap() },
+                    doc! { "_id": &guild_id },
                     doc! {
                         "$pull": {
                             "invites": {
@@ -427,6 +456,15 @@ pub fn delete(user: UserRef, target: ChannelRef) -> Option<Response> {
                 )
                 .is_ok()
             {
+                notifications::send_message_threaded(
+                    None,
+                    guild_id.clone(),
+                    Notification::guild_channel_delete(ChannelDelete {
+                        id: guild_id.clone(),
+                        channel: target.id.clone(),
+                    }),
+                );
+
                 try_delete()
             } else {
                 Some(Response::InternalServerError(
@@ -512,7 +550,7 @@ pub fn send_message(
         author: user.id,
         content,
         edited: None,
-        previous_content: None,
+        previous_content: vec![],
     };
 
     if message.send(&target) {
@@ -533,28 +571,21 @@ pub fn get_message(user: UserRef, target: ChannelRef, message: Message) -> Optio
         return Some(Response::LackingPermission(Permission::ReadMessages));
     }
 
-    let prev =
-        // ! CHECK IF USER HAS PERMISSION TO VIEW EDITS OF MESSAGES
-        if let Some(previous) = message.previous_content {
-            let mut entries = vec![];
-            for entry in previous {
-                entries.push(json!({
-                    "content": entry.content,
-                    "time": entry.time.timestamp(),
-                }));
-            }
-
-            Some(entries)
-        } else {
-            None
-        };
+    // ! CHECK IF USER HAS PERMISSION TO VIEW EDITS OF MESSAGES
+    let mut entries = vec![];
+    for entry in message.previous_content {
+        entries.push(json!({
+            "content": entry.content,
+            "time": entry.time.timestamp(),
+        }));
+    }
 
     Some(Response::Success(json!({
         "id": message.id,
         "author": message.author,
         "content": message.content,
         "edited": if let Some(t) = message.edited { Some(t.timestamp()) } else { None },
-        "previous_content": prev,
+        "previous_content": entries,
     })))
 }
 
@@ -596,7 +627,7 @@ pub fn edit_message(
             },
             "$push": {
                 "previous_content": {
-                    "content": message.content,
+                    "content": &message.content,
                     "time": time,
                 }
             },
@@ -604,19 +635,13 @@ pub fn edit_message(
         None,
     ) {
         Ok(_) => {
-            /*websocket::queue_message(
-                get_recipients(&target),
-                json!({
-                    "type": "message_update",
-                    "data": {
-                        "id": message.id,
-                        "channel": target.id,
-                        "content": edit.content.clone(),
-                        "edited": edited.timestamp()
-                    },
-                })
-                .to_string(),
-            );*/
+            notifications::send_message_given_channel(
+                Notification::message_edit(Edit {
+                    id: message.id.clone(),
+                    content: message.content,
+                }),
+                &target,
+            );
 
             Some(Response::Result(super::Status::Ok))
         }
@@ -641,17 +666,12 @@ pub fn delete_message(user: UserRef, target: ChannelRef, message: Message) -> Op
 
     match col.delete_one(doc! { "_id": &message.id }, None) {
         Ok(_) => {
-            /*websocket::queue_message(
-                get_recipients(&target),
-                json!({
-                    "type": "message_delete",
-                    "data": {
-                        "id": message.id,
-                        "channel": target.id
-                    },
-                })
-                .to_string(),
-            );*/
+            notifications::send_message_given_channel(
+                Notification::message_delete(Delete {
+                    id: message.id.clone(),
+                }),
+                &target,
+            );
 
             Some(Response::Result(super::Status::Ok))
         }
diff --git a/src/routes/guild.rs b/src/routes/guild.rs
index e44b3daa3f77d05e8bcc076bef3d3a8bbfff2bb0..eb0d49c8a2e16900ebcb365830bcc1c8913e3e3b 100644
--- a/src/routes/guild.rs
+++ b/src/routes/guild.rs
@@ -4,6 +4,10 @@ use crate::database::{self, channel::Channel, Permission, PermissionCalculator};
 use crate::guards::auth::UserRef;
 use crate::guards::channel::ChannelRef;
 use crate::guards::guild::{get_invite, get_member, GuildRef};
+use crate::notifications::{
+    self,
+    events::{guilds::*, Notification},
+};
 use crate::util::gen_token;
 
 use bson::{doc, from_bson, Bson};
@@ -180,6 +184,14 @@ pub fn remove_guild(user: UserRef, target: GuildRef) -> Option<Response> {
                         )
                         .is_ok()
                     {
+                        notifications::send_message_threaded(
+                            None,
+                            target.id.clone(),
+                            Notification::guild_delete(Delete {
+                                id: target.id.clone(),
+                            }),
+                        );
+
                         Some(Response::Result(super::Status::Ok))
                     } else {
                         Some(Response::InternalServerError(
@@ -212,6 +224,16 @@ pub fn remove_guild(user: UserRef, target: GuildRef) -> Option<Response> {
             )
             .is_ok()
         {
+            notifications::send_message_threaded(
+                None,
+                target.id.clone(),
+                Notification::guild_user_leave(UserLeave {
+                    id: target.id.clone(),
+                    user: user.id.clone(),
+                    banned: false,
+                }),
+            );
+
             Some(Response::Result(super::Status::Ok))
         } else {
             Some(Response::InternalServerError(
@@ -268,13 +290,24 @@ pub fn create_channel(
                     "nonce": &nonce,
                     "type": 2,
                     "guild": &target.id,
-                    "name": name,
-                    "description": description,
+                    "name": &name,
+                    "description": &description,
                 },
                 None,
             )
             .is_ok()
         {
+            notifications::send_message_threaded(
+                None,
+                target.id.clone(),
+                Notification::guild_channel_create(ChannelCreate {
+                    id: target.id.clone(),
+                    channel: id.clone(),
+                    name: name.clone(),
+                    description: description.clone(),
+                }),
+            );
+
             Some(Response::Success(json!({ "id": &id })))
         } else {
             Some(Response::BadRequest(
@@ -442,6 +475,15 @@ pub fn use_invite(user: UserRef, code: String) -> Response {
                     )
                     .is_ok()
                 {
+                    notifications::send_message_threaded(
+                        None,
+                        guild_id.clone(),
+                        Notification::guild_user_join(UserJoin {
+                            id: guild_id.clone(),
+                            user: user.id.clone(),
+                        }),
+                    );
+
                     Response::Success(json!({
                         "guild": &guild_id,
                         "channel": &invite.channel,
@@ -636,6 +678,16 @@ pub fn kick_member(user: UserRef, target: GuildRef, other: String) -> Option<Res
         )
         .is_ok()
     {
+        notifications::send_message_threaded(
+            None,
+            target.id.clone(),
+            Notification::guild_user_leave(UserLeave {
+                id: target.id.clone(),
+                user: other.clone(),
+                banned: false,
+            }),
+        );
+
         Some(Response::Result(super::Status::Ok))
     } else {
         Some(Response::InternalServerError(
@@ -712,6 +764,16 @@ pub fn ban_member(
         )
         .is_ok()
     {
+        notifications::send_message_threaded(
+            None,
+            target.id.clone(),
+            Notification::guild_user_leave(UserLeave {
+                id: target.id.clone(),
+                user: other.clone(),
+                banned: true,
+            }),
+        );
+
         Some(Response::Result(super::Status::Ok))
     } else {
         Some(Response::InternalServerError(
diff --git a/src/routes/user.rs b/src/routes/user.rs
index 71ccc83f64fc27a261c6595407e16c2058f4b077..e41b1451067e09c01491e089155b7393e894e93b 100644
--- a/src/routes/user.rs
+++ b/src/routes/user.rs
@@ -1,6 +1,10 @@
 use super::Response;
 use crate::database::{self, get_relationship, get_relationship_internal, mutual, Relationship};
 use crate::guards::auth::UserRef;
+use crate::notifications::{
+    self,
+    events::{users::*, Notification},
+};
 use crate::routes::channel;
 
 use bson::doc;
@@ -32,7 +36,7 @@ pub fn user(user: UserRef, target: UserRef) -> Response {
     Response::Success(json!({
         "id": target.id,
         "username": target.username,
-        "relationship": get_relationship(&user, &target) as u8,
+        "relationship": get_relationship(&user, &target) as i32,
         "mutual": {
             "guilds": mutual::find_mutual_guilds(&user.id, &target.id),
             "friends": mutual::find_mutual_friends(&user.id, &target.id),
@@ -67,7 +71,7 @@ pub fn lookup(user: UserRef, query: Json<LookupQuery>) -> Response {
                 results.push(json!({
                     "id": id,
                     "username": doc.get_str("username").unwrap(),
-                    "relationship": get_relationship_internal(&user.id, &id, &relationships) as u8
+                    "relationship": get_relationship_internal(&user.id, &id, &relationships) as i32
                 }));
             }
         }
@@ -186,7 +190,7 @@ pub fn get_friends(user: UserRef) -> Response {
 /// retrieve friend status with user
 #[get("/<target>/friend")]
 pub fn get_friend(user: UserRef, target: UserRef) -> Response {
-    Response::Success(json!({ "status": get_relationship(&user, &target) as u8 }))
+    Response::Success(json!({ "status": get_relationship(&user, &target) as i32 }))
 }
 
 /// create or accept a friend request
@@ -218,8 +222,8 @@ pub fn add_friend(user: UserRef, target: UserRef) -> Response {
                 if col
                     .update_one(
                         doc! {
-                            "_id": target.id,
-                            "relations.id": user.id
+                            "_id": target.id.clone(),
+                            "relations.id": user.id.clone()
                         },
                         doc! {
                             "$set": {
@@ -230,7 +234,25 @@ pub fn add_friend(user: UserRef, target: UserRef) -> Response {
                     )
                     .is_ok()
                 {
-                    Response::Success(json!({ "status": Relationship::Friend as u8 }))
+                    notifications::send_message_threaded(
+                        vec![target.id.clone()],
+                        None,
+                        Notification::user_friend_status(FriendStatus {
+                            id: user.id.clone(),
+                            status: Relationship::Friend as i32,
+                        }),
+                    );
+
+                    notifications::send_message_threaded(
+                        vec![user.id.clone()],
+                        None,
+                        Notification::user_friend_status(FriendStatus {
+                            id: target.id.clone(),
+                            status: Relationship::Friend as i32,
+                        }),
+                    );
+
+                    Response::Success(json!({ "status": Relationship::Friend as i32 }))
                 } else {
                     Response::InternalServerError(
                         json!({ "error": "Failed to commit! Try re-adding them as a friend." }),
@@ -269,12 +291,12 @@ pub fn add_friend(user: UserRef, target: UserRef) -> Response {
                 if col
                     .update_one(
                         doc! {
-                            "_id": target.id
+                            "_id": target.id.clone()
                         },
                         doc! {
                             "$push": {
                                 "relations": {
-                                    "id": user.id,
+                                    "id": user.id.clone(),
                                     "status": Relationship::Incoming as i32
                                 }
                             }
@@ -283,7 +305,25 @@ pub fn add_friend(user: UserRef, target: UserRef) -> Response {
                     )
                     .is_ok()
                 {
-                    Response::Success(json!({ "status": Relationship::Outgoing as u8 }))
+                    notifications::send_message_threaded(
+                        vec![user.id.clone()],
+                        None,
+                        Notification::user_friend_status(FriendStatus {
+                            id: target.id.clone(),
+                            status: Relationship::Outgoing as i32,
+                        }),
+                    );
+
+                    notifications::send_message_threaded(
+                        vec![target.id.clone()],
+                        None,
+                        Notification::user_friend_status(FriendStatus {
+                            id: user.id.clone(),
+                            status: Relationship::Incoming as i32,
+                        }),
+                    );
+
+                    Response::Success(json!({ "status": Relationship::Outgoing as i32 }))
                 } else {
                     Response::InternalServerError(
                         json!({ "error": "Failed to commit! Try re-adding them as a friend." }),
@@ -327,12 +367,12 @@ pub fn remove_friend(user: UserRef, target: UserRef) -> Response {
                 if col
                     .update_one(
                         doc! {
-                            "_id": target.id
+                            "_id": target.id.clone()
                         },
                         doc! {
                             "$pull": {
                                 "relations": {
-                                    "id": user.id
+                                    "id": user.id.clone()
                                 }
                             }
                         },
@@ -340,7 +380,25 @@ pub fn remove_friend(user: UserRef, target: UserRef) -> Response {
                     )
                     .is_ok()
                 {
-                    Response::Success(json!({ "status": Relationship::NONE as u8 }))
+                    notifications::send_message_threaded(
+                        vec![user.id.clone()],
+                        None,
+                        Notification::user_friend_status(FriendStatus {
+                            id: target.id.clone(),
+                            status: Relationship::NONE as i32,
+                        }),
+                    );
+
+                    notifications::send_message_threaded(
+                        vec![target.id.clone()],
+                        None,
+                        Notification::user_friend_status(FriendStatus {
+                            id: user.id.clone(),
+                            status: Relationship::NONE as i32,
+                        }),
+                    );
+
+                    Response::Success(json!({ "status": Relationship::NONE as i32 }))
                 } else {
                     Response::InternalServerError(
                         json!({ "error": "Failed to commit! Target remains in same state." }),
@@ -365,7 +423,9 @@ pub fn block_user(user: UserRef, target: UserRef) -> Response {
     let col = database::get_collection("users");
 
     match get_relationship(&user, &target) {
-        Relationship::Friend | Relationship::Incoming | Relationship::Outgoing => {
+        Relationship::Friend
+        | Relationship::Incoming
+        | Relationship::Outgoing => {
             if col
                 .update_one(
                     doc! {
@@ -384,8 +444,8 @@ pub fn block_user(user: UserRef, target: UserRef) -> Response {
                 if col
                     .update_one(
                         doc! {
-                            "_id": target.id,
-                            "relations.id": user.id
+                            "_id": target.id.clone(),
+                            "relations.id": user.id.clone()
                         },
                         doc! {
                             "$set": {
@@ -396,7 +456,91 @@ pub fn block_user(user: UserRef, target: UserRef) -> Response {
                     )
                     .is_ok()
                 {
-                    Response::Success(json!({ "status": Relationship::Blocked as u8 }))
+                    notifications::send_message_threaded(
+                        vec![user.id.clone()],
+                        None,
+                        Notification::user_friend_status(FriendStatus {
+                            id: target.id.clone(),
+                            status: Relationship::Blocked as i32,
+                        }),
+                    );
+
+                    notifications::send_message_threaded(
+                        vec![target.id.clone()],
+                        None,
+                        Notification::user_friend_status(FriendStatus {
+                            id: user.id.clone(),
+                            status: Relationship::BlockedOther as i32,
+                        }),
+                    );
+
+                    Response::Success(json!({ "status": Relationship::Blocked as i32 }))
+                } else {
+                    Response::InternalServerError(
+                        json!({ "error": "Failed to commit! Try blocking the user again, remove it first." }),
+                    )
+                }
+            } else {
+                Response::InternalServerError(
+                    json!({ "error": "Failed to commit to database, try again." }),
+                )
+            }
+        }
+
+        Relationship::NONE => {
+            if col
+                .update_one(
+                    doc! {
+                        "_id": user.id.clone(),
+                    },
+                    doc! {
+                        "$push": {
+                            "relations": {
+                                "id": target.id.clone(),
+                                "status": Relationship::Blocked as i32,
+                            }
+                        }
+                    },
+                    None,
+                )
+                .is_ok()
+            {
+                if col
+                    .update_one(
+                        doc! {
+                            "_id": target.id.clone(),
+                        },
+                        doc! {
+                            "$push": {
+                                "relations": {
+                                    "id": user.id.clone(),
+                                    "status": Relationship::BlockedOther as i32,
+                                }
+                            }
+                        },
+                        None,
+                    )
+                    .is_ok()
+                {
+                    notifications::send_message_threaded(
+                        vec![user.id.clone()],
+                        None,
+                        Notification::user_friend_status(FriendStatus {
+                            id: target.id.clone(),
+                            status: Relationship::Blocked as i32,
+                        }),
+                    );
+
+                    notifications::send_message_threaded(
+                        vec![target.id.clone()],
+                        None,
+                        Notification::user_friend_status(FriendStatus {
+                            id: user.id.clone(),
+                            status: Relationship::BlockedOther as i32,
+                        }),
+                    );
+
+                    Response::Success(json!({ "status": Relationship::Blocked as i32 }))
                 } else {
                     Response::InternalServerError(
                         json!({ "error": "Failed to commit! Try blocking the user again, remove it first." }),
@@ -427,16 +571,23 @@ pub fn block_user(user: UserRef, target: UserRef) -> Response {
                 )
                 .is_ok()
             {
-                Response::Success(json!({ "status": Relationship::Blocked as u8 }))
+                notifications::send_message_threaded(
+                    vec![user.id.clone()],
+                    None,
+                    Notification::user_friend_status(FriendStatus {
+                        id: target.id.clone(),
+                        status: Relationship::Blocked as i32,
+                    }),
+                );
+
+                Response::Success(json!({ "status": Relationship::Blocked as i32 }))
             } else {
                 Response::InternalServerError(
                     json!({ "error": "Failed to commit to database, try again." }),
                 )
             }
         }
-        Relationship::SELF | Relationship::NONE => {
-            Response::BadRequest(json!({ "error": "This has no effect." }))
-        }
+        Relationship::SELF => Response::BadRequest(json!({ "error": "This has no effect." })),
     }
 }
 
@@ -463,7 +614,16 @@ pub fn unblock_user(user: UserRef, target: UserRef) -> Response {
                     )
                     .is_ok()
                 {
-                    Response::Success(json!({ "status": Relationship::BlockedOther as u8 }))
+                    notifications::send_message_threaded(
+                        vec![user.id.clone()],
+                        None,
+                        Notification::user_friend_status(FriendStatus {
+                            id: target.id.clone(),
+                            status: Relationship::BlockedOther as i32,
+                        }),
+                    );
+
+                    Response::Success(json!({ "status": Relationship::BlockedOther as i32 }))
                 } else {
                     Response::InternalServerError(
                         json!({ "error": "Failed to commit to database, try again." }),
@@ -490,12 +650,12 @@ pub fn unblock_user(user: UserRef, target: UserRef) -> Response {
                     if col
                         .update_one(
                             doc! {
-                                "_id": target.id
+                                "_id": target.id.clone()
                             },
                             doc! {
                                 "$pull": {
                                     "relations": {
-                                        "id": user.id
+                                        "id": user.id.clone()
                                     }
                                 }
                             },
@@ -503,7 +663,25 @@ pub fn unblock_user(user: UserRef, target: UserRef) -> Response {
                         )
                         .is_ok()
                     {
-                        Response::Success(json!({ "status": Relationship::NONE as u8 }))
+                        notifications::send_message_threaded(
+                            vec![user.id.clone()],
+                            None,
+                            Notification::user_friend_status(FriendStatus {
+                                id: target.id.clone(),
+                                status: Relationship::NONE as i32,
+                            }),
+                        );
+
+                        notifications::send_message_threaded(
+                            vec![target.id.clone()],
+                            None,
+                            Notification::user_friend_status(FriendStatus {
+                                id: user.id.clone(),
+                                status: Relationship::NONE as i32,
+                            }),
+                        );
+
+                        Response::Success(json!({ "status": Relationship::NONE as i32 }))
                     } else {
                         Response::InternalServerError(
                             json!({ "error": "Failed to commit! Target remains in same state." }),