diff --git a/src/matrixeventprocessor.ts b/src/matrixeventprocessor.ts
index f0b5f8112206ae32efb845c20e0e700659b080c8..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 } from "./matrixmessageprocessor";
+import { MatrixMessageProcessor, IMatrixMessageProcessorParams } from "./matrixmessageprocessor";
 
 import { Log } from "./log";
 const log = new Log("MatrixEventProcessor");
@@ -102,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 1829609e1d7eaec76c3512085e8daeaa6c78f15b..fbb81d3729a63ef5df2727281b95a686dc773097 100644
--- a/src/matrixmessageprocessor.ts
+++ b/src/matrixmessageprocessor.ts
@@ -3,23 +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 interface IMatrixMessageProcessorParams {
+    displayname?: string;
+    mxClient?: MatrixClient;
+    roomId?: string;
+    userId?: string;
+}
+
 export class MatrixMessageProcessor {
     private guild: Discord.Guild;
     private listDepth: number = 0;
     private listBulletPoints: string[] = ["●", "○", "■", "‣"];
+    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
@@ -33,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}_`;
             }
@@ -49,12 +59,24 @@ export class MatrixMessageProcessor {
         return reply;
     }
 
-    private escapeDiscord(msg: string): string {
+    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");
 
-        msg = msg.replace(/@room/g, "@here");
+        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");
+            }
+        }
         const escapeChars = ["\\", "*", "_", "~", "`"];
         escapeChars.forEach((char) => {
             msg = msg.replace(new RegExp("\\" + char, "g"), "\\" + char);
@@ -152,7 +174,7 @@ export class MatrixMessageProcessor {
         }
 
         if (!emoji) {
-            return this.escapeDiscord(name);
+            return await this.escapeDiscord(name);
         }
         return `<${emoji.animated ? "a" : ""}:${emoji.name}:${emoji.id}>`;
     }
@@ -232,7 +254,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_matrixmessageprocessor.ts b/test/test_matrixmessageprocessor.ts
index 3434e628eb31fdd79658f070dca53027017fc5bb..2a48834be6978b87c0b5ca614a4f66213585f808 100644
--- a/test/test_matrixmessageprocessor.ts
+++ b/test/test_matrixmessageprocessor.ts
@@ -13,6 +13,23 @@ import { MatrixMessageProcessor } from "../src/matrixmessageprocessor";
 
 const expect = Chai.expect;
 
+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") {
@@ -65,13 +82,6 @@ describe("MatrixMessageProcessor", () => {
             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);
-            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");
-        });
     });
     describe("FormatMessage / formatted_body / simple", () => {
         it("leaves blank stuff untouched", async () => {
@@ -259,13 +269,6 @@ code
             const result = await mp.FormatMessage(msg, guild as any);
             expect(result).is.equal("*yay?*");
         });
-        it("Converts @room to @here", async () => {
-            const mp = new MatrixMessageProcessor(bot);
-            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 () => {
@@ -305,6 +308,76 @@ 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);