summary refs log tree commit diff
path: root/util
diff options
context:
space:
mode:
authorMadeline <46743919+MaddyUnderStars@users.noreply.github.com>2022-02-13 22:29:14 +1100
committerMadeline <46743919+MaddyUnderStars@users.noreply.github.com>2022-02-13 22:29:14 +1100
commit204fe2aed1ebaed98a842db785851eb4f64bc2be (patch)
treedbcbf5863f6ffe86d544608d5c206b207c6df307 /util
parent;jondfgsk (diff)
parentAppropriate DB charset (#629) (diff)
downloadserver-204fe2aed1ebaed98a842db785851eb4f64bc2be.tar.xz
Merge branch 'master' into maddyrtc
Diffstat (limited to 'util')
-rw-r--r--util/package-lock.json435
-rw-r--r--util/package.json2
-rw-r--r--util/src/entities/Channel.ts689
-rw-r--r--util/src/entities/Emoji.ts2
-rw-r--r--util/src/entities/Message.ts6
-rw-r--r--util/src/util/Database.ts1
-rw-r--r--util/src/util/InvisibleCharacters.ts56
-rw-r--r--util/src/util/Rights.ts15
-rw-r--r--util/src/util/index.ts1
9 files changed, 798 insertions, 409 deletions
diff --git a/util/package-lock.json b/util/package-lock.json
index c6f2ed6f..9d20da93 100644
--- a/util/package-lock.json
+++ b/util/package-lock.json
@@ -11,16 +11,15 @@
 			"license": "GPLV3",
 			"dependencies": {
 				"amqplib": "^0.8.0",
-				"better-sqlite3": "^7.4.3",
 				"form-data": "^4.0.0",
 				"jsonwebtoken": "^8.5.1",
 				"lambert-server": "^1.2.12",
 				"missing-native-js-functions": "^1.2.18",
 				"multer": "^1.4.3",
-				"nanocolors": "^0.2.12",
-				"node-fetch": "^2.6.1",
+				"node-fetch": "^2.6.2",
 				"patch-package": "^6.4.7",
 				"pg": "^8.7.1",
+				"picocolors": "^1.0.0",
 				"proxy-agent": "^5.0.0",
 				"reflect-metadata": "^0.1.13",
 				"typeorm": "^0.2.38",
@@ -1503,12 +1502,16 @@
 		"node_modules/aproba": {
 			"version": "1.2.0",
 			"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
-			"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+			"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+			"optional": true,
+			"peer": true
 		},
 		"node_modules/are-we-there-yet": {
 			"version": "1.1.7",
 			"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
 			"integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"delegates": "^1.0.0",
 				"readable-stream": "^2.0.6"
@@ -1517,12 +1520,16 @@
 		"node_modules/are-we-there-yet/node_modules/isarray": {
 			"version": "1.0.0",
 			"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-			"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+			"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+			"optional": true,
+			"peer": true
 		},
 		"node_modules/are-we-there-yet/node_modules/readable-stream": {
 			"version": "2.3.7",
 			"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
 			"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"core-util-is": "~1.0.0",
 				"inherits": "~2.0.3",
@@ -1536,12 +1543,16 @@
 		"node_modules/are-we-there-yet/node_modules/safe-buffer": {
 			"version": "5.1.2",
 			"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-			"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+			"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+			"optional": true,
+			"peer": true
 		},
 		"node_modules/are-we-there-yet/node_modules/string_decoder": {
 			"version": "1.1.1",
 			"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
 			"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"safe-buffer": "~5.1.0"
 			}
@@ -1749,6 +1760,8 @@
 			"resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-7.4.3.tgz",
 			"integrity": "sha512-07bKjClZg/f4KMVRkzWtoIvazVPcF1gsvVKVIXlxwleC2DxuIhnra3KCMlUT1rFeRYXXckot2a46UciF2d9KLw==",
 			"hasInstallScript": true,
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"bindings": "^1.5.0",
 				"prebuild-install": "^6.0.1",
@@ -1759,6 +1772,8 @@
 			"version": "2.0.0",
 			"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
 			"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+			"optional": true,
+			"peer": true,
 			"engines": {
 				"node": ">=10"
 			}
@@ -1767,6 +1782,8 @@
 			"version": "2.1.0",
 			"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
 			"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"minipass": "^3.0.0"
 			},
@@ -1778,6 +1795,8 @@
 			"version": "3.1.5",
 			"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
 			"integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"yallist": "^4.0.0"
 			},
@@ -1789,6 +1808,8 @@
 			"version": "2.1.2",
 			"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
 			"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"minipass": "^3.0.0",
 				"yallist": "^4.0.0"
@@ -1801,6 +1822,8 @@
 			"version": "1.0.4",
 			"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
 			"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+			"optional": true,
+			"peer": true,
 			"bin": {
 				"mkdirp": "bin/cmd.js"
 			},
@@ -1812,6 +1835,8 @@
 			"version": "6.1.11",
 			"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
 			"integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"chownr": "^2.0.0",
 				"fs-minipass": "^2.0.0",
@@ -1828,6 +1853,8 @@
 			"version": "1.5.0",
 			"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
 			"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"file-uri-to-path": "1.0.0"
 			}
@@ -1854,6 +1881,8 @@
 			"version": "4.1.0",
 			"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
 			"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"buffer": "^5.5.0",
 				"inherits": "^2.0.4",
@@ -1864,6 +1893,8 @@
 			"version": "3.6.0",
 			"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
 			"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"inherits": "^2.0.3",
 				"string_decoder": "^1.1.1",
@@ -1877,6 +1908,8 @@
 			"version": "1.3.0",
 			"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
 			"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"safe-buffer": "~5.2.0"
 			}
@@ -1995,6 +2028,8 @@
 					"url": "https://feross.org/support"
 				}
 			],
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"base64-js": "^1.3.1",
 				"ieee754": "^1.1.13"
@@ -2105,7 +2140,9 @@
 		"node_modules/chownr": {
 			"version": "1.1.4",
 			"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
-			"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
+			"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+			"optional": true,
+			"peer": true
 		},
 		"node_modules/ci-info": {
 			"version": "3.2.0",
@@ -2189,6 +2226,8 @@
 			"version": "1.1.0",
 			"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
 			"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+			"optional": true,
+			"peer": true,
 			"engines": {
 				"node": ">=0.10.0"
 			}
@@ -2286,7 +2325,9 @@
 		"node_modules/console-control-strings": {
 			"version": "1.1.0",
 			"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
-			"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
+			"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
+			"optional": true,
+			"peer": true
 		},
 		"node_modules/content-disposition": {
 			"version": "0.5.3",
@@ -2441,6 +2482,8 @@
 			"version": "4.2.1",
 			"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
 			"integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"mimic-response": "^2.0.0"
 			},
@@ -2458,6 +2501,8 @@
 			"version": "0.6.0",
 			"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
 			"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+			"optional": true,
+			"peer": true,
 			"engines": {
 				"node": ">=4.0.0"
 			}
@@ -2530,7 +2575,9 @@
 		"node_modules/delegates": {
 			"version": "1.0.0",
 			"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
-			"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
+			"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
+			"optional": true,
+			"peer": true
 		},
 		"node_modules/depd": {
 			"version": "1.1.2",
@@ -2549,6 +2596,8 @@
 			"version": "1.0.3",
 			"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
 			"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=",
+			"optional": true,
+			"peer": true,
 			"bin": {
 				"detect-libc": "bin/detect-libc.js"
 			},
@@ -2682,6 +2731,8 @@
 			"version": "1.4.4",
 			"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
 			"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"once": "^1.4.0"
 			}
@@ -2803,6 +2854,8 @@
 			"version": "2.0.3",
 			"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
 			"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
+			"optional": true,
+			"peer": true,
 			"engines": {
 				"node": ">=6"
 			}
@@ -2944,7 +2997,9 @@
 		"node_modules/file-uri-to-path": {
 			"version": "1.0.0",
 			"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
-			"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
+			"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+			"optional": true,
+			"peer": true
 		},
 		"node_modules/fill-range": {
 			"version": "7.0.1",
@@ -3037,7 +3092,9 @@
 		"node_modules/fs-constants": {
 			"version": "1.0.0",
 			"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
-			"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
+			"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+			"optional": true,
+			"peer": true
 		},
 		"node_modules/fs-extra": {
 			"version": "7.0.1",
@@ -3132,6 +3189,8 @@
 			"version": "2.7.4",
 			"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
 			"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"aproba": "^1.0.3",
 				"console-control-strings": "^1.0.0",
@@ -3147,6 +3206,8 @@
 			"version": "2.1.1",
 			"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
 			"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+			"optional": true,
+			"peer": true,
 			"engines": {
 				"node": ">=0.10.0"
 			}
@@ -3155,6 +3216,8 @@
 			"version": "3.0.1",
 			"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
 			"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"ansi-regex": "^2.0.0"
 			},
@@ -3271,7 +3334,9 @@
 		"node_modules/github-from-package": {
 			"version": "0.0.0",
 			"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
-			"integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4="
+			"integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=",
+			"optional": true,
+			"peer": true
 		},
 		"node_modules/glob": {
 			"version": "7.1.7",
@@ -3373,7 +3438,9 @@
 		"node_modules/has-unicode": {
 			"version": "2.0.1",
 			"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
-			"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
+			"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
+			"optional": true,
+			"peer": true
 		},
 		"node_modules/helmet": {
 			"version": "4.6.0",
@@ -3603,7 +3670,9 @@
 		"node_modules/ini": {
 			"version": "1.3.8",
 			"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
-			"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
+			"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+			"optional": true,
+			"peer": true
 		},
 		"node_modules/ip": {
 			"version": "1.1.5",
@@ -3660,6 +3729,8 @@
 			"version": "1.0.0",
 			"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
 			"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"number-is-nan": "^1.0.0"
 			},
@@ -4912,6 +4983,8 @@
 			"version": "2.1.0",
 			"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
 			"integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==",
+			"optional": true,
+			"peer": true,
 			"engines": {
 				"node": ">=8"
 			},
@@ -4982,7 +5055,9 @@
 		"node_modules/mkdirp-classic": {
 			"version": "0.5.3",
 			"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
-			"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
+			"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
+			"optional": true,
+			"peer": true
 		},
 		"node_modules/ms": {
 			"version": "2.0.0",
@@ -5017,15 +5092,12 @@
 				"thenify-all": "^1.0.0"
 			}
 		},
-		"node_modules/nanocolors": {
-			"version": "0.2.12",
-			"resolved": "https://registry.npmjs.org/nanocolors/-/nanocolors-0.2.12.tgz",
-			"integrity": "sha512-SFNdALvzW+rVlzqexid6epYdt8H9Zol7xDoQarioEFcFN0JHo4CYNztAxmtfgGTVRCmFlEOqqhBpoFGKqSAMug=="
-		},
 		"node_modules/napi-build-utils": {
 			"version": "1.0.2",
 			"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
-			"integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg=="
+			"integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
+			"optional": true,
+			"peer": true
 		},
 		"node_modules/natural-compare": {
 			"version": "1.4.0",
@@ -5093,6 +5165,8 @@
 			"version": "2.30.1",
 			"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz",
 			"integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"semver": "^5.4.1"
 			}
@@ -5101,6 +5175,8 @@
 			"version": "5.7.1",
 			"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
 			"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+			"optional": true,
+			"peer": true,
 			"bin": {
 				"semver": "bin/semver"
 			}
@@ -5113,11 +5189,41 @@
 			"peer": true
 		},
 		"node_modules/node-fetch": {
-			"version": "2.6.2",
-			"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.2.tgz",
-			"integrity": "sha512-aLoxToI6RfZ+0NOjmWAgn9+LEd30YCkJKFSyWacNZdEKTit/ZMcKjGkTRo8uWEsnIb/hfKecNPEbln02PdWbcA==",
+			"version": "2.6.7",
+			"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+			"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+			"dependencies": {
+				"whatwg-url": "^5.0.0"
+			},
 			"engines": {
 				"node": "4.x || >=6.0.0"
+			},
+			"peerDependencies": {
+				"encoding": "^0.1.0"
+			},
+			"peerDependenciesMeta": {
+				"encoding": {
+					"optional": true
+				}
+			}
+		},
+		"node_modules/node-fetch/node_modules/tr46": {
+			"version": "0.0.3",
+			"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+			"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
+		},
+		"node_modules/node-fetch/node_modules/webidl-conversions": {
+			"version": "3.0.1",
+			"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+			"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
+		},
+		"node_modules/node-fetch/node_modules/whatwg-url": {
+			"version": "5.0.0",
+			"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+			"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
+			"dependencies": {
+				"tr46": "~0.0.3",
+				"webidl-conversions": "^3.0.0"
 			}
 		},
 		"node_modules/node-gyp": {
@@ -5357,6 +5463,8 @@
 			"version": "4.1.2",
 			"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
 			"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"are-we-there-yet": "~1.1.2",
 				"console-control-strings": "~1.1.0",
@@ -5368,6 +5476,8 @@
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
 			"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+			"optional": true,
+			"peer": true,
 			"engines": {
 				"node": ">=0.10.0"
 			}
@@ -5929,6 +6039,11 @@
 				"split2": "^3.1.1"
 			}
 		},
+		"node_modules/picocolors": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+			"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+		},
 		"node_modules/picomatch": {
 			"version": "2.3.0",
 			"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
@@ -6003,6 +6118,8 @@
 			"version": "6.1.4",
 			"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz",
 			"integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"detect-libc": "^1.0.3",
 				"expand-template": "^2.0.3",
@@ -6157,6 +6274,8 @@
 			"version": "3.0.0",
 			"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
 			"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"end-of-stream": "^1.1.0",
 				"once": "^1.3.1"
@@ -6210,6 +6329,8 @@
 			"version": "1.2.8",
 			"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
 			"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"deep-extend": "^0.6.0",
 				"ini": "~1.3.0",
@@ -6471,7 +6592,9 @@
 		"node_modules/set-blocking": {
 			"version": "2.0.0",
 			"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
-			"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
+			"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+			"optional": true,
+			"peer": true
 		},
 		"node_modules/setprototypeof": {
 			"version": "1.1.1",
@@ -6514,7 +6637,8 @@
 		"node_modules/signal-exit": {
 			"version": "3.0.4",
 			"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.4.tgz",
-			"integrity": "sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q=="
+			"integrity": "sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q==",
+			"devOptional": true
 		},
 		"node_modules/simple-concat": {
 			"version": "1.0.1",
@@ -6533,12 +6657,16 @@
 					"type": "consulting",
 					"url": "https://feross.org/support"
 				}
-			]
+			],
+			"optional": true,
+			"peer": true
 		},
 		"node_modules/simple-get": {
-			"version": "3.1.0",
-			"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz",
-			"integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==",
+			"version": "3.1.1",
+			"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz",
+			"integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"decompress-response": "^4.2.0",
 				"once": "^1.3.1",
@@ -6767,6 +6895,8 @@
 			"version": "1.0.2",
 			"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
 			"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"code-point-at": "^1.0.0",
 				"is-fullwidth-code-point": "^1.0.0",
@@ -6780,6 +6910,8 @@
 			"version": "2.1.1",
 			"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
 			"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+			"optional": true,
+			"peer": true,
 			"engines": {
 				"node": ">=0.10.0"
 			}
@@ -6788,6 +6920,8 @@
 			"version": "3.0.1",
 			"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
 			"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"ansi-regex": "^2.0.0"
 			},
@@ -6828,6 +6962,8 @@
 			"version": "2.0.1",
 			"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
 			"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+			"optional": true,
+			"peer": true,
 			"engines": {
 				"node": ">=0.10.0"
 			}
@@ -6879,6 +7015,8 @@
 			"version": "2.1.1",
 			"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
 			"integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"chownr": "^1.1.1",
 				"mkdirp-classic": "^0.5.2",
@@ -6890,6 +7028,8 @@
 			"version": "2.2.0",
 			"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
 			"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"bl": "^4.0.3",
 				"end-of-stream": "^1.4.1",
@@ -6905,6 +7045,8 @@
 			"version": "3.6.0",
 			"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
 			"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"inherits": "^2.0.3",
 				"string_decoder": "^1.1.1",
@@ -6918,6 +7060,8 @@
 			"version": "1.3.0",
 			"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
 			"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"safe-buffer": "~5.2.0"
 			}
@@ -7110,6 +7254,8 @@
 			"version": "0.6.0",
 			"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
 			"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"safe-buffer": "^5.0.1"
 			},
@@ -7661,6 +7807,8 @@
 			"version": "1.1.3",
 			"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
 			"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
+			"optional": true,
+			"peer": true,
 			"dependencies": {
 				"string-width": "^1.0.2 || 2"
 			}
@@ -7807,7 +7955,8 @@
 		"node_modules/yallist": {
 			"version": "4.0.0",
 			"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-			"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+			"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+			"devOptional": true
 		},
 		"node_modules/yargonaut": {
 			"version": "1.1.4",
@@ -9130,12 +9279,16 @@
 		"aproba": {
 			"version": "1.2.0",
 			"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
-			"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw=="
+			"integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
+			"optional": true,
+			"peer": true
 		},
 		"are-we-there-yet": {
 			"version": "1.1.7",
 			"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.7.tgz",
 			"integrity": "sha512-nxwy40TuMiUGqMyRHgCSWZ9FM4VAoRP4xUYSTv5ImRog+h9yISPbVH7H8fASCIzYn9wlEv4zvFL7uKDMCFQm3g==",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"delegates": "^1.0.0",
 				"readable-stream": "^2.0.6"
@@ -9144,12 +9297,16 @@
 				"isarray": {
 					"version": "1.0.0",
 					"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
-					"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+					"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
+					"optional": true,
+					"peer": true
 				},
 				"readable-stream": {
 					"version": "2.3.7",
 					"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
 					"integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+					"optional": true,
+					"peer": true,
 					"requires": {
 						"core-util-is": "~1.0.0",
 						"inherits": "~2.0.3",
@@ -9163,12 +9320,16 @@
 				"safe-buffer": {
 					"version": "5.1.2",
 					"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-					"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+					"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+					"optional": true,
+					"peer": true
 				},
 				"string_decoder": {
 					"version": "1.1.1",
 					"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
 					"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+					"optional": true,
+					"peer": true,
 					"requires": {
 						"safe-buffer": "~5.1.0"
 					}
@@ -9333,6 +9494,8 @@
 			"version": "7.4.3",
 			"resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-7.4.3.tgz",
 			"integrity": "sha512-07bKjClZg/f4KMVRkzWtoIvazVPcF1gsvVKVIXlxwleC2DxuIhnra3KCMlUT1rFeRYXXckot2a46UciF2d9KLw==",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"bindings": "^1.5.0",
 				"prebuild-install": "^6.0.1",
@@ -9342,12 +9505,16 @@
 				"chownr": {
 					"version": "2.0.0",
 					"resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
-					"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ=="
+					"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+					"optional": true,
+					"peer": true
 				},
 				"fs-minipass": {
 					"version": "2.1.0",
 					"resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
 					"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+					"optional": true,
+					"peer": true,
 					"requires": {
 						"minipass": "^3.0.0"
 					}
@@ -9356,6 +9523,8 @@
 					"version": "3.1.5",
 					"resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
 					"integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
+					"optional": true,
+					"peer": true,
 					"requires": {
 						"yallist": "^4.0.0"
 					}
@@ -9364,6 +9533,8 @@
 					"version": "2.1.2",
 					"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
 					"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+					"optional": true,
+					"peer": true,
 					"requires": {
 						"minipass": "^3.0.0",
 						"yallist": "^4.0.0"
@@ -9372,12 +9543,16 @@
 				"mkdirp": {
 					"version": "1.0.4",
 					"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
-					"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw=="
+					"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+					"optional": true,
+					"peer": true
 				},
 				"tar": {
 					"version": "6.1.11",
 					"resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz",
 					"integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==",
+					"optional": true,
+					"peer": true,
 					"requires": {
 						"chownr": "^2.0.0",
 						"fs-minipass": "^2.0.0",
@@ -9393,6 +9568,8 @@
 			"version": "1.5.0",
 			"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
 			"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"file-uri-to-path": "1.0.0"
 			}
@@ -9418,6 +9595,8 @@
 			"version": "4.1.0",
 			"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
 			"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"buffer": "^5.5.0",
 				"inherits": "^2.0.4",
@@ -9428,6 +9607,8 @@
 					"version": "3.6.0",
 					"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
 					"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+					"optional": true,
+					"peer": true,
 					"requires": {
 						"inherits": "^2.0.3",
 						"string_decoder": "^1.1.1",
@@ -9438,6 +9619,8 @@
 					"version": "1.3.0",
 					"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
 					"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+					"optional": true,
+					"peer": true,
 					"requires": {
 						"safe-buffer": "~5.2.0"
 					}
@@ -9525,6 +9708,8 @@
 			"version": "5.7.1",
 			"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
 			"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"base64-js": "^1.3.1",
 				"ieee754": "^1.1.13"
@@ -9607,7 +9792,9 @@
 		"chownr": {
 			"version": "1.1.4",
 			"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
-			"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
+			"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+			"optional": true,
+			"peer": true
 		},
 		"ci-info": {
 			"version": "3.2.0",
@@ -9677,7 +9864,9 @@
 		"code-point-at": {
 			"version": "1.1.0",
 			"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
-			"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
+			"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=",
+			"optional": true,
+			"peer": true
 		},
 		"collect-v8-coverage": {
 			"version": "1.0.1",
@@ -9765,7 +9954,9 @@
 		"console-control-strings": {
 			"version": "1.1.0",
 			"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
-			"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
+			"integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=",
+			"optional": true,
+			"peer": true
 		},
 		"content-disposition": {
 			"version": "0.5.3",
@@ -9902,6 +10093,8 @@
 			"version": "4.2.1",
 			"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz",
 			"integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"mimic-response": "^2.0.0"
 			}
@@ -9915,7 +10108,9 @@
 		"deep-extend": {
 			"version": "0.6.0",
 			"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
-			"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA=="
+			"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+			"optional": true,
+			"peer": true
 		},
 		"deep-is": {
 			"version": "0.1.4",
@@ -9966,7 +10161,9 @@
 		"delegates": {
 			"version": "1.0.0",
 			"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
-			"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
+			"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=",
+			"optional": true,
+			"peer": true
 		},
 		"depd": {
 			"version": "1.1.2",
@@ -9981,7 +10178,9 @@
 		"detect-libc": {
 			"version": "1.0.3",
 			"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
-			"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
+			"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=",
+			"optional": true,
+			"peer": true
 		},
 		"detect-newline": {
 			"version": "3.1.0",
@@ -10081,6 +10280,8 @@
 			"version": "1.4.4",
 			"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
 			"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"once": "^1.4.0"
 			}
@@ -10161,7 +10362,9 @@
 		"expand-template": {
 			"version": "2.0.3",
 			"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
-			"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg=="
+			"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
+			"optional": true,
+			"peer": true
 		},
 		"expect": {
 			"version": "27.2.0",
@@ -10284,7 +10487,9 @@
 		"file-uri-to-path": {
 			"version": "1.0.0",
 			"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
-			"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
+			"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+			"optional": true,
+			"peer": true
 		},
 		"fill-range": {
 			"version": "7.0.1",
@@ -10356,7 +10561,9 @@
 		"fs-constants": {
 			"version": "1.0.0",
 			"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
-			"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
+			"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+			"optional": true,
+			"peer": true
 		},
 		"fs-extra": {
 			"version": "7.0.1",
@@ -10434,6 +10641,8 @@
 			"version": "2.7.4",
 			"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz",
 			"integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"aproba": "^1.0.3",
 				"console-control-strings": "^1.0.0",
@@ -10448,12 +10657,16 @@
 				"ansi-regex": {
 					"version": "2.1.1",
 					"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-					"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+					"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+					"optional": true,
+					"peer": true
 				},
 				"strip-ansi": {
 					"version": "3.0.1",
 					"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
 					"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+					"optional": true,
+					"peer": true,
 					"requires": {
 						"ansi-regex": "^2.0.0"
 					}
@@ -10539,7 +10752,9 @@
 		"github-from-package": {
 			"version": "0.0.0",
 			"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
-			"integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4="
+			"integrity": "sha1-l/tdlr/eiXMxPyDoKI75oWf6ZM4=",
+			"optional": true,
+			"peer": true
 		},
 		"glob": {
 			"version": "7.1.7",
@@ -10615,7 +10830,9 @@
 		"has-unicode": {
 			"version": "2.0.1",
 			"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
-			"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk="
+			"integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=",
+			"optional": true,
+			"peer": true
 		},
 		"helmet": {
 			"version": "4.6.0",
@@ -10784,7 +11001,9 @@
 		"ini": {
 			"version": "1.3.8",
 			"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
-			"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
+			"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+			"optional": true,
+			"peer": true
 		},
 		"ip": {
 			"version": "1.1.5",
@@ -10823,6 +11042,8 @@
 			"version": "1.0.0",
 			"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
 			"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"number-is-nan": "^1.0.0"
 			}
@@ -11816,7 +12037,9 @@
 		"mimic-response": {
 			"version": "2.1.0",
 			"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz",
-			"integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA=="
+			"integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==",
+			"optional": true,
+			"peer": true
 		},
 		"minimatch": {
 			"version": "3.0.4",
@@ -11877,7 +12100,9 @@
 		"mkdirp-classic": {
 			"version": "0.5.3",
 			"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
-			"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
+			"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
+			"optional": true,
+			"peer": true
 		},
 		"ms": {
 			"version": "2.0.0",
@@ -11909,15 +12134,12 @@
 				"thenify-all": "^1.0.0"
 			}
 		},
-		"nanocolors": {
-			"version": "0.2.12",
-			"resolved": "https://registry.npmjs.org/nanocolors/-/nanocolors-0.2.12.tgz",
-			"integrity": "sha512-SFNdALvzW+rVlzqexid6epYdt8H9Zol7xDoQarioEFcFN0JHo4CYNztAxmtfgGTVRCmFlEOqqhBpoFGKqSAMug=="
-		},
 		"napi-build-utils": {
 			"version": "1.0.2",
 			"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
-			"integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg=="
+			"integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg==",
+			"optional": true,
+			"peer": true
 		},
 		"natural-compare": {
 			"version": "1.4.0",
@@ -11975,6 +12197,8 @@
 			"version": "2.30.1",
 			"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-2.30.1.tgz",
 			"integrity": "sha512-/2D0wOQPgaUWzVSVgRMx+trKJRC2UG4SUc4oCJoXx9Uxjtp0Vy3/kt7zcbxHF8+Z/pK3UloLWzBISg72brfy1w==",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"semver": "^5.4.1"
 			},
@@ -11982,7 +12206,9 @@
 				"semver": {
 					"version": "5.7.1",
 					"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
-					"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
+					"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+					"optional": true,
+					"peer": true
 				}
 			}
 		},
@@ -11994,9 +12220,33 @@
 			"peer": true
 		},
 		"node-fetch": {
-			"version": "2.6.2",
-			"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.2.tgz",
-			"integrity": "sha512-aLoxToI6RfZ+0NOjmWAgn9+LEd30YCkJKFSyWacNZdEKTit/ZMcKjGkTRo8uWEsnIb/hfKecNPEbln02PdWbcA=="
+			"version": "2.6.7",
+			"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz",
+			"integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==",
+			"requires": {
+				"whatwg-url": "^5.0.0"
+			},
+			"dependencies": {
+				"tr46": {
+					"version": "0.0.3",
+					"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+					"integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o="
+				},
+				"webidl-conversions": {
+					"version": "3.0.1",
+					"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+					"integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE="
+				},
+				"whatwg-url": {
+					"version": "5.0.0",
+					"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+					"integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=",
+					"requires": {
+						"tr46": "~0.0.3",
+						"webidl-conversions": "^3.0.0"
+					}
+				}
+			}
 		},
 		"node-gyp": {
 			"version": "3.8.0",
@@ -12196,6 +12446,8 @@
 			"version": "4.1.2",
 			"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz",
 			"integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"are-we-there-yet": "~1.1.2",
 				"console-control-strings": "~1.1.0",
@@ -12206,7 +12458,9 @@
 		"number-is-nan": {
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
-			"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
+			"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=",
+			"optional": true,
+			"peer": true
 		},
 		"nwsapi": {
 			"version": "2.2.0",
@@ -12625,6 +12879,11 @@
 				"split2": "^3.1.1"
 			}
 		},
+		"picocolors": {
+			"version": "1.0.0",
+			"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
+			"integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
+		},
 		"picomatch": {
 			"version": "2.3.0",
 			"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
@@ -12675,6 +12934,8 @@
 			"version": "6.1.4",
 			"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-6.1.4.tgz",
 			"integrity": "sha512-Z4vpywnK1lBg+zdPCVCsKq0xO66eEV9rWo2zrROGGiRS4JtueBOdlB1FnY8lcy7JsUud/Q3ijUxyWN26Ika0vQ==",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"detect-libc": "^1.0.3",
 				"expand-template": "^2.0.3",
@@ -12798,6 +13059,8 @@
 			"version": "3.0.0",
 			"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
 			"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"end-of-stream": "^1.1.0",
 				"once": "^1.3.1"
@@ -12839,6 +13102,8 @@
 			"version": "1.2.8",
 			"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
 			"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"deep-extend": "^0.6.0",
 				"ini": "~1.3.0",
@@ -13044,7 +13309,9 @@
 		"set-blocking": {
 			"version": "2.0.0",
 			"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
-			"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
+			"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=",
+			"optional": true,
+			"peer": true
 		},
 		"setprototypeof": {
 			"version": "1.1.1",
@@ -13078,17 +13345,22 @@
 		"signal-exit": {
 			"version": "3.0.4",
 			"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.4.tgz",
-			"integrity": "sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q=="
+			"integrity": "sha512-rqYhcAnZ6d/vTPGghdrw7iumdcbXpsk1b8IG/rz+VWV51DM0p7XCtMoJ3qhPLIbp3tvyt3pKRbaaEMZYpHto8Q==",
+			"devOptional": true
 		},
 		"simple-concat": {
 			"version": "1.0.1",
 			"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
-			"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q=="
+			"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
+			"optional": true,
+			"peer": true
 		},
 		"simple-get": {
-			"version": "3.1.0",
-			"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz",
-			"integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==",
+			"version": "3.1.1",
+			"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.1.tgz",
+			"integrity": "sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"decompress-response": "^4.2.0",
 				"once": "^1.3.1",
@@ -13262,6 +13534,8 @@
 			"version": "1.0.2",
 			"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
 			"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"code-point-at": "^1.0.0",
 				"is-fullwidth-code-point": "^1.0.0",
@@ -13271,12 +13545,16 @@
 				"ansi-regex": {
 					"version": "2.1.1",
 					"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
-					"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+					"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=",
+					"optional": true,
+					"peer": true
 				},
 				"strip-ansi": {
 					"version": "3.0.1",
 					"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
 					"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
+					"optional": true,
+					"peer": true,
 					"requires": {
 						"ansi-regex": "^2.0.0"
 					}
@@ -13306,7 +13584,9 @@
 		"strip-json-comments": {
 			"version": "2.0.1",
 			"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
-			"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo="
+			"integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=",
+			"optional": true,
+			"peer": true
 		},
 		"supports-color": {
 			"version": "7.2.0",
@@ -13348,6 +13628,8 @@
 			"version": "2.1.1",
 			"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
 			"integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"chownr": "^1.1.1",
 				"mkdirp-classic": "^0.5.2",
@@ -13359,6 +13641,8 @@
 			"version": "2.2.0",
 			"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
 			"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"bl": "^4.0.3",
 				"end-of-stream": "^1.4.1",
@@ -13371,6 +13655,8 @@
 					"version": "3.6.0",
 					"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
 					"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
+					"optional": true,
+					"peer": true,
 					"requires": {
 						"inherits": "^2.0.3",
 						"string_decoder": "^1.1.1",
@@ -13381,6 +13667,8 @@
 					"version": "1.3.0",
 					"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
 					"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+					"optional": true,
+					"peer": true,
 					"requires": {
 						"safe-buffer": "~5.2.0"
 					}
@@ -13520,6 +13808,8 @@
 			"version": "0.6.0",
 			"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
 			"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"safe-buffer": "^5.0.1"
 			}
@@ -13876,6 +14166,8 @@
 			"version": "1.1.3",
 			"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz",
 			"integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==",
+			"optional": true,
+			"peer": true,
 			"requires": {
 				"string-width": "^1.0.2 || 2"
 			}
@@ -13980,7 +14272,8 @@
 		"yallist": {
 			"version": "4.0.0",
 			"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
-			"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+			"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+			"devOptional": true
 		},
 		"yargonaut": {
 			"version": "1.1.4",
diff --git a/util/package.json b/util/package.json
index aef5dcfc..d7baed9a 100644
--- a/util/package.json
+++ b/util/package.json
@@ -44,7 +44,7 @@
 		"lambert-server": "^1.2.12",
 		"missing-native-js-functions": "^1.2.18",
 		"multer": "^1.4.3",
-		"node-fetch": "^2.6.1",
+		"node-fetch": "^2.6.2",
 		"patch-package": "^6.4.7",
 		"pg": "^8.7.1",
 		"picocolors": "^1.0.0",
diff --git a/util/src/entities/Channel.ts b/util/src/entities/Channel.ts
index 4036b5d6..1cc4a538 100644
--- a/util/src/entities/Channel.ts
+++ b/util/src/entities/Channel.ts
@@ -1,332 +1,357 @@
-import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm";
-import { BaseClass } from "./BaseClass";
-import { Guild } from "./Guild";
-import { PublicUserProjection, User } from "./User";
-import { HTTPError } from "lambert-server";
-import { containsAll, emitEvent, getPermission, Snowflake, trimSpecial } from "../util";
-import { ChannelCreateEvent, ChannelRecipientRemoveEvent } from "../interfaces";
-import { Recipient } from "./Recipient";
-import { Message } from "./Message";
-import { ReadState } from "./ReadState";
-import { Invite } from "./Invite";
-import { VoiceState } from "./VoiceState";
-import { Webhook } from "./Webhook";
-import { DmChannelDTO } from "../dtos";
-
-export enum ChannelType {
-	GUILD_TEXT = 0, // a text channel within a server
-	DM = 1, // a direct message between users
-	GUILD_VOICE = 2, // a voice channel within a server
-	GROUP_DM = 3, // a direct message between multiple users
-	GUILD_CATEGORY = 4, // an organizational category that contains up to 50 channels
-	GUILD_NEWS = 5, // a channel that users can follow and crosspost into their own server
-	GUILD_STORE = 6, // a channel in which game developers can sell their game on Discord
-	// TODO: what are channel types between 7-9?
-	GUILD_NEWS_THREAD = 10, // a temporary sub-channel within a GUILD_NEWS channel
-	GUILD_PUBLIC_THREAD = 11, // a temporary sub-channel within a GUILD_TEXT channel
-	GUILD_PRIVATE_THREAD = 12, // a temporary sub-channel within a GUILD_TEXT channel that is only viewable by those invited and those with the MANAGE_THREADS permission
-	GUILD_STAGE_VOICE = 13, // a voice channel for hosting events with an audience
-}
-
-@Entity("channels")
-export class Channel extends BaseClass {
-	@Column()
-	created_at: Date;
-
-	@Column({ nullable: true })
-	name?: string;
-
-	@Column({ type: "text", nullable: true })
-	icon?: string | null;
-
-	@Column({ type: "int" })
-	type: ChannelType;
-
-	@OneToMany(() => Recipient, (recipient: Recipient) => recipient.channel, {
-		cascade: true,
-		orphanedRowAction: "delete",
-	})
-	recipients?: Recipient[];
-
-	@Column({ nullable: true })
-	last_message_id: string;
-
-	@Column({ nullable: true })
-	@RelationId((channel: Channel) => channel.guild)
-	guild_id?: string;
-
-	@JoinColumn({ name: "guild_id" })
-	@ManyToOne(() => Guild, {
-		onDelete: "CASCADE",
-	})
-	guild: Guild;
-
-	@Column({ nullable: true })
-	@RelationId((channel: Channel) => channel.parent)
-	parent_id: string;
-
-	@JoinColumn({ name: "parent_id" })
-	@ManyToOne(() => Channel)
-	parent?: Channel;
-
-	// only for group dms
-	@Column({ nullable: true })
-	@RelationId((channel: Channel) => channel.owner)
-	owner_id: string;
-
-	@JoinColumn({ name: "owner_id" })
-	@ManyToOne(() => User)
-	owner: User;
-
-	@Column({ nullable: true })
-	last_pin_timestamp?: number;
-
-	@Column({ nullable: true })
-	default_auto_archive_duration?: number;
-
-	@Column({ nullable: true })
-	position?: number;
-
-	@Column({ type: "simple-json", nullable: true })
-	permission_overwrites?: ChannelPermissionOverwrite[];
-
-	@Column({ nullable: true })
-	video_quality_mode?: number;
-
-	@Column({ nullable: true })
-	bitrate?: number;
-
-	@Column({ nullable: true })
-	user_limit?: number;
-
-	@Column({ nullable: true })
-	nsfw?: boolean;
-
-	@Column({ nullable: true })
-	rate_limit_per_user?: number;
-
-	@Column({ nullable: true })
-	topic?: string;
-
-	@OneToMany(() => Invite, (invite: Invite) => invite.channel, {
-		cascade: true,
-		orphanedRowAction: "delete",
-	})
-	invites?: Invite[];
-
-	@OneToMany(() => Message, (message: Message) => message.channel, {
-		cascade: true,
-		orphanedRowAction: "delete",
-	})
-	messages?: Message[];
-
-	@OneToMany(() => VoiceState, (voice_state: VoiceState) => voice_state.channel, {
-		cascade: true,
-		orphanedRowAction: "delete",
-	})
-	voice_states?: VoiceState[];
-
-	@OneToMany(() => ReadState, (read_state: ReadState) => read_state.channel, {
-		cascade: true,
-		orphanedRowAction: "delete",
-	})
-	read_states?: ReadState[];
-
-	@OneToMany(() => Webhook, (webhook: Webhook) => webhook.channel, {
-		cascade: true,
-		orphanedRowAction: "delete",
-	})
-	webhooks?: Webhook[];
-
-	// TODO: DM channel
-	static async createChannel(
-		channel: Partial<Channel>,
-		user_id: string = "0",
-		opts?: {
-			keepId?: boolean;
-			skipExistsCheck?: boolean;
-			skipPermissionCheck?: boolean;
-			skipEventEmit?: boolean;
-		}
-	) {
-		if (!opts?.skipPermissionCheck) {
-			// Always check if user has permission first
-			const permissions = await getPermission(user_id, channel.guild_id);
-			permissions.hasThrow("MANAGE_CHANNELS");
-		}
-
-		switch (channel.type) {
-			case ChannelType.GUILD_TEXT:
-			case ChannelType.GUILD_VOICE:
-				if (channel.parent_id && !opts?.skipExistsCheck) {
-					const exists = await Channel.findOneOrFail({ id: channel.parent_id });
-					if (!exists) throw new HTTPError("Parent id channel doesn't exist", 400);
-					if (exists.guild_id !== channel.guild_id)
-						throw new HTTPError("The category channel needs to be in the guild");
-				}
-				break;
-			case ChannelType.GUILD_CATEGORY:
-				break;
-			case ChannelType.DM:
-			case ChannelType.GROUP_DM:
-				throw new HTTPError("You can't create a dm channel in a guild");
-			// TODO: check if guild is community server
-			case ChannelType.GUILD_STORE:
-			case ChannelType.GUILD_NEWS:
-			default:
-				throw new HTTPError("Not yet supported");
-		}
-
-		if (!channel.permission_overwrites) channel.permission_overwrites = [];
-		// TODO: auto generate position
-
-		channel = {
-			...channel,
-			...(!opts?.keepId && { id: Snowflake.generate() }),
-			created_at: new Date(),
-			position: channel.position || 0,
-		};
-
-		await Promise.all([
-			new Channel(channel).save(),
-			!opts?.skipEventEmit
-				? emitEvent({
-						event: "CHANNEL_CREATE",
-						data: channel,
-						guild_id: channel.guild_id,
-				  } as ChannelCreateEvent)
-				: Promise.resolve(),
-		]);
-
-		return channel;
-	}
-
-	static async createDMChannel(recipients: string[], creator_user_id: string, name?: string) {
-		recipients = recipients.unique().filter((x) => x !== creator_user_id);
-		const otherRecipientsUsers = await User.find({ where: recipients.map((x) => ({ id: x })) });
-
-		// TODO: check config for max number of recipients
-		if (otherRecipientsUsers.length !== recipients.length) {
-			throw new HTTPError("Recipient/s not found");
-		}
-
-		const type = recipients.length === 1 ? ChannelType.DM : ChannelType.GROUP_DM;
-
-		let channel = null;
-
-		const channelRecipients = [...recipients, creator_user_id];
-
-		const userRecipients = await Recipient.find({
-			where: { user_id: creator_user_id },
-			relations: ["channel", "channel.recipients"],
-		});
-
-		for (let ur of userRecipients) {
-			let re = ur.channel.recipients!.map((r) => r.user_id);
-			if (re.length === channelRecipients.length) {
-				if (containsAll(re, channelRecipients)) {
-					if (channel == null) {
-						channel = ur.channel;
-						await ur.assign({ closed: false }).save();
-					}
-				}
-			}
-		}
-
-		if (channel == null) {
-			name = trimSpecial(name);
-
-			channel = await new Channel({
-				name,
-				type,
-				owner_id: type === ChannelType.DM ? undefined : creator_user_id,
-				created_at: new Date(),
-				last_message_id: null,
-				recipients: channelRecipients.map(
-					(x) =>
-						new Recipient({ user_id: x, closed: !(type === ChannelType.GROUP_DM || x === creator_user_id) })
-				),
-			}).save();
-		}
-
-		const channel_dto = await DmChannelDTO.from(channel);
-
-		if (type === ChannelType.GROUP_DM) {
-			for (let recipient of channel.recipients!) {
-				await emitEvent({
-					event: "CHANNEL_CREATE",
-					data: channel_dto.excludedRecipients([recipient.user_id]),
-					user_id: recipient.user_id,
-				});
-			}
-		} else {
-			await emitEvent({ event: "CHANNEL_CREATE", data: channel_dto, user_id: creator_user_id });
-		}
-
-		return channel_dto.excludedRecipients([creator_user_id]);
-	}
-
-	static async removeRecipientFromChannel(channel: Channel, user_id: string) {
-		await Recipient.delete({ channel_id: channel.id, user_id: user_id });
-		channel.recipients = channel.recipients?.filter((r) => r.user_id !== user_id);
-
-		if (channel.recipients?.length === 0) {
-			await Channel.deleteChannel(channel);
-			await emitEvent({
-				event: "CHANNEL_DELETE",
-				data: await DmChannelDTO.from(channel, [user_id]),
-				user_id: user_id,
-			});
-			return;
-		}
-
-		await emitEvent({
-			event: "CHANNEL_DELETE",
-			data: await DmChannelDTO.from(channel, [user_id]),
-			user_id: user_id,
-		});
-
-		//If the owner leave we make the first recipient in the list the new owner
-		if (channel.owner_id === user_id) {
-			channel.owner_id = channel.recipients!.find((r) => r.user_id !== user_id)!.user_id; //Is there a criteria to choose the new owner?
-			await emitEvent({
-				event: "CHANNEL_UPDATE",
-				data: await DmChannelDTO.from(channel, [user_id]),
-				channel_id: channel.id,
-			});
-		}
-
-		await channel.save();
-
-		await emitEvent({
-			event: "CHANNEL_RECIPIENT_REMOVE",
-			data: {
-				channel_id: channel.id,
-				user: await User.findOneOrFail({ where: { id: user_id }, select: PublicUserProjection }),
-			},
-			channel_id: channel.id,
-		} as ChannelRecipientRemoveEvent);
-	}
-
-	static async deleteChannel(channel: Channel) {
-		await Message.delete({ channel_id: channel.id }); //TODO we should also delete the attachments from the cdn but to do that we need to move cdn.ts in util
-		//TODO before deleting the channel we should check and delete other relations
-		await Channel.delete({ id: channel.id });
-	}
-
-	isDm() {
-		return this.type === ChannelType.DM || this.type === ChannelType.GROUP_DM;
-	}
-}
-
-export interface ChannelPermissionOverwrite {
-	allow: string;
-	deny: string;
-	id: string;
-	type: ChannelPermissionOverwriteType;
-}
-
-export enum ChannelPermissionOverwriteType {
-	role = 0,
-	member = 1,
-}
+import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm";

+import { BaseClass } from "./BaseClass";

+import { Guild } from "./Guild";

+import { PublicUserProjection, User } from "./User";

+import { HTTPError } from "lambert-server";

+import { containsAll, emitEvent, getPermission, Snowflake, trimSpecial, InvisibleCharacters } from "../util";

+import { ChannelCreateEvent, ChannelRecipientRemoveEvent } from "../interfaces";

+import { Recipient } from "./Recipient";

+import { Message } from "./Message";

+import { ReadState } from "./ReadState";

+import { Invite } from "./Invite";

+import { VoiceState } from "./VoiceState";

+import { Webhook } from "./Webhook";

+import { DmChannelDTO } from "../dtos";

+

+export enum ChannelType {

+	GUILD_TEXT = 0, // a text channel within a server

+	DM = 1, // a direct message between users

+	GUILD_VOICE = 2, // a voice channel within a server

+	GROUP_DM = 3, // a direct message between multiple users

+	GUILD_CATEGORY = 4, // an organizational category that contains up to 50 channels

+	GUILD_NEWS = 5, // a channel that users can follow and crosspost into their own server

+	GUILD_STORE = 6, // a channel in which game developers can sell their game on Discord

+	ENCRYPTED = 7, // end-to-end encrypted channel

+	ENCRYPTED_THREAD = 8, // end-to-end encrypted thread channel

+	GUILD_NEWS_THREAD = 10, // a temporary sub-channel within a GUILD_NEWS channel

+	GUILD_PUBLIC_THREAD = 11, // a temporary sub-channel within a GUILD_TEXT channel

+	GUILD_PRIVATE_THREAD = 12, // a temporary sub-channel within a GUILD_TEXT channel that is only viewable by those invited and those with the MANAGE_THREADS permission

+	GUILD_STAGE_VOICE = 13, // a voice channel for hosting events with an audience

+	CUSTOM_START = 64, // start custom channel types from here

+	UNHANDLED = 255 // unhandled unowned pass-through channel type

+}

+

+@Entity("channels")

+export class Channel extends BaseClass {

+	@Column()

+	created_at: Date;

+

+	@Column({ nullable: true })

+	name?: string;

+

+	@Column({ type: "text", nullable: true })

+	icon?: string | null;

+

+	@Column({ type: "int" })

+	type: ChannelType;

+

+	@OneToMany(() => Recipient, (recipient: Recipient) => recipient.channel, {

+		cascade: true,

+		orphanedRowAction: "delete",

+	})

+	recipients?: Recipient[];

+

+	@Column({ nullable: true })

+	last_message_id: string;

+

+	@Column({ nullable: true })

+	@RelationId((channel: Channel) => channel.guild)

+	guild_id?: string;

+

+	@JoinColumn({ name: "guild_id" })

+	@ManyToOne(() => Guild, {

+		onDelete: "CASCADE",

+	})

+	guild: Guild;

+

+	@Column({ nullable: true })

+	@RelationId((channel: Channel) => channel.parent)

+	parent_id: string;

+

+	@JoinColumn({ name: "parent_id" })

+	@ManyToOne(() => Channel)

+	parent?: Channel;

+

+	// only for group dms

+	@Column({ nullable: true })

+	@RelationId((channel: Channel) => channel.owner)

+	owner_id: string;

+

+	@JoinColumn({ name: "owner_id" })

+	@ManyToOne(() => User)

+	owner: User;

+

+	@Column({ nullable: true })

+	last_pin_timestamp?: number;

+

+	@Column({ nullable: true })

+	default_auto_archive_duration?: number;

+

+	@Column({ nullable: true })

+	position?: number;

+

+	@Column({ type: "simple-json", nullable: true })

+	permission_overwrites?: ChannelPermissionOverwrite[];

+

+	@Column({ nullable: true })

+	video_quality_mode?: number;

+

+	@Column({ nullable: true })

+	bitrate?: number;

+

+	@Column({ nullable: true })

+	user_limit?: number;

+

+	@Column({ nullable: true })

+	nsfw?: boolean;

+

+	@Column({ nullable: true })

+	rate_limit_per_user?: number;

+

+	@Column({ nullable: true })

+	topic?: string;

+

+	@OneToMany(() => Invite, (invite: Invite) => invite.channel, {

+		cascade: true,

+		orphanedRowAction: "delete",

+	})

+	invites?: Invite[];

+

+	@OneToMany(() => Message, (message: Message) => message.channel, {

+		cascade: true,

+		orphanedRowAction: "delete",

+	})

+	messages?: Message[];

+

+	@OneToMany(() => VoiceState, (voice_state: VoiceState) => voice_state.channel, {

+		cascade: true,

+		orphanedRowAction: "delete",

+	})

+	voice_states?: VoiceState[];

+

+	@OneToMany(() => ReadState, (read_state: ReadState) => read_state.channel, {

+		cascade: true,

+		orphanedRowAction: "delete",

+	})

+	read_states?: ReadState[];

+

+	@OneToMany(() => Webhook, (webhook: Webhook) => webhook.channel, {

+		cascade: true,

+		orphanedRowAction: "delete",

+	})

+	webhooks?: Webhook[];

+

+	// TODO: DM channel

+	static async createChannel(

+		channel: Partial<Channel>,

+		user_id: string = "0",

+		opts?: {

+			keepId?: boolean;

+			skipExistsCheck?: boolean;

+			skipPermissionCheck?: boolean;

+			skipEventEmit?: boolean;

+			skipNameChecks?: boolean;

+		}

+	) {

+		if (!opts?.skipPermissionCheck) {

+			// Always check if user has permission first

+			const permissions = await getPermission(user_id, channel.guild_id);

+			permissions.hasThrow("MANAGE_CHANNELS");

+		}

+

+		if (!opts?.skipNameChecks) {

+			const guild = await Guild.findOneOrFail({ id: channel.guild_id });

+			if (!guild.features.includes("ALLOW_INVALID_CHANNEL_NAMES") && channel.name) {

+				for (var character of InvisibleCharacters)

+					if (channel.name.includes(character))

+						throw new HTTPError("Channel name cannot include invalid characters", 403);

+

+				if (channel.name.match(/\-\-+/g))

+					throw new HTTPError("Channel name cannot include multiple adjacent dashes.", 403)

+

+				if (channel.name.charAt(0) === "-" ||

+					channel.name.charAt(channel.name.length - 1) === "-")

+					throw new HTTPError("Channel name cannot start/end with dash.", 403)

+			}

+

+			if (!guild.features.includes("ALLOW_UNNAMED_CHANNELS")) {

+				if (!channel.name)

+					throw new HTTPError("Channel name cannot be empty.", 403);

+			}

+		}

+

+		switch (channel.type) {

+			case ChannelType.GUILD_TEXT:

+			case ChannelType.GUILD_VOICE:

+				if (channel.parent_id && !opts?.skipExistsCheck) {

+					const exists = await Channel.findOneOrFail({ id: channel.parent_id });

+					if (!exists) throw new HTTPError("Parent id channel doesn't exist", 400);

+					if (exists.guild_id !== channel.guild_id)

+						throw new HTTPError("The category channel needs to be in the guild");

+				}

+				break;

+			case ChannelType.GUILD_CATEGORY:

+				break;

+			case ChannelType.DM:

+			case ChannelType.GROUP_DM:

+				throw new HTTPError("You can't create a dm channel in a guild");

+			// TODO: check if guild is community server

+			case ChannelType.GUILD_STORE:

+			case ChannelType.GUILD_NEWS:

+			default:

+				throw new HTTPError("Not yet supported");

+		}

+

+		if (!channel.permission_overwrites) channel.permission_overwrites = [];

+		// TODO: auto generate position

+

+		channel = {

+			...channel,

+			...(!opts?.keepId && { id: Snowflake.generate() }),

+			created_at: new Date(),

+			position: channel.position || 0,

+		};

+

+		await Promise.all([

+			new Channel(channel).save(),

+			!opts?.skipEventEmit

+				? emitEvent({

+					event: "CHANNEL_CREATE",

+					data: channel,

+					guild_id: channel.guild_id,

+				} as ChannelCreateEvent)

+				: Promise.resolve(),

+		]);

+

+		return channel;

+	}

+

+	static async createDMChannel(recipients: string[], creator_user_id: string, name?: string) {

+		recipients = recipients.unique().filter((x) => x !== creator_user_id);

+		const otherRecipientsUsers = await User.find({ where: recipients.map((x) => ({ id: x })) });

+

+		// TODO: check config for max number of recipients

+		if (otherRecipientsUsers.length !== recipients.length) {

+			throw new HTTPError("Recipient/s not found");

+		}

+

+		const type = recipients.length === 1 ? ChannelType.DM : ChannelType.GROUP_DM;

+

+		let channel = null;

+

+		const channelRecipients = [...recipients, creator_user_id];

+

+		const userRecipients = await Recipient.find({

+			where: { user_id: creator_user_id },

+			relations: ["channel", "channel.recipients"],

+		});

+

+		for (let ur of userRecipients) {

+			let re = ur.channel.recipients!.map((r) => r.user_id);

+			if (re.length === channelRecipients.length) {

+				if (containsAll(re, channelRecipients)) {

+					if (channel == null) {

+						channel = ur.channel;

+						await ur.assign({ closed: false }).save();

+					}

+				}

+			}

+		}

+

+		if (channel == null) {

+			name = trimSpecial(name);

+

+			channel = await new Channel({

+				name,

+				type,

+				owner_id: type === ChannelType.DM ? undefined : null, // 1:1 DMs are ownerless in fosscord-server

+				created_at: new Date(),

+				last_message_id: null,

+				recipients: channelRecipients.map(

+					(x) =>

+						new Recipient({ user_id: x, closed: !(type === ChannelType.GROUP_DM || x === creator_user_id) })

+				),

+			}).save();

+		}

+

+		const channel_dto = await DmChannelDTO.from(channel);

+

+		if (type === ChannelType.GROUP_DM) {

+			for (let recipient of channel.recipients!) {

+				await emitEvent({

+					event: "CHANNEL_CREATE",

+					data: channel_dto.excludedRecipients([recipient.user_id]),

+					user_id: recipient.user_id,

+				});

+			}

+		} else {

+			await emitEvent({ event: "CHANNEL_CREATE", data: channel_dto, user_id: creator_user_id });

+		}

+

+		return channel_dto.excludedRecipients([creator_user_id]);

+	}

+

+	static async removeRecipientFromChannel(channel: Channel, user_id: string) {

+		await Recipient.delete({ channel_id: channel.id, user_id: user_id });

+		channel.recipients = channel.recipients?.filter((r) => r.user_id !== user_id);

+

+		if (channel.recipients?.length === 0) {

+			await Channel.deleteChannel(channel);

+			await emitEvent({

+				event: "CHANNEL_DELETE",

+				data: await DmChannelDTO.from(channel, [user_id]),

+				user_id: user_id,

+			});

+			return;

+		}

+

+		await emitEvent({

+			event: "CHANNEL_DELETE",

+			data: await DmChannelDTO.from(channel, [user_id]),

+			user_id: user_id,

+		});

+

+		//If the owner leave the server user is the new owner

+		if (channel.owner_id === user_id) {

+			channel.owner_id = "1"; // The channel is now owned by the server user

+			await emitEvent({

+				event: "CHANNEL_UPDATE",

+				data: await DmChannelDTO.from(channel, [user_id]),

+				channel_id: channel.id,

+			});

+		}

+

+		await channel.save();

+

+		await emitEvent({

+			event: "CHANNEL_RECIPIENT_REMOVE",

+			data: {

+				channel_id: channel.id,

+				user: await User.findOneOrFail({ where: { id: user_id }, select: PublicUserProjection }),

+			},

+			channel_id: channel.id,

+		} as ChannelRecipientRemoveEvent);

+	}

+

+	static async deleteChannel(channel: Channel) {

+		await Message.delete({ channel_id: channel.id }); //TODO we should also delete the attachments from the cdn but to do that we need to move cdn.ts in util

+		//TODO before deleting the channel we should check and delete other relations

+		await Channel.delete({ id: channel.id });

+	}

+

+	isDm() {

+		return this.type === ChannelType.DM || this.type === ChannelType.GROUP_DM;

+	}

+}

+

+export interface ChannelPermissionOverwrite {

+	allow: string;

+	deny: string;

+	id: string;

+	type: ChannelPermissionOverwriteType;

+}

+

+export enum ChannelPermissionOverwriteType {

+	role = 0,

+	member = 1,

+}

diff --git a/util/src/entities/Emoji.ts b/util/src/entities/Emoji.ts
index 32d39234..a3615b7d 100644
--- a/util/src/entities/Emoji.ts
+++ b/util/src/entities/Emoji.ts
@@ -41,6 +41,6 @@ export class Emoji extends BaseClass {
 	@Column({ type: "simple-array" })
 	roles: string[]; // roles this emoji is whitelisted to (new discord feature?)
 	
-	@Column({ type: "simple-array" })
+	@Column({ type: "simple-array", nullable: true })
 	groups: string[]; // user groups this emoji is whitelisted to (Fosscord extension)
 }
diff --git a/util/src/entities/Message.ts b/util/src/entities/Message.ts
index 20a44ca3..e577d5df 100644
--- a/util/src/entities/Message.ts
+++ b/util/src/entities/Message.ts
@@ -84,8 +84,10 @@ export class Message extends BaseClass {
 	@RelationId((message: Message) => message.member)
 	member_id: string;
 
-	@JoinColumn({ name: "member_id" })
-	@ManyToOne(() => Member)
+	@JoinColumn({ name: "author_id", referencedColumnName: "id" })
+	@ManyToOne(() => User, {
+		onDelete: "CASCADE",
+	})
 	member?: Member;
 
 	@Column({ nullable: true })
diff --git a/util/src/util/Database.ts b/util/src/util/Database.ts
index e8177093..9ab5d14c 100644
--- a/util/src/util/Database.ts
+++ b/util/src/util/Database.ts
@@ -25,6 +25,7 @@ export function initDatabase(): Promise<Connection> {
 	// @ts-ignore
 	promise = createConnection({
 		type,
+        charset: 'utf8mb4',
 		url: isSqlite ? undefined : dbConnectionString,
 		database: isSqlite ? dbConnectionString : undefined,
 		// @ts-ignore
diff --git a/util/src/util/InvisibleCharacters.ts b/util/src/util/InvisibleCharacters.ts
new file mode 100644
index 00000000..2b014e14
--- /dev/null
+++ b/util/src/util/InvisibleCharacters.ts
@@ -0,0 +1,56 @@
+// List from https://invisible-characters.com/

+export const InvisibleCharacters = [

+	'\u{9}',			//Tab

+	'\u{20}',			//Space

+	'\u{ad}',			//Soft hyphen

+	'\u{34f}',			//Combining grapheme joiner

+	'\u{61c}',			//Arabic letter mark

+	'\u{115f}',			//Hangul choseong filler

+	'\u{1160}',			//Hangul jungseong filler

+	'\u{17b4}',			//Khmer vowel inherent AQ

+	'\u{17b5}',			//Khmer vowel inherent AA

+	'\u{180e}',			//Mongolian vowel separator

+	'\u{2000}',			//En quad

+	'\u{2001}',			//Em quad

+	'\u{2002}',			//En space

+	'\u{2003}',			//Em space

+	'\u{2004}',			//Three-per-em space

+	'\u{2005}',			//Four-per-em space

+	'\u{2006}',			//Six-per-em space

+	'\u{2007}',			//Figure space

+	'\u{2008}',			//Punctuation space

+	'\u{2009}',			//Thin space

+	'\u{200a}',			//Hair space

+	'\u{200b}',			//Zero width space

+	'\u{200c}',			//Zero width non-joiner

+	'\u{200d}',			//Zero width joiner

+	'\u{200e}',			//Left-to-right mark

+	'\u{200f}',			//Right-to-left mark

+	'\u{202f}',			//Narrow no-break space

+	'\u{205f}',			//Medium mathematical space

+	'\u{2060}',			//Word joiner

+	'\u{2061}',			//Function application

+	'\u{2062}',			//Invisible times

+	'\u{2063}',			//Invisible separator

+	'\u{2064}',			//Invisible plus

+	'\u{206a}',			//Inhibit symmetric swapping

+	'\u{206b}',			//Activate symmetric swapping

+	'\u{206c}',			//Inhibit arabic form shaping

+	'\u{206d}',			//Activate arabic form shaping

+	'\u{206e}',			//National digit shapes

+	'\u{206f}',			//Nominal digit shapes

+	'\u{3000}',			//Ideographic space

+	'\u{2800}',			//Braille pattern blank

+	'\u{3164}',			//Hangul filler

+	'\u{feff}',			//Zero width no-break space

+	'\u{ffa0}',			//Haldwidth hangul filler

+	'\u{1d159}',		//Musical symbol null notehead

+	'\u{1d173}',		//Musical symbol begin beam 

+	'\u{1d174}',		//Musical symbol end beam

+	'\u{1d175}',		//Musical symbol begin tie

+	'\u{1d176}',		//Musical symbol end tie

+	'\u{1d177}',		//Musical symbol begin slur

+	'\u{1d178}',		//Musical symbol end slur

+	'\u{1d179}',		//Musical symbol begin phrase

+	'\u{1d17a}'			//Musical symbol end phrase

+]; 
\ No newline at end of file
diff --git a/util/src/util/Rights.ts b/util/src/util/Rights.ts
index f0d00baf..9a99d393 100644
--- a/util/src/util/Rights.ts
+++ b/util/src/util/Rights.ts
@@ -35,9 +35,9 @@ export class Rights extends BitField {
 		ADD_MEMBERS: BitFlag(8), // can manually add any members in their guilds
 		BYPASS_RATE_LIMITS: BitFlag(9),
 		CREATE_APPLICATIONS: BitFlag(10),
-		CREATE_CHANNELS: BitFlag(11),
+		CREATE_CHANNELS: BitFlag(11), // can create guild channels or threads in the guilds that they have permission
 		CREATE_DMS: BitFlag(12),
-		CREATE_DM_GROUPS: BitFlag(13),
+		CREATE_DM_GROUPS: BitFlag(13), // can create group DMs or custom orphan channels
 		CREATE_GUILDS: BitFlag(14),
 		CREATE_INVITES: BitFlag(15), // can create mass invites in the guilds that they have CREATE_INSTANT_INVITE
 		CREATE_ROLES: BitFlag(16),
@@ -57,6 +57,17 @@ export class Rights extends BitField {
 		SELF_DELETE_DISABLE: BitFlag(30), // can disable/delete own account
 		DEBTABLE: BitFlag(31), // can use pay-to-use features
 		CREDITABLE: BitFlag(32), // can receive money from monetisation related features
+		KICK_BAN_MEMBERS: BitFlag(33),
+		// can kick or ban guild or group DM members in the guilds/groups that they have KICK_MEMBERS, or BAN_MEMBERS
+		SELF_LEAVE_GROUPS: BitFlag(34), 
+		// can leave the guilds or group DMs that they joined on their own (one can always leave a guild or group DMs they have been force-added)
+		PRESENCE: BitFlag(35),
+		// inverts the presence confidentiality default (OPERATOR's presence is not routed by default, others' are) for a given user
+		SELF_ADD_DISCOVERABLE: BitFlag(36), // can mark discoverable guilds that they have permissions to mark as discoverable
+		MANAGE_GUILD_DIRECTORY: BitFlag(37), // can change anything in the primary guild directory
+		INITIATE_INTERACTIONS: BitFlag(40), // can initiate interactions
+		RESPOND_TO_INTERACTIONS: BitFlag(41), // can respond to interactions
+		SEND_BACKDATED_EVENTS: BitFlag(42), // can send backdated events
 	};
 
 	any(permission: RightResolvable, checkOperator = true) {
diff --git a/util/src/util/index.ts b/util/src/util/index.ts
index c5703468..98e1146c 100644
--- a/util/src/util/index.ts
+++ b/util/src/util/index.ts
@@ -18,3 +18,4 @@ export * from "./Snowflake";
 export * from "./String";
 export * from "./Array";
 export * from "./TraverseDirectory";
+export * from "./InvisibleCharacters";
\ No newline at end of file