commit 6accde390ef7ddf6a0e84ac1e2cba4ad244edb2d
parent 42d21bfc1aa224c74c695bcf2b736b9afa284a75
Author: MTRNord <mtrnord1@gmail.com>
Date: Mon, 19 Dec 2022 20:22:36 +0100
Cleanup bot and introduce basic warning formatting and rooms
Diffstat:
4 files changed, 372 insertions(+), 193 deletions(-)
diff --git a/bert.ipynb b/bert.ipynb
@@ -647,7 +647,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
- "version": "3.9.15"
+ "version": "3.9.15 (main, Nov 24 2022, 14:31:59) \n[GCC 11.2.0]"
},
"orig_nbformat": 4,
"vscode": {
diff --git a/bot/package-lock.json b/bot/package-lock.json
@@ -140,17 +140,6 @@
"node": ">=8"
}
},
- "node_modules/@mapbox/node-pre-gyp/node_modules/mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
- "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
- "bin": {
- "mkdirp": "bin/cmd.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
"node_modules/@mapbox/node-pre-gyp/node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -186,17 +175,10 @@
"node": ">=10"
}
},
- "node_modules/@matrix-org/matrix-sdk-crypto-nodejs": {
- "version": "0.1.0-beta.3",
- "resolved": "https://registry.npmjs.org/@matrix-org/matrix-sdk-crypto-nodejs/-/matrix-sdk-crypto-nodejs-0.1.0-beta.3.tgz",
- "integrity": "sha512-jHFn6xBeNqfsY5gX60akbss7iFBHZwXycJWMw58Mjz08OwOi7AbTxeS9I2Pa4jX9/M2iinskmGZbzpqOT2fM3A==",
- "hasInstallScript": true,
- "dependencies": {
- "node-downloader-helper": "^2.1.1"
- },
- "engines": {
- "node": ">= 14"
- }
+ "node_modules/@mapbox/node-pre-gyp/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
},
"node_modules/@selderee/plugin-htmlparser2": {
"version": "0.6.0",
@@ -354,12 +336,12 @@
}
},
"node_modules/@types/express": {
- "version": "4.17.14",
- "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz",
- "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==",
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.15.tgz",
+ "integrity": "sha512-Yv0k4bXGOH+8a+7bELd2PqHQsuiANB+A8a4gnQrkRWzrkKlb6KHaVvyXhqs04sVW/OWlbPyYxRgYlIXLfrufMQ==",
"dependencies": {
"@types/body-parser": "*",
- "@types/express-serve-static-core": "^4.17.18",
+ "@types/express-serve-static-core": "^4.17.31",
"@types/qs": "*",
"@types/serve-static": "*"
}
@@ -391,9 +373,9 @@
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA=="
},
"node_modules/@types/node": {
- "version": "18.11.12",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.12.tgz",
- "integrity": "sha512-FgD3NtTAKvyMmD44T07zz2fEf+OKwutgBCEVM8GcvMGVGaDktiLNTDvPwC/LUe3PinMW+X6CuLOF2Ui1mAlSXg=="
+ "version": "18.11.17",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.17.tgz",
+ "integrity": "sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng=="
},
"node_modules/@types/node-fetch": {
"version": "2.6.2",
@@ -1562,14 +1544,11 @@
}
},
"node_modules/lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
- "dependencies": {
- "yallist": "^4.0.0"
- },
+ "version": "7.14.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz",
+ "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==",
"engines": {
- "node": ">=10"
+ "node": ">=12"
}
},
"node_modules/make-dir": {
@@ -1621,23 +1600,16 @@
"node": ">=16.0.0"
}
},
- "node_modules/matrix-bot-sdk/node_modules/lru-cache": {
- "version": "7.14.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz",
- "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/matrix-bot-sdk/node_modules/mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
- "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
- "bin": {
- "mkdirp": "bin/cmd.js"
+ "node_modules/matrix-bot-sdk/node_modules/@matrix-org/matrix-sdk-crypto-nodejs": {
+ "version": "0.1.0-beta.1",
+ "resolved": "https://registry.npmjs.org/@matrix-org/matrix-sdk-crypto-nodejs/-/matrix-sdk-crypto-nodejs-0.1.0-beta.1.tgz",
+ "integrity": "sha512-jCSKrmNh6kaqnOwS/Pqgqkeb+CAvwGuS0oNEW3LaWKrJWFAfUrt+lXBCs7kAP79Qo5ZKBU06BekbZuwYhWbhkQ==",
+ "hasInstallScript": true,
+ "dependencies": {
+ "node-downloader-helper": "^2.1.1"
},
"engines": {
- "node": ">=10"
+ "node": ">= 14"
}
},
"node_modules/media-typer": {
@@ -1724,11 +1696,6 @@
"yallist": "^3.0.0"
}
},
- "node_modules/minipass/node_modules/yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
- },
"node_modules/minizlib": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.3.3.tgz",
@@ -1738,14 +1705,14 @@
}
},
"node_modules/mkdirp": {
- "version": "0.5.6",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
- "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
- "dependencies": {
- "minimist": "^1.2.6"
- },
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
"bin": {
"mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
}
},
"node_modules/moo": {
@@ -2000,9 +1967,9 @@
}
},
"node_modules/postcss": {
- "version": "8.4.19",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz",
- "integrity": "sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==",
+ "version": "8.4.20",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.20.tgz",
+ "integrity": "sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==",
"funding": [
{
"type": "opencollective",
@@ -2262,18 +2229,87 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/sanitize-html": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.7.3.tgz",
- "integrity": "sha512-jMaHG29ak4miiJ8wgqA1849iInqORgNv7SLfSw9LtfOhEUQ1C0YHKH73R+hgyufBW9ZFeJrb057k9hjlfBCVlw==",
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.8.0.tgz",
+ "integrity": "sha512-ZsGyc6avnqgvEm3eMKrcy8xa7WM1MrGrfkGsUgQee2CU+vg3PCfNCexXwBDF/6dEPvaQ4k/QqRjnYKHL8xgNjg==",
"dependencies": {
"deepmerge": "^4.2.2",
"escape-string-regexp": "^4.0.0",
- "htmlparser2": "^6.0.0",
+ "htmlparser2": "^8.0.0",
"is-plain-object": "^5.0.0",
"parse-srcset": "^1.0.2",
"postcss": "^8.3.11"
}
},
+ "node_modules/sanitize-html/node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/sanitize-html/node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/sanitize-html/node_modules/domutils": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
+ "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/sanitize-html/node_modules/entities": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz",
+ "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA==",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/sanitize-html/node_modules/htmlparser2": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz",
+ "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==",
+ "funding": [
+ "https://github.com/fb55/htmlparser2?sponsor=1",
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "domutils": "^3.0.1",
+ "entities": "^4.3.0"
+ }
+ },
"node_modules/seedrandom": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz",
@@ -2304,6 +2340,22 @@
"node": ">=10"
}
},
+ "node_modules/semver/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/semver/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ },
"node_modules/send": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
@@ -2503,10 +2555,16 @@
"node": ">=4.5"
}
},
- "node_modules/tar/node_modules/yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+ "node_modules/tar/node_modules/mkdirp": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+ "dependencies": {
+ "minimist": "^1.2.6"
+ },
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ }
},
"node_modules/toidentifier": {
"version": "1.0.1",
@@ -2685,9 +2743,9 @@
}
},
"node_modules/yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
},
"node_modules/yargs": {
"version": "16.2.0",
@@ -2807,11 +2865,6 @@
}
}
},
- "mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
- "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
- },
"ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
@@ -2837,17 +2890,14 @@
"mkdirp": "^1.0.3",
"yallist": "^4.0.0"
}
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
}
}
},
- "@matrix-org/matrix-sdk-crypto-nodejs": {
- "version": "0.1.0-beta.3",
- "resolved": "https://registry.npmjs.org/@matrix-org/matrix-sdk-crypto-nodejs/-/matrix-sdk-crypto-nodejs-0.1.0-beta.3.tgz",
- "integrity": "sha512-jHFn6xBeNqfsY5gX60akbss7iFBHZwXycJWMw58Mjz08OwOi7AbTxeS9I2Pa4jX9/M2iinskmGZbzpqOT2fM3A==",
- "requires": {
- "node-downloader-helper": "^2.1.1"
- }
- },
"@selderee/plugin-htmlparser2": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/@selderee/plugin-htmlparser2/-/plugin-htmlparser2-0.6.0.tgz",
@@ -2973,12 +3023,12 @@
}
},
"@types/express": {
- "version": "4.17.14",
- "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.14.tgz",
- "integrity": "sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==",
+ "version": "4.17.15",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.15.tgz",
+ "integrity": "sha512-Yv0k4bXGOH+8a+7bELd2PqHQsuiANB+A8a4gnQrkRWzrkKlb6KHaVvyXhqs04sVW/OWlbPyYxRgYlIXLfrufMQ==",
"requires": {
"@types/body-parser": "*",
- "@types/express-serve-static-core": "^4.17.18",
+ "@types/express-serve-static-core": "^4.17.31",
"@types/qs": "*",
"@types/serve-static": "*"
}
@@ -3010,9 +3060,9 @@
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA=="
},
"@types/node": {
- "version": "18.11.12",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.12.tgz",
- "integrity": "sha512-FgD3NtTAKvyMmD44T07zz2fEf+OKwutgBCEVM8GcvMGVGaDktiLNTDvPwC/LUe3PinMW+X6CuLOF2Ui1mAlSXg=="
+ "version": "18.11.17",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.17.tgz",
+ "integrity": "sha512-HJSUJmni4BeDHhfzn6nF0sVmd1SMezP7/4F0Lq+aXzmp2xm9O7WXrUtHW/CHlYVtZUbByEvWidHqRtcJXGF2Ng=="
},
"@types/node-fetch": {
"version": "2.6.2",
@@ -3961,12 +4011,9 @@
}
},
"lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
- "requires": {
- "yallist": "^4.0.0"
- }
+ "version": "7.14.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz",
+ "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA=="
},
"make-dir": {
"version": "3.1.0",
@@ -3988,7 +4035,7 @@
"resolved": "https://registry.npmjs.org/matrix-bot-sdk/-/matrix-bot-sdk-0.6.2.tgz",
"integrity": "sha512-+kXlXkQBQgWC6oUwYEosJlXjceaj7jQUnPlALFhGeAabgVm8tmuvFNVKqClwvrrjj+0Gzsmt+rcJHmkvqymFXA==",
"requires": {
- "@matrix-org/matrix-sdk-crypto-nodejs": "^0.1.0-beta.1",
+ "@matrix-org/matrix-sdk-crypto-nodejs": "0.1.0-beta.1",
"@types/express": "^4.17.13",
"another-json": "^0.2.0",
"async-lock": "^1.3.2",
@@ -4007,15 +4054,13 @@
"sanitize-html": "^2.7.0"
},
"dependencies": {
- "lru-cache": {
- "version": "7.14.1",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz",
- "integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA=="
- },
- "mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
- "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
+ "@matrix-org/matrix-sdk-crypto-nodejs": {
+ "version": "0.1.0-beta.1",
+ "resolved": "https://registry.npmjs.org/@matrix-org/matrix-sdk-crypto-nodejs/-/matrix-sdk-crypto-nodejs-0.1.0-beta.1.tgz",
+ "integrity": "sha512-jCSKrmNh6kaqnOwS/Pqgqkeb+CAvwGuS0oNEW3LaWKrJWFAfUrt+lXBCs7kAP79Qo5ZKBU06BekbZuwYhWbhkQ==",
+ "requires": {
+ "node-downloader-helper": "^2.1.1"
+ }
}
}
},
@@ -4077,13 +4122,6 @@
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
- },
- "dependencies": {
- "yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
- }
}
},
"minizlib": {
@@ -4095,12 +4133,9 @@
}
},
"mkdirp": {
- "version": "0.5.6",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
- "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
- "requires": {
- "minimist": "^1.2.6"
- }
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
},
"moo": {
"version": "0.5.2",
@@ -4281,9 +4316,9 @@
"integrity": "sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg=="
},
"postcss": {
- "version": "8.4.19",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.19.tgz",
- "integrity": "sha512-h+pbPsyhlYj6N2ozBmHhHrs9DzGmbaarbLvWipMRO7RLS+v4onj26MPFXA5OBYFxyqYhUJK456SwDcY9H2/zsA==",
+ "version": "8.4.20",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.20.tgz",
+ "integrity": "sha512-6Q04AXR1212bXr5fh03u8aAwbLxAQNGQ/Q1LNa0VfOI06ZAlhPHtQvE4OIdpj4kLThXilalPnmDSOD65DcHt+g==",
"requires": {
"nanoid": "^3.3.4",
"picocolors": "^1.0.0",
@@ -4459,16 +4494,62 @@
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"sanitize-html": {
- "version": "2.7.3",
- "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.7.3.tgz",
- "integrity": "sha512-jMaHG29ak4miiJ8wgqA1849iInqORgNv7SLfSw9LtfOhEUQ1C0YHKH73R+hgyufBW9ZFeJrb057k9hjlfBCVlw==",
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-2.8.0.tgz",
+ "integrity": "sha512-ZsGyc6avnqgvEm3eMKrcy8xa7WM1MrGrfkGsUgQee2CU+vg3PCfNCexXwBDF/6dEPvaQ4k/QqRjnYKHL8xgNjg==",
"requires": {
"deepmerge": "^4.2.2",
"escape-string-regexp": "^4.0.0",
- "htmlparser2": "^6.0.0",
+ "htmlparser2": "^8.0.0",
"is-plain-object": "^5.0.0",
"parse-srcset": "^1.0.2",
"postcss": "^8.3.11"
+ },
+ "dependencies": {
+ "dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "requires": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ }
+ },
+ "domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "requires": {
+ "domelementtype": "^2.3.0"
+ }
+ },
+ "domutils": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz",
+ "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==",
+ "requires": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.1"
+ }
+ },
+ "entities": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.4.0.tgz",
+ "integrity": "sha512-oYp7156SP8LkeGD0GF85ad1X9Ai79WtRsZ2gxJqtBuzH+98YUV6jkHEKlZkMbcrjJjIVJNIDP/3WL9wQkoPbWA=="
+ },
+ "htmlparser2": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.1.tgz",
+ "integrity": "sha512-4lVbmc1diZC7GUJQtRQ5yBAeUCL1exyMwmForWkRLnwyzWBFxN633SALPMGYaWZvKe9j1pRZJpauvmxENSp/EA==",
+ "requires": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "domutils": "^3.0.1",
+ "entities": "^4.3.0"
+ }
+ }
}
},
"seedrandom": {
@@ -4490,6 +4571,21 @@
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
"requires": {
"lru-cache": "^6.0.0"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ }
}
},
"send": {
@@ -4657,10 +4753,13 @@
"yallist": "^3.1.1"
},
"dependencies": {
- "yallist": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+ "mkdirp": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+ "requires": {
+ "minimist": "^1.2.6"
+ }
}
}
},
@@ -4797,9 +4896,9 @@
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA=="
},
"yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
},
"yargs": {
"version": "16.2.0",
diff --git a/bot/package.json b/bot/package.json
@@ -17,5 +17,10 @@
"@tensorflow/tfjs-node": "^4.1.0",
"js-yaml": "^4.1.0",
"matrix-bot-sdk": "^0.6.2"
+ },
+ "overrides": {
+ "matrix-bot-sdk": {
+ "@matrix-org/matrix-sdk-crypto-nodejs": "0.1.0-beta.1"
+ }
}
}
diff --git a/bot/src/index.ts b/bot/src/index.ts
@@ -2,76 +2,151 @@ import {
MatrixClient,
SimpleFsStorageProvider,
AutojoinRoomsMixin,
- MessageEvent,
- TextualMessageEventContent,
- //RustSdkCryptoStorageProvider,
+ // MessageEvent,
+ // TextualMessageEventContent,
+ RustSdkCryptoStorageProvider,
} from "matrix-bot-sdk";
import { readFile } from "fs/promises";
import { load } from "js-yaml";
import * as tf from "@tensorflow/tfjs-node";
import { Rank, Tensor } from "@tensorflow/tfjs-node";
+import { TFSavedModel } from "@tensorflow/tfjs-node/dist/saved_model";
type Config = {
homeserver: string;
accessToken: string;
modelPath: string;
+ // A private room for admins to see responses on reports and other secret activity.
+ adminRoom: string;
+ // A possibly public room where warnings land which also is used to issue actions from as an admin
+ warningsRoom: string;
};
-const config = load(await readFile("./config.yaml", "utf8")) as Config;
-
-// This will be the URL where clients can reach your homeserver. Note that this might be different
-// from where the web/chat interface is hosted. The server must support password registration without
-// captcha or terms of service (public servers typically won't work).
-const homeserverUrl = config.homeserver;
-
-// Use the access token you got from login or registration above.
-const accessToken = config.accessToken;
-
-// In order to make sure the bot doesn't lose its state between restarts, we'll give it a place to cache
-// any information it needs to. You can implement your own storage provider if you like, but a JSON file
-// will work fine for this example.
-const storage = new SimpleFsStorageProvider("ml-bot.json");
-// Broken
-//const cryptoProvider = new RustSdkCryptoStorageProvider("./ml-bot-store");
-
-tf.enableProdMode()
-const model = await tf.node.loadSavedModel(config.modelPath);
-
-// Finally, let's create the client and set it to autojoin rooms. Autojoining is typical of bots to ensure
-// they can be easily added to any room.
-//const client = new MatrixClient(homeserverUrl, accessToken, storage, cryptoProvider);
-const client = new MatrixClient(homeserverUrl, accessToken, storage);
-AutojoinRoomsMixin.setupOnClient(client);
-
-// Before we start the bot, register our command handler
-client.on("room.message", handleMessage);
-
-// Now that everything is set up, start the bot. This will start the sync loop and run until killed.
-client.start().then(() => console.log("Bot started!"));
+class Bot {
+ public static async createBot() {
+ const config = load(await readFile("./config.yaml", "utf8")) as Config;
+
+ // Add some divider for clarity after tensorflow loaded up
+ const line = '-'.repeat(process.stdout.columns);
+ console.log(line);
+
+ // Check if required fields are set
+ if (config.homeserver == undefined && config.accessToken == undefined) {
+ console.error("Missing homeserver and accessToken config values");
+ process.exit(1);
+ } else if (config.homeserver == undefined) {
+ console.error("Missing homeserver config value");
+ process.exit(1);
+ } else if (config.accessToken == undefined) {
+ console.error("Missing accessToken config value");
+ process.exit(1);
+ }
+
+ if (config.adminRoom == undefined && config.warningsRoom == undefined) {
+ console.error("Missing adminRoom and warningsRoom config values");
+ process.exit(1);
+ } else if (config.adminRoom == undefined) {
+ console.error("Missing adminRoom config value");
+ process.exit(1);
+ } else if (config.warningsRoom == undefined) {
+ console.error("Missing warningsRoom config value");
+ process.exit(1);
+ }
+
+ if (config.adminRoom.startsWith("#")) {
+ console.error("adminRoom config value needs to be a roomid starting with a \"!\"");
+ process.exit(1);
+ }
+ if (config.warningsRoom.startsWith("#")) {
+ console.error("warningsRoom config value needs to be a roomid starting with a \"!\"");
+ process.exit(1);
+ }
+
+
+ // This will be the URL where clients can reach your homeserver. Note that this might be different
+ // from where the web/chat interface is hosted. The server must support password registration without
+ // captcha or terms of service (public servers typically won't work).
+ const homeserverUrl = config.homeserver;
+
+ // Use the access token you got from login or registration above.
+ const accessToken = config.accessToken;
+
+ // In order to make sure the bot doesn't lose its state between restarts, we'll give it a place to cache
+ // any information it needs to. You can implement your own storage provider if you like, but a JSON file
+ // will work fine for this example.
+ const storage = new SimpleFsStorageProvider("ml-bot.json");
+ const cryptoProvider = new RustSdkCryptoStorageProvider("./ml-bot-store");
+
+ tf.enableProdMode()
+ const model = await tf.node.loadSavedModel(config.modelPath);
+
+ // Finally, let's create the client and set it to autojoin rooms. Autojoining is typical of bots to ensure
+ // they can be easily added to any room.
+ const client = new MatrixClient(homeserverUrl, accessToken, storage, cryptoProvider);
+
+ // TODO replace with manual handling to need admin approval
+ AutojoinRoomsMixin.setupOnClient(client);
+
+ // Join rooms as needed but crash if missing
+ await client.joinRoom(config.adminRoom);
+ await client.joinRoom(config.warningsRoom);
+
+ return new Bot(config, client, model);
+ }
-// This is the command handler we registered a few lines up
-async function handleMessage(roomId: string, event: any) {
- // Don't handle unhelpful events (ones that aren't text messages, are redacted, or sent by us)
- if (event['content']?.['msgtype'] !== 'm.text') return;
- if (event['sender'] === await client.getUserId()) return;
+ private constructor(private config: Config, private client: MatrixClient, private model: TFSavedModel) {
+ // Before we start the bot, register our command handler
+ client.on("room.message", this.handleMessage.bind(this));
- const body = event['content']['body'];
- console.log(`Checking: "${body}"`)
+ // Now that everything is set up, start the bot. This will start the sync loop and run until killed.
+ client.start().then(() => console.log("Bot started!"));
+ }
- // Check if spam
- const data = tf.tensor([body])
- const prediction: Tensor<Rank.R2> = model.predict(data) as Tensor<Rank.R2>;
- const prediction_data: number[][] = await prediction.array() as number[][];
- console.log(`Prediction: ${prediction_data}`);
+ // This is the command handler we registered a few lines up
+ private async handleMessage(roomId: string, event: any) {
+ // Don't handle unhelpful events (ones that aren't text messages, are redacted, or sent by us)
+ if (event['content']?.['msgtype'] !== 'm.text') return;
+ if (event['sender'] === await this.client.getUserId()) return;
+ const body = event['content']['body'];
+ if (roomId !== this.config.adminRoom && roomId !== this.config.warningsRoom) {
+ await this.checkSpam(event, body, roomId);
+ }
+ }
- const message = new MessageEvent(event);
- const textEvent = new MessageEvent<TextualMessageEventContent>(message.raw);
- if (((prediction_data[0] ?? [])[0] ?? 0) > 0.8) {
- await client.unstableApis.addReactionToEvent(roomId, textEvent.eventId, "Classified Spam")
- } else {
- //await client.unstableApis.addReactionToEvent(roomId, textEvent.eventId, "Classified Not Spam")
+ private async checkSpam(event: any, body: string, roomId: string) {
+ // Check if spam
+ const data = tf.tensor([body])
+ const prediction: Tensor<Rank.R2> = this.model.predict(data) as Tensor<Rank.R2>;
+ const prediction_data: number[][] = await prediction.array() as number[][];
+ console.log(`Prediction: ${prediction_data}`);
+
+ const prediction_value = ((prediction_data[0] ?? [])[0] ?? 0);
+ if (prediction_value > 0.8) {
+ // TODO reverse resolve alias for the roomID and make pill.
+ const alert_event_id = await this.client.sendHtmlText(this.config.warningsRoom, `<blockquote>\n<p>${body}</p>\n</blockquote>\n<p>Above message was detected as spam. See json file for full event and use reactions to take action or no action.</p>\n<p>It was sent in ${roomId}</p>\n<p>Spam Score is: ${prediction_value.toFixed(3)}</p>\n`);
+ await this.client.unstableApis.addReactionToEvent(this.config.warningsRoom, alert_event_id, "🚨 Ban User");
+ await this.client.unstableApis.addReactionToEvent(this.config.warningsRoom, alert_event_id, "⚠️ Kick User");
+ await this.client.unstableApis.addReactionToEvent(this.config.warningsRoom, alert_event_id, "✅ False positive");
+ var eventContent = Buffer.from(JSON.stringify(event), 'utf8');
+ const media = await this.client.uploadContent(eventContent, "application/json", "event.json");
+ await this.client.sendMessage(this.config.warningsRoom, {
+ msgtype: "m.file",
+ body: "event.json",
+ filename: "event.json",
+ info: {
+ mimetype: "application/json",
+ size: eventContent.length,
+ },
+ url: media,
+ })
+ } else {
+ // const message = new MessageEvent(event);
+ // const textEvent = new MessageEvent<TextualMessageEventContent>(message.raw);
+ //await this.client.unstableApis.addReactionToEvent(roomId, textEvent.eventId, "Classified Not Spam")
+ }
}
+}
+await Bot.createBot();
-}