diff --git a/src/database/mutual.rs b/src/database/mutual.rs
index 5eb234169e2d19cfe7290918baa95aa9c84432bd..162dcc83e72681fb56c1df7614ae09d0abe08d32 100644
--- a/src/database/mutual.rs
+++ b/src/database/mutual.rs
@@ -1,7 +1,7 @@
-use super::get_collection;
+use super::{get_collection, MemberPermissions};
 
 use bson::doc;
-use mongodb::options::{FindOneOptions, FindOptions};
+use mongodb::options::FindOptions;
 
 pub fn find_mutual_guilds(user_id: &str, target_id: &str) -> Vec<String> {
     let col = get_collection("members");
@@ -79,23 +79,51 @@ pub fn find_mutual_groups(user_id: &str, target_id: &str) -> Vec<String> {
     }
 }
 
-pub fn has_mutual_connection(user_id: &str, target_id: &str) -> bool {
-    let col = get_collection("guilds");
-    if let Ok(result) = col.find_one(
+pub fn has_mutual_connection(user_id: &str, target_id: &str, with_permission: bool) -> bool {
+    let mut doc = doc! { "_id": 1 };
+
+    if with_permission {
+        doc.insert("default_permissions", 1);
+    }
+
+    let opt = FindOptions::builder().projection(doc);
+
+    if let Ok(result) = get_collection("guilds").find(
         doc! {
             "$and": [
                 { "members": { "$elemMatch": { "id": user_id   } } },
                 { "members": { "$elemMatch": { "id": target_id } } },
             ]
         },
-        FindOneOptions::builder()
-            .projection(doc! { "_id": 1 }) // ? TODO: fetch permissions
-            .build(),
-    ) {
-        if result.is_some() {
-            true
+        if with_permission {
+            opt.build()
         } else {
+            opt.limit(1).build()
+        },
+    ) {
+        if with_permission {
+            for item in result {
+                // ? logic should match permissions.rs#calculate
+                if let Ok(guild) = item {
+                    if guild.get_str("owner").unwrap() == user_id {
+                        return true;
+                    }
+
+                    let permissions = guild.get_i32("default_permissions").unwrap() as u32;
+
+                    if MemberPermissions([ permissions ]).get_send_direct_messages() {
+                        return true;
+                    }
+                }
+            }
+
             false
+        } else {
+            if result.count() > 0 {
+                true
+            } else {
+                false
+            }
         }
     } else {
         false
diff --git a/src/database/permissions.rs b/src/database/permissions.rs
index 29ebdbfd9b97f72206eedbabd8ba4610b520616a..ef51cd1641c7527d3049f1fab1ca6e1f83877252 100644
--- a/src/database/permissions.rs
+++ b/src/database/permissions.rs
@@ -19,7 +19,7 @@ pub enum Relationship {
     SELF = 6,
 }
 
-#[derive(Debug, PartialEq, Eq, TryFromPrimitive)]
+#[derive(Debug, PartialEq, Eq, TryFromPrimitive, Copy, Clone)]
 #[repr(u32)]
 pub enum Permission {
     Access = 1,
@@ -37,7 +37,7 @@ pub enum Permission {
 
 bitfield! {
     pub struct MemberPermissions(MSB0 [u32]);
-    u8;
+    u32;
     pub get_access, set_access: 31;
     pub get_create_invite, set_create_invite: 30;
     pub get_kick_members, set_kick_members: 29;
@@ -148,6 +148,7 @@ impl PermissionCalculator {
         let mut permissions: u32 = 0;
         if let Some(guild) = &self.guild {
             if let Some(_member) = &self.member {
+                // ? logic should match mutual.rs#has_mutual_connection
                 if guild.owner == self.user.id {
                     return u32::MAX;
                 }
@@ -162,9 +163,7 @@ impl PermissionCalculator {
                     if let Some(arr) = &channel.recipients {
                         let mut other_user = "";
                         for item in arr {
-                            if item == &self.user.id {
-                                permissions = 177;
-                            } else {
+                            if item != &self.user.id {
                                 other_user = item;
                             }
                         }
@@ -173,12 +172,16 @@ impl PermissionCalculator {
                         let relationship =
                             get_relationship_internal(&self.user.id, &other_user, &relationships);
 
-                        if relationship == Relationship::Blocked
+                        if relationship == Relationship::Friend {
+                            permissions = 177;
+                        } else if relationship == Relationship::Blocked
                             || relationship == Relationship::BlockedOther
                         {
                             permissions = 1;
-                        } else if has_mutual_connection(&self.user.id, other_user) {
+                        } else if has_mutual_connection(&self.user.id, other_user, true) {
                             permissions = 177;
+                        } else {
+                            permissions = 1;
                         }
                     }
                 }
diff --git a/src/routes/channel.rs b/src/routes/channel.rs
index c49574ed2979f21f3aa8eb4df2458cbe23a68689..bbee4f53a3e8b3ef9c01fb75b3b9dee4a5562419 100644
--- a/src/routes/channel.rs
+++ b/src/routes/channel.rs
@@ -431,6 +431,10 @@ pub fn send_message(
     let permissions = with_permissions!(user, target);
 
     if !permissions.get_send_messages() {
+        if target.channel_type == 0 {
+            return Some(Response::LackingPermission(Permission::SendDirectMessages));
+        }
+
         return Some(Response::LackingPermission(Permission::SendMessages));
     }
 
diff --git a/src/routes/mod.rs b/src/routes/mod.rs
index 2493df4fd4cd77b04083fa33d62effb59b2f88b6..aeeac189ecb5c64ba35ed1188dd08fc2d92a5ba8 100644
--- a/src/routes/mod.rs
+++ b/src/routes/mod.rs
@@ -50,8 +50,9 @@ impl<'a> rocket::response::Responder<'a> for Permission {
         rocket::response::Response::build()
             .header(ContentType::JSON)
             .sized_body(Cursor::new(format!(
-                "{{\"error\":\"Lacking {:?} permission.\"}}",
-                self
+                "{{\"error\":\"Lacking permission: {:?}.\",\"permission\":{}}}",
+                self,
+                self as u32,
             )))
             .ok()
     }
diff --git a/src/routes/user.rs b/src/routes/user.rs
index f2dee0fcbdc33ca696bd4b3d1174ee5c94256c4a..71ccc83f64fc27a261c6595407e16c2058f4b077 100644
--- a/src/routes/user.rs
+++ b/src/routes/user.rs
@@ -157,7 +157,7 @@ pub fn dm(user: UserRef, target: UserRef) -> Response {
 			).is_ok() {
                 Response::Success(json!({ "id": id.to_string() }))
             } else {
-                Response::InternalServerError(json!({ "error": "Failed to create new chanel." }))
+                Response::InternalServerError(json!({ "error": "Failed to create new channel." }))
             }
 		}
 	} else {