diff --git a/config/config.sample.yaml b/config/config.sample.yaml
index 2b8350597ca9ef0ddf984570efa16e2d3eda00cd..925df2bbadf7195dd2049b2c01c901c61620e0fa 100644
--- a/config/config.sample.yaml
+++ b/config/config.sample.yaml
@@ -87,5 +87,9 @@ channel:
        # Make all the discord users leave the room.
        ghostsLeave: true
 limits:
-    # Delay between discord users joining a room.
+    # Delay in milliseconds between discord users joining a room.
     roomGhostJoinDelay: 6000
+    # Delay in milliseconds before sending messages to discord to avoid echos.
+    # (Copies of a sent message may arrive from discord before we've
+    # fininished handling it, causing us to echo it back to the room)
+    discordSendDelay: 750
diff --git a/config/config.schema.yaml b/config/config.schema.yaml
index 56de3a8585438f47d06b7636f0849b9163a72c6a..4f832fa6ce069b1a2560c318a806e09c9127b00a 100644
--- a/config/config.schema.yaml
+++ b/config/config.schema.yaml
@@ -89,6 +89,8 @@ properties:
         properties:
             roomGhostJoinDelay:
                 type: "number"
+            discordSendDelay:
+                type: "number"
     channel:
         type: "object"
         properties:
diff --git a/src/bot.ts b/src/bot.ts
index deed4d7e4a38bd2d9b5a68eb405405d8e67935b9..eb23cf919ca1da4509f977ccf175a62c81f4c7b7 100644
--- a/src/bot.ts
+++ b/src/bot.ts
@@ -19,9 +19,6 @@ import * as mime from "mime";
 
 const log = new Log("DiscordBot");
 
-// Due to messages often arriving before we get a response from the send call,
-// messages get delayed from discord.
-const MSG_PROCESS_DELAY = 750;
 const MIN_PRESENCE_UPDATE_DELAY = 250;
 
 // TODO: This is bad. We should be serving the icon from the own homeserver.
@@ -46,6 +43,9 @@ export class DiscordBot {
   private channelSync: ChannelSyncroniser;
   private roomHandler: MatrixRoomHandler;
 
+  /* Handles messages queued up to be sent to discord. */
+  private discordMessageQueue: { [channelId: string]: Promise<any> };
+
   constructor(config: DiscordBridgeConfig, store: DiscordStore, private provisioner: Provisioner) {
     this.config = config;
     this.store = store;
@@ -55,6 +55,7 @@ export class DiscordBot {
       new MessageProcessorOpts(this.config.bridge.domain, this),
     );
     this.presenceHandler = new PresenceHandler(this);
+    this.discordMessageQueue = {};
   }
 
   public setBridge(bridge: Bridge) {
@@ -84,7 +85,7 @@ export class DiscordBot {
       return this.bridge.getIntentFromLocalpart(`_discord_${member.id}`);
   }
 
-  public run (): Promise<void> {
+  public run(): Promise<void> {
     return this.clientFactory.init().then(() => {
       return this.clientFactory.getClient();
     }).then((client: any) => {
@@ -103,11 +104,32 @@ export class DiscordBot {
       client.on("guildUpdate", (_, newGuild) => { this.channelSync.OnGuildUpdate(newGuild); });
       client.on("guildDelete", (guild) => { this.channelSync.OnGuildDelete(guild); });
 
-      client.on("messageDelete", (msg) => { this.DeleteDiscordMessage(msg); });
-      client.on("messageUpdate", (oldMessage, newMessage) => { this.OnMessageUpdate(oldMessage, newMessage); });
-      client.on("message", (msg) => { Bluebird.delay(MSG_PROCESS_DELAY).then(() => {
-          this.OnMessage(msg);
-        });
+      // Due to messages often arriving before we get a response from the send call,
+      // messages get delayed from discord. We use Bluebird.delay to handle this.
+
+      client.on("messageDelete", async (msg: Discord.Message) => {
+          // tslint:disable-next-line:await-promise
+          await Bluebird.delay(this.config.limits.discordSendDelay);
+          this.discordMessageQueue[msg.channel.id] = (async () => {
+              await (this.discordMessageQueue[msg.channel.id] || Promise.resolve());
+              await this.OnMessage(msg);
+          })();
+      });
+      client.on("messageUpdate", async (oldMessage: Discord.Message, newMessage: Discord.Message) => {
+          // tslint:disable-next-line:await-promise
+          await Bluebird.delay(this.config.limits.discordSendDelay);
+          this.discordMessageQueue[newMessage.channel.id] = (async () => {
+              await (this.discordMessageQueue[newMessage.channel.id] || Promise.resolve());
+              await this.OnMessageUpdate(oldMessage, newMessage);
+          })();
+      });
+      client.on("message", async (msg: Discord.Message) => {
+        // tslint:disable-next-line:await-promise
+        await Bluebird.delay(this.config.limits.discordSendDelay);
+        this.discordMessageQueue[msg.channel.id] = (async () => {
+            await (this.discordMessageQueue[msg.channel.id] || Promise.resolve());
+            await this.OnMessage(msg);
+        })();
       });
       const jsLog = new Log("discord.js");
 
@@ -173,12 +195,12 @@ export class DiscordBot {
     }
   }
 
-  public LookupRoom (server: string, room: string, sender?: string): Promise<ChannelLookupResult> {
+  public LookupRoom(server: string, room: string, sender?: string): Promise<ChannelLookupResult> {
     const hasSender = sender !== null;
     return this.clientFactory.getClient(sender).then((client) => {
       const guild = client.guilds.get(server);
       if (!guild) {
-        throw `Guild "${server}" not found`;
+        throw new Error(`Guild "${server}" not found`);
       }
       const channel = guild.channels.get(room);
       if (channel) {
@@ -187,7 +209,7 @@ export class DiscordBot {
         lookupResult.botUser = this.bot.user.id === client.user.id;
         return lookupResult;
       }
-      throw `Channel "${room}" not found`;
+      throw new Error(`Channel "${room}" not found`);
     }).catch((err) => {
       log.verbose("LookupRoom => ", err);
       if (hasSender) {
@@ -200,7 +222,7 @@ export class DiscordBot {
 
   public async ProcessMatrixStateEvent(event: any): Promise<void> {
       log.verbose(`Got state event from ${event.room_id} ${event.type}`);
-      const channel = <Discord.TextChannel> await this.GetChannelFromRoomId(event.room_id);
+      const channel = await this.GetChannelFromRoomId(event.room_id) as Discord.TextChannel;
       const msg = this.mxEventProcessor.StateEventToMessage(event, channel);
       if (!msg) {
           return;
@@ -327,7 +349,7 @@ export class DiscordBot {
     }
   }
 
-  public OnUserQuery (userId: string): any {
+  public OnUserQuery(userId: string): any {
     return false;
   }
 
@@ -435,7 +457,7 @@ export class DiscordBot {
 
   private async OnMessage(msg: Discord.Message) {
     const indexOfMsg = this.sentMessages.indexOf(msg.id);
-    const chan = <Discord.TextChannel> msg.channel;
+    const chan = msg.channel as Discord.TextChannel;
     if (indexOfMsg !== -1) {
       log.verbose("Got repeated message, ignoring.");
       delete this.sentMessages[indexOfMsg];
@@ -486,7 +508,7 @@ export class DiscordBot {
     }
 
     // Update presence because sometimes discord misses people.
-    this.userSync.OnUpdateUser(msg.author).then(() => {
+    return this.userSync.OnUpdateUser(msg.author).then(() => {
       return this.channelSync.GetRoomIdsFromChannel(msg.channel).catch((err) => {
         log.verbose("No bridged rooms to send message to. Oh well.");
         return null;
@@ -576,18 +598,18 @@ export class DiscordBot {
     }
   }
 
-    private async DeleteDiscordMessage(msg: Discord.Message) {
-        log.info(`Got delete event for ${msg.id}`);
-        const storeEvent = await this.store.Get(DbEvent, {discord_id: msg.id});
-        if (!storeEvent.Result) {
-          log.warn(`Could not redact because the event was not in the store.`);
-          return;
-        }
-        while (storeEvent.Next()) {
-          log.info(`Deleting discord msg ${storeEvent.DiscordId}`);
-          const intent = this.GetIntentFromDiscordMember(msg.author);
-          const matrixIds = storeEvent.MatrixId.split(";");
-          await intent.getClient().redactEvent(matrixIds[1], matrixIds[0]);
-        }
+  private async DeleteDiscordMessage(msg: Discord.Message) {
+    log.info(`Got delete event for ${msg.id}`);
+    const storeEvent = await this.store.Get(DbEvent, {discord_id: msg.id});
+    if (!storeEvent.Result) {
+      log.warn(`Could not redact because the event was not in the store.`);
+      return;
+    }
+    while (storeEvent.Next()) {
+      log.info(`Deleting discord msg ${storeEvent.DiscordId}`);
+      const intent = this.GetIntentFromDiscordMember(msg.author);
+      const matrixIds = storeEvent.MatrixId.split(";");
+      await intent.getClient().redactEvent(matrixIds[1], matrixIds[0]);
     }
+  }
 }
diff --git a/src/channelsyncroniser.ts b/src/channelsyncroniser.ts
index 6e1f9b30d4b8142a8fde44a0468350df49c0e9ec..84fa42a4b7756f76c2de452a20e742a8e40208a7 100644
--- a/src/channelsyncroniser.ts
+++ b/src/channelsyncroniser.ts
@@ -31,13 +31,13 @@ export interface ISingleChannelState {
     iconUrl: string; // nullable
     iconId: string; // nullable
     removeIcon: boolean;
-};
+}
 
 export interface IChannelState {
     id: string;
     mxChannels: ISingleChannelState[];
     iconMxcUrl: string; // nullable
-};
+}
 
 export class ChannelSyncroniser {
 
@@ -75,7 +75,7 @@ export class ChannelSyncroniser {
                 log.error("Failed to get channel state", e);
             }
         }
-        
+
         let iconMxcUrl = null;
         for (const channelState of channelStates) {
             channelState.iconMxcUrl = channelState.iconMxcUrl || iconMxcUrl;
@@ -103,7 +103,7 @@ export class ChannelSyncroniser {
             log.warn(`Couldn't find roomids for deleted channel ${channel.id}`);
             return;
         }
-        for (const roomid of roomids){
+        for (const roomid of roomids) {
             try {
                 await this.handleChannelDeletionForRoom(channel as Discord.TextChannel, roomid, entries[roomid][0]);
             } catch (e) {
@@ -139,13 +139,13 @@ export class ChannelSyncroniser {
             id: channel.id,
             mxChannels: [],
         });
-        
+
         const remoteRooms = await this.roomStore.getEntriesByRemoteRoomData({discord_channel: channel.id});
         if (remoteRooms.length === 0) {
             log.verbose(`Could not find any channels in room store.`);
             return channelState;
         }
-        
+
         const patternMap = {
             name: "#" + channel.name,
             guild: channel.guild.name,
@@ -165,19 +165,19 @@ export class ChannelSyncroniser {
             const singleChannelState = Object.assign({}, DEFAULT_SINGLECHANNEL_STATE, {
                 mxid,
             });
-            
+
             const oldName = remoteRoom.remote.get("discord_name");
             if (remoteRoom.remote.get("update_name") && (forceUpdate || oldName !== name)) {
                 log.verbose(`Channel ${mxid} name should be updated`);
                 singleChannelState.name = name;
             }
-            
+
             const oldTopic = remoteRoom.remote.get("discord_topic");
             if (remoteRoom.remote.get("update_topic") && (forceUpdate || oldTopic !== topic)) {
                 log.verbose(`Channel ${mxid} topic should be updated`);
                 singleChannelState.topic = topic;
             }
-            
+
             const oldIconUrl = remoteRoom.remote.get("discord_iconurl");
             // no force on icon update as we don't want to duplicate ALL the icons
             if (remoteRoom.remote.get("update_icon") && oldIconUrl !== iconUrl) {
@@ -211,14 +211,14 @@ export class ChannelSyncroniser {
                 remoteRoom.remote.set("discord_name", channelState.name);
                 roomUpdated = true;
             }
-            
+
             if (channelState.topic !== null) {
                 log.verbose(`Updating channeltopic for ${channelState.mxid} to "${channelState.topic}"`);
                 await intent.setRoomTopic(channelState.mxid, channelState.topic);
                 remoteRoom.remote.set("discord_topic", channelState.topic);
                 roomUpdated = true;
             }
-            
+
             if (channelState.iconUrl !== null) {
                 log.verbose(`Updating icon_url for ${channelState.mxid} to "${channelState.iconUrl}"`);
                 if (channelsState.iconMxcUrl === null) {
@@ -234,7 +234,7 @@ export class ChannelSyncroniser {
                 remoteRoom.remote.set("discord_iconurl_mxc", channelsState.iconMxcUrl);
                 roomUpdated = true;
             }
-            
+
             if (channelState.removeIcon) {
                 log.verbose(`Clearing icon_url for ${channelState.mxid}`);
                 await intent.setRoomAvatar(channelState.mxid, null);
@@ -242,7 +242,7 @@ export class ChannelSyncroniser {
                 remoteRoom.remote.set("discord_iconurl_mxc", null);
                 roomUpdated = true;
             }
-            
+
             if (roomUpdated) {
                 await this.roomStore.upsertEntry(remoteRoom);
             }
@@ -260,7 +260,7 @@ export class ChannelSyncroniser {
 
         this.roomStore.upsertEntry(entry);
         if (options.ghostsLeave) {
-            for (const member of channel.members.array()){
+            for (const member of channel.members.array()) {
                 try {
                     const mIntent = await this.bot.GetIntentFromDiscordMember(member);
                     mIntent.leave(roomId);
@@ -288,7 +288,7 @@ export class ChannelSyncroniser {
                 log.error(`Failed to set topic of room ${roomId} ${e}`);
             }
         }
-        
+
         if (plumbed !== true) {
             if (options.unsetRoomAlias) {
                 try {
diff --git a/src/config.ts b/src/config.ts
index c231adc639e3d24b11f221b49d7ce96886da6f4c..abba23fdc26b038de2e4ea309757ed0c2e35527e 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -77,6 +77,7 @@ class DiscordBridgeConfigChannelDeleteOptions {
 
 class DiscordBridgeConfigLimits {
   public roomGhostJoinDelay: number = 6000;
+  public discordSendDelay: number = 750;
 }
 
 export class LoggingFile {
diff --git a/src/db/postgres.ts b/src/db/postgres.ts
index b6655c49ec8c0406f4dfc24a3850e01c1c20476e..c5a7cde731ca22d27a28c7904fbbd6b71739fd25 100644
--- a/src/db/postgres.ts
+++ b/src/db/postgres.ts
@@ -16,7 +16,7 @@ export class Postgres implements IDatabaseConnector {
     }
 
     private db: IDatabase<any>;
-    constructor (private connectionString: string) {
+    constructor(private connectionString: string) {
 
     }
     public Open() {
diff --git a/src/db/sqlite3.ts b/src/db/sqlite3.ts
index 2d68ab176bd7bde36e0a99890688622577881bcb..47f5db5bd65a806fbc25faa5baed44136851962c 100644
--- a/src/db/sqlite3.ts
+++ b/src/db/sqlite3.ts
@@ -5,7 +5,7 @@ const log = new Log("SQLite3");
 
 export class SQLite3 implements IDatabaseConnector {
     private db: Database;
-    constructor (private filename: string) {
+    constructor(private filename: string) {
 
     }
 
diff --git a/src/discordas.ts b/src/discordas.ts
index 33b70b2b3404766b314538ebbad82e7693a0aa74..07a3b0042c3937a2f183a414dc16b64213233883 100644
--- a/src/discordas.ts
+++ b/src/discordas.ts
@@ -39,7 +39,7 @@ function generateRegistration(reg, callback)  {
   callback(reg);
 }
 
-function run (port: number, fileConfig: DiscordBridgeConfig) {
+function run(port: number, fileConfig: DiscordBridgeConfig) {
   const config = new DiscordBridgeConfig();
   config.ApplyConfig(fileConfig);
   Log.Configure(config.logging);
@@ -67,7 +67,9 @@ function run (port: number, fileConfig: DiscordBridgeConfig) {
     controller: {
       // onUserQuery: userQuery,
       onAliasQuery: roomhandler.OnAliasQuery.bind(roomhandler),
-      onEvent: roomhandler.OnEvent.bind(roomhandler),
+      onEvent: (request, context) =>
+          request.outcomeFrom(Promise.resolve(roomhandler.OnEvent(request, context)))
+      ,
       onAliasQueried: roomhandler.OnAliasQueried.bind(roomhandler),
       thirdPartyLookup: roomhandler.ThirdPartyLookup,
       onLog: (line, isError) => {
@@ -84,6 +86,11 @@ function run (port: number, fileConfig: DiscordBridgeConfig) {
     registration,
     userStore: config.database.userStorePath,
     roomStore: config.database.roomStorePath,
+    // To avoid out of order message sending.
+    queue: {
+      type: "per_room",
+      perRequest: true,
+    },
   });
   provisioner.SetBridge(bridge);
   roomhandler.setBridge(bridge);
diff --git a/src/log.ts b/src/log.ts
index 3e507a0f85b2e75fe962c35eeef01fa1ec6771b2..2b775da7e18e70212b8e4c48abbda2576c4d98f4 100644
--- a/src/log.ts
+++ b/src/log.ts
@@ -1,6 +1,6 @@
-import { createLogger, Logger, format, transports } from "winston";     
+import { createLogger, Logger, format, transports } from "winston";
 import { DiscordBridgeConfigLogging, LoggingFile} from "./config";
-import { inspect } from "util"; 
+import { inspect } from "util";
 import * as moment from "moment";
 import "winston-daily-rotate-file";
 
diff --git a/src/matrixeventprocessor.ts b/src/matrixeventprocessor.ts
index 93db39566c3f7a91b6f5039cd1c9fa65fb61330a..bfce1154dce66d63ac1861f10c7e293ae053ac96 100644
--- a/src/matrixeventprocessor.ts
+++ b/src/matrixeventprocessor.ts
@@ -36,7 +36,7 @@ export class MatrixEventProcessor {
     private bridge: any;
     private discord: DiscordBot;
 
-    constructor (opts: MatrixEventProcessorOpts) {
+    constructor(opts: MatrixEventProcessorOpts) {
         this.config = opts.config;
         this.bridge = opts.bridge;
         this.discord = opts.discord;
@@ -250,7 +250,7 @@ export class MatrixEventProcessor {
     private async SetEmbedAuthor(embed: Discord.RichEmbed, sender: string, profile?: any) {
         const intent = this.bridge.getIntent();
         let displayName = sender;
-        let avatarUrl = undefined;
+        let avatarUrl;
 
         // Are they a discord user.
         if (this.bridge.getBot().isRemoteUser(sender)) {
diff --git a/src/matrixroomhandler.ts b/src/matrixroomhandler.ts
index cd02b7049e7ceb027c5a588b5b0375152afecd26..bb63c0956b85814028dd1e91da4956fb9bec794a 100644
--- a/src/matrixroomhandler.ts
+++ b/src/matrixroomhandler.ts
@@ -41,7 +41,7 @@ export class MatrixRoomHandler {
   private bridge: Bridge;
   private discord: DiscordBot;
   private botUserId: string;
-  constructor (discord: DiscordBot, config: DiscordBridgeConfig, botUserId: string, private provisioner: Provisioner) {
+  constructor(discord: DiscordBot, config: DiscordBridgeConfig, botUserId: string, private provisioner: Provisioner) {
     this.discord = discord;
     this.config = config;
     this.botUserId = botUserId;
@@ -62,7 +62,7 @@ export class MatrixRoomHandler {
     this.bridge = bridge;
   }
 
-  public async OnAliasQueried (alias: string, roomId: string) {
+  public async OnAliasQueried(alias: string, roomId: string) {
     log.verbose("OnAliasQueried", `Got OnAliasQueried for ${alias} ${roomId}`);
     const channel = await this.discord.GetChannelFromRoomId(roomId) as Discord.GuildChannel;
 
@@ -78,7 +78,7 @@ export class MatrixRoomHandler {
     // Join a whole bunch of users.
     /* We delay the joins to give some implementations a chance to breathe */
     let delay = this.config.limits.roomGhostJoinDelay;
-    for (const member of (<Discord.TextChannel> channel).members.array()) {
+    for (const member of (channel as Discord.TextChannel).members.array()) {
         if (member.id === this.discord.GetBotId()) {
           continue;
         }
@@ -100,7 +100,7 @@ export class MatrixRoomHandler {
     await promiseChain;
   }
 
-  public OnEvent (request, context): Promise<any> {
+  public OnEvent(request, context): Promise<any> {
     const event = request.getData();
     if (event.unsigned.age > AGE_LIMIT) {
       log.warn(`Skipping event due to age ${event.unsigned.age} > ${AGE_LIMIT}`);
@@ -247,7 +247,7 @@ export class MatrixRoomHandler {
           const channelId = args[1];
           try {
               const discordResult = await this.discord.LookupRoom(guildId, channelId);
-              const channel = <Discord.TextChannel> discordResult.channel;
+              const channel = discordResult.channel as Discord.TextChannel;
 
               log.info(`Bridging matrix room ${event.room_id} to ${guildId}/${channelId}`);
               this.bridge.getIntent().sendMessage(event.room_id, {
@@ -321,7 +321,7 @@ export class MatrixRoomHandler {
       }
   }
 
-  public OnAliasQuery (alias: string, aliasLocalpart: string): Promise<any> {
+  public OnAliasQuery(alias: string, aliasLocalpart: string): Promise<any> {
     log.info("Got request for #", aliasLocalpart);
     const srvChanPair = aliasLocalpart.substr("_discord_".length).split("_", ROOM_NAME_PARTS);
     if (srvChanPair.length < ROOM_NAME_PARTS || srvChanPair[0] === "" || srvChanPair[1] === "") {
@@ -400,7 +400,7 @@ export class MatrixRoomHandler {
   }
 
   public async HandleDiscordCommand(msg: Discord.Message) {
-    if (!(<Discord.TextChannel> msg.channel).guild) {
+    if (!(msg.channel as Discord.TextChannel).guild) {
       msg.channel.send("**ERROR:** only available for guild channels");
     }
 
@@ -526,7 +526,7 @@ export class MatrixRoomHandler {
       return doJoin().catch(errorHandler);
   }
 
-  private createMatrixRoom (channel: Discord.TextChannel, alias: string) {
+  private createMatrixRoom(channel: Discord.TextChannel, alias: string) {
     const remote = new RemoteRoom(`discord_${channel.guild.id}_${channel.id}`);
     remote.set("discord_type", "text");
     remote.set("discord_guild", channel.guild.id);
diff --git a/src/messageprocessor.ts b/src/messageprocessor.ts
index eb35751615a4b0e13d03b54f24de783083c9ac13..32beb2f6b6a9b89fe26fc3ace80254e0685e0ccd 100644
--- a/src/messageprocessor.ts
+++ b/src/messageprocessor.ts
@@ -24,7 +24,7 @@ function _setupMarked() {
         sanitize: true,
         tables: false,
     });
-    
+
     const markedLexer = new marked.Lexer();
     // as discord doesn't support these markdown rules
     // we want to disable them by setting their regexes to non-matchable ones
@@ -34,7 +34,7 @@ function _setupMarked() {
     }
     // paragraph-end matching is different, as we don't have headers and thelike
     markedLexer.rules.paragraph = /^((?:[^\n]+\n\n)+)\n*/;
-    
+
     const markedInlineLexer = new marked.InlineLexer(true);
     // same again, remove tags discord doesn't support
     for (const r of ["tag", "link", "reflink", "nolink", "br"]) {
@@ -45,7 +45,7 @@ function _setupMarked() {
 }
 
 export class MessageProcessorOpts {
-    constructor (readonly domain: string, readonly bot: DiscordBot = null) {
+    constructor(readonly domain: string, readonly bot: DiscordBot = null) {
 
     }
 }
@@ -57,7 +57,7 @@ export class MessageProcessorMatrixResult {
 
 export class MessageProcessor {
     private readonly opts: MessageProcessorOpts;
-    constructor (opts: MessageProcessorOpts, bot: DiscordBot = null) {
+    constructor(opts: MessageProcessorOpts, bot: DiscordBot = null) {
         // Backwards compat
         if (bot != null) {
             this.opts = new MessageProcessorOpts(opts.domain, bot);
@@ -70,23 +70,23 @@ export class MessageProcessor {
         const result = new MessageProcessorMatrixResult();
 
         let content = msg.content;
-        
+
         // for the formatted body we need to parse markdown first
         // as else it'll HTML escape the result of the discord syntax
         let contentPostmark = marked(content).replace(/\n/g, "<br>").replace(/(<br>)?<\/p>(<br>)?/g, "</p>");
-        
+
         // parse the plain text stuff
         content = this.InsertEmbeds(content, msg);
         content = this.ReplaceMembers(content, msg);
         content = this.ReplaceChannels(content, msg);
         content = await this.ReplaceEmoji(content, msg);
-        
+
         // parse postmark stuff
         contentPostmark = this.InsertEmbedsPostmark(contentPostmark, msg);
         contentPostmark = this.ReplaceMembersPostmark(contentPostmark, msg);
         contentPostmark = this.ReplaceChannelsPostmark(contentPostmark, msg);
         contentPostmark = await this.ReplaceEmojiPostmark(contentPostmark, msg);
-        
+
         result.body = content;
         result.formattedBody = contentPostmark;
         return result;
diff --git a/src/presencehandler.ts b/src/presencehandler.ts
index 76ab6bacd2dd788ecce7afcb500aac7169ca2298..88a6cc8ac74f206e263b327a43a75f8428fa551e 100644
--- a/src/presencehandler.ts
+++ b/src/presencehandler.ts
@@ -14,12 +14,12 @@ export class PresenceHandler {
     private readonly bot: DiscordBot;
     private presenceQueue: User[];
     private interval: number;
-    constructor (bot: DiscordBot) {
+    constructor(bot: DiscordBot) {
         this.bot = bot;
         this.presenceQueue = [];
     }
 
-    get QueueCount (): number {
+    get QueueCount(): number {
         return this.presenceQueue.length;
     }
 
diff --git a/src/store.ts b/src/store.ts
index 562f52a74ae55a20060cd23e04c203ac4703c617..56769f9b5455b2370cd210ae25a70c7012423b94 100644
--- a/src/store.ts
+++ b/src/store.ts
@@ -19,7 +19,7 @@ export class DiscordStore {
   public db: IDatabaseConnector;
   private version: number;
   private config: DiscordBridgeConfigDatabase;
-  constructor (private configOrFile: DiscordBridgeConfigDatabase|string) {
+  constructor(private configOrFile: DiscordBridgeConfigDatabase|string) {
     if (typeof(configOrFile) === "string") {
         this.config = new DiscordBridgeConfigDatabase();
         this.config.filename = configOrFile;
@@ -64,7 +64,7 @@ export class DiscordStore {
   /**
    * Checks the database has all the tables needed.
    */
-  public async init (overrideSchema: number = 0): Promise<void> {
+  public async init(overrideSchema: number = 0): Promise<void> {
     log.info("Starting DB Init");
     await this.open_database();
     let version = await this.getSchemaVersion();
@@ -95,11 +95,11 @@ export class DiscordStore {
     log.info("Updated database to the latest schema");
   }
 
-  public close () {
+  public close() {
     this.db.Close();
   }
 
-  public create_table (statement: string, tablename: string): Promise<void|Error> {
+  public create_table(statement: string, tablename: string): Promise<void|Error> {
     return this.db.Exec(statement).then(() => {
       log.info("Created table", tablename);
     }).catch((err) => {
@@ -266,7 +266,7 @@ export class DiscordStore {
       return data.Delete(this);
   }
 
-  private async getSchemaVersion ( ): Promise<number> {
+  private async getSchemaVersion( ): Promise<number> {
     log.silly("_get_schema_version");
     let version = 0;
     try {
@@ -277,7 +277,7 @@ export class DiscordStore {
     return version;
   }
 
-  private setSchemaVersion (ver: number): Promise<any> {
+  private setSchemaVersion(ver: number): Promise<any> {
     log.silly("_set_schema_version => ", ver);
     return this.db.Run(
       `
diff --git a/src/usersyncroniser.ts b/src/usersyncroniser.ts
index 81605f0390080c53641d67f11cfffdde5068496b..d91101abedfd800ba9824b2f75d7acb9169dd5b4 100644
--- a/src/usersyncroniser.ts
+++ b/src/usersyncroniser.ts
@@ -33,13 +33,13 @@ export interface IUserState {
     avatarUrl: string; // Nullable
     avatarId: string;
     removeAvatar: boolean; // If the avatar has been removed from the user.
-};
+}
 
 export interface IGuildMemberRole {
     name: string;
     color: number;
     position: number;
-};
+}
 
 export interface IGuildMemberState {
     id: string;
diff --git a/src/util.ts b/src/util.ts
index 6346ffe5c140b625fff72acb24f751b95f57c6ae..85575f4826212123345483c6fa69d72360cb7d7e 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -15,20 +15,20 @@ export interface ICommandAction {
   description?: string;
   permission?: string;
   run(params: any): Promise<any>;
-};
+}
 
 export interface ICommandActions {
   [index: string]: ICommandAction;
-};
+}
 
 export interface ICommandParameter {
   description?: string;
   get(param: string): Promise<any>;
-};
+}
 
 export interface ICommandParameters {
   [index: string]: ICommandParameter;
-};
+}
 
 export class Util {
 
@@ -36,7 +36,7 @@ export class Util {
    * downloadFile - This function will take a URL and store the resulting data into
    * a buffer.
    */
-  public static DownloadFile (url: string): Promise<Buffer> {
+  public static DownloadFile(url: string): Promise<Buffer> {
     return new Promise((resolve, reject) => {
       let ht;
       if (url.startsWith("https")) {
@@ -67,7 +67,7 @@ export class Util {
    * uploadContentFromUrl - Upload content from a given URL to the homeserver
    * and return a MXC URL.
    */
-  public static UploadContentFromUrl (url: string, intent: Intent, name: string): Promise<IUploadResult> {
+  public static UploadContentFromUrl(url: string, intent: Intent, name: string): Promise<IUploadResult> {
     let contenttype;
     let size;
     name = name || null;
diff --git a/test/mocks/channel.ts b/test/mocks/channel.ts
index 08a0922980a95674f5635945f11d24042e5faa25..0ce4a288e139a5c32abe5b01e7187885149c6b3c 100644
--- a/test/mocks/channel.ts
+++ b/test/mocks/channel.ts
@@ -4,7 +4,7 @@ import {MockCollection} from "./collection";
 // Mocking TextChannel
 export class MockChannel {
     public members = new MockCollection<string, MockMember>();
-    constructor (
+    constructor(
         public id: string = "",
         public guild: any = null,
         public type: string = "text",
diff --git a/test/mocks/discordclient.ts b/test/mocks/discordclient.ts
index d431ebf1dd0b0a768d691aeeac08560148ef8a24..20da7ba2e72ef8d2dcbb5b801e2b5acfcce10b44 100644
--- a/test/mocks/discordclient.ts
+++ b/test/mocks/discordclient.ts
@@ -1,12 +1,13 @@
 import {MockCollection} from "./collection";
 import {MockGuild} from "./guild";
 import {MockUser} from "./user";
+import { EventEmitter } from "events";
 
 export class MockDiscordClient {
   public guilds = new MockCollection<string, MockGuild>();
   public user: MockUser;
   private testLoggedIn: boolean = false;
-  private testCallbacks: Map<string, () => void> = new Map();
+  private testCallbacks: Map<string, (...data: any[]) => void> = new Map();
 
   constructor() {
     const channels = [
@@ -30,10 +31,14 @@ export class MockDiscordClient {
     this.user = new MockUser("12345");
   }
 
-  public on(event: string, callback: () => void) {
+  public on(event: string, callback: (...data: any[]) => void) {
       this.testCallbacks.set(event, callback);
   }
 
+  public emit(event: string, ...data: any[]) {
+      return this.testCallbacks.get(event).apply(this, data);
+  }
+
   public async login(token: string): Promise<void> {
     if (token !== "passme") {
         throw new Error("Mock Discord Client only logins with the token 'passme'");
diff --git a/test/mocks/discordclientfactory.ts b/test/mocks/discordclientfactory.ts
index 99bb5b2e47e6fd4ffc5becc86a9e5f1a6082cff6..489adba780b375bbdae808026258095a0a089ef0 100644
--- a/test/mocks/discordclientfactory.ts
+++ b/test/mocks/discordclientfactory.ts
@@ -1,8 +1,9 @@
 import {MockDiscordClient} from "./discordclient";
 
 export class DiscordClientFactory {
+  private botClient: MockDiscordClient = null;
   constructor(config: any, store: any) {
-    ;
+    
   }
 
   public init(): Promise<void> {
@@ -10,6 +11,9 @@ export class DiscordClientFactory {
   }
 
   public getClient(userId?: string): Promise<MockDiscordClient> {
-    return Promise.resolve(new MockDiscordClient());
+    if (userId == null && !this.botClient) {
+        this.botClient = new MockDiscordClient();
+    }
+    return Promise.resolve(this.botClient);
   }
 }
diff --git a/test/mocks/emoji.ts b/test/mocks/emoji.ts
index 06c65350b86cd05a35754a25244c8382cc705970..c02734bdcce767512d9b2df8d2bb77b2830efd48 100644
--- a/test/mocks/emoji.ts
+++ b/test/mocks/emoji.ts
@@ -1,3 +1,3 @@
 export class MockEmoji {
-  constructor (public id: string = "", public name = "") { }
+  constructor(public id: string = "", public name = "") { }
 }
diff --git a/test/test_channelsyncroniser.ts b/test/test_channelsyncroniser.ts
index bc583596afbb03629ea940f61ab894afcf65c5b5..01b7aabcd1c83e48f4355e8a3056c9f553e4c4b4 100644
--- a/test/test_channelsyncroniser.ts
+++ b/test/test_channelsyncroniser.ts
@@ -148,7 +148,7 @@ function CreateChannelSync(remoteChannels: any[] = []): ChannelSyncroniser {
         },
     };
     const discordbot: any = {
-        
+
     };
     const config = new DiscordBridgeConfig();
     config.bridge.domain = "localhost";
@@ -172,9 +172,9 @@ describe("ChannelSyncroniser", () => {
                     },
                 }),
             ];
-            
+
             const channelSync = CreateChannelSync(testStore);
-            return channelSync.OnDelete(<any> chan).then(() => {
+            return channelSync.OnDelete(chan as any).then(() => {
                 expect(REMOTECHANNEL_REMOVED).is.false;
             });
         });
@@ -192,9 +192,9 @@ describe("ChannelSyncroniser", () => {
                     },
                 }),
             ];
-            
+
             const channelSync = CreateChannelSync(testStore);
-            return channelSync.OnDelete(<any> chan).then(() => {
+            return channelSync.OnDelete(chan as any).then(() => {
                 expect(REMOTECHANNEL_REMOVED).is.true;
             });
         });
@@ -213,9 +213,9 @@ describe("ChannelSyncroniser", () => {
                     },
                 }),
             ];
-            
+
             const channelSync = CreateChannelSync(testStore);
-            return channelSync.GetRoomIdsFromChannel(<any> chan).then((chans) => {
+            return channelSync.GetRoomIdsFromChannel(chan as any).then((chans) => {
                 expect(chans.length).equals(1);
                 expect(chans[0]).equals("!1:localhost");
             });
@@ -249,9 +249,9 @@ describe("ChannelSyncroniser", () => {
                     },
                 }),
             ];
-            
+
             const channelSync = CreateChannelSync(testStore);
-            return channelSync.GetRoomIdsFromChannel(<any> chan).then((chans) => {
+            return channelSync.GetRoomIdsFromChannel(chan as any).then((chans) => {
                 /* tslint:disable:no-magic-numbers */
                 expect(chans.length).equals(2);
                 /* tslint:enable:no-magic-numbers */
@@ -263,7 +263,7 @@ describe("ChannelSyncroniser", () => {
             const chan = new MockChannel();
             chan.id = "blah";
             const channelSync = CreateChannelSync();
-            expect(channelSync.GetRoomIdsFromChannel(<any> chan)).to.eventually.be.rejected;
+            expect(channelSync.GetRoomIdsFromChannel(chan as any)).to.eventually.be.rejected;
         });
     });
     describe("GetChannelUpdateState", () => {
@@ -271,9 +271,9 @@ describe("ChannelSyncroniser", () => {
             const chan = new MockChannel();
             chan.type = "text";
             chan.id = "blah";
-            
+
             const channelSync = CreateChannelSync();
-            return channelSync.GetChannelUpdateState(<any> chan).then((state) => {
+            return channelSync.GetChannelUpdateState(chan as any).then((state) => {
                 expect(state.id).equals(chan.id);
                 expect(state.mxChannels.length).equals(0);
             });
@@ -286,7 +286,7 @@ describe("ChannelSyncroniser", () => {
             chan.name = "newName";
             chan.topic = "newTopic";
             chan.guild = guild;
-            
+
             const testStore = [
                 new Entry({
                     id: "1",
@@ -301,9 +301,9 @@ describe("ChannelSyncroniser", () => {
                     },
                 }),
             ];
-            
+
             const channelSync = CreateChannelSync(testStore);
-            return channelSync.GetChannelUpdateState(<any> chan).then((state) => {
+            return channelSync.GetChannelUpdateState(chan as any).then((state) => {
                 expect(state.mxChannels.length).equals(1);
                 expect(state.mxChannels[0].name).equals("[Discord] newGuild #newName");
                 expect(state.mxChannels[0].topic).equals("newTopic");
@@ -317,7 +317,7 @@ describe("ChannelSyncroniser", () => {
             chan.name = "newName";
             chan.topic = "newTopic";
             chan.guild = guild;
-            
+
             const testStore = [
                 new Entry({
                     id: "1",
@@ -330,9 +330,9 @@ describe("ChannelSyncroniser", () => {
                     },
                 }),
             ];
-            
+
             const channelSync = CreateChannelSync(testStore);
-            return channelSync.GetChannelUpdateState(<any> chan).then((state) => {
+            return channelSync.GetChannelUpdateState(chan as any).then((state) => {
                 expect(state.mxChannels.length).equals(1);
                 expect(state.mxChannels[0].name).is.null;
                 expect(state.mxChannels[0].topic).is.null;
@@ -346,7 +346,7 @@ describe("ChannelSyncroniser", () => {
             chan.name = "newName";
             chan.topic = "newTopic";
             chan.guild = guild;
-            
+
             const testStore = [
                 new Entry({
                     id: "1",
@@ -361,9 +361,9 @@ describe("ChannelSyncroniser", () => {
                     },
                 }),
             ];
-            
+
             const channelSync = CreateChannelSync(testStore);
-            return channelSync.GetChannelUpdateState(<any> chan).then((state) => {
+            return channelSync.GetChannelUpdateState(chan as any).then((state) => {
                 expect(state.mxChannels.length).equals(1);
                 expect(state.mxChannels[0].name).is.null;
                 expect(state.mxChannels[0].topic).is.null;
@@ -376,7 +376,7 @@ describe("ChannelSyncroniser", () => {
             chan.type = "text";
             chan.id = "blah";
             chan.guild = guild;
-            
+
             const testStore = [
                 new Entry({
                     id: "1",
@@ -389,9 +389,9 @@ describe("ChannelSyncroniser", () => {
                     },
                 }),
             ];
-            
+
             const channelSync = CreateChannelSync(testStore);
-            return channelSync.GetChannelUpdateState(<any> chan).then((state) => {
+            return channelSync.GetChannelUpdateState(chan as any).then((state) => {
                 expect(state.mxChannels.length).equals(1);
                 expect(state.mxChannels[0].iconUrl).equals("https://cdn.discordapp.com/icons/654321/new_icon.png");
                 expect(state.mxChannels[0].iconId).equals("new_icon");
@@ -404,7 +404,7 @@ describe("ChannelSyncroniser", () => {
             chan.type = "text";
             chan.id = "blah";
             chan.guild = guild;
-            
+
             const testStore = [
                 new Entry({
                     id: "1",
@@ -417,9 +417,9 @@ describe("ChannelSyncroniser", () => {
                     },
                 }),
             ];
-            
+
             const channelSync = CreateChannelSync(testStore);
-            return channelSync.GetChannelUpdateState(<any> chan).then((state) => {
+            return channelSync.GetChannelUpdateState(chan as any).then((state) => {
                 expect(state.mxChannels.length).equals(1);
                 expect(state.mxChannels[0].iconUrl).is.null;
                 expect(state.mxChannels[0].iconId).is.null;
@@ -432,7 +432,7 @@ describe("ChannelSyncroniser", () => {
             chan.type = "text";
             chan.id = "blah";
             chan.guild = guild;
-            
+
             const testStore = [
                 new Entry({
                     id: "1",
@@ -445,9 +445,9 @@ describe("ChannelSyncroniser", () => {
                     },
                 }),
             ];
-            
+
             const channelSync = CreateChannelSync(testStore);
-            return channelSync.GetChannelUpdateState(<any> chan).then((state) => {
+            return channelSync.GetChannelUpdateState(chan as any).then((state) => {
                 expect(state.mxChannels.length).equals(1);
                 expect(state.mxChannels[0].removeIcon).is.true;
             });
@@ -463,7 +463,7 @@ describe("ChannelSyncroniser", () => {
             chan.name = "newName";
             chan.topic = "newTopic";
             chan.guild = guild;
-            
+
             const testStore = [
                 new Entry({
                     id: "1",
@@ -480,9 +480,9 @@ describe("ChannelSyncroniser", () => {
                     },
                 }),
             ];
-            
+
             const channelSync = CreateChannelSync(testStore);
-            return channelSync.OnUpdate(<any> chan).then((state) => {
+            return channelSync.OnUpdate(chan as any).then((state) => {
                 expect(ROOM_NAME_SET).equals("[Discord] newGuild #newName");
                 expect(ROOM_TOPIC_SET).equals("newTopic");
                 expect(ROOM_AVATAR_SET).equals("avatarset");
diff --git a/test/test_discordbot.ts b/test/test_discordbot.ts
index 1233fb299e4437b5b30d6de931c14851c4bf703a..a350b1784949c320af1cdf1fa9c093b155ca23ae 100644
--- a/test/test_discordbot.ts
+++ b/test/test_discordbot.ts
@@ -7,6 +7,8 @@ import { Log } from "../src/log";
 import { MessageProcessorMatrixResult } from "../src/messageprocessor";
 import { MockGuild } from "./mocks/guild";
 import { MockMember } from "./mocks/member";
+import { DiscordBot } from "../src/bot";
+import { MockDiscordClient } from "./mocks/discordclient";
 
 Chai.use(ChaiAsPromised);
 
@@ -52,6 +54,9 @@ describe("DiscordBot", () => {
     bridge: {
         domain: "localhost",
     },
+    limits: {
+        discordSendDelay: 50,
+    },
   };
   describe("run()", () => {
     it("should resolve when ready.", () => {
@@ -140,6 +145,30 @@ describe("DiscordBot", () => {
       });
     });
   });
+  describe("event:message", () => {
+    it("should delay messages so they arrive in order", async () => {
+        discordBot = new modDiscordBot.DiscordBot(
+          config,
+          mockBridge,
+      );
+        let expected = 0;
+        discordBot.OnMessage = (msg: any) => {
+          assert.equal(msg.n, expected);
+          expected++;
+          return Promise.resolve();
+      };
+        const client: MockDiscordClient = (await discordBot.ClientFactory.getClient()) as MockDiscordClient;
+        discordBot.setBridge(mockBridge);
+        await discordBot.run();
+        const ITERATIONS = 25;
+        const CHANID = 123;
+        // Send delay of 50ms, 2 seconds / 50ms - 5 for safety.
+        for (let i = 0; i < ITERATIONS; i++) {
+          client.emit("message", { n: i, channel: { id: CHANID} });
+      }
+        await discordBot.discordMessageQueue[CHANID];
+    });
+  });
 
   // describe("ProcessMatrixMsgEvent()", () => {
   //
diff --git a/test/test_matrixeventprocessor.ts b/test/test_matrixeventprocessor.ts
index e70d16950bdd7e4c710576ee279c97b1b6eade71..beb033672d8afc01c5ed81dfeeee336110f7201e 100644
--- a/test/test_matrixeventprocessor.ts
+++ b/test/test_matrixeventprocessor.ts
@@ -36,7 +36,7 @@ const mxClient = {
 };
 
 function createMatrixEventProcessor
-    (disableMentions: boolean = false, disableEveryone = false, disableHere = false): MatrixEventProcessor {
+   (disableMentions: boolean = false, disableEveryone = false, disableHere = false): MatrixEventProcessor {
     const bridge = {
         getClientFactory: () => {
             return {
diff --git a/test/test_messageprocessor.ts b/test/test_messageprocessor.ts
index 4d3bd3d615245c4d8fc8aa5e3560919711f24ba2..ccdb5bbfe14eb6366db53140c01b78563db5cb57 100644
--- a/test/test_messageprocessor.ts
+++ b/test/test_messageprocessor.ts
@@ -21,12 +21,12 @@ const bot = {
 describe("MessageProcessor", () => {
     describe("init", () => {
         it("constructor", () => {
-            const mp = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const mp = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
         });
     });
     describe("FormatDiscordMessage", () => {
       it("processes plain text messages correctly", async () => {
-        const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+        const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
         const msg = new Discord.Message(null, null, null);
         msg.embeds = [];
         msg.content = "Hello World!";
@@ -35,7 +35,7 @@ describe("MessageProcessor", () => {
         Chai.assert(result.formattedBody, "Hello World!");
       });
       it("processes markdown messages correctly.", async () => {
-        const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+        const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
         const msg = new Discord.Message(null, null, null);
         msg.embeds = [];
         msg.content = "Hello *World*!";
@@ -43,8 +43,8 @@ describe("MessageProcessor", () => {
         Chai.assert.equal(result.body, "Hello *World*!");
         Chai.assert.equal(result.formattedBody, "<p>Hello <em>World</em>!</p>");
       });
-      it("processes non-discord markdown correctly.", async() => {
-        const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+      it("processes non-discord markdown correctly.", async () => {
+        const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
         const msg = new Discord.Message(null, null, null);
         msg.embeds = [];
         msg.content = "> inb4 tests";
@@ -58,8 +58,8 @@ describe("MessageProcessor", () => {
         Chai.assert.equal(result.body, "[test](http://example.com)");
         Chai.assert.equal(result.formattedBody, "<p>[test](<a href=\"http://example.com\">http://example.com</a>)</p>");
       });
-      it("processes discord-specific markdown correctly.", async() => {
-        const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+      it("processes discord-specific markdown correctly.", async () => {
+        const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
         const msg = new Discord.Message(null, null, null);
         msg.embeds = [];
         msg.content = "_ italic _";
@@ -70,7 +70,7 @@ describe("MessageProcessor", () => {
     });
     describe("FormatEmbeds", () => {
       it("should format embeds correctly", async () => {
-        const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+        const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
         const msg = new Discord.Message(null, null, null);
         msg.embeds = [
             {
@@ -102,12 +102,12 @@ describe("MessageProcessor", () => {
     });
     describe("FormatEdit", () => {
       it("should format basic edits appropriately", async () => {
-        const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+        const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
         const oldMsg = new Discord.Message(null, null, null);
         const newMsg = new Discord.Message(null, null, null);
         oldMsg.embeds = [];
         newMsg.embeds = [];
-       
+
         // Content updated but not changed
         oldMsg.content = "a";
         newMsg.content = "b";
@@ -118,12 +118,12 @@ describe("MessageProcessor", () => {
       });
 
       it("should format markdown heavy edits apropriately", async () => {
-        const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+        const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
         const oldMsg = new Discord.Message(null, null, null);
         const newMsg = new Discord.Message(null, null, null);
         oldMsg.embeds = [];
         newMsg.embeds = [];
-       
+
         // Content updated but not changed
         oldMsg.content = "a slice of **cake**";
         newMsg.content = "*a* slice of cake";
@@ -135,10 +135,10 @@ describe("MessageProcessor", () => {
       });
 
     });
-        
+
     describe("ReplaceMembers", () => {
         it("processes members missing from the guild correctly", () => {
-            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
             const guild: any = new MockGuild("123", []);
             const channel = new Discord.TextChannel(guild, null);
             const msg = new Discord.Message(channel, null, null);
@@ -147,7 +147,7 @@ describe("MessageProcessor", () => {
             Chai.assert.equal(content, "Hello @_discord_12345:localhost");
         });
         it("processes members with usernames correctly", () => {
-            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
             const guild: any = new MockGuild("123", []);
             guild._mockAddMember(new MockMember("12345", "TestUsername"));
             const channel = new Discord.TextChannel(guild, null);
@@ -157,7 +157,7 @@ describe("MessageProcessor", () => {
             Chai.assert.equal(content, "Hello TestUsername");
         });
         it("processes members with nickname correctly", () => {
-            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
             const guild: any = new MockGuild("123", []);
             guild._mockAddMember(new MockMember("12345", "TestUsername", null, "TestNickname"));
             const channel = new Discord.TextChannel(guild, null);
@@ -169,7 +169,7 @@ describe("MessageProcessor", () => {
     });
     describe("ReplaceMembersPostmark", () => {
         it("processes members missing from the guild correctly", () => {
-            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
             const guild: any = new MockGuild("123", []);
             const channel = new Discord.TextChannel(guild, null);
             const msg = new Discord.Message(channel, null, null);
@@ -179,7 +179,7 @@ describe("MessageProcessor", () => {
                 "Hello <a href=\"https://matrix.to/#/@_discord_12345:localhost\">@_discord_12345:localhost</a>");
         });
         it("processes members with usernames correctly", () => {
-            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
             const guild: any = new MockGuild("123", []);
             guild._mockAddMember(new MockMember("12345", "TestUsername"));
             const channel = new Discord.TextChannel(guild, null);
@@ -192,7 +192,7 @@ describe("MessageProcessor", () => {
     });
     describe("ReplaceChannels", () => {
         it("processes unknown channel correctly", () => {
-            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
             const guild: any = new MockGuild("123", []);
             const channel = new Discord.TextChannel(guild, {id: "456", name: "TestChannel"});
             const msg = new Discord.Message(channel, null, null);
@@ -201,7 +201,7 @@ describe("MessageProcessor", () => {
             Chai.assert.equal(content, "Hello #123456789");
         });
         it("processes channels correctly", () => {
-            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
             const guild: any = new MockGuild("123", []);
             const channel = new Discord.TextChannel(guild, {id: "456", name: "TestChannel"});
             guild.channels.set("456", channel);
@@ -213,7 +213,7 @@ describe("MessageProcessor", () => {
     });
     describe("ReplaceChannelsPostmark", () => {
         it("processes unknown channel correctly", () => {
-            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
             const guild: any = new MockGuild("123", []);
             const channel = new Discord.TextChannel(guild, {id: "456", name: "TestChannel"});
             const msg = new Discord.Message(channel, null, null);
@@ -223,7 +223,7 @@ describe("MessageProcessor", () => {
                 "Hello <a href=\"https://matrix.to/#/#_discord_123_123456789:localhost\">#123456789</a>");
         });
         it("processes channels correctly", () => {
-            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
             const guild: any = new MockGuild("123", []);
             const channel = new Discord.TextChannel(guild, {id: "456", name: "TestChannel"});
             guild.channels.set("456", channel);
@@ -236,7 +236,7 @@ describe("MessageProcessor", () => {
     });
     describe("ReplaceEmoji", () => {
         it("processes unknown emoji correctly", async () => {
-            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
             const guild: any = new MockGuild("123", []);
             const channel = new Discord.TextChannel(guild, {id: "456", name: "TestChannel"});
             const msg = new Discord.Message(channel, null, null);
@@ -245,7 +245,7 @@ describe("MessageProcessor", () => {
             Chai.assert.equal(content, "Hello <:hello:123456789>");
         });
         it("processes emoji correctly", async () => {
-            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
             const guild: any = new MockGuild("123", []);
             const channel = new Discord.TextChannel(guild, {id: "456", name: "TestChannel"});
             guild.channels.set("456", channel);
@@ -257,7 +257,7 @@ describe("MessageProcessor", () => {
     });
     describe("ReplaceEmojiPostmark", () => {
         it("processes unknown emoji correctly", async () => {
-            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
             const guild: any = new MockGuild("123", []);
             const channel = new Discord.TextChannel(guild, {id: "456", name: "TestChannel"});
             const msg = new Discord.Message(channel, null, null);
@@ -266,7 +266,7 @@ describe("MessageProcessor", () => {
             Chai.assert.equal(content, "Hello &lt;:hello:123456789&gt;");
         });
         it("processes emoji correctly", async () => {
-            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
             const guild: any = new MockGuild("123", []);
             const channel = new Discord.TextChannel(guild, {id: "456", name: "TestChannel"});
             guild.channels.set("456", channel);
@@ -278,7 +278,7 @@ describe("MessageProcessor", () => {
     });
     describe("InsertEmbeds", () => {
         it("processes titleless embeds properly", () => {
-            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
             const msg = new Discord.Message(null, null, null);
             msg.embeds = [
                 new Discord.MessageEmbed(msg, {
@@ -290,7 +290,7 @@ describe("MessageProcessor", () => {
             Chai.assert.equal(content, "\n\n----\nTestDescription");
         });
         it("processes urlless embeds properly", () => {
-            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
             const msg = new Discord.Message(null, null, null);
             msg.embeds = [
                 new Discord.MessageEmbed(msg, {
@@ -303,7 +303,7 @@ describe("MessageProcessor", () => {
             Chai.assert.equal(content, "\n\n----\n##### TestTitle\nTestDescription");
         });
         it("processes linked embeds properly", () => {
-            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
             const msg = new Discord.Message(null, null, null);
             msg.embeds = [
                 new Discord.MessageEmbed(msg, {
@@ -317,7 +317,7 @@ describe("MessageProcessor", () => {
             Chai.assert.equal(content, "\n\n----\n##### [TestTitle](testurl)\nTestDescription");
         });
         it("rejects titleless and descriptionless embeds", () => {
-            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
             const msg = new Discord.Message(null, null, null);
             msg.embeds = [
                 new Discord.MessageEmbed(msg, {
@@ -329,7 +329,7 @@ describe("MessageProcessor", () => {
             Chai.assert.equal(content, "Some content...");
         });
         it("processes multiple embeds properly", () => {
-            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
             const msg = new Discord.Message(null, null, null);
             msg.embeds = [
                 new Discord.MessageEmbed(msg, {
@@ -351,7 +351,7 @@ describe("MessageProcessor", () => {
             );
         });
         it("inserts embeds properly", () => {
-            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), <DiscordBot> bot);
+            const processor = new MessageProcessor(new MessageProcessorOpts("localhost"), bot as DiscordBot);
             const msg = new Discord.Message(null, null, null);
             msg.embeds = [
                 new Discord.MessageEmbed(msg, {
diff --git a/test/test_presencehandler.ts b/test/test_presencehandler.ts
index d36335dbefd98b0180b61668cbd0855751fcfddb..c6c652cbcacde39c0d275d73c84d4600eb9f804c 100644
--- a/test/test_presencehandler.ts
+++ b/test/test_presencehandler.ts
@@ -33,49 +33,49 @@ const bot = {
 describe("PresenceHandler", () => {
     describe("init", () => {
         it("constructor", () => {
-            const handler = new PresenceHandler(<DiscordBot> bot);
+            const handler = new PresenceHandler(bot as DiscordBot);
         });
     });
     describe("Start", () => {
         it("should start without errors", () => {
-            const handler = new PresenceHandler(<DiscordBot> bot);
+            const handler = new PresenceHandler(bot as DiscordBot);
             handler.Start(INTERVAL);
         });
     });
     describe("Stop", () => {
         it("should stop without errors", () => {
-            const handler = new PresenceHandler(<DiscordBot> bot);
+            const handler = new PresenceHandler(bot as DiscordBot);
             handler.Start(INTERVAL);
             handler.Stop();
         });
     });
     describe("EnqueueUser", () => {
         it("adds a user properly", () => {
-            const handler = new PresenceHandler(<DiscordBot> bot);
+            const handler = new PresenceHandler(bot as DiscordBot);
             const COUNT = 2;
-            handler.EnqueueUser(<any> new MockUser("abc", "def"));
-            handler.EnqueueUser(<any> new MockUser("123", "ghi"));
+            handler.EnqueueUser(new MockUser("abc", "def") as any);
+            handler.EnqueueUser(new MockUser("123", "ghi") as any);
             Chai.assert.equal(handler.QueueCount, COUNT);
         });
         it("does not add duplicate users", () => {
-            const handler = new PresenceHandler(<DiscordBot> bot);
-            handler.EnqueueUser(<any> new MockUser("abc", "def"));
-            handler.EnqueueUser(<any> new MockUser("abc", "def"));
+            const handler = new PresenceHandler(bot as DiscordBot);
+            handler.EnqueueUser(new MockUser("abc", "def") as any);
+            handler.EnqueueUser(new MockUser("abc", "def") as any);
             Chai.assert.equal(handler.QueueCount, 1);
         });
         it("does not add the bot user", () => {
-            const handler = new PresenceHandler(<DiscordBot> bot);
-            handler.EnqueueUser(<any> new MockUser("1234", "def"));
+            const handler = new PresenceHandler(bot as DiscordBot);
+            handler.EnqueueUser(new MockUser("1234", "def") as any);
             Chai.assert.equal(handler.QueueCount, 0);
         });
     });
     describe("DequeueUser", () => {
         it("removes users properly", () => {
-            const handler = new PresenceHandler(<DiscordBot> bot);
+            const handler = new PresenceHandler(bot as DiscordBot);
             const members = [
-                <any> new MockUser("abc", "def"),
-                <any> new MockUser("def", "ghi"),
-                <any> new MockUser("ghi", "wew"),
+                new MockUser("abc", "def") as any,
+                new MockUser("def", "ghi") as any,
+                new MockUser("ghi", "wew") as any,
             ];
             handler.EnqueueUser(members[0]);
             handler.EnqueueUser(members[1]);
@@ -92,8 +92,8 @@ describe("PresenceHandler", () => {
     describe("ProcessUser", () => {
         it("processes an online user", () => {
             lastStatus = null;
-            const handler = new PresenceHandler(<DiscordBot> bot);
-            const member = <any> new MockUser("abc", "def");
+            const handler = new PresenceHandler(bot as DiscordBot);
+            const member = new MockUser("abc", "def") as any;
             member.MockSetPresence(new Discord.Presence({
                 status: "online",
             }));
@@ -104,8 +104,8 @@ describe("PresenceHandler", () => {
         });
         it("processes an offline user", () => {
             lastStatus = null;
-            const handler = new PresenceHandler(<DiscordBot> bot);
-            const member = <any> new MockUser("abc", "def");
+            const handler = new PresenceHandler(bot as DiscordBot);
+            const member = new MockUser("abc", "def") as any;
             member.MockSetPresence(new Discord.Presence({
                 status: "offline",
             }));
@@ -117,8 +117,8 @@ describe("PresenceHandler", () => {
         });
         it("processes an idle user", () => {
             lastStatus = null;
-            const handler = new PresenceHandler(<DiscordBot> bot);
-            const member = <any> new MockUser("abc", "def");
+            const handler = new PresenceHandler(bot as DiscordBot);
+            const member = new MockUser("abc", "def") as any;
             member.MockSetPresence(new Discord.Presence({
                 status: "idle",
             }));
@@ -129,8 +129,8 @@ describe("PresenceHandler", () => {
         });
         it("processes an dnd user", () => {
             lastStatus = null;
-            const handler = new PresenceHandler(<DiscordBot> bot);
-            const member = <any> new MockUser("abc", "def");
+            const handler = new PresenceHandler(bot as DiscordBot);
+            const member = new MockUser("abc", "def") as any;
             member.MockSetPresence(new Discord.Presence({
                 status: "dnd",
             }));
@@ -151,8 +151,8 @@ describe("PresenceHandler", () => {
         });
         it("processes a user playing games", () => {
             lastStatus = null;
-            const handler = new PresenceHandler(<DiscordBot> bot);
-            const member = <any> new MockUser("abc", "def");
+            const handler = new PresenceHandler(bot as DiscordBot);
+            const member = new MockUser("abc", "def") as any;
             member.MockSetPresence(new Discord.Presence({
                 status: "online",
                 game: new Discord.Game({name: "Test Game"}),
diff --git a/test/test_usersyncroniser.ts b/test/test_usersyncroniser.ts
index f63e4399827e0ec031867859a11ecc07edf51af5..c1daddc4c3d0d17e388e022f8a6bee38a7a9f0c5 100644
--- a/test/test_usersyncroniser.ts
+++ b/test/test_usersyncroniser.ts
@@ -126,7 +126,7 @@ function CreateUserSync(remoteUsers: any[] = []): UserSyncroniser {
                 guild.channels.set("543345", chan as any);
                 return chan;
             }
-            throw new Error("Channel not found"); 
+            throw new Error("Channel not found");
         },
         GetGuilds: () => {
             return [];
diff --git a/tools/chanfix.ts b/tools/chanfix.ts
index 446f9d2e457cb89e91edcd9a4146fbdfc29a0ec2..3824c28e3225fa293ebe07412f7736f9fe0cd707 100644
--- a/tools/chanfix.ts
+++ b/tools/chanfix.ts
@@ -101,7 +101,7 @@ bridge.loadDatabases().catch((e) => {
     });
 }).then((clientTmp: any) => {
     client = clientTmp;
-    
+
     // first set update_icon to true if needed
     return bridge.getRoomStore().getEntriesByRemoteRoomData({
         update_name: true,
@@ -109,7 +109,7 @@ bridge.loadDatabases().catch((e) => {
     });
 }).then((mxRoomEntries) => {
     const promiseList = [];
-    
+
     mxRoomEntries.forEach((entry) => {
         if (entry.remote.get("plumbed")) {
             return; // skipping plumbed rooms
@@ -125,7 +125,7 @@ bridge.loadDatabases().catch((e) => {
 }).then(() => {
     // now it is time to actually run the updates
     let promiseChain: Bluebird<any> = Bluebird.resolve();
-    
+
     let delay = config.limits.roomGhostJoinDelay; // we'll just re-use this
     client.guilds.forEach((guild) => {
         promiseChain = promiseChain.return(Bluebird.delay(delay).then(() => {
diff --git a/tools/ghostfix.ts b/tools/ghostfix.ts
index 139a104c406470d4e3b81e36f466397caf5658e1..94dbedc224a85ca6afd4e987e52584113a2dca13 100644
--- a/tools/ghostfix.ts
+++ b/tools/ghostfix.ts
@@ -114,7 +114,7 @@ bridge.loadDatabases().catch((e) => {
 }).then((clientTmp: any) => {
     client = clientTmp;
     let promiseChain: Bluebird<any> = Bluebird.resolve();
-    
+
     let delay = config.limits.roomGhostJoinDelay;
     client.guilds.forEach((guild) => {
         guild.channels.forEach((channel) => {
diff --git a/tools/userClientTools.ts b/tools/userClientTools.ts
index 8b09af9ec2f950b6538079b82640b441019fcc9a..94bd2ad9c3f548aa544a675a1e2b1d8c29649002 100644
--- a/tools/userClientTools.ts
+++ b/tools/userClientTools.ts
@@ -99,7 +99,7 @@ Please enter your Discord Token
   });
 }
 
-function addUserToken (userid: string, token: string): Bluebird<null> {
+function addUserToken(userid: string, token: string): Bluebird<null> {
   const clientFactory = new DiscordClientFactory(discordstore);
   return clientFactory.getDiscordId(token).then((discordid: string) => {
     return discordstore.add_user_token(userid, discordid, token);