diff --git a/config/config.sample.yaml b/config/config.sample.yaml
index 925df2bbadf7195dd2049b2c01c901c61620e0fa..146668def098cd7a639b253fb4cf49030c6ea3b3 100644
--- a/config/config.sample.yaml
+++ b/config/config.sample.yaml
@@ -19,20 +19,11 @@ bridge:
   disablePresence: false
   # Disable sending typing notifications when somebody on Discord types.
   disableTypingNotifications: false
-  # Disable parsing discord usernames out of matrix messages so
-  # that it highlights discord users.
-  # WARNING: Not always 100% accurate, but close enough usually.
-  disableDiscordMentions: false
   # Disable deleting messages on Discord if a message is redacted on Matrix.
   disableDeletionForwarding: false
   # Enable users to bridge rooms using !discord commands. See
   # https://t2bot.io/discord for instructions.
   enableSelfServiceBridging: false
-  # For both below, a space is inserted after @ to stop the mentions working.
-  # Disable relaying @everyone to Discord. Non-puppeted users can abuse this.
-  disableEveryoneMention: false
-  # Disable relaying @here to Discord. Non-puppeted users can abuse this.
-  disableHereMention: false
 # Authentication configuration for the discord bot.
 auth:
   clientID: "12345"
diff --git a/config/config.schema.yaml b/config/config.schema.yaml
index 4f832fa6ce069b1a2560c318a806e09c9127b00a..17b816ca6060f16f7bd0cd4e6872ce2c9d102a08 100644
--- a/config/config.schema.yaml
+++ b/config/config.schema.yaml
@@ -16,16 +16,10 @@ properties:
             type: "boolean"
           disableTypingNotifications:
             type: "boolean"
-          disableDiscordMentions:
-            type: "boolean"
           disableDeletionForwarding:
             type: "boolean"
           enableSelfServiceBridging:
             type: "boolean"
-          disableEveryoneMention:
-            type: "boolean"
-          disableHereMention:
-            type: "boolean"
     auth:
         type: "object"
         required: ["botToken", "clientID"]
diff --git a/src/matrixeventprocessor.ts b/src/matrixeventprocessor.ts
index d0128e257e0274c1c99a85dacb20021a1a722ad3..2ad0107368de6ebf72a54f592d7917a9a968eca2 100644
--- a/src/matrixeventprocessor.ts
+++ b/src/matrixeventprocessor.ts
@@ -8,7 +8,7 @@ import * as mime from "mime";
 import { MatrixUser, Bridge } from "matrix-appservice-bridge";
 import { Client as MatrixClient } from "matrix-js-sdk";
 import { IMatrixEvent, IMatrixEventContent, IMatrixMessage } from "./matrixtypes";
-import { MatrixMessageProcessor, MatrixMessageProcessorOpts } from "./matrixmessageprocessor";
+import { MatrixMessageProcessor, IMatrixMessageProcessorParams } from "./matrixmessageprocessor";
 
 import { Log } from "./log";
 const log = new Log("MatrixEventProcessor");
@@ -44,13 +44,7 @@ export class MatrixEventProcessor {
         this.config = opts.config;
         this.bridge = opts.bridge;
         this.discord = opts.discord;
-        this.matrixMsgProcessor = new MatrixMessageProcessor(
-            this.discord,
-            new MatrixMessageProcessorOpts(
-                this.config.bridge.disableEveryoneMention,
-                this.config.bridge.disableHereMention,
-            ),
-        );
+        this.matrixMsgProcessor = new MatrixMessageProcessor(this.discord);
     }
 
     public StateEventToMessage(event: IMatrixEvent, channel: Discord.TextChannel): string | undefined {
@@ -108,9 +102,18 @@ export class MatrixEventProcessor {
             log.warn(`Trying to fetch member state or profile for ${event.sender} failed`, err);
         }
 
+        const params = {
+            mxClient,
+            roomId: event.room_id,
+            userId: event.sender,
+        } as IMatrixMessageProcessorParams;
+        if (profile) {
+            params.displayname = profile.displayname;
+        }
+
         let body: string = "";
         if (event.type !== "m.sticker") {
-            body = await this.matrixMsgProcessor.FormatMessage(event.content as IMatrixMessage, channel.guild, profile);
+            body = await this.matrixMsgProcessor.FormatMessage(event.content as IMatrixMessage, channel.guild, params);
         }
 
         const messageEmbed = new Discord.RichEmbed();
diff --git a/src/matrixmessageprocessor.ts b/src/matrixmessageprocessor.ts
index 190a372a9651adcf3c7a81655940b850c3111a30..27dee33618da60db6507c1c0897888b2b22694a7 100644
--- a/src/matrixmessageprocessor.ts
+++ b/src/matrixmessageprocessor.ts
@@ -3,27 +3,33 @@ import { IMatrixMessage, IMatrixEvent } from "./matrixtypes";
 import * as Parser from "node-html-parser";
 import { Util } from "./util";
 import { DiscordBot } from "./bot";
+import { Client as MatrixClient } from "matrix-js-sdk";
 
 const MIN_NAME_LENGTH = 2;
 const MAX_NAME_LENGTH = 32;
 const MATRIX_TO_LINK = "https://matrix.to/#/";
 
-export class MatrixMessageProcessorOpts {
-    constructor(readonly disableEveryone: boolean = true, readonly disableHere: boolean = true) { }
+export interface IMatrixMessageProcessorParams {
+    displayname?: string;
+    mxClient?: MatrixClient;
+    roomId?: string;
+    userId?: string;
 }
 
 export class MatrixMessageProcessor {
     private guild: Discord.Guild;
     private listDepth: number = 0;
     private listBulletPoints: string[] = ["●", "○", "■", "‣"];
-    constructor(public bot: DiscordBot, public opts: MatrixMessageProcessorOpts) { }
+    private params?: IMatrixMessageProcessorParams;
+    constructor(public bot: DiscordBot) { }
     public async FormatMessage(
         msg: IMatrixMessage,
         guild: Discord.Guild,
-        profile?: IMatrixEvent | null,
+        params?: IMatrixMessageProcessorParams,
     ): Promise<string> {
         this.guild = guild;
         this.listDepth = 0;
+        this.params = params;
         let reply = "";
         if (msg.formatted_body) {
             // parser needs everything wrapped in html elements
@@ -37,15 +43,15 @@ export class MatrixMessageProcessor {
             reply = await this.walkNode(parsed);
             reply = reply.replace(/\s*$/, ""); // trim off whitespace at end
         } else {
-            reply = this.escapeDiscord(msg.body);
+            reply = await this.escapeDiscord(msg.body);
         }
 
         if (msg.msgtype === "m.emote") {
-            if (profile &&
-                profile.displayname &&
-                profile.displayname.length >= MIN_NAME_LENGTH &&
-                profile.displayname.length <= MAX_NAME_LENGTH) {
-                reply = `_${profile.displayname} ${reply}_`;
+            if (params &&
+                params.displayname &&
+                params.displayname.length >= MIN_NAME_LENGTH &&
+                params.displayname.length <= MAX_NAME_LENGTH) {
+                reply = `_${params.displayname} ${reply}_`;
             } else {
                 reply = `_${reply}_`;
             }
@@ -53,14 +59,24 @@ export class MatrixMessageProcessor {
         return reply;
     }
 
-    private escapeDiscord(msg: string): string {
-        if (this.opts.disableEveryone) {
-            msg = msg.replace(/@everyone/g, "@ everyone");
-        }
-        if (this.opts.disableHere) {
-            msg = msg.replace(/@here/g, "@ here");
+    private async escapeDiscord(msg: string): Promise<string> {
+        // \u200B is the zero-width space --> they still look the same but don't mention
+        msg = msg.replace(/@everyone/g, "@\u200Beveryone");
+        msg = msg.replace(/@here/g, "@\u200Bhere");
+
+        if (msg.includes("@room") && this.params && this.params.mxClient && this.params.roomId && this.params.userId) {
+            // let's check for more complex logic if @room should be replaced
+            const res: IMatrixEvent = await this.params.mxClient.getStateEvent(this.params.roomId, "m.room.power_levels");
+            if (
+                res && res.users
+                && res.users[this.params.userId] !== undefined
+                && res.notifications
+                && res.notifications.room !== undefined
+                && res.users[this.params.userId] >= res.notifications.room
+            ) {
+                msg = msg.replace(/@room/g, "@here");
+            }
         }
-        msg = msg.replace(/@room/g, "@here");
         const escapeChars = ["\\", "*", "_", "~", "`"];
         msg = msg.split(" ").map((s) => {
             if (s.match(/^https?:\/\//)) {
@@ -173,7 +189,7 @@ export class MatrixMessageProcessor {
         }
 
         if (!emoji) {
-            return this.escapeDiscord(name);
+            return await this.escapeDiscord(name);
         }
         return `<${emoji.animated ? "a" : ""}:${emoji.name}:${emoji.id}>`;
     }
@@ -253,7 +269,7 @@ export class MatrixMessageProcessor {
             if ((node as Parser.TextNode).text === "\n") {
                 return "";
             }
-            return this.escapeDiscord((node as Parser.TextNode).text);
+            return await this.escapeDiscord((node as Parser.TextNode).text);
         } else if (node.nodeType === Parser.NodeType.ELEMENT_NODE) {
             const nodeHtml = node as Parser.HTMLElement;
             switch (nodeHtml.tagName) {
diff --git a/src/matrixtypes.ts b/src/matrixtypes.ts
index 22a876945404b4499cbae7b7c78a3eba65e85760..9e72460f93ae884d79ca4f4e37fd196813939661 100644
--- a/src/matrixtypes.ts
+++ b/src/matrixtypes.ts
@@ -23,6 +23,8 @@ export interface IMatrixEvent {
     content?: IMatrixEventContent;
     unsigned?: any; // tslint:disable-line no-any
     origin_server_ts?: number;
+    users?: any; // tslint:disable-line no-any
+    notifications?: any; // tslint:disable-line no-any
 }
 
 export interface IMatrixMessage {
diff --git a/test/test_matrixeventprocessor.ts b/test/test_matrixeventprocessor.ts
index 2f2a8bff85ddb91f42083bb76372c4825420e3bc..3d61f0ee22444532ac03cb2aaa214b07d313a770 100644
--- a/test/test_matrixeventprocessor.ts
+++ b/test/test_matrixeventprocessor.ts
@@ -59,11 +59,7 @@ const mxClient = {
     },
 };
 
-function createMatrixEventProcessor(
-    disableMentions: boolean = false,
-    disableEveryone = false,
-    disableHere = false,
-): MatrixEventProcessor {
+function createMatrixEventProcessor(): MatrixEventProcessor {
     const bridge = {
         getBot: () => {
             return {
@@ -134,9 +130,6 @@ function createMatrixEventProcessor(
         },
     };
     const config = new DiscordBridgeConfig();
-    config.bridge.disableDiscordMentions = disableMentions;
-    config.bridge.disableEveryoneMention = disableEveryone;
-    config.bridge.disableHereMention = disableHere;
 
     const Util = Object.assign(require("../src/util").Util, {
         DownloadFile: (name: string) => {
@@ -375,26 +368,26 @@ describe("MatrixEventProcessor", () => {
             Chai.assert.equal(author!.url, "https://matrix.to/#/@test:localhost");
         });
 
-        it("Should remove everyone mentions if configured.", async () => {
-            const processor = createMatrixEventProcessor(false, true);
+        it("Should remove everyone mentions.", async () => {
+            const processor = createMatrixEventProcessor();
             const embeds = await processor.EventToEmbed({
                 content: {
                     body: "@everyone Hello!",
                 },
                 sender: "@test:localhost",
             } as IMatrixEvent, mockChannel as any);
-            Chai.assert.equal(embeds.messageEmbed.description, "@ everyone Hello!");
+            Chai.assert.equal(embeds.messageEmbed.description, "@\u200Beveryone Hello!");
         });
 
-        it("Should remove here mentions if configured.", async () => {
-            const processor = createMatrixEventProcessor(false, false, true);
+        it("Should remove here mentions.", async () => {
+            const processor = createMatrixEventProcessor();
             const embeds = await processor.EventToEmbed({
                 content: {
                     body: "@here Hello!",
                 },
                 sender: "@test:localhost",
             } as IMatrixEvent, mockChannel as any);
-            Chai.assert.equal(embeds.messageEmbed.description, "@ here Hello!");
+            Chai.assert.equal(embeds.messageEmbed.description, "@\u200Bhere Hello!");
         });
 
         it("Should replace /me with * displayname, and italicize message", async () => {
diff --git a/test/test_matrixmessageprocessor.ts b/test/test_matrixmessageprocessor.ts
index 46667dc426550fefb911e0ee9bd0926fbc05959a..90587095f58d03ed1b58e0c4b44149524865f0e4 100644
--- a/test/test_matrixmessageprocessor.ts
+++ b/test/test_matrixmessageprocessor.ts
@@ -6,14 +6,30 @@ import { MockChannel } from "./mocks/channel";
 import { MockEmoji } from "./mocks/emoji";
 import { DiscordBot } from "../src/bot";
 import { DbEmoji } from "../src/db/dbdataemoji";
-import { MatrixMessageProcessor, MatrixMessageProcessorOpts } from "../src/matrixmessageprocessor";
+import { MatrixMessageProcessor } from "../src/matrixmessageprocessor";
 
 // we are a test file and thus need those
 /* tslint:disable:no-unused-expression max-file-line-count no-any */
 
 const expect = Chai.expect;
 
-const opts = new MatrixMessageProcessorOpts();
+const mxClient = {
+    getStateEvent: async (roomId, stateType, _) => {
+        if (stateType === "m.room.power_levels") {
+            return {
+                notifications: {
+                    room: 50,
+                },
+                users: {
+                    "@nopower:localhost": 0,
+                    "@power:localhost": 100,
+                },
+            };
+        }
+        return null;
+    }
+};
+
 const bot = {
     GetEmojiByMxc: async (mxc: string): Promise<DbEmoji> => {
         if (mxc === "mxc://real_emote:localhost") {
@@ -46,100 +62,86 @@ function getHtmlMessage(msg: string, msgtype: string = "m.text") {
 describe("MatrixMessageProcessor", () => {
     describe("FormatMessage / body / simple", () => {
         it("leaves blank stuff untouched", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getPlainMessage("hello world!");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("hello world!");
         });
         it("escapes simple stuff", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getPlainMessage("hello *world* how __are__ you?");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("hello \\*world\\* how \\_\\_are\\_\\_ you?");
         });
         it("escapes more complex stuff", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getPlainMessage("wow \\*this\\* is cool");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("wow \\\\\\*this\\\\\\* is cool");
         });
-        it("Converts @room to @here", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
-            const guild = new MockGuild("1234");
-            const msg = getPlainMessage("hey @room");
-            const result = await mp.FormatMessage(msg, guild as any);
-            expect(result).is.equal("hey @here");
-        });
-        it("doesn't discord-escape links", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
-            const guild = new MockGuild("1234");
-            const msg = getPlainMessage("http://example.com/_test_/");
-            const result = await mp.FormatMessage(msg, guild as any);
-            expect(result).is.equal("http://example.com/_test_/");
-        });
     });
     describe("FormatMessage / formatted_body / simple", () => {
         it("leaves blank stuff untouched", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("hello world!");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("hello world!");
         });
         it("un-escapes simple stuff", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("foxes &amp; foxes");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("foxes & foxes");
         });
         it("converts italic formatting", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("this text is <em>italic</em> and so is <i>this one</i>");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("this text is *italic* and so is *this one*");
         });
         it("converts bold formatting", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("wow some <b>bold</b> and <strong>more</strong> boldness!");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("wow some **bold** and **more** boldness!");
         });
         it("converts underline formatting", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("to be <u>underlined</u> or not to be?");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("to be __underlined__ or not to be?");
         });
         it("converts strike formatting", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("does <del>this text</del> exist?");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("does ~~this text~~ exist?");
         });
         it("converts code", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("WOW this is <code>some awesome</code> code");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("WOW this is `some awesome` code");
         });
         it("converts multiline-code", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("<p>here</p><pre><code>is\ncode\n</code></pre><p>yay</p>");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("here```\nis\ncode\n```yay");
         });
         it("converts multiline language code", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage(`<p>here</p>
 <pre><code class="language-js">is
@@ -150,14 +152,14 @@ code
             expect(result).is.equal("here```js\nis\ncode\n```yay");
         });
         it("handles linebreaks", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("line<br>break");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("line\nbreak");
         });
         it("handles <hr>", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("test<hr>foxes");
             const result = await mp.FormatMessage(msg, guild as any);
@@ -166,42 +168,42 @@ code
     });
     describe("FormatMessage / formatted_body / complex", () => {
         it("html unescapes stuff inside of code", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("<code>is &lt;em&gt;italic&lt;/em&gt;?</code>");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("`is <em>italic</em>?`");
         });
         it("html unescapes inside of pre", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("<pre><code>wow &amp;</code></pre>");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("```\nwow &```");
         });
         it("doesn't parse inside of code", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("<code>*yay*</code>");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("`*yay*`");
         });
         it("doesn't parse inside of pre", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("<pre><code>*yay*</code></pre>");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("```\n*yay*```");
         });
         it("parses new lines", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("<em>test</em><br><strong>ing</strong>");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("*test*\n**ing**");
         });
         it("drops mx-reply", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("<mx-reply><blockquote>message</blockquote></mx-reply>test reply");
             const result = await mp.FormatMessage(msg, guild as any);
@@ -238,7 +240,7 @@ code
     });
     describe("FormatMessage / formatted_body / discord", () => {
         it("Parses user pills", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const member = new MockMember("12345", "TestUsername", guild);
             guild.members.set("12345", member);
@@ -247,7 +249,7 @@ code
             expect(result).is.equal("<@12345>");
         });
         it("Ignores invalid user pills", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const member = new MockMember("12345", "TestUsername", guild);
             guild.members.set("12345", member);
@@ -256,7 +258,7 @@ code
             expect(result).is.equal("[TestUsername](https://matrix.to/#/@_discord_789:localhost)");
         });
         it("Parses channel pills", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const channel = new MockChannel("12345", guild, "text", "SomeChannel");
             guild.channels.set("12345", channel as any);
@@ -266,7 +268,7 @@ code
             expect(result).is.equal("<#12345>");
         });
         it("Handles invalid channel pills", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const channel = new MockChannel("12345", guild, "text", "SomeChannel");
             guild.channels.set("12345", channel as any);
@@ -275,37 +277,30 @@ code
             expect(result).is.equal("https://matrix.to/#/#_discord_1234_789:localhost");
         });
         it("Handles external channel pills", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("<a href=\"https://matrix.to/#/#matrix:matrix.org\">#SomeChannel</a>");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("https://matrix.to/#/#matrix:matrix.org");
         });
         it("Ignores links without href", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("<a><em>yay?</em></a>");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("*yay?*");
         });
         it("Ignores links with non-matrix href", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("<a href=\"http://example.com\"><em>yay?</em></a>");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("[*yay?*](http://example.com)");
         });
-        it("Converts @room to @here", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
-            const guild = new MockGuild("1234");
-            const msg = getHtmlMessage("hey @room");
-            const result = await mp.FormatMessage(msg, guild as any);
-            expect(result).is.equal("hey @here");
-        });
     });
     describe("FormatMessage / formatted_body / emoji", () => {
         it("Inserts emoji by name", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const emoji = new MockEmoji("123456", "test_emoji");
             guild.emojis.set("123456", emoji);
@@ -314,7 +309,7 @@ code
             expect(result).is.equal("<:test_emoji:123456>");
         });
         it("Inserts emojis by mxc url", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const emoji = new MockEmoji("123456", "test_emoji");
             guild.emojis.set("123456", emoji);
@@ -323,7 +318,7 @@ code
             expect(result).is.equal("<:test_emoji:123456>");
         });
         it("ignores unknown mxc urls", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const emoji = new MockEmoji("123456", "test_emoji");
             guild.emojis.set("123456", emoji);
@@ -332,7 +327,7 @@ code
             expect(result).is.equal("yay");
         });
         it("ignores with no alt / title, too", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const emoji = new MockEmoji("123456", "test_emoji");
             guild.emojis.set("123456", emoji);
@@ -341,30 +336,100 @@ code
             expect(result).is.equal("");
         });
     });
+    describe("FormatMessage / formatted_body / matrix", () => {
+        it("escapes @everyone", async () => {
+            const mp = new MatrixMessageProcessor(bot);
+            const guild = new MockGuild("1234");
+            const msg = getPlainMessage("hey @everyone");
+            const result = await mp.FormatMessage(msg, guild as any);
+            expect(result).is.equal("hey @\u200Beveryone");
+        });
+        it("escapes @here", async () => {
+            const mp = new MatrixMessageProcessor(bot);
+            const guild = new MockGuild("1234");
+            const msg = getPlainMessage("hey @here");
+            const result = await mp.FormatMessage(msg, guild as any);
+            expect(result).is.equal("hey @\u200Bhere");
+        });
+        it("converts @room to @here, if sufficient power", async () => {
+            const mp = new MatrixMessageProcessor(bot);
+            const guild = new MockGuild("1234");
+            const msg = getPlainMessage("hey @room");
+            const params = {
+                mxClient,
+                roomId: "!123456:localhost",
+                userId: "@power:localhost",
+            };
+            const result = await mp.FormatMessage(msg, guild as any, params as any);
+            expect(result).is.equal("hey @here");
+        });
+        it("ignores @room to @here conversion, if insufficient power", async () => {
+            const mp = new MatrixMessageProcessor(bot);
+            const guild = new MockGuild("1234");
+            const msg = getPlainMessage("hey @room");
+            const params = {
+                mxClient,
+                roomId: "!123456:localhost",
+                userId: "@nopower:localhost",
+            };
+            const result = await mp.FormatMessage(msg, guild as any, params as any);
+            expect(result).is.equal("hey @room");
+        });
+        it("handles /me for normal names", async () => {
+            const mp = new MatrixMessageProcessor(bot);
+            const guild = new MockGuild("1234");
+            const msg = getPlainMessage("floofs", "m.emote");
+            const params = {
+                displayname: "fox",
+            };
+            const result = await mp.FormatMessage(msg, guild as any, params as any);
+            expect(result).is.equal("_fox floofs_");
+        });
+        it("handles /me for short names", async () => {
+            const mp = new MatrixMessageProcessor(bot);
+            const guild = new MockGuild("1234");
+            const msg = getPlainMessage("floofs", "m.emote");
+            const params = {
+                displayname: "f",
+            };
+            const result = await mp.FormatMessage(msg, guild as any, params as any);
+            expect(result).is.equal("_floofs_");
+        });
+        it("handles /me for long names", async () => {
+            const mp = new MatrixMessageProcessor(bot);
+            const guild = new MockGuild("1234");
+            const msg = getPlainMessage("floofs", "m.emote");
+            const params = {
+                displayname: "foxfoxfoxfoxfoxfoxfoxfoxfoxfoxfoxfox",
+            };
+            const result = await mp.FormatMessage(msg, guild as any, params as any);
+            expect(result).is.equal("_floofs_");
+        });
+    });
     describe("FormatMessage / formatted_body / blockquotes", () => {
         it("parses single blockquotes", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("<blockquote>hey</blockquote>there");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("> hey\n\nthere");
         });
         it("parses double blockquotes", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("<blockquote><blockquote>hey</blockquote>you</blockquote>there");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("> > hey\n> \n> you\n\nthere");
         });
         it("parses blockquotes with <p>", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage("<blockquote>\n<p>spoky</p>\n</blockquote>\n<p>test</p>\n");
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("> spoky\n\ntest");
         });
         it("parses double blockquotes with <p>", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage(`<blockquote>
 <blockquote>
@@ -380,7 +445,7 @@ code
     });
     describe("FormatMessage / formatted_body / lists", () => {
         it("parses simple unordered lists", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage(`<p>soru</p>
 <ul>
@@ -393,7 +458,7 @@ code
             expect(result).is.equal("soru\n● test\n● ing\n\nmore");
         });
         it("parses nested unordered lists", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage(`<p>foxes</p>
 <ul>
@@ -411,7 +476,7 @@ code
             expect(result).is.equal("foxes\n● awesome\n● floofy\n    ○ fur\n    ○ tail\n\nyay!");
         });
         it("parses more nested unordered lists", async () => {
-            const mp = new MatrixMessageProcessor(bot, opts);
+            const mp = new MatrixMessageProcessor(bot);
             const guild = new MockGuild("1234");
             const msg = getHtmlMessage(`<p>foxes</p>
 <ul>
@@ -431,7 +496,7 @@ code
         });
     });
     it("parses simple ordered lists", async () => {
-        const mp = new MatrixMessageProcessor(bot, opts);
+        const mp = new MatrixMessageProcessor(bot);
         const guild = new MockGuild("1234");
         const msg = getHtmlMessage(`<p>oookay</p>
 <ol>
@@ -444,7 +509,7 @@ code
         expect(result).is.equal("oookay\n1. test\n2. test more\n\nok?");
     });
     it("parses nested ordered lists", async () => {
-        const mp = new MatrixMessageProcessor(bot, opts);
+        const mp = new MatrixMessageProcessor(bot);
         const guild = new MockGuild("1234");
         const msg = getHtmlMessage(`<p>and now</p>
 <ol>
@@ -463,7 +528,7 @@ code
         expect(result).is.equal("and now\n1. test\n2. test more\n    1. and more\n    2. more?\n3. done!\n\nok?");
     });
     it("parses ordered lists with different start", async () => {
-        const mp = new MatrixMessageProcessor(bot, opts);
+        const mp = new MatrixMessageProcessor(bot);
         const guild = new MockGuild("1234");
         const msg = getHtmlMessage(`<ol start="5">
 <li>test</li>
@@ -473,7 +538,7 @@ code
         expect(result).is.equal("\n5. test\n6. test more");
     });
     it("parses ul in ol", async () => {
-        const mp = new MatrixMessageProcessor(bot, opts);
+        const mp = new MatrixMessageProcessor(bot);
         const guild = new MockGuild("1234");
         const msg = getHtmlMessage(`<ol>
 <li>test</li>
@@ -488,7 +553,7 @@ code
         expect(result).is.equal("\n1. test\n2. test more\n    ○ asdf\n    ○ jklö");
     });
     it("parses ol in ul", async () => {
-        const mp = new MatrixMessageProcessor(bot, opts);
+        const mp = new MatrixMessageProcessor(bot);
         const guild = new MockGuild("1234");
         const msg = getHtmlMessage(`<ul>
 <li>test</li>