diff --git a/src/main.rs b/src/main.rs
index 2207e5ffd6f9b8e360898d2db279bae27000f3d4..7058333d02135e18c5b31639560ee6c7d3d45a9d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -17,26 +17,18 @@ use serenity::{
     utils::MessageBuilder,
 };
 
+#[macro_use]
+mod util;
 mod config;
 mod reaction_roles;
 mod token_management;
 mod user_management;
-mod util;
 mod voting;
 
 use config::CONFIG;
 use reaction_roles::{add_role_by_reaction, remove_role_by_reaction};
 use util::get_string_from_react;
 
-macro_rules! e {
-    ($error: literal, $x:expr) => {
-        match $x {
-            Ok(_) => (),
-            Err(why) => error!($error, why),
-        }
-    };
-}
-
 struct Handler;
 
 impl EventHandler for Handler {
@@ -51,30 +43,17 @@ impl EventHandler for Handler {
         }
         let message_content: Vec<_> = msg.content[1..].splitn(2, ' ').collect();
         match message_content[0] {
-            "say" => {
-                println!("{:#?}", msg.content);
-            }
+            "say" => println!("{:#?}", msg.content),
             "register" => user_management::Commands::register(ctx, msg.clone(), message_content[1]),
             "verify" => user_management::Commands::verify(ctx, msg.clone(), message_content[1]),
-            "move" => {
-                voting::Commands::move_something(ctx, msg.clone(), message_content[1]);
-            }
-            "motion" => {
-                voting::Commands::motion(ctx, msg.clone(), message_content[1]);
-            }
-            "poll" => {
-                voting::Commands::poll(ctx, msg.clone(), message_content[1]);
-            }
-            "cowsay" => {
-                voting::Commands::cowsay(ctx, msg.clone(), message_content[1]);
-            }
+            "move" => voting::Commands::move_something(ctx, msg.clone(), message_content[1]),
+            "motion" => voting::Commands::motion(ctx, msg.clone(), message_content[1]),
+            "poll" => voting::Commands::poll(ctx, msg.clone(), message_content[1]),
+            "cowsay" => voting::Commands::cowsay(ctx, msg.clone(), message_content[1]),
             "logreact" => {
                 e!("Error deleting logreact prompt: {:?}", msg.delete(&ctx));
-                e!(
-                    "Error sending message {:?}",
-                    msg.channel_id
-                        .say(&ctx.http, "React to this to log the ID (for the next 5min)")
-                )
+                send_message!(msg.channel_id, &ctx.http, 
+                    "React to this to log the ID (for the next 5min)");
             }
             "help" => {
                 let mut message = MessageBuilder::new();
@@ -86,40 +65,25 @@ impl EventHandler for Handler {
                     "Use {}poll <proposal> to see what people think about something",
                     &CONFIG.command_prefix
                 ));
-                e!(
-                    "Error sending message: {:?}",
-                    msg.channel_id.say(&ctx.http, message.build())
-                );
-            }
-            _ => {
-                e!(
-                    "Error sending message: {:?}",
-                    msg.channel_id.say(
-                        &ctx.http,
-                        format!("Unrecognised command. Try {}help", &CONFIG.command_prefix)
-                    )
-                );
-            }
+                send_message!(msg.channel_id, &ctx.http, message.build());
+            },
+            _ => send_message!(msg.channel_id, &ctx.http, 
+                    format!("Unrecognised command. Try {}help", &CONFIG.command_prefix)),
         }
     }
 
     fn reaction_add(&self, ctx: Context, add_reaction: channel::Reaction) {
         match add_reaction.message(&ctx.http) {
             Ok(message) => {
-                let message_type = get_message_type(&message);
-                if message_type == MessageType::RoleReactMessage
-                    && add_reaction.user_id.0 != CONFIG.bot_id
-                {
-                    add_role_by_reaction(&ctx, message, add_reaction);
-                    return;
-                }
-                if message.author.id.0 != CONFIG.bot_id || add_reaction.user_id == CONFIG.bot_id {
-                    return;
-                }
-                match message_type {
-                    MessageType::Motion => {
-                        voting::reaction_add(ctx, add_reaction);
-                    }
+                match get_message_type(&message) {
+                    MessageType::RoleReactMessage if add_reaction.user_id.0 != CONFIG.bot_id => {
+                        add_role_by_reaction(&ctx, message, add_reaction);
+                        return
+                    },
+                    _ if message.author.id.0 != CONFIG.bot_id || add_reaction.user_id == CONFIG.bot_id => {
+                        return;
+                    },
+                    MessageType::Motion => voting::reaction_add(ctx, add_reaction),
                     MessageType::LogReact => {
                         let react_user = add_reaction.user(&ctx).unwrap();
                         let react_as_string = get_string_from_react(&add_reaction.emoji);
@@ -141,14 +105,11 @@ impl EventHandler for Handler {
                             add_reaction.emoji,
                         ));
                         msg.push_mono(react_as_string);
-                        e!(
-                            "Error sending message: {:?}",
-                            message.channel_id.say(&ctx.http, msg.build())
-                        );
-                    }
-                    _ => {}
+                        send_message!(message.channel_id, &ctx.http, msg.build());
+                    },
+                    _ => {},
                 }
-            }
+            },
             Err(why) => error!("Failed to get react message {:?}", why),
         }
     }
@@ -156,21 +117,18 @@ impl EventHandler for Handler {
     fn reaction_remove(&self, ctx: Context, removed_reaction: channel::Reaction) {
         match removed_reaction.message(&ctx.http) {
             Ok(message) => {
-                let message_type = get_message_type(&message);
-                if message_type == MessageType::RoleReactMessage
-                    && removed_reaction.user_id != CONFIG.bot_id
-                {
-                    remove_role_by_reaction(&ctx, message, removed_reaction);
-                    return;
-                }
-                if message.author.id.0 != CONFIG.bot_id || removed_reaction.user_id == CONFIG.bot_id
-                {
-                    return;
+                match get_message_type(&message) {
+                    MessageType::RoleReactMessage if removed_reaction.user_id != CONFIG.bot_id => {
+                        remove_role_by_reaction(&ctx, message, removed_reaction);
+                        return
+                    },
+                    _ if message.author.id.0 != CONFIG.bot_id || removed_reaction.user_id == CONFIG.bot_id => {
+                        return;
+                    },
+                    MessageType::Motion => voting::reaction_remove(ctx, removed_reaction),
+                    _ => {},
                 }
-                if message_type == MessageType::Motion {
-                    voting::reaction_remove(ctx, removed_reaction);
-                }
-            }
+            },
             Err(why) => error!("Failed to get react message {:?}", why),
         }
     }
diff --git a/src/reaction_roles.rs b/src/reaction_roles.rs
index 779aaf9df5f809173612153fcaf37c1a51cf9061..f0f1b38b009b00eedde06b9fd25098e57fd7215a 100644
--- a/src/reaction_roles.rs
+++ b/src/reaction_roles.rs
@@ -8,15 +8,6 @@ use serenity::{
 use std::collections::{HashMap, HashSet};
 use std::iter::FromIterator;
 
-macro_rules! e {
-    ($error: literal, $x:expr) => {
-        match $x {
-            Ok(_) => (),
-            Err(why) => error!($error, why),
-        }
-    };
-}
-
 pub fn add_role_by_reaction(ctx: &Context, msg: Message, added_reaction: Reaction) {
     let user = added_reaction
         .user_id
diff --git a/src/user_management.rs b/src/user_management.rs
index 82de3b1978c0fbfb5b3f28585f6071fae79c9b4c..8f18fe9239452c8c6090d19b8f0a478f38a1a8de 100644
--- a/src/user_management.rs
+++ b/src/user_management.rs
@@ -8,15 +8,6 @@ use serenity::{
 use crate::config::CONFIG;
 use crate::token_management::*;
 
-macro_rules! e {
-    ($error: literal, $x:expr) => {
-        match $x {
-            Ok(_) => (),
-            Err(why) => error!($error, why),
-        }
-    };
-}
-
 pub fn new_member(ctx: &Context, mut new_member: Member) {
     let mut message = MessageBuilder::new();
     message.push("Nice to see you here ");
@@ -24,16 +15,12 @@ pub fn new_member(ctx: &Context, mut new_member: Member) {
     message.push_line("! Would you care to introduce yourself?");
     message.push_line("If you're not sure where to start, perhaps you could tell us about your projects, your first computer…");
     message.push_line("You should also know that we follow the Freenode Channel Guidelines: https://freenode.net/changuide, and try to avoid defamatory content");
-    if let Err(why) = CONFIG.welcome_channel.say(&ctx, message.build()) {
-        error!("Error sending message: {:?}", why);
-    }
+    send_message!(CONFIG.welcome_channel, &ctx, message.build());
 
     let mut message = MessageBuilder::new();
     message.push(format!("Say hi to {} in ", new_member.display_name()));
     message.mention(&CONFIG.welcome_channel);
-    if let Err(why) = CONFIG.main_channel.say(&ctx, message.build()) {
-        error!("Error sending message: {:?}", why);
-    }
+    send_message!(CONFIG.main_channel, &ctx, message.build());
 
     if let Err(why) = new_member.add_role(&ctx.http, CONFIG.unregistered_member_role) {
         error!("Error adding user role: {:?}", why);
@@ -53,19 +40,15 @@ pub struct Commands;
 impl Commands {
     pub fn register(ctx: Context, msg: Message, account_name: &str) {
         if account_name.is_empty() {
-            e!(
-                "Error sending message: {:?}",
-                msg.channel_id
-                    .say(&ctx.http, "Usage: !register <ucc username>")
-            );
+            send_message!(msg.channel_id, &ctx.http, "Usage: !register <ucc username>");
             return;
         }
-        e!(
-            "Error sending message: {:?}",
-            // TODO convert to email
-            msg.channel_id
-                .say(&ctx.http, format!("Hey {} here's that token you ordered: {}\nIf this wasn't you just ignore this.", account_name, generate_token(&msg.author, account_name)))
-        );
+        send_message!(
+            msg.channel_id, 
+            &ctx.http, 
+            format!("Hey {} here's that token you ordered: {}\nIf this wasn't you just ignore this.", 
+                account_name, 
+                generate_token(&msg.author, account_name)));
         e!("Error deleting register message: {:?}", msg.delete(ctx));
     }
     pub fn verify(ctx: Context, msg: Message, token: &str) {
@@ -102,11 +85,7 @@ impl Commands {
                         })
                 );
             }
-            Err(reason) => e!(
-                "Error sending message: {:?}",
-                msg.channel_id
-                    .say(&ctx.http, format!("Verification error: {:?}", reason))
-            ),
+            Err(reason) => send_message!(msg.channel_id, &ctx.http, format!("Verification error: {:?}", reason)),
         }
         e!("Error deleting register message: {:?}", msg.delete(&ctx));
     }
diff --git a/src/util.rs b/src/util.rs
index 75aba7ffb49697e3a9d8ad3778fc586bd1816785..777c641f034577c8c3245124257ed750b24f5d43 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -21,3 +21,24 @@ pub fn get_react_from_string(string: String, guild: PartialGuild) -> ReactionTyp
             |custom_emoji| ReactionType::from(custom_emoji.clone()),
         )
 }
+
+#[macro_use]
+macro_rules! e {
+    ($error: literal, $x:expr) => {
+        match $x {
+            Ok(_) => (),
+            Err(why) => error!($error, why),
+        }
+    };
+}
+
+#[macro_use]
+macro_rules! send_message {
+    ($chan:expr, $context:expr, $message:expr) => {
+        match $chan
+            .say($context, $message) {
+            Ok(_) => (),
+            Err(why) => error!("Error sending message: {:?}", why),
+        }
+    };
+}
diff --git a/src/voting.rs b/src/voting.rs
index 4920fee502e87a72439d61c732a7a128dc0d6c5b..12ecfc60c2c05a6ddbe74d34790474e6f1782b68 100644
--- a/src/voting.rs
+++ b/src/voting.rs
@@ -9,15 +9,6 @@ use std::sync::Mutex;
 use crate::config::CONFIG;
 use crate::util::get_string_from_react;
 
-macro_rules! e {
-    ($error: literal, $x:expr) => {
-        match $x {
-            Ok(_) => (),
-            Err(why) => error!($error, why),
-        }
-    };
-}
-
 pub struct Commands;
 impl Commands {
     pub fn move_something(ctx: Context, msg: Message, content: &str) {
@@ -26,20 +17,12 @@ impl Commands {
             create_motion(&ctx, &msg, motion);
             return;
         }
-        e!(
-            "Error sending message: {:?}",
-            msg.channel_id.say(
-                &ctx.http,
-                "If there's something you want to motion, put it after the !move keyword",
-            )
-        );
+        send_message!(msg.channel_id, &ctx.http,
+            "If there's something you want to motion, put it after the !move keyword");
     }
     pub fn motion(ctx: Context, msg: Message, _content: &str) {
-        e!("Error sending message: {:?}",
-                msg.channel_id.say(
-                &ctx.http,
-                "I hope you're not having a motion. You may have wanted to !move something instead."
-            ));
+        send_message!(msg.channel_id, &ctx.http,
+            "I hope you're not having a motion. You may have wanted to !move something instead.");
     }
     pub fn poll(ctx: Context, msg: Message, content: &str) {
         let topic = content;
@@ -47,13 +30,8 @@ impl Commands {
             create_poll(&ctx, &msg, topic);
             return;
         }
-        e!(
-            "Error sending message: {:?}",
-            msg.channel_id.say(
-                &ctx.http,
-                "If there's something you want to motion, put it after the !move keyword",
-            )
-        );
+        send_message!(msg.channel_id, &ctx.http,
+            "If there's something you want to motion, put it after the !move keyword");
     }
     pub fn cowsay(ctx: Context, msg: Message, content: &str) {
         let output = if !content.trim().is_empty() {
@@ -78,10 +56,7 @@ impl Commands {
             String::from_utf8(output.stdout).expect("unable to parse stdout to String"),
             None,
         );
-        e!(
-            "Error sending message: {:?}",
-            msg.channel_id.say(&ctx.http, message.build())
-        );
+        send_message!(msg.channel_id, &ctx.http, message.build());
     }
 }
 
@@ -284,9 +259,7 @@ fn update_motion(
             message.push(" is now ");
             message.push_bold(status);
             message.push_italic(format!(" (was {})", last_status));
-            if let Err(why) = CONFIG.announcement_channel.say(&ctx.http, message.build()) {
-                error!("Error sending message: {:?}", why);
-            };
+            send_message!(CONFIG.announcement_channel, &ctx.http, message.build());
         }
     };