diff --git a/src/database/entities/message.rs b/src/database/entities/message.rs
index b73351588a85eed476ede33dd21001d98afab233..86d810ebe3dc2d28ea7e538e143e8bfaaf0971a7 100644
--- a/src/database/entities/message.rs
+++ b/src/database/entities/message.rs
@@ -59,7 +59,7 @@ impl Content {
             None,
             None
         )
-        .publish(&target)
+        .publish(&target, false)
         .await
     }
 }
@@ -109,7 +109,7 @@ impl Message {
         }
     }
 
-    pub async fn publish(self, channel: &Channel) -> Result<()> {
+    pub async fn publish(self, channel: &Channel, process_embeds: bool) -> Result<()> {
         get_collection("messages")
             .insert_one(to_bson(&self).unwrap().as_document().unwrap().clone(), None)
             .await
@@ -230,8 +230,11 @@ impl Message {
             });
         }
 
-        self.process_embed();
+        if process_embeds {
+            self.process_embed();
+        }
 
+        let mentions = self.mentions.clone();
         let enc = serde_json::to_string(&self).unwrap();
         ClientboundNotification::Message(self).publish(channel.id().to_string());
 
@@ -250,6 +253,11 @@ impl Message {
                         }
                     }
                 }
+                Channel::TextChannel { .. } => {
+                    if let Some(mut mentions) = mentions {
+                        target_ids.append(&mut mentions);
+                    }
+                }
                 _ => {}
             }
 
diff --git a/src/database/permissions/channel.rs b/src/database/permissions/channel.rs
index e05f4ce9f1ae154a3bc63d2f627c8981f372176a..712bb963715dadbe0304da45b657b70d9aa8fe68 100644
--- a/src/database/permissions/channel.rs
+++ b/src/database/permissions/channel.rs
@@ -15,6 +15,8 @@ pub enum ChannelPermission {
     ManageChannel = 0b00000000000000000000000000001000,  // 8
     VoiceCall = 0b00000000000000000000000000010000,      // 16
     InviteOthers = 0b00000000000000000000000000100000,   // 32
+    EmbedLinks = 0b00000000000000000000000001000000,     // 64
+    UploadFiles = 0b00000000000000000000000010000000,   // 128
 }
 
 impl_op_ex!(+ |a: &ChannelPermission, b: &ChannelPermission| -> u32 { *a as u32 | *b as u32 });
@@ -29,6 +31,8 @@ bitfield! {
     pub get_manage_channel, _: 28;
     pub get_voice_call, _: 27;
     pub get_invite_others, _: 26;
+    pub get_embed_links, _: 25;
+    pub get_upload_files, _: 24;
 }
 
 impl<'a> PermissionCalculator<'a> {
@@ -60,7 +64,9 @@ impl<'a> PermissionCalculator<'a> {
                         if perms.get_send_message() {
                             return Ok(ChannelPermission::View
                                 + ChannelPermission::SendMessage
-                                + ChannelPermission::VoiceCall);
+                                + ChannelPermission::VoiceCall
+                                + ChannelPermission::EmbedLinks
+                                + ChannelPermission::UploadFiles);
                         }
 
                         return Ok(ChannelPermission::View as u32);
@@ -79,7 +85,9 @@ impl<'a> PermissionCalculator<'a> {
                         + ChannelPermission::SendMessage
                         + ChannelPermission::ManageChannel
                         + ChannelPermission::VoiceCall
-                        + ChannelPermission::InviteOthers)
+                        + ChannelPermission::InviteOthers
+                        + ChannelPermission::EmbedLinks
+                        + ChannelPermission::UploadFiles)
                 } else {
                     Ok(0)
                 }
@@ -94,7 +102,9 @@ impl<'a> PermissionCalculator<'a> {
                     Ok(ChannelPermission::View
                         + ChannelPermission::SendMessage
                         + ChannelPermission::VoiceCall
-                        + ChannelPermission::InviteOthers)
+                        + ChannelPermission::InviteOthers
+                        + ChannelPermission::EmbedLinks
+                        + ChannelPermission::UploadFiles)
                 }
             }
         }
diff --git a/src/routes/channels/message_send.rs b/src/routes/channels/message_send.rs
index 18259d79123c0ff38fd7d5241404de771779e6d2..caba740a50b0e061d0ac810ccf4a2ebfa5d58338 100644
--- a/src/routes/channels/message_send.rs
+++ b/src/routes/channels/message_send.rs
@@ -54,7 +54,7 @@ pub async fn req(user: User, target: Ref, message: Json<Data>) -> Result<JsonVal
         .await?;
 
     if !perm.get_send_message() {
-        Err(Error::MissingPermission)?
+        return Err(Error::MissingPermission)
     }
 
     if get_collection("messages")
@@ -106,6 +106,10 @@ pub async fn req(user: User, target: Ref, message: Json<Data>) -> Result<JsonVal
 
     let mut attachments = vec![];
     if let Some(ids) = &message.attachments {
+        if ids.len() > 0 && !perm.get_embed_links() {
+            return Err(Error::MissingPermission)
+        }
+
         // ! FIXME: move this to app config
         if ids.len() >= 5 {
             return Err(Error::TooManyAttachments)
@@ -140,7 +144,7 @@ pub async fn req(user: User, target: Ref, message: Json<Data>) -> Result<JsonVal
         },
     };
 
-    msg.clone().publish(&target).await?;
+    msg.clone().publish(&target, perm.get_embed_links()).await?;
 
     Ok(json!(msg))
 }