diff --git a/src/database/channel.rs b/src/database/channel.rs
new file mode 100644
index 0000000000000000000000000000000000000000..be88081674f577f6dae95b7607a1f56777bf9bcd
--- /dev/null
+++ b/src/database/channel.rs
@@ -0,0 +1,12 @@
+use serde::{ Deserialize, Serialize };
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct Channel {
+    #[serde(rename = "_id")]
+    pub id: String,
+	pub channel_type: u8,
+	
+	// for Direct Messages
+	pub recipients: Option<Vec<String>>,
+	pub active: Option<bool>,
+}
diff --git a/src/database/message.rs b/src/database/message.rs
new file mode 100644
index 0000000000000000000000000000000000000000..d65b2118e29611af733a3c2e02db9bf9ceabbd6f
--- /dev/null
+++ b/src/database/message.rs
@@ -0,0 +1,8 @@
+
+use serde::{ Deserialize, Serialize };
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct Message {
+    #[serde(rename = "_id")]
+    pub id: String,
+}
diff --git a/src/database/mod.rs b/src/database/mod.rs
index a2b0e33ece1f4f8d96ad13b8fa9d937f250c004f..fb1d14cfcc07c750fcb06521a88eb8b60be46f01 100644
--- a/src/database/mod.rs
+++ b/src/database/mod.rs
@@ -24,4 +24,6 @@ pub fn get_collection(collection: &str) -> Collection {
 	get_db().collection(collection)
 }
 
-pub mod user;
\ No newline at end of file
+pub mod user;
+pub mod channel;
+pub mod message;
diff --git a/src/guards/auth.rs b/src/guards/auth.rs
index 3f718da94a3878c88bf252e7e3dac3b679fbf0ac..7c3b2bc128c978ca55024efe32915193336c3139 100644
--- a/src/guards/auth.rs
+++ b/src/guards/auth.rs
@@ -3,15 +3,9 @@ use rocket::http::{ Status, RawStr };
 use rocket::request::{ self, Request, FromRequest, FromParam };
 
 use bson::{ bson, doc, from_bson };
-use ulid::Ulid;
 
 use crate::database;
-
-pub struct User(
-	pub Ulid,
-	pub String,
-	pub database::user::User,
-);
+use database::user::User;
 
 #[derive(Debug)]
 pub enum AuthError {
@@ -33,11 +27,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for User {
 				let result = col.find_one(doc! { "access_token": key }, None).unwrap();
 
 				if let Some(user) = result {
-					Outcome::Success(User (
-						Ulid::from_string(user.get_str("_id").unwrap()).unwrap(),
-						user.get_str("username").unwrap().to_string(),
-						from_bson(bson::Bson::Document(user)).expect("Failed to unwrap user.")
-					))
+					Outcome::Success(from_bson(bson::Bson::Document(user)).expect("Failed to unwrap user."))
 				} else {
 					Outcome::Failure((Status::Forbidden, AuthError::Invalid))
 				}
@@ -55,11 +45,7 @@ impl<'r> FromParam<'r> for User {
 		let result = col.find_one(doc! { "_id": param.to_string() }, None).unwrap();
 
 		if let Some(user) = result {
-			Ok(User (
-				Ulid::from_string(user.get_str("_id").unwrap()).unwrap(),
-				user.get_str("username").unwrap().to_string(),
-				from_bson(bson::Bson::Document(user)).expect("Failed to unwrap user.")
-			))
+			Ok(from_bson(bson::Bson::Document(user)).expect("Failed to unwrap user."))
 		} else {
 			Err(param)
 		}
diff --git a/src/guards/channel.rs b/src/guards/channel.rs
index 9142c178e2570e8ad0bb0802c4487386c0f453e4..daa277d5ced8aefd760ab31e77571414f47e1c99 100644
--- a/src/guards/channel.rs
+++ b/src/guards/channel.rs
@@ -1,24 +1,11 @@
-use rocket::Outcome;
-use rocket::http::{ Status, RawStr };
-use rocket::request::{ self, Request, FromRequest, FromParam };
-
-use bson::{ bson, doc, ordered::OrderedDocument };
-use std::convert::TryFrom;
-use ulid::Ulid;
+use rocket::http::{ RawStr };
+use rocket::request::{ FromParam };
+use bson::{ bson, doc, from_bson };
 
 use crate::database;
-use crate::routes::channel::ChannelType;
-
-pub struct Channel (
-	pub Ulid,
-	pub ChannelType,
-	pub OrderedDocument,
-);
 
-pub struct Message (
-	pub Ulid,
-	pub OrderedDocument,
-);
+use database::channel::Channel;
+use database::message::Message;
 
 impl<'r> FromParam<'r> for Channel {
     type Error = &'r RawStr;
@@ -28,11 +15,7 @@ impl<'r> FromParam<'r> for Channel {
 		let result = col.find_one(doc! { "_id": param.to_string() }, None).unwrap();
 
 		if let Some(channel) = result {
-			Ok(Channel (
-				Ulid::from_string(channel.get_str("_id").unwrap()).unwrap(),
-				ChannelType::try_from(channel.get_i32("type").unwrap() as usize).unwrap(),
-				channel
-			))
+			Ok(from_bson(bson::Bson::Document(channel)).expect("Failed to unwrap channel."))
 		} else {
 			Err(param)
 		}
@@ -47,10 +30,7 @@ impl<'r> FromParam<'r> for Message {
 		let result = col.find_one(doc! { "_id": param.to_string() }, None).unwrap();
 
 		if let Some(message) = result {
-			Ok(Message (
-				Ulid::from_string(message.get_str("_id").unwrap()).unwrap(),
-				message
-			))
+			Ok(from_bson(bson::Bson::Document(message)).expect("Failed to unwrap message."))
 		} else {
 			Err(param)
 		}
diff --git a/src/routes/channel.rs b/src/routes/channel.rs
index ed36ee80ce7f9b07fb40aa0a2fd68d514a5df47e..81d3f07437e4255573b61ebe7193a1c9914c0739 100644
--- a/src/routes/channel.rs
+++ b/src/routes/channel.rs
@@ -1,12 +1,8 @@
-use crate::guards::{ auth::User, channel::Channel };
-use crate::database;
+use crate::database::{ user::User, channel::Channel };
 
-use rocket_contrib::json::{ Json, JsonValue };
-use serde::{ Serialize, Deserialize };
-use mongodb::options::FindOptions;
+use rocket_contrib::json::{ JsonValue };
 use num_enum::TryFromPrimitive;
-use bson::{ bson, doc };
-use ulid::Ulid;
+use bson::{ doc };
 
 #[derive(Debug, TryFromPrimitive)]
 #[repr(usize)]
@@ -17,19 +13,21 @@ pub enum ChannelType {
 }
 
 fn has_permission(user: &User, target: &Channel) -> bool {
-	let id = user.0.to_string();
-	match target.1 {
-		ChannelType::DM |
-		ChannelType::GROUP_DM => {
-			for user in target.2.get_array("recipients").expect("DB[recipients]") {
-				if user.as_str().expect("Expected string id.") == id {
-					return true;
+	match target.channel_type {
+		0..=1 => {
+			if let Some(arr) = &target.recipients {
+				for item in arr {
+					if item == &user.id {
+						return true;
+					}
 				}
 			}
 
 			false
 		},
-		ChannelType::GUILD_CHANNEL =>
+		2 =>
+			false,
+		_ =>
 			false
 	}
 }
@@ -41,12 +39,10 @@ pub fn channel(user: User, target: Channel) -> Option<JsonValue> {
 		return None
 	}
 
-	let Channel ( id, channel_type, doc ) = target;
-
 	Some(
 		json!({
-			"id": id.to_string(),
-			"type": channel_type as u8
+			"id": target.id,
+			"type": target.channel_type
 		}
 	))
 }
diff --git a/src/routes/user.rs b/src/routes/user.rs
index 01907890cc2c52e75afa2afa270ec214a2c6ff9b..1fde7d9e3ad5369471d92c8656217eac99b19225 100644
--- a/src/routes/user.rs
+++ b/src/routes/user.rs
@@ -1,5 +1,4 @@
-use crate::guards::auth::User;
-use crate::database;
+use crate::database::{ self, user::User, channel::Channel };
 use crate::routes::channel;
 
 use rocket_contrib::json::{ Json, JsonValue };
@@ -11,14 +10,12 @@ use ulid::Ulid;
 /// retrieve your user information
 #[get("/@me")]
 pub fn me(user: User) -> JsonValue {
-	let User ( id, username, doc ) = user;
-
 	json!({
-		"id": id.to_string(),
-		"username": username,
-		"email": doc.email,
-		"verified": doc.email_verification.verified,
-		"created_timestamp": id.datetime().timestamp(),
+		"id": user.id,
+		"username": user.username,
+		"email": user.email,
+		"verified": user.email_verification.verified,
+		"created_timestamp": Ulid::from_string(&user.id).unwrap().datetime().timestamp(),
 	})
 }
 
@@ -46,7 +43,7 @@ pub fn lookup(_user: User, query: Json<Query>) -> JsonValue {
 
 	let mut results = Vec::new();
 	for user in users {
-		let u: database::user::User = from_bson(bson::Bson::Document(user.unwrap())).expect("Failed to unwrap user.");
+		let u: User = from_bson(bson::Bson::Document(user.unwrap())).expect("Failed to unwrap user.");
 		results.push(
 			json!({
 				"id": u.id,
@@ -73,35 +70,21 @@ pub fn dms(user: User) -> JsonValue {
 					"type": channel::ChannelType::GROUP_DM as i32
 				}
 			],
-			"recipients": user.0.to_string()
+			"recipients": user.id
 		},
 		None
 	).expect("Failed channel lookup");
 
 	let mut channels = Vec::new();
-	for res in results {
-		let doc = res.expect("Failed to unwrap document");
-
-		let mut recipients = Vec::new();
-		for user in doc.get_array("recipients").expect("DB[recipients]") {
-			recipients.push(
-				user.as_str()
-					.expect("Should be a string.")
-			);
-		}
-
-		let active =
-			match doc.get_bool("active") {
-				Ok(x) => x,
-				Err(_) => true
-			};
+	for item in results {
+		let channel: Channel = from_bson(bson::Bson::Document(item.unwrap())).expect("Failed to unwrap channel.");
 		
 		channels.push(
 			json!({
-				"id": doc.get_str("_id").expect("DB[id]"),
-				"type": doc.get_i32("type").expect("DB[type]"),
-				"recipients": recipients,
-				"active": active
+				"id": channel.id,
+				"type": channel.channel_type,
+				"recipients": channel.recipients,
+				"active": channel.active.unwrap()
 			})
 		);
 	}
@@ -115,12 +98,12 @@ pub fn dm(user: User, target: User) -> JsonValue {
 	let col = database::get_collection("channels");
 
 	match col.find_one(
-		doc! { "type": channel::ChannelType::DM as i32, "recipients": [ user.0.to_string(), target.0.to_string() ] },
+		doc! { "type": channel::ChannelType::DM as i32, "recipients": [ user.id.clone(), target.id.clone() ] },
 		None
 	).expect("Failed channel lookup") {
 		Some(channel) =>
 			json!({
-				"id": channel.get_str("_id").expect("DB[id]")
+				"id": channel.get_str("_id").unwrap()
 			}),
 		None => {
 			let id = Ulid::new();
@@ -129,7 +112,7 @@ pub fn dm(user: User, target: User) -> JsonValue {
 				doc! {
 					"_id": id.to_string(),
 					"type": channel::ChannelType::DM as i32,
-					"recipients": [ user.0.to_string(), target.0.to_string() ],
+					"recipients": [ user.id, target.id ],
 					"active": false
 				},
 				None
@@ -153,15 +136,13 @@ enum Relationship {
 }
 
 fn get_relationship(a: &User, b: &User) -> Relationship {
-	if a.0.to_string() == b.0.to_string() {
+	if a.id == b.id {
 		return Relationship::SELF
 	}
 
-	if let Some(arr) = &b.2.relations {
-		let id = a.0.to_string();
-		
+	if let Some(arr) = &b.relations {
 		for entry in arr {
-			if entry.id == id {
+			if entry.id == a.id {
 				match entry.status {
 					0 => {
 						return Relationship::FRIEND
@@ -190,7 +171,7 @@ fn get_relationship(a: &User, b: &User) -> Relationship {
 #[get("/@me/friend")]
 pub fn get_friends(user: User) -> JsonValue {
 	let mut results = Vec::new();
-	if let Some(arr) = user.2.relations {
+	if let Some(arr) = user.relations {
 		for item in arr {
 			results.push(
 				json!({
@@ -210,7 +191,7 @@ pub fn get_friend(user: User, target: User) -> JsonValue {
 	let relationship = get_relationship(&user, &target);
 
 	json!({
-		"id": target.0.to_string(),
+		"id": target.id,
 		"status": relationship as u8
 	})
 }
@@ -219,10 +200,7 @@ pub fn get_friend(user: User, target: User) -> JsonValue {
 #[put("/<target>/friend")]
 pub fn add_friend(user: User, target: User) -> JsonValue {
 	let col = database::get_collection("users");
-
 	let relationship = get_relationship(&user, &target);
-	let User ( id, _, _ ) = user;
-	let User ( tid, _, _ ) = target;
 
 	match relationship {
 		Relationship::FRIEND =>
@@ -238,8 +216,8 @@ pub fn add_friend(user: User, target: User) -> JsonValue {
 		Relationship::INCOMING => {
 			col.update_one(
 				doc! {
-					"_id": id.to_string(),
-					"relations.id": tid.to_string()
+					"_id": user.id.clone(),
+					"relations.id": target.id.clone()
 				},
 				doc! {
 					"$set": {
@@ -251,8 +229,8 @@ pub fn add_friend(user: User, target: User) -> JsonValue {
 			
 			col.update_one(
 				doc! {
-					"_id": tid.to_string(),
-					"relations.id": id.to_string()
+					"_id": target.id,
+					"relations.id": user.id
 				},
 				doc! {
 					"$set": {
@@ -279,12 +257,12 @@ pub fn add_friend(user: User, target: User) -> JsonValue {
 		Relationship::NONE => {
 			col.update_one(
 				doc! {
-					"_id": id.to_string()
+					"_id": user.id.clone()
 				},
 				doc! {
 					"$push": {
 						"relations": {
-							"id": tid.to_string(),
+							"id": target.id.clone(),
 							"status": Relationship::OUTGOING as i32
 						}
 					}
@@ -294,12 +272,12 @@ pub fn add_friend(user: User, target: User) -> JsonValue {
 			
 			col.update_one(
 				doc! {
-					"_id": tid.to_string()
+					"_id": target.id
 				},
 				doc! {
 					"$push": {
 						"relations": {
-							"id": id.to_string(),
+							"id": user.id,
 							"status": Relationship::INCOMING as i32
 						}
 					}
@@ -323,10 +301,7 @@ pub fn add_friend(user: User, target: User) -> JsonValue {
 #[delete("/<target>/friend")]
 pub fn remove_friend(user: User, target: User) -> JsonValue {
 	let col = database::get_collection("users");
-
 	let relationship = get_relationship(&user, &target);
-	let User ( id, _, _ ) = user;
-	let User ( tid, _, _ ) = target;
 
 	match relationship {
 		Relationship::FRIEND |
@@ -334,12 +309,12 @@ pub fn remove_friend(user: User, target: User) -> JsonValue {
 		Relationship::INCOMING => {
 			col.update_one(
 				doc! {
-					"_id": id.to_string()
+					"_id": user.id.clone()
 				},
 				doc! {
 					"$pull": {
 						"relations": {
-							"id": tid.to_string()
+							"id": target.id.clone()
 						}
 					}
 				},
@@ -348,12 +323,12 @@ pub fn remove_friend(user: User, target: User) -> JsonValue {
 
 			col.update_one(
 				doc! {
-					"_id": tid.to_string()
+					"_id": target.id
 				},
 				doc! {
 					"$pull": {
 						"relations": {
-							"id": id.to_string()
+							"id": user.id
 						}
 					}
 				},