diff --git a/src/config.rs b/src/config.rs
index 86287a5e16e6bc1403d372bdb82b5fade0c4e802..9320830f9d933801b383f04b4782afd10c7071fd 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -7,6 +7,8 @@ use std::fs;
 lazy_static! {
     static ref CONFIG_FILE: String = fs::read_to_string("config.yml").unwrap();
     pub static ref CONFIG: UccbotConfig = serde_yaml::from_str(&CONFIG_FILE).unwrap();
+    static ref SECRETS_FILE: String = fs::read_to_string("secrets.yml").unwrap();
+    pub static ref SECRETS: UccbotSecrets = serde_yaml::from_str(&SECRETS_FILE).unwrap();
 }
 
 #[derive(Debug, Deserialize)]
@@ -32,7 +34,12 @@ pub struct UccbotConfig {
     pub react_role_messages: Vec<ReactionMapping>,
     #[serde(default = "ldap_bind_address")]
     pub bind_address: String,
+}
+
+#[derive(Debug, Deserialize)]
+pub struct UccbotSecrets {
     pub ldap_pass: String,
+    pub discord_token: String,
 }
 
 pub fn ldap_bind_address() -> String {
diff --git a/src/ldap.rs b/src/ldap.rs
index bf9aa123d44d788ba7b5883d43ed9cbac72fa296..1346ffc24bbaec0cff6dd7ede550cbf4cc1006ae 100644
--- a/src/ldap.rs
+++ b/src/ldap.rs
@@ -1,5 +1,5 @@
+use crate::config::{CONFIG, SECRETS};
 use ldap3::{LdapConn, LdapConnSettings, Scope, SearchEntry};
-use crate::config::CONFIG;
 
 #[derive(Debug)]
 pub struct LDAPUser {
@@ -10,11 +10,11 @@ pub struct LDAPUser {
 
 pub fn ldap_search(username: &str) -> Option<LDAPUser> {
     let settings = LdapConnSettings::new().set_no_tls_verify(true);
-    let ldap = LdapConn::with_settings(settings, &CONFIG.bind_address)
-        .expect("Unable to connect to LDAP");
+    let ldap =
+        LdapConn::with_settings(settings, &CONFIG.bind_address).expect("Unable to connect to LDAP");
     ldap.simple_bind(
         "cn=ucc-discord-bot,cn=Users,dc=ad,dc=ucc,dc=gu,dc=uwa,dc=edu,dc=au",
-        &CONFIG.ldap_pass,
+        &SECRETS.ldap_pass,
     )
     .expect("Unable to attempt to bind to LDAP")
     .success()
@@ -29,7 +29,7 @@ pub fn ldap_search(username: &str) -> Option<LDAPUser> {
         .expect("LDAP error")
         .success()
         .expect("LDAP search error");
-    if rs.len() != 1 {
+    if rs.is_empty() {
         return None;
     }
     let result = SearchEntry::construct(rs[0].clone()).attrs;
@@ -50,10 +50,7 @@ pub fn ldap_search(username: &str) -> Option<LDAPUser> {
 }
 
 pub fn ldap_exists(username: &str) -> bool {
-    match ldap_search(username) {
-        Some(_) => true,
-        None => false,
-    }
+    ldap_search(username).is_some()
 }
 
 #[derive(Debug)]
diff --git a/src/main.rs b/src/main.rs
index 439e38e279472f7771f7a6637c45dd734207ebc0..2486c3e798119ae609a16c4845963ca1316a43ba 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -13,7 +13,7 @@ extern crate diesel;
 extern crate ldap3;
 
 use simplelog::*;
-use std::fs::{read_to_string, File};
+use std::fs::File;
 
 use chrono::prelude::Utc;
 use serenity::{
@@ -32,7 +32,7 @@ mod token_management;
 mod user_management;
 mod voting;
 
-use config::CONFIG;
+use config::{CONFIG, SECRETS};
 use reaction_roles::{add_role_by_reaction, remove_role_by_reaction};
 use util::get_string_from_react;
 
@@ -135,7 +135,7 @@ impl EventHandler for Handler {
                 _ if message.author.id.0 != CONFIG.bot_id
                     || add_reaction.user_id == CONFIG.bot_id =>
                 {
-                    return;
+                    return
                 }
                 MessageType::Motion => voting::reaction_add(ctx, add_reaction),
                 MessageType::LogReact => {
@@ -177,7 +177,7 @@ impl EventHandler for Handler {
                 _ if message.author.id.0 != CONFIG.bot_id
                     || removed_reaction.user_id == CONFIG.bot_id =>
                 {
-                    return;
+                    return
                 }
                 MessageType::Motion => voting::reaction_remove(ctx, removed_reaction),
                 _ => {}
@@ -222,13 +222,10 @@ fn main() {
     ])
     .unwrap();
 
-    // Configure the client with your Discord bot token in the environment.
-    let token = read_to_string("discord_token").unwrap();
-
     // Create a new instance of the Client, logging in as a bot. This will
     // automatically prepend your bot token with "Bot ", which is a requirement
     // by Discord for bot users.
-    let mut client = Client::new(&token, Handler).expect("Err creating client");
+    let mut client = Client::new(&SECRETS.discord_token, Handler).expect("Err creating client");
 
     // Finally, start a single shard, and start listening to events.
     //
diff --git a/src/token_management.rs b/src/token_management.rs
index d32a067c08e90d47161acc3c24947a9005467e7f..ff11f94b0c6889137862ac3cbd7f8d651073b4e2 100644
--- a/src/token_management.rs
+++ b/src/token_management.rs
@@ -5,6 +5,8 @@ use rand::Rng;
 use serenity::model::user::User;
 use std::str;
 
+pub static TOKEN_LIFETIME: i64 = 300; // 5 minutes
+
 lazy_static! {
     static ref KEY: [u8; 32] = rand::thread_rng().gen::<[u8; 32]>();
     static ref CIPHER: Cipher = Cipher::aes_256_cbc();
@@ -76,7 +78,7 @@ pub fn parse_token(discord_user: &User, encrypted_token: &str) -> Result<String,
         return Err(TokenError::DiscordIdMismatch);
     }
     let time_delta_seconds = Utc::now().timestamp() - token_timestamp.timestamp();
-    if time_delta_seconds > 5 * 60 {
+    if time_delta_seconds > TOKEN_LIFETIME {
         warn!(
             "... attempt failed : token expired ({} seconds old)",
             time_delta_seconds
diff --git a/src/user_management.rs b/src/user_management.rs
index 2bb4019262923db9b3bd7e326838ac17761bb29e..7b5bddffd6f9b52aa6e81090136c256837cb4fc1 100644
--- a/src/user_management.rs
+++ b/src/user_management.rs
@@ -34,7 +34,7 @@ pub fn new_member(ctx: &Context, mut new_member: Member) {
 
     if let Err(why) = new_member.add_role(&ctx.http, CONFIG.unregistered_member_role) {
         error!("Error adding user role: {:?}", why);
-    };
+    }
 }
 
 fn member_nickname(member: &database::Member) -> String {
@@ -400,13 +400,14 @@ impl Commands {
             Commands::set_info(ctx, msg, "");
             return;
         }
-        let clear_property = match field {
+        match field {
             "bio" => database::set_member_bio(&msg.author.id.0, None),
             "git" => database::set_member_git(&msg.author.id.0, None),
             "photo" => database::set_member_photo(&msg.author.id.0, None),
             "web" => database::set_member_website(&msg.author.id.0, None),
             "study" => database::set_member_study(&msg.author.id.0, None),
             _ => Err(diesel::result::Error::NotFound),
-        };
+        }
+        .expect("Unable to clear profile field");
     }
 }
diff --git a/src/voting.rs b/src/voting.rs
index bbb5c7daa53975674a364b9b1787eef9a78aac3c..6d679612eed4150e7542545066464c614c6fc5d4 100644
--- a/src/voting.rs
+++ b/src/voting.rs
@@ -198,6 +198,19 @@ fn set_cached_motion(id: serenity::model::id::MessageId, motion_info: MotionInfo
     warn!("{}", "Couldn't find motion in cache to set");
 }
 
+macro_rules! tiebreaker {
+    ($ctx: expr, $vote: expr, $motion_info: expr) => {
+        if $motion_info.votes.get($vote).unwrap().iter().any(|u| {
+            u.has_role($ctx, CONFIG.server_id, CONFIG.tiebreaker_role)
+                .unwrap()
+        }) {
+            0.25
+        } else {
+            0.0
+        }
+    };
+}
+
 fn update_motion(
     ctx: &Context,
     msg: &mut Message,
@@ -211,31 +224,11 @@ fn update_motion(
     let against_votes = motion_info.votes.get(&CONFIG.against_vote).unwrap().len() as isize - 1;
     let abstain_votes = motion_info.votes.get(&CONFIG.abstain_vote).unwrap().len() as isize - 1;
 
-    let has_tiebreaker = |users: &Vec<serenity::model::user::User>| {
-        users.iter().any(|u| {
-            u.has_role(ctx, CONFIG.server_id, CONFIG.tiebreaker_role)
-                .unwrap()
-        })
-    };
-
-    let for_strength = for_votes as f32
-        + (if has_tiebreaker(motion_info.votes.get(&CONFIG.for_vote).unwrap()) {
-            0.25
-        } else {
-            0.0
-        });
-    let against_strength = against_votes as f32
-        + (if has_tiebreaker(motion_info.votes.get(&CONFIG.against_vote).unwrap()) {
-            0.25
-        } else {
-            0.0
-        });
-    let abstain_strength = abstain_votes as f32
-        + (if has_tiebreaker(motion_info.votes.get(&CONFIG.abstain_vote).unwrap()) {
-            0.25
-        } else {
-            0.0
-        });
+    let for_strength = for_votes as f32 + tiebreaker!(ctx, &CONFIG.for_vote, motion_info);
+    let against_strength =
+        against_votes as f32 + tiebreaker!(ctx, &CONFIG.against_vote, motion_info);
+    let abstain_strength =
+        abstain_votes as f32 + tiebreaker!(ctx, &CONFIG.abstain_vote, motion_info);
 
     let old_embed = msg.embeds[0].clone();
     let topic = old_embed.clone().title.unwrap();