diff --git a/src/bot.ts b/src/bot.ts
index 1649dd72406cdbfaa6b282567d6f17f63bdbf106..ed6288719cd2a42a10826bfc28a6bade143c756a 100644
--- a/src/bot.ts
+++ b/src/bot.ts
@@ -1,7 +1,7 @@
 import { DiscordBridgeConfig } from "./config";
 import { DiscordClientFactory } from "./clientfactory";
 import { DiscordStore } from "./store";
-import { DbGuildEmoji } from "./db/dbdataemoji";
+import { DbEmoji } from "./db/dbdataemoji";
 import { DbEvent } from "./db/dbdataevent";
 import { MatrixUser, RemoteUser, Bridge, Entry } from "matrix-appservice-bridge";
 import { Util } from "./util";
@@ -19,6 +19,9 @@ import { Provisioner } from "./provisioner";
 // messages get delayed from discord.
 const MSG_PROCESS_DELAY = 750;
 const MIN_PRESENCE_UPDATE_DELAY = 250;
+const AVATAR_SIZE = 512; // matrix -> discord
+const MAX_DISCORD_NAME_LENGTH = 32;
+const DISCORD_NAME_START = 0;
 // 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 {
@@ -308,19 +311,18 @@ export class DiscordBot {
     });
   }
 
-  public async GetGuildEmoji(guild: Discord.Guild, id: string): Promise<string> {
-    const dbEmoji: DbGuildEmoji = await this.store.Get(DbGuildEmoji, {emoji_id: id});
+  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) {
-      // Fetch the emoji
-      if (!guild.emojis.has(id)) {
-        throw new Error("The guild does not contain the emoji");
-      }
-      const emoji: Discord.Emoji = guild.emojis.get(id);
+      const url = "https://cdn.discordapp.com/emojis/" + id + (animated ? ".gif" : ".png");
       const intent = this.bridge.getIntent();
-      const mxcUrl = (await Util.UploadContentFromUrl(emoji.url, intent, emoji.name)).mxcUrl;
-      dbEmoji.EmojiId = emoji.id;
-      dbEmoji.GuildId = guild.id;
-      dbEmoji.Name = emoji.name;
+      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);
     }
diff --git a/src/db/dbdataemoji.ts b/src/db/dbdataemoji.ts
index 46d8b79cd424423455521b407ad74af4bf77b46f..d0534e7cc25e3c3d2ff44e4dfca8a7a1ec2334ad 100644
--- a/src/db/dbdataemoji.ts
+++ b/src/db/dbdataemoji.ts
@@ -2,10 +2,10 @@ import { DiscordStore } from "../store";
 import { IDbData } from "./dbdatainterface";
 import * as log from "npmlog";
 
-export class DbGuildEmoji implements IDbData {
+export class DbEmoji implements IDbData {
     public EmojiId: string;
-    public GuildId: string;
     public Name: string;
+    public Animated: boolean;
     public MxcUrl: string;
     public CreatedAt: number;
     public UpdatedAt: number;
@@ -14,15 +14,15 @@ export class DbGuildEmoji implements IDbData {
     public RunQuery(store: DiscordStore, params: any): Promise<null> {
         return store.db.getAsync(`
             SELECT *
-            FROM guild_emoji
+            FROM emoji
             WHERE emoji_id = $id`, {
                 $id: params.emoji_id,
             }).then((row) => {
                 this.Result = row !== undefined;
                 if (this.Result) {
                     this.EmojiId = row.emoji_id;
-                    this.GuildId = row.guild_id;
                     this.Name = row.name;
+                    this.Animated = row.animated;
                     this.MxcUrl = row.mxc_url;
                     this.CreatedAt = row.created_at;
                     this.UpdatedAt = row.updated_at;
@@ -34,12 +34,12 @@ export class DbGuildEmoji implements IDbData {
         this.CreatedAt = new Date().getTime();
         this.UpdatedAt = this.CreatedAt;
         return store.db.runAsync(`
-            INSERT INTO guild_emoji
-            (emoji_id,guild_id,name,mxc_url,created_at,updated_at)
-            VALUES ($emoji_id,$guild_id,$name,$mxc_url,$created_at,$updated_at);`, {
+            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,
-                $guild_id: this.GuildId,
                 $name: this.Name,
+                $animated: this.Animated,
                 $mxc_url: this.MxcUrl,
                 $created_at: this.CreatedAt,
                 $updated_at: this.UpdatedAt,
@@ -50,16 +50,16 @@ export class DbGuildEmoji implements IDbData {
         // Ensure this has incremented by 1 for Insert+Update operations.
         this.UpdatedAt = new Date().getTime() + 1;
         return store.db.runAsync(`
-            UPDATE guild_emoji
+            UPDATE emoji
             SET name = $name,
+            animated = $animated,
             mxc_url = $mxc_url,
             updated_at = $updated_at
             WHERE
-            emoji_id = $emoji_id
-            AND guild_id = $guild_id`, {
+            emoji_id = $emoji_id`, {
                 $emoji_id: this.EmojiId,
-                $guild_id: this.GuildId,
                 $name: this.Name,
+                $animated: this.Animated,
                 $mxc_url: this.MxcUrl,
                 $updated_at: this.UpdatedAt,
         });
diff --git a/src/db/schema/v7.ts b/src/db/schema/v7.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5bb8b70a6a67e63d4a6a2e0c9671bd693f351510
--- /dev/null
+++ b/src/db/schema/v7.ts
@@ -0,0 +1,37 @@
+import {IDbSchema} from "./dbschema";
+import {DiscordStore} from "../../store";
+import {DiscordClientFactory} from "../../clientfactory";
+import * as log from "npmlog";
+import * as Bluebird from "bluebird";
+
+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.execAsync(`
+        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;
+      `).error(() => {
+        // ignore errors
+        log.warning("DiscordSchema", "Failed to migrate old data to new table");
+      });
+    });
+  }
+
+  public rollBack(store: DiscordStore): Promise <null> {
+    return store.db.execAsync(
+      `DROP TABLE IF EXISTS emoji;`,
+    );
+  }
+}
diff --git a/src/messageprocessor.ts b/src/messageprocessor.ts
index cac98a036261a07861e7c3d27b641e27ecff5e0f..57e1cb35ad4af9a1d9c3b5151a155e9f73105eea 100644
--- a/src/messageprocessor.ts
+++ b/src/messageprocessor.ts
@@ -9,12 +9,13 @@ const USER_REGEX_POSTMARK = /&lt;@!?([0-9]*)&gt;/g;
 const CHANNEL_REGEX = /<#?([0-9]*)>/g;
 const CHANNEL_REGEX_POSTMARK = /&lt;#?([0-9]*)&gt;/g;
 const EMOJI_SIZE = "1em";
-const EMOJI_REGEX = /<:(\w+):([0-9]*)>/g;
-const EMOJI_REGEX_POSTMARK = /&lt;:(\w+):([0-9]*)&gt;/g;
+const EMOJI_REGEX = /<(a?):(\w+):([0-9]*)>/g;
+const EMOJI_REGEX_POSTMARK = /&lt;(a?):(\w+):([0-9]*)&gt;/g;
 const MATRIX_TO_LINK = "https://matrix.to/#/";
 
-const NAME_EMOJI_REGEX_GROUP = 1;
-const ID_EMOJI_REGEX_GROUP = 2;
+const ANIMATED_EMOJI_REGEX_GROUP = 1;
+const NAME_EMOJI_REGEX_GROUP = 2;
+const ID_EMOJI_REGEX_GROUP = 3;
 
 marked.setOptions({
     sanitize: true,
@@ -144,11 +145,12 @@ export class MessageProcessor {
     public async ReplaceEmoji(content: string, msg: Discord.Message): Promise<string> {
         let results = EMOJI_REGEX.exec(content);
         while (results !== null) {
+            const animated = results[ANIMATED_EMOJI_REGEX_GROUP] === "a";
             const name = results[NAME_EMOJI_REGEX_GROUP];
             const id = results[ID_EMOJI_REGEX_GROUP];
             try {
-                // we still fetch the mxcUrl to check if the emoji is valid
-                const mxcUrl = await this.opts.bot.GetGuildEmoji(msg.guild, id);
+                // we still fetch the mxcUrl to check if the emoji is valid=
+                const mxcUrl = await this.bot.GetEmoji(name, animated, id);
                 content = content.replace(results[0], `:${name}:`);
             } catch (ex) {
                 log.warn("MessageProcessor",
@@ -163,10 +165,11 @@ export class MessageProcessor {
     public async ReplaceEmojiPostmark(content: string, msg: Discord.Message): Promise<string> {
         let results = EMOJI_REGEX_POSTMARK.exec(content);
         while (results !== null) {
+            const animated = results[ANIMATED_EMOJI_REGEX_GROUP] === "a";
             const name = escapeHtml(results[NAME_EMOJI_REGEX_GROUP]);
             const id = results[ID_EMOJI_REGEX_GROUP];
             try {
-                const mxcUrl = await this.opts.bot.GetGuildEmoji(msg.guild, id);
+                const mxcUrl = await this.bot.GetEmoji(name, animated, id);
                 content = content.replace(results[0],
                     `<img alt="${name}" src="${mxcUrl}" style="height: ${EMOJI_SIZE};"/>`);
             } catch (ex) {
diff --git a/src/store.ts b/src/store.ts
index 6ae5d09e3e25878207d4bfbdf5dc85adb948dc18..6bb4ec47129243d6775658c5c837b9482bf3f5dd 100644
--- a/src/store.ts
+++ b/src/store.ts
@@ -4,7 +4,7 @@ import * as Bluebird from "bluebird";
 import * as fs from "fs";
 import { IDbSchema } from "./db/schema/dbschema";
 import { IDbData} from "./db/dbdatainterface";
-const CURRENT_SCHEMA = 6;
+const CURRENT_SCHEMA = 7;
 /**
  * Stores data for specific users and data not specific to rooms.
  */
@@ -136,22 +136,22 @@ export class DiscordStore {
 
   public get_user_discord_ids(userId: string): Promise<string[]> {
     log.silly("SQL", "get_user_discord_ids => %s", userId);
-    return this.db.getAsync(
+    return this.db.allAsync(
       `
       SELECT discord_id
       FROM user_id_discord_id
-      WHERE user_id = $userId
+      WHERE user_id = $userId;
       `, {
         $userId: userId,
       },
     ).then( (rows) => {
       if (rows !== undefined) {
-        rows.map((row) => row.discord_id);
+        return rows.map((row) => row.discord_id);
       } else {
         return [];
       }
     }).catch( (err) => {
-      log.error("DiscordStore", "Error getting discord ids  %s", err.Error);
+      log.error("DiscordStore", "Error getting discord ids: %s", err.Error);
       throw err;
     });
   }
diff --git a/test/test_messageprocessor.ts b/test/test_messageprocessor.ts
index 9e3cf5d838adaeb7d06e2983e263db90a1b9a223..063a29d80d226e4ca9dde2557ebc5ced1c0c87c4 100644
--- a/test/test_messageprocessor.ts
+++ b/test/test_messageprocessor.ts
@@ -16,7 +16,7 @@ log.level = "silly";
 
 // const assert = Chai.assert;
 const bot = {
-    GetGuildEmoji: (guild: Discord.Guild, id: string): Promise<string> => {
+    GetEmoji: (name: string, animated: boolean, id: string): Promise<string> => {
         if (id === "3333333") {
             return Promise.resolve("mxc://image");
         } else {
diff --git a/test/test_store.ts b/test/test_store.ts
index 4d6c2bd969eb25da1539ba41b5b58213c98d7751..5ba015a11e8b8962c45631cac394a86f4469e807 100644
--- a/test/test_store.ts
+++ b/test/test_store.ts
@@ -3,7 +3,7 @@ import * as ChaiAsPromised from "chai-as-promised";
 // import * as Proxyquire from "proxyquire";
 import { DiscordStore } from "../src/store";
 import * as log from "npmlog";
-import { DbGuildEmoji } from "../src/db/dbdataemoji";
+import { DbEmoji } from "../src/db/dbdataemoji";
 import { DbEvent } from "../src/db/dbdataevent";
 
 Chai.use(ChaiAsPromised);
@@ -29,13 +29,13 @@ describe("DiscordStore", () => {
       })).to.eventually.be.fulfilled;
     });
   });
-  describe("Get|Insert|Update<DbGuildEmoji>", () => {
+  describe("Get|Insert|Update<DbEmoji>", () => {
     it("should insert successfully", () => {
       const store = new DiscordStore(":memory:");
       return expect(store.init().then(() => {
-        const emoji = new DbGuildEmoji();
+        const emoji = new DbEmoji();
         emoji.EmojiId = "123";
-        emoji.GuildId = "456";
+        emoji.Animated = false;
         emoji.Name = "TestEmoji";
         emoji.MxcUrl = "TestUrl";
         return store.Insert(emoji);
@@ -44,37 +44,37 @@ describe("DiscordStore", () => {
     it("should get successfully", async () => {
         const store = new DiscordStore(":memory:");
         await store.init();
-        const insertEmoji = new DbGuildEmoji();
+        const insertEmoji = new DbEmoji();
         insertEmoji.EmojiId = "123";
-        insertEmoji.GuildId = "456";
+        insertEmoji.Animated = false;
         insertEmoji.Name = "TestEmoji";
         insertEmoji.MxcUrl = "TestUrl";
         await store.Insert(insertEmoji);
-        const getEmoji = await store.Get(DbGuildEmoji, {emoji_id: "123"});
+        const getEmoji = await store.Get(DbEmoji, {emoji_id: "123"});
         Chai.assert.equal(getEmoji.Name, "TestEmoji");
         Chai.assert.equal(getEmoji.MxcUrl, "TestUrl");
     });
     it("should not return nonexistant emoji", async () => {
         const store = new DiscordStore(":memory:");
         await store.init();
-        const getEmoji = await store.Get(DbGuildEmoji, {emoji_id: "123"});
+        const getEmoji = await store.Get(DbEmoji, {emoji_id: "123"});
         Chai.assert.isFalse(getEmoji.Result);
     });
     it("should update successfully", async () => {
         const store = new DiscordStore(":memory:");
         await store.init();
-        const insertEmoji = new DbGuildEmoji();
+        const insertEmoji = new DbEmoji();
         insertEmoji.EmojiId = "123";
-        insertEmoji.GuildId = "456";
+        insertEmoji.Animated = false;
         insertEmoji.Name = "TestEmoji";
         insertEmoji.MxcUrl = "TestUrl";
         await store.Insert(insertEmoji);
         insertEmoji.EmojiId = "123";
-        insertEmoji.GuildId = "456";
+        insertEmoji.Animated = false;
         insertEmoji.Name = "TestEmoji2";
         insertEmoji.MxcUrl = "NewURL";
         await store.Update(insertEmoji);
-        const getEmoji = await store.Get(DbGuildEmoji, {emoji_id: "123"});
+        const getEmoji = await store.Get(DbEmoji, {emoji_id: "123"});
         Chai.assert.equal(getEmoji.Name, "TestEmoji2");
         Chai.assert.equal(getEmoji.MxcUrl, "NewURL");
         Chai.assert.notEqual(getEmoji.CreatedAt, getEmoji.UpdatedAt);