diff --git a/src/bot.ts b/src/bot.ts
index eb23cf919ca1da4509f977ccf175a62c81f4c7b7..9afd52cb8052d0a26bd48e20c83323c4fe31034c 100644
--- a/src/bot.ts
+++ b/src/bot.ts
@@ -24,592 +24,596 @@ const MIN_PRESENCE_UPDATE_DELAY = 250;
 // TODO: This is bad. We should be serving the icon from the own homeserver.
 const MATRIX_ICON_URL = "https://matrix.org/_matrix/media/r0/download/matrix.org/mlxoESwIsTbJrfXyAAogrNxA";
 class ChannelLookupResult {
-  public channel: Discord.TextChannel;
-  public botUser: boolean;
+    public channel: Discord.TextChannel;
+    public botUser: boolean;
 }
 
 export class DiscordBot {
-  private config: DiscordBridgeConfig;
-  private clientFactory: DiscordClientFactory;
-  private store: DiscordStore;
-  private bot: Discord.Client;
-  private bridge: Bridge;
-  private presenceInterval: any;
-  private sentMessages: string[];
-  private msgProcessor: MessageProcessor;
-  private mxEventProcessor: MatrixEventProcessor;
-  private presenceHandler: PresenceHandler;
-  private userSync: UserSyncroniser;
-  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;
-    this.sentMessages = [];
-    this.clientFactory = new DiscordClientFactory(store, config.auth);
-    this.msgProcessor = new MessageProcessor(
-      new MessageProcessorOpts(this.config.bridge.domain, this),
-    );
-    this.presenceHandler = new PresenceHandler(this);
-    this.discordMessageQueue = {};
-  }
-
-  public setBridge(bridge: Bridge) {
-    this.bridge = bridge;
-    this.mxEventProcessor = new MatrixEventProcessor(
-        new MatrixEventProcessorOpts(this.config, bridge, this),
-    );
-  }
-
-  public setRoomHandler(roomHandler: MatrixRoomHandler) {
-    this.roomHandler = roomHandler;
-  }
-
-  get ClientFactory(): DiscordClientFactory {
-     return this.clientFactory;
-  }
-
-  get UserSyncroniser(): UserSyncroniser {
-    return this.userSync;
-  }
-
-  get ChannelSyncroniser(): ChannelSyncroniser {
-    return this.channelSync;
-  }
-
-  public GetIntentFromDiscordMember(member: Discord.GuildMember | Discord.User): any {
-      return this.bridge.getIntentFromLocalpart(`_discord_${member.id}`);
-  }
-
-  public run(): Promise<void> {
-    return this.clientFactory.init().then(() => {
-      return this.clientFactory.getClient();
-    }).then((client: any) => {
-      if (!this.config.bridge.disableTypingNotifications) {
-        client.on("typingStart", (c, u) => { this.OnTyping(c, u, true); });
-        client.on("typingStop", (c, u) => { this.OnTyping(c, u, false);  });
-      }
-      if (!this.config.bridge.disablePresence) {
-        client.on("presenceUpdate", (_, newMember: Discord.GuildMember) => {
-          this.presenceHandler.EnqueueUser(newMember.user);
-        });
-      }
-      this.channelSync = new ChannelSyncroniser(this.bridge, this.config, this);
-      client.on("channelUpdate", (_, newChannel) => { this.channelSync.OnUpdate(newChannel); });
-      client.on("channelDelete", (channel) => { this.channelSync.OnDelete(channel); });
-      client.on("guildUpdate", (_, newGuild) => { this.channelSync.OnGuildUpdate(newGuild); });
-      client.on("guildDelete", (guild) => { this.channelSync.OnGuildDelete(guild); });
-
-      // 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");
-
-      this.userSync = new UserSyncroniser(this.bridge, this.config, this);
-      client.on("userUpdate", (_, user) => this.userSync.OnUpdateUser(user));
-      client.on("guildMemberAdd", (user) => this.userSync.OnAddGuildMember(user));
-      client.on("guildMemberRemove", (user) =>  this.userSync.OnRemoveGuildMember(user));
-      client.on("guildMemberUpdate", (oldUser, newUser) =>  this.userSync.OnUpdateGuildMember(oldUser, newUser));
-      client.on("debug", (msg) => { jsLog.verbose(msg); });
-      client.on("error", (msg) => { jsLog.error(msg); });
-      client.on("warn", (msg) => { jsLog.warn(msg); });
-      log.info("Discord bot client logged in.");
-      this.bot = client;
-
-      if (!this.config.bridge.disablePresence) {
-        if (!this.config.bridge.presenceInterval) {
-          this.config.bridge.presenceInterval = MIN_PRESENCE_UPDATE_DELAY;
-        }
-        this.bot.guilds.forEach((guild) => {
-            guild.members.forEach((member) => {
-                if (member.id !== this.GetBotId()) {
-                  this.presenceHandler.EnqueueUser(member.user);
-                }
-            });
-        });
-        this.presenceHandler.Start(
-            Math.max(this.config.bridge.presenceInterval, MIN_PRESENCE_UPDATE_DELAY),
+    private config: DiscordBridgeConfig;
+    private clientFactory: DiscordClientFactory;
+    private store: DiscordStore;
+    private bot: Discord.Client;
+    private bridge: Bridge;
+    private presenceInterval: any;
+    private sentMessages: string[];
+    private msgProcessor: MessageProcessor;
+    private mxEventProcessor: MatrixEventProcessor;
+    private presenceHandler: PresenceHandler;
+    private userSync: UserSyncroniser;
+    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;
+        this.sentMessages = [];
+        this.clientFactory = new DiscordClientFactory(store, config.auth);
+        this.msgProcessor = new MessageProcessor(
+            new MessageProcessorOpts(this.config.bridge.domain, this),
         );
-      }
-    });
-  }
+        this.presenceHandler = new PresenceHandler(this);
+        this.discordMessageQueue = {};
+    }
 
-  public GetBotId(): string {
-    return this.bot.user.id;
-  }
+    public setBridge(bridge: Bridge) {
+        this.bridge = bridge;
+        this.mxEventProcessor = new MatrixEventProcessor(
+            new MatrixEventProcessorOpts(this.config, bridge, this),
+        );
+    }
 
-  public GetGuilds(): Discord.Guild[] {
-    return this.bot.guilds.array();
-  }
+    public setRoomHandler(roomHandler: MatrixRoomHandler) {
+        this.roomHandler = roomHandler;
+    }
 
-  public ThirdpartySearchForChannels(guildId: string, channelName: string): any[] {
-    if (channelName.startsWith("#")) {
-      channelName = channelName.substr(1);
+    get ClientFactory(): DiscordClientFactory {
+        return this.clientFactory;
     }
-    if (this.bot.guilds.has(guildId) ) {
-      const guild = this.bot.guilds.get(guildId);
-      return guild.channels.filter((channel) => {
-        return channel.name.toLowerCase() === channelName.toLowerCase(); // Implement searching in the future.
-      }).map((channel) => {
-        return {
-          alias: `#_discord_${guild.id}_${channel.id}:${this.config.bridge.domain}`,
-          protocol: "discord",
-          fields: {
-            guild_id: guild.id,
-            channel_name: channel.name,
-            channel_id: channel.id,
-          },
-        };
-      });
-    } else {
-      log.info("Tried to do a third party lookup for a channel, but the guild did not exist");
-      return [];
+
+    get UserSyncroniser(): UserSyncroniser {
+        return this.userSync;
     }
-  }
-
-  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 new Error(`Guild "${server}" not found`);
-      }
-      const channel = guild.channels.get(room);
-      if (channel) {
-        const lookupResult = new ChannelLookupResult();
-        lookupResult.channel = channel;
-        lookupResult.botUser = this.bot.user.id === client.user.id;
-        return lookupResult;
-      }
-      throw new Error(`Channel "${room}" not found`);
-    }).catch((err) => {
-      log.verbose("LookupRoom => ", err);
-      if (hasSender) {
-        log.verbose(`Couldn't find guild/channel under user account. Falling back.`);
-        return this.LookupRoom(server, room, null);
-      }
-      throw err;
-    });
-  }
-
-  public async ProcessMatrixStateEvent(event: any): Promise<void> {
-      log.verbose(`Got state event from ${event.room_id} ${event.type}`);
-      const channel = await this.GetChannelFromRoomId(event.room_id) as Discord.TextChannel;
-      const msg = this.mxEventProcessor.StateEventToMessage(event, channel);
-      if (!msg) {
-          return;
-      }
-      let res = await channel.send(msg);
-      if (!Array.isArray(res)) {
-        res = [res];
-      }
-      res.forEach((m: Discord.Message) => {
-        log.verbose("Sent (state msg) ", m);
-        this.sentMessages.push(m.id);
-        const evt = new DbEvent();
-        evt.MatrixId = event.event_id + ";" + event.room_id;
-        evt.DiscordId = m.id;
-        evt.GuildId = channel.guild.id;
-        evt.ChannelId = channel.id;
-        return this.store.Insert(evt);
-      });
-  }
-
-  public async ProcessMatrixMsgEvent(event: any, guildId: string, channelId: string): Promise<null> {
-    const mxClient = this.bridge.getClientFactory().getClientAs();
-    log.verbose(`Looking up ${guildId}_${channelId}`);
-    const result = await this.LookupRoom(guildId, channelId, event.sender);
-    const chan = result.channel;
-    const botUser = result.botUser;
-    let profile = null;
-    if (result.botUser) {
-        // We are doing this through webhooks so fetch the user profile.
-        profile = await mxClient.getStateEvent(event.room_id, "m.room.member", event.sender);
-        if (profile === null) {
-          log.warn(`User ${event.sender} has no member state. That's odd.`);
-        }
+
+    get ChannelSyncroniser(): ChannelSyncroniser {
+        return this.channelSync;
     }
-    const embedSet = await this.mxEventProcessor.EventToEmbed(event, profile, chan);
-    const embed = embedSet.messageEmbed;
-    const opts: Discord.MessageOptions = {};
-    const file = await this.mxEventProcessor.HandleAttachment(event, mxClient);
-    if (typeof(file) === "string") {
-        embed.description += " " + file;
-    } else {
-        opts.file = file;
+
+    public GetIntentFromDiscordMember(member: Discord.GuildMember | Discord.User): any {
+        return this.bridge.getIntentFromLocalpart(`_discord_${member.id}`);
     }
 
-    let msg = null;
-    let hook: Discord.Webhook ;
-    if (botUser) {
-      const webhooks = await chan.fetchWebhooks();
-      hook = webhooks.filterArray((h) => h.name === "_matrix").pop();
-      // Create a new webhook if none already exists
-      try {
-        if (!hook) {
-          hook = await chan.createWebhook("_matrix", MATRIX_ICON_URL, "Matrix Bridge: Allow rich user messages");
-        }
-      } catch (err) {
-        log.error("Unable to create \"_matrix\" webhook. ", err);
-      }
+    public run(): Promise<void> {
+        return this.clientFactory.init().then(() => {
+            return this.clientFactory.getClient();
+        }).then((client: any) => {
+            if (!this.config.bridge.disableTypingNotifications) {
+                client.on("typingStart", (c, u) => { this.OnTyping(c, u, true); });
+                client.on("typingStop", (c, u) => { this.OnTyping(c, u, false);  });
+            }
+            if (!this.config.bridge.disablePresence) {
+                client.on("presenceUpdate", (_, newMember: Discord.GuildMember) => {
+                    this.presenceHandler.EnqueueUser(newMember.user);
+                });
+            }
+            this.channelSync = new ChannelSyncroniser(this.bridge, this.config, this);
+            client.on("channelUpdate", (_, newChannel) => { this.channelSync.OnUpdate(newChannel); });
+            client.on("channelDelete", (channel) => { this.channelSync.OnDelete(channel); });
+            client.on("guildUpdate", (_, newGuild) => { this.channelSync.OnGuildUpdate(newGuild); });
+            client.on("guildDelete", (guild) => { this.channelSync.OnGuildDelete(guild); });
+
+            // 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");
+
+            this.userSync = new UserSyncroniser(this.bridge, this.config, this);
+            client.on("userUpdate", (_, user) => this.userSync.OnUpdateUser(user));
+            client.on("guildMemberAdd", (user) => this.userSync.OnAddGuildMember(user));
+            client.on("guildMemberRemove", (user) =>  this.userSync.OnRemoveGuildMember(user));
+            client.on("guildMemberUpdate", (oldUser, newUser) =>  this.userSync.OnUpdateGuildMember(oldUser, newUser));
+            client.on("debug", (msg) => { jsLog.verbose(msg); });
+            client.on("error", (msg) => { jsLog.error(msg); });
+            client.on("warn", (msg) => { jsLog.warn(msg); });
+            log.info("Discord bot client logged in.");
+            this.bot = client;
+
+            if (!this.config.bridge.disablePresence) {
+                if (!this.config.bridge.presenceInterval) {
+                    this.config.bridge.presenceInterval = MIN_PRESENCE_UPDATE_DELAY;
+                }
+                this.bot.guilds.forEach((guild) => {
+                    guild.members.forEach((member) => {
+                        if (member.id !== this.GetBotId()) {
+                            this.presenceHandler.EnqueueUser(member.user);
+                        }
+                    });
+                });
+                this.presenceHandler.Start(
+                    Math.max(this.config.bridge.presenceInterval, MIN_PRESENCE_UPDATE_DELAY),
+                );
+            }
+        });
     }
-    try {
-      if (!botUser) {
-        opts.embed = embedSet.replyEmbed;
-        msg = await chan.send(embed.description, opts);
-      } else if (hook) {
-        msg = await hook.send(embed.description, {
-            username: embed.author.name,
-            avatarURL: embed.author.icon_url,
-            files: opts.file ? [opts.file] : undefined,
-            embeds: embedSet.replyEmbed ? [embedSet.replyEmbed] : undefined,
-        } as any);
-      } else {
-        if (embedSet.replyEmbed) {
-            embed.addField("Replying to", embedSet.replyEmbed.author.name);
-            embed.addField("Reply text", embedSet.replyEmbed.description);
+
+    public GetBotId(): string {
+        return this.bot.user.id;
+    }
+
+    public GetGuilds(): Discord.Guild[] {
+        return this.bot.guilds.array();
+    }
+
+    public ThirdpartySearchForChannels(guildId: string, channelName: string): any[] {
+        if (channelName.startsWith("#")) {
+            channelName = channelName.substr(1);
+        }
+        if (this.bot.guilds.has(guildId) ) {
+            const guild = this.bot.guilds.get(guildId);
+            return guild.channels.filter((channel) => {
+                return channel.name.toLowerCase() === channelName.toLowerCase(); // Implement searching in the future.
+            }).map((channel) => {
+                return {
+                    alias: `#_discord_${guild.id}_${channel.id}:${this.config.bridge.domain}`,
+                    fields: {
+                        channel_id: channel.id,
+                        channel_name: channel.name,
+                        guild_id: guild.id,
+                    },
+                    protocol: "discord",
+                };
+            });
+        } else {
+            log.info("Tried to do a third party lookup for a channel, but the guild did not exist");
+            return [];
         }
-        opts.embed = embed;
-        msg = await chan.send("", opts);
-      }
-    } catch (err) {
-      log.error("Couldn't send message. ", err);
     }
-    if (!Array.isArray(msg)) {
-      msg = [msg];
+
+    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 new Error(`Guild "${server}" not found`);
+            }
+            const channel = guild.channels.get(room);
+            if (channel) {
+                const lookupResult = new ChannelLookupResult();
+                lookupResult.channel = channel;
+                lookupResult.botUser = this.bot.user.id === client.user.id;
+                return lookupResult;
+            }
+            throw new Error(`Channel "${room}" not found`);
+        }).catch((err) => {
+            log.verbose("LookupRoom => ", err);
+            if (hasSender) {
+                log.verbose(`Couldn't find guild/channel under user account. Falling back.`);
+                return this.LookupRoom(server, room, null);
+            }
+            throw err;
+        });
     }
-    msg.forEach((m: Discord.Message) => {
-      log.verbose("Sent ", m);
-      this.sentMessages.push(m.id);
-      const evt = new DbEvent();
-      evt.MatrixId = event.event_id + ";" + event.room_id;
-      evt.DiscordId = m.id;
-      // Webhooks don't send guild info.
-      evt.GuildId = guildId;
-      evt.ChannelId = channelId;
-      return this.store.Insert(evt);
-    });
-    return;
-  }
-
-  public async ProcessMatrixRedact(event: any) {
-    if (this.config.bridge.disableDeletionForwarding) {
-      return;
+
+    public async ProcessMatrixStateEvent(event: any): Promise<void> {
+        log.verbose(`Got state event from ${event.room_id} ${event.type}`);
+        const channel = await this.GetChannelFromRoomId(event.room_id) as Discord.TextChannel;
+        const msg = this.mxEventProcessor.StateEventToMessage(event, channel);
+        if (!msg) {
+            return;
+        }
+        let res = await channel.send(msg);
+        if (!Array.isArray(res)) {
+            res = [res];
+        }
+        res.forEach((m: Discord.Message) => {
+            log.verbose("Sent (state msg) ", m);
+            this.sentMessages.push(m.id);
+            const evt = new DbEvent();
+            evt.MatrixId = event.event_id + ";" + event.room_id;
+            evt.DiscordId = m.id;
+            evt.GuildId = channel.guild.id;
+            evt.ChannelId = channel.id;
+            return this.store.Insert(evt);
+        });
     }
-    log.info(`Got redact request for ${event.redacts}`);
-    log.verbose(`Event:`, event);
 
-    const storeEvent = await this.store.Get(DbEvent, {matrix_id: event.redacts + ";" + event.room_id});
+    public async ProcessMatrixMsgEvent(event: any, guildId: string, channelId: string): Promise<null> {
+        const mxClient = this.bridge.getClientFactory().getClientAs();
+        log.verbose(`Looking up ${guildId}_${channelId}`);
+        const result = await this.LookupRoom(guildId, channelId, event.sender);
+        const chan = result.channel;
+        const botUser = result.botUser;
+        let profile = null;
+        if (result.botUser) {
+            // We are doing this through webhooks so fetch the user profile.
+            profile = await mxClient.getStateEvent(event.room_id, "m.room.member", event.sender);
+            if (profile === null) {
+                log.warn(`User ${event.sender} has no member state. That's odd.`);
+            }
+        }
+        const embedSet = await this.mxEventProcessor.EventToEmbed(event, profile, chan);
+        const embed = embedSet.messageEmbed;
+        const opts: Discord.MessageOptions = {};
+        const file = await this.mxEventProcessor.HandleAttachment(event, mxClient);
+        if (typeof(file) === "string") {
+            embed.description += " " + file;
+        } else {
+            opts.file = file;
+        }
 
-    if (!storeEvent.Result) {
-      log.warn(`Could not redact because the event was not in the store.`);
-      return;
+        let msg = null;
+        let hook: Discord.Webhook ;
+        if (botUser) {
+            const webhooks = await chan.fetchWebhooks();
+            hook = webhooks.filterArray((h) => h.name === "_matrix").pop();
+            // Create a new webhook if none already exists
+            try {
+                if (!hook) {
+                    hook = await chan.createWebhook(
+                        "_matrix",
+                        MATRIX_ICON_URL,
+                        "Matrix Bridge: Allow rich user messages");
+                }
+            } catch (err) {
+                log.error("Unable to create \"_matrix\" webhook. ", err);
+            }
+        }
+        try {
+            if (!botUser) {
+                opts.embed = embedSet.replyEmbed;
+                msg = await chan.send(embed.description, opts);
+            } else if (hook) {
+                msg = await hook.send(embed.description, {
+                    avatarURL: embed.author.icon_url,
+                    embeds: embedSet.replyEmbed ? [embedSet.replyEmbed] : undefined,
+                    files: opts.file ? [opts.file] : undefined,
+                    username: embed.author.name,
+                } as any);
+            } else {
+                if (embedSet.replyEmbed) {
+                    embed.addField("Replying to", embedSet.replyEmbed.author.name);
+                    embed.addField("Reply text", embedSet.replyEmbed.description);
+                }
+                opts.embed = embed;
+                msg = await chan.send("", opts);
+            }
+        } catch (err) {
+            log.error("Couldn't send message. ", err);
+        }
+        if (!Array.isArray(msg)) {
+            msg = [msg];
+        }
+        msg.forEach((m: Discord.Message) => {
+            log.verbose("Sent ", m);
+            this.sentMessages.push(m.id);
+            const evt = new DbEvent();
+            evt.MatrixId = event.event_id + ";" + event.room_id;
+            evt.DiscordId = m.id;
+            // Webhooks don't send guild info.
+            evt.GuildId = guildId;
+            evt.ChannelId = channelId;
+            return this.store.Insert(evt);
+        });
+        return;
     }
-    log.info(`Redact event matched ${storeEvent.ResultCount} entries`);
-    while (storeEvent.Next()) {
-      log.info(`Deleting discord msg ${storeEvent.DiscordId}`);
-      const result = await this.LookupRoom(storeEvent.GuildId, storeEvent.ChannelId, event.sender);
-      const chan = result.channel;
-
-      const msg = await chan.fetchMessage(storeEvent.DiscordId);
-      try {
-        await msg.delete();
-        log.info(`Deleted message`);
-      } catch (ex) {
-        log.warn(`Failed to delete message`, ex);
-      }
+
+    public async ProcessMatrixRedact(event: any) {
+        if (this.config.bridge.disableDeletionForwarding) {
+            return;
+        }
+        log.info(`Got redact request for ${event.redacts}`);
+        log.verbose(`Event:`, event);
+
+        const storeEvent = await this.store.Get(DbEvent, {matrix_id: event.redacts + ";" + event.room_id});
+
+        if (!storeEvent.Result) {
+            log.warn(`Could not redact because the event was not in the store.`);
+            return;
+        }
+        log.info(`Redact event matched ${storeEvent.ResultCount} entries`);
+        while (storeEvent.Next()) {
+            log.info(`Deleting discord msg ${storeEvent.DiscordId}`);
+            const result = await this.LookupRoom(storeEvent.GuildId, storeEvent.ChannelId, event.sender);
+            const chan = result.channel;
+
+            const msg = await chan.fetchMessage(storeEvent.DiscordId);
+            try {
+                await msg.delete();
+                log.info(`Deleted message`);
+            } catch (ex) {
+                log.warn(`Failed to delete message`, ex);
+            }
+        }
     }
-  }
 
-  public OnUserQuery(userId: string): any {
-    return false;
-  }
+    public OnUserQuery(userId: string): any {
+        return false;
+    }
 
-  public GetDiscordUserOrMember(
-      userId: Discord.Snowflake, guildId?: Discord.Snowflake,
-  ): Promise<Discord.User|Discord.GuildMember> {
+    public GetDiscordUserOrMember(
+        userId: Discord.Snowflake, guildId?: Discord.Snowflake,
+    ): Promise<Discord.User|Discord.GuildMember> {
         try {
             if (guildId && this.bot.guilds.has(guildId)) {
-               return this.bot.guilds.get(guildId).fetchMember(userId);
+                return this.bot.guilds.get(guildId).fetchMember(userId);
             }
             return this.bot.fetchUser(userId);
         } catch (ex) {
             log.warn(`Could not fetch user data for ${userId} (guild: ${guildId})`);
             return undefined;
         }
-  }
-
-  public GetChannelFromRoomId(roomId: string): Promise<Discord.Channel> {
-    return this.bridge.getRoomStore().getEntriesByMatrixId(
-      roomId,
-    ).then((entries) => {
-      if (entries.length === 0) {
-        log.verbose(`Couldn"t find channel for roomId ${roomId}.`);
-        return Promise.reject("Room(s) not found.");
-      }
-      const entry = entries[0];
-      const guild = this.bot.guilds.get(entry.remote.get("discord_guild"));
-      if (guild) {
-        const channel = this.bot.channels.get(entry.remote.get("discord_channel"));
-        if (channel) {
-          return channel;
-        }
-        throw Error("Channel given in room entry not found");
-      }
-      throw Error("Guild given in room entry not found");
-    });
-  }
-
-  public async GetEmoji(name: string, animated: boolean, id: string): Promise<string> {
-    if (!id.match(/^\d+$/)) {
-      throw new Error("Non-numerical ID");
-    }
-    const dbEmoji: DbEmoji = await this.store.Get(DbEmoji, {emoji_id: id});
-    if (!dbEmoji.Result) {
-      const url = "https://cdn.discordapp.com/emojis/" + id + (animated ? ".gif" : ".png");
-      const intent = this.bridge.getIntent();
-      const mxcUrl = (await Util.UploadContentFromUrl(url, intent, name)).mxcUrl;
-      dbEmoji.EmojiId = id;
-      dbEmoji.Name = name;
-      dbEmoji.Animated = animated;
-      dbEmoji.MxcUrl = mxcUrl;
-      await this.store.Insert(dbEmoji);
-    }
-    return dbEmoji.MxcUrl;
-  }
-
-  public GetRoomIdsFromGuild(guild: String): Promise<string[]> {
-    return this.bridge.getRoomStore().getEntriesByRemoteRoomData({
-      discord_guild: guild,
-    }).then((rooms) => {
-      if (rooms.length === 0) {
-        log.verbose(`Couldn't find room(s) for guild id:${guild}.`);
-        return Promise.reject("Room(s) not found.");
-      }
-      return rooms.map((room) => room.matrix.getId());
-    });
-  }
-
-  private async SendMatrixMessage(matrixMsg: MessageProcessorMatrixResult, chan: Discord.Channel,
-                                  guild: Discord.Guild, author: Discord.User,
-                                  msgID: string): Promise<boolean> {
-    const rooms = await this.channelSync.GetRoomIdsFromChannel(chan);
-    const intent = this.GetIntentFromDiscordMember(author);
-
-    rooms.forEach((room) => {
-      intent.sendMessage(room, {
-        body: matrixMsg.body,
-        msgtype: "m.text",
-        formatted_body: matrixMsg.formattedBody,
-        format: "org.matrix.custom.html",
-      }).then((res) => {
-        const evt = new DbEvent();
-        evt.MatrixId = res.event_id + ";" + room;
-        evt.DiscordId = msgID;
-        evt.ChannelId = chan.id;
-        evt.GuildId = guild.id;
-        return this.store.Insert(evt);
-      });
-    });
-
-    // Sending was a success
-    return true;
-  }
-
-  private OnTyping(channel: Discord.Channel, user: Discord.User, isTyping: boolean) {
-    this.channelSync.GetRoomIdsFromChannel(channel).then((rooms) => {
-      const intent = this.GetIntentFromDiscordMember(user);
-      return Promise.all(rooms.map((room) => {
-        return intent.sendTyping(room, isTyping);
-      }));
-    }).catch((err) => {
-      log.warn("Failed to send typing indicator.", err);
-    });
-  }
-
-  private async OnMessage(msg: Discord.Message) {
-    const indexOfMsg = this.sentMessages.indexOf(msg.id);
-    const chan = msg.channel as Discord.TextChannel;
-    if (indexOfMsg !== -1) {
-      log.verbose("Got repeated message, ignoring.");
-      delete this.sentMessages[indexOfMsg];
-      return; // Skip *our* messages
     }
-    if (msg.author.id === this.bot.user.id) {
-      // We don't support double bridging.
-      return;
-    }
-    // Issue #57: Detect webhooks
-    if (msg.webhookID != null) {
-      const webhook = (await chan.fetchWebhooks())
-                      .filterArray((h) => h.name === "_matrix").pop();
-      if (webhook != null && msg.webhookID === webhook.id) {
-        // Filter out our own webhook messages.
-        return;
-      }
+
+    public GetChannelFromRoomId(roomId: string): Promise<Discord.Channel> {
+        return this.bridge.getRoomStore().getEntriesByMatrixId(
+            roomId,
+        ).then((entries) => {
+            if (entries.length === 0) {
+                log.verbose(`Couldn"t find channel for roomId ${roomId}.`);
+                return Promise.reject("Room(s) not found.");
+            }
+            const entry = entries[0];
+            const guild = this.bot.guilds.get(entry.remote.get("discord_guild"));
+            if (guild) {
+                const channel = this.bot.channels.get(entry.remote.get("discord_channel"));
+                if (channel) {
+                    return channel;
+                }
+                throw Error("Channel given in room entry not found");
+            }
+            throw Error("Guild given in room entry not found");
+        });
     }
 
-    // Check if there's an ongoing bridge request
-    if ((msg.content === "!approve" || msg.content === "!deny") && this.provisioner.HasPendingRequest(chan)) {
-      try {
-        const isApproved = msg.content === "!approve";
-        const successfullyBridged = await this.provisioner.MarkApproved(chan, msg.member, isApproved);
-        if (successfullyBridged && isApproved) {
-          msg.channel.sendMessage("Thanks for your response! The matrix bridge has been approved");
-        } else if (successfullyBridged && !isApproved) {
-          msg.channel.sendMessage("Thanks for your response! The matrix bridge has been declined");
-        } else {
-          msg.channel.sendMessage("Thanks for your response, however the time for responses has expired - sorry!");
+    public async GetEmoji(name: string, animated: boolean, id: string): Promise<string> {
+        if (!id.match(/^\d+$/)) {
+            throw new Error("Non-numerical ID");
         }
-      } catch (err) {
-        if (err.message === "You do not have permission to manage webhooks in this channel") {
-          msg.channel.sendMessage(err.message);
-        } else {
-          log.error("Error processing room approval");
-          log.error(err);
+        const dbEmoji: DbEmoji = await this.store.Get(DbEmoji, {emoji_id: id});
+        if (!dbEmoji.Result) {
+            const url = "https://cdn.discordapp.com/emojis/" + id + (animated ? ".gif" : ".png");
+            const intent = this.bridge.getIntent();
+            const mxcUrl = (await Util.UploadContentFromUrl(url, intent, name)).mxcUrl;
+            dbEmoji.EmojiId = id;
+            dbEmoji.Name = name;
+            dbEmoji.Animated = animated;
+            dbEmoji.MxcUrl = mxcUrl;
+            await this.store.Insert(dbEmoji);
         }
-      }
-
-      return; // stop processing - we're approving/declining the bridge request
+        return dbEmoji.MxcUrl;
     }
 
-    // check if it is a command to process by the bot itself
-    if (msg.content.startsWith("!matrix")) {
-      await this.roomHandler.HandleDiscordCommand(msg);
-      return;
+    public GetRoomIdsFromGuild(guild: string): Promise<string[]> {
+        return this.bridge.getRoomStore().getEntriesByRemoteRoomData({
+            discord_guild: guild,
+        }).then((rooms) => {
+            if (rooms.length === 0) {
+                log.verbose(`Couldn't find room(s) for guild id:${guild}.`);
+                return Promise.reject("Room(s) not found.");
+            }
+            return rooms.map((room) => room.matrix.getId());
+        });
     }
 
-    // Update presence because sometimes discord misses people.
-    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;
-      });
-    }).then((rooms) => {
-      if (rooms === null) {
-        return null;
-      }
-      const intent = this.GetIntentFromDiscordMember(msg.author);
-      // Check Attachements
-      msg.attachments.forEach((attachment) => {
-        Util.UploadContentFromUrl(attachment.url, intent, attachment.filename).then((content) => {
-          const fileMime = mime.lookup(attachment.filename);
-          const msgtype = attachment.height ? "m.image" : "m.file";
-          const info = {
-            mimetype: fileMime,
-            size: attachment.filesize,
-            w: null,
-            h: null,
-          };
-          if (msgtype === "m.image") {
-            info.w = attachment.width;
-            info.h = attachment.height;
-          }
-          rooms.forEach((room) => {
+    private async SendMatrixMessage(matrixMsg: MessageProcessorMatrixResult, chan: Discord.Channel,
+                                    guild: Discord.Guild, author: Discord.User,
+                                    msgID: string): Promise<boolean> {
+        const rooms = await this.channelSync.GetRoomIdsFromChannel(chan);
+        const intent = this.GetIntentFromDiscordMember(author);
+
+        rooms.forEach((room) => {
             intent.sendMessage(room, {
-              body: attachment.filename,
-              info,
-              msgtype,
-              url: content.mxcUrl,
-              external_url: attachment.url,
-            }).then((res) => {
-              const evt = new DbEvent();
-              evt.MatrixId = res.event_id + ";" + room;
-              evt.DiscordId = msg.id;
-              evt.ChannelId = msg.channel.id;
-              evt.GuildId = msg.guild.id;
-              return this.store.Insert(evt);
-            });
-          });
-        });
-      });
-      if (msg.content !== null && msg.content !== "") {
-        this.msgProcessor.FormatDiscordMessage(msg).then((result) => {
-            rooms.forEach((room) => {
-              const trySend = () => intent.sendMessage(room, {
-                body: result.body,
-                msgtype: "m.text",
-                formatted_body: result.formattedBody,
+                body: matrixMsg.body,
                 format: "org.matrix.custom.html",
-              });
-              const afterSend = (res) => {
+                formatted_body: matrixMsg.formattedBody,
+                msgtype: "m.text",
+            }).then((res) => {
                 const evt = new DbEvent();
                 evt.MatrixId = res.event_id + ";" + room;
-                evt.DiscordId = msg.id;
-                evt.ChannelId = msg.channel.id;
-                evt.GuildId = msg.guild.id;
+                evt.DiscordId = msgID;
+                evt.ChannelId = chan.id;
+                evt.GuildId = guild.id;
                 return this.store.Insert(evt);
-              };
-              trySend().then(afterSend).catch((e) => {
-                if (e.errcode !== "M_FORBIDDEN") {
-                  log.error("DiscordBot", "Failed to send message into room.", e);
-                  return;
-                }
-                return this.userSync.EnsureJoin(msg.member, room).then(() => trySend()).then(afterSend);
-              });
             });
         });
-      }
-    }).catch((err) => {
-      log.verbose("Failed to send message into room.", err);
-    });
-  }
-
-  private async OnMessageUpdate(oldMsg: Discord.Message, newMsg: Discord.Message) {
-    // Check if an edit was actually made
-    if (oldMsg.content === newMsg.content) {
-      return;
+
+        // Sending was a success
+        return true;
+    }
+
+    private OnTyping(channel: Discord.Channel, user: Discord.User, isTyping: boolean) {
+        this.channelSync.GetRoomIdsFromChannel(channel).then((rooms) => {
+            const intent = this.GetIntentFromDiscordMember(user);
+            return Promise.all(rooms.map((room) => {
+                return intent.sendTyping(room, isTyping);
+            }));
+        }).catch((err) => {
+            log.warn("Failed to send typing indicator.", err);
+        });
     }
 
-    // Create a new edit message using the old and new message contents
-    const editedMsg = await this.msgProcessor.FormatEdit(oldMsg, newMsg);
+    private async OnMessage(msg: Discord.Message) {
+        const indexOfMsg = this.sentMessages.indexOf(msg.id);
+        const chan = msg.channel as Discord.TextChannel;
+        if (indexOfMsg !== -1) {
+            log.verbose("Got repeated message, ignoring.");
+            delete this.sentMessages[indexOfMsg];
+            return; // Skip *our* messages
+        }
+        if (msg.author.id === this.bot.user.id) {
+            // We don't support double bridging.
+            return;
+        }
+        // Issue #57: Detect webhooks
+        if (msg.webhookID != null) {
+            const webhook = (await chan.fetchWebhooks())
+                            .filterArray((h) => h.name === "_matrix").pop();
+            if (webhook != null && msg.webhookID === webhook.id) {
+              // Filter out our own webhook messages.
+                return;
+            }
+        }
+
+        // Check if there's an ongoing bridge request
+        if ((msg.content === "!approve" || msg.content === "!deny") && this.provisioner.HasPendingRequest(chan)) {
+            try {
+                const isApproved = msg.content === "!approve";
+                const successfullyBridged = await this.provisioner.MarkApproved(chan, msg.member, isApproved);
+                if (successfullyBridged && isApproved) {
+                    msg.channel.sendMessage("Thanks for your response! The matrix bridge has been approved");
+                } else if (successfullyBridged && !isApproved) {
+                    msg.channel.sendMessage("Thanks for your response! The matrix bridge has been declined");
+                } else {
+                    msg.channel.sendMessage("Thanks for your response, however" +
+                        "the time for responses has expired - sorry!");
+                }
+            } catch (err) {
+                if (err.message === "You do not have permission to manage webhooks in this channel") {
+                    msg.channel.sendMessage(err.message);
+                } else {
+                    log.error("Error processing room approval");
+                    log.error(err);
+                }
+            }
+
+            return; // stop processing - we're approving/declining the bridge request
+        }
+
+        // check if it is a command to process by the bot itself
+        if (msg.content.startsWith("!matrix")) {
+            await this.roomHandler.HandleDiscordCommand(msg);
+            return;
+        }
 
-    // Send the message to all bridged matrix rooms
-    if (!await this.SendMatrixMessage(editedMsg, newMsg.channel, newMsg.guild, newMsg.author, newMsg.id)) {
-      log.error("Unable to announce message edit for msg id:", newMsg.id);
+        // Update presence because sometimes discord misses people.
+        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;
+            });
+        }).then((rooms) => {
+            if (rooms === null) {
+              return null;
+            }
+            const intent = this.GetIntentFromDiscordMember(msg.author);
+            // Check Attachements
+            msg.attachments.forEach((attachment) => {
+                Util.UploadContentFromUrl(attachment.url, intent, attachment.filename).then((content) => {
+                    const fileMime = mime.lookup(attachment.filename);
+                    const msgtype = attachment.height ? "m.image" : "m.file";
+                    const info = {
+                        h: null,
+                        mimetype: fileMime,
+                        size: attachment.filesize,
+                        w: null,
+                    };
+                    if (msgtype === "m.image") {
+                        info.w = attachment.width;
+                        info.h = attachment.height;
+                    }
+                    rooms.forEach((room) => {
+                        intent.sendMessage(room, {
+                            body: attachment.filename,
+                            external_url: attachment.url,
+                            info,
+                            msgtype,
+                            url: content.mxcUrl,
+                        }).then((res) => {
+                            const evt = new DbEvent();
+                            evt.MatrixId = res.event_id + ";" + room;
+                            evt.DiscordId = msg.id;
+                            evt.ChannelId = msg.channel.id;
+                            evt.GuildId = msg.guild.id;
+                            return this.store.Insert(evt);
+                        });
+                    });
+                });
+            });
+            if (msg.content !== null && msg.content !== "") {
+                this.msgProcessor.FormatDiscordMessage(msg).then((result) => {
+                    rooms.forEach((room) => {
+                        const trySend = () => intent.sendMessage(room, {
+                            body: result.body,
+                            format: "org.matrix.custom.html",
+                            formatted_body: result.formattedBody,
+                            msgtype: "m.text",
+                        });
+                        const afterSend = (res) => {
+                            const evt = new DbEvent();
+                            evt.MatrixId = res.event_id + ";" + room;
+                            evt.DiscordId = msg.id;
+                            evt.ChannelId = msg.channel.id;
+                            evt.GuildId = msg.guild.id;
+                            return this.store.Insert(evt);
+                        };
+                        trySend().then(afterSend).catch((e) => {
+                            if (e.errcode !== "M_FORBIDDEN") {
+                                log.error("DiscordBot", "Failed to send message into room.", e);
+                                return;
+                            }
+                            return this.userSync.EnsureJoin(msg.member, room).then(() => trySend()).then(afterSend);
+                        });
+                    });
+                });
+            }
+        }).catch((err) => {
+            log.verbose("Failed to send message into room.", err);
+        });
     }
-  }
-
-  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;
+
+    private async OnMessageUpdate(oldMsg: Discord.Message, newMsg: Discord.Message) {
+        // Check if an edit was actually made
+        if (oldMsg.content === newMsg.content) {
+            return;
+        }
+
+        // Create a new edit message using the old and new message contents
+        const editedMsg = await this.msgProcessor.FormatEdit(oldMsg, newMsg);
+
+        // Send the message to all bridged matrix rooms
+        if (!await this.SendMatrixMessage(editedMsg, newMsg.channel, newMsg.guild, newMsg.author, newMsg.id)) {
+            log.error("Unable to announce message edit for msg id:", newMsg.id);
+        }
     }
-    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 84fa42a4b7756f76c2de452a20e742a8e40208a7..a92a9eae1dc797d592e52c0d5cddcc8743f2dfaa 100644
--- a/src/channelsyncroniser.ts
+++ b/src/channelsyncroniser.ts
@@ -10,18 +10,18 @@ const log = new Log("ChannelSync");
 const POWER_LEVEL_MESSAGE_TALK = 50;
 
 const DEFAULT_CHANNEL_STATE = {
+    iconMxcUrl: null,
     id: null,
     mxChannels: [],
-    iconMxcUrl: null,
 };
 
 const DEFAULT_SINGLECHANNEL_STATE = {
+    iconId: null,
+    iconUrl: null, // nullable
     mxid: null,
     name: null, // nullable
-    topic: null, // nullable
-    iconUrl: null, // nullable
-    iconId: null,
     removeIcon: false,
+    topic: null, // nullable
 };
 
 export interface ISingleChannelState {
@@ -147,8 +147,8 @@ export class ChannelSyncroniser {
         }
 
         const patternMap = {
-            name: "#" + channel.name,
             guild: channel.guild.name,
+            name: "#" + channel.name,
         };
         let name = this.config.channel.namePattern;
         for (const p of Object.keys(patternMap)) {
diff --git a/src/clientfactory.ts b/src/clientfactory.ts
index a9e1b8b944aeddf90d18f893e8cfbb4dba0f6b4a..13e6bff5af205bf45c758912d9a85ea9a7b3633b 100644
--- a/src/clientfactory.ts
+++ b/src/clientfactory.ts
@@ -9,86 +9,86 @@ const log = new Log("ClientFactory");
 const READY_TIMEOUT = 5000;
 
 export class DiscordClientFactory {
-  private config: DiscordBridgeConfigAuth;
-  private store: DiscordStore;
-  private botClient: any;
-  private clients: Map<string, any>;
-  constructor(store: DiscordStore, config?: DiscordBridgeConfigAuth) {
-    this.config = config;
-    this.clients = new Map();
-    this.store = store;
-  }
-
-  public async init(): Promise<void> {
-    if (this.config === undefined) {
-      return Promise.reject("Client config not supplied.");
+    private config: DiscordBridgeConfigAuth;
+    private store: DiscordStore;
+    private botClient: any;
+    private clients: Map<string, any>;
+    constructor(store: DiscordStore, config?: DiscordBridgeConfigAuth) {
+        this.config = config;
+        this.clients = new Map();
+        this.store = store;
     }
-    // We just need to make sure we have a bearer token.
-    // Create a new Bot client.
-    this.botClient = Bluebird.promisifyAll(new Client({
-      fetchAllMembers: true,
-      sync: true,
-      messageCacheLifetime: 5,
-    }));
-    return Bluebird.all([
-        this.botClient.onAsync("ready").timeout(READY_TIMEOUT, "Bot timed out waiting for ready."),
-        this.botClient.login(this.config.botToken),
-    ]).then(() => { return; }).catch((err) => {
-        log.error("Could not login as the bot user. This is bad!", err);
-        throw err;
-    });
-  }
-
- public getDiscordId(token: String): Bluebird<string> {
-    const client: any = new Client({
-      fetchAllMembers: false,
-      sync: false,
-      messageCacheLifetime: 5,
-    });
-    return new Bluebird<string>((resolve, reject) => {
-      client.on("ready", () => {
-        const id = client.user.id;
-        client.destroy();
-        resolve(id);
-      });
-      client.login(token).catch(reject);
-    }).timeout(READY_TIMEOUT).catch((err: Error) => {
-      log.warn("Could not login as a normal user.", err.message);
-      throw Error("Could not retrieve ID");
-    });
-  }
 
-  public async getClient(userId: string = null): Promise<any> {
-    if (userId == null) {
-      return this.botClient;
-    }
-    if (this.clients.has(userId)) {
-      log.verbose("Returning cached user client for", userId);
-      return this.clients.get(userId);
+    public async init(): Promise<void> {
+        if (this.config === undefined) {
+            return Promise.reject("Client config not supplied.");
+        }
+        // We just need to make sure we have a bearer token.
+        // Create a new Bot client.
+        this.botClient = Bluebird.promisifyAll(new Client({
+            fetchAllMembers: true,
+            messageCacheLifetime: 5,
+            sync: true,
+        }));
+        return Bluebird.all([
+            this.botClient.onAsync("ready").timeout(READY_TIMEOUT, "Bot timed out waiting for ready."),
+            this.botClient.login(this.config.botToken),
+        ]).then(() => { return; }).catch((err) => {
+            log.error("Could not login as the bot user. This is bad!", err);
+            throw err;
+        });
     }
-    const discordIds = await this.store.get_user_discord_ids(userId);
-    if (discordIds.length === 0) {
-      return Promise.resolve(this.botClient);
+
+   public getDiscordId(token: string): Bluebird<string> {
+        const client: any = new Client({
+            fetchAllMembers: false,
+            messageCacheLifetime: 5,
+            sync: false,
+        });
+        return new Bluebird<string>((resolve, reject) => {
+            client.on("ready", () => {
+                const id = client.user.id;
+                client.destroy();
+                resolve(id);
+            });
+            client.login(token).catch(reject);
+        }).timeout(READY_TIMEOUT).catch((err: Error) => {
+            log.warn("Could not login as a normal user.", err.message);
+            throw Error("Could not retrieve ID");
+        });
     }
-    // TODO: Select a profile based on preference, not the first one.
-    const token = await this.store.get_token(discordIds[0]);
-    const client: any = Bluebird.promisifyAll(new Client({
-      fetchAllMembers: true,
-      sync: true,
-      messageCacheLifetime: 5,
-    }));
-    const jsLog = new Log("discord.js-ppt");
-    client.on("debug", (msg) => { jsLog.verbose(msg); });
-    client.on("error", (msg) => { jsLog.error(msg); });
-    client.on("warn", (msg) => { jsLog.warn(msg); });
-    try {
-      await client.login(token);
-      log.verbose("Logged in. Storing ", userId);
-      this.clients.set(userId, client);
-      return client;
-    } catch (err) {
-      log.warn(`Could not log ${userId} in. Returning bot user for now.`, err);
-      return this.botClient;
+
+    public async getClient(userId: string = null): Promise<any> {
+        if (userId == null) {
+            return this.botClient;
+        }
+        if (this.clients.has(userId)) {
+            log.verbose("Returning cached user client for", userId);
+            return this.clients.get(userId);
+        }
+        const discordIds = await this.store.get_user_discord_ids(userId);
+        if (discordIds.length === 0) {
+            return Promise.resolve(this.botClient);
+        }
+        // TODO: Select a profile based on preference, not the first one.
+        const token = await this.store.get_token(discordIds[0]);
+        const client: any = Bluebird.promisifyAll(new Client({
+            fetchAllMembers: true,
+            messageCacheLifetime: 5,
+            sync: true,
+        }));
+        const jsLog = new Log("discord.js-ppt");
+        client.on("debug", (msg) => { jsLog.verbose(msg); });
+        client.on("error", (msg) => { jsLog.error(msg); });
+        client.on("warn", (msg) => { jsLog.warn(msg); });
+        try {
+            await client.login(token);
+            log.verbose("Logged in. Storing ", userId);
+            this.clients.set(userId, client);
+            return client;
+        } catch (err) {
+            log.warn(`Could not log ${userId} in. Returning bot user for now.`, err);
+            return this.botClient;
+        }
     }
-  }
 }
diff --git a/src/config.ts b/src/config.ts
index abba23fdc26b038de2e4ea309757ed0c2e35527e..e6ec2628cf2673e8fe18e5d10cf15cf7abefa488 100644
--- a/src/config.ts
+++ b/src/config.ts
@@ -1,91 +1,91 @@
 /** Type annotations for config/config.schema.yaml */
 export class DiscordBridgeConfig {
-  public bridge: DiscordBridgeConfigBridge = new DiscordBridgeConfigBridge();
-  public auth: DiscordBridgeConfigAuth = new DiscordBridgeConfigAuth();
-  public logging: DiscordBridgeConfigLogging = new DiscordBridgeConfigLogging();
-  public database: DiscordBridgeConfigDatabase = new DiscordBridgeConfigDatabase();
-  public room: DiscordBridgeConfigRoom = new DiscordBridgeConfigRoom();
-  public channel: DiscordBridgeConfigChannel = new DiscordBridgeConfigChannel();
-  public limits: DiscordBridgeConfigLimits = new DiscordBridgeConfigLimits();
+    public bridge: DiscordBridgeConfigBridge = new DiscordBridgeConfigBridge();
+    public auth: DiscordBridgeConfigAuth = new DiscordBridgeConfigAuth();
+    public logging: DiscordBridgeConfigLogging = new DiscordBridgeConfigLogging();
+    public database: DiscordBridgeConfigDatabase = new DiscordBridgeConfigDatabase();
+    public room: DiscordBridgeConfigRoom = new DiscordBridgeConfigRoom();
+    public channel: DiscordBridgeConfigChannel = new DiscordBridgeConfigChannel();
+    public limits: DiscordBridgeConfigLimits = new DiscordBridgeConfigLimits();
 
-  /**
-   * Apply a set of keys and values over the default config.
-   * @param _config Config keys
-   * @param configLayer Private parameter
-   */
-  public ApplyConfig(newConfig: {[key: string]: any}, configLayer: any = this) {
-    Object.keys(newConfig).forEach((key) => {
-      if ( typeof(configLayer[key]) === "object" &&
-           !Array.isArray(configLayer[key])) {
-        this.ApplyConfig(newConfig[key], this[key]);
-        return;
-      }
-      configLayer[key] = newConfig[key];
-    });
-  }
+    /**
+     * Apply a set of keys and values over the default config.
+     * @param _config Config keys
+     * @param configLayer Private parameter
+     */
+    public ApplyConfig(newConfig: {[key: string]: any}, configLayer: any = this) {
+          Object.keys(newConfig).forEach((key) => {
+            if ( typeof(configLayer[key]) === "object" &&
+                    !Array.isArray(configLayer[key])) {
+                this.ApplyConfig(newConfig[key], this[key]);
+                return;
+            }
+            configLayer[key] = newConfig[key];
+        });
+    }
 }
 
 class DiscordBridgeConfigBridge {
-  public domain: string;
-  public homeserverUrl: string;
-  public presenceInterval: number = 500;
-  public disablePresence: boolean;
-  public disableTypingNotifications: boolean;
-  public disableDiscordMentions: boolean;
-  public disableDeletionForwarding: boolean;
-  public enableSelfServiceBridging: boolean;
-  public disableEveryoneMention: boolean = false;
-  public disableHereMention: boolean = false;
+    public domain: string;
+    public homeserverUrl: string;
+    public presenceInterval: number = 500;
+    public disablePresence: boolean;
+    public disableTypingNotifications: boolean;
+    public disableDiscordMentions: boolean;
+    public disableDeletionForwarding: boolean;
+    public enableSelfServiceBridging: boolean;
+    public disableEveryoneMention: boolean = false;
+    public disableHereMention: boolean = false;
 }
 
 export class DiscordBridgeConfigDatabase {
-  public connString: string;
-  public filename: string;
-  public userStorePath: string;
-  public roomStorePath: string;
+    public connString: string;
+    public filename: string;
+    public userStorePath: string;
+    public roomStorePath: string;
 }
 
 export class DiscordBridgeConfigAuth {
-  public clientID: string;
-  public botToken: string;
+    public clientID: string;
+    public botToken: string;
 }
 
 export class DiscordBridgeConfigLogging {
-  public console: string = "info";
-  public lineDateFormat: string = "MMM-D HH:mm:ss.SSS";
-  public files: LoggingFile[] = [];
+    public console: string = "info";
+    public lineDateFormat: string = "MMM-D HH:mm:ss.SSS";
+    public files: LoggingFile[] = [];
 }
 
 class DiscordBridgeConfigRoom {
-  public defaultVisibility: string;
+    public defaultVisibility: string;
 }
 
 class DiscordBridgeConfigChannel {
-  public namePattern: string = "[Discord] :guild :name";
-  public deleteOptions = new DiscordBridgeConfigChannelDeleteOptions();
+    public namePattern: string = "[Discord] :guild :name";
+    public deleteOptions = new DiscordBridgeConfigChannelDeleteOptions();
 }
 
 class DiscordBridgeConfigChannelDeleteOptions {
-  public namePrefix: string = null;
-  public topicPrefix: string = null;
-  public disableMessaging: boolean = false;
-  public unsetRoomAlias: boolean = true;
-  public unlistFromDirectory: boolean = true;
-  public setInviteOnly: boolean = true;
-  public ghostsLeave: boolean = true;
+    public namePrefix: string = null;
+    public topicPrefix: string = null;
+    public disableMessaging: boolean = false;
+    public unsetRoomAlias: boolean = true;
+    public unlistFromDirectory: boolean = true;
+    public setInviteOnly: boolean = true;
+    public ghostsLeave: boolean = true;
 }
 
 class DiscordBridgeConfigLimits {
-  public roomGhostJoinDelay: number = 6000;
-  public discordSendDelay: number = 750;
+    public roomGhostJoinDelay: number = 6000;
+    public discordSendDelay: number = 750;
 }
 
 export class LoggingFile {
-  public file: string;
-  public level: string = "info";
-  public maxFiles: string = "14d";
-  public maxSize: string|number = "50m";
-  public datePattern: string = "YYYY-MM-DD";
-  public enabled: string[] = [];
-  public disabled: string[] = [];
+    public file: string;
+    public level: string = "info";
+    public maxFiles: string = "14d";
+    public maxSize: string|number = "50m";
+    public datePattern: string = "YYYY-MM-DD";
+    public enabled: string[] = [];
+    public disabled: string[] = [];
 }
diff --git a/src/db/dbdataemoji.ts b/src/db/dbdataemoji.ts
index 41d16c3bd24bb1d3e40d84ea3e1f4a10edfbc622..79a358d68eb6dc22f3d0244e84d413a2da4d83a9 100644
--- a/src/db/dbdataemoji.ts
+++ b/src/db/dbdataemoji.ts
@@ -36,11 +36,11 @@ export class DbEmoji implements IDbData {
             INSERT INTO emoji
             (emoji_id,name,animated,mxc_url,created_at,updated_at)
             VALUES ($emoji_id,$name,$animated,$mxc_url,$created_at,$updated_at);`, {
-                emoji_id: this.EmojiId,
-                name: this.Name,
                 animated: Number(this.Animated),
-                mxc_url: this.MxcUrl,
                 created_at: this.CreatedAt,
+                emoji_id: this.EmojiId,
+                mxc_url: this.MxcUrl,
+                name: this.Name,
                 updated_at: this.UpdatedAt,
         });
     }
@@ -56,10 +56,10 @@ export class DbEmoji implements IDbData {
             updated_at = $updated_at
             WHERE
             emoji_id = $emoji_id`, {
-                emoji_id: this.EmojiId,
-                name: this.Name,
                 animated: Number(this.Animated),
+                emoji_id: this.EmojiId,
                 mxc_url: this.MxcUrl,
+                name: this.Name,
                 updated_at: this.UpdatedAt,
         });
     }
diff --git a/src/db/dbdataevent.ts b/src/db/dbdataevent.ts
index 8756b9ec431a2b4ad5dbe9ae1fc9c7030fda57fb..ab66fe023023783447fe193f0c693f99103b80a0 100644
--- a/src/db/dbdataevent.ts
+++ b/src/db/dbdataevent.ts
@@ -36,8 +36,8 @@ export class DbEvent implements IDbDataMany {
 
         for (const rowM of rowsM) {
             const row = {
-                matrix_id: rowM.matrix_id,
                 discord_id: rowM.discord_id,
+                matrix_id: rowM.matrix_id,
             };
             for (const rowD of await store.db.All(`
                     SELECT *
@@ -72,8 +72,8 @@ export class DbEvent implements IDbDataMany {
             INSERT INTO event_store
             (matrix_id,discord_id)
             VALUES ($matrix_id,$discord_id);`, {
-                matrix_id: this.MatrixId,
                 discord_id: this.DiscordId,
+                matrix_id: this.MatrixId,
         });
         // Check if the discord item exists?
         const msgExists = await store.db.Get(`
@@ -89,9 +89,9 @@ export class DbEvent implements IDbDataMany {
             INSERT INTO discord_msg_store
             (msg_id, guild_id, channel_id)
             VALUES ($msg_id, $guild_id, $channel_id);`, {
-                msg_id: this.DiscordId,
-                guild_id: this.GuildId,
                 channel_id: this.ChannelId,
+                guild_id: this.GuildId,
+                msg_id: this.DiscordId,
         });
     }
 
@@ -104,8 +104,8 @@ export class DbEvent implements IDbDataMany {
             DELETE FROM event_store
             WHERE matrix_id = $matrix_id
             AND discord_id = $discord_id;`, {
-                matrix_id: this.MatrixId,
                 discord_id: this.DiscordId,
+                matrix_id: this.MatrixId,
         });
         return store.db.Run(`
             DELETE FROM discord_msg_store
diff --git a/src/db/postgres.ts b/src/db/postgres.ts
index c5a7cde731ca22d27a28c7904fbbd6b71739fd25..b0207bd7b517d1cd2689c56f00ec32569517e274 100644
--- a/src/db/postgres.ts
+++ b/src/db/postgres.ts
@@ -1,10 +1,9 @@
-import {IMain, IDatabase} from "pg-promise";
 import * as pgPromise from "pg-promise";
 import { Log } from "../log";
 import { IDatabaseConnector } from "./connector";
 const log = new Log("SQLite3");
 
-const pgp: IMain = pgPromise({
+const pgp: pgPromise.IMain = pgPromise({
     // Initialization Options
 });
 
@@ -15,7 +14,7 @@ export class Postgres implements IDatabaseConnector {
         });
     }
 
-    private db: IDatabase<any>;
+    private db: pgPromise.IDatabase<any>;
     constructor(private connectionString: string) {
 
     }
diff --git a/src/db/schema/dbschema.ts b/src/db/schema/dbschema.ts
index 563aeae5ae1b0d9032635741fc2dfa897a1f4c5a..e96ceb6c4b28b0c6ebd8cea095ce61a35db157cc 100644
--- a/src/db/schema/dbschema.ts
+++ b/src/db/schema/dbschema.ts
@@ -1,6 +1,6 @@
 import { DiscordStore } from "../../store";
 export interface IDbSchema {
-  description: string;
-  run(store: DiscordStore): Promise<null|void|Error|Error[]>;
-  rollBack(store: DiscordStore): Promise<null|void|Error|Error[]>;
+    description: string;
+    run(store: DiscordStore): Promise<null|void|Error|Error[]>;
+    rollBack(store: DiscordStore): Promise<null|void|Error|Error[]>;
 }
diff --git a/src/db/schema/v1.ts b/src/db/schema/v1.ts
index c2824a58c41bf9d9add8a57042d2cee61059e741..20004bb01b2e9458cdb2f003d082cc370dc5161c 100644
--- a/src/db/schema/v1.ts
+++ b/src/db/schema/v1.ts
@@ -1,25 +1,25 @@
 import {IDbSchema} from "./dbschema";
 import {DiscordStore} from "../../store";
 export class Schema implements IDbSchema {
-  public description = "Schema, Client Auth Table";
-  public run(store: DiscordStore): Promise<Error> {
-    return store.create_table(`
-    CREATE TABLE schema (
-      version	INTEGER UNIQUE NOT NULL
-    );`, "schema").then(() => {
-      return store.db.Exec("INSERT INTO schema VALUES (0);");
-    }).then(() => {
-      return store.create_table(`
-      CREATE TABLE user_tokens (
-        userId TEXT UNIQUE NOT NULL,
-        token TEXT UNIQUE NOT NULL
-      );`, "user_tokens");
-    });
-  }
-  public rollBack(store: DiscordStore): Promise<Error> {
-    return store.db.Exec(
-      `DROP TABLE IF EXISTS schema;
-      DROP TABLE IF EXISTS user_tokens`,
-    );
-  }
+    public description = "Schema, Client Auth Table";
+    public run(store: DiscordStore): Promise<Error> {
+        return store.create_table(`
+        CREATE TABLE schema (
+            version	INTEGER UNIQUE NOT NULL
+        );`, "schema").then(() => {
+            return store.db.Exec("INSERT INTO schema VALUES (0);");
+        }).then(() => {
+            return store.create_table(`
+            CREATE TABLE user_tokens (
+                userId TEXT UNIQUE NOT NULL,
+                token TEXT UNIQUE NOT NULL
+            );`, "user_tokens");
+        });
+      }
+    public rollBack(store: DiscordStore): Promise<Error> {
+        return store.db.Exec(
+            `DROP TABLE IF EXISTS schema;
+            DROP TABLE IF EXISTS user_tokens`,
+        );
+    }
 }
diff --git a/src/db/schema/v2.ts b/src/db/schema/v2.ts
index 2f6d8a10b8b056bb53f696b55ecb5905b2af5aad..c5c0cf4b6aed614030836cfe6145e442d1046623 100644
--- a/src/db/schema/v2.ts
+++ b/src/db/schema/v2.ts
@@ -1,26 +1,26 @@
 import {IDbSchema} from "./dbschema";
 import {DiscordStore} from "../../store";
 export class Schema implements IDbSchema {
-  public description = "Create DM Table, User Options";
-  public run(store: DiscordStore): Promise<Error[]> {
-    return Promise.all([
-      store.create_table(`
-      CREATE TABLE dm_rooms (
-        discord_id	TEXT NOT NULL,
-        channel_id	TEXT NOT NULL,
-        room_id	TEXT UNIQUE NOT NULL
-      );`, "dm_rooms"),
-      store.create_table(`
-      CREATE TABLE client_options (
-        discord_id	TEXT UNIQUE NOT NULL,
-        options	INTEGER NOT NULL
-      );`, "client_options",
-    )]);
-  }
-  public rollBack(store: DiscordStore): Promise<Error> {
-    return store.db.Exec(
-      `DROP TABLE IF EXISTS dm_rooms;
-      DROP TABLE IF EXISTS client_options;`,
-    );
-  }
+    public description = "Create DM Table, User Options";
+    public run(store: DiscordStore): Promise<Error[]> {
+        return Promise.all([
+            store.create_table(`
+            CREATE TABLE dm_rooms (
+                discord_id	TEXT NOT NULL,
+                channel_id	TEXT NOT NULL,
+                room_id	TEXT UNIQUE NOT NULL
+            );`, "dm_rooms"),
+            store.create_table(`
+            CREATE TABLE client_options (
+                discord_id	TEXT UNIQUE NOT NULL,
+                options	INTEGER NOT NULL
+            );`, "client_options",
+        )]);
+    }
+    public rollBack(store: DiscordStore): Promise<Error> {
+        return store.db.Exec(
+            `DROP TABLE IF EXISTS dm_rooms;
+            DROP TABLE IF EXISTS client_options;`,
+        );
+    }
 }
diff --git a/src/db/schema/v3.ts b/src/db/schema/v3.ts
index bc2440603775e425496a3c834732a2a292aa5e25..ab4562785c0ed95b671c19530c7a5cc16badddcb 100644
--- a/src/db/schema/v3.ts
+++ b/src/db/schema/v3.ts
@@ -6,92 +6,92 @@ import { Log } from "../../log";
 const log = new Log("SchemaV3");
 
 export class Schema implements IDbSchema {
-  public description = "user_tokens split into user_id_discord_id";
-  public run(store: DiscordStore): Promise<null> {
-    const promise = Promise.all([store.create_table(`
-      CREATE TABLE user_id_discord_id (
-        discord_id TEXT NOT NULL,
-        user_id TEXT NOT NULL,
-        PRIMARY KEY(discord_id, user_id)
-      );`, "user_id_discord_id"),
-      store.create_table(`
-      CREATE TABLE discord_id_token (
-        discord_id TEXT UNIQUE NOT NULL,
-        token	TEXT NOT NULL,
-        PRIMARY KEY(discord_id)
-      );`, "discord_id_token",
-      )]);
-    return promise.then(() => {
-      // Backup before moving data.
-      return store.backup_database();
-    }).then(() => {
-      // Move old data to new tables.
-      return this.moveUserIds(store);
-    }).then(() => {
-      // Drop old table.
-      return store.db.Run(
-        `DROP TABLE IF EXISTS user_tokens;`,
-      );
-    });
-  }
+    public description = "user_tokens split into user_id_discord_id";
+    public run(store: DiscordStore): Promise<null> {
+        const promise = Promise.all([store.create_table(`
+            CREATE TABLE user_id_discord_id (
+                discord_id TEXT NOT NULL,
+                user_id TEXT NOT NULL,
+                PRIMARY KEY(discord_id, user_id)
+            );`, "user_id_discord_id"),
+            store.create_table(`
+            CREATE TABLE discord_id_token (
+                discord_id TEXT UNIQUE NOT NULL,
+                token	TEXT NOT NULL,
+                PRIMARY KEY(discord_id)
+            );`, "discord_id_token",
+            )]);
+        return promise.then(() => {
+            // Backup before moving data.
+            return store.backup_database();
+        }).then(() => {
+            // Move old data to new tables.
+            return this.moveUserIds(store);
+        }).then(() => {
+            // Drop old table.
+            return store.db.Run(
+                `DROP TABLE IF EXISTS user_tokens;`,
+            );
+        });
+    }
 
-  public rollBack(store: DiscordStore): Promise <void> {
-    return Promise.all([store.db.Run(
-      `DROP TABLE IF EXISTS user_id_discord_id;`,
-    ), store.db.Run(
-      `DROP TABLE IF EXISTS discord_id_token;`,
-    )]).then(() => {
+    public rollBack(store: DiscordStore): Promise <void> {
+        return Promise.all([store.db.Run(
+            `DROP TABLE IF EXISTS user_id_discord_id;`,
+        ), store.db.Run(
+            `DROP TABLE IF EXISTS discord_id_token;`,
+        )]).then(() => {
 
-    });
-  }
+        });
+    }
 
-  private async moveUserIds(store: DiscordStore): Promise <null> {
-  log.info("Performing one time moving of tokens to new table. Please wait.");
-  let rows;
-  try {
-    rows = await store.db.All(`SELECT * FROM user_tokens`);
-  } catch (err) {
-    log.error(`
+    private async moveUserIds(store: DiscordStore): Promise <null> {
+        log.info("Performing one time moving of tokens to new table. Please wait.");
+        let rows;
+        try {
+            rows = await store.db.All(`SELECT * FROM user_tokens`);
+        } catch (err) {
+            log.error(`
 Could not select users from 'user_tokens'.It is possible that the table does
 not exist on your database in which case you can proceed safely. Otherwise
 a copy of the database before the schema update has been placed in the root
 directory.`);
-    log.error(err);
-    return;
-  }
-  const promises = [];
-  const clientFactory = new DiscordClientFactory(store);
-  for (const row of rows) {
-    log.info("Moving ", row.userId);
-    try {
-      const dId = clientFactory.getDiscordId(row.token);
-      if (dId === null) {
-        continue;
-      }
-      log.verbose("INSERT INTO discord_id_token.");
-      await store.db.Run(
-        `
-            INSERT INTO discord_id_token (discord_id,token)
-            VALUES ($discordId,$token);
-            `
-        , {
-          $discordId: dId,
-          $token: row.token,
-        });
-      log.verbose("INSERT INTO user_id_discord_id.");
-      await store.db.Run(
-        `
-            INSERT INTO user_id_discord_id (discord_id,user_id)
-            VALUES ($discordId,$userId);
-            `
-        , {
-          $discordId: dId,
-          $userId: row.userId,
-        });
-    } catch (err) {
-      log.error(`Couldn't move ${row.userId}'s token into new table.`);
-      log.error(err);
+            log.error(err);
+            return;
+        }
+        const promises = [];
+        const clientFactory = new DiscordClientFactory(store);
+        for (const row of rows) {
+            log.info("Moving ", row.userId);
+            try {
+                const dId = clientFactory.getDiscordId(row.token);
+                if (dId === null) {
+                    continue;
+                }
+                log.verbose("INSERT INTO discord_id_token.");
+                await store.db.Run(
+                    `
+                        INSERT INTO discord_id_token (discord_id,token)
+                        VALUES ($discordId,$token);
+                    `
+                    , {
+                        $discordId: dId,
+                        $token: row.token,
+                    });
+                log.verbose("INSERT INTO user_id_discord_id.");
+                await store.db.Run(
+                    `
+                        INSERT INTO user_id_discord_id (discord_id,user_id)
+                        VALUES ($discordId,$userId);
+                    `
+                    , {
+                        $discordId: dId,
+                        $userId: row.userId,
+                    });
+            } catch (err) {
+                log.error(`Couldn't move ${row.userId}'s token into new table.`);
+                log.error(err);
+            }
+        }
     }
-  }
-}
 }
diff --git a/src/db/schema/v4.ts b/src/db/schema/v4.ts
index 80443ab5458b578f94dc0eb55f6ad4c9feb2c4e9..602583fc03cc5dd204fbf4da1b529aee1f0ed18f 100644
--- a/src/db/schema/v4.ts
+++ b/src/db/schema/v4.ts
@@ -2,23 +2,23 @@ import {IDbSchema} from "./dbschema";
 import {DiscordStore} from "../../store";
 
 export class Schema implements IDbSchema {
-  public description = "create guild emoji table";
-  public run(store: DiscordStore): Promise<Error> {
-    return store.create_table(`
-      CREATE TABLE guild_emoji (
-        emoji_id TEXT NOT NULL,
-        guild_id TEXT NOT NULL,
-        name TEXT NOT NULL,
-        mxc_url TEXT NOT NULL,
-        created_at INTEGER NOT NULL,
-        updated_at INTEGER NOT NULL,
-        PRIMARY KEY(emoji_id, guild_id)
-    );`, "guild_emoji");
-  }
+    public description = "create guild emoji table";
+    public run(store: DiscordStore): Promise<Error> {
+        return store.create_table(`
+            CREATE TABLE guild_emoji (
+                emoji_id TEXT NOT NULL,
+                guild_id TEXT NOT NULL,
+                name TEXT NOT NULL,
+                mxc_url TEXT NOT NULL,
+                created_at INTEGER NOT NULL,
+                updated_at INTEGER NOT NULL,
+                PRIMARY KEY(emoji_id, guild_id)
+        );`, "guild_emoji");
+    }
 
-  public rollBack(store: DiscordStore): Promise <Error> {
-    return store.db.Run(
-      `DROP TABLE IF EXISTS guild_emoji;`,
-    );
-  }
+    public rollBack(store: DiscordStore): Promise <Error> {
+        return store.db.Run(
+            `DROP TABLE IF EXISTS guild_emoji;`,
+        );
+    }
 }
diff --git a/src/db/schema/v5.ts b/src/db/schema/v5.ts
index 223bc44637a6e3f8271ce55c056e59d217e9b405..aaa31a9bb5c4bb0f4d0f14b2f6ee1448bc0e91a0 100644
--- a/src/db/schema/v5.ts
+++ b/src/db/schema/v5.ts
@@ -2,19 +2,19 @@ import {IDbSchema} from "./dbschema";
 import {DiscordStore} from "../../store";
 
 export class Schema implements IDbSchema {
-  public description = "create event_store table";
-  public run(store: DiscordStore): Promise<Error> {
-    return store.create_table(`
-      CREATE TABLE event_store (
-        matrix_id TEXT NOT NULL,
-        discord_id TEXT NOT NULL,
-        PRIMARY KEY(matrix_id, discord_id)
-    );`, "event_store");
-  }
+    public description = "create event_store table";
+    public run(store: DiscordStore): Promise<Error> {
+        return store.create_table(`
+            CREATE TABLE event_store (
+                matrix_id TEXT NOT NULL,
+                discord_id TEXT NOT NULL,
+                PRIMARY KEY(matrix_id, discord_id)
+        );`, "event_store");
+    }
 
-  public rollBack(store: DiscordStore): Promise <Error> {
-    return store.db.Run(
-      `DROP TABLE IF EXISTS event_store;`,
-    );
-  }
+    public rollBack(store: DiscordStore): Promise <Error> {
+        return store.db.Run(
+            `DROP TABLE IF EXISTS event_store;`,
+        );
+    }
 }
diff --git a/src/db/schema/v6.ts b/src/db/schema/v6.ts
index 74c7a4c38090c9c0961f13620f979dadad8fb613..29e29e552f50acd8f2a6d1db775bccddcc79b7cf 100644
--- a/src/db/schema/v6.ts
+++ b/src/db/schema/v6.ts
@@ -2,30 +2,30 @@ import {IDbSchema} from "./dbschema";
 import {DiscordStore} from "../../store";
 
 export class Schema implements IDbSchema {
-  public description = "create event_store and discord_msg_store tables";
-  public async run(store: DiscordStore): Promise<void|Error> {
-    await store.db.Run(
-        `DROP TABLE IF EXISTS event_store;`,
-    );
-    await store.create_table(`
-      CREATE TABLE event_store (
-        matrix_id TEXT NOT NULL,
-        discord_id TEXT NOT NULL,
-        PRIMARY KEY(matrix_id, discord_id)
-    );`, "event_store");
-    return await store.create_table(`
-      CREATE TABLE discord_msg_store (
-        msg_id TEXT NOT NULL,
-        guild_id TEXT NOT NULL,
-        channel_id TEXT NOT NULL,
-        PRIMARY KEY(msg_id)
-    );`, "discord_msg_store");
-  }
+    public description = "create event_store and discord_msg_store tables";
+    public async run(store: DiscordStore): Promise<void|Error> {
+        await store.db.Run(
+            `DROP TABLE IF EXISTS event_store;`,
+        );
+        await store.create_table(`
+            CREATE TABLE event_store (
+                matrix_id TEXT NOT NULL,
+                discord_id TEXT NOT NULL,
+                PRIMARY KEY(matrix_id, discord_id)
+        );`, "event_store");
+        return await store.create_table(`
+            CREATE TABLE discord_msg_store (
+                msg_id TEXT NOT NULL,
+                guild_id TEXT NOT NULL,
+                channel_id TEXT NOT NULL,
+                PRIMARY KEY(msg_id)
+        );`, "discord_msg_store");
+    }
 
-  public rollBack(store: DiscordStore): Promise <null> {
-    return store.db.Exec(
-      `DROP TABLE IF EXISTS event_store;` +
-      `DROP TABLE IF EXISTS discord_msg_store;`,
-    );
-  }
+    public rollBack(store: DiscordStore): Promise <null> {
+        return store.db.Exec(
+            `DROP TABLE IF EXISTS event_store;` +
+            `DROP TABLE IF EXISTS discord_msg_store;`,
+        );
+    }
 }
diff --git a/src/db/schema/v7.ts b/src/db/schema/v7.ts
index adb3a336a58867aad5c0daec3e6d827532acf46a..4fba9edc0ed1eed3d33ac8dbc48418190334e71d 100644
--- a/src/db/schema/v7.ts
+++ b/src/db/schema/v7.ts
@@ -5,33 +5,33 @@ import { Log } from "../../log";
 const log = new Log("SchemaV7");
 
 export class Schema implements IDbSchema {
-  public description = "create guild emoji table";
-  public run(store: DiscordStore): Promise<null> {
-    return store.create_table(`
-      CREATE TABLE emoji (
-        emoji_id TEXT NOT NULL,
-        name TEXT NOT NULL,
-        animated INTEGER NOT NULL,
-        mxc_url TEXT NOT NULL,
-        created_at INTEGER NOT NULL,
-        updated_at INTEGER NOT NULL,
-        PRIMARY KEY(emoji_id)
-    );`, "emoji").then(() => {
-      // migrate existing emoji
-      return store.db.Run(`
-        INSERT INTO emoji
-          (emoji_id, name, animated, mxc_url, created_at, updated_at)
-        SELECT emoji_id, name, 0 AS animated, mxc_url, created_at, updated_at FROM guild_emoji;
-      `).catch(() => {
-        // ignore errors
-        log.warning("Failed to migrate old data to new table");
-      });
-    });
-  }
+    public description = "create guild emoji table";
+    public run(store: DiscordStore): Promise<null> {
+        return store.create_table(`
+            CREATE TABLE emoji (
+                emoji_id TEXT NOT NULL,
+                name TEXT NOT NULL,
+                animated INTEGER NOT NULL,
+                mxc_url TEXT NOT NULL,
+                created_at INTEGER NOT NULL,
+                updated_at INTEGER NOT NULL,
+                PRIMARY KEY(emoji_id)
+        );`, "emoji").then(() => {
+            // migrate existing emoji
+            return store.db.Run(`
+                INSERT INTO emoji
+                  (emoji_id, name, animated, mxc_url, created_at, updated_at)
+                SELECT emoji_id, name, 0 AS animated, mxc_url, created_at, updated_at FROM guild_emoji;
+            `).catch(() => {
+                // ignore errors
+                log.warning("Failed to migrate old data to new table");
+            });
+        });
+    }
 
-  public rollBack(store: DiscordStore): Promise <null> {
-    return store.db.Run(
-      `DROP TABLE IF EXISTS emoji;`,
-    );
-  }
+    public rollBack(store: DiscordStore): Promise <null> {
+        return store.db.Run(
+            `DROP TABLE IF EXISTS emoji;`,
+        );
+    }
 }
diff --git a/src/discordas.ts b/src/discordas.ts
index 2a09458e4c5c57c157d3715bd629a9c34553eb00..fa8d870e6031985579ef4826654ad6b48c1c03ce 100644
--- a/src/discordas.ts
+++ b/src/discordas.ts
@@ -12,104 +12,103 @@ import { Log } from "./log";
 const log = new Log("DiscordAS");
 
 const cli = new Cli({
-  bridgeConfig: {
-    affectsRegistration: true,
-    schema: "./config/config.schema.yaml",
-  },
-  registrationPath: "discord-registration.yaml",
-  generateRegistration,
-  run,
+    bridgeConfig: {
+        affectsRegistration: true,
+        schema: "./config/config.schema.yaml",
+    },
+    generateRegistration,
+    registrationPath: "discord-registration.yaml",
+    run,
 });
 
 try {
-  cli.run();
+    cli.run();
 } catch (err) {
-  log.error("Failed to start bridge.");
-  log.error(err);
+    log.error("Failed to start bridge.");
+    log.error(err);
 }
 
 function generateRegistration(reg, callback)  {
-  reg.setId(AppServiceRegistration.generateToken());
-  reg.setHomeserverToken(AppServiceRegistration.generateToken());
-  reg.setAppServiceToken(AppServiceRegistration.generateToken());
-  reg.setSenderLocalpart("_discord_bot");
-  reg.addRegexPattern("users", "@_discord_.*", true);
-  reg.addRegexPattern("aliases", "#_discord_.*", true);
-  reg.setRateLimited(false);
-  reg.setProtocols(["discord"]);
-  callback(reg);
+    reg.setId(AppServiceRegistration.generateToken());
+    reg.setHomeserverToken(AppServiceRegistration.generateToken());
+    reg.setAppServiceToken(AppServiceRegistration.generateToken());
+    reg.setSenderLocalpart("_discord_bot");
+    reg.addRegexPattern("users", "@_discord_.*", true);
+    reg.addRegexPattern("aliases", "#_discord_.*", true);
+    reg.setRateLimited(false);
+    reg.setProtocols(["discord"]);
+    callback(reg);
 }
 
 function run(port: number, fileConfig: DiscordBridgeConfig) {
-  const config = new DiscordBridgeConfig();
-  config.ApplyConfig(fileConfig);
-  Log.Configure(config.logging);
-  log.info("Starting Discord AS");
-  const yamlConfig = yaml.safeLoad(fs.readFileSync(cli.opts.registrationPath, "utf8"));
-  const registration = AppServiceRegistration.fromObject(yamlConfig);
-  if (registration === null) {
-    throw new Error("Failed to parse registration file");
-  }
+    const config = new DiscordBridgeConfig();
+    config.ApplyConfig(fileConfig);
+    Log.Configure(config.logging);
+    log.info("Starting Discord AS");
+    const yamlConfig = yaml.safeLoad(fs.readFileSync(cli.opts.registrationPath, "utf8"));
+    const registration = AppServiceRegistration.fromObject(yamlConfig);
+    if (registration === null) {
+        throw new Error("Failed to parse registration file");
+    }
 
-  const botUserId = "@" + registration.sender_localpart + ":" + config.bridge.domain;
-  const clientFactory = new ClientFactory({
-    appServiceUserId: botUserId,
-    token: registration.as_token,
-    url: config.bridge.homeserverUrl,
-  });
-  const provisioner = new Provisioner();
-  // Warn and deprecate old config options.
-  const discordstore = new DiscordStore(config.database);
-  const discordbot = new DiscordBot(config, discordstore, provisioner);
-  const roomhandler = new MatrixRoomHandler(discordbot, config, botUserId, provisioner);
+    const botUserId = "@" + registration.sender_localpart + ":" + config.bridge.domain;
+    const clientFactory = new ClientFactory({
+        appServiceUserId: botUserId,
+        token: registration.as_token,
+        url: config.bridge.homeserverUrl,
+    });
+    const provisioner = new Provisioner();
+    // Warn and deprecate old config options.
+    const discordstore = new DiscordStore(config.database);
+    const discordbot = new DiscordBot(config, discordstore, provisioner);
+    const roomhandler = new MatrixRoomHandler(discordbot, config, botUserId, provisioner);
 
-  const bridge = new Bridge({
-    clientFactory,
-    controller: {
-      // onUserQuery: userQuery,
-      onAliasQuery: roomhandler.OnAliasQuery.bind(roomhandler),
-      onEvent: (request, context) =>
-          request.outcomeFrom(Bluebird.resolve(roomhandler.OnEvent(request, context)))
-      ,
-      onAliasQueried: roomhandler.OnAliasQueried.bind(roomhandler),
-      thirdPartyLookup: roomhandler.ThirdPartyLookup,
-      onLog: (line, isError) => {
-        log.verbose("matrix-appservice-bridge", line);
-      },
-    },
-    intentOptions: {
-      clients: {
-        dontJoin: true, // handled manually
-      },
-    },
-    domain: config.bridge.domain,
-    homeserverUrl: config.bridge.homeserverUrl,
-    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);
-  discordbot.setBridge(bridge);
-  discordbot.setRoomHandler(roomhandler);
-  log.info("Initing bridge.");
-  log.info(`Started listening on port ${port}.`);
-  bridge.run(port, config).then(() => {
-    log.info("Initing store.");
-    return discordstore.init();
-  }).then(() => {
-    log.info("Initing bot.");
-    return discordbot.run().then(() => {
-      log.info("Discordbot started successfully.");
+    const bridge = new Bridge({
+        clientFactory,
+        controller: {
+            // onUserQuery: userQuery,
+            onAliasQueried: roomhandler.OnAliasQueried.bind(roomhandler),
+            onAliasQuery: roomhandler.OnAliasQuery.bind(roomhandler),
+            onEvent: (request, context) =>
+                request.outcomeFrom(Bluebird.resolve(roomhandler.OnEvent(request, context))),
+            onLog: (line, isError) => {
+                log.verbose("matrix-appservice-bridge", line);
+            },
+            thirdPartyLookup: roomhandler.ThirdPartyLookup,
+        },
+        domain: config.bridge.domain,
+        homeserverUrl: config.bridge.homeserverUrl,
+        intentOptions: {
+            clients: {
+                dontJoin: true, // handled manually
+            },
+        },
+        queue: {
+            perRequest: true,
+            type: "per_room",
+        },
+        registration,
+        roomStore: config.database.roomStorePath,
+        userStore: config.database.userStorePath,
+        // To avoid out of order message sending.
+    });
+    provisioner.SetBridge(bridge);
+    roomhandler.setBridge(bridge);
+    discordbot.setBridge(bridge);
+    discordbot.setRoomHandler(roomhandler);
+    log.info("Initing bridge.");
+    log.info(`Started listening on port ${port}.`);
+    bridge.run(port, config).then(() => {
+        log.info("Initing store.");
+        return discordstore.init();
+    }).then(() => {
+        log.info("Initing bot.");
+        return discordbot.run().then(() => {
+            log.info("Discordbot started successfully.");
+        });
+    }).catch((err) => {
+        log.error(err);
+        log.error("Failure during startup. Exiting.");
+        process.exit(1);
     });
-  }).catch((err) => {
-    log.error(err);
-    log.error("Failure during startup. Exiting.");
-    process.exit(1);
-  });
 }
diff --git a/src/log.ts b/src/log.ts
index 2b775da7e18e70212b8e4c48abbda2576c4d98f4..410fb5bf98413020b4587b2def61e4044416e2a6 100644
--- a/src/log.ts
+++ b/src/log.ts
@@ -59,7 +59,7 @@ export class Log {
 
     private static setupFileTransport(config: LoggingFile): transports.FileTransportInstance {
         config = Object.assign(new LoggingFile(), config);
-        const filterOutMods = format((info, opts) => {
+        const filterOutMods = format((info, _) => {
             if (config.disabled.includes(info.module) &&
                 config.enabled.length > 0 &&
                 !config.enabled.includes(info.module)
@@ -70,15 +70,15 @@ export class Log {
         });
 
         const opts = {
-            filename: config.file,
-            maxFiles: config.maxFiles,
-            maxSize: config.maxSize,
             datePattern: config.datePattern,
-            level: config.level,
+            filename: config.file,
             format: format.combine(
                 filterOutMods(),
                 FORMAT_FUNC,
             ),
+            level: config.level,
+            maxFiles: config.maxFiles,
+            maxSize: config.maxSize,
         };
 
         return new (transports as any).DailyRotateFile(opts);
diff --git a/src/matrixeventprocessor.ts b/src/matrixeventprocessor.ts
index bfce1154dce66d63ac1861f10c7e293ae053ac96..399a098bb36f16a24fc5e9d5df1ff80c85b7cf3a 100644
--- a/src/matrixeventprocessor.ts
+++ b/src/matrixeventprocessor.ts
@@ -1,12 +1,12 @@
 import * as Discord from "discord.js";
-import {MessageProcessorOpts, MessageProcessor} from "./messageprocessor";
-import {DiscordBot} from "./bot";
-import {DiscordBridgeConfig} from "./config";
+import { MessageProcessorOpts, MessageProcessor } from "./messageprocessor";
+import { DiscordBot } from "./bot";
+import { DiscordBridgeConfig } from "./config";
 import * as escapeStringRegexp from "escape-string-regexp";
-import {Util} from "./util";
+import { Util } from "./util";
 import * as path from "path";
 import * as mime from "mime";
-import {MatrixUser} from "matrix-appservice-bridge";
+import { MatrixUser } from "matrix-appservice-bridge";
 
 import { Log } from "./log";
 const log = new Log("MatrixEventProcessor");
@@ -201,8 +201,8 @@ export class MatrixEventProcessor {
             size = attachment.byteLength;
             if (size < MaxFileSize) {
                 return {
-                    name,
                     attachment,
+                    name,
                 };
             }
         }
diff --git a/src/matrixroomhandler.ts b/src/matrixroomhandler.ts
index bb63c0956b85814028dd1e91da4956fb9bec794a..ae8c52a36debd0e7b80aad9ac9c601b524da4781 100644
--- a/src/matrixroomhandler.ts
+++ b/src/matrixroomhandler.ts
@@ -1,12 +1,12 @@
 import { DiscordBot } from "./bot";
 import {
-  Bridge,
-  RemoteRoom,
-  thirdPartyLookup,
-  thirdPartyProtocolResult,
-  thirdPartyUserResult,
-  thirdPartyLocationResult,
- } from "matrix-appservice-bridge";
+    Bridge,
+    RemoteRoom,
+    thirdPartyLookup,
+    thirdPartyProtocolResult,
+    thirdPartyUserResult,
+    thirdPartyLocationResult,
+} from "matrix-appservice-bridge";
 import { DiscordBridgeConfig } from "./config";
 
 import * as Discord from "discord.js";
@@ -37,519 +37,521 @@ const JOIN_ROOM_SCHEDULE = [
 
 export class MatrixRoomHandler {
 
-  private config: DiscordBridgeConfig;
-  private bridge: Bridge;
-  private discord: DiscordBot;
-  private botUserId: string;
-  constructor(discord: DiscordBot, config: DiscordBridgeConfig, botUserId: string, private provisioner: Provisioner) {
-    this.discord = discord;
-    this.config = config;
-    this.botUserId = botUserId;
-  }
-
-  public get ThirdPartyLookup(): thirdPartyLookup {
-    return {
-      protocols: ["discord"],
-      getProtocol: this.tpGetProtocol.bind(this),
-      getLocation: this.tpGetLocation.bind(this),
-      parseLocation: this.tpParseLocation.bind(this),
-      getUser: this.tpGetUser.bind(this),
-      parseUser: this.tpParseUser.bind(this),
-    };
-  }
-
-  public setBridge(bridge: Bridge) {
-    this.bridge = bridge;
-  }
-
-  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;
-
-    // Fire and forget RoomDirectory mapping
-    this.bridge.getIntent().getClient().setRoomDirectoryVisibilityAppService(
-        channel.guild.id,
-        roomId,
-        "public",
-    );
-    await this.discord.ChannelSyncroniser.OnUpdate(channel);
-    let promiseChain: Bluebird<any> = Bluebird.resolve();
-    /* We delay the joins to give some implementations a chance to breathe */
-    // 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 (channel as Discord.TextChannel).members.array()) {
-        if (member.id === this.discord.GetBotId()) {
-          continue;
+    private config: DiscordBridgeConfig;
+    private bridge: Bridge;
+    private discord: DiscordBot;
+    private botUserId: string;
+    constructor(discord: DiscordBot, config: DiscordBridgeConfig, botUserId: string, private provisioner: Provisioner) {
+        this.discord = discord;
+        this.config = config;
+        this.botUserId = botUserId;
+    }
+
+    public get ThirdPartyLookup(): thirdPartyLookup {
+        return {
+            getLocation: this.tpGetLocation.bind(this),
+            getProtocol: this.tpGetProtocol.bind(this),
+            getUser: this.tpGetUser.bind(this),
+            parseLocation: this.tpParseLocation.bind(this),
+            parseUser: this.tpParseUser.bind(this),
+            protocols: ["discord"],
+        };
+    }
+
+    public setBridge(bridge: Bridge) {
+        this.bridge = bridge;
+    }
+
+    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;
+
+        // Fire and forget RoomDirectory mapping
+        this.bridge.getIntent().getClient().setRoomDirectoryVisibilityAppService(
+            channel.guild.id,
+            roomId,
+            "public",
+        );
+        await this.discord.ChannelSyncroniser.OnUpdate(channel);
+        let promiseChain: Bluebird<any> = Bluebird.resolve();
+        /* We delay the joins to give some implementations a chance to breathe */
+        // 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 (channel as Discord.TextChannel).members.array()) {
+            if (member.id === this.discord.GetBotId()) {
+              continue;
+            }
+            promiseChain = promiseChain.return(Bluebird.delay(delay).then(() => {
+                log.info("OnAliasQueried", `UserSyncing ${member.id}`);
+                // Ensure the profile is up to date.
+                return this.discord.UserSyncroniser.OnUpdateUser(member.user);
+            }).then(() => {
+                log.info("OnAliasQueried", `Joining ${member.id} to ${roomId}`);
+                return this.joinRoom(this.discord.GetIntentFromDiscordMember(member), roomId)
+                    .then(() => {
+                      // set the correct discord guild name
+                      this.discord.UserSyncroniser.EnsureJoin(member, roomId);
+                    });
+            }));
+            delay += this.config.limits.roomGhostJoinDelay;
+        }
+        // tslint:disable-next-line:await-promise
+        await promiseChain;
+    }
+
+    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}`);
+            return Promise.reject("Event too old");
         }
-        promiseChain = promiseChain.return(Bluebird.delay(delay).then(() => {
-            log.info("OnAliasQueried", `UserSyncing ${member.id}`);
-            // Ensure the profile is up to date.
-            return this.discord.UserSyncroniser.OnUpdateUser(member.user);
-        }).then(() => {
-            log.info("OnAliasQueried", `Joining ${member.id} to ${roomId}`);
-            return this.joinRoom(this.discord.GetIntentFromDiscordMember(member), roomId)
-                .then(() => {
-                  // set the correct discord guild name
-                  this.discord.UserSyncroniser.EnsureJoin(member, roomId);
+        if (event.type === "m.room.member" && event.content.membership === "invite") {
+            return this.HandleInvite(event);
+        } else if (event.type === "m.room.member" && event.content.membership === "join") {
+            if (this.bridge.getBot().isRemoteUser(event.state_key)) {
+                return this.discord.UserSyncroniser.OnMemberState(event, USERSYNC_STATE_DELAY_MS);
+            } else {
+                return this.discord.ProcessMatrixStateEvent(event);
+            }
+        } else if (["m.room.member", "m.room.name", "m.room.topic"].includes(event.type)) {
+            return this.discord.ProcessMatrixStateEvent(event);
+        } else if (event.type === "m.room.redaction" && context.rooms.remote) {
+            return this.discord.ProcessMatrixRedact(event);
+        } else if (event.type === "m.room.message" || event.type === "m.sticker") {
+            log.verbose(`Got ${event.type} event`);
+            const isBotCommand = event.type === "m.room.message" &&
+                event.content.body &&
+                event.content.body.startsWith("!discord");
+            if (isBotCommand) {
+                return this.ProcessCommand(event, context);
+            } else if (context.rooms.remote) {
+                const srvChanPair = context.rooms.remote.roomId.substr("_discord".length).split("_", ROOM_NAME_PARTS);
+                return this.discord.ProcessMatrixMsgEvent(event, srvChanPair[0], srvChanPair[1]).catch((err) => {
+                    log.warn("There was an error sending a matrix event", err);
                 });
-        }));
-        delay += this.config.limits.roomGhostJoinDelay;
+            }
+        } else if (event.type === "m.room.encryption" && context.rooms.remote) {
+            return this.HandleEncryptionWarning(event.room_id).catch((err) => {
+                return Promise.reject(`Failed to handle encrypted room, ${err}`);
+            });
+        } else {
+            log.verbose("Got non m.room.message event");
+        }
+        return Promise.reject("Event not processed by bridge");
     }
-    // tslint:disable-next-line:await-promise
-    await promiseChain;
-  }
-
-  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}`);
-      return Promise.reject("Event too old");
+
+    public async HandleEncryptionWarning(roomId: string): Promise<void> {
+        const intent = this.bridge.getIntent();
+        log.info(`User has turned on encryption in ${roomId}, so leaving.`);
+        /* N.B 'status' is not specced but https://github.com/matrix-org/matrix-doc/pull/828
+         has been open for over a year with no resolution. */
+        const sendPromise = intent.sendMessage(roomId, {
+            body: "You have turned on encryption in this room, so the service will not bridge any new messages.",
+            msgtype: "m.notice",
+            status: "critical",
+        });
+        const channel = await this.discord.GetChannelFromRoomId(roomId);
+        await (channel as Discord.TextChannel).send(
+          "Someone on Matrix has turned on encryption in this room, so the service will not bridge any new messages",
+        );
+        await sendPromise;
+        await intent.leave(roomId);
+        await this.bridge.getRoomStore().removeEntriesByMatrixRoomId(roomId);
     }
-    if (event.type === "m.room.member" && event.content.membership === "invite") {
-      return this.HandleInvite(event);
-    } else if (event.type === "m.room.member" && event.content.membership === "join") {
-        if (this.bridge.getBot().isRemoteUser(event.state_key)) {
-            return this.discord.UserSyncroniser.OnMemberState(event, USERSYNC_STATE_DELAY_MS);
+
+    public HandleInvite(event: any) {
+        log.info("Received invite for " + event.state_key + " in room " + event.room_id);
+        if (event.state_key === this.botUserId) {
+            log.info("Accepting invite for bridge bot");
+            return this.joinRoom(this.bridge.getIntent(), event.room_id);
         } else {
-          return this.discord.ProcessMatrixStateEvent(event);
+            return this.discord.ProcessMatrixStateEvent(event);
+        }
+    }
+
+    public async ProcessCommand(event: any, context: any) {
+        const intent = this.bridge.getIntent();
+        // Due to #257 we need to check if we are joined.
+        try {
+            await intent.getClient().sendReadReceipt(event.event_id);
+        } catch (ex) {
+            log.warn("Couldn't send a read reciept into the room:", ex, ". Ignoring command.");
+            return;
         }
-    } else if (["m.room.member", "m.room.name", "m.room.topic"].includes(event.type)) {
-      return this.discord.ProcessMatrixStateEvent(event);
-    } else if (event.type === "m.room.redaction" && context.rooms.remote) {
-      return this.discord.ProcessMatrixRedact(event);
-    } else if (event.type === "m.room.message" || event.type === "m.sticker") {
-        log.verbose(`Got ${event.type} event`);
-        const isBotCommand = event.type === "m.room.message" &&
-            event.content.body &&
-            event.content.body.startsWith("!discord");
-        if (isBotCommand) {
-            return this.ProcessCommand(event, context);
-        } else if (context.rooms.remote) {
-            const srvChanPair = context.rooms.remote.roomId.substr("_discord".length).split("_", ROOM_NAME_PARTS);
-            return this.discord.ProcessMatrixMsgEvent(event, srvChanPair[0], srvChanPair[1]).catch((err) => {
-                log.warn("There was an error sending a matrix event", err);
+
+        if (!this.config.bridge.enableSelfServiceBridging) {
+            // We can do this here because the only commands we support are self-service bridging
+            return this.bridge.getIntent().sendMessage(event.room_id, {
+                body: "The owner of this bridge does not permit self-service bridging.",
+                msgtype: "m.notice",
             });
         }
-    } else if (event.type === "m.room.encryption" && context.rooms.remote) {
-        return this.HandleEncryptionWarning(event.room_id).catch((err) => {
-            return Promise.reject(`Failed to handle encrypted room, ${err}`);
+
+        // Check to make sure the user has permission to do anything in the room. We can do this here
+        // because the only commands we support are self-service commands (which therefore require some
+        // level of permissions)
+        const plEvent = await this.bridge.getIntent().getClient()
+            .getStateEvent(event.room_id, "m.room.power_levels", "");
+        let userLevel = PROVISIONING_DEFAULT_USER_POWER_LEVEL;
+        let requiredLevel = PROVISIONING_DEFAULT_POWER_LEVEL;
+        if (plEvent && plEvent.state_default) {
+            requiredLevel = plEvent.state_default;
+        }
+        if (plEvent && plEvent.users_default) {
+            userLevel = plEvent.users_default;
+        }
+        if (plEvent && plEvent.users && plEvent.users[event.sender]) {
+            userLevel = plEvent.users[event.sender];
+        }
+
+        if (userLevel < requiredLevel) {
+            return this.bridge.getIntent().sendMessage(event.room_id, {
+                body: "You do not have the required power level in this room to create a bridge to a Discord channel.",
+                msgtype: "m.notice",
+            });
+        }
+
+        const {command, args} = Util.MsgToArgs(event.content.body, "!discord");
+
+        if (command === "help" && args[0] === "bridge") {
+            const link = Util.GetBotLink(this.config);
+            return this.bridge.getIntent().sendMessage(event.room_id, {
+                body: "How to bridge a Discord guild:\n" +
+                "1. Invite the bot to your Discord guild using this link: " + link + "\n" +
+                "2. Invite me to the matrix room you'd like to bridge\n" +
+                "3. Open the Discord channel you'd like to bridge in a web browser\n" +
+                "4. In the matrix room, send the message `!discord bridge <guild id> <channel id>` " +
+                "(without the backticks)\n" +
+                "   Note: The Guild ID and Channel ID can be retrieved from the URL in your web browser.\n" +
+                "   The URL is formatted as https://discordapp.com/channels/GUILD_ID/CHANNEL_ID\n" +
+                "5. Enjoy your new bridge!",
+                msgtype: "m.notice",
+            });
+        } else if (command === "bridge") {
+            if (context.rooms.remote) {
+                return this.bridge.getIntent().sendMessage(event.room_id, {
+                    body: "This room is already bridged to a Discord guild.",
+                    msgtype: "m.notice",
+                });
+            }
+
+            const minArgs = 2;
+            if (args.length < minArgs) {
+                return this.bridge.getIntent().sendMessage(event.room_id, {
+                    body: "Invalid syntax. For more information try !discord help bridge",
+                    msgtype: "m.notice",
+                });
+            }
+
+            const guildId = args[0];
+            const channelId = args[1];
+            try {
+                const discordResult = await this.discord.LookupRoom(guildId, channelId);
+                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, {
+                    body: "I'm asking permission from the guild administrators to make this bridge.",
+                    msgtype: "m.notice",
+                });
+
+                await this.provisioner.AskBridgePermission(channel, event.sender);
+                this.provisioner.BridgeMatrixRoom(channel, event.room_id);
+                return this.bridge.getIntent().sendMessage(event.room_id, {
+                    body: "I have bridged this room to your channel",
+                    msgtype: "m.notice",
+                });
+            } catch (err) {
+                if (err.message === "Timed out waiting for a response from the Discord owners"
+                    || err.message === "The bridge has been declined by the Discord guild") {
+                    return this.bridge.getIntent().sendMessage(event.room_id, {
+                        body: err.message,
+                        msgtype: "m.notice",
+                    });
+                }
+
+                log.error(`Error bridging ${event.room_id} to ${guildId}/${channelId}`);
+                log.error(err);
+                return this.bridge.getIntent().sendMessage(event.room_id, {
+                    body: "There was a problem bridging that channel - has the guild owner approved the bridge?",
+                    msgtype: "m.notice",
+                });
+            }
+        } else if (command === "unbridge") {
+            const remoteRoom = context.rooms.remote;
+
+            if (!remoteRoom) {
+                return this.bridge.getIntent().sendMessage(event.room_id, {
+                    body: "This room is not bridged.",
+                    msgtype: "m.notice",
+                });
+            }
+
+            if (!remoteRoom.data.plumbed) {
+                return this.bridge.getIntent().sendMessage(event.room_id, {
+                    body: "This room cannot be unbridged.",
+                    msgtype: "m.notice",
+                });
+            }
+
+            try {
+                await this.provisioner.UnbridgeRoom(remoteRoom);
+                return this.bridge.getIntent().sendMessage(event.room_id, {
+                    body: "This room has been unbridged",
+                    msgtype: "m.notice",
+                });
+            } catch (err) {
+                log.error("Error while unbridging room " + event.room_id);
+                log.error(err);
+                return this.bridge.getIntent().sendMessage(event.room_id, {
+                    body: "There was an error unbridging this room. " +
+                      "Please try again later or contact the bridge operator.",
+                    msgtype: "m.notice",
+                });
+            }
+        } else if (command === "help") {
+            // Unknown command or no command given to get help on, so we'll just give them the help
+            return this.bridge.getIntent().sendMessage(event.room_id, {
+                body: "Available commands:\n" +
+                "!discord bridge <guild id> <channel id>   - Bridges this room to a Discord channel\n" +
+                "!discord unbridge                         - Unbridges a Discord channel from this room\n" +
+                "!discord help <command>                   - Help menu for another command. Eg: !discord help bridge\n",
+                msgtype: "m.notice",
+            });
+        }
+    }
+
+    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] === "") {
+            log.warn(`Alias '${aliasLocalpart}' was missing a server and/or a channel`);
+            return;
+        }
+        return this.discord.LookupRoom(srvChanPair[0], srvChanPair[1]).then((result) => {
+            log.info("Creating #", aliasLocalpart);
+            return this.createMatrixRoom(result.channel, aliasLocalpart);
+        }).catch((err) => {
+            log.error(`Couldn't find discord room '${aliasLocalpart}'.`, err);
         });
-    } else {
-      log.verbose("Got non m.room.message event");
     }
-    return Promise.reject("Event not processed by bridge");
-  }
-
-  public async HandleEncryptionWarning(roomId: string): Promise<void> {
-      const intent = this.bridge.getIntent();
-      log.info(`User has turned on encryption in ${roomId}, so leaving.`);
-      /* N.B 'status' is not specced but https://github.com/matrix-org/matrix-doc/pull/828
-       has been open for over a year with no resolution. */
-      const sendPromise = intent.sendMessage(roomId, {
-          msgtype: "m.notice",
-          status: "critical",
-          body: "You have turned on encryption in this room, so the service will not bridge any new messages.",
-      });
-      const channel = await this.discord.GetChannelFromRoomId(roomId);
-      await (channel as Discord.TextChannel).send(
-        "Someone on Matrix has turned on encryption in this room, so the service will not bridge any new messages",
-      );
-      await sendPromise;
-      await intent.leave(roomId);
-      await this.bridge.getRoomStore().removeEntriesByMatrixRoomId(roomId);
-  }
-
-  public HandleInvite(event: any) {
-    log.info("Received invite for " + event.state_key + " in room " + event.room_id);
-    if (event.state_key === this.botUserId) {
-      log.info("Accepting invite for bridge bot");
-      return this.joinRoom(this.bridge.getIntent(), event.room_id);
-    } else {
-      return this.discord.ProcessMatrixStateEvent(event);
+
+    public tpGetProtocol(protocol: string): Promise<thirdPartyProtocolResult> {
+        return Promise.resolve({
+            field_types: {
+                // guild_name: {
+                //   regexp: "\S.{0,98}\S",
+                //   placeholder: "Guild",
+                // },
+                channel_id: {
+                    placeholder: "",
+                    regexp: "[0-9]*",
+                },
+                channel_name: {
+                    placeholder: "#Channel",
+                    regexp: "[A-Za-z0-9_\-]{2,100}",
+                },
+                discriminator: {
+                    placeholder: "1234",
+                    regexp: "[0-9]{4}",
+                },
+                guild_id: {
+                    placeholder: "",
+                    regexp: "[0-9]*",
+                },
+                username: {
+                    placeholder: "Username",
+                    regexp: "[A-Za-z0-9_\-]{2,100}",
+                },
+            },
+            instances: this.discord.GetGuilds().map((guild) => {
+                return {
+                    bot_user_id: this.botUserId,
+                    desc: guild.name,
+                    fields: {
+                        guild_id: guild.id,
+                    },
+                    icon: guild.iconURL || ICON_URL, // TODO: Use icons from our content repo. Potential security risk.
+                    network_id: guild.id,
+                };
+            }),
+            location_fields: ["guild_id", "channel_name"],
+            user_fields: ["username", "discriminator"],
+        });
     }
-  }
-
-  public async ProcessCommand(event: any, context: any) {
-      const intent = this.bridge.getIntent();
-      // Due to #257 we need to check if we are joined.
-      try {
-          await intent.getClient().sendReadReceipt(event.event_id);
-      } catch (ex) {
-          log.warn("Couldn't send a read reciept into the room:", ex, ". Ignoring command.");
-          return;
-      }
-
-      if (!this.config.bridge.enableSelfServiceBridging) {
-          // We can do this here because the only commands we support are self-service bridging
-          return this.bridge.getIntent().sendMessage(event.room_id, {
-              msgtype: "m.notice",
-              body: "The owner of this bridge does not permit self-service bridging.",
-          });
-      }
-
-      // Check to make sure the user has permission to do anything in the room. We can do this here
-      // because the only commands we support are self-service commands (which therefore require some
-      // level of permissions)
-      const plEvent = await this.bridge.getIntent().getClient().getStateEvent(event.room_id, "m.room.power_levels", "");
-      let userLevel = PROVISIONING_DEFAULT_USER_POWER_LEVEL;
-      let requiredLevel = PROVISIONING_DEFAULT_POWER_LEVEL;
-      if (plEvent && plEvent.state_default) {
-          requiredLevel = plEvent.state_default;
-      }
-      if (plEvent && plEvent.users_default) {
-          userLevel = plEvent.users_default;
-      }
-      if (plEvent && plEvent.users && plEvent.users[event.sender]) {
-          userLevel = plEvent.users[event.sender];
-      }
-
-      if (userLevel < requiredLevel) {
-          return this.bridge.getIntent().sendMessage(event.room_id, {
-              msgtype: "m.notice",
-              body: "You do not have the required power level in this room to create a bridge to a Discord channel.",
-          });
-      }
-
-      const {command, args} = Util.MsgToArgs(event.content.body, "!discord");
-
-      if (command === "help" && args[0] === "bridge") {
-          const link = Util.GetBotLink(this.config);
-          return this.bridge.getIntent().sendMessage(event.room_id, {
-              msgtype: "m.notice",
-              body: "How to bridge a Discord guild:\n" +
-              "1. Invite the bot to your Discord guild using this link: " + link + "\n" +
-              "2. Invite me to the matrix room you'd like to bridge\n" +
-              "3. Open the Discord channel you'd like to bridge in a web browser\n" +
-              "4. In the matrix room, send the message `!discord bridge <guild id> <channel id>` " +
-              "(without the backticks)\n" +
-              "   Note: The Guild ID and Channel ID can be retrieved from the URL in your web browser.\n" +
-              "   The URL is formatted as https://discordapp.com/channels/GUILD_ID/CHANNEL_ID\n" +
-              "5. Enjoy your new bridge!",
-          });
-      } else if (command === "bridge") {
-          if (context.rooms.remote) {
-              return this.bridge.getIntent().sendMessage(event.room_id, {
-                  msgtype: "m.notice",
-                  body: "This room is already bridged to a Discord guild.",
-              });
-          }
-
-          const minArgs = 2;
-          if (args.length < minArgs) {
-              return this.bridge.getIntent().sendMessage(event.room_id, {
-                  msgtype: "m.notice",
-                  body: "Invalid syntax. For more information try !discord help bridge",
-              });
-          }
-
-          const guildId = args[0];
-          const channelId = args[1];
-          try {
-              const discordResult = await this.discord.LookupRoom(guildId, channelId);
-              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, {
-                  msgtype: "m.notice",
-                  body: "I'm asking permission from the guild administrators to make this bridge.",
-              });
-
-              await this.provisioner.AskBridgePermission(channel, event.sender);
-              this.provisioner.BridgeMatrixRoom(channel, event.room_id);
-              return this.bridge.getIntent().sendMessage(event.room_id, {
-                  msgtype: "m.notice",
-                  body: "I have bridged this room to your channel",
-              });
-          } catch (err) {
-              if (err.message === "Timed out waiting for a response from the Discord owners"
-                  || err.message === "The bridge has been declined by the Discord guild") {
-                  return this.bridge.getIntent().sendMessage(event.room_id, {
-                      msgtype: "m.notice",
-                      body: err.message,
-                  });
-              }
-
-              log.error(`Error bridging ${event.room_id} to ${guildId}/${channelId}`);
-              log.error(err);
-              return this.bridge.getIntent().sendMessage(event.room_id, {
-                  msgtype: "m.notice",
-                  body: "There was a problem bridging that channel - has the guild owner approved the bridge?",
-              });
-          }
-      } else if (command === "unbridge") {
-          const remoteRoom = context.rooms.remote;
-
-          if (!remoteRoom) {
-              return this.bridge.getIntent().sendMessage(event.room_id, {
-                  msgtype: "m.notice",
-                  body: "This room is not bridged.",
-              });
-          }
-
-          if (!remoteRoom.data.plumbed) {
-              return this.bridge.getIntent().sendMessage(event.room_id, {
-                  msgtype: "m.notice",
-                  body: "This room cannot be unbridged.",
-              });
-          }
-
-          try {
-              await this.provisioner.UnbridgeRoom(remoteRoom);
-              return this.bridge.getIntent().sendMessage(event.room_id, {
-                  msgtype: "m.notice",
-                  body: "This room has been unbridged",
-              });
-          } catch (err) {
-              log.error("Error while unbridging room " + event.room_id);
-              log.error(err);
-              return this.bridge.getIntent().sendMessage(event.room_id, {
-                  msgtype: "m.notice",
-                  body: "There was an error unbridging this room. " +
-                    "Please try again later or contact the bridge operator.",
-              });
-          }
-      } else if (command === "help") {
-          // Unknown command or no command given to get help on, so we'll just give them the help
-          return this.bridge.getIntent().sendMessage(event.room_id, {
-              msgtype: "m.notice",
-              body: "Available commands:\n" +
-              "!discord bridge <guild id> <channel id>   - Bridges this room to a Discord channel\n" +
-              "!discord unbridge                         - Unbridges a Discord channel from this room\n" +
-              "!discord help <command>                   - Help menu for another command. Eg: !discord help bridge\n",
-          });
-      }
-  }
-
-  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] === "") {
-      log.warn(`Alias '${aliasLocalpart}' was missing a server and/or a channel`);
-      return;
+
+    public tpGetLocation(protocol: string, fields: any): Promise<thirdPartyLocationResult[]> {
+        log.info("Got location request ", protocol, fields);
+        const chans = this.discord.ThirdpartySearchForChannels(fields.guild_id, fields.channel_name);
+        return Promise.resolve(chans);
     }
-    return this.discord.LookupRoom(srvChanPair[0], srvChanPair[1]).then((result) => {
-      log.info("Creating #", aliasLocalpart);
-      return this.createMatrixRoom(result.channel, aliasLocalpart);
-    }).catch((err) => {
-      log.error(`Couldn't find discord room '${aliasLocalpart}'.`, err);
-    });
-  }
-
-  public tpGetProtocol(protocol: string): Promise<thirdPartyProtocolResult> {
-    return Promise.resolve({
-      user_fields: ["username", "discriminator"],
-      location_fields: ["guild_id", "channel_name"],
-      field_types: {
-        // guild_name: {
-        //   regexp: "\S.{0,98}\S",
-        //   placeholder: "Guild",
-        // },
-        guild_id: {
-          regexp: "[0-9]*",
-          placeholder: "",
-        },
-        channel_id: {
-          regexp: "[0-9]*",
-          placeholder: "",
-        },
-        channel_name: {
-           regexp: "[A-Za-z0-9_\-]{2,100}",
-           placeholder: "#Channel",
-        },
-        username: {
-          regexp: "[A-Za-z0-9_\-]{2,100}",
-          placeholder: "Username",
-        },
-        discriminator: {
-          regexp: "[0-9]{4}",
-          placeholder: "1234",
-        },
-      },
-      instances: this.discord.GetGuilds().map((guild) => {
-        return {
-          network_id: guild.id,
-          bot_user_id: this.botUserId,
-          desc: guild.name,
-          icon: guild.iconURL || ICON_URL, // TODO: Use icons from our content repo. Potential security risk.
-          fields: {
-            guild_id: guild.id,
-          },
-        };
-      }),
-    });
-  }
-
-  public tpGetLocation(protocol: string, fields: any): Promise<thirdPartyLocationResult[]> {
-    log.info("Got location request ", protocol, fields);
-    const chans = this.discord.ThirdpartySearchForChannels(fields.guild_id, fields.channel_name);
-    return Promise.resolve(chans);
-  }
-
-  public tpParseLocation(alias: string): Promise<thirdPartyLocationResult[]>  {
-    return Promise.reject({err: "Unsupported", code: HTTP_UNSUPPORTED});
-  }
-
-  public tpGetUser(protocol: string, fields: any): Promise<thirdPartyUserResult[]> {
-    log.info("Got user request ", protocol, fields);
-    return Promise.reject({err: "Unsupported", code: HTTP_UNSUPPORTED});
-  }
-
-  public tpParseUser(userid: string): Promise<thirdPartyUserResult[]> {
-    return Promise.reject({err: "Unsupported", code: HTTP_UNSUPPORTED});
-  }
-
-  public async HandleDiscordCommand(msg: Discord.Message) {
-    if (!(msg.channel as Discord.TextChannel).guild) {
-      msg.channel.send("**ERROR:** only available for guild channels");
+
+    public tpParseLocation(alias: string): Promise<thirdPartyLocationResult[]>  {
+        return Promise.reject({err: "Unsupported", code: HTTP_UNSUPPORTED});
+    }
+
+    public tpGetUser(protocol: string, fields: any): Promise<thirdPartyUserResult[]> {
+        log.info("Got user request ", protocol, fields);
+        return Promise.reject({err: "Unsupported", code: HTTP_UNSUPPORTED});
     }
 
-    const {command, args} = Util.MsgToArgs(msg.content, "!matrix");
-
-    const intent = this.bridge.getIntent();
-
-    const actions: ICommandActions = {
-      kick: {
-        params: ["name"],
-        description: "Kicks a user on the matrix side",
-        permission: "KICK_MEMBERS",
-        run: this.DiscordModerationActionGenerator(msg.channel as Discord.TextChannel, "kick", "Kicked"),
-      },
-      ban: {
-        params: ["name"],
-        description: "Bans a user on the matrix side",
-        permission: "BAN_MEMBERS",
-        run: this.DiscordModerationActionGenerator(msg.channel as Discord.TextChannel, "ban", "Banned"),
-      },
-      unban: {
-        params: ["name"],
-        description: "Unbans a user on the matrix side",
-        permission: "BAN_MEMBERS",
-        run: this.DiscordModerationActionGenerator(msg.channel as Discord.TextChannel, "unban", "Unbanned"),
-      },
-    };
-
-    const parameters: ICommandParameters = {
-      name: {
-        description: "The display name or mxid of a matrix user",
-        get: async (name) => {
-          const channelMxids = await this.discord.ChannelSyncroniser.GetRoomIdsFromChannel(msg.channel);
-          const mxUserId = await Util.GetMxidFromName(intent, name, channelMxids);
-          return mxUserId;
-        },
-      },
-    };
-
-    if (command === "help") {
-      let replyMessage = "Available Commands:\n";
-      for (const actionKey of Object.keys(actions)) {
-        const action = actions[actionKey];
-        if (!msg.member.hasPermission(action.permission as any)) {
-          continue;
+    public tpParseUser(userid: string): Promise<thirdPartyUserResult[]> {
+        return Promise.reject({err: "Unsupported", code: HTTP_UNSUPPORTED});
+    }
+
+    public async HandleDiscordCommand(msg: Discord.Message) {
+        if (!(msg.channel as Discord.TextChannel).guild) {
+            msg.channel.send("**ERROR:** only available for guild channels");
         }
-        replyMessage += " - `!matrix " + actionKey;
-        for (const param of action.params) {
-          replyMessage += ` <${param}>`;
+
+        const {command, args} = Util.MsgToArgs(msg.content, "!matrix");
+
+        const intent = this.bridge.getIntent();
+
+        const actions: ICommandActions = {
+            ban: {
+                description: "Bans a user on the matrix side",
+                params: ["name"],
+                permission: "BAN_MEMBERS",
+                run: this.DiscordModerationActionGenerator(msg.channel as Discord.TextChannel, "ban", "Banned"),
+            },
+            kick: {
+                description: "Kicks a user on the matrix side",
+                params: ["name"],
+                permission: "KICK_MEMBERS",
+                run: this.DiscordModerationActionGenerator(msg.channel as Discord.TextChannel, "kick", "Kicked"),
+            },
+            unban: {
+                description: "Unbans a user on the matrix side",
+                params: ["name"],
+                permission: "BAN_MEMBERS",
+                run: this.DiscordModerationActionGenerator(msg.channel as Discord.TextChannel, "unban", "Unbanned"),
+            },
+        };
+
+        const parameters: ICommandParameters = {
+            name: {
+                description: "The display name or mxid of a matrix user",
+                get: async (name) => {
+                    const channelMxids = await this.discord.ChannelSyncroniser.GetRoomIdsFromChannel(msg.channel);
+                    const mxUserId = await Util.GetMxidFromName(intent, name, channelMxids);
+                    return mxUserId;
+                },
+            },
+        };
+
+        if (command === "help") {
+            let replyHelpMessage = "Available Commands:\n";
+            for (const actionKey of Object.keys(actions)) {
+                const action = actions[actionKey];
+                if (!msg.member.hasPermission(action.permission as any)) {
+                    continue;
+                }
+                replyHelpMessage += " - `!matrix " + actionKey;
+                for (const param of action.params) {
+                    replyHelpMessage += ` <${param}>`;
+                }
+                replyHelpMessage += "`: " + action.description + "\n";
+            }
+            replyHelpMessage += "\nParameters:\n";
+            for (const parameterKey of Object.keys(parameters)) {
+                const parameter = parameters[parameterKey];
+                replyHelpMessage += " - `<" + parameterKey + ">`: " + parameter.description + "\n";
+            }
+            msg.channel.send(replyHelpMessage);
+            return;
         }
-        replyMessage += "`: " + action.description + "\n";
-      }
-      replyMessage += "\nParameters:\n";
-      for (const parameterKey of Object.keys(parameters)) {
-        const parameter = parameters[parameterKey];
-        replyMessage += " - `<" + parameterKey + ">`: " + parameter.description + "\n";
-      }
-      msg.channel.send(replyMessage);
-      return;
-    }
 
-    if (!actions[command]) {
-      msg.channel.send("**Error:** unknown command. Try `!matrix help` to see all commands");
-      return;
+        if (!actions[command]) {
+            msg.channel.send("**Error:** unknown command. Try `!matrix help` to see all commands");
+            return;
+        }
+
+        if (!msg.member.hasPermission(actions[command].permission as any)) {
+            msg.channel.send("**ERROR:** insufficiant permissions to use this matrix command");
+            return;
+        }
+
+        let replyMessage = "";
+        try {
+            replyMessage = await Util.ParseCommand(actions[command], parameters, args);
+        } catch (e) {
+            replyMessage = "**ERROR:** " + e.message;
+        }
+
+        msg.channel.send(replyMessage);
     }
 
-    if (!msg.member.hasPermission(actions[command].permission as any)) {
-      msg.channel.send("**ERROR:** insufficiant permissions to use this matrix command");
-      return;
+    private DiscordModerationActionGenerator(discordChannel: Discord.TextChannel, funcKey: string, action: string) {
+        return async ({name}) => {
+            let allChannelMxids = [];
+            await Promise.all(discordChannel.guild.channels.map((chan) => {
+                return this.discord.ChannelSyncroniser.GetRoomIdsFromChannel(chan).then((chanMxids) => {
+                    allChannelMxids = allChannelMxids.concat(chanMxids);
+                }).catch((e) => {
+                    // pass, non-text-channel
+                });
+            }));
+            let errorMsg = "";
+            await Promise.all(allChannelMxids.map((chanMxid) => {
+                const intent = this.bridge.getIntent();
+                return intent[funcKey](chanMxid, name).catch((e) => {
+                    // maybe we don't have permission to kick/ban/unban...?
+                    errorMsg += `\nCouldn't ${funcKey} ${name} from ${chanMxid}`;
+                });
+            }));
+            if (errorMsg) {
+                throw Error(errorMsg);
+            }
+            return `${action} ${name}`;
+        };
     }
 
-    let replyMessage = "";
-    try {
-      replyMessage = await Util.ParseCommand(actions[command], parameters, args);
-    } catch (e) {
-      replyMessage = "**ERROR:** " + e.message;
+    private joinRoom(intent: any, roomIdOrAlias: string): Promise<string> {
+        let currentSchedule = JOIN_ROOM_SCHEDULE[0];
+        const doJoin = () => Util.DelayedPromise(currentSchedule)
+            .then(() => intent.getClient().joinRoom(roomIdOrAlias));
+        const errorHandler = (err) => {
+            log.error(`Error joining room ${roomIdOrAlias} as ${intent.getClient().getUserId()}`);
+            log.error(err);
+            const idx = JOIN_ROOM_SCHEDULE.indexOf(currentSchedule);
+            if (idx === JOIN_ROOM_SCHEDULE.length - 1) {
+                log.warn(`Cannot join ${roomIdOrAlias} as ${intent.getClient().getUserId()}`);
+                return Promise.reject(err);
+            } else {
+                currentSchedule = JOIN_ROOM_SCHEDULE[idx + 1];
+                return doJoin().catch(errorHandler);
+            }
+        };
+
+        return doJoin().catch(errorHandler);
     }
 
-    msg.channel.send(replyMessage);
-  }
-
-  private DiscordModerationActionGenerator(discordChannel: Discord.TextChannel, funcKey: string, action: string) {
-    return async ({name}) => {
-      let allChannelMxids = [];
-      await Promise.all(discordChannel.guild.channels.map((chan) => {
-        return this.discord.ChannelSyncroniser.GetRoomIdsFromChannel(chan).then((chanMxids) => {
-          allChannelMxids = allChannelMxids.concat(chanMxids);
-        }).catch((e) => {
-          // pass, non-text-channel
-        });
-      }));
-      let errorMsg = "";
-      await Promise.all(allChannelMxids.map((chanMxid) => {
-        const intent = this.bridge.getIntent();
-        return intent[funcKey](chanMxid, name).catch((e) => {
-          // maybe we don't have permission to kick/ban/unban...?
-          errorMsg += `\nCouldn't ${funcKey} ${name} from ${chanMxid}`;
-        });
-      }));
-      if (errorMsg) {
-        throw Error(errorMsg);
-      }
-      return `${action} ${name}`;
-    };
-  }
-
-  private joinRoom(intent: any, roomIdOrAlias: string): Promise<string> {
-      let currentSchedule = JOIN_ROOM_SCHEDULE[0];
-      const doJoin = () => Util.DelayedPromise(currentSchedule).then(() => intent.getClient().joinRoom(roomIdOrAlias));
-      const errorHandler = (err) => {
-          log.error(`Error joining room ${roomIdOrAlias} as ${intent.getClient().getUserId()}`);
-          log.error(err);
-          const idx = JOIN_ROOM_SCHEDULE.indexOf(currentSchedule);
-          if (idx === JOIN_ROOM_SCHEDULE.length - 1) {
-              log.warn(`Cannot join ${roomIdOrAlias} as ${intent.getClient().getUserId()}`);
-              return Promise.reject(err);
-          } else {
-              currentSchedule = JOIN_ROOM_SCHEDULE[idx + 1];
-              return doJoin().catch(errorHandler);
-          }
-      };
-
-      return doJoin().catch(errorHandler);
-  }
-
-  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);
-    remote.set("discord_channel", channel.id);
-    remote.set("update_name", true);
-    remote.set("update_topic", true);
-    remote.set("update_icon", true);
-    const creationOpts = {
-      visibility: this.config.room.defaultVisibility,
-      room_alias_name: alias,
-      initial_state: [
-        {
-          type: "m.room.join_rules",
-          content: {
-            join_rule: "public",
-          },
-          state_key: "",
-        },
-      ],
-    };
-    return {
-      creationOpts,
-      remote,
-    };
-  }
+    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);
+        remote.set("discord_channel", channel.id);
+        remote.set("update_name", true);
+        remote.set("update_topic", true);
+        remote.set("update_icon", true);
+        const creationOpts = {
+            initial_state: [
+                {
+                    content: {
+                        join_rule: "public",
+                    },
+                    state_key: "",
+                    type: "m.room.join_rules",
+                },
+            ],
+            room_alias_name: alias,
+            visibility: this.config.room.defaultVisibility,
+        };
+        return {
+            creationOpts,
+            remote,
+        };
+    }
 }
diff --git a/src/presencehandler.ts b/src/presencehandler.ts
index 88a6cc8ac74f206e263b327a43a75f8428fa551e..8e2c9964551bcd3c33073849361e66f7e40dbf37 100644
--- a/src/presencehandler.ts
+++ b/src/presencehandler.ts
@@ -1,4 +1,4 @@
-import {User, Presence} from "discord.js";
+import { User, Presence } from "discord.js";
 import { DiscordBot } from "./bot";
 import { Log } from "./log";
 const log = new Log("PresenceHandler");
diff --git a/src/provisioner.ts b/src/provisioner.ts
index c8a2e0d5cb559b0f79173f493058ca3979a381af..7bbb286f3c4dcf35b84259f0c1cae6d7079365ae 100644
--- a/src/provisioner.ts
+++ b/src/provisioner.ts
@@ -4,7 +4,6 @@ import {
     MatrixRoom,
 } from "matrix-appservice-bridge";
 import * as Discord from "discord.js";
-import { Permissions } from "discord.js";
 
 const PERMISSION_REQUEST_TIMEOUT = 300000; // 5 minutes
 
@@ -76,7 +75,7 @@ export class Provisioner {
         }
 
         const perms = channel.permissionsFor(member);
-        if (!perms.hasPermission(Permissions.FLAGS.MANAGE_WEBHOOKS)) {
+        if (!perms.hasPermission(Discord.Permissions.FLAGS.MANAGE_WEBHOOKS)) {
             // Missing permissions, so just reject it
             return Promise.reject(new Error("You do not have permission to manage webhooks in this channel"));
         }
diff --git a/src/store.ts b/src/store.ts
index 56769f9b5455b2370cd210ae25a70c7012423b94..5dc491c2efe674d283ec9042119fbb344db06f52 100644
--- a/src/store.ts
+++ b/src/store.ts
@@ -13,293 +13,293 @@ const log = new Log("DiscordStore");
  * Stores data for specific users and data not specific to rooms.
  */
 export class DiscordStore {
-  /**
-   * @param  {string} filepath Location of the SQLite database file.
-   */
-  public db: IDatabaseConnector;
-  private version: number;
-  private config: DiscordBridgeConfigDatabase;
-  constructor(private configOrFile: DiscordBridgeConfigDatabase|string) {
-    if (typeof(configOrFile) === "string") {
-        this.config = new DiscordBridgeConfigDatabase();
-        this.config.filename = configOrFile;
-    } else {
-        this.config = configOrFile;
+    /**
+     * @param  {string} filepath Location of the SQLite database file.
+     */
+    public db: IDatabaseConnector;
+    private version: number;
+    private config: DiscordBridgeConfigDatabase;
+    constructor(private configOrFile: DiscordBridgeConfigDatabase|string) {
+        if (typeof(configOrFile) === "string") {
+            this.config = new DiscordBridgeConfigDatabase();
+            this.config.filename = configOrFile;
+        } else {
+            this.config = configOrFile;
+        }
+        this.version = null;
     }
-    this.version = null;
-  }
 
-  public backup_database(): Promise<void|{}> {
-    if (this.config.filename == null) {
-        log.warn("Backups not supported on non-sqlite connector");
-        return;
-    }
-    if (this.config.filename === ":memory:") {
-      log.info("Can't backup a :memory: database.");
-      return Promise.resolve();
+    public backup_database(): Promise<void|{}> {
+        if (this.config.filename == null) {
+            log.warn("Backups not supported on non-sqlite connector");
+            return;
+        }
+        if (this.config.filename === ":memory:") {
+            log.info("Can't backup a :memory: database.");
+            return Promise.resolve();
+        }
+        const BACKUP_NAME = this.config.filename + ".backup";
+
+        return new Promise((resolve, reject) => {
+            // Check to see if a backup file already exists.
+            fs.access(BACKUP_NAME, (err) => {
+                return resolve(err === null);
+            });
+        }).then((result) => {
+            return new Promise((resolve, reject) => {
+                if (!result) {
+                    log.warn("NOT backing up database while a file already exists");
+                    resolve(true);
+                }
+                const rd = fs.createReadStream(this.config.filename);
+                rd.on("error", reject);
+                const wr = fs.createWriteStream(BACKUP_NAME);
+                wr.on("error", reject);
+                wr.on("close", resolve);
+                rd.pipe(wr);
+            });
+        });
     }
-    const BACKUP_NAME = this.config.filename + ".backup";
 
-    return new Promise((resolve, reject) => {
-      // Check to see if a backup file already exists.
-      fs.access(BACKUP_NAME, (err) => {
-        return resolve(err === null);
-      });
-    }).then((result) => {
-      return new Promise((resolve, reject) => {
-        if (!result) {
-          log.warn("NOT backing up database while a file already exists");
-          resolve(true);
+    /**
+     * Checks the database has all the tables needed.
+     */
+    public async init(overrideSchema: number = 0): Promise<void> {
+        log.info("Starting DB Init");
+        await this.open_database();
+        let version = await this.getSchemaVersion();
+        const targetSchema = overrideSchema || CURRENT_SCHEMA;
+        while (version < targetSchema) {
+            version++;
+            const schemaClass = require(`./db/schema/v${version}.js`).Schema;
+            const schema = (new schemaClass() as IDbSchema);
+            log.info(`Updating database to v${version}, "${schema.description}"`);
+            try {
+                await schema.run(this);
+                log.info("Updated database to version ", version);
+            } catch (ex) {
+                log.error("Couldn't update database to schema ", version);
+                log.error(ex);
+                log.info("Rolling back to version ", version - 1);
+                try {
+                    await schema.rollBack(this);
+                } catch (ex) {
+                    log.error(ex);
+                    throw Error("Failure to update to latest schema. And failed to rollback.");
+                }
+                throw Error("Failure to update to latest schema.");
+            }
+            this.version = version;
+            await this.setSchemaVersion(version);
         }
-        const rd = fs.createReadStream(this.config.filename);
-        rd.on("error", reject);
-        const wr = fs.createWriteStream(BACKUP_NAME);
-        wr.on("error", reject);
-        wr.on("close", resolve);
-        rd.pipe(wr);
-      });
-    });
-  }
+        log.info("Updated database to the latest schema");
+    }
 
-  /**
-   * Checks the database has all the tables needed.
-   */
-  public async init(overrideSchema: number = 0): Promise<void> {
-    log.info("Starting DB Init");
-    await this.open_database();
-    let version = await this.getSchemaVersion();
-    const targetSchema = overrideSchema || CURRENT_SCHEMA;
-    while (version < targetSchema) {
-      version++;
-      const schemaClass = require(`./db/schema/v${version}.js`).Schema;
-      const schema = (new schemaClass() as IDbSchema);
-      log.info(`Updating database to v${version}, "${schema.description}"`);
-      try {
-        await schema.run(this);
-        log.info("Updated database to version ", version);
-      } catch (ex) {
-        log.error("Couldn't update database to schema ", version);
-        log.error(ex);
-        log.info("Rolling back to version ", version - 1);
-        try {
-          await schema.rollBack(this);
-        } catch (ex) {
-          log.error(ex);
-          throw Error("Failure to update to latest schema. And failed to rollback.");
-        }
-        throw Error("Failure to update to latest schema.");
-      }
-      this.version = version;
-      await this.setSchemaVersion(version);
+    public close() {
+        this.db.Close();
+    }
+
+    public create_table(statement: string, tablename: string): Promise<void|Error> {
+        return this.db.Exec(statement).then(() => {
+            log.info("Created table", tablename);
+        }).catch((err) => {
+            throw new Error(`Error creating '${tablename}': ${err}`);
+        });
     }
-    log.info("Updated database to the latest schema");
-  }
 
-  public close() {
-    this.db.Close();
-  }
+    public add_user_token(userId: string, discordId: string, token: string): Promise<any> {
+        log.silly("SQL", "add_user_token => ", userId);
+        return Promise.all([
+            this.db.Run(
+              `
+              INSERT INTO user_id_discord_id (discord_id,user_id) VALUES ($discordId,$userId);
+              `
+            , {
+                discordId,
+                userId,
+            }),
+            this.db.Run(
+              `
+              INSERT INTO discord_id_token (discord_id,token) VALUES ($discordId,$token);
+              `
+            , {
+                discordId,
+                token,
+            }),
+        ]).catch( (err) => {
+            log.error("Error storing user token ", err);
+            throw err;
+        });
+    }
 
-  public create_table(statement: string, tablename: string): Promise<void|Error> {
-    return this.db.Exec(statement).then(() => {
-      log.info("Created table", tablename);
-    }).catch((err) => {
-      throw new Error(`Error creating '${tablename}': ${err}`);
-    });
-  }
+    public delete_user_token(discordId: string): Promise<null> {
+        log.silly("SQL", "delete_user_token => ", discordId);
+        return this.db.Run(
+            `
+            DELETE FROM user_id_discord_id WHERE discord_id = $id;
+            DELETE FROM discord_id_token WHERE discord_id = $id;
+            `
+        , {
+            $id: discordId,
+        }).catch( (err) => {
+            log.error("Error deleting user token ", err);
+            throw err;
+        });
+    }
 
-  public add_user_token(userId: string, discordId: string, token: string): Promise<any> {
-    log.silly("SQL", "add_user_token => ", userId);
-    return Promise.all([
-        this.db.Run(
-          `
-          INSERT INTO user_id_discord_id (discord_id,user_id) VALUES ($discordId,$userId);
-          `
+    public get_user_discord_ids(userId: string): Promise<string[]> {
+        log.silly("SQL", "get_user_discord_ids => ", userId);
+        return this.db.All(
+            `
+            SELECT discord_id
+            FROM user_id_discord_id
+            WHERE user_id = $userId;
+            `
         , {
             userId,
-            discordId,
-        }),
-        this.db.Run(
-          `
-          INSERT INTO discord_id_token (discord_id,token) VALUES ($discordId,$token);
-          `
+        }).then( (rows) => {
+            if (rows != null) {
+                return rows.map((row) => row.discord_id);
+            } else {
+                return [];
+            }
+        }).catch( (err) => {
+            log.error("Error getting discord ids: ", err.Error);
+            throw err;
+        });
+    }
+
+    public get_token(discordId: string): Promise<string> {
+        log.silly("SQL", "discord_id_token => ", discordId);
+        return this.db.Get(
+            `
+            SELECT token
+            FROM discord_id_token
+            WHERE discord_id = $discordId
+            `
         , {
             discordId,
-            token,
-        }),
-    ]).catch( (err) => {
-      log.error("Error storing user token ", err);
-      throw err;
-    });
-  }
-
-  public delete_user_token(discordId: string): Promise<null> {
-    log.silly("SQL", "delete_user_token => ", discordId);
-    return this.db.Run(
-      `
-      DELETE FROM user_id_discord_id WHERE discord_id = $id;
-      DELETE FROM discord_id_token WHERE discord_id = $id;
-      `
-    , {
-      $id: discordId,
-    }).catch( (err) => {
-      log.error("Error deleting user token ", err);
-      throw err;
-    });
-  }
-
-  public get_user_discord_ids(userId: string): Promise<string[]> {
-    log.silly("SQL", "get_user_discord_ids => ", userId);
-    return this.db.All(
-      `
-      SELECT discord_id
-      FROM user_id_discord_id
-      WHERE user_id = $userId;
-      `, {
-        userId,
-      },
-    ).then( (rows) => {
-      if (rows != null) {
-        return rows.map((row) => row.discord_id);
-      } else {
-        return [];
-      }
-    }).catch( (err) => {
-      log.error("Error getting discord ids: ", err.Error);
-      throw err;
-    });
-  }
-
-  public get_token(discordId: string): Promise<string> {
-    log.silly("SQL", "discord_id_token => ", discordId);
-    return this.db.Get(
-      `
-      SELECT token
-      FROM discord_id_token
-      WHERE discord_id = $discordId
-      `, {
-        discordId,
-      },
-    ).then( (row) => {
-      return row != null ? row.token : null;
-    }).catch( (err) => {
-      log.error("Error getting discord ids ", err.Error);
-      throw err;
-    });
-  }
-
-  public get_dm_room(discordId, discordChannel): Promise<string> {
-    log.silly("SQL", "get_dm_room => ", discordChannel); // Don't show discordId for privacy reasons
-    return this.db.Get(
-      `
-      SELECT room_id
-      FROM dm_rooms
-      WHERE dm_rooms.discord_id = $discordId
-      AND dm_rooms.discord_channel = $discordChannel;
-      `
-    , {
-      discordId,
-      discordChannel,
-    }).then( (row) => {
-      return row != null ? row.room_id : null;
-    }).catch( (err) => {
-      log.error("Error getting room_id ", err.Error);
-      throw err;
-    });
-  }
+        }).then( (row) => {
+            return row != null ? row.token : null;
+        }).catch( (err) => {
+            log.error("Error getting discord ids ", err.Error);
+            throw err;
+        });
+    }
 
-  public set_dm_room(discordId, discordChannel, roomId): Promise<null> {
-    log.silly("SQL", "set_dm_room => ", discordChannel); // Don't show discordId for privacy reasons
-    return this.db.Run(
-      `
-      REPLACE INTO dm_rooms (discord_id,discord_channel,room_id)
-      VALUES ($discordId,$discordChannel,$roomId);
-      `
-    , {
-      discordId,
-      discordChannel,
-      roomId,
-    }).catch( (err) => {
-      log.error("Error executing set_dm_room query  ", err.Error);
-      throw err;
-    });
-  }
+    public get_dm_room(discordId, discordChannel): Promise<string> {
+        log.silly("SQL", "get_dm_room => ", discordChannel); // Don't show discordId for privacy reasons
+        return this.db.Get(
+            `
+            SELECT room_id
+            FROM dm_rooms
+            WHERE dm_rooms.discord_id = $discordId
+            AND dm_rooms.discord_channel = $discordChannel;
+            `
+        , {
+            discordChannel,
+            discordId,
+        }).then( (row) => {
+            return row != null ? row.room_id : null;
+        }).catch( (err) => {
+            log.error("Error getting room_id ", err.Error);
+            throw err;
+        });
+    }
 
-  public get_all_user_discord_ids(): Promise<any> {
-    log.silly("SQL", "get_users_tokens");
-    return this.db.All(
-      `
-      SELECT *
-      FROM get_user_discord_ids
-      `,
-    ).then( (rows) => {
-      return rows;
-    }).catch( (err) => {
-      log.error("Error getting user token  ", err.Error);
-      throw err;
-    });
-  }
+    public set_dm_room(discordId, discordChannel, roomId): Promise<null> {
+        log.silly("SQL", "set_dm_room => ", discordChannel); // Don't show discordId for privacy reasons
+        return this.db.Run(
+            `
+            REPLACE INTO dm_rooms (discord_id,discord_channel,room_id)
+            VALUES ($discordId,$discordChannel,$roomId);
+            `
+        , {
+            discordChannel,
+            discordId,
+            roomId,
+        }).catch( (err) => {
+            log.error("Error executing set_dm_room query  ", err.Error);
+            throw err;
+        });
+    }
 
-  public Get<T extends IDbData>(dbType: {new(): T; }, params: any): Promise<T|null> {
-      const dType = new dbType();
-      log.silly(`get <${dType.constructor.name} with params ${params}>`);
-      return dType.RunQuery(this, params).then(() => {
-          log.silly(`Finished query with ${dType.Result ? "Results" : "No Results"}`);
-          return dType;
-      }).catch((ex) => {
-          log.warn(`get <${dType.constructor.name} with params ${params} FAILED with exception ${ex}>`);
-          return null;
-      });
-  }
+    public get_all_user_discord_ids(): Promise<any> {
+        log.silly("SQL", "get_users_tokens");
+        return this.db.All(
+            `
+            SELECT *
+            FROM get_user_discord_ids
+            `,
+        ).then( (rows) => {
+            return rows;
+        }).catch( (err) => {
+            log.error("Error getting user token  ", err.Error);
+            throw err;
+        });
+    }
 
-  public Insert<T extends IDbData>(data: T): Promise<Error> {
-      log.silly(`insert <${data.constructor.name}>`);
-      return data.Insert(this);
-  }
+    public Get<T extends IDbData>(dbType: {new(): T; }, params: any): Promise<T|null> {
+        const dType = new dbType();
+        log.silly(`get <${dType.constructor.name} with params ${params}>`);
+        return dType.RunQuery(this, params).then(() => {
+            log.silly(`Finished query with ${dType.Result ? "Results" : "No Results"}`);
+            return dType;
+        }).catch((ex) => {
+            log.warn(`get <${dType.constructor.name} with params ${params} FAILED with exception ${ex}>`);
+            return null;
+        });
+    }
 
-  public Update<T extends IDbData>(data: T): Promise<Error>  {
-      log.silly(`insert <${data.constructor.name}>`);
-      return data.Update(this);
-  }
+    public Insert<T extends IDbData>(data: T): Promise<Error> {
+        log.silly(`insert <${data.constructor.name}>`);
+        return data.Insert(this);
+    }
 
-  public Delete<T extends IDbData>(data: T): Promise<Error>  {
-      log.silly(`insert <${data.constructor.name}>`);
-      return data.Delete(this);
-  }
+    public Update<T extends IDbData>(data: T): Promise<Error>  {
+        log.silly(`insert <${data.constructor.name}>`);
+        return data.Update(this);
+    }
 
-  private async getSchemaVersion( ): Promise<number> {
-    log.silly("_get_schema_version");
-    let version = 0;
-    try {
-        version = await this.db.Get(`SELECT version FROM schema`);
-    } catch (er) {
-        log.warn("Couldn't fetch schema version, defaulting to 0");
+    public Delete<T extends IDbData>(data: T): Promise<Error>  {
+        log.silly(`insert <${data.constructor.name}>`);
+        return data.Delete(this);
     }
-    return version;
-  }
 
-  private setSchemaVersion(ver: number): Promise<any> {
-    log.silly("_set_schema_version => ", ver);
-    return this.db.Run(
-      `
-      UPDATE schema
-      SET version = $ver
-      `, {ver},
-    );
-  }
+    private async getSchemaVersion( ): Promise<number> {
+        log.silly("_get_schema_version");
+        let version = 0;
+        try {
+            version = await this.db.Get(`SELECT version FROM schema`);
+        } catch (er) {
+            log.warn("Couldn't fetch schema version, defaulting to 0");
+        }
+        return version;
+    }
 
-  private async open_database(): Promise<void|Error> {
-    if (this.config.filename) {
-        log.info("Filename present in config, using sqlite");
-        this.db = new SQLite3(this.config.filename);
-    } else if (this.config.connString) {
-        log.info("connString present in config, using postgres");
-        this.db = new Postgres(this.config.connString);
+    private setSchemaVersion(ver: number): Promise<any> {
+        log.silly("_set_schema_version => ", ver);
+        return this.db.Run(
+            `
+            UPDATE schema
+            SET version = $ver
+            `, {ver},
+        );
     }
-    try {
-        this.db.Open();
-    } catch (ex) {
-      log.error("Error opening database:", ex);
-      throw new Error("Couldn't open database. The appservice won't be able to continue.");
+
+    private async open_database(): Promise<void|Error> {
+        if (this.config.filename) {
+            log.info("Filename present in config, using sqlite");
+            this.db = new SQLite3(this.config.filename);
+        } else if (this.config.connString) {
+            log.info("connString present in config, using postgres");
+            this.db = new Postgres(this.config.connString);
+        }
+        try {
+            this.db.Open();
+        } catch (ex) {
+            log.error("Error opening database:", ex);
+            throw new Error("Couldn't open database. The appservice won't be able to continue.");
+        }
     }
-  }
 }
diff --git a/src/usersyncroniser.ts b/src/usersyncroniser.ts
index d91101abedfd800ba9824b2f75d7acb9169dd5b4..5724752ac19bf7799d16fc6bc7d73e1ed1047b68 100644
--- a/src/usersyncroniser.ts
+++ b/src/usersyncroniser.ts
@@ -1,37 +1,37 @@
-import {User, GuildMember, GuildChannel} from "discord.js";
+import { User, GuildMember, GuildChannel } from "discord.js";
 import { DiscordBot } from "./bot";
-import {Util} from "./util";
+import { Util } from "./util";
 import { MatrixUser, RemoteUser, Bridge, Entry, UserBridgeStore } from "matrix-appservice-bridge";
-import {DiscordBridgeConfig} from "./config";
+import { DiscordBridgeConfig } from "./config";
 import * as Bluebird from "bluebird";
-import {Log} from "./log";
+import { Log } from "./log";
 
 const log = new Log("UserSync");
 
 const DEFAULT_USER_STATE = {
-    id: null,
+    avatarId: null,
+    avatarUrl: null, // Nullable
     createUser: false,
-    mxUserId: null,
     displayName: null, // Nullable
-    avatarUrl: null, // Nullable
-    avatarId: null,
+    id: null,
+    mxUserId: null,
     removeAvatar: false,
 };
 
 const DEFAULT_GUILD_STATE = {
+    displayName: null,
     id: null,
     mxUserId: null,
-    displayName: null,
     roles: [],
 };
 
 export interface IUserState {
-    id: string;
+    avatarId: string;
+    avatarUrl: string; // Nullable
     createUser: boolean;
-    mxUserId: string;
     displayName: string; // Nullable
-    avatarUrl: string; // Nullable
-    avatarId: string;
+    id: string;
+    mxUserId: string;
     removeAvatar: boolean; // If the avatar has been removed from the user.
 }
 
@@ -42,9 +42,9 @@ export interface IGuildMemberRole {
 }
 
 export interface IGuildMemberState {
+    displayName: string;
     id: string;
     mxUserId: string;
-    displayName: string;
     roles: IGuildMemberRole[];
 }
 
@@ -154,9 +154,9 @@ export class UserSyncroniser {
         /* The intent class tries to be smart and deny a state update for <PL50 users.
            Obviously a user can change their own state so we use the client instead. */
         const tryState = () => intent.getClient().sendStateEvent(roomId, "m.room.member", {
-            "membership": "join",
             "avatar_url": remoteUser.get("avatarurl_mxc"),
             "displayname": memberState.displayName,
+            "membership": "join",
             "uk.half-shot.discord.member": {
                 id: memberState.id,
                 roles: memberState.roles,
@@ -228,8 +228,8 @@ export class UserSyncroniser {
             id: newMember.id,
             mxUserId: `@_discord_${newMember.id}:${this.config.bridge.domain}`,
             roles: newMember.roles.map((role) => { return {
-                name: role.name,
                 color: role.color,
+                name: role.name,
                 position: role.position,
             }; }),
         });
diff --git a/src/util.ts b/src/util.ts
index ccc3b289e151d716ce06ee0a117321210f02fce6..c3f226a3ee4eb19194b0ec80a9992e093d5dc876 100644
--- a/src/util.ts
+++ b/src/util.ts
@@ -11,247 +11,246 @@ import { Log } from "./log";
 const log = new Log("Util");
 
 export interface ICommandAction {
-  params: string[];
-  description?: string;
-  permission?: string;
-  run(params: any): Promise<any>;
+    params: string[];
+    description?: string;
+    permission?: string;
+    run(params: any): Promise<any>;
 }
 
 export interface ICommandActions {
-  [index: string]: ICommandAction;
+    [index: string]: ICommandAction;
 }
 
 export interface ICommandParameter {
-  description?: string;
-  get(param: string): Promise<any>;
+    description?: string;
+    get(param: string): Promise<any>;
 }
 
 export interface ICommandParameters {
-  [index: string]: ICommandParameter;
+    [index: string]: ICommandParameter;
 }
 
 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> {
+        return new Promise((resolve, reject) => {
+            let ht;
+            if (url.startsWith("https")) {
+                ht = https;
+            } else {
+                ht = http;
+            }
+            const req = ht.get((url), (res) => {
+                let buffer = Buffer.alloc(0);
+                if (res.statusCode !== HTTP_OK) {
+                    reject(`Non 200 status code (${res.statusCode})`);
+                }
 
-  /**
-   * downloadFile - This function will take a URL and store the resulting data into
-   * a buffer.
-   */
-  public static DownloadFile(url: string): Promise<Buffer> {
-    return new Promise((resolve, reject) => {
-      let ht;
-      if (url.startsWith("https")) {
-        ht = https;
-      } else {
-        ht = http;
-      }
-      const req = ht.get((url), (res) => {
-        let buffer = Buffer.alloc(0);
-        if (res.statusCode !== HTTP_OK) {
-          reject(`Non 200 status code (${res.statusCode})`);
-        }
+                res.on("data", (d) => {
+                    buffer = Buffer.concat([buffer, d]);
+                });
 
-        res.on("data", (d) => {
-          buffer = Buffer.concat([buffer, d]);
+                res.on("end", () => {
+                    resolve(buffer);
+                });
+            });
+            req.on("error", (err) => {
+                reject(`Failed to download. ${err.code}`);
+            });
         });
+    }
+    /**
+     * 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> {
+        let contenttype;
+        let size;
+        name = name || null;
+        return new Promise((resolve, reject) => {
+            let ht;
+            if (url.startsWith("https")) {
+                ht = https;
+            } else {
+                ht = http;
+            }
+            const req = ht.get( url, (res) => {
+                let buffer = Buffer.alloc(0);
 
-        res.on("end", () => {
-          resolve(buffer);
-        });
-      });
-      req.on("error", (err) => {
-        reject(`Failed to download. ${err.code}`);
-      });
-    });
-  }
-  /**
-   * 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> {
-    let contenttype;
-    let size;
-    name = name || null;
-    return new Promise((resolve, reject) => {
-      let ht;
-      if (url.startsWith("https")) {
-        ht = https;
-      } else {
-        ht = http;
-      }
-      const req = ht.get( url, (res) => {
-        let buffer = Buffer.alloc(0);
+                if (res.headers.hasOwnProperty("content-type")) {
+                    contenttype = res.headers["content-type"];
+                } else {
+                    log.verbose("No content-type given by server, guessing based on file name.");
+                    contenttype = mime.lookup(url);
+                }
 
-        if (res.headers.hasOwnProperty("content-type")) {
-          contenttype = res.headers["content-type"];
-        } else {
-          log.verbose("No content-type given by server, guessing based on file name.");
-          contenttype = mime.lookup(url);
-        }
+                if (name === null) {
+                    const names = url.split("/");
+                    name = names[names.length - 1];
+                }
 
-        if (name === null) {
-          const names = url.split("/");
-          name = names[names.length - 1];
-        }
+                res.on("data", (d) => {
+                    buffer = Buffer.concat([buffer, d]);
+                });
 
-        res.on("data", (d) => {
-          buffer = Buffer.concat([buffer, d]);
+                res.on("end", () => {
+                    resolve(buffer);
+                });
+            });
+            req.on("error", (err) => {
+                reject(`Failed to download. ${err.code}`);
+            });
+        }).then((buffer: Buffer) => {
+            size = buffer.length;
+            return intent.getClient().uploadContent(buffer, {
+                name,
+                onlyContentUri: true,
+                rawResponse: false,
+                type: contenttype,
+            });
+        }).then((contentUri) => {
+            log.verbose("Media uploaded to ", contentUri);
+            return {
+                mxcUrl: contentUri,
+                size,
+            };
+        }).catch((reason) => {
+            log.error("Failed to upload content:\n", reason);
+            throw reason;
         });
+    }
 
-        res.on("end", () => {
-          resolve(buffer);
+    /**
+     * Gets a promise that will resolve after the given number of milliseconds
+     * @param {number} duration The number of milliseconds to wait
+     * @returns {Promise<any>} The promise
+     */
+    public static DelayedPromise(duration: number): Promise<any> {
+        return new Promise<any>((resolve, reject) => {
+            setTimeout(resolve, duration);
         });
-      });
-      req.on("error", (err) => {
-        reject(`Failed to download. ${err.code}`);
-      });
-    }).then((buffer: Buffer) => {
-      size = buffer.length;
-      return intent.getClient().uploadContent(buffer, {
-        name,
-        type: contenttype,
-        onlyContentUri: true,
-        rawResponse: false,
-      });
-    }).then((contentUri) => {
-      log.verbose("Media uploaded to ", contentUri);
-      return {
-        mxcUrl: contentUri,
-        size,
-      };
-    }).catch((reason) => {
-      log.error("Failed to upload content:\n", reason);
-      throw reason;
-    });
-  }
-
-  /**
-   * Gets a promise that will resolve after the given number of milliseconds
-   * @param {number} duration The number of milliseconds to wait
-   * @returns {Promise<any>} The promise
-   */
-  public static DelayedPromise(duration: number): Promise<any> {
-    return new Promise<any>((resolve, reject) => {
-      setTimeout(resolve, duration);
-    });
-  }
-
-  public static GetBotLink(config: any): string {
-    /* tslint:disable:no-bitwise */
-    const perms = Permissions.FLAGS.READ_MESSAGES |
-      Permissions.FLAGS.SEND_MESSAGES |
-      Permissions.FLAGS.CHANGE_NICKNAME |
-      Permissions.FLAGS.CONNECT |
-      Permissions.FLAGS.SPEAK |
-      Permissions.FLAGS.EMBED_LINKS |
-      Permissions.FLAGS.ATTACH_FILES |
-      Permissions.FLAGS.READ_MESSAGE_HISTORY |
-      Permissions.FLAGS.MANAGE_WEBHOOKS |
-      Permissions.FLAGS.MANAGE_MESSAGES;
-    /* tslint:enable:no-bitwise */
+    }
 
-    const clientId = config.auth.clientID;
+    public static GetBotLink(config: any): string {
+        /* tslint:disable:no-bitwise */
+        const perms = Permissions.FLAGS.READ_MESSAGES |
+            Permissions.FLAGS.SEND_MESSAGES |
+            Permissions.FLAGS.CHANGE_NICKNAME |
+            Permissions.FLAGS.CONNECT |
+            Permissions.FLAGS.SPEAK |
+            Permissions.FLAGS.EMBED_LINKS |
+            Permissions.FLAGS.ATTACH_FILES |
+            Permissions.FLAGS.READ_MESSAGE_HISTORY |
+            Permissions.FLAGS.MANAGE_WEBHOOKS |
+            Permissions.FLAGS.MANAGE_MESSAGES;
+        /* tslint:enable:no-bitwise */
 
-    return `https://discordapp.com/api/oauth2/authorize?client_id=${clientId}&scope=bot&permissions=${perms}`;
-  }
+        const clientId = config.auth.clientID;
 
-  public static async GetMxidFromName(intent: Intent, name: string, channelMxids: string[]) {
-    if (name[0] === "@" && name.includes(":")) {
-        return name;
-    }
-    const client = intent.getClient();
-    const matrixUsers = {};
-    let matches = 0;
-    await Promise.all(channelMxids.map((chan) => {
-      // we would use this.bridge.getBot().getJoinedMembers()
-      // but we also want to be able to search through banned members
-      // so we gotta roll our own thing
-      return client._http.authedRequestWithPrefix(
-        undefined,
-        "GET",
-        "/rooms/" + encodeURIComponent(chan) + "/members",
-        undefined,
-        undefined,
-        "/_matrix/client/r0",
-      ).then((res) => {
-        res.chunk.forEach((member) => {
-          if (member.membership !== "join" && member.membership !== "ban") {
-            return;
-          }
-          const mxid = member.state_key;
-          if (mxid.startsWith("@_discord_")) {
-            return;
-          }
-          let displayName = member.content.displayname;
-          if (!displayName && member.unsigned && member.unsigned.prev_content &&
-            member.unsigned.prev_content.displayname) {
-            displayName = member.unsigned.prev_content.displayname;
-          }
-          if (!displayName) {
-            displayName = mxid.substring(1, mxid.indexOf(":"));
-          }
-          if (name.toLowerCase() === displayName.toLowerCase() || name === mxid) {
-            matrixUsers[mxid] = displayName;
-            matches++;
-          }
-        });
-      });
-    }));
-    if (matches === 0) {
-      throw Error(`No users matching ${name} found`);
+        return `https://discordapp.com/api/oauth2/authorize?client_id=${clientId}&scope=bot&permissions=${perms}`;
     }
-    if (matches > 1) {
-      let errStr = "Multiple matching users found:\n";
-      for (const mxid of Object.keys(matrixUsers)) {
-        errStr += `${matrixUsers[mxid]} (\`${mxid}\`)\n`;
-      }
-      throw Error(errStr);
-    }
-    return Object.keys(matrixUsers)[0];
-  }
 
-  public static async ParseCommand(action: ICommandAction, parameters: ICommandParameters, args: string[]) {
-    if (action.params.length === 1) {
-      args[0] = args.join(" ");
-    }
-    const params = {};
-    let i = 0;
-    for (const param of action.params) {
-      params[param] = await parameters[param].get(args[i]);
-      i++;
+    public static async GetMxidFromName(intent: Intent, name: string, channelMxids: string[]) {
+        if (name[0] === "@" && name.includes(":")) {
+            return name;
+        }
+        const client = intent.getClient();
+        const matrixUsers = {};
+        let matches = 0;
+        await Promise.all(channelMxids.map((chan) => {
+            // we would use this.bridge.getBot().getJoinedMembers()
+            // but we also want to be able to search through banned members
+            // so we gotta roll our own thing
+            return client._http.authedRequestWithPrefix(
+                undefined,
+                "GET",
+                "/rooms/" + encodeURIComponent(chan) + "/members",
+                undefined,
+                undefined,
+                "/_matrix/client/r0",
+            ).then((res) => {
+                res.chunk.forEach((member) => {
+                    if (member.membership !== "join" && member.membership !== "ban") {
+                        return;
+                    }
+                    const mxid = member.state_key;
+                    if (mxid.startsWith("@_discord_")) {
+                        return;
+                    }
+                    let displayName = member.content.displayname;
+                    if (!displayName && member.unsigned && member.unsigned.prev_content &&
+                        member.unsigned.prev_content.displayname) {
+                        displayName = member.unsigned.prev_content.displayname;
+                    }
+                    if (!displayName) {
+                        displayName = mxid.substring(1, mxid.indexOf(":"));
+                    }
+                    if (name.toLowerCase() === displayName.toLowerCase() || name === mxid) {
+                        matrixUsers[mxid] = displayName;
+                        matches++;
+                    }
+                });
+            });
+        }));
+        if (matches === 0) {
+            throw Error(`No users matching ${name} found`);
+        }
+        if (matches > 1) {
+            let errStr = "Multiple matching users found:\n";
+            for (const mxid of Object.keys(matrixUsers)) {
+                errStr += `${matrixUsers[mxid]} (\`${mxid}\`)\n`;
+            }
+            throw Error(errStr);
+        }
+        return Object.keys(matrixUsers)[0];
     }
 
-    const retStr = await action.run(params);
-    return retStr;
-  }
+    public static async ParseCommand(action: ICommandAction, parameters: ICommandParameters, args: string[]) {
+        if (action.params.length === 1) {
+            args[0] = args.join(" ");
+        }
+        const params = {};
+        let i = 0;
+        for (const param of action.params) {
+            params[param] = await parameters[param].get(args[i]);
+            i++;
+        }
+
+        const retStr = await action.run(params);
+        return retStr;
+    }
 
-  public static MsgToArgs(msg: string, prefix: string) {
-    prefix += " ";
-    let command = "help";
-    let args = [];
-    if (msg.length >= prefix.length) {
-        const allArgs = msg.substring(prefix.length).split(" ");
-        if (allArgs.length && allArgs[0] !== "") {
-            command = allArgs[0];
-            allArgs.splice(0, 1);
-            args = allArgs;
+    public static MsgToArgs(msg: string, prefix: string) {
+        prefix += " ";
+        let command = "help";
+        let args = [];
+        if (msg.length >= prefix.length) {
+            const allArgs = msg.substring(prefix.length).split(" ");
+            if (allArgs.length && allArgs[0] !== "") {
+                command = allArgs[0];
+                allArgs.splice(0, 1);
+                args = allArgs;
+            }
         }
+        return {command, args};
     }
-    return {command, args};
-  }
 
-  public static GetReplyFromReplyBody(body: string) {
-      const lines = body.split("\n");
-      while (lines[0].startsWith("> ") || lines[0].trim().length === 0) {
-          lines.splice(0, 1);
-          if (lines.length === 0) {
-              return "";
-          }
-      }
-      return lines.join("\n").trim();
-  }
+    public static GetReplyFromReplyBody(body: string) {
+        const lines = body.split("\n");
+        while (lines[0].startsWith("> ") || lines[0].trim().length === 0) {
+            lines.splice(0, 1);
+            if (lines.length === 0) {
+                return "";
+            }
+        }
+        return lines.join("\n").trim();
+    }
 }
 
 interface IUploadResult {
-  mxcUrl: string;
-  size: number;
+    mxcUrl: string;
+    size: number;
 }
diff --git a/test/config.ts b/test/config.ts
index cba8b315bc53f11a180327733e313476f7976ea0..12cd897f25bf3240306be2559b30a9271a3ed35f 100644
--- a/test/config.ts
+++ b/test/config.ts
@@ -1,6 +1,9 @@
 import {argv} from "process";
 import {Log} from "../src/log";
 
+// we are a test file and thus need those
+/* tslint:disable:no-unused-expression max-file-line-count */
+
 if (!argv.includes("--noisy")) {
     Log.ForceSilent();
 }
diff --git a/test/mocks/collection.ts b/test/mocks/collection.ts
index c02d9c8055a072ae436ea974c57c8b81168c8d08..1dd67428eaca64ac15e9374d23923d953dca57f6 100644
--- a/test/mocks/collection.ts
+++ b/test/mocks/collection.ts
@@ -1,11 +1,11 @@
 import { Collection } from "discord.js";
 
 export class MockCollection<T1, T2> extends Collection<T1, T2> {
-  public array(): T2[] {
-    return [...this.values()];
-  }
+    public array(): T2[] {
+        return [...this.values()];
+    }
 
-  public keyArray(): T1[] {
-    return [...this.keys()];
-  }
+    public keyArray(): T1[] {
+        return [...this.keys()];
+    }
 }
diff --git a/test/mocks/discordclient.ts b/test/mocks/discordclient.ts
index 20da7ba2e72ef8d2dcbb5b801e2b5acfcce10b44..21e152f4d400d03c24a42639022dff5f3f8cf85f 100644
--- a/test/mocks/discordclient.ts
+++ b/test/mocks/discordclient.ts
@@ -4,51 +4,53 @@ 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, (...data: any[]) => void> = new Map();
+    public guilds = new MockCollection<string, MockGuild>();
+    public user: MockUser;
+    private testLoggedIn: boolean = false;
+    private testCallbacks: Map<string, (...data: any[]) => void> = new Map();
 
-  constructor() {
-    const channels = [
-      {
-        id: "321",
-        name: "achannel",
-        type: "text",
-      }, {
-        id: "654",
-        name: "a-channel",
-        type: "text",
-      }, {
-        id: "987",
-        name: "a channel",
-        type: "text",
-      },
-    ];
-    this.guilds.set("123", new MockGuild("MyGuild", channels));
-    this.guilds.set("456", new MockGuild("My Spaces Gui", channels));
-    this.guilds.set("789", new MockGuild("My Dash-Guild", channels));
-    this.user = new MockUser("12345");
-  }
-
-  public on(event: string, callback: (...data: any[]) => void) {
-      this.testCallbacks.set(event, callback);
-  }
+    constructor() {
+        const channels = [
+            {
+                id: "321",
+                name: "achannel",
+                type: "text",
+            },
+            {
+                id: "654",
+                name: "a-channel",
+                type: "text",
+            },
+            {
+                id: "987",
+                name: "a channel",
+                type: "text",
+            },
+        ];
+        this.guilds.set("123", new MockGuild("MyGuild", channels));
+        this.guilds.set("456", new MockGuild("My Spaces Gui", channels));
+        this.guilds.set("789", new MockGuild("My Dash-Guild", channels));
+        this.user = new MockUser("12345");
+    }
 
-  public emit(event: string, ...data: any[]) {
-      return this.testCallbacks.get(event).apply(this, data);
-  }
+    public on(event: string, callback: (...data: any[]) => void) {
+        this.testCallbacks.set(event, callback);
+    }
 
-  public async login(token: string): Promise<void> {
-    if (token !== "passme") {
-        throw new Error("Mock Discord Client only logins with the token 'passme'");
+    public emit(event: string, ...data: any[]) {
+        return this.testCallbacks.get(event).apply(this, data);
     }
-    this.testLoggedIn = true;
-    if (this.testCallbacks.has("ready")) {
-        this.testCallbacks.get("ready")();
+
+    public async login(token: string): Promise<void> {
+        if (token !== "passme") {
+            throw new Error("Mock Discord Client only logins with the token 'passme'");
+        }
+        this.testLoggedIn = true;
+        if (this.testCallbacks.has("ready")) {
+            this.testCallbacks.get("ready")();
+        }
+        return;
     }
-    return;
-  }
 
-  public destroy() { } // no-op
+    public destroy() { } // no-op
 }
diff --git a/test/mocks/discordclientfactory.ts b/test/mocks/discordclientfactory.ts
index 489adba780b375bbdae808026258095a0a089ef0..a09e08e0d70f76da480f77ef0a3058977d3ed7e6 100644
--- a/test/mocks/discordclientfactory.ts
+++ b/test/mocks/discordclientfactory.ts
@@ -1,19 +1,19 @@
 import {MockDiscordClient} from "./discordclient";
 
 export class DiscordClientFactory {
-  private botClient: MockDiscordClient = null;
-  constructor(config: any, store: any) {
-    
-  }
+    private botClient: MockDiscordClient = null;
+    constructor(config: any, store: any) {
 
-  public init(): Promise<void> {
-    return Promise.resolve();
-  }
+    }
+
+    public init(): Promise<void> {
+      return Promise.resolve();
+    }
 
-  public getClient(userId?: string): Promise<MockDiscordClient> {
-    if (userId == null && !this.botClient) {
-        this.botClient = new MockDiscordClient();
+    public getClient(userId?: string): Promise<MockDiscordClient> {
+        if (userId == null && !this.botClient) {
+            this.botClient = new MockDiscordClient();
+        }
+        return Promise.resolve(this.botClient);
     }
-    return Promise.resolve(this.botClient);
-  }
 }
diff --git a/test/mocks/emoji.ts b/test/mocks/emoji.ts
index c02734bdcce767512d9b2df8d2bb77b2830efd48..222db143abfbfc98124024714fc81771517b6dd2 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/mocks/guild.ts b/test/mocks/guild.ts
index bc0b625c05255619fad2ea3847a1036d6378ff20..7365691a0618fe54cf374e804143559ea6175bde 100644
--- a/test/mocks/guild.ts
+++ b/test/mocks/guild.ts
@@ -4,28 +4,28 @@ import {MockEmoji} from "./emoji";
 import {Channel} from "discord.js";
 
 export class MockGuild {
-  public channels = new MockCollection<string, Channel>();
-  public members = new MockCollection<string, MockMember>();
-  public emojis = new MockCollection<string, MockEmoji>();
-  public id: string;
-  public name: string;
-  public icon: string;
-  constructor(id: string, channels: any[] = [], name: string = null) {
-    this.id = id;
-    this.name = name || id;
-    channels.forEach((item) => {
-      this.channels.set(item.id, item);
-    });
-  }
+    public channels = new MockCollection<string, Channel>();
+    public members = new MockCollection<string, MockMember>();
+    public emojis = new MockCollection<string, MockEmoji>();
+    public id: string;
+    public name: string;
+    public icon: string;
+    constructor(id: string, channels: any[] = [], name: string = null) {
+        this.id = id;
+        this.name = name || id;
+        channels.forEach((item) => {
+            this.channels.set(item.id, item);
+        });
+    }
 
-  public fetchMember(id: string): Promise<MockMember|Error> {
-    if (this.members.has(id)) {
-      return Promise.resolve(this.members.get(id));
+    public fetchMember(id: string): Promise<MockMember|Error> {
+        if (this.members.has(id)) {
+            return Promise.resolve(this.members.get(id));
+        }
+        return Promise.reject("Member not in this guild");
     }
-    return Promise.reject("Member not in this guild");
-  }
 
-  public _mockAddMember(member: MockMember) {
-      this.members.set(member.id, member);
-  }
+    public _mockAddMember(member: MockMember) {
+        this.members.set(member.id, member);
+    }
 }
diff --git a/test/mocks/member.ts b/test/mocks/member.ts
index 6ddddb4db1aa75c39d429170c07193e92debc0cd..b1fef212bf4acdd9ce057877043ad5916fea85ff 100644
--- a/test/mocks/member.ts
+++ b/test/mocks/member.ts
@@ -2,19 +2,19 @@ import {MockUser} from "./user";
 import * as Discord from "discord.js";
 
 export class MockMember {
-  public id = "";
-  public presence: Discord.Presence;
-  public user: MockUser;
-  public nickname: string;
-  public roles = [];
-  constructor(id: string, username: string, public guild = null, public displayName: string = username) {
-    this.id = id;
-    this.presence = new Discord.Presence({});
-    this.user = new MockUser(this.id, username);
-    this.nickname = displayName;
-  }
+    public id = "";
+    public presence: Discord.Presence;
+    public user: MockUser;
+    public nickname: string;
+    public roles = [];
+    constructor(id: string, username: string, public guild = null, public displayName: string = username) {
+        this.id = id;
+        this.presence = new Discord.Presence({});
+        this.user = new MockUser(this.id, username);
+        this.nickname = displayName;
+    }
 
-  public MockSetPresence(presence: Discord.Presence) {
-      this.presence = presence;
-  }
+    public MockSetPresence(presence: Discord.Presence) {
+        this.presence = presence;
+    }
 }
diff --git a/test/mocks/user.ts b/test/mocks/user.ts
index d4545e1b2849fa774e3e51cfbe9a98e35240df7c..43d5929a241b531cb4015e466a49541e60cbe029 100644
--- a/test/mocks/user.ts
+++ b/test/mocks/user.ts
@@ -1,16 +1,16 @@
 import { Presence } from "discord.js";
 
 export class MockUser {
-  public presence: Presence;
-  constructor(
-      public id: string,
-      public username: string = "",
-      public discriminator: string = "",
-      public avatarURL: string = "",
-      public avatar: string = "",
-  ) { }
+    public presence: Presence;
+    constructor(
+        public id: string,
+        public username: string = "",
+        public discriminator: string = "",
+        public avatarURL: string = "",
+        public avatar: string = "",
+    ) { }
 
-  public MockSetPresence(presence: Presence) {
-      this.presence = presence;
-  }
+    public MockSetPresence(presence: Presence) {
+        this.presence = presence;
+    }
 }
diff --git a/test/test_channelsyncroniser.ts b/test/test_channelsyncroniser.ts
index 01b7aabcd1c83e48f4355e8a3056c9f553e4c4b4..a3e91a975146dc1fca4b746044c06c90be4041a1 100644
--- a/test/test_channelsyncroniser.ts
+++ b/test/test_channelsyncroniser.ts
@@ -13,6 +13,9 @@ import { MessageProcessor, MessageProcessorOpts } from "../src/messageprocessor"
 import { MockChannel } from "./mocks/channel";
 import { Bridge, MatrixRoom, RemoteRoom } from "matrix-appservice-bridge";
 
+// we are a test file and thus need those
+/* tslint:disable:no-unused-expression max-file-line-count no-any */
+
 Chai.use(ChaiAsPromised);
 const expect = Chai.expect;
 
@@ -52,10 +55,69 @@ class Entry {
 function CreateChannelSync(remoteChannels: any[] = []): ChannelSyncroniser {
     UTIL_UPLOADED_AVATAR = false;
     const bridge: any = {
+        getIntent: (id) => {
+            ROOM_NAME_SET = null;
+            ROOM_TOPIC_SET = null;
+            ROOM_AVATAR_SET = null;
+            STATE_EVENT_SENT = false;
+            ALIAS_DELETED = false;
+            ROOM_DIRECTORY_VISIBILITY = null;
+            return {
+                getClient: () => {
+                    return {
+                        deleteAlias: (alias) => {
+                            ALIAS_DELETED = true;
+                            return Promise.resolve();
+                        },
+                        getStateEvent: (mxid, event) => {
+                            return Promise.resolve(event);
+                        },
+                        sendStateEvent: (mxid, event, data) => {
+                            STATE_EVENT_SENT = true;
+                            return Promise.resolve();
+                        },
+                        setRoomDirectoryVisibility: (mxid, visibility) => {
+                            ROOM_DIRECTORY_VISIBILITY = visibility;
+                            return Promise.resolve();
+                        },
+                        setRoomName: (mxid, name) => {
+                            ROOM_NAME_SET = name;
+                            return Promise.resolve();
+                        },
+                        setRoomTopic: (mxid, topic) => {
+                            ROOM_TOPIC_SET = topic;
+                            return Promise.resolve();
+                        },
+                    };
+                },
+                setRoomAvatar: (mxid, mxc) => {
+                    ROOM_AVATAR_SET = mxc;
+                    return Promise.resolve();
+                },
+                setRoomName: (mxid, name) => {
+                    ROOM_NAME_SET = name;
+                    return Promise.resolve();
+                },
+                setRoomTopic: (mxid, topic) => {
+                    ROOM_TOPIC_SET = topic;
+                    return Promise.resolve();
+                },
+            };
+        },
         getRoomStore: () => {
             REMOTECHANNEL_SET = false;
             REMOTECHANNEL_REMOVED = false;
             return {
+                getEntriesByMatrixId: (roomid) => {
+                    const entries = [];
+                    remoteChannels.forEach((c) => {
+                        const mxid = c.matrix.getId();
+                        if (roomid === mxid) {
+                            entries.push(c);
+                        }
+                    });
+                    return entries;
+                },
                 getEntriesByMatrixIds: (roomids) => {
                     const entries = {};
                     remoteChannels.forEach((c) => {
@@ -69,16 +131,6 @@ function CreateChannelSync(remoteChannels: any[] = []): ChannelSyncroniser {
                     });
                     return entries;
                 },
-                getEntriesByMatrixId: (roomid) => {
-                    const entries = [];
-                    remoteChannels.forEach((c) => {
-                        const mxid = c.matrix.getId();
-                        if (roomid === mxid) {
-                            entries.push(c);
-                        }
-                    });
-                    return entries;
-                },
                 getEntriesByRemoteRoomData: (data) => {
                     return remoteChannels.filter((c) => {
                         for (const d of Object.keys(data)) {
@@ -89,60 +141,11 @@ function CreateChannelSync(remoteChannels: any[] = []): ChannelSyncroniser {
                         return true;
                     });
                 },
-                upsertEntry: (room) => {
-                    REMOTECHANNEL_SET = true;
-                },
                 removeEntriesByMatrixRoomId: (room) => {
                     REMOTECHANNEL_REMOVED = true;
                 },
-            };
-        },
-        getIntent: (id) => {
-            ROOM_NAME_SET = null;
-            ROOM_TOPIC_SET = null;
-            ROOM_AVATAR_SET = null;
-            STATE_EVENT_SENT = false;
-            ALIAS_DELETED = false;
-            ROOM_DIRECTORY_VISIBILITY = null;
-            return {
-                setRoomName: (mxid, name) => {
-                    ROOM_NAME_SET = name;
-                    return Promise.resolve();
-                },
-                setRoomTopic: (mxid, topic) => {
-                    ROOM_TOPIC_SET = topic;
-                    return Promise.resolve();
-                },
-                setRoomAvatar: (mxid, mxc) => {
-                    ROOM_AVATAR_SET = mxc;
-                    return Promise.resolve();
-                },
-                getClient: () => {
-                    return {
-                        getStateEvent: (mxid, event) => {
-                            return Promise.resolve(event);
-                        },
-                        setRoomName: (mxid, name) => {
-                            ROOM_NAME_SET = name;
-                            return Promise.resolve();
-                        },
-                        setRoomTopic: (mxid, topic) => {
-                            ROOM_TOPIC_SET = topic;
-                            return Promise.resolve();
-                        },
-                        sendStateEvent: (mxid, event, data) => {
-                            STATE_EVENT_SENT = true;
-                            return Promise.resolve();
-                        },
-                        deleteAlias: (alias) => {
-                            ALIAS_DELETED = true;
-                            return Promise.resolve();
-                        },
-                        setRoomDirectoryVisibility: (mxid, visibility) => {
-                            ROOM_DIRECTORY_VISIBILITY = visibility;
-                            return Promise.resolve();
-                        },
-                    };
+                upsertEntry: (room) => {
+                    REMOTECHANNEL_SET = true;
                 },
             };
         },
@@ -166,10 +169,10 @@ describe("ChannelSyncroniser", () => {
                 new Entry({
                     id: "1",
                     matrix_id: "!1:localhost",
-                    remote_id: "111",
                     remote: {
                         discord_channel: chan.id,
                     },
+                    remote_id: "111",
                 }),
             ];
 
@@ -186,10 +189,10 @@ describe("ChannelSyncroniser", () => {
                 new Entry({
                     id: "1",
                     matrix_id: "!1:localhost",
-                    remote_id: "111",
                     remote: {
                         discord_channel: chan.id,
                     },
+                    remote_id: "111",
                 }),
             ];
 
@@ -207,10 +210,10 @@ describe("ChannelSyncroniser", () => {
                 new Entry({
                     id: "1",
                     matrix_id: "!1:localhost",
-                    remote_id: "111",
                     remote: {
                         discord_channel: chan.id,
                     },
+                    remote_id: "111",
                 }),
             ];
 
@@ -227,26 +230,26 @@ describe("ChannelSyncroniser", () => {
                 new Entry({
                     id: "1",
                     matrix_id: "!1:localhost",
-                    remote_id: "111",
                     remote: {
                         discord_channel: chan.id,
                     },
+                    remote_id: "111",
                 }),
                 new Entry({
                     id: "2",
                     matrix_id: "!2:localhost",
-                    remote_id: "111",
                     remote: {
                         discord_channel: chan.id,
                     },
+                    remote_id: "111",
                 }),
                 new Entry({
                     id: "3",
                     matrix_id: "!3:localhost",
-                    remote_id: "false",
                     remote: {
                         discord_channel: "no",
                     },
+                    remote_id: "false",
                 }),
             ];
 
@@ -291,7 +294,6 @@ describe("ChannelSyncroniser", () => {
                 new Entry({
                     id: "1",
                     matrix_id: "!1:localhost",
-                    remote_id: "111",
                     remote: {
                         discord_channel: chan.id,
                         discord_name: "[Discord] oldGuild oldName",
@@ -299,6 +301,7 @@ describe("ChannelSyncroniser", () => {
                         update_name: true,
                         update_topic: true,
                     },
+                    remote_id: "111",
                 }),
             ];
 
@@ -322,12 +325,12 @@ describe("ChannelSyncroniser", () => {
                 new Entry({
                     id: "1",
                     matrix_id: "!1:localhost",
-                    remote_id: "111",
                     remote: {
                         discord_channel: chan.id,
                         discord_name: "[Discord] oldGuild oldName",
                         discord_topic: "oldTopic",
                     },
+                    remote_id: "111",
                 }),
             ];
 
@@ -351,7 +354,6 @@ describe("ChannelSyncroniser", () => {
                 new Entry({
                     id: "1",
                     matrix_id: "!1:localhost",
-                    remote_id: "111",
                     remote: {
                         discord_channel: chan.id,
                         discord_name: "[Discord] newGuild #newName",
@@ -359,6 +361,7 @@ describe("ChannelSyncroniser", () => {
                         update_name: true,
                         update_topic: true,
                     },
+                    remote_id: "111",
                 }),
             ];
 
@@ -381,12 +384,12 @@ describe("ChannelSyncroniser", () => {
                 new Entry({
                     id: "1",
                     matrix_id: "!1:localhost",
-                    remote_id: "111",
                     remote: {
                         discord_channel: chan.id,
                         discord_iconurl: "https://cdn.discordapp.com/icons/654321/old_icon.png",
                         update_icon: true,
                     },
+                    remote_id: "111",
                 }),
             ];
 
@@ -409,12 +412,12 @@ describe("ChannelSyncroniser", () => {
                 new Entry({
                     id: "1",
                     matrix_id: "!1:localhost",
-                    remote_id: "111",
                     remote: {
                         discord_channel: chan.id,
                         discord_iconurl: "https://cdn.discordapp.com/icons/654321/new_icon.png",
                         update_icon: true,
                     },
+                    remote_id: "111",
                 }),
             ];
 
@@ -437,12 +440,12 @@ describe("ChannelSyncroniser", () => {
                 new Entry({
                     id: "1",
                     matrix_id: "!1:localhost",
-                    remote_id: "111",
                     remote: {
                         discord_channel: chan.id,
                         discord_iconurl: "https://cdn.discordapp.com/icons/654321/icon.png",
                         update_icon: true,
                     },
+                    remote_id: "111",
                 }),
             ];
 
@@ -468,16 +471,16 @@ describe("ChannelSyncroniser", () => {
                 new Entry({
                     id: "1",
                     matrix_id: "!1:localhost",
-                    remote_id: "111",
                     remote: {
                         discord_channel: chan.id,
+                        discord_iconurl: "https://cdn.discordapp.com/icons/654321/old_icon.png",
                         discord_name: "[Discord] oldGuild #oldName",
                         discord_topic: "oldTopic",
-                        discord_iconurl: "https://cdn.discordapp.com/icons/654321/old_icon.png",
+                        update_icon: true,
                         update_name: true,
                         update_topic: true,
-                        update_icon: true,
                     },
+                    remote_id: "111",
                 }),
             ];
 
diff --git a/test/test_clientfactory.ts b/test/test_clientfactory.ts
index 6660d4cc2f6246ad74c180fcf7fb05d4b784c8a4..2d48b64ad48cc00e7f2356be33929432a8709099 100644
--- a/test/test_clientfactory.ts
+++ b/test/test_clientfactory.ts
@@ -4,6 +4,9 @@ import * as Proxyquire from "proxyquire";
 import {DiscordBridgeConfigAuth} from "../src/config";
 import {MockDiscordClient} from "./mocks/discordclient";
 
+// we are a test file and thus need those
+/* tslint:disable:no-unused-expression max-file-line-count no-any */
+
 Chai.use(ChaiAsPromised);
 const expect = Chai.expect;
 
@@ -12,14 +15,6 @@ const DiscordClientFactory = Proxyquire("../src/clientfactory", {
 }).DiscordClientFactory;
 
 const STORE = {
-    get_user_discord_ids: (userid: string) => {
-        if (userid === "@valid:localhost") {
-            return Promise.resolve(["12345"]);
-        } else if (userid === "@invalid:localhost") {
-            return Promise.resolve(["1234555"]);
-        }
-        return Promise.resolve([]);
-    },
     get_token: (discordid: string) => {
         if (discordid === "12345") {
             return Promise.resolve("passme");
@@ -28,6 +23,14 @@ const STORE = {
         }
         return Promise.reject("Token not found");
     },
+    get_user_discord_ids: (userid: string) => {
+        if (userid === "@valid:localhost") {
+            return Promise.resolve(["12345"]);
+        } else if (userid === "@invalid:localhost") {
+            return Promise.resolve(["1234555"]);
+        }
+        return Promise.resolve([]);
+    },
 };
 
 describe("ClientFactory", () => {
diff --git a/test/test_config.ts b/test/test_config.ts
index 32c305699d56257e9e208912cdbc368434cc5cea..472d944e11772daadd479b3bba5961437b2c1f42 100644
--- a/test/test_config.ts
+++ b/test/test_config.ts
@@ -1,6 +1,10 @@
 import * as Chai from "chai";
 import * as ChaiAsPromised from "chai-as-promised";
 import { DiscordBridgeConfig } from "../src/config";
+
+// we are a test file and thus need those
+/* tslint:disable:no-unused-expression max-file-line-count no-any */
+
 Chai.use(ChaiAsPromised);
 const expect = Chai.expect;
 
@@ -9,11 +13,11 @@ describe("DiscordBridgeConfig.ApplyConfig", () => {
         const config = new DiscordBridgeConfig();
         config.ApplyConfig({
             bridge: {
-                homeserverUrl: "blah",
-                disableTypingNotifications: true,
-                disableDiscordMentions: false,
                 disableDeletionForwarding: true,
+                disableDiscordMentions: false,
+                disableTypingNotifications: true,
                 enableSelfServiceBridging: false,
+                homeserverUrl: "blah",
             },
             logging: {
                 console: "warn",
diff --git a/test/test_configschema.ts b/test/test_configschema.ts
index 0533016160c9240d477a1ec8db00d71afc17ae05..439ba3c415db72c85c55f8ed10801866b2cba59a 100644
--- a/test/test_configschema.ts
+++ b/test/test_configschema.ts
@@ -2,6 +2,9 @@ import * as yaml from "js-yaml";
 import * as Chai from "chai";
 import { ConfigValidator } from "matrix-appservice-bridge";
 
+// we are a test file and thus need those
+/* tslint:disable:no-unused-expression max-file-line-count no-any */
+
 const expect = Chai.expect;
 
 describe("ConfigSchema", () => {
diff --git a/test/test_discordbot.ts b/test/test_discordbot.ts
index a350b1784949c320af1cdf1fa9c093b155ca23ae..704394777bf2c576bec6cc5dc35238ffbb0e259d 100644
--- a/test/test_discordbot.ts
+++ b/test/test_discordbot.ts
@@ -10,192 +10,195 @@ import { MockMember } from "./mocks/member";
 import { DiscordBot } from "../src/bot";
 import { MockDiscordClient } from "./mocks/discordclient";
 
+// we are a test file and thus need those
+/* tslint:disable:no-unused-expression max-file-line-count no-any */
+
 Chai.use(ChaiAsPromised);
 
 const assert = Chai.assert;
 // const should = Chai.should as any;
 
 const mockBridge = {
-  getRoomStore: () => {
-    return {
-      getEntriesByRemoteRoomData: (data) => {
-        if (data.discord_channel === "321") {
-          return Promise.resolve([{
-            matrix: {
-              getId: () => "foobar:example.com",
+    getIntentFromLocalpart: (localpart: string) => {
+        return {
+            sendTyping: (room: string, isTyping: boolean) => {
+                return;
             },
-          }]);
-        }
-        return Promise.resolve([]);
-      },
-    };
-  },
-  getIntentFromLocalpart: (localpart: string) => {
-    return {
-      sendTyping: (room: string, isTyping: boolean) => {
-        return;
-      },
-    };
-  },
-  getUserStore: () => {
-    return {};
-  },
+        };
+    },
+    getRoomStore: () => {
+        return {
+            getEntriesByRemoteRoomData: (data) => {
+                if (data.discord_channel === "321") {
+                    return Promise.resolve([{
+                        matrix: {
+                            getId: () => "foobar:example.com",
+                        },
+                    }]);
+                }
+                return Promise.resolve([]);
+            },
+        };
+    },
+    getUserStore: () => {
+        return {};
+    },
 };
 
 const modDiscordBot = Proxyquire("../src/bot", {
-  "./clientfactory": require("./mocks/discordclientfactory"),
+    "./clientfactory": require("./mocks/discordclientfactory"),
 });
 describe("DiscordBot", () => {
-  let discordBot;
-  const config = {
-    auth: {
-        botToken: "blah",
-    },
-    bridge: {
-        domain: "localhost",
-    },
-    limits: {
-        discordSendDelay: 50,
-    },
-  };
-  describe("run()", () => {
-    it("should resolve when ready.", () => {
-      discordBot = new modDiscordBot.DiscordBot(
-        config,
-        null,
-      );
-      discordBot.setBridge(mockBridge);
-      return discordBot.run();
-    });
-  });
-
-  describe("LookupRoom()", () => {
-    beforeEach(() => {
-      discordBot = new modDiscordBot.DiscordBot(
-        config,
-        null,
-      );
-      discordBot.setBridge(mockBridge);
-      return discordBot.run();
-    });
-    it("should reject a missing guild.", () => {
-      return assert.isRejected(discordBot.LookupRoom("541", "321"));
+    let discordBot;
+    const config = {
+        auth: {
+            botToken: "blah",
+        },
+        bridge: {
+            domain: "localhost",
+        },
+        limits: {
+            discordSendDelay: 50,
+        },
+    };
+    describe("run()", () => {
+        it("should resolve when ready.", () => {
+            discordBot = new modDiscordBot.DiscordBot(
+                config,
+                null,
+            );
+            discordBot.setBridge(mockBridge);
+            return discordBot.run();
+        });
     });
 
-    it("should reject a missing channel.", () => {
-      return assert.isRejected(discordBot.LookupRoom("123", "666"));
+    describe("LookupRoom()", () => {
+        beforeEach(() => {
+            discordBot = new modDiscordBot.DiscordBot(
+                config,
+                null,
+            );
+            discordBot.setBridge(mockBridge);
+            return discordBot.run();
+        });
+        it("should reject a missing guild.", () => {
+            return assert.isRejected(discordBot.LookupRoom("541", "321"));
+        });
+
+        it("should reject a missing channel.", () => {
+            return assert.isRejected(discordBot.LookupRoom("123", "666"));
+        });
+
+        it("should resolve a guild and channel id.", () => {
+            return assert.isFulfilled(discordBot.LookupRoom("123", "321"));
+        });
     });
-
-    it("should resolve a guild and channel id.", () => {
-      return assert.isFulfilled(discordBot.LookupRoom("123", "321"));
+    describe("OnMessageUpdate()", () => {
+        it("should return on an unchanged message", () => {
+            discordBot = new modDiscordBot.DiscordBot(
+                config,
+                mockBridge,
+            );
+
+            const guild: any = new MockGuild("123", []);
+            guild._mockAddMember(new MockMember("12345", "TestUsername"));
+            const channel = new Discord.TextChannel(guild, null);
+            const oldMsg = new Discord.Message(channel, null, null);
+            const newMsg = new Discord.Message(channel, null, null);
+            oldMsg.embeds = [];
+            newMsg.embeds = [];
+
+            // Content updated but not changed
+            oldMsg.content = "a";
+            newMsg.content = "a";
+
+            // Mock the SendMatrixMessage method to check if it is called
+            let checkMsgSent = false;
+            discordBot.SendMatrixMessage = (...args) => checkMsgSent = true;
+
+            discordBot.OnMessageUpdate(oldMsg, newMsg).then(() => {
+                Chai.assert.equal(checkMsgSent, false);
+            });
+        });
+
+        it("should send a matrix message on an edited discord message", () => {
+            discordBot = new modDiscordBot.DiscordBot(
+                config,
+                mockBridge,
+            );
+
+            const guild: any = new MockGuild("123", []);
+            guild._mockAddMember(new MockMember("12345", "TestUsername"));
+            const channel = new Discord.TextChannel(guild, null);
+            const oldMsg = new Discord.Message(channel, null, null);
+            const newMsg = new Discord.Message(channel, null, null);
+            oldMsg.embeds = [];
+            newMsg.embeds = [];
+
+            // Content updated and edited
+            oldMsg.content = "a";
+            newMsg.content = "b";
+
+            // Mock the SendMatrixMessage method to check if it is called
+            let checkMsgSent = false;
+            discordBot.SendMatrixMessage = (...args) => checkMsgSent = true;
+
+            discordBot.OnMessageUpdate(oldMsg, newMsg).then(() => {
+                Chai.assert.equal(checkMsgSent, true);
+            });
+        });
     });
-  });
-  describe("OnMessageUpdate()", () => {
-    it("should return on an unchanged message", () => {
-      discordBot = new modDiscordBot.DiscordBot(
-        config,
-        mockBridge,
-      );
-
-      const guild: any = new MockGuild("123", []);
-      guild._mockAddMember(new MockMember("12345", "TestUsername"));
-      const channel = new Discord.TextChannel(guild, null);
-      const oldMsg = new Discord.Message(channel, null, null);
-      const newMsg = new Discord.Message(channel, null, null);
-      oldMsg.embeds = [];
-      newMsg.embeds = [];
-
-      // Content updated but not changed
-      oldMsg.content = "a";
-      newMsg.content = "a";
-
-      // Mock the SendMatrixMessage method to check if it is called
-      let checkMsgSent = false;
-      discordBot.SendMatrixMessage = (...args) => checkMsgSent = true;
-
-      discordBot.OnMessageUpdate(oldMsg, newMsg).then(() => {
-        Chai.assert.equal(checkMsgSent, false);
-      });
+    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];
+        });
     });
 
-    it("should send a matrix message on an edited discord message", () => {
-      discordBot = new modDiscordBot.DiscordBot(
-        config,
-        mockBridge,
-      );
-
-      const guild: any = new MockGuild("123", []);
-      guild._mockAddMember(new MockMember("12345", "TestUsername"));
-      const channel = new Discord.TextChannel(guild, null);
-      const oldMsg = new Discord.Message(channel, null, null);
-      const newMsg = new Discord.Message(channel, null, null);
-      oldMsg.embeds = [];
-      newMsg.embeds = [];
-
-      // Content updated and edited
-      oldMsg.content = "a";
-      newMsg.content = "b";
-
-      // Mock the SendMatrixMessage method to check if it is called
-      let checkMsgSent = false;
-      discordBot.SendMatrixMessage = (...args) => checkMsgSent = true;
-
-      discordBot.OnMessageUpdate(oldMsg, newMsg).then(() => {
-        Chai.assert.equal(checkMsgSent, true);
-      });
-    });
-  });
-  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()", () => {
-  //
-  // });
-  // describe("UpdateRoom()", () => {
-  //
-  // });
-  // describe("UpdateUser()", () => {
-  //
-  // });
-  // describe("UpdatePresence()", () => {
-  //
-  // });
-  // describe("OnTyping()", () => {
-  //   const discordBot = new modDiscordBot.DiscordBot(
-  //     config,
-  //   );
-  //   discordBot.setBridge(mockBridge);
-  //   discordBot.run();
-  //   it("should reject an unknown room.", () => {
-  //     return assert.isRejected(discordBot.OnTyping( {id: "512"}, {id: "12345"}, true));
-  //   });
-  //   it("should resolve a known room.", () => {
-  //     return assert.isFulfilled(discordBot.OnTyping( {id: "321"}, {id: "12345"}, true));
-  //   });
-  // });
-  // describe("OnMessage()", () => {
-  //
-  // });
+    // describe("ProcessMatrixMsgEvent()", () => {
+    //
+    // });
+    // describe("UpdateRoom()", () => {
+    //
+    // });
+    // describe("UpdateUser()", () => {
+    //
+    // });
+    // describe("UpdatePresence()", () => {
+    //
+    // });
+    // describe("OnTyping()", () => {
+    //   const discordBot = new modDiscordBot.DiscordBot(
+    //     config,
+    //   );
+    //   discordBot.setBridge(mockBridge);
+    //   discordBot.run();
+    //   it("should reject an unknown room.", () => {
+    //     return assert.isRejected(discordBot.OnTyping( {id: "512"}, {id: "12345"}, true));
+    //   });
+    //   it("should resolve a known room.", () => {
+    //     return assert.isFulfilled(discordBot.OnTyping( {id: "321"}, {id: "12345"}, true));
+    //   });
+    // });
+    // describe("OnMessage()", () => {
+    //
+    // });
 });
diff --git a/test/test_log.ts b/test/test_log.ts
index c70e6fef896280a06053e4766638db816b9e3de2..42a7f9c787f1d004b74aa4d50d77bcf70f382808 100644
--- a/test/test_log.ts
+++ b/test/test_log.ts
@@ -2,6 +2,10 @@ import * as Chai from "chai";
 import * as ChaiAsPromised from "chai-as-promised";
 import * as Proxyquire from "proxyquire";
 import * as RealLog from "../src/log";
+
+// we are a test file and thus need those
+/* tslint:disable:no-unused-expression max-file-line-count no-any */
+
 Chai.use(ChaiAsPromised);
 const expect = Chai.expect;
 
@@ -12,15 +16,15 @@ let loggedMessages = [];
 const WinstonMock = {
     createLogger: (format, transports) => {
         return createdLogger = {
-            format,
-            transports,
             close: () => {
                 loggerClosed = true;
             },
-            silent: false,
+            format,
             log: (type, ...msg) => {
                 loggedMessages = loggedMessages.concat(msg);
             },
+            silent: false,
+            transports,
         };
     },
 };
diff --git a/test/test_matrixeventprocessor.ts b/test/test_matrixeventprocessor.ts
index beb033672d8afc01c5ed81dfeeee336110f7201e..861e164b77862a5a7c966191454da9cb96d30aa9 100644
--- a/test/test_matrixeventprocessor.ts
+++ b/test/test_matrixeventprocessor.ts
@@ -14,6 +14,9 @@ import {DiscordBridgeConfig} from "../src/config";
 import {MessageProcessor, MessageProcessorOpts} from "../src/messageprocessor";
 import {MockChannel} from "./mocks/channel";
 
+// we are a test file and thus need those
+/* tslint:disable:no-unused-expression max-file-line-count no-any */
+
 Chai.use(ChaiAsPromised);
 const expect = Chai.expect;
 // const assert = Chai.assert;
@@ -35,9 +38,17 @@ const mxClient = {
     },
 };
 
-function createMatrixEventProcessor
-   (disableMentions: boolean = false, disableEveryone = false, disableHere = false): MatrixEventProcessor {
+function createMatrixEventProcessor(
+    disableMentions: boolean = false,
+    disableEveryone = false,
+    disableHere = false,
+): MatrixEventProcessor {
     const bridge = {
+        getBot: () => {
+            return {
+                isRemoteUser: () => false,
+            };
+        },
         getClientFactory: () => {
             return {
                 getClientAs: () => {
@@ -45,11 +56,6 @@ function createMatrixEventProcessor
                 },
             };
         },
-        getBot: () => {
-            return {
-                isRemoteUser: () => false,
-            };
-        },
         getIntent: () => {
             return {
                 getClient: () => {
@@ -62,31 +68,31 @@ function createMatrixEventProcessor
                 getEvent: async (_, eventId: string) => {
                     if (eventId === "$goodEvent:localhost") {
                         return {
-                            sender: "@doggo:localhost",
                             content: {
                                 body: "Hello!",
                             },
+                            sender: "@doggo:localhost",
                         };
                     } else if (eventId === "$reply:localhost") {
                         return {
-                            sender: "@doggo:localhost",
                             content: {
                                 "body": `> <@doggo:localhost> This is the original body
 
-This is the first reply`,
+                                This is the first reply`,
                                 "m.relates_to": {
                                     "m.in_reply_to": {
                                         event_id: "$goodEvent:localhost",
                                     },
                                 },
                             },
+                            sender: "@doggo:localhost",
                         };
                     } else if (eventId === "$nontext:localhost") {
                         return {
-                            sender: "@doggo:localhost",
                             content: {
                                 something: "not texty",
                             },
+                            sender: "@doggo:localhost",
                         };
                     }
                     return null;
@@ -96,8 +102,8 @@ This is the first reply`,
                         return null;
                     }
                     return {
-                        displayname: "Doggo!",
                         avatar_url: "mxc://fakeurl.com",
+                        displayname: "Doggo!",
                     };
                 },
             };
@@ -154,11 +160,11 @@ describe("MatrixEventProcessor", () => {
         it("Should echo name changes", () => {
             const processor = createMatrixEventProcessor();
             const event = {
-                sender: "@user:localhost",
-                type: "m.room.name",
                 content: {
                     name: "Test Name",
                 },
+                sender: "@user:localhost",
+                type: "m.room.name",
             };
             const channel = new MockChannel("123456");
             const msg = processor.StateEventToMessage(event, channel as any);
@@ -167,11 +173,11 @@ describe("MatrixEventProcessor", () => {
         it("Should echo topic changes", () => {
             const processor = createMatrixEventProcessor();
             const event = {
-                sender: "@user:localhost",
-                type: "m.room.topic",
                 content: {
                     topic: "Test Topic",
                 },
+                sender: "@user:localhost",
+                type: "m.room.topic",
             };
             const channel = new MockChannel("123456");
             const msg = processor.StateEventToMessage(event, channel as any);
@@ -180,11 +186,11 @@ describe("MatrixEventProcessor", () => {
         it("Should echo joins", () => {
             const processor = createMatrixEventProcessor();
             const event = {
-                sender: "@user:localhost",
-                type: "m.room.member",
                 content: {
                     membership: "join",
                 },
+                sender: "@user:localhost",
+                type: "m.room.member",
                 unsigned: {},
             };
             const channel = new MockChannel("123456");
@@ -194,13 +200,13 @@ describe("MatrixEventProcessor", () => {
         it("Should echo invites", () => {
             const processor = createMatrixEventProcessor();
             const event = {
-                sender: "@user:localhost",
-                type: "m.room.member",
                 content: {
                     membership: "invite",
                 },
-                unsigned: {},
+                sender: "@user:localhost",
                 state_key: "@user2:localhost",
+                type: "m.room.member",
+                unsigned: {},
             };
             const channel = new MockChannel("123456");
             const msg = processor.StateEventToMessage(event, channel as any);
@@ -209,13 +215,13 @@ describe("MatrixEventProcessor", () => {
         it("Should echo kicks", () => {
             const processor = createMatrixEventProcessor();
             const event = {
-                sender: "@user:localhost",
-                type: "m.room.member",
                 content: {
                     membership: "leave",
                 },
-                unsigned: {},
+                sender: "@user:localhost",
                 state_key: "@user2:localhost",
+                type: "m.room.member",
+                unsigned: {},
             };
             const channel = new MockChannel("123456");
             const msg = processor.StateEventToMessage(event, channel as any);
@@ -224,13 +230,13 @@ describe("MatrixEventProcessor", () => {
         it("Should echo leaves", () => {
             const processor = createMatrixEventProcessor();
             const event = {
-                sender: "@user:localhost",
-                type: "m.room.member",
                 content: {
                     membership: "leave",
                 },
-                unsigned: {},
+                sender: "@user:localhost",
                 state_key: "@user:localhost",
+                type: "m.room.member",
+                unsigned: {},
             };
             const channel = new MockChannel("123456");
             const msg = processor.StateEventToMessage(event, channel as any);
@@ -239,13 +245,13 @@ describe("MatrixEventProcessor", () => {
         it("Should echo bans", () => {
             const processor = createMatrixEventProcessor();
             const event = {
-                sender: "@user:localhost",
-                type: "m.room.member",
                 content: {
                     membership: "ban",
                 },
-                unsigned: {},
+                sender: "@user:localhost",
                 state_key: "@user2:localhost",
+                type: "m.room.member",
+                unsigned: {},
             };
             const channel = new MockChannel("123456");
             const msg = processor.StateEventToMessage(event, channel as any);
@@ -256,13 +262,14 @@ describe("MatrixEventProcessor", () => {
         it("Should contain a profile.", async () => {
             const processor = createMatrixEventProcessor();
             const embeds = await processor.EventToEmbed({
-                sender: "@test:localhost",
                 content: {
                     body: "testcontent",
                 },
-            }, {
-                displayname: "Test User",
+                sender: "@test:localhost",
+            },
+            {
                 avatar_url: "mxc://localhost/avatarurl",
+                displayname: "Test User",
             }, mockChannel as any);
             const author = embeds.messageEmbed.author;
             Chai.assert.equal(author.name, "Test User");
@@ -273,10 +280,10 @@ describe("MatrixEventProcessor", () => {
         it("Should contain the users displayname if it exists.", async () => {
             const processor = createMatrixEventProcessor();
             const embeds = await processor.EventToEmbed({
-                sender: "@test:localhost",
                 content: {
                     body: "testcontent",
                 },
+                sender: "@test:localhost",
             }, {
                 displayname: "Test User"}, mockChannel as any);
             const author = embeds.messageEmbed.author;
@@ -288,10 +295,10 @@ describe("MatrixEventProcessor", () => {
         it("Should contain the users userid if the displayname is not set", async () => {
             const processor = createMatrixEventProcessor();
             const embeds = await processor.EventToEmbed({
-                sender: "@test:localhost",
                 content: {
                     body: "testcontent",
                 },
+                sender: "@test:localhost",
             }, null, mockChannel as any);
             const author = embeds.messageEmbed.author;
             Chai.assert.equal(author.name, "@test:localhost");
@@ -302,10 +309,10 @@ describe("MatrixEventProcessor", () => {
         it("Should use the userid when the displayname is too short", async () => {
             const processor = createMatrixEventProcessor();
             const embeds = await processor.EventToEmbed({
-                sender: "@test:localhost",
                 content: {
                     body: "testcontent",
                 },
+                sender: "@test:localhost",
             }, {
                 displayname: "t"}, mockChannel as any);
             const author = embeds.messageEmbed.author;
@@ -315,10 +322,10 @@ describe("MatrixEventProcessor", () => {
         it("Should use the userid when displayname is too long", async () => {
             const processor = createMatrixEventProcessor();
             const embeds = await processor.EventToEmbed({
-                sender: "@test:localhost",
                 content: {
                     body: "testcontent",
                 },
+                sender: "@test:localhost",
             }, {
                 displayname: "this is a very very long displayname that should be capped",
             }, mockChannel as any);
@@ -329,10 +336,10 @@ describe("MatrixEventProcessor", () => {
         it("Should cap the sender name if it is too long", async () => {
             const processor = createMatrixEventProcessor();
             const embeds = await processor.EventToEmbed({
-                sender: "@testwithalottosayaboutitselfthatwillgoonandonandonandon:localhost",
                 content: {
                     body: "testcontent",
                 },
+                sender: "@testwithalottosayaboutitselfthatwillgoonandonandonandon:localhost",
             }, null, mockChannel as any);
             const author = embeds.messageEmbed.author;
             Chai.assert.equal(author.name, "@testwithalottosayaboutitselftha");
@@ -341,10 +348,10 @@ describe("MatrixEventProcessor", () => {
         it("Should contain the users avatar if it exists.", async () => {
             const processor = createMatrixEventProcessor();
             const embeds = await processor.EventToEmbed({
-                sender: "@test:localhost",
                 content: {
                     body: "testcontent",
                 },
+                sender: "@test:localhost",
             }, {avatar_url: "mxc://localhost/test"}, mockChannel as any);
             const author = embeds.messageEmbed.author;
             Chai.assert.equal(author.name, "@test:localhost");
@@ -355,10 +362,10 @@ describe("MatrixEventProcessor", () => {
         it("Should enable mentions if configured.", async () => {
             const processor = createMatrixEventProcessor();
             const embeds = await processor.EventToEmbed({
-                sender: "@test:localhost",
                 content: {
                     body: "@testuser2 Hello!",
                 },
+                sender: "@test:localhost",
             }, {avatar_url: "test"}, mockChannel as any);
             Chai.assert.equal(embeds.messageEmbed.description, "<@!12345> Hello!");
         });
@@ -366,10 +373,10 @@ describe("MatrixEventProcessor", () => {
         it("Should disable mentions if configured.", async () => {
             const processor = createMatrixEventProcessor(true);
             const embeds = await processor.EventToEmbed({
-                sender: "@test:localhost",
                 content: {
                     body: "@testuser2 Hello!",
                 },
+                sender: "@test:localhost",
             }, {avatar_url: "test"}, mockChannel as any);
             Chai.assert.equal(embeds.messageEmbed.description, "@testuser2 Hello!");
         });
@@ -377,10 +384,10 @@ describe("MatrixEventProcessor", () => {
         it("Should remove everyone mentions if configured.", async () => {
             const processor = createMatrixEventProcessor(false, true);
             const embeds = await processor.EventToEmbed({
-                sender: "@test:localhost",
                 content: {
                     body: "@everyone Hello!",
                 },
+                sender: "@test:localhost",
             }, {avatar_url: "test"}, mockChannel as any);
             Chai.assert.equal(embeds.messageEmbed.description, "@ everyone Hello!");
         });
@@ -388,10 +395,10 @@ describe("MatrixEventProcessor", () => {
         it("Should remove here mentions if configured.", async () => {
             const processor = createMatrixEventProcessor(false, false, true);
             const embeds = await processor.EventToEmbed({
-                sender: "@test:localhost",
                 content: {
                     body: "@here Hello!",
                 },
+                sender: "@test:localhost",
             }, {avatar_url: "test"}, mockChannel as any);
             Chai.assert.equal(embeds.messageEmbed.description, "@ here Hello!");
         });
@@ -406,10 +413,10 @@ describe("MatrixEventProcessor", () => {
                 emojis: mockCollectionEmojis,
             });
             const embeds = await processor.EventToEmbed({
-                sender: "@test:localhost",
                 content: {
                     body: "I like :supercake:",
                 },
+                sender: "@test:localhost",
             }, {avatar_url: "test"}, mockChannelEmojis as any);
             Chai.assert.equal(
                 embeds.messageEmbed.description,
@@ -427,10 +434,10 @@ describe("MatrixEventProcessor", () => {
                 emojis: mockCollectionEmojis,
             });
             const embeds = await processor.EventToEmbed({
-                sender: "@test:localhost",
                 content: {
                     body: "I like :lamecake:",
                 },
+                sender: "@test:localhost",
             }, {avatar_url: "test"}, mockChannelEmojis as any);
             Chai.assert.equal(
                 embeds.messageEmbed.description,
@@ -440,11 +447,11 @@ describe("MatrixEventProcessor", () => {
         it("Should replace /me with * displayname, and italicize message", async () => {
             const processor = createMatrixEventProcessor();
             const embeds = await processor.EventToEmbed({
-                sender: "@test:localhost",
                 content: {
                     body: "likes puppies",
                     msgtype: "m.emote",
                 },
+                sender: "@test:localhost",
             }, {
                 displayname: "displayname",
             }, mockChannel as any);
@@ -456,12 +463,12 @@ describe("MatrixEventProcessor", () => {
         it("Should handle stickers.", async () => {
             const processor = createMatrixEventProcessor();
             const embeds = await processor.EventToEmbed({
-                sender: "@test:localhost",
-                type: "m.sticker",
                 content: {
                     body: "Bunnies",
                     url: "mxc://bunny",
                 },
+                sender: "@test:localhost",
+                type: "m.sticker",
             }, {avatar_url: "test"}, mockChannel as any);
             Chai.assert.equal(embeds.messageEmbed.description, "");
         });
@@ -472,9 +479,9 @@ describe("MatrixEventProcessor", () => {
             const guild: any = new MockGuild("123", []);
             const members: Discord.GuildMember[] = [new Discord.GuildMember(guild, {
                 user: {
-                    username: "TestUsername",
-                    id: "12345",
                     discriminator: "54321",
+                    id: "12345",
+                    username: "TestUsername",
                 },
             })];
             Chai.assert.equal(
@@ -500,20 +507,20 @@ describe("MatrixEventProcessor", () => {
             const members: Discord.GuildMember[] = [new Discord.GuildMember(guild, {
                 nick: "Test",
                 user: {
-                    username: "Test",
                     id: "54321",
+                    username: "Test",
                 },
             }), new Discord.GuildMember(guild, {
                 nick: "TestNickname",
                 user: {
-                    username: "TestUsername",
                     id: "12345",
+                    username: "TestUsername",
                 },
             }), new Discord.GuildMember(guild, {
                 nick: "𝖘𝖔𝖒𝖊𝖋𝖆𝖓𝖈𝖞𝖓𝖎𝖈𝖐𝖓𝖆𝖒𝖊",
                 user: {
-                    username: "SomeFancyNickname",
                     id: "66666",
+                    username: "SomeFancyNickname",
                 },
             })];
             Chai.assert.equal(processor.FindMentionsInPlainBody("Hello TestNickname", members), "Hello <@!12345>");
@@ -556,15 +563,15 @@ describe("MatrixEventProcessor", () => {
             const members: Discord.GuildMember[] = [new Discord.GuildMember(guild, {
                 nick: "that",
                 user: {
-                    username: "TestUsername",
                     id: "12345",
+                    username: "TestUsername",
                 },
             }),
                 new Discord.GuildMember(guild, {
                     nick: "testingstring",
                     user: {
-                        username: "that",
                         id: "12345",
+                        username: "that",
                     },
                 })];
             const msg = "Welcome thatman";
@@ -586,8 +593,8 @@ describe("MatrixEventProcessor", () => {
             const processor = createMatrixEventProcessor();
             return expect(processor.HandleAttachment({
                 content: {
-                    msgtype: "m.video",
                     body: "filename.webm",
+                    msgtype: "m.video",
                     url: "mxc://localhost/200",
                 },
             }, mxClient)).to.eventually.satisfy((attachment) => {
@@ -600,10 +607,10 @@ describe("MatrixEventProcessor", () => {
             const processor = createMatrixEventProcessor();
             return expect(processor.HandleAttachment({
                 content: {
-                    msgtype: "m.video",
                     info: {
                         size: 1,
                     },
+                    msgtype: "m.video",
                 },
             }, mxClient)).to.eventually.eq("");
         });
@@ -612,11 +619,11 @@ describe("MatrixEventProcessor", () => {
             const processor = createMatrixEventProcessor();
             return expect(processor.HandleAttachment({
                 content: {
-                    msgtype: "m.video",
+                    body: "filename.webm",
                     info: {
                         size: LARGE_FILE,
                     },
-                    body: "filename.webm",
+                    msgtype: "m.video",
                     url: "mxc://localhost/8000000",
                 },
             }, mxClient)).to.eventually.eq("[filename.webm](https://localhost/8000000)");
@@ -625,11 +632,11 @@ describe("MatrixEventProcessor", () => {
             const processor = createMatrixEventProcessor();
             return expect(processor.HandleAttachment({
                 content: {
-                    msgtype: "m.video",
+                    body: "filename.webm",
                     info: {
                         size: SMALL_FILE,
                     },
-                    body: "filename.webm",
+                    msgtype: "m.video",
                     url: "mxc://localhost/200",
                 },
             }, mxClient)).to.eventually.satisfy((attachment) => {
@@ -642,11 +649,11 @@ describe("MatrixEventProcessor", () => {
             const processor = createMatrixEventProcessor();
             return expect(processor.HandleAttachment({
                 content: {
-                    msgtype: "m.video",
+                    body: "filename.webm",
                     info: {
                         size: 200,
                     },
-                    body: "filename.webm",
+                    msgtype: "m.video",
                     url: "mxc://localhost/8000000",
                 },
             }, mxClient)).to.eventually.eq("[filename.webm](https://localhost/8000000)");
@@ -654,15 +661,15 @@ describe("MatrixEventProcessor", () => {
         it("Should handle stickers.", () => {
             const processor = createMatrixEventProcessor();
             return expect(processor.HandleAttachment({
-                sender: "@test:localhost",
-                type: "m.sticker",
                 content: {
                     body: "Bunnies",
-                    url: "mxc://bunny",
                     info: {
                         mimetype: "image/png",
                     },
+                    url: "mxc://bunny",
                 },
+                sender: "@test:localhost",
+                type: "m.sticker",
             }, mxClient)).to.eventually.satisfy((attachment) => {
                 expect(attachment.name).to.eq("Bunnies.png");
                 return true;
@@ -673,19 +680,17 @@ describe("MatrixEventProcessor", () => {
         it("should handle reply-less events", async () => {
             const processor = createMatrixEventProcessor();
             const result = await processor.GetEmbedForReply({
-                sender: "@test:localhost",
-                type: "m.room.message",
                 content: {
                     body: "Test",
                 },
+                sender: "@test:localhost",
+                type: "m.room.message",
             });
             expect(result).to.be.undefined;
         });
         it("should handle replies without a fallback", async () => {
             const processor = createMatrixEventProcessor();
             const result = await processor.GetEmbedForReply({
-                sender: "@test:localhost",
-                type: "m.room.message",
                 content: {
                     "body": "Test",
                     "m.relates_to": {
@@ -694,6 +699,8 @@ describe("MatrixEventProcessor", () => {
                         },
                     },
                 },
+                sender: "@test:localhost",
+                type: "m.room.message",
             });
             expect(result[0].description).to.be.equal("Hello!");
             expect(result[0].author.name).to.be.equal("Doggo!");
@@ -704,8 +711,6 @@ describe("MatrixEventProcessor", () => {
         it("should handle replies with a missing event", async () => {
             const processor = createMatrixEventProcessor();
             const result = await processor.GetEmbedForReply({
-                sender: "@test:localhost",
-                type: "m.room.message",
                 content: {
                     "body": `> <@doggo:localhost> This is the fake body
 
@@ -716,6 +721,8 @@ This is where the reply goes`,
                         },
                     },
                 },
+                sender: "@test:localhost",
+                type: "m.room.message",
             });
             expect(result[0].description).to.be.equal("Reply with unknown content");
             expect(result[0].author.name).to.be.equal("Unknown");
@@ -726,8 +733,6 @@ This is where the reply goes`,
         it("should handle replies with a valid reply event", async () => {
             const processor = createMatrixEventProcessor();
             const result = await processor.GetEmbedForReply({
-                sender: "@test:localhost",
-                type: "m.room.message",
                 content: {
                     "body": `> <@doggo:localhost> This is the original body
 
@@ -738,6 +743,8 @@ This is where the reply goes`,
                         },
                     },
                 },
+                sender: "@test:localhost",
+                type: "m.room.message",
             });
             expect(result[0].description).to.be.equal("Hello!");
             expect(result[0].author.name).to.be.equal("Doggo!");
@@ -748,8 +755,6 @@ This is where the reply goes`,
         it("should handle replies on top of replies", async () => {
             const processor = createMatrixEventProcessor();
             const result = await processor.GetEmbedForReply({
-                sender: "@test:localhost",
-                type: "m.room.message",
                 content: {
                     "body": `> <@doggo:localhost> This is the first reply
 
@@ -760,6 +765,8 @@ This is the second reply`,
                         },
                     },
                 },
+                sender: "@test:localhost",
+                type: "m.room.message",
             });
             expect(result[0].description).to.be.equal("This is the first reply");
             expect(result[0].author.name).to.be.equal("Doggo!");
@@ -770,8 +777,6 @@ This is the second reply`,
         it("should handle replies with non text events", async () => {
             const processor = createMatrixEventProcessor();
             const result = await processor.GetEmbedForReply({
-                sender: "@test:localhost",
-                type: "m.room.message",
                 content: {
                     "body": `> <@doggo:localhost> sent an image.
 
@@ -782,6 +787,8 @@ This is the reply`,
                         },
                     },
                 },
+                sender: "@test:localhost",
+                type: "m.room.message",
             });
             expect(result[0].description).to.be.equal("Reply with unknown content");
             expect(result[0].author.name).to.be.equal("Doggo!");
diff --git a/test/test_matrixroomhandler.ts b/test/test_matrixroomhandler.ts
index 8d2e7f6281b898a65b886912e9bfb185ae03823b..4b4004dd2d971a314048bae196f0bba1c23a0da7 100644
--- a/test/test_matrixroomhandler.ts
+++ b/test/test_matrixroomhandler.ts
@@ -13,6 +13,9 @@ import {MockGuild} from "./mocks/guild";
 import {Guild} from "discord.js";
 import { Util } from "../src/util";
 
+// we are a test file and thus need those
+/* tslint:disable:no-unused-expression max-file-line-count no-any */
+
 Chai.use(ChaiAsPromised);
 const expect = Chai.expect;
 
@@ -24,11 +27,11 @@ const RoomHandler = (Proxyquire("../src/matrixroomhandler", {
     "./util": {
         Util: {
             DelayedPromise: Util.DelayedPromise,
-            MsgToArgs: Util.MsgToArgs,
-            ParseCommand: Util.ParseCommand,
             GetMxidFromName: () => {
                 return "@123456:localhost";
             },
+            MsgToArgs: Util.MsgToArgs,
+            ParseCommand: Util.ParseCommand,
         },
     },
 })).MatrixRoomHandler;
@@ -53,24 +56,24 @@ function createRH(opts: any = {}) {
     USERSBANNED = 0;
     USERSUNBANNED = 0;
     const bridge = {
+        getBot: () => {
+            return {
+                isRemoteUser: (id) => {
+                    return id !== undefined && id.startsWith("@_discord_");
+                },
+            };
+        },
         getIntent: () => {
             return {
-                sendMessage: (roomId, content) => Promise.resolve(content),
+                ban: () => { USERSBANNED++; return Promise.resolve(); },
                 getClient: () => mxClient,
                 join: () => { USERSJOINED++; },
-                leave: () => { },
                 kick: () => { USERSKICKED++; return Promise.resolve(); },
-                ban: () => { USERSBANNED++; return Promise.resolve(); },
+                leave: () => { },
+                sendMessage: (roomId, content) => Promise.resolve(content),
                 unban: () => { USERSUNBANNED++; return Promise.resolve(); },
             };
         },
-        getBot: () => {
-            return {
-                isRemoteUser: (id) => {
-                    return id !== undefined && id.startsWith("@_discord_");
-                },
-            };
-        },
         getRoomStore: () => {
             return {
                 removeEntriesByMatrixRoomId: () => {
@@ -80,17 +83,19 @@ function createRH(opts: any = {}) {
         },
     };
     const us = {
+        EnsureJoin: () => Promise.resolve(),
         OnMemberState: () => Promise.resolve("user_sync_handled"),
         OnUpdateUser: () => Promise.resolve(),
-        EnsureJoin: () => Promise.resolve(),
     };
     const cs = {
-        OnUpdate: () => Promise.resolve(),
         GetRoomIdsFromChannel: (chan) => {
             return Promise.resolve(["#" + chan.id + ":localhost"]);
         },
+        OnUpdate: () => Promise.resolve(),
     };
     const bot = {
+        ChannelSyncroniser: cs,
+        GetBotId: () => "bot12345",
         GetChannelFromRoomId: (roomid: string) => {
             if (roomid === "!accept:localhost") {
                 const guild = new MockGuild("666666");
@@ -106,10 +111,10 @@ function createRH(opts: any = {}) {
                 return Promise.reject("Roomid not found");
             }
         },
-        GetBotId: () => "bot12345",
-        ProcessMatrixRedact: () => Promise.resolve("redacted"),
-        ProcessMatrixMsgEvent: () => Promise.resolve("processed"),
-        ProcessMatrixStateEvent: () => Promise.resolve("stateevent"),
+        GetGuilds: () => [new MockGuild("123", [])],
+        GetIntentFromDiscordMember: () => {
+            return bridge.getIntent();
+        },
         LookupRoom: (guildid, discordid) => {
             if (guildid !== "123") {
                 return Promise.reject("Guild not found");
@@ -119,15 +124,13 @@ function createRH(opts: any = {}) {
             const channel = new MockChannel();
             return Promise.resolve({channel, botUser: true });
         },
-        GetGuilds: () => [new MockGuild("123", [])],
+        ProcessMatrixMsgEvent: () => Promise.resolve("processed"),
+        ProcessMatrixRedact: () => Promise.resolve("redacted"),
+        ProcessMatrixStateEvent: () => Promise.resolve("stateevent"),
         ThirdpartySearchForChannels: () => {
             return [];
         },
-        GetIntentFromDiscordMember: () => {
-            return bridge.getIntent();
-        },
         UserSyncroniser: us,
-        ChannelSyncroniser: cs,
     };
     const config = new DiscordBridgeConfig();
     config.limits.roomGhostJoinDelay = 0;
@@ -137,19 +140,19 @@ function createRH(opts: any = {}) {
         config.bridge.enableSelfServiceBridging = true;
     }
     const mxClient = {
-        joinRoom: () => {
-            USERSJOINED++;
-            return Promise.resolve();
-        },
         getStateEvent: () => {
             return Promise.resolve(opts.powerLevels || {});
         },
-        setRoomDirectoryVisibilityAppService: () => {
+        joinRoom: () => {
+            USERSJOINED++;
             return Promise.resolve();
         },
         sendReadReceipt: () => {
             return Promise.resolve();
         },
+        setRoomDirectoryVisibilityAppService: () => {
+            return Promise.resolve();
+        },
     };
     const provisioner = {
         AskBridgePermission: () => {
@@ -257,7 +260,9 @@ describe("MatrixRoomHandler", () => {
                 },
             };
             return expect(handler.OnEvent(buildRequest({
-                type: "m.room.message", content: {body: "abc"}}), context)).to.eventually.equal("processed");
+                content: {body: "abc"},
+                type: "m.room.message",
+            }), context)).to.eventually.equal("processed");
         });
         it("should alert if encryption is turned on", () => {
             const handler = createRH();
@@ -269,14 +274,17 @@ describe("MatrixRoomHandler", () => {
                 },
             };
             return expect(handler.OnEvent(buildRequest({
-                type: "m.room.encryption", room_id: "!accept:localhost"}), context)).to.eventually.be.fulfilled;
+                room_id: "!accept:localhost",
+                type: "m.room.encryption",
+            }), context)).to.eventually.be.fulfilled;
         });
         it("should process !discord commands", () => {
             const handler = createRH();
             handler.ProcessCommand = (ev) => Promise.resolve("processedcmd");
             return expect(handler.OnEvent(buildRequest({
-                type: "m.room.message", content: {body: "!discord cmd"}}), null))
-                .to.eventually.equal("processedcmd");
+                content: {body: "!discord cmd"},
+                type: "m.room.message",
+            }), null)).to.eventually.equal("processedcmd");
         });
         it("should ignore regular messages with no linked room", () => {
             const handler = createRH();
@@ -286,8 +294,9 @@ describe("MatrixRoomHandler", () => {
                 },
             };
             return expect(handler.OnEvent(buildRequest({
-                type: "m.room.message", content: {body: "abc"}}), context))
-                .to.be.rejectedWith("Event not processed by bridge");
+                content: {body: "abc"},
+                type: "m.room.message",
+            }), context)).to.be.rejectedWith("Event not processed by bridge");
         });
         it("should process stickers", () => {
             const handler = createRH();
@@ -299,11 +308,11 @@ describe("MatrixRoomHandler", () => {
                 },
             };
             return expect(handler.OnEvent(buildRequest({
-                type: "m.sticker",
                 content: {
                     body: "abc",
                     url: "mxc://abc",
                 },
+                type: "m.sticker",
             }), context)).to.eventually.equal("processed");
         });
     });
@@ -329,8 +338,8 @@ describe("MatrixRoomHandler", () => {
             return expect(handler.ProcessCommand({
                 room_id: "!123:localhost",
             })).to.eventually.be.deep.equal({
-                msgtype: "m.notice",
                 body: "The owner of this bridge does not permit self-service bridging.",
+                msgtype: "m.notice",
             });
         });
         it("should warn if user is not powerful enough with defaults", () => {
@@ -338,8 +347,8 @@ describe("MatrixRoomHandler", () => {
             return expect(handler.ProcessCommand({
                 room_id: "!123:localhost",
             })).to.eventually.be.deep.equal({
-                msgtype: "m.notice",
                 body: "You do not have the required power level in this room to create a bridge to a Discord channel.",
+                msgtype: "m.notice",
             });
         });
         it("should warn if user is not powerful enough with custom state default", () => {
@@ -349,8 +358,8 @@ describe("MatrixRoomHandler", () => {
             return expect(handler.ProcessCommand({
                 room_id: "!123:localhost",
             })).to.eventually.be.deep.equal({
-                msgtype: "m.notice",
                 body: "You do not have the required power level in this room to create a bridge to a Discord channel.",
+                msgtype: "m.notice",
             });
         });
         it("should allow if user is powerful enough with defaults", () => {
@@ -358,8 +367,8 @@ describe("MatrixRoomHandler", () => {
                     users_default: 60,
                 }});
             return handler.ProcessCommand({
-                room_id: "!123:localhost",
                 content: {body: "!discord help"},
+                room_id: "!123:localhost",
             }).then((evt) => {
                 return expect(evt.body.startsWith("Available commands")).to.be.true;
             });
@@ -371,9 +380,9 @@ describe("MatrixRoomHandler", () => {
                     },
                 }});
             return handler.ProcessCommand({
+                content: {body: "!discord help"},
                 room_id: "!123:localhost",
                 sender: "@user:localhost",
-                content: {body: "!discord help"},
             }).then((evt) => {
                 return expect(evt.body.startsWith("Available commands")).to.be.true;
             });
@@ -385,57 +394,67 @@ describe("MatrixRoomHandler", () => {
                     }});
                 const context = {rooms: {}};
                 return handler.ProcessCommand({
-                    room_id: "!123:localhost",
                     content: {body: "!discord bridge 123 456"},
+                    room_id: "!123:localhost",
                 }, context).then((evt) => {
                     return expect(evt.body).to.be.eq("I have bridged this room to your channel");
                 });
             });
             it("will fail to bridge if permissions were denied", () => {
-                const handler: any = createRH({powerLevels: {
+                const handler: any = createRH({
+                    denyBridgePermission: true,
+                    powerLevels: {
                         users_default: 100,
-                    }, denyBridgePermission: true});
+                    },
+                });
                 const context = {rooms: {}};
                 return handler.ProcessCommand({
-                    room_id: "!123:localhost",
                     content: {body: "!discord bridge 123 456"},
+                    room_id: "!123:localhost",
                 }, context).then((evt) => {
                     return expect(evt.body).to.be.eq("The bridge has been declined by the Discord guild");
                 });
             });
             it("will fail to bridge if permissions were denied", () => {
-                const handler: any = createRH({powerLevels: {
+                const handler: any = createRH({
+                    failBridgeMatrix: true,
+                    powerLevels: {
                         users_default: 100,
-                    }, failBridgeMatrix: true});
+                    },
+                });
                 const context = {rooms: {}};
                 return handler.ProcessCommand({
-                    room_id: "!123:localhost",
                     content: {body: "!discord bridge 123 456"},
+                    room_id: "!123:localhost",
                 }, context).then((evt) => {
                     return expect(evt.body).to.be
                         .eq("There was a problem bridging that channel - has the guild owner approved the bridge?");
                 });
             });
             it("will not bridge if a link already exists", () => {
-                const handler: any = createRH({powerLevels: {
+                const handler: any = createRH({
+                    powerLevels: {
                         users_default: 100,
-                    }});
+                    },
+                });
                 const context = {rooms: { remote: true }};
                 return handler.ProcessCommand({
-                    room_id: "!123:localhost",
                     content: {body: "!discord bridge"},
+                    room_id: "!123:localhost",
                 }, context).then((evt) => {
                     return expect(evt.body).to.be.eq("This room is already bridged to a Discord guild.");
                 });
             });
             it("will not bridge without required args", () => {
-                const handler: any = createRH({powerLevels: {
+                const handler: any = createRH({
+                    powerLevels: {
                         users_default: 100,
-                    }});
+                    },
+                });
                 const context = {rooms: {}};
                 return handler.ProcessCommand({
-                    room_id: "!123:localhost",
                     content: {body: "!discord bridge"},
+                    room_id: "!123:localhost",
                 }, context).then((evt) => {
                     return expect(evt.body).to.contain("Invalid syntax");
                 });
@@ -443,59 +462,70 @@ describe("MatrixRoomHandler", () => {
         });
         describe("!discord unbridge", () => {
             it("will unbridge", () => {
-                const handler: any = createRH({powerLevels: {
+                const handler: any = createRH({
+                    powerLevels: {
                         users_default: 100,
-                    }});
+                    },
+                });
                 const context = {rooms: { remote: {
                     data: {
                         plumbed: true,
                     },
-                        } }};
+                } }};
                 return handler.ProcessCommand({
-                    room_id: "!123:localhost",
                     content: {body: "!discord unbridge"},
+                    room_id: "!123:localhost",
                 }, context).then((evt) => {
                     return expect(evt.body).to.be.eq("This room has been unbridged");
                 });
             });
             it("will not unbridge if a link does not exist", () => {
-                const handler: any = createRH({powerLevels: {
+                const handler: any = createRH({
+                    powerLevels: {
                         users_default: 100,
-                    }});
+                    },
+                });
                 const context = {rooms: { remote: undefined }};
                 return handler.ProcessCommand({
-                    room_id: "!123:localhost",
                     content: {body: "!discord unbridge"},
+                    room_id: "!123:localhost",
                 }, context).then((evt) => {
                     return expect(evt.body).to.be.eq("This room is not bridged.");
                 });
             });
             it("will not unbridge non-plumbed rooms", () => {
-                const handler: any = createRH({powerLevels: {
+                const handler: any = createRH({
+                    powerLevels: {
                         users_default: 100,
-                    }});
+                    },
+                });
                 const context = {rooms: { remote: {
-                            data: {
-                                plumbed: false,
-                }}}};
+                    data: {
+                        plumbed: false,
+                    },
+                }}};
                 return handler.ProcessCommand({
-                    room_id: "!123:localhost",
                     content: {body: "!discord unbridge"},
+                    room_id: "!123:localhost",
                 }, context).then((evt) => {
                     return expect(evt.body).to.be.eq("This room cannot be unbridged.");
                 });
             });
             it("will show error if unbridge fails", () => {
-                const handler: any = createRH({powerLevels: {
+                const handler: any = createRH({
+                    failUnbridge: true,
+                    powerLevels: {
                         users_default: 100,
-                    }, failUnbridge: true});
+                    },
+                });
                 const context = {rooms: { remote: {
-                            data: {
-                                plumbed: true,
-                            }}}};
+                    data: {
+                        plumbed: true,
+                    },
+                }}};
                 return handler.ProcessCommand({
-                    room_id: "!123:localhost",
                     content: {body: "!discord unbridge"},
+                    room_id: "!123:localhost",
                 }, context).then((evt) => {
                     return expect(evt.body).to.contain("There was an error unbridging this room.");
                 });
@@ -548,8 +578,8 @@ describe("MatrixRoomHandler", () => {
         it("will return an array", () => {
             const handler: any = createRH({});
             return handler.tpGetLocation("", {
-                guild_id: "",
                 channel_name: "",
+                guild_id: "",
             }).then((channels) => {
                 expect(channels).to.be.a("array");
             });
@@ -597,6 +627,7 @@ describe("MatrixRoomHandler", () => {
             const intent = {
                 getClient: () => {
                     return {
+                        getUserId: () => "@test:localhost",
                         joinRoom: () => {
                             if (shouldFail) {
                                 shouldFail = false;
@@ -604,7 +635,6 @@ describe("MatrixRoomHandler", () => {
                             }
                             return Promise.resolve();
                         },
-                        getUserId: () => "@test:localhost",
                     };
                 },
             };
@@ -637,8 +667,8 @@ describe("MatrixRoomHandler", () => {
             };
             const message = {
                 channel,
-                member,
                 content: "!matrix kick someuser",
+                member,
             };
             return handler.HandleDiscordCommand(message).then(() => {
                 expect(USERSKICKED).equals(1);
@@ -655,8 +685,8 @@ describe("MatrixRoomHandler", () => {
             };
             const message = {
                 channel,
-                member,
                 content: "!matrix kick someuser",
+                member,
             };
             return handler.HandleDiscordCommand(message).then(() => {
                 // tslint:disable-next-line:no-magic-numbers
@@ -674,8 +704,8 @@ describe("MatrixRoomHandler", () => {
             };
             const message = {
                 channel,
-                member,
                 content: "!matrix kick someuser",
+                member,
             };
             return handler.HandleDiscordCommand(message).then(() => {
                 expect(USERSKICKED).equals(0);
@@ -692,8 +722,8 @@ describe("MatrixRoomHandler", () => {
             };
             const message = {
                 channel,
-                member,
                 content: "!matrix ban someuser",
+                member,
             };
             return handler.HandleDiscordCommand(message).then(() => {
                 expect(USERSBANNED).equals(1);
@@ -710,8 +740,8 @@ describe("MatrixRoomHandler", () => {
             };
             const message = {
                 channel,
-                member,
                 content: "!matrix unban someuser",
+                member,
             };
             return handler.HandleDiscordCommand(message).then(() => {
                 expect(USERSUNBANNED).equals(1);
diff --git a/test/test_messageprocessor.ts b/test/test_messageprocessor.ts
index ccdb5bbfe14eb6366db53140c01b78563db5cb57..d9a9d2b805dcd6d20b6c549a429c7141953f2e04 100644
--- a/test/test_messageprocessor.ts
+++ b/test/test_messageprocessor.ts
@@ -6,6 +6,9 @@ import { DiscordBot } from "../src/bot";
 import { MockGuild } from "./mocks/guild";
 import { MockMember } from "./mocks/member";
 
+// we are a test file and thus need those
+/* tslint:disable:no-unused-expression max-file-line-count no-any */
+
 Chai.use(ChaiAsPromised);
 
 const bot = {
@@ -79,6 +82,7 @@ describe("MessageProcessor", () => {
                 color: null,
                 createdAt: null,
                 createdTimestamp: null,
+                description: "Description",
                 fields: null,
                 footer: null,
                 hexColor: null,
@@ -86,11 +90,10 @@ describe("MessageProcessor", () => {
                 message: null,
                 provider: null,
                 thumbnail: null,
-                type: null,
-                video: null,
                 title: "Title",
-                description: "Description",
+                type: null,
                 url: "http://example.com",
+                video: null,
             },
         ];
         msg.content = "message";
@@ -294,8 +297,8 @@ describe("MessageProcessor", () => {
             const msg = new Discord.Message(null, null, null);
             msg.embeds = [
                 new Discord.MessageEmbed(msg, {
-                    title: "TestTitle",
                     description: "TestDescription",
+                    title: "TestTitle",
                 }),
             ];
             const inContent = "";
@@ -307,9 +310,9 @@ describe("MessageProcessor", () => {
             const msg = new Discord.Message(null, null, null);
             msg.embeds = [
                 new Discord.MessageEmbed(msg, {
+                    description: "TestDescription",
                     title: "TestTitle",
                     url: "testurl",
-                    description: "TestDescription",
                 }),
             ];
             const inContent = "";
@@ -333,14 +336,14 @@ describe("MessageProcessor", () => {
             const msg = new Discord.Message(null, null, null);
             msg.embeds = [
                 new Discord.MessageEmbed(msg, {
+                    description: "TestDescription",
                     title: "TestTitle",
                     url: "testurl",
-                    description: "TestDescription",
                 }),
                 new Discord.MessageEmbed(msg, {
+                    description: "TestDescription2",
                     title: "TestTitle2",
                     url: "testurl2",
-                    description: "TestDescription2",
                 }),
             ];
             const inContent = "";
@@ -355,9 +358,9 @@ describe("MessageProcessor", () => {
             const msg = new Discord.Message(null, null, null);
             msg.embeds = [
                 new Discord.MessageEmbed(msg, {
+                    description: "TestDescription",
                     title: "TestTitle",
                     url: "testurl",
-                    description: "TestDescription",
                 }),
             ];
             const inContent = "Content that goes in the message";
diff --git a/test/test_presencehandler.ts b/test/test_presencehandler.ts
index c6c652cbcacde39c0d275d73c84d4600eb9f804c..0cb21732795d80fb200a7356796c9c520a37085d 100644
--- a/test/test_presencehandler.ts
+++ b/test/test_presencehandler.ts
@@ -7,12 +7,18 @@ import { PresenceHandler } from "../src/presencehandler";
 import { DiscordBot } from "../src/bot";
 import { MockUser } from "./mocks/user";
 
+// we are a test file and thus need those
+/* tslint:disable:no-unused-expression max-file-line-count no-any */
+
 Chai.use(ChaiAsPromised);
 const expect = Chai.expect;
 const INTERVAL = 250;
 let lastStatus = null;
 // const assert = Chai.assert;
 const bot = {
+    GetBotId: () => {
+        return "1234";
+    },
     GetIntentFromDiscordMember: (member) => {
         return {
             getClient: () => {
@@ -25,9 +31,6 @@ const bot = {
             },
         };
     },
-    GetBotId: () => {
-        return "1234";
-    },
 };
 
 describe("PresenceHandler", () => {
@@ -140,8 +143,8 @@ describe("PresenceHandler", () => {
                 status_msg: "Do not disturb",
             });
             member.MockSetPresence(new Discord.Presence({
-                status: "dnd",
                 game: new Discord.Game({name: "Test Game"}),
+                status: "dnd",
             }));
             handler.ProcessUser(member);
             Chai.assert.deepEqual(lastStatus, {
@@ -154,8 +157,8 @@ describe("PresenceHandler", () => {
             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"}),
+                status: "online",
             }));
             handler.ProcessUser(member);
             Chai.assert.deepEqual(lastStatus, {
@@ -163,8 +166,8 @@ describe("PresenceHandler", () => {
                 status_msg: "Playing Test Game",
             });
             member.MockSetPresence(new Discord.Presence({
-                status: "online",
                 game: new Discord.Game({name: "Test Game", type: 1}),
+                status: "online",
             }));
             handler.ProcessUser(member);
             Chai.assert.deepEqual(lastStatus, {
diff --git a/test/test_store.ts b/test/test_store.ts
index 9b1956a24e73bf0e427e94749ca03c7300f381a8..6dfc9aaf72898357144f3cdec4e32dbd754c5d46 100644
--- a/test/test_store.ts
+++ b/test/test_store.ts
@@ -5,6 +5,10 @@ import { DiscordStore, CURRENT_SCHEMA } from "../src/store";
 import { DbEmoji } from "../src/db/dbdataemoji";
 import { DbEvent } from "../src/db/dbdataevent";
 import { Log } from "../src/log";
+
+// we are a test file and thus need those
+/* tslint:disable:no-unused-expression max-file-line-count no-any */
+
 Chai.use(ChaiAsPromised);
 const expect = Chai.expect;
 
diff --git a/test/test_usersyncroniser.ts b/test/test_usersyncroniser.ts
index c1daddc4c3d0d17e388e022f8a6bee38a7a9f0c5..8e53c14d28dccc76dae769da30f6228db3bc01d7 100644
--- a/test/test_usersyncroniser.ts
+++ b/test/test_usersyncroniser.ts
@@ -9,6 +9,9 @@ import {MockMember} from "./mocks/member";
 import {MockGuild} from "./mocks/guild";
 import { MockChannel } from "./mocks/channel";
 
+// we are a test file and thus need those
+/* tslint:disable:no-unused-expression max-file-line-count no-any */
+
 Chai.use(ChaiAsPromised);
 const expect = Chai.expect;
 
@@ -49,31 +52,6 @@ function CreateUserSync(remoteUsers: any[] = []): UserSyncroniser {
     SEV_KEY = null;
     SEV_COUNT = 0;
     const bridge: any = {
-        getUserStore: () => {
-            REMOTEUSER_SET = null;
-            LINK_RM_USER = null;
-            LINK_MX_USER = null;
-            return {
-                getRemoteUser: (id) => {
-                    const user = remoteUsers.find((u) => u.id === id);
-                    if (user === undefined) {
-                        return null;
-                    }
-                    return user;
-                },
-                getRemoteUsersFromMatrixId: (id) => {
-                    return remoteUsers.filter((u) => u.id === id);
-                },
-                setRemoteUser: (remoteUser) => {
-                    REMOTEUSER_SET = remoteUser;
-                    return Promise.resolve();
-                },
-                linkUsers: (mxUser, remoteUser) => {
-                    LINK_MX_USER = mxUser;
-                    LINK_RM_USER = remoteUser;
-                },
-            };
-        },
         getIntent: (id) => {
             DISPLAYNAME_SET = null;
             AVATAR_SET = null;
@@ -82,6 +60,16 @@ function CreateUserSync(remoteUsers: any[] = []): UserSyncroniser {
             JOINS = 0;
             LEAVES = 0;
             return {
+                getClient: () => {
+                    return {
+                        sendStateEvent: (roomId, type, content, key) => {
+                            SEV_ROOM_ID = roomId;
+                            SEV_CONTENT = content;
+                            SEV_KEY = key;
+                            SEV_COUNT++;
+                        },
+                    };
+                },
                 join: (roomId) => {
                     JOIN_ROOM_ID = roomId;
                     JOINS++;
@@ -90,34 +78,43 @@ function CreateUserSync(remoteUsers: any[] = []): UserSyncroniser {
                     LEAVE_ROOM_ID = roomId;
                     LEAVES++;
                 },
+                setAvatarUrl: (ava) => {
+                    AVATAR_SET = ava;
+                    return Promise.resolve();
+                },
                 setDisplayName: (dn) => {
                     DISPLAYNAME_SET = dn;
                     return Promise.resolve();
                 },
-                setAvatarUrl: (ava) => {
-                    AVATAR_SET = ava;
-                    return Promise.resolve();
+            };
+        },
+        getUserStore: () => {
+            REMOTEUSER_SET = null;
+            LINK_RM_USER = null;
+            LINK_MX_USER = null;
+            return {
+                getRemoteUser: (id) => {
+                    const user = remoteUsers.find((u) => u.id === id);
+                    if (user === undefined) {
+                        return null;
+                    }
+                    return user;
                 },
-                getClient: () => {
-                    return {
-                        sendStateEvent: (roomId, type, content, key) => {
-                            SEV_ROOM_ID = roomId;
-                            SEV_CONTENT = content;
-                            SEV_KEY = key;
-                            SEV_COUNT++;
-                        },
-                    };
+                getRemoteUsersFromMatrixId: (id) => {
+                    return remoteUsers.filter((u) => u.id === id);
+                },
+                linkUsers: (mxUser, remoteUser) => {
+                    LINK_MX_USER = mxUser;
+                    LINK_RM_USER = remoteUser;
+                },
+                setRemoteUser: (remoteUser) => {
+                    REMOTEUSER_SET = remoteUser;
+                    return Promise.resolve();
                 },
             };
         },
     };
     const discordbot: any = {
-        GetRoomIdsFromGuild: () => {
-            return Promise.resolve(GUILD_ROOM_IDS);
-        },
-        GetIntentFromDiscordMember: (id) => {
-            return bridge.getIntent(id);
-        },
         GetChannelFromRoomId: (id) => {
             if (id === "!found:localhost") {
                 const guild = new MockGuild("666666");
@@ -131,6 +128,12 @@ function CreateUserSync(remoteUsers: any[] = []): UserSyncroniser {
         GetGuilds: () => {
             return [];
         },
+        GetIntentFromDiscordMember: (id) => {
+            return bridge.getIntent(id);
+        },
+        GetRoomIdsFromGuild: () => {
+            return Promise.resolve(GUILD_ROOM_IDS);
+        },
     };
     const config = new DiscordBridgeConfig();
     config.bridge.domain = "localhost";
@@ -231,12 +234,12 @@ describe("UserSyncroniser", () => {
        it("Will create a new user", () => {
            const userSync = CreateUserSync();
            const state: IUserState = {
-               id: "123456",
+               avatarId: null,
+               avatarUrl: null, // Nullable
                createUser: true,
-               mxUserId: "@_discord_123456:localhost",
                displayName: null, // Nullable
-               avatarUrl: null, // Nullable
-               avatarId: null,
+               id: "123456",
+               mxUserId: "@_discord_123456:localhost",
                removeAvatar: false,
            };
            return userSync.ApplyStateToProfile(state).then(() => {
@@ -248,12 +251,12 @@ describe("UserSyncroniser", () => {
        it("Will set a display name", () => {
            const userSync = CreateUserSync();
            const state: IUserState = {
-               id: "123456",
+               avatarId: null,
+               avatarUrl: null, // Nullable
                createUser: true,
-               mxUserId: "@_discord_123456:localhost",
                displayName: "123456", // Nullable
-               avatarUrl: null, // Nullable
-               avatarId: null,
+               id: "123456",
+               mxUserId: "@_discord_123456:localhost",
                removeAvatar: false,
            };
            return userSync.ApplyStateToProfile(state).then(() => {
@@ -269,12 +272,12 @@ describe("UserSyncroniser", () => {
        it("Will set an avatar", () => {
            const userSync = CreateUserSync();
            const state: IUserState = {
-               id: "123456",
+               avatarId: null,
+               avatarUrl: "654321", // Nullable
                createUser: true,
-               mxUserId: "@_discord_123456:localhost",
                displayName: null, // Nullable
-               avatarUrl: "654321", // Nullable
-               avatarId: null,
+               id: "123456",
+               mxUserId: "@_discord_123456:localhost",
                removeAvatar: false,
            };
            return userSync.ApplyStateToProfile(state).then(() => {
@@ -291,12 +294,12 @@ describe("UserSyncroniser", () => {
        it("Will remove an avatar", () => {
            const userSync = CreateUserSync();
            const state: IUserState = {
-               id: "123456",
+               avatarId: null,
+               avatarUrl: null, // Nullable
                createUser: true,
-               mxUserId: "@_discord_123456:localhost",
                displayName: null, // Nullable
-               avatarUrl: null, // Nullable
-               avatarId: null,
+               id: "123456",
+               mxUserId: "@_discord_123456:localhost",
                removeAvatar: true,
            };
            return userSync.ApplyStateToProfile(state).then(() => {
@@ -313,12 +316,12 @@ describe("UserSyncroniser", () => {
        it("will do nothing if nothing needs to be done", () => {
            const userSync = CreateUserSync([new RemoteUser("123456")]);
            const state: IUserState = {
-               id: "123456",
+               avatarId: null,
+               avatarUrl: null, // Nullable
                createUser: false,
-               mxUserId: "@_discord_123456:localhost",
                displayName: null, // Nullable
-               avatarUrl: null, // Nullable
-               avatarId: null,
+               id: "123456",
+               mxUserId: "@_discord_123456:localhost",
                removeAvatar: false,
            };
            return userSync.ApplyStateToProfile(state).then(() => {
@@ -334,9 +337,9 @@ describe("UserSyncroniser", () => {
        it("Will apply a new nick", () => {
            const userSync = CreateUserSync([new RemoteUser("123456")]);
            const state: IGuildMemberState = {
+               displayName: "Good Boy",
                id: "123456",
                mxUserId: "@_discord_123456:localhost",
-               displayName: "Good Boy",
                roles: [],
            };
            return userSync.ApplyStateToRoom(state, "!abc:localhost", "123456").then(() => {
@@ -350,9 +353,9 @@ describe("UserSyncroniser", () => {
        it("Will not apply unchanged nick", () => {
            const userSync = CreateUserSync([new RemoteUser("123456")]);
            const state: IGuildMemberState = {
+               displayName: null,
                id: "123456",
                mxUserId: "@_discord_123456:localhost",
-               displayName: null,
                roles: [],
            };
            return userSync.ApplyStateToRoom(state, "!abc:localhost", "123456").then(() => {
@@ -368,13 +371,13 @@ describe("UserSyncroniser", () => {
            const TESTROLE_COLOR = 1337;
            const TESTROLE_POSITION = 42;
            const state: IGuildMemberState = {
+               displayName: "Good Boy",
                id: "123456",
                mxUserId: "@_discord_123456:localhost",
-               displayName: "Good Boy",
                roles: [
                    {
-                       name: TESTROLE_NAME,
                        color: TESTROLE_COLOR,
+                       name: TESTROLE_NAME,
                        position: TESTROLE_POSITION,
                    },
                ],
@@ -431,8 +434,8 @@ describe("UserSyncroniser", () => {
            const TESTROLE_POSITION = 42;
            member.roles = [
                {
-                   name: TESTROLE_NAME,
                    color: TESTROLE_COLOR,
+                   name: TESTROLE_NAME,
                    position: TESTROLE_POSITION,
                },
            ];
@@ -557,47 +560,37 @@ describe("UserSyncroniser", () => {
             const userSync = CreateUserSync([new RemoteUser("123456")]);
             return Promise.all([
                 expect(userSync.OnMemberState({
-                    origin_server_ts: 10000,
-                    content: {
-
-                    },
+                    content: { },
                     event_id: "Anicent:localhost",
+                    origin_server_ts: 10000,
                     room_id: "!found:localhost",
                     state_key: "123456",
                 }, DELAY_MS)).to.eventually.equal(UserSyncroniser.ERR_NEWER_EVENT, "State 1 Failed"),
                 expect(userSync.OnMemberState({
-                    origin_server_ts: 7000,
-                    content: {
-
-                    },
+                    content: { },
                     event_id: "QuiteOld:localhost",
+                    origin_server_ts: 7000,
                     room_id: "!found:localhost",
                     state_key: "123456",
                 }, DELAY_MS)).to.eventually.equal(UserSyncroniser.ERR_NEWER_EVENT, "State 2 Failed"),
                 expect(userSync.OnMemberState({
-                    origin_server_ts: 3000,
-                    content: {
-
-                    },
+                    content: { },
                     event_id: "FreshEnough:localhost",
+                    origin_server_ts: 3000,
                     room_id: "!found:localhost",
                     state_key: "123456",
                 }, DELAY_MS)).to.eventually.equal(UserSyncroniser.ERR_NEWER_EVENT, "State 3 Failed"),
                 expect(userSync.OnMemberState({
-                    origin_server_ts: 4000,
-                    content: {
-
-                    },
+                    content: { },
                     event_id: "GettingOnABit:localhost",
+                    origin_server_ts: 4000,
                     room_id: "!found:localhost",
                     state_key: "123456",
                 }, DELAY_MS)).to.eventually.equal(UserSyncroniser.ERR_NEWER_EVENT, "State 4 Failed"),
                 expect(userSync.OnMemberState({
-                    origin_server_ts: 100,
-                    content: {
-
-                    },
+                    content: { },
                     event_id: "FreshOutTheOven:localhost",
+                    origin_server_ts: 100,
                     room_id: "!found:localhost",
                     state_key: "123456",
                 }, DELAY_MS)).to.eventually.be.fulfilled,
diff --git a/test/test_util.ts b/test/test_util.ts
index dc48346bf48a8c85bbeaf673c49eb804f24590ec..44ec959cbeb94feb237a67ed92a78a08d1c41158 100644
--- a/test/test_util.ts
+++ b/test/test_util.ts
@@ -3,6 +3,9 @@ import * as ChaiAsPromised from "chai-as-promised";
 
 import { Util, ICommandAction, ICommandParameters } from "../src/util";
 
+// we are a test file and thus need those
+/* tslint:disable:no-unused-expression max-file-line-count no-any */
+
 Chai.use(ChaiAsPromised);
 const expect = Chai.expect;
 
@@ -15,11 +18,11 @@ function CreateMockIntent(members) {
                         const ret = [];
                         for (const member of members[url]) {
                             ret.push({
-                                membership: member.membership,
-                                state_key: member.mxid,
                                 content: {
                                     displayname: member.displayname,
                                 },
+                                membership: member.membership,
+                                state_key: member.mxid,
                             });
                         }
                         return {
@@ -73,9 +76,9 @@ describe("Util", () => {
             const mockRooms = {
                 "/rooms/abc/members": [
                     {
+                        displayname: "GoodBoy",
                         membership: "join",
                         mxid: "@123:localhost",
-                        displayname: "GoodBoy",
                     },
                 ],
             };
@@ -88,14 +91,14 @@ describe("Util", () => {
             const mockRooms = {
                 "/rooms/abc/members": [
                     {
+                        displayname: "GoodBoy",
                         membership: "join",
                         mxid: "@123:localhost",
-                        displayname: "GoodBoy",
                     },
                     {
+                        displayname: "GoodBoy",
                         membership: "join",
                         mxid: "@456:localhost",
-                        displayname: "GoodBoy",
                     },
                 ],
             };
@@ -106,9 +109,9 @@ describe("Util", () => {
             const mockRooms = {
                 "/rooms/abc/members": [
                     {
+                        displayname: "GoodBoy",
                         membership: "join",
                         mxid: "@123:localhost",
-                        displayname: "GoodBoy",
                     },
                 ],
             };
diff --git a/tools/addRoomsToDirectory.ts b/tools/addRoomsToDirectory.ts
index 9d398a9df72349cc959db5e759170fca2f97475e..0bf11300b261496d882e3ed153f4451f8fd2a92f 100644
--- a/tools/addRoomsToDirectory.ts
+++ b/tools/addRoomsToDirectory.ts
@@ -13,25 +13,25 @@ import { Log } from "../src/log";
 const log = new Log("AddRoomsToDirectory");
 const optionDefinitions = [
     {
-        name: "help",
         alias: "h",
-        type: Boolean,
         description: "Display this usage guide.",
+        name: "help",
+        type: Boolean,
     },
     {
-      name: "config",
-      alias: "c",
-      type: String,
-      defaultValue: "config.yaml",
-      description: "The AS config file.",
-      typeLabel: "<config.yaml>",
+        alias: "c",
+        defaultValue: "config.yaml",
+        description: "The AS config file.",
+        name: "config",
+        type: String,
+        typeLabel: "<config.yaml>",
     },
     {
-        name: "store",
         alias: "s",
-        type: String,
         defaultValue: "room-store.db",
         description: "The location of the room store.",
+        name: "store",
+        type: String,
     },
 ];
 
@@ -41,8 +41,9 @@ if (options.help) {
     /* tslint:disable:no-console */
     console.log(usage([
     {
+        content: "A tool to set all the bridged rooms to visible in the directory.",
         header: "Add rooms to directory",
-        content: "A tool to set all the bridged rooms to visible in the directory."},
+    },
     {
         header: "Options",
         optionList: optionDefinitions,
@@ -65,12 +66,12 @@ const clientFactory = new ClientFactory({
 });
 
 const bridge = new Bridge({
-    homeserverUrl: true,
-    registration: true,
-    domain: "rubbish",
     controller: {
         onEvent: () => { },
     },
+    domain: "rubbish",
+    homeserverUrl: true,
+    registration: true,
     roomStore: options.store,
 });
 
diff --git a/tools/adminme.ts b/tools/adminme.ts
index 0f818ae59d0475f0a2bd965b2b52d6f409e0f8b5..2d8cf88a38c659c2980f962d1ebf765fda01484c 100644
--- a/tools/adminme.ts
+++ b/tools/adminme.ts
@@ -11,61 +11,67 @@ import * as usage from "command-line-usage";
 import { DiscordBridgeConfig } from "../src/config";
 
 const optionDefinitions = [
-  {
-    name: "help",
-    alias: "h",
-    type: Boolean,
-    description: "Display this usage guide."},
-  {
-    name: "config",
-    alias: "c",
-    type: String,
-    defaultValue: "config.yaml",
-    description: "The AS config file.",
-    typeLabel: "<config.yaml>" },
-  {
-    name: "roomid",
-    alias: "r",
-    type: String,
-    description: "The roomid to modify"},
-  {
-    name: "userid",
-    alias: "u",
-    type: String,
-    description: "The userid to give powers"},
-  {
-    name: "power",
-    alias: "p",
-    type: Number,
-    defaultValue: 100,
-    description: "The power to set",
-    typeLabel: "<0-100>" },
+    {
+        alias: "h",
+        description: "Display this usage guide.",
+        name: "help",
+        type: Boolean,
+    },
+    {
+        alias: "c",
+        defaultValue: "config.yaml",
+        description: "The AS config file.",
+        name: "config",
+        type: String,
+        typeLabel: "<config.yaml>",
+    },
+    {
+        alias: "r",
+        description: "The roomid to modify",
+        name: "roomid",
+        type: String,
+    },
+    {
+        alias: "u",
+        description: "The userid to give powers",
+        name: "userid",
+        type: String,
+    },
+    {
+        alias: "p",
+        defaultValue: 100,
+        description: "The power to set",
+        name: "power",
+        type: Number,
+        typeLabel: "<0-100>",
+    },
 ];
 
 const options = args(optionDefinitions);
 
 if (options.help) {
-  /* tslint:disable:no-console */
-  console.log(usage([
-    {
-      header: "Admin Me",
-      content: "A tool to give a user a power level in a bot user controlled room."},
-    {
-      header: "Options",
-      optionList: optionDefinitions,
-    },
-  ]));
-  process.exit(0);
+    /* tslint:disable:no-console */
+    console.log(usage([
+        {
+            content: "A tool to give a user a power level in a bot user controlled room.",
+            header: "Admin Me",
+        },
+        {
+            header: "Options",
+            optionList: optionDefinitions,
+        },
+    ]));
+    process.exit(0);
 }
 
 if (!options.roomid) {
-  console.error("Missing roomid parameter. Check -h");
-  process.exit(1);
+    console.error("Missing roomid parameter. Check -h");
+    process.exit(1);
 }
 
 if (!options.userid) {
-  console.error("Missing userid parameter. Check -h");
-  process.exit(1);
+    console.error("Missing userid parameter. Check -h");
+    process.exit(1);
 }
 
 const yamlConfig = yaml.safeLoad(fs.readFileSync("discord-registration.yaml", "utf8"));
@@ -73,13 +79,13 @@ const registration = AppServiceRegistration.fromObject(yamlConfig);
 const config: DiscordBridgeConfig = yaml.safeLoad(fs.readFileSync(options.config, "utf8")) as DiscordBridgeConfig;
 
 if (registration === null) {
- throw new Error("Failed to parse registration file");
+    throw new Error("Failed to parse registration file");
 }
 
 const clientFactory = new ClientFactory({
- appServiceUserId: "@" + registration.sender_localpart + ":" + config.bridge.domain,
- token: registration.as_token,
- url: config.bridge.homeserverUrl,
+    appServiceUserId: "@" + registration.sender_localpart + ":" + config.bridge.domain,
+    token: registration.as_token,
+    url: config.bridge.homeserverUrl,
 });
 const client = clientFactory.getClientAs();
 const intent = new Intent(client, client, {registered: true});
diff --git a/tools/chanfix.ts b/tools/chanfix.ts
index 3824c28e3225fa293ebe07412f7736f9fe0cd707..e9a1d7d07a69ba908305c8d78eb5844767e44720 100644
--- a/tools/chanfix.ts
+++ b/tools/chanfix.ts
@@ -16,18 +16,18 @@ const log = new Log("ChanFix");
 
 const optionDefinitions = [
     {
-        name: "help",
         alias: "h",
-        type: Boolean,
         description: "Display this usage guide.",
+        name: "help",
+        type: Boolean,
     },
     {
-      name: "config",
-      alias: "c",
-      type: String,
-      defaultValue: "config.yaml",
-      description: "The AS config file.",
-      typeLabel: "<config.yaml>",
+        alias: "c",
+        defaultValue: "config.yaml",
+        description: "The AS config file.",
+        name: "config",
+        type: String,
+        typeLabel: "<config.yaml>",
     },
 ];
 
@@ -37,9 +37,10 @@ if (options.help) {
     /* tslint:disable:no-console */
     console.log(usage([
     {
-        header: "Fix bridged channels",
         content: "A tool to fix channels of rooms already bridged " +
-            "to matrix, to make sure their names, icons etc. are correctly."},
+        "to matrix, to make sure their names, icons etc. are correctly.",
+        header: "Fix bridged channels",
+    },
     {
         header: "Options",
         optionList: optionDefinitions,
@@ -72,16 +73,16 @@ const bridge = new Bridge({
     controller: {
         onEvent: () => { },
     },
+    domain: config.bridge.domain,
+    homeserverUrl: config.bridge.homeserverUrl,
     intentOptions: {
         clients: {
             dontJoin: true, // handled manually
       },
     },
-    domain: config.bridge.domain,
-    homeserverUrl: config.bridge.homeserverUrl,
     registration,
-    userStore: config.database.userStorePath,
     roomStore: config.database.roomStorePath,
+    userStore: config.database.userStorePath,
 });
 
 provisioner.SetBridge(bridge);
diff --git a/tools/ghostfix.ts b/tools/ghostfix.ts
index 94dbedc224a85ca6afd4e987e52584113a2dca13..0b6b0ee21ee51c75d32903a5af485f380785821c 100644
--- a/tools/ghostfix.ts
+++ b/tools/ghostfix.ts
@@ -28,18 +28,18 @@ const JOIN_ROOM_SCHEDULE = [
 
 const optionDefinitions = [
     {
-        name: "help",
         alias: "h",
-        type: Boolean,
         description: "Display this usage guide.",
+        name: "help",
+        type: Boolean,
     },
     {
-      name: "config",
-      alias: "c",
-      type: String,
-      defaultValue: "config.yaml",
-      description: "The AS config file.",
-      typeLabel: "<config.yaml>",
+        alias: "c",
+        defaultValue: "config.yaml",
+        description: "The AS config file.",
+        name: "config",
+        type: String,
+        typeLabel: "<config.yaml>",
     },
 ];
 
@@ -49,9 +49,10 @@ if (options.help) {
     /* tslint:disable:no-console */
     console.log(usage([
     {
-        header: "Fix usernames of joined ghosts",
         content: "A tool to fix usernames of ghosts already in " +
-            "matrix rooms, to make sure they represent the correct discord usernames."},
+        "matrix rooms, to make sure they represent the correct discord usernames.",
+        header: "Fix usernames of joined ghosts",
+    },
     {
         header: "Options",
         optionList: optionDefinitions,
@@ -84,16 +85,16 @@ const bridge = new Bridge({
     controller: {
         onEvent: () => { },
     },
+    domain: config.bridge.domain,
+    homeserverUrl: config.bridge.homeserverUrl,
     intentOptions: {
         clients: {
             dontJoin: true, // handled manually
       },
     },
-    domain: config.bridge.domain,
-    homeserverUrl: config.bridge.homeserverUrl,
     registration,
-    userStore: config.database.userStorePath,
     roomStore: config.database.roomStorePath,
+    userStore: config.database.userStorePath,
 });
 
 provisioner.SetBridge(bridge);
diff --git a/tools/userClientTools.ts b/tools/userClientTools.ts
index 94bd2ad9c3f548aa544a675a1e2b1d8c29649002..26029fde3fc509d32c97bafbed84e969575af4ad 100644
--- a/tools/userClientTools.ts
+++ b/tools/userClientTools.ts
@@ -14,94 +14,99 @@ const log = new Log("UserClientTools");
 const PUPPETING_DOC_URL = "https://github.com/Half-Shot/matrix-appservice-discord/blob/develop/docs/puppeting.md";
 
 const optionDefinitions = [
-  {
-    name: "help",
-    alias: "h",
-    type: Boolean,
-    description: "Display this usage guide."},
-  {
-    name: "config",
-    alias: "c",
-    type: String,
-    defaultValue: "config.yaml",
-    description: "The AS config file.",
-    typeLabel: "<config.yaml>" },
-  {
-    name: "add",
-    type: Boolean,
-    description: "Add the user to the database."},
-  {
-    name: "remove",
-    type: Boolean,
-    description: "Remove the user from the database."},
+    {
+        alias: "h",
+        description: "Display this usage guide.",
+        name: "help",
+        type: Boolean,
+    },
+    {
+        alias: "c",
+        defaultValue: "config.yaml",
+        description: "The AS config file.",
+        name: "config",
+        type: String,
+        typeLabel: "<config.yaml>",
+    },
+    {
+        description: "Add the user to the database.",
+        name: "add",
+        type: Boolean,
+    },
+    {
+        description: "Remove the user from the database.",
+        name: "remove",
+        type: Boolean,
+    },
 ];
 
 const options = args(optionDefinitions);
 if (options.help || (options.add && options.remove) || !(options.add || options.remove)) {
-  /* tslint:disable:no-console */
-  console.log(usage([
-    {
-      header: "User Client Tools",
-      content: "A tool to give a user a power level in a bot user controlled room."},
-    {
-      header: "Options",
-      optionList: optionDefinitions,
-    },
-  ]));
-  process.exit(0);
+    /* tslint:disable:no-console */
+    console.log(usage([
+        {
+            content: "A tool to give a user a power level in a bot user controlled room.",
+            header: "User Client Tools",
+        },
+        {
+            header: "Options",
+            optionList: optionDefinitions,
+        },
+    ]));
+    process.exit(0);
 }
 
 const config: DiscordBridgeConfig = yaml.safeLoad(fs.readFileSync(options.config, "utf8"));
 const discordstore = new DiscordStore(config.database ? config.database.filename : "discord.db");
 discordstore.init().then(() => {
-  log.info("Loaded database.");
-  handleUI();
+    log.info("Loaded database.");
+    handleUI();
 }).catch((err) => {
-  log.info("Couldn't load database. Cannot continue.");
-  log.info("Ensure the bridge is not running while using this command.");
-  process.exit(1);
+    log.info("Couldn't load database. Cannot continue.");
+    log.info("Ensure the bridge is not running while using this command.");
+    process.exit(1);
 });
 
 function handleUI() {
-  const rl = readline.createInterface({
-    input: process.stdin,
-    output: process.stdout,
-  });
-  let userid = null;
-  let token = null;
+    const rl = readline.createInterface({
+        input: process.stdin,
+        output: process.stdout,
+    });
+    let userid = null;
+    let token = null;
 
-  rl.question("Please enter your UserID ( ex @Half-Shot:half-shot.uk, @username:matrix.org)", (answeru) => {
-    userid = answeru;
-    if (options.add) {
-      rl.question(`
+    rl.question("Please enter your UserID ( ex @Half-Shot:half-shot.uk, @username:matrix.org)", (answeru) => {
+        userid = answeru;
+        if (options.add) {
+            rl.question(`
 Please enter your Discord Token
 (Instructions for this are on ${PUPPETING_DOC_URL})`, (answert) => {
-        token = answert;
-        rl.close();
-        addUserToken(userid, token).then(() => {
-          log.info("Completed successfully");
-          process.exit(0);
-        }).catch((err) => {
-          log.info("Failed to add, $s", err);
-          process.exit(1);
-        });
-      });
-    } else if (options.remove) {
-      rl.close();
-      discordstore.delete_user_token(userid).then(() => {
-        log.info("Completed successfully");
-        process.exit(0);
-      }).catch((err) => {
-        log.info("Failed to delete, $s", err);
-        process.exit(1);
-      });
-    }
-  });
+                token = answert;
+                rl.close();
+                addUserToken(userid, token).then(() => {
+                    log.info("Completed successfully");
+                    process.exit(0);
+                }).catch((err) => {
+                    log.info("Failed to add, $s", err);
+                    process.exit(1);
+                });
+            });
+        } else if (options.remove) {
+            rl.close();
+            discordstore.delete_user_token(userid).then(() => {
+                log.info("Completed successfully");
+                process.exit(0);
+            }).catch((err) => {
+                log.info("Failed to delete, $s", err);
+                process.exit(1);
+            });
+        }
+    });
 }
 
 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);
-  });
+    const clientFactory = new DiscordClientFactory(discordstore);
+    return clientFactory.getDiscordId(token).then((discordid: string) => {
+        return discordstore.add_user_token(userid, discordid, token);
+    });
 }