diff --git a/src/bot.ts b/src/bot.ts
index a77c32ed0f1714c076dffe06fd19faa7cf69198a..5242f2cce2eed15b41b7cd41e35d0ea4ce655b4b 100644
--- a/src/bot.ts
+++ b/src/bot.ts
@@ -36,6 +36,7 @@ import { Log } from "./log";
 import * as Discord from "discord.js";
 import * as mime from "mime";
 import { IMatrixEvent, IMatrixMediaInfo } from "./matrixtypes";
+import { DiscordCommandHandler } from "./discordcommandhandler";
 
 const log = new Log("DiscordBot");
 
@@ -74,6 +75,7 @@ export class DiscordBot {
     private channelSync: ChannelSyncroniser;
     private roomHandler: MatrixRoomHandler;
     private provisioner: Provisioner;
+    private discordCommandHandler: DiscordCommandHandler;
     /* Caches */
     private roomIdsForGuildCache: Map<string, {roomIds: string[], ts: number}> = new Map();
 
@@ -99,6 +101,7 @@ export class DiscordBot {
             new MatrixEventProcessorOpts(config, bridge, this),
         );
         this.channelSync = new ChannelSyncroniser(bridge, config, this, store.roomStore);
+        this.discordCommandHandler = new DiscordCommandHandler(this);
         // init vars
         this.sentMessages = [];
         this.discordMessageQueue = {};
@@ -711,7 +714,7 @@ export class DiscordBot {
 
         // check if it is a command to process by the bot itself
         if (msg.content.startsWith("!matrix")) {
-            await this.roomHandler.HandleDiscordCommand(msg);
+            await this.discordCommandHandler.Process(msg);
             return;
         }
 
diff --git a/src/discordcommandhandler.ts b/src/discordcommandhandler.ts
new file mode 100644
index 0000000000000000000000000000000000000000..1d76d544a7158210149bc5f70ad6948ccdc72c90
--- /dev/null
+++ b/src/discordcommandhandler.ts
@@ -0,0 +1,120 @@
+import { DiscordBot } from "./bot";
+import * as Discord from "discord.js";
+import { Uitl, ICommandActions, ICommandParameters } from "./util";
+export class DiscordCommandHandler {
+    constructor(
+        private discord: DiscordBot;
+    ) { }
+
+    public async Process(msg: Discord.Message) {
+        if (!(msg.channel as Discord.TextChannel).guild) {
+            await msg.channel.send("**ERROR:** only available for guild channels");
+            return;
+        }
+
+        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.ModerationActionGenerator(msg.channel as Discord.TextChannel, "ban", "Banned"),
+            },
+            kick: {
+                description: "Kicks a user on the matrix side",
+                params: ["name"],
+                permission: "KICK_MEMBERS",
+                run: this.ModerationActionGenerator(msg.channel as Discord.TextChannel, "kick", "Kicked"),
+            },
+            unban: {
+                description: "Unbans a user on the matrix side",
+                params: ["name"],
+                permission: "BAN_MEMBERS",
+                run: this.ModerationActionGenerator(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 Discord.PermissionResolvable)) {
+                    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`;
+            }
+            await msg.channel.send(replyHelpMessage);
+            return;
+        }
+
+        if (!actions[command]) {
+            await msg.channel.send("**Error:** unknown command. Try `!matrix help` to see all commands");
+            return;
+        }
+
+        if (!msg.member.hasPermission(actions[command].permission as Discord.PermissionResolvable)) {
+            await 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;
+        }
+
+        await msg.channel.send(replyMessage);
+    }
+
+    private ModerationActionGenerator(discordChannel: Discord.TextChannel, funcKey: string, action: string) {
+        return async ({name}) => {
+            let allChannelMxids: string[] = [];
+            await Promise.all(discordChannel.guild.channels.map(async (chan) => {
+                try {
+                    const chanMxids = await this.discord.ChannelSyncroniser.GetRoomIdsFromChannel(chan);
+                    allChannelMxids = allChannelMxids.concat(chanMxids);
+                } catch (e) {
+                    // pass, non-text-channel
+                }
+            }));
+            let errorMsg = "";
+            await Promise.all(allChannelMxids.map(async (chanMxid) => {
+                const intent = this.bridge.getIntent();
+                try {
+                    await 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}`;
+        };
+    }
+}
diff --git a/src/matrixcommandhandler.ts b/src/matrixcommandhandler.ts
index a116d6f5f127220f2cbb347e5a6906a024b4e1ce..36ed7d71c1cfed3f029fb0680e4073e8363555e0 100644
--- a/src/matrixcommandhandler.ts
+++ b/src/matrixcommandhandler.ts
@@ -35,7 +35,7 @@ export class MatrixCommandHandler {
         }
     }
 
-    public async ProcessCommand(event: IMatrixEvent, context: BridgeContext) {
+    public async Process(event: IMatrixEvent, context: BridgeContext) {
         const intent = this.bridge.getIntent();
         if (!(await this.isBotInRoom(event.room_id))) {
             log.warn(`Bot is not in ${event.room_id}. Ignoring command`);
diff --git a/src/matrixeventprocessor.ts b/src/matrixeventprocessor.ts
index 28945add25b48c88d2916a52682cc2e429a99d63..7c7f6a516ccfd7114329f177280c2429eefb76ce 100644
--- a/src/matrixeventprocessor.ts
+++ b/src/matrixeventprocessor.ts
@@ -115,7 +115,7 @@ export class MatrixEventProcessor {
                 event.content!.body &&
                 event.content!.body!.startsWith("!discord");
             if (isBotCommand) {
-                await this.mxCommandHandler.ProcessCommand(event, context);
+                await this.mxCommandHandler.Process(event, context);
                 return;
             } else if (context.rooms.remote) {
                 const srvChanPair = context.rooms.remote.roomId.substr("_discord".length).split("_", ROOM_NAME_PARTS);
diff --git a/src/matrixroomhandler.ts b/src/matrixroomhandler.ts
index c648f6e503884cd2395bf076b76a375959c72fd9..a91d4c76eb22b7e366a73a8e8ee093f76d85783e 100644
--- a/src/matrixroomhandler.ts
+++ b/src/matrixroomhandler.ts
@@ -28,7 +28,7 @@ import {
 import { DiscordBridgeConfig } from "./config";
 
 import * as Discord from "discord.js";
-import { Util, ICommandActions, ICommandParameters } from "./util";
+import { Util } from "./util";
 import { Provisioner } from "./provisioner";
 import { Log } from "./log";
 const log = new Log("MatrixRoomHandler");
@@ -218,117 +218,6 @@ export class MatrixRoomHandler {
         throw {err: "Unsupported", code: HTTP_UNSUPPORTED};
     }
 
-    public async HandleDiscordCommand(msg: Discord.Message) {
-        if (!(msg.channel as Discord.TextChannel).guild) {
-            await msg.channel.send("**ERROR:** only available for guild channels");
-        }
-
-        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 Discord.PermissionResolvable)) {
-                    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`;
-            }
-            await msg.channel.send(replyHelpMessage);
-            return;
-        }
-
-        if (!actions[command]) {
-            await msg.channel.send("**Error:** unknown command. Try `!matrix help` to see all commands");
-            return;
-        }
-
-        if (!msg.member.hasPermission(actions[command].permission as Discord.PermissionResolvable)) {
-            await 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;
-        }
-
-        await msg.channel.send(replyMessage);
-    }
-
-    private DiscordModerationActionGenerator(discordChannel: Discord.TextChannel, funcKey: string, action: string) {
-        return async ({name}) => {
-            let allChannelMxids: string[] = [];
-            await Promise.all(discordChannel.guild.channels.map(async (chan) => {
-                try {
-                    const chanMxids = await this.discord.ChannelSyncroniser.GetRoomIdsFromChannel(chan);
-                    allChannelMxids = allChannelMxids.concat(chanMxids);
-                } catch (e) {
-                    // pass, non-text-channel
-                }
-            }));
-            let errorMsg = "";
-            await Promise.all(allChannelMxids.map(async (chanMxid) => {
-                const intent = this.bridge.getIntent();
-                try {
-                    await 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 async joinRoom(intent: Intent, roomIdOrAlias: string, member?: Discord.GuildMember): Promise<void> {
         let currentSchedule = JOIN_ROOM_SCHEDULE[0];
         const doJoin = async () => {
diff --git a/test/test_matrixcommandhandler.ts b/test/test_matrixcommandhandler.ts
index 8bef1b1462b331713d18f43a834cc69eb97587b0..78f4b13fab38a350fa2e93ab1a71cd3780a513d9 100644
--- a/test/test_matrixcommandhandler.ts
+++ b/test/test_matrixcommandhandler.ts
@@ -96,24 +96,24 @@ function createCH(opts: any = {}) {
 }
 
 describe("MatrixCommandHandler", () => {
-    describe("ProcessCommand", () => {
+    describe("Process", () => {
         it("should not process command if not in room", async () => {
             const handler: any = createCH({disableSS: true});
-            const ret = await handler.ProcessCommand({
+            const ret = await handler.Process({
                 room_id: "!666:localhost",
             });
             expect(ret).to.be.undefined;
         });
         it("should warn if self service is disabled", async () => {
             const handler: any = createCH({disableSS: true});
-            await handler.ProcessCommand({
+            await handler.Process({
                 room_id: "!123:localhost",
             });
             expect(MESSAGESENT.body).equals("The owner of this bridge does not permit self-service bridging.");
         });
         it("should warn if user is not powerful enough with defaults", async () => {
             const handler: any = createCH();
-            await handler.ProcessCommand({
+            await handler.Process({
                 room_id: "!123:localhost",
             });
             expect(MESSAGESENT.body).equals("You do not have the required power level in this room to " +
@@ -123,7 +123,7 @@ describe("MatrixCommandHandler", () => {
             const handler: any = createCH({powerLevels: {
                 state_default: 67,
             }});
-            await handler.ProcessCommand({
+            await handler.Process({
                 room_id: "!123:localhost",
             });
             expect(MESSAGESENT.body).equals("You do not have the required power level in this room to " +
@@ -133,7 +133,7 @@ describe("MatrixCommandHandler", () => {
             const handler: any = createCH({powerLevels: {
                 users_default: 60,
             }});
-            const evt = await handler.ProcessCommand({
+            const evt = await handler.Process({
                 content: {body: "!discord help"},
                 room_id: "!123:localhost",
             });
@@ -145,7 +145,7 @@ describe("MatrixCommandHandler", () => {
                  "@user:localhost": 100,
                 },
             }});
-            const evt = await handler.ProcessCommand({
+            const evt = await handler.Process({
                 content: {body: "!discord help"},
                 room_id: "!123:localhost",
                 sender: "@user:localhost",
@@ -158,7 +158,7 @@ describe("MatrixCommandHandler", () => {
                         users_default: 100,
                     }});
                 const context = {rooms: {}};
-                const evt = await handler.ProcessCommand({
+                const evt = await handler.Process({
                     content: {body: "!discord bridge 123 456"},
                     room_id: "!123:localhost",
                 }, context);
@@ -172,7 +172,7 @@ describe("MatrixCommandHandler", () => {
                     },
                 });
                 const context = {rooms: {}};
-                const evt = await handler.ProcessCommand({
+                const evt = await handler.Process({
                     content: {body: "!discord bridge 123 456"},
                     room_id: "!123:localhost",
                 }, context);
@@ -186,7 +186,7 @@ describe("MatrixCommandHandler", () => {
                     },
                 });
                 const context = {rooms: {}};
-                const evt = await handler.ProcessCommand({
+                const evt = await handler.Process({
                     content: {body: "!discord bridge 123 456"},
                     room_id: "!123:localhost",
                 }, context);
@@ -200,7 +200,7 @@ describe("MatrixCommandHandler", () => {
                     },
                 });
                 const context = {rooms: { remote: true }};
-                const evt = await handler.ProcessCommand({
+                const evt = await handler.Process({
                     content: {body: "!discord bridge"},
                     room_id: "!123:localhost",
                 }, context);
@@ -213,7 +213,7 @@ describe("MatrixCommandHandler", () => {
                     },
                 });
                 const context = {rooms: {}};
-                const evt = await handler.ProcessCommand({
+                const evt = await handler.Process({
                     content: {body: "!discord bridge"},
                     room_id: "!123:localhost",
                 }, context);
@@ -224,7 +224,7 @@ describe("MatrixCommandHandler", () => {
                         users_default: 100,
                     }});
                 const context = {rooms: {}};
-                const evt = await handler.ProcessCommand({
+                const evt = await handler.Process({
                     content: {body: "!discord bridge 123/456"},
                     room_id: "!123:localhost",
                 }, context);
@@ -243,7 +243,7 @@ describe("MatrixCommandHandler", () => {
                         plumbed: true,
                     },
                 } }};
-                const evt = await handler.ProcessCommand({
+                const evt = await handler.Process({
                     content: {body: "!discord unbridge"},
                     room_id: "!123:localhost",
                 }, context);
@@ -256,7 +256,7 @@ describe("MatrixCommandHandler", () => {
                     },
                 });
                 const context = {rooms: { remote: undefined }};
-                const evt = await handler.ProcessCommand({
+                const evt = await handler.Process({
                     content: {body: "!discord unbridge"},
                     room_id: "!123:localhost",
                 }, context);
@@ -273,7 +273,7 @@ describe("MatrixCommandHandler", () => {
                         plumbed: false,
                     },
                 }}};
-                const evt = await handler.ProcessCommand({
+                const evt = await handler.Process({
                     content: {body: "!discord unbridge"},
                     room_id: "!123:localhost",
                 }, context);
@@ -291,7 +291,7 @@ describe("MatrixCommandHandler", () => {
                         plumbed: true,
                     },
                 }}};
-                const evt = await handler.ProcessCommand({
+                const evt = await handler.Process({
                     content: {body: "!discord unbridge"},
                     room_id: "!123:localhost",
                 }, context);