diff --git a/package-lock.json b/package-lock.json
index b8a96d3d8f23d7655b8f0f43c395e715b5b2f1b1..cfb06075bd3cfa08843b8795ecfa0a5b898a4682 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -132,24 +132,70 @@
       "integrity": "sha512-EzRFg92bRSD1W/zeuNkeGwph0nkWf+pP2l/lYW4/5hav7RjKKBN5kV1Ix7Tvi0CMu3pC4Wi/U7rNisiJMR3ORg==",
       "dev": true
     },
+    "@types/body-parser": {
+      "version": "1.17.1",
+      "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.17.1.tgz",
+      "integrity": "sha512-RoX2EZjMiFMjZh9lmYrwgoP9RTpAjSHiJxdp4oidAQVO02T7HER3xj9UKue5534ULWeqVEkujhWcyvUce+d68w==",
+      "requires": {
+        "@types/connect": "*",
+        "@types/node": "*"
+      }
+    },
     "@types/chai": {
       "version": "3.5.2",
       "resolved": "https://registry.npmjs.org/@types/chai/-/chai-3.5.2.tgz",
       "integrity": "sha1-wRzSgX06QBt7oPWkIPNcVhObHB4=",
       "dev": true
     },
+    "@types/color-name": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
+      "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
+    },
     "@types/command-line-args": {
       "version": "5.0.0",
       "resolved": "https://registry.npmjs.org/@types/command-line-args/-/command-line-args-5.0.0.tgz",
       "integrity": "sha512-4eOPXyn5DmP64MCMF8ePDvdlvlzt2a+F8ZaVjqmh2yFCpGjc1kI3kGnCFYX9SCsGTjQcWIyVZ86IHCEyjy/MNg==",
       "dev": true
     },
+    "@types/connect": {
+      "version": "3.4.33",
+      "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz",
+      "integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==",
+      "requires": {
+        "@types/node": "*"
+      }
+    },
+    "@types/express": {
+      "version": "4.17.2",
+      "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.2.tgz",
+      "integrity": "sha512-5mHFNyavtLoJmnusB8OKJ5bshSzw+qkMIBAobLrIM48HJvunFva9mOa6aBwh64lBFyNwBbs0xiEFuj4eU/NjCA==",
+      "requires": {
+        "@types/body-parser": "*",
+        "@types/express-serve-static-core": "*",
+        "@types/serve-static": "*"
+      }
+    },
+    "@types/express-serve-static-core": {
+      "version": "4.17.1",
+      "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.1.tgz",
+      "integrity": "sha512-9e7jj549ZI+RxY21Cl0t8uBnWyb22HzILupyHZjYEVK//5TT/1bZodU+yUbLnPdoYViBBnNWbxp4zYjGV0zUGw==",
+      "requires": {
+        "@types/node": "*",
+        "@types/range-parser": "*"
+      }
+    },
     "@types/js-yaml": {
       "version": "3.12.1",
       "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-3.12.1.tgz",
       "integrity": "sha512-SGGAhXLHDx+PK4YLNcNGa6goPf9XRWQNAUUbffkwVGGXIxmDKWyGGL4inzq2sPmExu431Ekb9aEMn9BkPqEYFA==",
       "dev": true
     },
+    "@types/mime": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz",
+      "integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw=="
+    },
     "@types/mocha": {
       "version": "5.2.7",
       "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz",
@@ -161,6 +207,20 @@
       "resolved": "https://registry.npmjs.org/@types/node/-/node-10.14.15.tgz",
       "integrity": "sha512-CBR5avlLcu0YCILJiDIXeU2pTw7UK/NIxfC63m7d7CVamho1qDEzXKkOtEauQRPMy6MI8mLozth+JJkas7HY6g=="
     },
+    "@types/range-parser": {
+      "version": "1.2.3",
+      "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
+      "integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA=="
+    },
+    "@types/serve-static": {
+      "version": "1.13.3",
+      "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.3.tgz",
+      "integrity": "sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g==",
+      "requires": {
+        "@types/express-serve-static-core": "*",
+        "@types/mime": "*"
+      }
+    },
     "@types/sqlite3": {
       "version": "3.1.5",
       "resolved": "https://registry.npmjs.org/@types/sqlite3/-/sqlite3-3.1.5.tgz",
@@ -349,9 +409,9 @@
       "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
     },
     "aws4": {
-      "version": "1.8.0",
-      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
-      "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
+      "version": "1.9.0",
+      "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.0.tgz",
+      "integrity": "sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A=="
     },
     "babel-code-frame": {
       "version": "6.26.0",
@@ -372,7 +432,7 @@
         },
         "chalk": {
           "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
           "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
           "dev": true,
           "requires": {
@@ -447,9 +507,9 @@
       "integrity": "sha1-DmVcm5wkNeqraL9AJyJtK1WjRSQ="
     },
     "bluebird": {
-      "version": "3.5.5",
-      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.5.tgz",
-      "integrity": "sha512-5am6HnnfN+urzt4yfg7IgTbotDjIT/u8AJpEt0sIU9FtXfVeezXAPKswrG+xKUCOYAINpSdgZVDU6QFh+cuH3w=="
+      "version": "3.7.2",
+      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
+      "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg=="
     },
     "body-parser": {
       "version": "1.19.0",
@@ -1001,9 +1061,9 @@
       }
     },
     "dom-serializer": {
-      "version": "0.2.1",
-      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.1.tgz",
-      "integrity": "sha512-sK3ujri04WyjwQXVoK4PU3y8ula1stq10GJZpqHIUgoGZdsGzAGu65BnU3d08aTVSvO7mGPZUc0wTEDL+qGE0Q==",
+      "version": "0.2.2",
+      "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
+      "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==",
       "requires": {
         "domelementtype": "^2.0.1",
         "entities": "^2.0.0"
@@ -1253,7 +1313,7 @@
         },
         "chalk": {
           "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
           "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
           "dev": true,
           "requires": {
@@ -1274,7 +1334,7 @@
     },
     "espree": {
       "version": "3.5.4",
-      "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
+      "resolved": "http://registry.npmjs.org/espree/-/espree-3.5.4.tgz",
       "integrity": "sha512-yAcIQxtmMiB/jL32dzEp2enBeidsB7xWPLNiw3IIkpVds1P+h7qF9YwJq1yUNzp2OKXgAprs4F61ih66UsoD1A==",
       "dev": true,
       "requires": {
@@ -1402,9 +1462,9 @@
       "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
     },
     "fast-json-stable-stringify": {
-      "version": "2.0.0",
-      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
-      "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+      "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
     },
     "fast-levenshtein": {
       "version": "2.0.6",
@@ -1618,6 +1678,11 @@
         "path-is-absolute": "^1.0.0"
       }
     },
+    "glob-to-regexp": {
+      "version": "0.4.1",
+      "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+      "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
+    },
     "globals": {
       "version": "9.18.0",
       "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz",
@@ -1827,7 +1892,7 @@
         },
         "chalk": {
           "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
           "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
           "dev": true,
           "requires": {
@@ -2286,25 +2351,62 @@
       "integrity": "sha512-pfDSB7QYoVg0Io4KMV9hhPoXpj6p0uBscgtyUSKCOFZe8bqgbpStfgnKIbF/ulnr6U3ICu4OqdyxAqBgOhZwBQ=="
     },
     "matrix-bot-sdk": {
-      "version": "github:Half-Shot/matrix-js-bot-sdk#9177a5424b772da1539cd8fb2f827bca461d9039",
-      "from": "github:Half-Shot/matrix-js-bot-sdk#hs/bridge-patches",
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/matrix-bot-sdk/-/matrix-bot-sdk-0.4.0.tgz",
+      "integrity": "sha512-ZIICFEYDsSX3emPnVRTV1FIV22zkt7KiJbTYN4rHQ3Z/rk66RB7Y+TMHxrkJCqPs3xVdaGmGkh5m+hNi4fibRg==",
       "requires": {
-        "@types/node": "^10.14.9",
-        "bluebird": "^3.5.5",
-        "chalk": "^2.4.2",
+        "@types/express": "^4.17.2",
+        "bluebird": "^3.7.1",
+        "chalk": "^3.0.0",
         "express": "^4.17.1",
+        "glob-to-regexp": "^0.4.1",
         "hash.js": "^1.1.7",
-        "htmlencode": "0.0.4",
+        "htmlencode": "^0.0.4",
         "lowdb": "^1.0.0",
         "lru-cache": "^5.1.1",
+        "mkdirp": "^0.5.1",
         "morgan": "^1.9.1",
         "request": "^2.88.0",
-        "request-promise": "^4.2.4",
-        "sanitize-html": "^1.20.1",
-        "tslint": "^5.17.0",
-        "typescript": "^3.5.2"
+        "request-promise": "^4.2.5",
+        "sanitize-html": "^1.20.1"
       },
       "dependencies": {
+        "ansi-styles": {
+          "version": "4.2.0",
+          "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.0.tgz",
+          "integrity": "sha512-7kFQgnEaMdRtwf6uSfUnVr9gSGC7faurn+J/Mv90/W+iTtN0405/nLdopfMWwchyxhbGYl6TC4Sccn9TUkGAgg==",
+          "requires": {
+            "@types/color-name": "^1.1.1",
+            "color-convert": "^2.0.1"
+          }
+        },
+        "chalk": {
+          "version": "3.0.0",
+          "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+          "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+          "requires": {
+            "ansi-styles": "^4.1.0",
+            "supports-color": "^7.1.0"
+          }
+        },
+        "color-convert": {
+          "version": "2.0.1",
+          "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+          "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+          "requires": {
+            "color-name": "~1.1.4"
+          }
+        },
+        "color-name": {
+          "version": "1.1.4",
+          "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+          "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+        },
+        "has-flag": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+          "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
+        },
         "lru-cache": {
           "version": "5.1.1",
           "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
@@ -2312,6 +2414,14 @@
           "requires": {
             "yallist": "^3.0.2"
           }
+        },
+        "supports-color": {
+          "version": "7.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
+          "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
+          "requires": {
+            "has-flag": "^4.0.0"
+          }
         }
       }
     },
@@ -2382,16 +2492,16 @@
       "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
     },
     "mime-db": {
-      "version": "1.40.0",
-      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
-      "integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
+      "version": "1.42.0",
+      "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz",
+      "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ=="
     },
     "mime-types": {
-      "version": "2.1.24",
-      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
-      "integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
+      "version": "2.1.25",
+      "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz",
+      "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==",
       "requires": {
-        "mime-db": "1.40.0"
+        "mime-db": "1.42.0"
       }
     },
     "minimalistic-assert": {
@@ -2458,7 +2568,7 @@
       "dependencies": {
         "commander": {
           "version": "2.15.1",
-          "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
+          "resolved": "http://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
           "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
           "dev": true
         },
@@ -2561,7 +2671,7 @@
     },
     "next-tick": {
       "version": "1.0.0",
-      "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
+      "resolved": "http://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
       "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
       "dev": true
     },
@@ -2860,7 +2970,7 @@
       "dependencies": {
         "semver": {
           "version": "4.3.2",
-          "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.2.tgz",
+          "resolved": "http://registry.npmjs.org/semver/-/semver-4.3.2.tgz",
           "integrity": "sha1-x6BxWKgL7dBSNVt3DYLWZA+AO+c="
         }
       }
@@ -2939,9 +3049,9 @@
       "dev": true
     },
     "postcss": {
-      "version": "7.0.17",
-      "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.17.tgz",
-      "integrity": "sha512-546ZowA+KZ3OasvQZHsbuEpysvwTZNGJv9EfyCQdsIDltPSWHAeTQ5fQy/Npi2ZDtLI3zs7Ps/p6wThErhm9fQ==",
+      "version": "7.0.25",
+      "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.25.tgz",
+      "integrity": "sha512-NXXVvWq9icrm/TgQC0O6YVFi4StfJz46M1iNd/h6B26Nvh/HKI+q4YZtFN/EjcInZliEscO/WL10BXnc1E5nwg==",
       "requires": {
         "chalk": "^2.4.2",
         "source-map": "^0.6.1",
@@ -3051,9 +3161,9 @@
       "dev": true
     },
     "psl": {
-      "version": "1.3.0",
-      "resolved": "https://registry.npmjs.org/psl/-/psl-1.3.0.tgz",
-      "integrity": "sha512-avHdspHO+9rQTLbv1RO+MPYeP/SzsCoxofjVnHanETfQhTJrmB0HlDoW+EiN/R+C0BZ+gERab9NY0lPN2TxNag=="
+      "version": "1.7.0",
+      "resolved": "https://registry.npmjs.org/psl/-/psl-1.7.0.tgz",
+      "integrity": "sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ=="
     },
     "punycode": {
       "version": "2.1.1",
@@ -3181,22 +3291,22 @@
       }
     },
     "request-promise": {
-      "version": "4.2.4",
-      "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.4.tgz",
-      "integrity": "sha512-8wgMrvE546PzbR5WbYxUQogUnUDfM0S7QIFZMID+J73vdFARkFy+HElj4T+MWYhpXwlLp0EQ8Zoj8xUA0he4Vg==",
+      "version": "4.2.5",
+      "resolved": "https://registry.npmjs.org/request-promise/-/request-promise-4.2.5.tgz",
+      "integrity": "sha512-ZgnepCykFdmpq86fKGwqntyTiUrHycALuGggpyCZwMvGaZWgxW6yagT0FHkgo5LzYvOaCNvxYwWYIjevSH1EDg==",
       "requires": {
         "bluebird": "^3.5.0",
-        "request-promise-core": "1.1.2",
+        "request-promise-core": "1.1.3",
         "stealthy-require": "^1.1.1",
         "tough-cookie": "^2.3.3"
       }
     },
     "request-promise-core": {
-      "version": "1.1.2",
-      "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz",
-      "integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==",
+      "version": "1.1.3",
+      "resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.3.tgz",
+      "integrity": "sha512-QIs2+ArIGQVp5ZYbWD5ZLCY29D5CfWizP8eWnm8FoGD1TX61veauETVQbrV60662V0oFBkrDOuaBI8XgtuyYAQ==",
       "requires": {
-        "lodash": "^4.17.11"
+        "lodash": "^4.17.15"
       }
     },
     "require-directory": {
@@ -3626,7 +3736,7 @@
         },
         "chalk": {
           "version": "1.1.3",
-          "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
+          "resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
           "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
           "dev": true,
           "requires": {
@@ -3895,9 +4005,9 @@
       "dev": true
     },
     "typescript": {
-      "version": "3.5.3",
-      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.5.3.tgz",
-      "integrity": "sha512-ACzBtm/PhXBDId6a6sDJfroT2pOWt/oOnk4/dElG5G33ZL776N3Y6/6bKZJBFpd+b05F3Ct9qDjMeJmRWtE2/g=="
+      "version": "3.7.4",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.4.tgz",
+      "integrity": "sha512-A25xv5XCtarLwXpcDNZzCGvW2D1S3/bACratYBx2sax8PefsFhlYmkQicKHvpYflFS8if4zne5zT5kpJ7pzuvw=="
     },
     "typical": {
       "version": "2.6.1",
diff --git a/package.json b/package.json
index 283b4bc70d5097e48b6ae540a10f3525bfaa064b..dddab552e1beb579d9952f13195ee263ac3ef31c 100644
--- a/package.json
+++ b/package.json
@@ -43,14 +43,13 @@
     "escape-html": "^1.0.3",
     "escape-string-regexp": "^1.0.5",
     "js-yaml": "^3.13.1",
-    "matrix-bot-sdk": "Half-Shot/matrix-js-bot-sdk#hs/bridge-patches",
+    "matrix-bot-sdk": "0.4.0",
     "mime": "^1.6.0",
     "node-html-parser": "^1.1.15",
     "matrix-discord-parser": "0.0.3",
     "p-queue": "^6.0.1",
     "pg-promise": "^8.5.1",
     "prom-client": "^11.3.0",
-    "typescript": "^3.1.3",
     "winston": "^3.0.0",
     "winston-daily-rotate-file": "^3.3.0"
   },
@@ -70,6 +69,7 @@
     "source-map-support": "^0.5.12",
     "ts-node": "^8.1.0",
     "tslint": "^5.11.0",
+    "typescript": "^3.7",
     "why-is-node-running": "^2.0.3"
   }
-}
\ No newline at end of file
+}
diff --git a/src/db/schema/v11.ts b/src/db/schema/v11.ts
new file mode 100644
index 0000000000000000000000000000000000000000..470aae67c7b54c660855ed981798904e8dfddebb
--- /dev/null
+++ b/src/db/schema/v11.ts
@@ -0,0 +1,42 @@
+/*
+Copyright 2019 matrix-appservice-discord
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+import {IDbSchema} from "./dbschema";
+import {DiscordStore} from "../../store";
+import { Log } from "../../log";
+
+const log = new Log("SchemaV11");
+
+export class Schema implements IDbSchema {
+    public description = "create stores for bot sdk";
+
+    public async run(store: DiscordStore): Promise<void> {
+        try {
+            store.createTable("CREATE TABLE registered_users (user_id TEXT UNIQUE NOT NULL);", "registered_users");
+            store.createTable("CREATE TABLE as_txns (txn_id TEXT UNIQUE NOT NULL);", "as_txns");
+        } catch (ex) {
+            log.error("Failed to apply indexes:", ex);
+        }
+
+    }
+
+    public async rollBack(store: DiscordStore): Promise<void> {
+        await store.db.Exec(
+            `DROP TABLE IF EXISTS registered_users;
+            DROP TABLE IF EXISTS as_txns;`,
+        );
+    }
+}
diff --git a/src/discordas.ts b/src/discordas.ts
index f1bc1d794aee07352a3490fe06eaaeb54dd9d500..154feeb9a66885552f1130214401168701ada608 100644
--- a/src/discordas.ts
+++ b/src/discordas.ts
@@ -143,16 +143,18 @@ async function run() {
     }
     const registration = yaml.safeLoad(fs.readFileSync(registrationPath, "utf8")) as IAppserviceRegistration;
     setupLogging();
+
+    const store = new DiscordStore(config.database);
+
     const appservice = new Appservice({
         bindAddress: config.bridge.bindAddress || "0.0.0.0",
         homeserverName: config.bridge.domain,
         homeserverUrl: config.bridge.homeserverUrl,
         port,
         registration,
+        storage: store,
     });
 
-    const store = new DiscordStore(config.database);
-
     if (config.metrics.enable) {
         log.info("Enabled metrics");
         MetricPeg.set(new PrometheusBridgeMetrics().init(appservice, config.metrics));
diff --git a/src/store.ts b/src/store.ts
index a0397363c9aed0001e1556cf7617703c8de23688..ca8d7ffa052c83597ec2d62d30f190fae98362c4 100644
--- a/src/store.ts
+++ b/src/store.ts
@@ -24,16 +24,21 @@ import { Postgres } from "./db/postgres";
 import { IDatabaseConnector } from "./db/connector";
 import { DbRoomStore } from "./db/roomstore";
 import { DbUserStore } from "./db/userstore";
+import { IAppserviceStorageProvider } from "matrix-bot-sdk";
 const log = new Log("DiscordStore");
-export const CURRENT_SCHEMA = 10;
+export const CURRENT_SCHEMA = 11;
 /**
  * Stores data for specific users and data not specific to rooms.
  */
-export class DiscordStore {
+export class DiscordStore implements IAppserviceStorageProvider {
     public db: IDatabaseConnector;
     private config: DiscordBridgeConfigDatabase;
     private pRoomStore: DbRoomStore;
     private pUserStore: DbUserStore;
+
+    private registeredUsers: Set<string>;
+    private asTxns: Set<string>;
+
     constructor(configOrFile: DiscordBridgeConfigDatabase|string) {
         if (typeof(configOrFile) === "string") {
             this.config = new DiscordBridgeConfigDatabase();
@@ -118,6 +123,14 @@ export class DiscordStore {
             await this.setSchemaVersion(version);
         }
         log.info("Updated database to the latest schema");
+        // We need to prepopulate some sets
+        for (const row of await this.db.All("SELECT * FROM registered_users")) {
+            this.registeredUsers.add(row.user_id as string);
+        }
+
+        for (const row of await this.db.All("SELECT * FROM as_txns")) {
+            this.asTxns.add(row.txn_id as string);
+        }
     }
 
     public async close() {
@@ -263,6 +276,22 @@ export class DiscordStore {
         await data.Delete(this);
     }
 
+    public addRegisteredUser(userId: string) {
+        this.registeredUsers.add(userId);
+        this.db.Run("INSERT INTO registered_users VALUES ($userId)", {userId});
+    }
+    public isUserRegistered(userId: string): boolean {
+        return this.registeredUsers.has(userId);
+    }
+
+    public setTransactionCompleted(transactionId: string) {
+        this.asTxns.add(transactionId);
+        this.db.Run("INSERT INTO txn_id VALUES ($transactionId)", {transactionId});
+    }
+    public isTransactionCompleted(transactionId: string): boolean {
+        return this.asTxns.has(transactionId);
+    }
+
     private async getSchemaVersion( ): Promise<number> {
         log.silly("_get_schema_version");
         let version = 0;