From 6253a91276e567f72f716b8c2420d275dd558443 Mon Sep 17 00:00:00 2001
From: Paul Makles <paulmakles@gmail.com>
Date: Mon, 28 Dec 2020 15:21:11 +0000
Subject: [PATCH] Move all entities to their own folder.

---
 src/database/channel.rs          | 217 --------------------
 src/database/entities/channel.rs |  31 +++
 src/database/entities/guild.rs   |  43 ++++
 src/database/entities/message.rs |  22 ++
 src/database/entities/mod.rs     |   4 +
 src/database/entities/user.rs    |  15 ++
 src/database/guards/mod.rs       |  19 ++
 src/database/guild.rs            | 341 -------------------------------
 src/database/message.rs          | 120 -----------
 src/database/mod.rs              |  10 +-
 src/database/mutual.rs           | 130 ------------
 src/database/permissions.rs      | 228 ---------------------
 src/database/user.rs             | 307 ----------------------------
 13 files changed, 135 insertions(+), 1352 deletions(-)
 delete mode 100644 src/database/channel.rs
 create mode 100644 src/database/entities/channel.rs
 create mode 100644 src/database/entities/guild.rs
 create mode 100644 src/database/entities/message.rs
 create mode 100644 src/database/entities/mod.rs
 create mode 100644 src/database/entities/user.rs
 create mode 100644 src/database/guards/mod.rs
 delete mode 100644 src/database/guild.rs
 delete mode 100644 src/database/message.rs
 delete mode 100644 src/database/mutual.rs
 delete mode 100644 src/database/permissions.rs
 delete mode 100644 src/database/user.rs

diff --git a/src/database/channel.rs b/src/database/channel.rs
deleted file mode 100644
index a1bfaa1..0000000
--- a/src/database/channel.rs
+++ /dev/null
@@ -1,217 +0,0 @@
-use super::get_collection;
-
-use lru::LruCache;
-use mongodb::bson::{doc, from_bson, Bson};
-use rocket::http::RawStr;
-use rocket::request::FromParam;
-use rocket_contrib::json::JsonValue;
-use serde::{Deserialize, Serialize};
-use std::sync::{Arc, Mutex};
-use rocket::futures::StreamExt;
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-pub struct LastMessage {
-    // message id
-    id: String,
-    // author's id
-    user_id: String,
-    // truncated content with author's name prepended (for GDM / GUILD)
-    short_content: String,
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-pub struct Channel {
-    #[serde(rename = "_id")]
-    pub id: String,
-    #[serde(rename = "type")]
-    pub channel_type: u8,
-
-    // DM: whether the DM is active
-    pub active: Option<bool>,
-    // DM + GDM: last message in channel
-    pub last_message: Option<LastMessage>,
-    // DM + GDM: recipients for channel
-    pub recipients: Option<Vec<String>>,
-    // GDM: owner of group
-    pub owner: Option<String>,
-    // GUILD: channel parent
-    pub guild: Option<String>,
-    // GUILD + GDM: channel name
-    pub name: Option<String>,
-    // GUILD + GDM: channel description
-    pub description: Option<String>,
-}
-
-impl Channel {
-    pub fn serialise(self) -> JsonValue {
-        match self.channel_type {
-            0 => json!({
-                "id": self.id,
-                "type": self.channel_type,
-                "last_message": self.last_message,
-                "recipients": self.recipients,
-            }),
-            1 => json!({
-                "id": self.id,
-                "type": self.channel_type,
-                "last_message": self.last_message,
-                "recipients": self.recipients,
-                "name": self.name,
-                "owner": self.owner,
-                "description": self.description,
-            }),
-            2 => json!({
-                "id": self.id,
-                "type": self.channel_type,
-                "guild": self.guild,
-                "name": self.name,
-                "description": self.description,
-            }),
-            _ => unreachable!(),
-        }
-    }
-}
-
-lazy_static! {
-    static ref CACHE: Arc<Mutex<LruCache<String, Channel>>> =
-        Arc::new(Mutex::new(LruCache::new(4_000_000)));
-}
-
-pub async fn fetch_channel(id: &str) -> Result<Option<Channel>, String> {
-    {
-        if let Ok(mut cache) = CACHE.lock() {
-            let existing = cache.get(&id.to_string());
-
-            if let Some(channel) = existing {
-                return Ok(Some((*channel).clone()));
-            }
-        } else {
-            return Err("Failed to lock cache.".to_string());
-        }
-    }
-
-    let col = get_collection("channels");
-    if let Ok(result) = col.find_one(doc! { "_id": id }, None).await {
-        if let Some(doc) = result {
-            if let Ok(channel) = from_bson(Bson::Document(doc)) as Result<Channel, _> {
-                let mut cache = CACHE.lock().unwrap();
-                cache.put(id.to_string(), channel.clone());
-
-                Ok(Some(channel))
-            } else {
-                Err("Failed to deserialize channel!".to_string())
-            }
-        } else {
-            Ok(None)
-        }
-    } else {
-        Err("Failed to fetch channel from database.".to_string())
-    }
-}
-
-pub async fn fetch_channels(ids: &Vec<String>) -> Result<Vec<Channel>, String> {
-    let mut missing = vec![];
-    let mut channels = vec![];
-
-    {
-        if let Ok(mut cache) = CACHE.lock() {
-            for id in ids {
-                let existing = cache.get(id);
-
-                if let Some(channel) = existing {
-                    channels.push((*channel).clone());
-                } else {
-                    missing.push(id);
-                }
-            }
-        } else {
-            return Err("Failed to lock cache.".to_string());
-        }
-    }
-
-    if missing.len() == 0 {
-        return Ok(channels);
-    }
-
-    let col = get_collection("channels");
-    if let Ok(mut result) = col.find(doc! { "_id": { "$in": missing } }, None).await {
-        while let Some(item) = result.next().await {
-            let mut cache = CACHE.lock().unwrap();
-            if let Ok(doc) = item {
-                if let Ok(channel) = from_bson(Bson::Document(doc)) as Result<Channel, _> {
-                    cache.put(channel.id.clone(), channel.clone());
-                    channels.push(channel);
-                } else {
-                    return Err("Failed to deserialize channel!".to_string());
-                }
-            } else {
-                return Err("Failed to fetch channel.".to_string());
-            }
-        }
-
-        Ok(channels)
-    } else {
-        Err("Failed to fetch channel from database.".to_string())
-    }
-}
-
-impl<'r> FromParam<'r> for Channel {
-    type Error = &'r RawStr;
-
-    fn from_param(param: &'r RawStr) -> Result<Self, Self::Error> {
-        Err(param)
-        /*if let Ok(result) = fetch_channel(param).await {
-            if let Some(channel) = result {
-                Ok(channel)
-            } else {
-                Err(param)
-            }
-        } else {
-            Err(param)
-        }*/
-    }
-}
-
-/*use crate::notifications::events::Notification;
-
-pub fn process_event(event: &Notification) {
-    match event {
-        Notification::group_user_join(ev) => {
-            let mut cache = CACHE.lock().unwrap();
-            if let Some(channel) = cache.peek_mut(&ev.id) {
-                channel.recipients.as_mut().unwrap().push(ev.user.clone());
-            }
-        }
-        Notification::group_user_leave(ev) => {
-            let mut cache = CACHE.lock().unwrap();
-            if let Some(channel) = cache.peek_mut(&ev.id) {
-                let recipients = channel.recipients.as_mut().unwrap();
-                if let Some(pos) = recipients.iter().position(|x| *x == ev.user) {
-                    recipients.remove(pos);
-                }
-            }
-        }
-        Notification::guild_channel_create(ev) => {
-            let mut cache = CACHE.lock().unwrap();
-            cache.put(
-                ev.id.clone(),
-                Channel {
-                    id: ev.channel.clone(),
-                    channel_type: 2,
-                    active: None,
-                    last_message: None,
-                    recipients: None,
-                    owner: None,
-                    guild: Some(ev.id.clone()),
-                    name: Some(ev.name.clone()),
-                    description: Some(ev.description.clone()),
-                },
-            );
-        }
-        Notification::guild_channel_delete(ev) => {
-            let mut cache = CACHE.lock().unwrap();
-            cache.pop(&ev.channel);
-        }
-        _ => {}
-    }
-}*/
diff --git a/src/database/entities/channel.rs b/src/database/entities/channel.rs
new file mode 100644
index 0000000..413b7f1
--- /dev/null
+++ b/src/database/entities/channel.rs
@@ -0,0 +1,31 @@
+use serde::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct LastMessage {
+    id: String,
+    user_id: String,
+    short_content: String,
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct Channel {
+    #[serde(rename = "_id")]
+    pub id: String,
+    #[serde(rename = "type")]
+    pub channel_type: u8,
+
+    // DM: whether the DM is active
+    pub active: Option<bool>,
+    // DM + GDM: last message in channel
+    pub last_message: Option<LastMessage>,
+    // DM + GDM: recipients for channel
+    pub recipients: Option<Vec<String>>,
+    // GDM: owner of group
+    pub owner: Option<String>,
+    // GUILD: channel parent
+    pub guild: Option<String>,
+    // GUILD + GDM: channel name
+    pub name: Option<String>,
+    // GUILD + GDM: channel description
+    pub description: Option<String>,
+}
diff --git a/src/database/entities/guild.rs b/src/database/entities/guild.rs
new file mode 100644
index 0000000..ee5a54e
--- /dev/null
+++ b/src/database/entities/guild.rs
@@ -0,0 +1,43 @@
+use serde::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct MemberCompositeKey {
+    pub guild: String,
+    pub user: String,
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct Member {
+    #[serde(rename = "_id")]
+    pub id: MemberCompositeKey,
+    pub nickname: Option<String>,
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct Invite {
+    pub code: String,
+    pub creator: String,
+    pub channel: String,
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct Ban {
+    pub id: String,
+    pub reason: String,
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct Guild {
+    #[serde(rename = "_id")]
+    pub id: String,
+    // pub nonce: String, used internally
+    pub name: String,
+    pub description: String,
+    pub owner: String,
+
+    pub channels: Vec<String>,
+    pub invites: Vec<Invite>,
+    pub bans: Vec<Ban>,
+
+    pub default_permissions: u32,
+}
diff --git a/src/database/entities/message.rs b/src/database/entities/message.rs
new file mode 100644
index 0000000..9f8c233
--- /dev/null
+++ b/src/database/entities/message.rs
@@ -0,0 +1,22 @@
+use mongodb::bson::DateTime;
+use serde::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct PreviousEntry {
+    pub content: String,
+    pub time: DateTime,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct Message {
+    #[serde(rename = "_id")]
+    pub id: String,
+    pub nonce: Option<String>,
+    pub channel: String,
+    pub author: String,
+
+    pub content: String,
+    pub edited: Option<DateTime>,
+
+    pub previous_content: Vec<PreviousEntry>,
+}
diff --git a/src/database/entities/mod.rs b/src/database/entities/mod.rs
new file mode 100644
index 0000000..4ad9863
--- /dev/null
+++ b/src/database/entities/mod.rs
@@ -0,0 +1,4 @@
+pub mod channel;
+pub mod message;
+pub mod guild;
+pub mod user;
\ No newline at end of file
diff --git a/src/database/entities/user.rs b/src/database/entities/user.rs
new file mode 100644
index 0000000..2e44ed6
--- /dev/null
+++ b/src/database/entities/user.rs
@@ -0,0 +1,15 @@
+use serde::{Deserialize, Serialize};
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct Relationship {
+    pub id: String,
+    pub status: u8,
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
+pub struct User {
+    #[serde(rename = "_id")]
+    pub id: String,
+    pub username: Option<String>,
+    pub relations: Option<Vec<Relationship>>,
+}
diff --git a/src/database/guards/mod.rs b/src/database/guards/mod.rs
new file mode 100644
index 0000000..e308776
--- /dev/null
+++ b/src/database/guards/mod.rs
@@ -0,0 +1,19 @@
+/**
+// ! FIXME
+impl<'r> FromParam<'r> for User {
+    type Error = &'r RawStr;
+
+    fn from_param(param: &'r RawStr) -> Result<Self, Self::Error> {
+        Err(param)
+        /*if let Ok(result) = fetch_channel(param).await {
+            if let Some(channel) = result {
+                Ok(channel)
+            } else {
+                Err(param)
+            }
+        } else {
+            Err(param)
+        }*/
+    }
+}
+*/
diff --git a/src/database/guild.rs b/src/database/guild.rs
deleted file mode 100644
index b8243f3..0000000
--- a/src/database/guild.rs
+++ /dev/null
@@ -1,341 +0,0 @@
-use super::channel::fetch_channels;
-use super::get_collection;
-
-use lru::LruCache;
-use rocket::futures::StreamExt;
-use mongodb::bson::{doc, from_bson, Bson};
-use rocket::http::RawStr;
-use rocket::request::FromParam;
-use rocket_contrib::json::JsonValue;
-use serde::{Deserialize, Serialize};
-use std::sync::{Arc, Mutex};
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-pub struct MemberRef {
-    pub guild: String,
-    pub user: String,
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-pub struct Member {
-    #[serde(rename = "_id")]
-    pub id: MemberRef,
-    pub nickname: Option<String>,
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-pub struct Invite {
-    pub code: String,
-    pub creator: String,
-    pub channel: String,
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-pub struct Ban {
-    pub id: String,
-    pub reason: String,
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-pub struct Guild {
-    #[serde(rename = "_id")]
-    pub id: String,
-    // pub nonce: String, used internally
-    pub name: String,
-    pub description: String,
-    pub owner: String,
-
-    pub channels: Vec<String>,
-    pub invites: Vec<Invite>,
-    pub bans: Vec<Ban>,
-
-    pub default_permissions: u32,
-}
-
-impl Guild {
-    pub fn serialise(self) -> JsonValue {
-        json!({
-            "id": self.id,
-            "name": self.name,
-            "description": self.description,
-            "owner": self.owner
-        })
-    }
-
-    pub async fn fetch_channels(&self) -> Result<Vec<super::channel::Channel>, String> {
-        super::channel::fetch_channels(&self.channels).await
-    }
-
-    pub async fn seralise_with_channels(self) -> Result<JsonValue, String> {
-        let channels = self
-            .fetch_channels()
-            .await?
-            .into_iter()
-            .map(|x| x.serialise())
-            .collect();
-
-        let mut value = self.serialise();
-        value
-            .as_object_mut()
-            .unwrap()
-            .insert("channels".to_string(), channels);
-        Ok(value)
-    }
-}
-
-#[derive(Hash, Eq, PartialEq)]
-pub struct MemberKey(pub String, pub String);
-
-lazy_static! {
-    static ref CACHE: Arc<Mutex<LruCache<String, Guild>>> =
-        Arc::new(Mutex::new(LruCache::new(4_000_000)));
-    static ref MEMBER_CACHE: Arc<Mutex<LruCache<MemberKey, Member>>> =
-        Arc::new(Mutex::new(LruCache::new(4_000_000)));
-}
-
-pub async fn fetch_guild(id: &str) -> Result<Option<Guild>, String> {
-    {
-        if let Ok(mut cache) = CACHE.lock() {
-            let existing = cache.get(&id.to_string());
-
-            if let Some(guild) = existing {
-                return Ok(Some((*guild).clone()));
-            }
-        } else {
-            return Err("Failed to lock cache.".to_string());
-        }
-    }
-
-    let col = get_collection("guilds");
-    if let Ok(result) = col.find_one(doc! { "_id": id }, None).await {
-        if let Some(doc) = result {
-            dbg!(doc.to_string());
-            if let Ok(guild) = from_bson(Bson::Document(doc)) as Result<Guild, _> {
-                let mut cache = CACHE.lock().unwrap();
-                cache.put(id.to_string(), guild.clone());
-
-                Ok(Some(guild))
-            } else {
-                Err("Failed to deserialize guild!".to_string())
-            }
-        } else {
-            Ok(None)
-        }
-    } else {
-        Err("Failed to fetch guild from database.".to_string())
-    }
-}
-
-pub async fn fetch_guilds(ids: &Vec<String>) -> Result<Vec<Guild>, String> {
-    let mut missing = vec![];
-    let mut guilds = vec![];
-
-    {
-        if let Ok(mut cache) = CACHE.lock() {
-            for id in ids {
-                let existing = cache.get(id);
-
-                if let Some(guild) = existing {
-                    guilds.push((*guild).clone());
-                } else {
-                    missing.push(id);
-                }
-            }
-        } else {
-            return Err("Failed to lock cache.".to_string());
-        }
-    }
-
-    if missing.len() == 0 {
-        return Ok(guilds);
-    }
-
-    let col = get_collection("guilds");
-    if let Ok(mut result) = col.find(doc! { "_id": { "$in": missing } }, None).await {
-        if let Some(item) = result.next().await {
-            let mut cache = CACHE.lock().unwrap();
-            if let Ok(doc) = item {
-                dbg!(doc.to_string());
-                if let Ok(guild) = from_bson(Bson::Document(doc)) as Result<Guild, _> {
-                    cache.put(guild.id.clone(), guild.clone());
-                    guilds.push(guild);
-                } else {
-                    return Err("Failed to deserialize guild!".to_string());
-                }
-            } else {
-                return Err("Failed to fetch guild.".to_string());
-            }
-        }
-
-        Ok(guilds)
-    } else {
-        Err("Failed to fetch channel from database.".to_string())
-    }
-}
-
-pub async fn serialise_guilds_with_channels(ids: &Vec<String>) -> Result<Vec<JsonValue>, String> {
-    let guilds = fetch_guilds(&ids).await?;
-    let cids: Vec<String> = guilds.iter().flat_map(|x| x.channels.clone()).collect();
-
-    let channels = fetch_channels(&cids).await?;
-    Ok(guilds
-        .into_iter()
-        .map(|x| {
-            let id = x.id.clone();
-            let mut obj = x.serialise();
-            obj.as_object_mut().unwrap().insert(
-                "channels".to_string(),
-                channels
-                    .iter()
-                    .filter(|x| x.guild.is_some() && x.guild.as_ref().unwrap() == &id)
-                    .map(|x| x.clone().serialise())
-                    .collect(),
-            );
-            obj
-        })
-        .collect())
-}
-
-pub async fn fetch_member(key: MemberKey) -> Result<Option<Member>, String> {
-    {
-        if let Ok(mut cache) = MEMBER_CACHE.lock() {
-            let existing = cache.get(&key);
-
-            if let Some(member) = existing {
-                return Ok(Some((*member).clone()));
-            }
-        } else {
-            return Err("Failed to lock cache.".to_string());
-        }
-    }
-
-    let col = get_collection("members");
-    if let Ok(result) = col.find_one(
-        doc! {
-            "_id.guild": &key.0,
-            "_id.user": &key.1,
-        },
-        None,
-    ).await {
-        if let Some(doc) = result {
-            if let Ok(member) = from_bson(Bson::Document(doc)) as Result<Member, _> {
-                let mut cache = MEMBER_CACHE.lock().unwrap();
-                cache.put(key, member.clone());
-
-                Ok(Some(member))
-            } else {
-                Err("Failed to deserialize member!".to_string())
-            }
-        } else {
-            Ok(None)
-        }
-    } else {
-        Err("Failed to fetch member from database.".to_string())
-    }
-}
-
-impl<'r> FromParam<'r> for Guild {
-    type Error = &'r RawStr;
-
-    fn from_param(param: &'r RawStr) -> Result<Self, Self::Error> {
-        Err(param)
-        /*if let Ok(result) = fetch_guild(param) {
-            if let Some(channel) = result {
-                Ok(channel)
-            } else {
-                Err(param)
-            }
-        } else {
-            Err(param)
-        }*/
-    }
-}
-
-pub async fn get_invite<U: Into<Option<String>>>(
-    code: &String,
-    user: U,
-) -> Option<(String, String, Invite)> {
-    let mut doc = doc! {
-        "invites": {
-            "$elemMatch": {
-                "code": &code
-            }
-        }
-    };
-
-    if let Some(user_id) = user.into() {
-        doc.insert(
-            "bans",
-            doc! {
-                "$not": {
-                    "$elemMatch": {
-                        "id": user_id
-                    }
-                }
-            },
-        );
-    }
-
-    if let Ok(result) = get_collection("guilds").find_one(
-        doc,
-        mongodb::options::FindOneOptions::builder()
-            .projection(doc! {
-                "_id": 1,
-                "name": 1,
-                "invites.$": 1,
-            })
-            .build(),
-    ).await {
-        if let Some(doc) = result {
-            let invite = doc
-                .get_array("invites")
-                .unwrap()
-                .iter()
-                .next()
-                .unwrap()
-                .as_document()
-                .unwrap();
-
-            Some((
-                doc.get_str("_id").unwrap().to_string(),
-                doc.get_str("name").unwrap().to_string(),
-                from_bson(Bson::Document(invite.clone())).unwrap(),
-            ))
-        } else {
-            None
-        }
-    } else {
-        None
-    }
-}
-
-/*use crate::notifications::events::Notification;
-
-pub fn process_event(event: &Notification) {
-    match event {
-        Notification::guild_channel_create(_ev) => {} // ? for later use
-        Notification::guild_channel_delete(_ev) => {} // ? for later use
-        Notification::guild_delete(ev) => {
-            let mut cache = CACHE.lock().unwrap();
-            cache.pop(&ev.id);
-        }
-        Notification::guild_user_join(ev) => {
-            let mut cache = MEMBER_CACHE.lock().unwrap();
-            cache.put(
-                MemberKey(ev.id.clone(), ev.user.clone()),
-                Member {
-                    id: MemberRef {
-                        guild: ev.id.clone(),
-                        user: ev.user.clone(),
-                    },
-                    nickname: None,
-                },
-            );
-        }
-        Notification::guild_user_leave(ev) => {
-            let mut cache = MEMBER_CACHE.lock().unwrap();
-            cache.pop(&MemberKey(ev.id.clone(), ev.user.clone()));
-        }
-        _ => {}
-    }
-}*/
diff --git a/src/database/message.rs b/src/database/message.rs
deleted file mode 100644
index f03e747..0000000
--- a/src/database/message.rs
+++ /dev/null
@@ -1,120 +0,0 @@
-use super::get_collection;
-use crate::database::channel::Channel;
-use crate::pubsub::hive;
-use crate::routes::channel::ChannelType;
-
-//use mongodb::bson::from_bson;
-//use rocket::futures::StreamExt;
-//use mongodb::bson::{doc, to_bson, Bson, DateTime};
-use mongodb::bson::{doc, to_bson, DateTime};
-use rocket::http::RawStr;
-use rocket::request::FromParam;
-use serde::{Deserialize, Serialize};
-
-use log::warn;
-
-#[derive(Serialize, Deserialize, Debug)]
-pub struct PreviousEntry {
-    pub content: String,
-    pub time: DateTime,
-}
-
-#[derive(Serialize, Deserialize, Debug)]
-pub struct Message {
-    #[serde(rename = "_id")]
-    pub id: String,
-    pub nonce: Option<String>,
-    pub channel: String,
-    pub author: String,
-
-    pub content: String,
-    pub edited: Option<DateTime>,
-
-    pub previous_content: Vec<PreviousEntry>,
-}
-
-// ? TODO: write global send message
-// ? pub fn send_message();
-// ? handle websockets?
-impl Message {
-    pub async fn send(&self, target: &Channel) -> bool {
-        if get_collection("messages")
-            .insert_one(to_bson(&self).unwrap().as_document().unwrap().clone(), None)
-            .await
-            .is_ok()
-        {
-            if hive::publish(
-                &target.id,
-                crate::pubsub::events::Notification::message_create(
-                    crate::pubsub::events::message::Create {
-                        id: self.id.clone(),
-                        nonce: self.nonce.clone(),
-                        channel: self.channel.clone(),
-                        author: self.author.clone(),
-                        content: self.content.clone(),
-                    },
-                ),
-            )
-            .is_err()
-            {
-                warn!("Saved message but couldn't send notification.");
-            }
-
-            let short_content: String = self.content.chars().take(24).collect();
-
-            // !! this stuff can be async
-            if target.channel_type == ChannelType::DM as u8
-                || target.channel_type == ChannelType::GROUPDM as u8
-            {
-                let mut update = doc! {
-                    "$set": {
-                        "last_message": {
-                            "id": &self.id,
-                            "user_id": &self.author,
-                            "short_content": short_content,
-                        }
-                    }
-                };
-
-                if target.channel_type == ChannelType::DM as u8 {
-                    update
-                        .get_document_mut("$set")
-                        .unwrap()
-                        .insert("active", true);
-                }
-
-                if get_collection("channels")
-                    .update_one(doc! { "_id": &target.id }, update, None)
-                    .await
-                    .is_ok()
-                {
-                    true
-                } else {
-                    false
-                }
-            } else {
-                true
-            }
-        } else {
-            false
-        }
-    }
-}
-
-impl<'r> FromParam<'r> for Message {
-    type Error = &'r RawStr;
-
-    fn from_param(param: &'r RawStr) -> Result<Self, Self::Error> {
-        Err(param)
-        /*let col = get_collection("messages");
-        let result = col
-            .find_one(doc! { "_id": param.to_string() }, None)
-            .unwrap();
-
-        if let Some(message) = result {
-            Ok(from_bson(Bson::Document(message)).expect("Failed to unwrap message."))
-        } else {
-            Err(param)
-        }*/
-    }
-}
diff --git a/src/database/mod.rs b/src/database/mod.rs
index 118e0fa..5f5810a 100644
--- a/src/database/mod.rs
+++ b/src/database/mod.rs
@@ -27,12 +27,4 @@ pub fn get_collection(collection: &str) -> Collection {
 }
 
 pub mod migrations;
-
-// pub mod channel;
-// pub mod guild;
-// pub mod message;
-// pub mod mutual;
-// pub mod permissions;
-// pub mod user;
-
-// pub use permissions::*;
+pub mod entities;
diff --git a/src/database/mutual.rs b/src/database/mutual.rs
deleted file mode 100644
index 1304840..0000000
--- a/src/database/mutual.rs
+++ /dev/null
@@ -1,130 +0,0 @@
-use super::{get_collection, MemberPermissions};
-
-use mongodb::bson::{doc, Document};
-use mongodb::options::FindOptions;
-use rocket::futures::StreamExt;
-
-pub async fn find_mutual_guilds(user_id: &str, target_id: &str) -> Vec<String> {
-    let col = get_collection("members");
-    if let Ok(mut result) = col.find(
-        doc! {
-            "$and": [
-                { "id": user_id   },
-                { "id": target_id },
-            ]
-        },
-        FindOptions::builder().projection(doc! { "_id": 1 }).build(),
-    ).await {
-        let mut results = vec![];
-
-        while let Some(doc) = result.next().await {
-            if let Ok(guild) = doc {
-                results.push(guild.get_str("_id").unwrap().to_string());
-            }
-        }
-
-        results
-    } else {
-        vec![]
-    }
-}
-
-pub async fn find_mutual_friends(user_id: &str, target_id: &str) -> Vec<String> {
-    let col = get_collection("users");
-    if let Ok(mut result) = col.find(
-        doc! {
-            "$and": [
-                { "relations": { "$elemMatch": { "id": user_id,   "status": 0 } } },
-                { "relations": { "$elemMatch": { "id": target_id, "status": 0 } } },
-            ]
-        },
-        FindOptions::builder().projection(doc! { "_id": 1 }).build(),
-    ).await {
-        let mut results = vec![];
-
-        while let Some(doc) = result.next().await {
-            if let Ok(user) = doc {
-                results.push(user.get_str("_id").unwrap().to_string());
-            }
-        }
-
-        results
-    } else {
-        vec![]
-    }
-}
-
-pub async fn find_mutual_groups(user_id: &str, target_id: &str) -> Vec<String> {
-    let col = get_collection("channels");
-    if let Ok(mut result) = col.find(
-        doc! {
-            "type": 1,
-            "$and": [
-                { "recipients": user_id },
-                { "recipients": target_id },
-            ]
-        },
-        FindOptions::builder().projection(doc! { "_id": 1 }).build(),
-    ).await {
-        let mut results = vec![];
-
-        while let Some(doc) = result.next().await {
-            if let Ok(group) = doc {
-                results.push(group.get_str("_id").unwrap().to_string());
-            }
-        }
-
-        results
-    } else {
-        vec![]
-    }
-}
-
-pub async 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(mut result) = get_collection("guilds").find(
-        doc! {
-            "$and": [
-                { "members": { "$elemMatch": { "id": user_id   } } },
-                { "members": { "$elemMatch": { "id": target_id } } },
-            ]
-        },
-        if with_permission {
-            opt.build()
-        } else {
-            opt.limit(1).build()
-        },
-    ).await {
-        if with_permission {
-            while let Some(item) = result.next().await {
-                // ? 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.collect::<Vec<Result<Document, _>>>().await.len() > 0 {
-            true
-        } else {
-            false
-        }
-    } else {
-        false
-    }
-}
diff --git a/src/database/permissions.rs b/src/database/permissions.rs
deleted file mode 100644
index e5726ca..0000000
--- a/src/database/permissions.rs
+++ /dev/null
@@ -1,228 +0,0 @@
-use super::mutual::has_mutual_connection;
-use crate::database::channel::Channel;
-use crate::database::guild::{fetch_guild, fetch_member, Guild, Member, MemberKey};
-use crate::database::user::{User, UserRelationship};
-
-use num_enum::TryFromPrimitive;
-
-#[derive(Debug, PartialEq, Eq, TryFromPrimitive)]
-#[repr(u8)]
-pub enum Relationship {
-    Friend = 0,
-    Outgoing = 1,
-    Incoming = 2,
-    Blocked = 3,
-    BlockedOther = 4,
-    NONE = 5,
-    SELF = 6,
-}
-
-#[derive(Debug, PartialEq, Eq, TryFromPrimitive, Copy, Clone)]
-#[repr(u32)]
-pub enum Permission {
-    Access = 1,
-    CreateInvite = 2,
-    KickMembers = 4,
-    BanMembers = 8,
-    ReadMessages = 16,
-    SendMessages = 32,
-    ManageMessages = 64,
-    ManageChannels = 128,
-    ManageServer = 256,
-    ManageRoles = 512,
-    SendDirectMessages = 1024,
-}
-
-bitfield! {
-    pub struct MemberPermissions(MSB0 [u32]);
-    u32;
-    pub get_access, set_access: 31;
-    pub get_create_invite, set_create_invite: 30;
-    pub get_kick_members, set_kick_members: 29;
-    pub get_ban_members, set_ban_members: 28;
-    pub get_read_messages, set_read_messages: 27;
-    pub get_send_messages, set_send_messages: 26;
-    pub get_manage_messages, set_manage_messages: 25;
-    pub get_manage_channels, set_manage_channels: 24;
-    pub get_manage_server, set_manage_server: 23;
-    pub get_manage_roles, set_manage_roles: 22;
-    pub get_send_direct_messages, set_send_direct_messages: 21;
-}
-
-pub fn get_relationship_internal(
-    user_id: &str,
-    target_id: &str,
-    relationships: &Option<Vec<UserRelationship>>,
-) -> Relationship {
-    if user_id == target_id {
-        return Relationship::SELF;
-    }
-
-    if let Some(arr) = &relationships {
-        for entry in arr {
-            if entry.id == target_id {
-                match entry.status {
-                    0 => return Relationship::Friend,
-                    1 => return Relationship::Outgoing,
-                    2 => return Relationship::Incoming,
-                    3 => return Relationship::Blocked,
-                    4 => return Relationship::BlockedOther,
-                    _ => return Relationship::NONE,
-                }
-            }
-        }
-    }
-
-    Relationship::NONE
-}
-
-pub fn get_relationship(a: &User, b: &User) -> Relationship {
-    if a.id == b.id {
-        return Relationship::SELF;
-    }
-
-    get_relationship_internal(&a.id, &b.id, &a.relations)
-}
-
-pub struct PermissionCalculator {
-    pub user: User,
-    pub channel: Option<Channel>,
-    pub guild: Option<Guild>,
-    pub member: Option<Member>,
-}
-
-impl PermissionCalculator {
-    pub fn new(user: User) -> PermissionCalculator {
-        PermissionCalculator {
-            user,
-            channel: None,
-            guild: None,
-            member: None,
-        }
-    }
-
-    pub fn channel(self, channel: Channel) -> PermissionCalculator {
-        PermissionCalculator {
-            channel: Some(channel),
-            ..self
-        }
-    }
-
-    pub fn guild(self, guild: Guild) -> PermissionCalculator {
-        PermissionCalculator {
-            guild: Some(guild),
-            ..self
-        }
-    }
-
-    pub async fn fetch_data(mut self) -> PermissionCalculator {
-        let guild = if let Some(value) = self.guild {
-            Some(value)
-        } else if let Some(channel) = &self.channel {
-            match channel.channel_type {
-                0..=1 => None,
-                2 => {
-                    if let Some(id) = &channel.guild {
-                        if let Ok(result) = fetch_guild(id).await {
-                            result
-                        } else {
-                            None
-                        }
-                    } else {
-                        None
-                    }
-                }
-                _ => None,
-            }
-        } else {
-            None
-        };
-
-        if let Some(guild) = &guild {
-            if let Ok(result) = fetch_member(MemberKey(guild.id.clone(), self.user.id.clone())).await {
-                self.member = result;
-            }
-        }
-
-        self.guild = guild;
-        self
-    }
-
-    pub async fn calculate(&self) -> u32 {
-        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;
-                }
-
-                permissions = guild.default_permissions as u32;
-            }
-        }
-
-        if let Some(channel) = &self.channel {
-            match channel.channel_type {
-                0 => {
-                    if let Some(arr) = &channel.recipients {
-                        let mut other_user = None;
-                        for item in arr {
-                            if item != &self.user.id {
-                                other_user = Some(item);
-                            }
-                        }
-
-                        if let Some(other) = other_user {
-                            let relationship = get_relationship_internal(
-                                &self.user.id,
-                                &other,
-                                &self.user.relations,
-                            );
-
-                            if relationship == Relationship::Friend {
-                                permissions = 1024 + 128 + 32 + 16 + 1;
-                            } else if relationship == Relationship::Blocked
-                                || relationship == Relationship::BlockedOther
-                            {
-                                permissions = 1;
-                            } else if has_mutual_connection(&self.user.id, other, true).await {
-                                permissions = 1024 + 128 + 32 + 16 + 1;
-                            } else {
-                                permissions = 1;
-                            }
-                        } else {
-                            // ? In this case, it is a "self DM".
-                            return 1024 + 128 + 32 + 16 + 1;
-                        }
-                    }
-                }
-                1 => {
-                    if let Some(id) = &channel.owner {
-                        if &self.user.id == id {
-                            return u32::MAX;
-                        }
-                    }
-
-                    if let Some(arr) = &channel.recipients {
-                        for item in arr {
-                            if item == &self.user.id {
-                                permissions = 177;
-                                break;
-                            }
-                        }
-                    }
-                }
-                2 => {
-                    // nothing implemented yet
-                }
-                _ => {}
-            }
-        }
-
-        permissions
-    }
-
-    pub async fn as_permission(&self) -> MemberPermissions<[u32; 1]> {
-        MemberPermissions([self.calculate().await])
-    }
-}
diff --git a/src/database/user.rs b/src/database/user.rs
deleted file mode 100644
index e20ba46..0000000
--- a/src/database/user.rs
+++ /dev/null
@@ -1,307 +0,0 @@
-use super::get_collection;
-use super::channel::fetch_channels;
-use super::guild::serialise_guilds_with_channels;
-
-use lru::LruCache;
-use rocket::futures::StreamExt;
-use mongodb::options::FindOptions;
-use rocket::http::{RawStr, Status};
-use serde::{Deserialize, Serialize};
-use rocket_contrib::json::JsonValue;
-use mongodb::bson::{doc, from_bson, Bson, DateTime, Document};
-use rocket::request::{self, FromParam, FromRequest, Request, Outcome};
-
-use std::sync::{Arc, Mutex};
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-pub struct UserEmailVerification {
-    pub verified: bool,
-    pub target: Option<String>,
-    pub expiry: Option<DateTime>,
-    pub rate_limit: Option<DateTime>,
-    pub code: Option<String>,
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-pub struct UserRelationship {
-    pub id: String,
-    pub status: u8,
-}
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-pub struct User {
-    #[serde(rename = "_id")]
-    pub id: String,
-    pub email: String,
-    pub username: String,
-    pub password: String,
-    pub display_name: String,
-    pub access_token: Option<String>,
-    pub email_verification: UserEmailVerification,
-    pub relations: Option<Vec<UserRelationship>>,
-}
-
-impl User {
-    pub fn serialise(self, relationship: i32) -> JsonValue {
-        if relationship == super::Relationship::SELF as i32 {
-            json!({
-                "id": self.id,
-                "username": self.username,
-                "display_name": self.display_name,
-                "email": self.email,
-                "verified": self.email_verification.verified,
-            })
-        } else {
-            json!({
-                "id": self.id,
-                "username": self.username,
-                "display_name": self.display_name,
-                "relationship": relationship
-            })
-        }
-    }
-
-    pub async fn find_guilds(&self) -> Result<Vec<String>, String> {
-        let members = get_collection("members")
-            .find(
-                doc! {
-                    "_id.user": &self.id
-                },
-                None,
-            )
-            .await
-            .map_err(|_| "Failed to fetch members.")?;
-
-        Ok(members
-            .collect::<Vec<Result<Document, _>>>()
-            .await
-            .into_iter()
-            .filter_map(|x| match x {
-                Ok(doc) => match doc.get_document("_id") {
-                    Ok(id) => match id.get_str("guild") {
-                        Ok(value) => Some(value.to_string()),
-                        Err(_) => None,
-                    },
-                    Err(_) => None,
-                },
-                Err(_) => None,
-            })
-            .collect())
-    }
-
-    pub async fn find_dms(&self) -> Result<Vec<String>, String> {
-        let channels = get_collection("channels")
-            .find(
-                doc! {
-                    "recipients": &self.id
-                },
-                FindOptions::builder().projection(doc! { "_id": 1 }).build(),
-            )
-            .await
-            .map_err(|_| "Failed to fetch channel ids.")?;
-
-        Ok(channels
-            .collect::<Vec<Result<Document, _>>>()
-            .await
-            .into_iter()
-            .filter_map(|x| x.ok())
-            .filter_map(|x| match x.get_str("_id") {
-                Ok(value) => Some(value.to_string()),
-                Err(_) => None,
-            })
-            .collect())
-    }
-
-    pub async fn create_payload(self) -> Result<JsonValue, String> {
-        let v = vec![];
-        let relations = self.relations.as_ref().unwrap_or(&v);
-
-        let users: Vec<JsonValue> = fetch_users(&relations.iter().map(|x| x.id.clone()).collect()).await?
-            .into_iter()
-            .map(|x| {
-                let id = x.id.clone();
-                x.serialise(relations.iter().find(|y| y.id == id).unwrap().status as i32)
-            })
-            .collect();
-
-        let channels: Vec<JsonValue> = fetch_channels(&self.find_dms().await?).await?
-            .into_iter()
-            .map(|x| x.serialise())
-            .collect();
-
-        Ok(json!({
-            "users": users,
-            "channels": channels,
-            "guilds": serialise_guilds_with_channels(&self.find_guilds().await?).await?,
-            "user": self.serialise(super::Relationship::SELF as i32)
-        }))
-    }
-}
-
-lazy_static! {
-    static ref CACHE: Arc<Mutex<LruCache<String, User>>> =
-        Arc::new(Mutex::new(LruCache::new(4_000_000)));
-}
-
-pub async fn fetch_user(id: &str) -> Result<Option<User>, String> {
-    {
-        if let Ok(mut cache) = CACHE.lock() {
-            let existing = cache.get(&id.to_string());
-
-            if let Some(user) = existing {
-                return Ok(Some((*user).clone()));
-            }
-        } else {
-            return Err("Failed to lock cache.".to_string());
-        }
-    }
-
-    let col = get_collection("users");
-    if let Ok(result) = col.find_one(doc! { "_id": id }, None).await {
-        if let Some(doc) = result {
-            if let Ok(user) = from_bson(Bson::Document(doc)) as Result<User, _> {
-                let mut cache = CACHE.lock().unwrap();
-                cache.put(id.to_string(), user.clone());
-
-                Ok(Some(user))
-            } else {
-                Err("Failed to deserialize user!".to_string())
-            }
-        } else {
-            Ok(None)
-        }
-    } else {
-        Err("Failed to fetch user from database.".to_string())
-    }
-}
-
-pub async fn fetch_users(ids: &Vec<String>) -> Result<Vec<User>, String> {
-    let mut missing = vec![];
-    let mut users = vec![];
-
-    {
-        if let Ok(mut cache) = CACHE.lock() {
-            for id in ids {
-                let existing = cache.get(id);
-
-                if let Some(user) = existing {
-                    users.push((*user).clone());
-                } else {
-                    missing.push(id);
-                }
-            }
-        } else {
-            return Err("Failed to lock cache.".to_string());
-        }
-    }
-
-    if missing.len() == 0 {
-        return Ok(users);
-    }
-
-    let col = get_collection("users");
-    if let Ok(mut result) = col.find(doc! { "_id": { "$in": missing } }, None).await {
-        while let Some(item) = result.next().await {
-            let mut cache = CACHE.lock().unwrap();
-            if let Ok(doc) = item {
-                if let Ok(user) = from_bson(Bson::Document(doc)) as Result<User, _> {
-                    cache.put(user.id.clone(), user.clone());
-                    users.push(user);
-                } else {
-                    return Err("Failed to deserialize user!".to_string());
-                }
-            } else {
-                return Err("Failed to fetch user.".to_string());
-            }
-        }
-
-        Ok(users)
-    } else {
-        Err("Failed to fetch user from database.".to_string())
-    }
-}
-
-#[derive(Debug)]
-pub enum AuthError {
-    Failed,
-    Missing,
-    Invalid,
-}
-
-#[rocket::async_trait]
-impl<'a, 'r> FromRequest<'a, 'r> for User {
-    type Error = AuthError;
-
-    async fn from_request(request: &'a Request<'r>) -> request::Outcome<Self, Self::Error> {
-        let u = request.headers().get("x-user").next();
-        let t = request.headers().get("x-auth-token").next();
-
-        if let Some(uid) = u {
-            if let Some(token) = t {
-                if let Ok(result) = fetch_user(uid).await {
-                    if let Some(user) = result {
-                        if let Some(access_token) = &user.access_token {
-                            if access_token == token {
-                                Outcome::Success(user)
-                            } else {
-                                Outcome::Failure((Status::Forbidden, AuthError::Invalid))
-                            }
-                        } else {
-                            Outcome::Failure((Status::Forbidden, AuthError::Invalid))
-                        }
-                    } else {
-                        Outcome::Failure((Status::Forbidden, AuthError::Invalid))
-                    }
-                } else {
-                    Outcome::Failure((Status::Forbidden, AuthError::Failed))
-                }
-            } else {
-                Outcome::Failure((Status::Forbidden, AuthError::Missing))
-            }
-        } else {
-            Outcome::Failure((Status::Forbidden, AuthError::Missing))
-        }
-    }
-}
-
-impl<'r> FromParam<'r> for User {
-    type Error = &'r RawStr;
-
-    fn from_param(param: &'r RawStr) -> Result<Self, Self::Error> {
-        Err(param)
-        /*if let Ok(result) = fetch_user(&param.to_string()).await {
-            if let Some(user) = result {
-                Ok(user)
-            } else {
-                Err(param)
-            }
-        } else {
-            Err(param)
-        }*/
-    }
-}
-
-/*pub fn process_event(event: &Notification) {
-    match event {
-        Notification::user_friend_status(ev) => {
-            let mut cache = CACHE.lock().unwrap();
-            if let Some(user) = cache.peek_mut(&ev.id) {
-                if let Some(relations) = user.relations.as_mut() {
-                    if ev.status == 0 {
-                        if let Some(pos) = relations.iter().position(|x| x.id == ev.user) {
-                            relations.remove(pos);
-                        }
-                    } else if let Some(entry) = relations.iter_mut().find(|x| x.id == ev.user) {
-                        entry.status = ev.status as u8;
-                    } else {
-                        relations.push(UserRelationship {
-                            id: ev.id.clone(),
-                            status: ev.status as u8,
-                        });
-                    }
-                }
-            }
-        }
-        _ => {}
-    }
-}*/
-- 
GitLab