diff --git a/src/routes/channel.rs b/src/routes/channel.rs
deleted file mode 100644
index 592da2a9e4cd241e5ecc59c414868d5a514a8af4..0000000000000000000000000000000000000000
--- a/src/routes/channel.rs
+++ /dev/null
@@ -1,688 +0,0 @@
-use super::Response;
-use crate::database::{
-    self, channel::Channel, get_relationship, get_relationship_internal, message::Message,
-    user::User, Permission, PermissionCalculator, Relationship,
-};
-use crate::util::vec_to_set;
-
-use chrono::prelude::*;
-use mongodb::bson::{doc, from_bson, Bson, Document};
-use mongodb::options::FindOptions;
-use num_enum::TryFromPrimitive;
-use rocket::request::Form;
-use rocket_contrib::json::Json;
-use rocket::futures::StreamExt;
-use serde::{Deserialize, Serialize};
-use ulid::Ulid;
-
-const MAXGROUPSIZE: usize = 50;
-
-#[derive(Debug, TryFromPrimitive)]
-#[repr(usize)]
-pub enum ChannelType {
-    DM = 0,
-    GROUPDM = 1,
-    GUILDCHANNEL = 2,
-}
-
-macro_rules! with_permissions {
-    ($user: expr, $target: expr) => {{
-        let permissions = PermissionCalculator::new($user.clone())
-            .channel($target.clone())
-            .fetch_data()
-            .await;
-
-        let value = permissions.as_permission().await;
-        if !value.get_access() {
-            return None;
-        }
-
-        value
-    }};
-}
-
-#[derive(Serialize, Deserialize)]
-pub struct CreateGroup {
-    name: String,
-    nonce: String,
-    users: Vec<String>,
-}
-
-/// create a new group
-#[post("/create", data = "<info>")]
-pub async fn create_group(user: User, info: Json<CreateGroup>) -> Response {
-    let name: String = info.name.chars().take(32).collect();
-    let nonce: String = info.nonce.chars().take(32).collect();
-
-    let mut set = vec_to_set(&info.users);
-    set.insert(user.id.clone());
-
-    if set.len() > MAXGROUPSIZE {
-        return Response::BadRequest(json!({ "error": "Maximum group size is 50." }));
-    }
-
-    let col = database::get_collection("channels");
-    if let Some(_) = col.find_one(doc! { "nonce": nonce.clone() }, None).await.unwrap() {
-        return Response::BadRequest(json!({ "error": "Group already created!" }));
-    }
-
-    let mut query = vec![];
-    for item in &set {
-        if item == &user.id {
-            continue;
-        }
-
-        query.push(Bson::String(item.clone()));
-    }
-
-    if let Ok(result) = database::get_collection("users").find(
-        doc! {
-            "_id": {
-                "$in": &query
-            }
-        },
-        FindOptions::builder().limit(query.len() as i64).build(),
-    ).await {
-        if result.collect::<Vec<Result<Document, _>>>().await.len() != query.len() {
-            return Response::BadRequest(json!({ "error": "Specified non-existant user(s)." }));
-        }
-
-        for item in set {
-            if item == user.id {
-                continue;
-            }
-
-            if get_relationship_internal(&user.id, &item, &user.relations) != Relationship::Friend {
-                return Response::BadRequest(json!({ "error": "Not friends with user(s)." }));
-            }
-        }
-
-        query.push(Bson::String(user.id.clone()));
-
-        let id = Ulid::new().to_string();
-        if col
-            .insert_one(
-                doc! {
-                    "_id": id.clone(),
-                    "nonce": nonce,
-                    "type": ChannelType::GROUPDM as u32,
-                    "recipients": &query,
-                    "name": name,
-                    "owner": &user.id,
-                },
-                None,
-            )
-            .await
-            .is_ok()
-        {
-            Response::Success(json!({ "id": id }))
-        } else {
-            Response::InternalServerError(json!({ "error": "Failed to create guild channel." }))
-        }
-    } else {
-        Response::InternalServerError(json!({ "error": "Failed to validate users." }))
-    }
-}
-
-/// fetch channel information
-#[get("/<target>")]
-pub async fn channel(user: User, target: Channel) -> Option<Response> {
-    with_permissions!(user, target);
-    Some(Response::Success(target.serialise()))
-}
-
-/// [groups] add user to channel
-#[put("/<target>/recipients/<member>")]
-pub async fn add_member(user: User, target: Channel, member: User) -> Option<Response> {
-    if target.channel_type != 1 {
-        return Some(Response::BadRequest(json!({ "error": "Not a group DM." })));
-    }
-
-    with_permissions!(user, target);
-
-    let recp = target.recipients.as_ref().unwrap();
-    if recp.len() == 50 {
-        return Some(Response::BadRequest(
-            json!({ "error": "Maximum group size is 50." }),
-        ));
-    }
-
-    let set = vec_to_set(&recp);
-    if set.get(&member.id).is_some() {
-        return Some(Response::BadRequest(
-            json!({ "error": "User already in group!" }),
-        ));
-    }
-
-    match get_relationship(&user, &member) {
-        Relationship::Friend => {
-            if database::get_collection("channels")
-                .update_one(
-                    doc! { "_id": target.id.clone() },
-                    doc! {
-                        "$push": {
-                            "recipients": &member.id
-                        }
-                    },
-                    None,
-                )
-                .await
-                .is_ok()
-            {
-                if (Message {
-                    id: Ulid::new().to_string(),
-                    nonce: None,
-                    channel: target.id.clone(),
-                    author: "system".to_string(),
-                    content: format!("<@{}> added <@{}> to the group.", &user.id, &member.id),
-                    edited: None,
-                    previous_content: vec![],
-                })
-                .send(&target)
-                .await
-                {
-                    /*notifications::send_message_given_channel(
-                        Notification::group_user_join(UserJoin {
-                            id: target.id.clone(),
-                            user: member.id.clone(),
-                        }),
-                        &target, FIXME
-                    );*/
-
-                    Some(Response::Result(super::Status::Ok))
-                } else {
-                    Some(Response::PartialStatus(
-                        json!({ "error": "Failed to send join message, but user has been added." }),
-                    ))
-                }
-            } else {
-                Some(Response::InternalServerError(
-                    json!({ "error": "Failed to add user to group." }),
-                ))
-            }
-        }
-        _ => Some(Response::BadRequest(
-            json!({ "error": "Not friends with user." }),
-        )),
-    }
-}
-
-/// [groups] remove user from channel
-#[delete("/<target>/recipients/<member>")]
-pub async fn remove_member(user: User, target: Channel, member: User) -> Option<Response> {
-    if target.channel_type != 1 {
-        return Some(Response::BadRequest(json!({ "error": "Not a group DM." })));
-    }
-
-    if &user.id == &member.id {
-        return Some(Response::BadRequest(
-            json!({ "error": "Cannot kick yourself, leave the channel instead." }),
-        ));
-    }
-
-    let permissions = with_permissions!(user, target);
-
-    if !permissions.get_kick_members() {
-        return Some(Response::LackingPermission(Permission::KickMembers));
-    }
-
-    let set = vec_to_set(target.recipients.as_ref().unwrap());
-    if set.get(&member.id).is_none() {
-        return Some(Response::BadRequest(
-            json!({ "error": "User not in group!" }),
-        ));
-    }
-
-    if database::get_collection("channels")
-        .update_one(
-            doc! { "_id": &target.id },
-            doc! {
-                "$pull": {
-                    "recipients": &member.id
-                }
-            },
-            None,
-        )
-        .await
-        .is_ok()
-    {
-        if (Message {
-            id: Ulid::new().to_string(),
-            nonce: None,
-            channel: target.id.clone(),
-            author: "system".to_string(),
-            content: format!("<@{}> removed <@{}> from the group.", &user.id, &member.id),
-            edited: None,
-            previous_content: vec![],
-        })
-        .send(&target)
-        .await
-        {
-            /*notifications::send_message_given_channel(
-                Notification::group_user_leave(UserLeave {
-                    id: target.id.clone(),
-                    user: member.id.clone(),
-                }),
-                &target, FIXME
-            );*/
-
-            Some(Response::Result(super::Status::Ok))
-        } else {
-            Some(Response::PartialStatus(
-                json!({ "error": "Failed to send join message, but user has been removed." }),
-            ))
-        }
-    } else {
-        Some(Response::InternalServerError(
-            json!({ "error": "Failed to add user to group." }),
-        ))
-    }
-}
-
-/// delete channel
-/// or leave group DM
-/// or close DM conversation
-#[delete("/<target>")]
-pub async fn delete(user: User, target: Channel) -> Option<Response> {
-    let permissions = with_permissions!(user, target);
-
-    if !permissions.get_manage_channels() {
-        return Some(Response::LackingPermission(Permission::ManageChannels));
-    }
-
-    let col = database::get_collection("channels");
-    let target_id = target.id.clone();
-
-    let try_delete = async || {
-        let messages = database::get_collection("messages");
-
-        if messages
-            .delete_many(doc! { "channel": &target_id }, None)
-            .await
-            .is_ok()
-        {
-            if col.delete_one(doc! { "_id": &target_id }, None).await.is_ok() {
-                Some(Response::Result(super::Status::Ok))
-            } else {
-                Some(Response::InternalServerError(
-                    json!({ "error": "Failed to delete channel." }),
-                ))
-            }
-        } else {
-            Some(Response::InternalServerError(
-                json!({ "error": "Failed to delete messages." }),
-            ))
-        }
-    };
-
-    match target.channel_type {
-        0 => {
-            if col
-                .update_one(
-                    doc! { "_id": &target_id },
-                    doc! { "$set": { "active": false } },
-                    None,
-                )
-                .await
-                .is_ok()
-            {
-                Some(Response::Result(super::Status::Ok))
-            } else {
-                Some(Response::InternalServerError(
-                    json!({ "error": "Failed to close channel." }),
-                ))
-            }
-        }
-        1 => {
-            let mut recipients = vec_to_set(
-                target
-                    .recipients
-                    .as_ref()
-                    .expect("Missing recipients on Group DM."),
-            );
-            let owner = target.owner.as_ref().expect("Missing owner on Group DM.");
-
-            if recipients.len() == 1 {
-                try_delete().await
-            } else {
-                recipients.remove(&user.id);
-                let new_owner = if owner == &user.id {
-                    recipients.iter().next().unwrap()
-                } else {
-                    &owner
-                };
-
-                if col
-                    .update_one(
-                        doc! { "_id": target_id },
-                        doc! {
-                            "$set": {
-                                "owner": new_owner,
-                            },
-                            "$pull": {
-                                "recipients": &user.id,
-                            }
-                        },
-                        None,
-                    )
-                    .await
-                    .is_ok()
-                {
-                    if (Message {
-                        id: Ulid::new().to_string(),
-                        nonce: None,
-                        channel: target.id.clone(),
-                        author: "system".to_string(),
-                        content: format!("<@{}> left the group.", &user.id),
-                        edited: None,
-                        previous_content: vec![],
-                    })
-                    .send(&target)
-                    .await
-                    {
-                        /*notifications::send_message_given_channel(
-                            Notification::group_user_leave(UserLeave {
-                                id: target.id.clone(),
-                                user: user.id.clone(),
-                            }),
-                            &target, FIXME
-                        );*/
-
-                        Some(Response::Result(super::Status::Ok))
-                    } else {
-                        Some(Response::PartialStatus(
-                            json!({ "error": "Failed to send leave message, but you have left the group." }),
-                        ))
-                    }
-                } else {
-                    Some(Response::InternalServerError(
-                        json!({ "error": "Failed to remove you from the group." }),
-                    ))
-                }
-            }
-        }
-        2 => {
-            let guild_id = target.guild.unwrap();
-            if database::get_collection("guilds")
-                .update_one(
-                    doc! { "_id": &guild_id },
-                    doc! {
-                        "$pull": {
-                            "invites": {
-                                "channel": &target.id
-                            },
-                            "channels": &target.id
-                        }
-                    },
-                    None,
-                )
-                .await
-                .is_ok()
-            {
-                /*notifications::send_message_threaded(
-                    None,
-                    guild_id.clone(),
-                    Notification::guild_channel_delete(ChannelDelete {
-                        id: guild_id.clone(),
-                        channel: target.id.clone(),
-                    }), FIXME
-                );*/
-
-                try_delete().await
-            } else {
-                Some(Response::InternalServerError(
-                    json!({ "error": "Failed to remove invites." }),
-                ))
-            }
-        }
-        _ => Some(Response::InternalServerError(
-            json!({ "error": "Unknown error has occurred." }),
-        )),
-    }
-}
-
-#[derive(Serialize, Deserialize, FromForm)]
-pub struct MessageFetchOptions {
-    limit: Option<i64>,
-    before: Option<String>,
-    after: Option<String>,
-}
-
-/// fetch channel messages
-#[get("/<target>/messages?<options..>")]
-pub async fn messages(
-    user: User,
-    target: Channel,
-    options: Form<MessageFetchOptions>,
-) -> Option<Response> {
-    let permissions = with_permissions!(user, target);
-
-    if !permissions.get_read_messages() {
-        return Some(Response::LackingPermission(Permission::ReadMessages));
-    }
-
-    // ! FIXME: update wiki to reflect changes
-    let mut query = doc! { "channel": target.id };
-
-    if let Some(before) = &options.before {
-        query.insert("_id", doc! { "$lt": before });
-    }
-
-    if let Some(after) = &options.after {
-        query.insert("_id", doc! { "$gt": after });
-    }
-
-    let limit = if let Some(limit) = options.limit {
-        limit.min(100).max(0)
-    } else {
-        50
-    };
-
-    let col = database::get_collection("messages");
-    let mut result = col
-        .find(
-            query,
-            FindOptions::builder()
-                .limit(limit)
-                .sort(doc! {
-                    "_id": -1
-                })
-                .build(),
-        )
-        .await
-        .unwrap();
-
-    let mut messages = Vec::new();
-    while let Some(item) = result.next().await {
-        let message: Message =
-            from_bson(Bson::Document(item.unwrap())).expect("Failed to unwrap message.");
-        messages.push(json!({
-            "id": message.id,
-            "author": message.author,
-            "content": message.content,
-            "edited": if let Some(t) = message.edited { Some(t.timestamp()) } else { None }
-        }));
-    }
-
-    Some(Response::Success(json!(messages)))
-}
-
-#[derive(Serialize, Deserialize)]
-pub struct SendMessage {
-    content: String,
-    nonce: String,
-}
-
-/// send a message to a channel
-#[post("/<target>/messages", data = "<message>")]
-pub async fn send_message(user: User, target: Channel, message: Json<SendMessage>) -> Option<Response> {
-    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));
-    }
-
-    let content: String = message.content.chars().take(2000).collect();
-    let nonce: String = message.nonce.chars().take(32).collect();
-
-    if content.len() == 0 {
-        return Some(Response::NotAcceptable(
-            json!({ "error": "No message content!" }),
-        ));
-    }
-
-    let col = database::get_collection("messages");
-    if col
-        .find_one(doc! { "nonce": nonce.clone() }, None)
-        .await
-        .unwrap()
-        .is_some()
-    {
-        return Some(Response::BadRequest(
-            json!({ "error": "Message already sent!" }),
-        ));
-    }
-
-    let id = Ulid::new().to_string();
-    let message = Message {
-        id: id.clone(),
-        nonce: Some(nonce),
-        channel: target.id.clone(),
-        author: user.id,
-        content,
-        edited: None,
-        previous_content: vec![],
-    };
-
-    if message.send(&target).await {
-        Some(Response::Success(json!({ "id": id })))
-    } else {
-        Some(Response::BadRequest(
-            json!({ "error": "Failed to send message." }),
-        ))
-    }
-}
-
-/// get a message
-#[get("/<target>/messages/<message>")]
-pub async fn get_message(user: User, target: Channel, message: Message) -> Option<Response> {
-    let permissions = with_permissions!(user, target);
-
-    if !permissions.get_read_messages() {
-        return Some(Response::LackingPermission(Permission::ReadMessages));
-    }
-
-    // ! 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": entries,
-    })))
-}
-
-#[derive(Serialize, Deserialize)]
-pub struct EditMessage {
-    content: String,
-}
-
-/// edit a message
-#[patch("/<target>/messages/<message>", data = "<edit>")]
-pub async fn edit_message(
-    user: User,
-    target: Channel,
-    message: Message,
-    edit: Json<EditMessage>,
-) -> Option<Response> {
-    with_permissions!(user, target);
-
-    if message.author != user.id {
-        return Some(Response::Unauthorized(
-            json!({ "error": "You did not send this message." }),
-        ));
-    }
-
-    let col = database::get_collection("messages");
-    let time = if let Some(edited) = message.edited {
-        edited.0
-    } else {
-        Ulid::from_string(&message.id).unwrap().datetime()
-    };
-
-    let edited = Utc::now();
-    match col.update_one(
-        doc! { "_id": message.id.clone() },
-        doc! {
-            "$set": {
-                "content": &edit.content,
-                "edited": Bson::DateTime(edited)
-            },
-            "$push": {
-                "previous_content": {
-                    "content": &message.content,
-                    "time": time,
-                }
-            },
-        },
-        None,
-    )
-    .await {
-        Ok(_) => {
-            /*notifications::send_message_given_channel(
-                Notification::message_edit(Edit {
-                    id: message.id.clone(),
-                    channel: target.id.clone(),
-                    author: message.author.clone(),
-                    content: edit.content.clone(),
-                }),
-                &target, FIXME
-            );*/
-
-            Some(Response::Result(super::Status::Ok))
-        }
-        Err(_) => Some(Response::InternalServerError(
-            json!({ "error": "Failed to update message." }),
-        )),
-    }
-}
-
-/// delete a message
-#[delete("/<target>/messages/<message>")]
-pub async fn delete_message(user: User, target: Channel, message: Message) -> Option<Response> {
-    let permissions = with_permissions!(user, target);
-
-    if !permissions.get_manage_messages() && message.author != user.id {
-        return Some(Response::LackingPermission(Permission::ManageMessages));
-    }
-
-    let col = database::get_collection("messages");
-
-    match col.delete_one(doc! { "_id": &message.id }, None).await {
-        Ok(_) => {
-            /*notifications::send_message_given_channel(
-                Notification::message_delete(Delete {
-                    id: message.id.clone(),
-                }),
-                &target, FIXME
-            );*/
-
-            Some(Response::Result(super::Status::Ok))
-        }
-        Err(_) => Some(Response::InternalServerError(
-            json!({ "error": "Failed to delete message." }),
-        )),
-    }
-}
diff --git a/src/routes/channels/mod.rs b/src/routes/channels/mod.rs
new file mode 100644
index 0000000000000000000000000000000000000000..9a5378acc6a6de07d35b1c9796f88801f844f3d0
--- /dev/null
+++ b/src/routes/channels/mod.rs
@@ -0,0 +1,5 @@
+use rocket::Route;
+
+pub fn routes() -> Vec<Route> {
+    routes! []
+}
diff --git a/src/routes/guild.rs b/src/routes/guild.rs
deleted file mode 100644
index 4ab993a1ca8605c605fe131f82a67cf1da636911..0000000000000000000000000000000000000000
--- a/src/routes/guild.rs
+++ /dev/null
@@ -1,818 +0,0 @@
-use super::channel::ChannelType;
-use super::Response;
-use crate::database::guild::{fetch_member as get_member, get_invite, Guild, MemberKey};
-use crate::database::{
-    self, channel::fetch_channel, channel::Channel, guild::serialise_guilds_with_channels,
-    user::User, Permission, PermissionCalculator,
-};
-use crate::util::gen_token;
-
-use mongodb::bson::{doc, Bson};
-use mongodb::options::{FindOneOptions, FindOptions};
-use rocket::request::Form;
-use rocket_contrib::json::Json;
-use serde::{Deserialize, Serialize};
-use rocket::futures::StreamExt;
-use ulid::Ulid;
-
-// ! FIXME: GET RID OF THIS
-macro_rules! with_permissions {
-    ($user: expr, $target: expr) => {{
-        let permissions = PermissionCalculator::new($user.clone())
-            .guild($target.clone())
-            .fetch_data()
-            .await;
-
-        let value = permissions.as_permission().await;
-        if !value.get_access() {
-            return None;
-        }
-
-        (value, permissions.member.unwrap())
-    }};
-}
-
-/// fetch your guilds
-#[get("/@me")]
-pub async fn my_guilds(user: User) -> Response {
-    if let Ok(gids) = user.find_guilds().await {
-        if let Ok(data) = serialise_guilds_with_channels(&gids).await {
-            Response::Success(json!(data))
-        } else {
-            Response::InternalServerError(json!({ "error": "Failed to fetch guilds." }))
-        }
-    } else {
-        Response::InternalServerError(json!({ "error": "Failed to fetch memberships." }))
-    }
-}
-
-/// fetch a guild
-#[get("/<target>")]
-pub async fn guild(user: User, target: Guild) -> Option<Response> {
-    with_permissions!(user, target);
-
-    if let Ok(result) = target.seralise_with_channels().await {
-        Some(Response::Success(result))
-    } else {
-        Some(Response::InternalServerError(
-            json!({ "error": "Failed to fetch channels!" }),
-        ))
-    }
-}
-
-/// delete or leave a guild
-#[delete("/<target>")]
-pub async fn remove_guild(user: User, target: Guild) -> Option<Response> {
-    with_permissions!(user, target);
-
-    if user.id == target.owner {
-        let channels = database::get_collection("channels");
-        if let Ok(mut result) = channels.find(
-            doc! {
-                "type": 2,
-                "guild": &target.id
-            },
-            FindOptions::builder().projection(doc! { "_id": 1 }).build(),
-        ).await {
-            let mut values = vec![];
-            while let Some(item) = result.next().await {
-                if let Ok(doc) = item {
-                    values.push(Bson::String(doc.get_str("_id").unwrap().to_string()));
-                }
-            }
-
-            if database::get_collection("messages")
-                .delete_many(
-                    doc! {
-                        "channel": {
-                            "$in": values
-                        }
-                    },
-                    None,
-                )
-                .await
-                .is_ok()
-            {
-                if channels
-                    .delete_many(
-                        doc! {
-                            "type": 2,
-                            "guild": &target.id,
-                        },
-                        None,
-                    )
-                    .await
-                    .is_ok()
-                {
-                    if database::get_collection("members")
-                        .delete_many(
-                            doc! {
-                                "_id.guild": &target.id,
-                            },
-                            None,
-                        )
-                        .await
-                        .is_ok()
-                    {
-                        if database::get_collection("guilds")
-                            .delete_one(
-                                doc! {
-                                    "_id": &target.id
-                                },
-                                None,
-                            )
-                            .await
-                            .is_ok()
-                        {
-                            /*notifications::send_message_threaded(
-                                None,
-                                target.id.clone(),
-                                Notification::guild_delete(Delete {
-                                    id: target.id.clone(),
-                                }), FIXME
-                            );*/
-
-                            Some(Response::Result(super::Status::Ok))
-                        } else {
-                            Some(Response::InternalServerError(
-                                json!({ "error": "Failed to delete guild." }),
-                            ))
-                        }
-                    } else {
-                        Some(Response::InternalServerError(
-                            json!({ "error": "Failed to delete guild members." }),
-                        ))
-                    }
-                } else {
-                    Some(Response::InternalServerError(
-                        json!({ "error": "Failed to delete guild channels." }),
-                    ))
-                }
-            } else {
-                Some(Response::InternalServerError(
-                    json!({ "error": "Failed to delete guild messages." }),
-                ))
-            }
-        } else {
-            Some(Response::InternalServerError(
-                json!({ "error": "Could not fetch channels." }),
-            ))
-        }
-    } else if database::get_collection("members")
-        .delete_one(
-            doc! {
-                "_id.guild": &target.id,
-                "_id.user": &user.id,
-            },
-            None,
-        )
-        .await
-        .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,
-            }), FIXME
-        );*/
-
-        Some(Response::Result(super::Status::Ok))
-    } else {
-        Some(Response::InternalServerError(
-            json!({ "error": "Failed to remove you from the guild." }),
-        ))
-    }
-}
-
-#[derive(Serialize, Deserialize)]
-pub struct CreateChannel {
-    nonce: String,
-    name: String,
-    description: Option<String>,
-}
-
-/// create a new channel
-#[post("/<target>/channels", data = "<info>")]
-pub async fn create_channel(user: User, target: Guild, info: Json<CreateChannel>) -> Option<Response> {
-    let (permissions, _) = with_permissions!(user, target);
-
-    if !permissions.get_manage_channels() {
-        return Some(Response::LackingPermission(Permission::ManageChannels));
-    }
-
-    let nonce: String = info.nonce.chars().take(32).collect();
-    let name: String = info.name.chars().take(32).collect();
-    let description: String = info
-        .description
-        .clone()
-        .unwrap_or(String::new())
-        .chars()
-        .take(255)
-        .collect();
-
-    if let Ok(result) =
-        database::get_collection("channels").find_one(doc! { "nonce": &nonce }, None)
-        .await
-    {
-        if result.is_some() {
-            return Some(Response::BadRequest(
-                json!({ "error": "Channel already created." }),
-            ));
-        }
-
-        let id = Ulid::new().to_string();
-        if database::get_collection("channels")
-            .insert_one(
-                doc! {
-                    "_id": &id,
-                    "nonce": &nonce,
-                    "type": 2,
-                    "guild": &target.id,
-                    "name": &name,
-                    "description": &description,
-                },
-                None,
-            )
-            .await
-            .is_ok()
-        {
-            if database::get_collection("guilds")
-                .update_one(
-                    doc! {
-                        "_id": &target.id
-                    },
-                    doc! {
-                        "$addToSet": {
-                            "channels": &id
-                        }
-                    },
-                    None,
-                )
-                .await
-                .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(),
-                    }), FIXME
-                );*/
-
-                Some(Response::Success(json!({ "id": &id })))
-            } else {
-                Some(Response::InternalServerError(
-                    json!({ "error": "Couldn't save channel list." }),
-                ))
-            }
-        } else {
-            Some(Response::InternalServerError(
-                json!({ "error": "Couldn't create channel." }),
-            ))
-        }
-    } else {
-        Some(Response::BadRequest(
-            json!({ "error": "Failed to check if channel was made." }),
-        ))
-    }
-}
-
-#[derive(Serialize, Deserialize)]
-pub struct InviteOptions {
-    // ? TODO: add options
-}
-
-/// create a new invite
-#[post("/<target>/channels/<channel>/invite", data = "<_options>")]
-pub async fn create_invite(
-    user: User,
-    target: Guild,
-    channel: Channel,
-    _options: Json<InviteOptions>,
-) -> Option<Response> {
-    let (permissions, _) = with_permissions!(user, target);
-
-    if !permissions.get_create_invite() {
-        return Some(Response::LackingPermission(Permission::CreateInvite));
-    }
-
-    let code = gen_token(7);
-    if database::get_collection("guilds")
-        .update_one(
-            doc! { "_id": target.id },
-            doc! {
-                "$push": {
-                    "invites": {
-                        "code": &code,
-                        "creator": user.id,
-                        "channel": channel.id,
-                    }
-                }
-            },
-            None,
-        )
-        .await
-        .is_ok()
-    {
-        Some(Response::Success(json!({ "code": code })))
-    } else {
-        Some(Response::BadRequest(
-            json!({ "error": "Failed to create invite." }),
-        ))
-    }
-}
-
-/// remove an invite
-#[delete("/<target>/invites/<code>")]
-pub async fn remove_invite(user: User, target: Guild, code: String) -> Option<Response> {
-    let (permissions, _) = with_permissions!(user, target);
-
-    if let Some((guild_id, _, invite)) = get_invite(&code, None).await {
-        if invite.creator != user.id && !permissions.get_manage_server() {
-            return Some(Response::LackingPermission(Permission::ManageServer));
-        }
-
-        if database::get_collection("guilds")
-            .update_one(
-                doc! {
-                    "_id": &guild_id,
-                },
-                doc! {
-                    "$pull": {
-                        "invites": {
-                            "code": &code
-                        }
-                    }
-                },
-                None,
-            )
-            .await
-            .is_ok()
-        {
-            Some(Response::Result(super::Status::Ok))
-        } else {
-            Some(Response::BadRequest(
-                json!({ "error": "Failed to delete invite." }),
-            ))
-        }
-    } else {
-        Some(Response::NotFound(
-            json!({ "error": "Failed to fetch invite or code is invalid." }),
-        ))
-    }
-}
-
-/// fetch all guild invites
-#[get("/<target>/invites")]
-pub async fn fetch_invites(user: User, target: Guild) -> Option<Response> {
-    let (permissions, _) = with_permissions!(user, target);
-
-    if !permissions.get_manage_server() {
-        return Some(Response::LackingPermission(Permission::ManageServer));
-    }
-
-    Some(Response::Success(json!(target.invites)))
-}
-
-/// view an invite before joining
-#[get("/join/<code>", rank = 1)]
-pub async fn fetch_invite(user: User, code: String) -> Response {
-    if let Some((guild_id, name, invite)) = get_invite(&code, user.id).await {
-        match fetch_channel(&invite.channel).await {
-            Ok(result) => {
-                if let Some(channel) = result {
-                    Response::Success(json!({
-                        "guild": {
-                            "id": guild_id,
-                            "name": name,
-                        },
-                        "channel": {
-                            "id": channel.id,
-                            "name": channel.name,
-                        }
-                    }))
-                } else {
-                    Response::NotFound(json!({ "error": "Channel does not exist." }))
-                }
-            }
-            Err(err) => Response::InternalServerError(json!({ "error": err })),
-        }
-    } else {
-        Response::NotFound(json!({ "error": "Failed to fetch invite or code is invalid." }))
-    }
-}
-
-/// join a guild using an invite
-#[post("/join/<code>", rank = 1)]
-pub async fn use_invite(user: User, code: String) -> Response {
-    if let Some((guild_id, _, invite)) = get_invite(&code, Some(user.id.clone())).await {
-        if let Ok(result) = database::get_collection("members").find_one(
-            doc! {
-                "_id.guild": &guild_id,
-                "_id.user": &user.id
-            },
-            FindOneOptions::builder()
-                .projection(doc! { "_id": 1 })
-                .build(),
-        )
-        .await {
-            if result.is_none() {
-                if database::get_collection("members")
-                    .insert_one(
-                        doc! {
-                            "_id": {
-                                "guild": &guild_id,
-                                "user": &user.id
-                            }
-                        },
-                        None,
-                    )
-                    .await
-                    .is_ok()
-                {
-                    /*notifications::send_message_threaded(
-                        None,
-                        guild_id.clone(),
-                        Notification::guild_user_join(UserJoin {
-                            id: guild_id.clone(),
-                            user: user.id.clone(),
-                        }), FIXME
-                    );*/
-
-                    Response::Success(json!({
-                        "guild": &guild_id,
-                        "channel": &invite.channel,
-                    }))
-                } else {
-                    Response::InternalServerError(
-                        json!({ "error": "Failed to add you to the guild." }),
-                    )
-                }
-            } else {
-                Response::BadRequest(json!({ "error": "Already in the guild." }))
-            }
-        } else {
-            Response::InternalServerError(
-                json!({ "error": "Failed to check if you're in the guild." }),
-            )
-        }
-    } else {
-        Response::NotFound(json!({ "error": "Failed to fetch invite or code is invalid." }))
-    }
-}
-
-#[derive(Serialize, Deserialize)]
-pub struct CreateGuild {
-    name: String,
-    description: Option<String>,
-    nonce: String,
-}
-
-/// create a new guild
-#[post("/create", data = "<info>")]
-pub async fn create_guild(user: User, info: Json<CreateGuild>) -> Response {
-    if !user.email_verification.verified {
-        return Response::Unauthorized(json!({ "error": "Email not verified!" }));
-    }
-
-    let name: String = info.name.chars().take(32).collect();
-    let description: String = info
-        .description
-        .clone()
-        .unwrap_or("No description.".to_string())
-        .chars()
-        .take(255)
-        .collect();
-    let nonce: String = info.nonce.chars().take(32).collect();
-
-    let channels = database::get_collection("channels");
-    let col = database::get_collection("guilds");
-    if col
-        .find_one(doc! { "nonce": nonce.clone() }, None)
-        .await
-        .unwrap()
-        .is_some()
-    {
-        return Response::BadRequest(json!({ "error": "Guild already created!" }));
-    }
-
-    let id = Ulid::new().to_string();
-    let channel_id = Ulid::new().to_string();
-    if channels
-        .insert_one(
-            doc! {
-                "_id": channel_id.clone(),
-                "type": ChannelType::GUILDCHANNEL as u32,
-                "name": "general",
-                "description": "",
-                "guild": id.clone(),
-            },
-            None,
-        )
-        .await
-        .is_err()
-    {
-        return Response::InternalServerError(
-            json!({ "error": "Failed to create guild channel." }),
-        );
-    }
-
-    if database::get_collection("members")
-        .insert_one(
-            doc! {
-                "_id": {
-                    "guild": &id,
-                    "user": &user.id
-                }
-            },
-            None,
-        )
-        .await
-        .is_err()
-    {
-        return Response::InternalServerError(
-            json!({ "error": "Failed to add you to members list." }),
-        );
-    }
-
-    if col
-        .insert_one(
-            doc! {
-                "_id": &id,
-                "nonce": nonce,
-                "name": name,
-                "description": description,
-                "owner": &user.id,
-                "channels": [ channel_id.clone() ],
-                "invites": [],
-                "bans": [],
-                "default_permissions": 51,
-            },
-            None,
-        )
-        .await
-        .is_ok()
-    {
-        Response::Success(json!({ "id": id }))
-    } else {
-        channels
-            .delete_one(doc! { "_id": channel_id }, None)
-            .await
-            .expect("Failed to delete the channel we just made.");
-
-        Response::InternalServerError(json!({ "error": "Failed to create guild." }))
-    }
-}
-
-/// fetch a guild's member
-#[get("/<target>/members")]
-pub async fn fetch_members(user: User, target: Guild) -> Option<Response> {
-    with_permissions!(user, target);
-
-    if let Ok(mut result) =
-        database::get_collection("members").find(doc! { "_id.guild": target.id }, None)
-        .await
-    {
-        let mut users = vec![];
-
-        while let Some(item) = result.next().await {
-            if let Ok(doc) = item {
-                users.push(json!({
-                    "id": doc.get_document("_id").unwrap().get_str("user").unwrap(),
-                    "nickname": doc.get_str("nickname").ok(),
-                }));
-            }
-        }
-
-        Some(Response::Success(json!(users)))
-    } else {
-        Some(Response::InternalServerError(
-            json!({ "error": "Failed to fetch members." }),
-        ))
-    }
-}
-
-/// fetch a guild member
-#[get("/<target>/members/<other>")]
-pub async fn fetch_member(user: User, target: Guild, other: String) -> Option<Response> {
-    with_permissions!(user, target);
-
-    if let Ok(result) = get_member(MemberKey(target.id, other)).await {
-        if let Some(member) = result {
-            Some(Response::Success(json!({
-                "id": member.id.user,
-                "nickname": member.nickname,
-            })))
-        } else {
-            Some(Response::NotFound(
-                json!({ "error": "Member does not exist!" }),
-            ))
-        }
-    } else {
-        Some(Response::InternalServerError(
-            json!({ "error": "Failed to fetch member." }),
-        ))
-    }
-}
-
-/// kick a guild member
-#[delete("/<target>/members/<other>")]
-pub async fn kick_member(user: User, target: Guild, other: String) -> Option<Response> {
-    let (permissions, _) = with_permissions!(user, target);
-
-    if user.id == other {
-        return Some(Response::BadRequest(
-            json!({ "error": "Cannot kick yourself." }),
-        ));
-    }
-
-    if !permissions.get_kick_members() {
-        return Some(Response::LackingPermission(Permission::KickMembers));
-    }
-
-    if let Ok(result) = get_member(MemberKey(target.id.clone(), other.clone())).await {
-        if result.is_none() {
-            return Some(Response::BadRequest(
-                json!({ "error": "User not part of guild." }),
-            ));
-        }
-    } else {
-        return Some(Response::InternalServerError(
-            json!({ "error": "Failed to fetch member." }),
-        ));
-    }
-
-    if database::get_collection("members")
-        .delete_one(
-            doc! {
-                "_id.guild": &target.id,
-                "_id.user": &other,
-            },
-            None,
-        )
-        .await
-        .is_ok()
-    {
-        /*notifications::send_message_threaded(
-            None,
-            target.id.clone(),
-            Notification::guild_user_leave(UserLeave {
-                id: target.id.clone(),
-                user: other.clone(),
-                banned: false,
-            }), FIXME
-        );*/
-
-        Some(Response::Result(super::Status::Ok))
-    } else {
-        Some(Response::InternalServerError(
-            json!({ "error": "Failed to kick member." }),
-        ))
-    }
-}
-
-#[derive(Serialize, Deserialize, FromForm)]
-pub struct BanOptions {
-    reason: Option<String>,
-}
-
-/// ban a guild member
-#[put("/<target>/members/<other>/ban?<options..>")]
-pub async fn ban_member(
-    user: User,
-    target: Guild,
-    other: String,
-    options: Form<BanOptions>,
-) -> Option<Response> {
-    let (permissions, _) = with_permissions!(user, target);
-    let reason: String = options
-        .reason
-        .clone()
-        .unwrap_or("No reason specified.".to_string())
-        .chars()
-        .take(64)
-        .collect();
-
-    if user.id == other {
-        return Some(Response::BadRequest(
-            json!({ "error": "Cannot ban yourself." }),
-        ));
-    }
-
-    if !permissions.get_ban_members() {
-        return Some(Response::LackingPermission(Permission::BanMembers));
-    }
-
-    if let Ok(result) = get_member(MemberKey(target.id.clone(), other.clone())).await {
-        if result.is_none() {
-            return Some(Response::BadRequest(
-                json!({ "error": "User not part of guild." }),
-            ));
-        }
-    } else {
-        return Some(Response::InternalServerError(
-            json!({ "error": "Failed to fetch member." }),
-        ));
-    }
-
-    if database::get_collection("guilds")
-        .update_one(
-            doc! { "_id": &target.id },
-            doc! {
-                "$push": {
-                    "bans": {
-                        "id": &other,
-                        "reason": reason,
-                    }
-                }
-            },
-            None,
-        )
-        .await
-        .is_err()
-    {
-        return Some(Response::BadRequest(
-            json!({ "error": "Failed to add ban to guild." }),
-        ));
-    }
-
-    if database::get_collection("members")
-        .delete_one(
-            doc! {
-                "_id.guild": &target.id,
-                "_id.user": &other,
-            },
-            None,
-        )
-        .await
-        .is_ok()
-    {
-        /*notifications::send_message_threaded(
-            None,
-            target.id.clone(),
-            Notification::guild_user_leave(UserLeave {
-                id: target.id.clone(),
-                user: other.clone(),
-                banned: true,
-            }), FIXME
-        );*/
-
-        Some(Response::Result(super::Status::Ok))
-    } else {
-        Some(Response::InternalServerError(
-            json!({ "error": "Failed to kick member after adding to ban list." }),
-        ))
-    }
-}
-
-/// unban a guild member
-#[delete("/<target>/members/<other>/ban")]
-pub async fn unban_member(user: User, target: Guild, other: String) -> Option<Response> {
-    let (permissions, _) = with_permissions!(user, target);
-
-    if user.id == other {
-        return Some(Response::BadRequest(
-            json!({ "error": "Cannot unban yourself (not checking if you're banned)." }),
-        ));
-    }
-
-    if !permissions.get_ban_members() {
-        return Some(Response::LackingPermission(Permission::BanMembers));
-    }
-
-    if target.bans.iter().any(|v| v.id == other) {
-        return Some(Response::BadRequest(json!({ "error": "User not banned." })));
-    }
-
-    if database::get_collection("guilds")
-        .update_one(
-            doc! {
-                "_id": &target.id
-            },
-            doc! {
-                "$pull": {
-                    "bans": {
-                        "$elemMatch": {
-                            "id": &other
-                        }
-                    }
-                }
-            },
-            None,
-        )
-        .await
-        .is_ok()
-    {
-        Some(Response::Result(super::Status::Ok))
-    } else {
-        Some(Response::BadRequest(
-            json!({ "error": "Failed to remove ban." }),
-        ))
-    }
-}
diff --git a/src/routes/guild/mod.rs b/src/routes/guild/mod.rs
new file mode 100644
index 0000000000000000000000000000000000000000..9a5378acc6a6de07d35b1c9796f88801f844f3d0
--- /dev/null
+++ b/src/routes/guild/mod.rs
@@ -0,0 +1,5 @@
+use rocket::Route;
+
+pub fn routes() -> Vec<Route> {
+    routes! []
+}
diff --git a/src/routes/mod.rs b/src/routes/mod.rs
index 07c2b91bb8e1dc8c70daf7bdd80133a2eb748d95..c5bc6063f05a3634d168a85e7658515b9971372e 100644
--- a/src/routes/mod.rs
+++ b/src/routes/mod.rs
@@ -2,71 +2,20 @@ pub use rocket::http::Status;
 pub use rocket::response::Redirect;
 use rocket::Rocket;
 
-// use crate::database::Permission;
-// use rocket_contrib::json::JsonValue;
-
-/* pub mod channel;
-pub mod guild;
-pub mod user; */
-pub mod root;
-
-/* #[derive(Responder)]
-pub enum Response {
-    #[response()]
-    Result(Status),
-    #[response()]
-    Success(JsonValue),
-    #[response()]
-    Redirect(Redirect),
-    #[response(status = 207)]
-    PartialStatus(JsonValue),
-    #[response(status = 400)]
-    BadRequest(JsonValue),
-    #[response(status = 401)]
-    Unauthorized(JsonValue),
-    #[response(status = 401)]
-    LackingPermission(Permission),
-    #[response(status = 404)]
-    NotFound(JsonValue),
-    #[response(status = 406)]
-    NotAcceptable(JsonValue),
-    #[response(status = 409)]
-    Conflict(JsonValue),
-    #[response(status = 410)]
-    Gone(JsonValue),
-    #[response(status = 418)]
-    Teapot(JsonValue),
-    #[response(status = 422)]
-    UnprocessableEntity(JsonValue),
-    #[response(status = 429)]
-    TooManyRequests(JsonValue),
-    #[response(status = 500)]
-    InternalServerError(JsonValue),
-}
-
-use rocket::http::ContentType;
-use rocket::request::Request;
-use std::io::Cursor;
-
-use rocket::response::{Responder, Result};
-
-impl<'a> Responder<'a, 'static> for Permission {
-    fn respond_to(self, _: &Request) -> Result<'static> {
-        let body = format!(
-            "{{\"error\":\"Lacking permission: {:?}.\",\"permission\":{}}}",
-            self, self as u32,
-        );
-
-        rocket::response::Response::build()
-            .header(ContentType::JSON)
-            .sized_body(body.len(), Cursor::new(body))
-            .ok()
-    }
-} */
+mod root;
+mod users;
+mod guild;
+mod onboard;
+mod channels;
 
 pub fn mount(rocket: Rocket) -> Rocket {
     rocket
         .mount("/", routes![root::root, root::teapot])
+        .mount("/onboard", onboard::routes())
+        .mount("/users", users::routes())
+        .mount("/channels", channels::routes())
+        .mount("/guild", guild::routes())
+
         /*.mount(
             "/users",
             routes![
diff --git a/src/routes/onboard/hello.rs b/src/routes/onboard/hello.rs
new file mode 100644
index 0000000000000000000000000000000000000000..ecf5847782f14c40669f0d78bf0fcbae4b9e2da8
--- /dev/null
+++ b/src/routes/onboard/hello.rs
@@ -0,0 +1,7 @@
+use crate::util::result::Result;
+use rauth::auth::Session;
+
+#[get("/hello")]
+pub async fn req(session: Session) -> Result<String> {
+    Ok("try onboard user".to_string())
+}
diff --git a/src/routes/onboard/mod.rs b/src/routes/onboard/mod.rs
new file mode 100644
index 0000000000000000000000000000000000000000..74216aba9b2b3da618379599576133e637105be6
--- /dev/null
+++ b/src/routes/onboard/mod.rs
@@ -0,0 +1,9 @@
+use rocket::Route;
+
+mod hello;
+
+pub fn routes() -> Vec<Route> {
+    routes! [
+        hello::req
+    ]
+}
diff --git a/src/routes/user.rs b/src/routes/user.rs
deleted file mode 100644
index e464e82fb21659f99029f007167e0297e578bee0..0000000000000000000000000000000000000000
--- a/src/routes/user.rs
+++ /dev/null
@@ -1,752 +0,0 @@
-use super::Response;
-use crate::database::{
-    self, get_relationship, get_relationship_internal, user::User, Relationship,
-};
-use crate::routes::channel;
-
-use mongodb::bson::doc;
-use mongodb::options::{Collation, FindOneOptions, FindOptions};
-use rocket_contrib::json::Json;
-use serde::{Deserialize, Serialize};
-use rocket::futures::StreamExt;
-use ulid::Ulid;
-
-/// retrieve your user information
-#[get("/@me")]
-pub async fn me(user: User) -> Response {
-    Response::Success(user.serialise(Relationship::SELF as i32))
-}
-
-/// retrieve another user's information
-#[get("/<target>")]
-pub async fn user(user: User, target: User) -> Response {
-    let relationship = get_relationship(&user, &target) as i32;
-    Response::Success(user.serialise(relationship))
-}
-
-#[derive(Serialize, Deserialize)]
-pub struct UserQuery {
-    username: String,
-}
-
-/// find a user by their username
-#[post("/query", data = "<query>")]
-pub async fn query(user: User, query: Json<UserQuery>) -> Response {
-    let col = database::get_collection("users");
-
-    if let Ok(result) = col.find_one(
-        doc! { "username": query.username.clone() },
-        FindOneOptions::builder()
-            .collation(Collation::builder().locale("en").strength(2).build())
-            .build(),
-    )
-    .await {
-        if let Some(doc) = result {
-            let id = doc.get_str("_id").unwrap();
-            Response::Success(json!({
-                "id": id,
-                "username": doc.get_str("username").unwrap(),
-                "display_name": doc.get_str("display_name").unwrap(),
-                "relationship": get_relationship_internal(&user.id, &id, &user.relations) as i32
-            }))
-        } else {
-            Response::NotFound(json!({
-                "error": "User not found!"
-            }))
-        }
-    } else {
-        Response::InternalServerError(json!({ "error": "Failed database query." }))
-    }
-}
-
-/*#[derive(Serialize, Deserialize)]
-pub struct LookupQuery {
-    username: String,
-}
-
-/// lookup a user on Revolt
-/// currently only supports exact username searches
-#[post("/lookup", data = "<query>")]
-pub fn lookup(user: User, query: Json<LookupQuery>) -> Response {
-    let relationships = user.fetch_relationships();
-    let col = database::get_collection("users");
-
-    if let Ok(users) = col.find(
-        doc! { "username": query.username.clone() },
-        FindOptions::builder()
-            .projection(doc! { "_id": 1, "username": 1 })
-            .limit(10)
-            .build(),
-    ) {
-        let mut results = Vec::new();
-        for item in users {
-            if let Ok(doc) = item {
-                let id = doc.get_str("id").unwrap();
-                results.push(json!({
-                    "id": id,
-                    "username": doc.get_str("username").unwrap(),
-                    "relationship": get_relationship_internal(&user.id, &id, &relationships) as i32
-                }));
-            }
-        }
-
-        Response::Success(json!(results))
-    } else {
-        Response::InternalServerError(json!({ "error": "Failed database query." }))
-    }
-}*/
-
-/// retrieve all of your DMs
-#[get("/@me/dms")]
-pub async fn dms(user: User) -> Response {
-    let col = database::get_collection("channels");
-
-    if let Ok(mut results) = col.find(
-        doc! {
-            "$or": [
-                {
-                    "type": channel::ChannelType::DM as i32,
-                    "active": true
-                },
-                {
-                    "type": channel::ChannelType::GROUPDM as i32
-                }
-            ],
-            "recipients": user.id
-        },
-        FindOptions::builder().projection(doc! {}).build(),
-    )
-    .await {
-        let mut channels = Vec::new();
-        while let Some(item) = results.next().await {
-            if let Ok(doc) = item {
-                let id = doc.get_str("_id").unwrap();
-                let last_message = doc.get_document("last_message").unwrap();
-                let recipients = doc.get_array("recipients").unwrap();
-
-                match doc.get_i32("type").unwrap() {
-                    0 => {
-                        channels.push(json!({
-                            "id": id,
-                            "type": 0,
-                            "last_message": last_message,
-                            "recipients": recipients,
-                        }));
-                    }
-                    1 => {
-                        channels.push(json!({
-                            "id": id,
-                            "type": 1,
-                            "recipients": recipients,
-                            "name": doc.get_str("name").unwrap(),
-                            "owner": doc.get_str("owner").unwrap(),
-                            "description": doc.get_str("description").unwrap_or(""),
-                        }));
-                    }
-                    _ => unreachable!(),
-                }
-            }
-        }
-
-        Response::Success(json!(channels))
-    } else {
-        Response::InternalServerError(json!({ "error": "Failed database query." }))
-    }
-}
-
-/// open a DM with a user
-#[get("/<target>/dm")]
-pub async fn dm(user: User, target: User) -> Response {
-    let col = database::get_collection("channels");
-
-    if let Ok(result) = col.find_one(
-		doc! { "type": channel::ChannelType::DM as i32, "recipients": { "$all": [ user.id.clone(), target.id.clone() ] } },
-		None
-	)
-    .await {
-        if let Some(channel) = result {
-            Response::Success( json!({ "id": channel.get_str("_id").unwrap() }))
-        } else {
-			let id = Ulid::new();
-
-			if col.insert_one(
-				doc! {
-					"_id": id.to_string(),
-					"type": channel::ChannelType::DM as i32,
-					"recipients": [ user.id, target.id ],
-					"active": false
-				},
-				None
-			)
-            .await
-            .is_ok() {
-                Response::Success(json!({ "id": id.to_string() }))
-            } else {
-                Response::InternalServerError(json!({ "error": "Failed to create new channel." }))
-            }
-		}
-	} else {
-        Response::InternalServerError(json!({ "error": "Failed server query." }))
-    }
-}
-
-/// retrieve all of your friends
-#[get("/@me/friend")]
-pub async fn get_friends(user: User) -> Response {
-    let mut results = Vec::new();
-    if let Some(arr) = user.relations {
-        for item in arr {
-            results.push(json!({
-                "id": item.id,
-                "status": item.status
-            }))
-        }
-    }
-
-    Response::Success(json!(results))
-}
-
-/// retrieve friend status with user
-#[get("/<target>/friend")]
-pub async fn get_friend(user: User, target: User) -> Response {
-    Response::Success(json!({ "status": get_relationship(&user, &target) as i32 }))
-}
-
-/// create or accept a friend request
-#[put("/<target>/friend")]
-pub async fn add_friend(user: User, target: User) -> Response {
-    let col = database::get_collection("users");
-
-    match get_relationship(&user, &target) {
-        Relationship::Friend => Response::BadRequest(json!({ "error": "Already friends." })),
-        Relationship::Outgoing => {
-            Response::BadRequest(json!({ "error": "Already sent a friend request." }))
-        }
-        Relationship::Incoming => {
-            if col
-                .update_one(
-                    doc! {
-                        "_id": user.id.clone(),
-                        "relations.id": target.id.clone()
-                    },
-                    doc! {
-                        "$set": {
-                            "relations.$.status": Relationship::Friend as i32
-                        }
-                    },
-                    None,
-                )
-                .await
-                .is_ok()
-            {
-                if col
-                    .update_one(
-                        doc! {
-                            "_id": target.id.clone(),
-                            "relations.id": user.id.clone()
-                        },
-                        doc! {
-                            "$set": {
-                                "relations.$.status": Relationship::Friend as i32
-                            }
-                        },
-                        None,
-                    )
-                    .await
-                    .is_ok()
-                {
-                    /*notifications::send_message_threaded(
-                        vec![target.id.clone()],
-                        None,
-                        Notification::user_friend_status(FriendStatus {
-                            id: target.id.clone(),
-                            user: user.id.clone(),
-                            status: Relationship::Friend as i32,
-                        }),
-                    );
-
-                    notifications::send_message_threaded(
-                        vec![user.id.clone()],
-                        None,
-                        Notification::user_friend_status(FriendStatus {
-                            id: user.id.clone(),
-                            user: target.id.clone(),
-                            status: Relationship::Friend as i32,
-                        }), FIXME
-                    );*/
-
-                    Response::Success(json!({ "status": Relationship::Friend as i32 }))
-                } else {
-                    Response::InternalServerError(
-                        json!({ "error": "Failed to commit! Try re-adding them as a friend." }),
-                    )
-                }
-            } else {
-                Response::InternalServerError(
-                    json!({ "error": "Failed to commit to database, try again." }),
-                )
-            }
-        }
-        Relationship::Blocked => {
-            Response::BadRequest(json!({ "error": "You have blocked this person." }))
-        }
-        Relationship::BlockedOther => {
-            Response::Conflict(json!({ "error": "You have been blocked by this person." }))
-        }
-        Relationship::NONE => {
-            if col
-                .update_one(
-                    doc! {
-                        "_id": user.id.clone()
-                    },
-                    doc! {
-                        "$push": {
-                            "relations": {
-                                "id": target.id.clone(),
-                                "status": Relationship::Outgoing as i32
-                            }
-                        }
-                    },
-                    None,
-                )
-                .await
-                .is_ok()
-            {
-                if col
-                    .update_one(
-                        doc! {
-                            "_id": target.id.clone()
-                        },
-                        doc! {
-                            "$push": {
-                                "relations": {
-                                    "id": user.id.clone(),
-                                    "status": Relationship::Incoming as i32
-                                }
-                            }
-                        },
-                        None,
-                    )
-                    .await
-                    .is_ok()
-                {
-                    /*notifications::send_message_threaded(
-                        vec![user.id.clone()],
-                        None,
-                        Notification::user_friend_status(FriendStatus {
-                            id: user.id.clone(),
-                            user: target.id.clone(),
-                            status: Relationship::Outgoing as i32,
-                        }),
-                    );
-
-                    notifications::send_message_threaded(
-                        vec![target.id.clone()],
-                        None,
-                        Notification::user_friend_status(FriendStatus {
-                            id: target.id.clone(),
-                            user: user.id.clone(),
-                            status: Relationship::Incoming as i32,
-                        }), FIXME
-                    );*/
-
-                    Response::Success(json!({ "status": Relationship::Outgoing as i32 }))
-                } else {
-                    Response::InternalServerError(
-                        json!({ "error": "Failed to commit! Try re-adding them as a friend." }),
-                    )
-                }
-            } else {
-                Response::InternalServerError(
-                    json!({ "error": "Failed to commit to database, try again." }),
-                )
-            }
-        }
-        Relationship::SELF => {
-            Response::BadRequest(json!({ "error": "You're already friends with yourself, no? c:" }))
-        }
-    }
-}
-
-/// remove a friend or deny a request
-#[delete("/<target>/friend")]
-pub async fn remove_friend(user: User, target: User) -> Response {
-    let col = database::get_collection("users");
-
-    match get_relationship(&user, &target) {
-        Relationship::Friend | Relationship::Outgoing | Relationship::Incoming => {
-            if col
-                .update_one(
-                    doc! {
-                        "_id": user.id.clone()
-                    },
-                    doc! {
-                        "$pull": {
-                            "relations": {
-                                "id": target.id.clone()
-                            }
-                        }
-                    },
-                    None,
-                )
-                .await
-                .is_ok()
-            {
-                if col
-                    .update_one(
-                        doc! {
-                            "_id": target.id.clone()
-                        },
-                        doc! {
-                            "$pull": {
-                                "relations": {
-                                    "id": user.id.clone()
-                                }
-                            }
-                        },
-                        None,
-                    )
-                    .await
-                    .is_ok()
-                {
-                    /*notifications::send_message_threaded(
-                        vec![user.id.clone()],
-                        None,
-                        Notification::user_friend_status(FriendStatus {
-                            id: user.id.clone(),
-                            user: target.id.clone(),
-                            status: Relationship::NONE as i32,
-                        }),
-                    );
-
-                    notifications::send_message_threaded(
-                        vec![target.id.clone()],
-                        None,
-                        Notification::user_friend_status(FriendStatus {
-                            id: target.id.clone(),
-                            user: user.id.clone(),
-                            status: Relationship::NONE as i32,
-                        }), FIXME
-                    );*/
-
-                    Response::Success(json!({ "status": Relationship::NONE as i32 }))
-                } else {
-                    Response::InternalServerError(
-                        json!({ "error": "Failed to commit! Target remains in same state." }),
-                    )
-                }
-            } else {
-                Response::InternalServerError(
-                    json!({ "error": "Failed to commit to database, try again." }),
-                )
-            }
-        }
-        Relationship::Blocked
-        | Relationship::BlockedOther
-        | Relationship::NONE
-        | Relationship::SELF => Response::BadRequest(json!({ "error": "This has no effect." })),
-    }
-}
-
-/// block a user
-#[put("/<target>/block")]
-pub async fn block_user(user: User, target: User) -> Response {
-    let col = database::get_collection("users");
-
-    match get_relationship(&user, &target) {
-        Relationship::Friend | Relationship::Incoming | Relationship::Outgoing => {
-            if col
-                .update_one(
-                    doc! {
-                        "_id": user.id.clone(),
-                        "relations.id": target.id.clone()
-                    },
-                    doc! {
-                        "$set": {
-                            "relations.$.status": Relationship::Blocked as i32
-                        }
-                    },
-                    None,
-                )
-                .await
-                .is_ok()
-            {
-                if col
-                    .update_one(
-                        doc! {
-                            "_id": target.id.clone(),
-                            "relations.id": user.id.clone()
-                        },
-                        doc! {
-                            "$set": {
-                                "relations.$.status": Relationship::BlockedOther as i32
-                            }
-                        },
-                        None,
-                    )
-                    .await
-                    .is_ok()
-                {
-                    /*notifications::send_message_threaded(
-                        vec![user.id.clone()],
-                        None,
-                        Notification::user_friend_status(FriendStatus {
-                            id: user.id.clone(),
-                            user: target.id.clone(),
-                            status: Relationship::Blocked as i32,
-                        }),
-                    );
-
-                    notifications::send_message_threaded(
-                        vec![target.id.clone()],
-                        None,
-                        Notification::user_friend_status(FriendStatus {
-                            id: target.id.clone(),
-                            user: user.id.clone(),
-                            status: Relationship::BlockedOther as i32,
-                        }), FIXME
-                    );*/
-
-                    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,
-                )
-                .await
-                .is_ok()
-            {
-                if col
-                    .update_one(
-                        doc! {
-                            "_id": target.id.clone(),
-                        },
-                        doc! {
-                            "$push": {
-                                "relations": {
-                                    "id": user.id.clone(),
-                                    "status": Relationship::BlockedOther as i32,
-                                }
-                            }
-                        },
-                        None,
-                    )
-                    .await
-                    .is_ok()
-                {
-                    /*notifications::send_message_threaded(
-                        vec![user.id.clone()],
-                        None,
-                        Notification::user_friend_status(FriendStatus {
-                            id: user.id.clone(),
-                            user: target.id.clone(),
-                            status: Relationship::Blocked as i32,
-                        }),
-                    );
-
-                    notifications::send_message_threaded(
-                        vec![target.id.clone()],
-                        None,
-                        Notification::user_friend_status(FriendStatus {
-                            id: target.id.clone(),
-                            user: user.id.clone(),
-                            status: Relationship::BlockedOther as i32,
-                        }), FIXME
-                    );*/
-
-                    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::Blocked => {
-            Response::BadRequest(json!({ "error": "Already blocked this person." }))
-        }
-        Relationship::BlockedOther => {
-            if col
-                .update_one(
-                    doc! {
-                        "_id": user.id.clone(),
-                        "relations.id": target.id.clone()
-                    },
-                    doc! {
-                        "$set": {
-                            "relations.$.status": Relationship::Blocked as i32
-                        }
-                    },
-                    None,
-                )
-                .await
-                .is_ok()
-            {
-                /*notifications::send_message_threaded(
-                    vec![user.id.clone()],
-                    None,
-                    Notification::user_friend_status(FriendStatus {
-                        id: user.id.clone(),
-                        user: target.id.clone(),
-                        status: Relationship::Blocked as i32,
-                    }), FIXME
-                );*/
-
-                Response::Success(json!({ "status": Relationship::Blocked as i32 }))
-            } else {
-                Response::InternalServerError(
-                    json!({ "error": "Failed to commit to database, try again." }),
-                )
-            }
-        }
-        Relationship::SELF => Response::BadRequest(json!({ "error": "This has no effect." })),
-    }
-}
-
-/// unblock a user
-#[delete("/<target>/block")]
-pub async fn unblock_user(user: User, target: User) -> Response {
-    let col = database::get_collection("users");
-
-    match get_relationship(&user, &target) {
-        Relationship::Blocked => match get_relationship(&target, &user) {
-            Relationship::Blocked => {
-                if col
-                    .update_one(
-                        doc! {
-                            "_id": user.id.clone(),
-                            "relations.id": target.id.clone()
-                        },
-                        doc! {
-                            "$set": {
-                                "relations.$.status": Relationship::BlockedOther as i32
-                            }
-                        },
-                        None,
-                    )
-                    .await
-                    .is_ok()
-                {
-                    /*notifications::send_message_threaded(
-                        vec![user.id.clone()],
-                        None,
-                        Notification::user_friend_status(FriendStatus {
-                            id: user.id.clone(),
-                            user: target.id.clone(),
-                            status: Relationship::BlockedOther as i32,
-                        }), FIXME
-                    );*/
-
-                    Response::Success(json!({ "status": Relationship::BlockedOther as i32 }))
-                } else {
-                    Response::InternalServerError(
-                        json!({ "error": "Failed to commit to database, try again." }),
-                    )
-                }
-            }
-            Relationship::BlockedOther => {
-                if col
-                    .update_one(
-                        doc! {
-                            "_id": user.id.clone()
-                        },
-                        doc! {
-                            "$pull": {
-                                "relations": {
-                                    "id": target.id.clone()
-                                }
-                            }
-                        },
-                        None,
-                    )
-                    .await
-                    .is_ok()
-                {
-                    if col
-                        .update_one(
-                            doc! {
-                                "_id": target.id.clone()
-                            },
-                            doc! {
-                                "$pull": {
-                                    "relations": {
-                                        "id": user.id.clone()
-                                    }
-                                }
-                            },
-                            None,
-                        )
-                        .await
-                        .is_ok()
-                    {
-                        /*notifications::send_message_threaded(
-                            vec![user.id.clone()],
-                            None,
-                            Notification::user_friend_status(FriendStatus {
-                                id: user.id.clone(),
-                                user: target.id.clone(),
-                                status: Relationship::NONE as i32,
-                            }),
-                        );
-
-                        notifications::send_message_threaded(
-                            vec![target.id.clone()],
-                            None,
-                            Notification::user_friend_status(FriendStatus {
-                                id: target.id.clone(),
-                                user: user.id.clone(),
-                                status: Relationship::NONE as i32,
-                            }), FIXME
-                        );*/
-
-                        Response::Success(json!({ "status": Relationship::NONE as i32 }))
-                    } else {
-                        Response::InternalServerError(
-                            json!({ "error": "Failed to commit! Target remains in same state." }),
-                        )
-                    }
-                } else {
-                    Response::InternalServerError(
-                        json!({ "error": "Failed to commit to database, try again." }),
-                    )
-                }
-            }
-            _ => unreachable!(),
-        },
-        Relationship::BlockedOther => {
-            Response::BadRequest(json!({ "error": "Cannot remove block by other user." }))
-        }
-        Relationship::Friend
-        | Relationship::Incoming
-        | Relationship::Outgoing
-        | Relationship::SELF
-        | Relationship::NONE => Response::BadRequest(json!({ "error": "This has no effect." })),
-    }
-}
diff --git a/src/routes/users/fetch_user.rs b/src/routes/users/fetch_user.rs
new file mode 100644
index 0000000000000000000000000000000000000000..009bace7e02f79e9c862211717d46ddb97b6ff91
--- /dev/null
+++ b/src/routes/users/fetch_user.rs
@@ -0,0 +1,7 @@
+use crate::util::result::Result;
+
+#[get("/<id>")]
+pub async fn req(id: String) -> Result<String> {
+    println!("{}", id);
+    Ok("LETS FUCKING GOOOO".to_string())
+}
diff --git a/src/routes/users/mod.rs b/src/routes/users/mod.rs
new file mode 100644
index 0000000000000000000000000000000000000000..4251314cc7e25e44688ba492475c1940dfadce99
--- /dev/null
+++ b/src/routes/users/mod.rs
@@ -0,0 +1,9 @@
+use rocket::Route;
+
+mod fetch_user;
+
+pub fn routes() -> Vec<Route> {
+    routes! [
+        fetch_user::req
+    ]
+}