✨ update util
This commit is contained in:
parent
e99008a1a5
commit
766dcc24aa
1
util/.vscode/launch.json
vendored
1
util/.vscode/launch.json
vendored
@ -18,6 +18,7 @@
|
|||||||
"type": "node",
|
"type": "node",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"runtimeArgs": ["--inspect-brk", "${workspaceRoot}/node_modules/jest/bin/jest.js", "--runInBand"],
|
"runtimeArgs": ["--inspect-brk", "${workspaceRoot}/node_modules/jest/bin/jest.js", "--runInBand"],
|
||||||
|
"preLaunchTask": "tsc: build - tsconfig.json",
|
||||||
"console": "integratedTerminal",
|
"console": "integratedTerminal",
|
||||||
"internalConsoleOptions": "neverOpen",
|
"internalConsoleOptions": "neverOpen",
|
||||||
"port": 9229
|
"port": 9229
|
||||||
|
313
util/package-lock.json
generated
313
util/package-lock.json
generated
@ -16,10 +16,11 @@
|
|||||||
"dot-prop": "^6.0.1",
|
"dot-prop": "^6.0.1",
|
||||||
"env-paths": "^2.2.1",
|
"env-paths": "^2.2.1",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
"lambert-server": "^1.2.8",
|
"lambert-server": "^1.2.10",
|
||||||
"missing-native-js-functions": "^1.2.10",
|
"missing-native-js-functions": "^1.2.11",
|
||||||
"node-fetch": "^2.6.1",
|
"node-fetch": "^2.6.1",
|
||||||
"patch-package": "^6.4.7",
|
"patch-package": "^6.4.7",
|
||||||
|
"pg": "^8.7.1",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"sqlite3": "^5.0.2",
|
"sqlite3": "^5.0.2",
|
||||||
"typeorm": "^0.2.37",
|
"typeorm": "^0.2.37",
|
||||||
@ -1765,6 +1766,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz",
|
||||||
"integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg=="
|
"integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/buffer-writer": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bytes": {
|
"node_modules/bytes": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
|
||||||
@ -6098,16 +6107,16 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/lambert-server": {
|
"node_modules/lambert-server": {
|
||||||
"version": "1.2.8",
|
"version": "1.2.10",
|
||||||
"resolved": "https://registry.npmjs.org/lambert-server/-/lambert-server-1.2.8.tgz",
|
"resolved": "https://registry.npmjs.org/lambert-server/-/lambert-server-1.2.10.tgz",
|
||||||
"integrity": "sha512-vi/Ku/QudY+WIdGO9bc0qLfVhfuJFWXk1+etesPW1vW29sPbmevLL6IwfvCtw+/MyzRAJLOyCBfQ310a68+2QQ==",
|
"integrity": "sha512-BHGPmpUrRklFJHPu0vAA8NBewtEd4IX80FRpV4nX9z8kHTUYHqnYHoBeUEWoUmxAeFQvQae1Axk5RQXRQk4VNw==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"body-parser": "^1.19.0",
|
"body-parser": "^1.19.0",
|
||||||
"chalk": "^4.1.1",
|
"chalk": "^4.1.1",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-async-errors": "^3.1.1",
|
"express-async-errors": "^3.1.1",
|
||||||
"helmet": "^4.4.1",
|
"helmet": "^4.4.1",
|
||||||
"missing-native-js-functions": "^1.1.8"
|
"missing-native-js-functions": "^1.2.11"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/leven": {
|
"node_modules/leven": {
|
||||||
@ -6329,9 +6338,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/missing-native-js-functions": {
|
"node_modules/missing-native-js-functions": {
|
||||||
"version": "1.2.10",
|
"version": "1.2.11",
|
||||||
"resolved": "https://registry.npmjs.org/missing-native-js-functions/-/missing-native-js-functions-1.2.10.tgz",
|
"resolved": "https://registry.npmjs.org/missing-native-js-functions/-/missing-native-js-functions-1.2.11.tgz",
|
||||||
"integrity": "sha512-sq+oAw/C3OtUyKopLNOf/+U85YNx7db6fy5nVfGVKlGdcV8tX24GjOSkcZeCAnAIjMEnlQBWTr17JXa3OJj22g=="
|
"integrity": "sha512-U97IscNBL4Wg9adYjEBT46Hb0Ld5dPT8vbdwFX+TNzGrFQCc4WqoGAZouaLNFwUqxzzHZ9DVg59unwnQyeIIQg=="
|
||||||
},
|
},
|
||||||
"node_modules/mkdirp": {
|
"node_modules/mkdirp": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
@ -6916,6 +6925,11 @@
|
|||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/packet-reader": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ=="
|
||||||
|
},
|
||||||
"node_modules/parent-require": {
|
"node_modules/parent-require": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/parent-require/-/parent-require-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/parent-require/-/parent-require-1.0.0.tgz",
|
||||||
@ -7065,6 +7079,80 @@
|
|||||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
|
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"node_modules/pg": {
|
||||||
|
"version": "8.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pg/-/pg-8.7.1.tgz",
|
||||||
|
"integrity": "sha512-7bdYcv7V6U3KAtWjpQJJBww0UEsWuh4yQ/EjNf2HeO/NnvKjpvhEIe/A/TleP6wtmSKnUnghs5A9jUoK6iDdkA==",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer-writer": "2.0.0",
|
||||||
|
"packet-reader": "1.0.0",
|
||||||
|
"pg-connection-string": "^2.5.0",
|
||||||
|
"pg-pool": "^3.4.1",
|
||||||
|
"pg-protocol": "^1.5.0",
|
||||||
|
"pg-types": "^2.1.0",
|
||||||
|
"pgpass": "1.x"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"pg-native": ">=2.0.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"pg-native": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pg-connection-string": {
|
||||||
|
"version": "2.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz",
|
||||||
|
"integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ=="
|
||||||
|
},
|
||||||
|
"node_modules/pg-int8": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pg-pool": {
|
||||||
|
"version": "3.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.4.1.tgz",
|
||||||
|
"integrity": "sha512-TVHxR/gf3MeJRvchgNHxsYsTCHQ+4wm3VIHSS19z8NC0+gioEhq1okDY1sm/TYbfoP6JLFx01s0ShvZ3puP/iQ==",
|
||||||
|
"peerDependencies": {
|
||||||
|
"pg": ">=8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pg-protocol": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ=="
|
||||||
|
},
|
||||||
|
"node_modules/pg-types": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
|
||||||
|
"dependencies": {
|
||||||
|
"pg-int8": "1.0.1",
|
||||||
|
"postgres-array": "~2.0.0",
|
||||||
|
"postgres-bytea": "~1.0.0",
|
||||||
|
"postgres-date": "~1.0.4",
|
||||||
|
"postgres-interval": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/pgpass": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-YmuA56alyBq7M59vxVBfPJrGSozru8QAdoNlWuW3cz8l+UX3cWge0vTvjKhsSHSJpo3Bom8/Mm6hf0TR5GY0+w==",
|
||||||
|
"dependencies": {
|
||||||
|
"split2": "^3.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/picomatch": {
|
"node_modules/picomatch": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
|
||||||
@ -7088,6 +7176,41 @@
|
|||||||
"node": ">= 6"
|
"node": ">= 6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/postgres-array": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/postgres-bytea": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU=",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/postgres-date": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/postgres-interval": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"xtend": "^4.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/prelude-ls": {
|
"node_modules/prelude-ls": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
|
||||||
@ -7604,6 +7727,35 @@
|
|||||||
"memory-pager": "^1.0.2"
|
"memory-pager": "^1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/split2": {
|
||||||
|
"version": "3.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz",
|
||||||
|
"integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==",
|
||||||
|
"dependencies": {
|
||||||
|
"readable-stream": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/split2/node_modules/readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/split2/node_modules/string_decoder": {
|
||||||
|
"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==",
|
||||||
|
"dependencies": {
|
||||||
|
"safe-buffer": "~5.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/sprintf-js": {
|
"node_modules/sprintf-js": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||||
@ -8492,6 +8644,14 @@
|
|||||||
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
|
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/xtend": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/y18n": {
|
"node_modules/y18n": {
|
||||||
"version": "5.0.8",
|
"version": "5.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||||
@ -10030,6 +10190,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz",
|
||||||
"integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg=="
|
"integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg=="
|
||||||
},
|
},
|
||||||
|
"buffer-writer": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw=="
|
||||||
|
},
|
||||||
"bytes": {
|
"bytes": {
|
||||||
"version": "3.1.0",
|
"version": "3.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
|
||||||
@ -13373,16 +13538,16 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"lambert-server": {
|
"lambert-server": {
|
||||||
"version": "1.2.8",
|
"version": "1.2.10",
|
||||||
"resolved": "https://registry.npmjs.org/lambert-server/-/lambert-server-1.2.8.tgz",
|
"resolved": "https://registry.npmjs.org/lambert-server/-/lambert-server-1.2.10.tgz",
|
||||||
"integrity": "sha512-vi/Ku/QudY+WIdGO9bc0qLfVhfuJFWXk1+etesPW1vW29sPbmevLL6IwfvCtw+/MyzRAJLOyCBfQ310a68+2QQ==",
|
"integrity": "sha512-BHGPmpUrRklFJHPu0vAA8NBewtEd4IX80FRpV4nX9z8kHTUYHqnYHoBeUEWoUmxAeFQvQae1Axk5RQXRQk4VNw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"body-parser": "^1.19.0",
|
"body-parser": "^1.19.0",
|
||||||
"chalk": "^4.1.1",
|
"chalk": "^4.1.1",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-async-errors": "^3.1.1",
|
"express-async-errors": "^3.1.1",
|
||||||
"helmet": "^4.4.1",
|
"helmet": "^4.4.1",
|
||||||
"missing-native-js-functions": "^1.1.8"
|
"missing-native-js-functions": "^1.2.11"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"leven": {
|
"leven": {
|
||||||
@ -13570,9 +13735,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"missing-native-js-functions": {
|
"missing-native-js-functions": {
|
||||||
"version": "1.2.10",
|
"version": "1.2.11",
|
||||||
"resolved": "https://registry.npmjs.org/missing-native-js-functions/-/missing-native-js-functions-1.2.10.tgz",
|
"resolved": "https://registry.npmjs.org/missing-native-js-functions/-/missing-native-js-functions-1.2.11.tgz",
|
||||||
"integrity": "sha512-sq+oAw/C3OtUyKopLNOf/+U85YNx7db6fy5nVfGVKlGdcV8tX24GjOSkcZeCAnAIjMEnlQBWTr17JXa3OJj22g=="
|
"integrity": "sha512-U97IscNBL4Wg9adYjEBT46Hb0Ld5dPT8vbdwFX+TNzGrFQCc4WqoGAZouaLNFwUqxzzHZ9DVg59unwnQyeIIQg=="
|
||||||
},
|
},
|
||||||
"mkdirp": {
|
"mkdirp": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
@ -14013,6 +14178,11 @@
|
|||||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"packet-reader": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ=="
|
||||||
|
},
|
||||||
"parent-require": {
|
"parent-require": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/parent-require/-/parent-require-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/parent-require/-/parent-require-1.0.0.tgz",
|
||||||
@ -14136,6 +14306,61 @@
|
|||||||
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
|
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=",
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
|
"pg": {
|
||||||
|
"version": "8.7.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pg/-/pg-8.7.1.tgz",
|
||||||
|
"integrity": "sha512-7bdYcv7V6U3KAtWjpQJJBww0UEsWuh4yQ/EjNf2HeO/NnvKjpvhEIe/A/TleP6wtmSKnUnghs5A9jUoK6iDdkA==",
|
||||||
|
"requires": {
|
||||||
|
"buffer-writer": "2.0.0",
|
||||||
|
"packet-reader": "1.0.0",
|
||||||
|
"pg-connection-string": "^2.5.0",
|
||||||
|
"pg-pool": "^3.4.1",
|
||||||
|
"pg-protocol": "^1.5.0",
|
||||||
|
"pg-types": "^2.1.0",
|
||||||
|
"pgpass": "1.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pg-connection-string": {
|
||||||
|
"version": "2.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz",
|
||||||
|
"integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ=="
|
||||||
|
},
|
||||||
|
"pg-int8": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw=="
|
||||||
|
},
|
||||||
|
"pg-pool": {
|
||||||
|
"version": "3.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.4.1.tgz",
|
||||||
|
"integrity": "sha512-TVHxR/gf3MeJRvchgNHxsYsTCHQ+4wm3VIHSS19z8NC0+gioEhq1okDY1sm/TYbfoP6JLFx01s0ShvZ3puP/iQ==",
|
||||||
|
"requires": {}
|
||||||
|
},
|
||||||
|
"pg-protocol": {
|
||||||
|
"version": "1.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.5.0.tgz",
|
||||||
|
"integrity": "sha512-muRttij7H8TqRNu/DxrAJQITO4Ac7RmX3Klyr/9mJEOBeIpgnF8f9jAfRz5d3XwQZl5qBjF9gLsUtMPJE0vezQ=="
|
||||||
|
},
|
||||||
|
"pg-types": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
|
||||||
|
"requires": {
|
||||||
|
"pg-int8": "1.0.1",
|
||||||
|
"postgres-array": "~2.0.0",
|
||||||
|
"postgres-bytea": "~1.0.0",
|
||||||
|
"postgres-date": "~1.0.4",
|
||||||
|
"postgres-interval": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pgpass": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-YmuA56alyBq7M59vxVBfPJrGSozru8QAdoNlWuW3cz8l+UX3cWge0vTvjKhsSHSJpo3Bom8/Mm6hf0TR5GY0+w==",
|
||||||
|
"requires": {
|
||||||
|
"split2": "^3.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"picomatch": {
|
"picomatch": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
|
||||||
@ -14150,6 +14375,29 @@
|
|||||||
"node-modules-regexp": "^1.0.0"
|
"node-modules-regexp": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"postgres-array": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
|
||||||
|
"integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA=="
|
||||||
|
},
|
||||||
|
"postgres-bytea": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-AntTPAqokOJtFy1Hz5zOzFIazTU="
|
||||||
|
},
|
||||||
|
"postgres-date": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q=="
|
||||||
|
},
|
||||||
|
"postgres-interval": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
|
||||||
|
"requires": {
|
||||||
|
"xtend": "^4.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"prelude-ls": {
|
"prelude-ls": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
|
||||||
@ -14564,6 +14812,34 @@
|
|||||||
"memory-pager": "^1.0.2"
|
"memory-pager": "^1.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"split2": {
|
||||||
|
"version": "3.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz",
|
||||||
|
"integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==",
|
||||||
|
"requires": {
|
||||||
|
"readable-stream": "^3.0.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "3.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
|
||||||
|
"integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
|
||||||
|
"requires": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"string_decoder": {
|
||||||
|
"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==",
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "~5.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"sprintf-js": {
|
"sprintf-js": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||||
@ -15187,6 +15463,11 @@
|
|||||||
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
|
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"xtend": {
|
||||||
|
"version": "4.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
|
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ=="
|
||||||
|
},
|
||||||
"y18n": {
|
"y18n": {
|
||||||
"version": "5.0.8",
|
"version": "5.0.8",
|
||||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
|
||||||
|
@ -9,8 +9,7 @@
|
|||||||
"patch": "patch-package",
|
"patch": "patch-package",
|
||||||
"test": "npm run build && jest",
|
"test": "npm run build && jest",
|
||||||
"postinstall": "npm run patch && npm run build",
|
"postinstall": "npm run patch && npm run build",
|
||||||
"build": "npx tsc -b .",
|
"build": "npx tsc -b ."
|
||||||
"generate:schema": "npx typescript-json-schema tsconfig.json '*' -o src/entities/schema.json"
|
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
@ -44,10 +43,11 @@
|
|||||||
"dot-prop": "^6.0.1",
|
"dot-prop": "^6.0.1",
|
||||||
"env-paths": "^2.2.1",
|
"env-paths": "^2.2.1",
|
||||||
"jsonwebtoken": "^8.5.1",
|
"jsonwebtoken": "^8.5.1",
|
||||||
"lambert-server": "^1.2.8",
|
"lambert-server": "^1.2.10",
|
||||||
"missing-native-js-functions": "^1.2.10",
|
"missing-native-js-functions": "^1.2.11",
|
||||||
"node-fetch": "^2.6.1",
|
"node-fetch": "^2.6.1",
|
||||||
"patch-package": "^6.4.7",
|
"patch-package": "^6.4.7",
|
||||||
|
"pg": "^8.7.1",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"sqlite3": "^5.0.2",
|
"sqlite3": "^5.0.2",
|
||||||
"typeorm": "^0.2.37",
|
"typeorm": "^0.2.37",
|
||||||
|
@ -8,13 +8,13 @@ export class Application extends BaseClass {
|
|||||||
@Column()
|
@Column()
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
icon?: string;
|
icon?: string;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
description: string;
|
description: string;
|
||||||
|
|
||||||
@Column("simple-array")
|
@Column({ type: "simple-array", nullable: true })
|
||||||
rpc_origins?: string[];
|
rpc_origins?: string[];
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
@ -23,16 +23,16 @@ export class Application extends BaseClass {
|
|||||||
@Column()
|
@Column()
|
||||||
bot_require_code_grant: boolean;
|
bot_require_code_grant: boolean;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
terms_of_service_url?: string;
|
terms_of_service_url?: string;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
privacy_policy_url?: string;
|
privacy_policy_url?: string;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
owner_id: string;
|
owner_id: string;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
summary?: string;
|
summary?: string;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
@ -52,13 +52,13 @@ export class Application extends BaseClass {
|
|||||||
@ManyToOne(() => Guild, (guild: Guild) => guild.id)
|
@ManyToOne(() => Guild, (guild: Guild) => guild.id)
|
||||||
guild: Guild; // if this application is a game sold, this field will be the guild to which it has been linked
|
guild: Guild; // if this application is a game sold, this field will be the guild to which it has been linked
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
primary_sku_id?: string; // if this application is a game sold, this field will be the id of the "Game SKU" that is created,
|
primary_sku_id?: string; // if this application is a game sold, this field will be the id of the "Game SKU" that is created,
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
slug?: string; // if this application is a game sold, this field will be the URL slug that links to the store page
|
slug?: string; // if this application is a game sold, this field will be the URL slug that links to the store page
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
cover_image?: string; // the application's default rich presence invite cover image hash
|
cover_image?: string; // the application's default rich presence invite cover image hash
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
|
@ -46,7 +46,7 @@ export class AuditLogEntry extends BaseClass {
|
|||||||
@RelationId((auditlog: AuditLogEntry) => auditlog.target)
|
@RelationId((auditlog: AuditLogEntry) => auditlog.target)
|
||||||
target_id: string;
|
target_id: string;
|
||||||
|
|
||||||
@JoinColumn({ name: "user_id" })
|
@JoinColumn({ name: "target_id" })
|
||||||
@ManyToOne(() => User, (user: User) => user.id)
|
@ManyToOne(() => User, (user: User) => user.id)
|
||||||
target?: User;
|
target?: User;
|
||||||
|
|
||||||
@ -63,7 +63,7 @@ export class AuditLogEntry extends BaseClass {
|
|||||||
})
|
})
|
||||||
action_type: AuditLogEvents;
|
action_type: AuditLogEvents;
|
||||||
|
|
||||||
@Column("simple-json")
|
@Column({ type: "simple-json", nullable: true })
|
||||||
options?: {
|
options?: {
|
||||||
delete_member_days?: string;
|
delete_member_days?: string;
|
||||||
members_removed?: string;
|
members_removed?: string;
|
||||||
@ -76,10 +76,10 @@ export class AuditLogEntry extends BaseClass {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
@Column("simple-json")
|
@Column({ type: "simple-json" })
|
||||||
changes: AuditLogChange[];
|
changes: AuditLogChange[];
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
reason?: string;
|
reason?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,6 @@ export class Ban extends BaseClass {
|
|||||||
@Column()
|
@Column()
|
||||||
ip: string;
|
ip: string;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
reason?: string;
|
reason?: string;
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,26 @@
|
|||||||
import "reflect-metadata";
|
import "reflect-metadata";
|
||||||
import { BaseEntity, BeforeInsert, BeforeUpdate, PrimaryColumn } from "typeorm";
|
import {
|
||||||
|
BaseEntity,
|
||||||
|
BeforeInsert,
|
||||||
|
BeforeUpdate,
|
||||||
|
EntityMetadata,
|
||||||
|
FindConditions,
|
||||||
|
FindManyOptions,
|
||||||
|
PrimaryColumn,
|
||||||
|
} from "typeorm";
|
||||||
import { Snowflake } from "../util/Snowflake";
|
import { Snowflake } from "../util/Snowflake";
|
||||||
import Ajv, { ValidateFunction } from "ajv";
|
|
||||||
import schema from "./schema.json";
|
|
||||||
import "missing-native-js-functions";
|
import "missing-native-js-functions";
|
||||||
|
|
||||||
// TODO use class-validator https://typeorm.io/#/validation with class annotators (isPhone/isEmail) combined with types from typescript-json-schema
|
// TODO use class-validator https://typeorm.io/#/validation with class annotators (isPhone/isEmail) combined with types from typescript-json-schema
|
||||||
// btw. we don't use class-validator for everything, because we need to explicitly set the type instead of deriving it from typescript also it doesn't easily support nested objects
|
// btw. we don't use class-validator for everything, because we need to explicitly set the type instead of deriving it from typescript also it doesn't easily support nested objects
|
||||||
|
|
||||||
const ajv = new Ajv({
|
|
||||||
removeAdditional: "all",
|
|
||||||
useDefaults: true,
|
|
||||||
coerceTypes: true,
|
|
||||||
// @ts-ignore
|
|
||||||
validateFormats: false,
|
|
||||||
allowUnionTypes: true,
|
|
||||||
});
|
|
||||||
|
|
||||||
export class BaseClass extends BaseEntity {
|
export class BaseClass extends BaseEntity {
|
||||||
@PrimaryColumn()
|
@PrimaryColumn()
|
||||||
id: string;
|
id: string;
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
constructor(props?: any, public opts: { id?: string } = {}) {
|
constructor(public props?: any, public opts: { id?: string } = {}) {
|
||||||
super();
|
super();
|
||||||
this.assign(props);
|
|
||||||
|
|
||||||
if (!this.construct.schema) {
|
|
||||||
this.construct.schema = ajv.compile({ ...schema, $ref: `#/definitions/${this.construct.name}` });
|
|
||||||
}
|
|
||||||
|
|
||||||
this.id = this.opts.id || Snowflake.generate();
|
this.id = this.opts.id || Snowflake.generate();
|
||||||
}
|
}
|
||||||
@ -38,19 +30,20 @@ export class BaseClass extends BaseEntity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get metadata() {
|
get metadata() {
|
||||||
return this.construct.getRepository().metadata;
|
return this.construct.getRepository().metadata as EntityMetadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
assign(props: any) {
|
assign(props: any) {
|
||||||
if (!props || typeof props !== "object") return;
|
if (!props || typeof props !== "object") return;
|
||||||
|
|
||||||
|
delete props.id;
|
||||||
delete props.opts;
|
delete props.opts;
|
||||||
|
delete props.props;
|
||||||
|
|
||||||
const properties = new Set(this.metadata.columns.map((x: any) => x.propertyName));
|
const properties = new Set(this.metadata.columns.map((x: any) => x.propertyName));
|
||||||
// will not include relational properties (e.g. @RelationId @ManyToMany)
|
// will not include relational properties (e.g. @RelationId @ManyToMany)
|
||||||
|
|
||||||
for (const key in props) {
|
for (const key in props) {
|
||||||
if (this.hasOwnProperty(key)) continue;
|
|
||||||
if (!properties.has(key)) continue;
|
if (!properties.has(key)) continue;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const setter = this[`set${key.capitalize()}`];
|
const setter = this[`set${key.capitalize()}`];
|
||||||
@ -66,8 +59,7 @@ export class BaseClass extends BaseEntity {
|
|||||||
@BeforeUpdate()
|
@BeforeUpdate()
|
||||||
@BeforeInsert()
|
@BeforeInsert()
|
||||||
validate() {
|
validate() {
|
||||||
const valid = this.construct.schema(this.toJSON());
|
this.assign(this.props);
|
||||||
if (!valid) throw ajv.errors;
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,4 +67,14 @@ export class BaseClass extends BaseEntity {
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return Object.fromEntries(this.metadata.columns.map((x) => [x.propertyName, this[x.propertyName]]));
|
return Object.fromEntries(this.metadata.columns.map((x) => [x.propertyName, this[x.propertyName]]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static increment<T extends BaseClass>(conditions: FindConditions<T>, propertyPath: string, value: number | string) {
|
||||||
|
const repository = this.getRepository();
|
||||||
|
return repository.increment(conditions, propertyPath, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static decrement<T extends BaseClass>(conditions: FindConditions<T>, propertyPath: string, value: number | string) {
|
||||||
|
const repository = this.getRepository();
|
||||||
|
return repository.decrement(conditions, propertyPath, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -60,25 +60,25 @@ export class Channel extends BaseClass {
|
|||||||
@ManyToOne(() => User, (user: User) => user.id)
|
@ManyToOne(() => User, (user: User) => user.id)
|
||||||
owner: User;
|
owner: User;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
last_pin_timestamp?: number;
|
last_pin_timestamp?: number;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
default_auto_archive_duration?: number;
|
default_auto_archive_duration?: number;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
position: number;
|
position: number;
|
||||||
|
|
||||||
@Column("simple-json")
|
@Column({ type: "simple-json" })
|
||||||
permission_overwrites: ChannelPermissionOverwrite[];
|
permission_overwrites: ChannelPermissionOverwrite[];
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
video_quality_mode?: number;
|
video_quality_mode?: number;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
bitrate?: number;
|
bitrate?: number;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
user_limit?: number;
|
user_limit?: number;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
@ -87,7 +87,7 @@ export class Channel extends BaseClass {
|
|||||||
@Column()
|
@Column()
|
||||||
rate_limit_per_user: number;
|
rate_limit_per_user: number;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
topic?: string;
|
topic?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import { Snowflake } from "../util/Snowflake";
|
|||||||
|
|
||||||
@Entity("config")
|
@Entity("config")
|
||||||
export class ConfigEntity extends BaseClass {
|
export class ConfigEntity extends BaseClass {
|
||||||
@Column("simple-json")
|
@Column({ type: "simple-json" })
|
||||||
value: ConfigValue;
|
value: ConfigValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,21 +1,29 @@
|
|||||||
import { Column, Entity } from "typeorm";
|
import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
|
||||||
import { BaseClass } from "./BaseClass";
|
import { BaseClass } from "./BaseClass";
|
||||||
|
import { User } from "./User";
|
||||||
|
|
||||||
@Entity("connected_accounts")
|
@Entity("connected_accounts")
|
||||||
export class ConnectedAccount extends BaseClass {
|
export class ConnectedAccount extends BaseClass {
|
||||||
@Column()
|
@RelationId((account: ConnectedAccount) => account.user)
|
||||||
|
user_id: string;
|
||||||
|
|
||||||
|
@JoinColumn({ name: "user_id" })
|
||||||
|
@ManyToOne(() => User, (user: User) => user.connected_accounts)
|
||||||
|
user: User;
|
||||||
|
|
||||||
|
@Column({ select: false })
|
||||||
access_token: string;
|
access_token: string;
|
||||||
|
|
||||||
@Column()
|
@Column({ select: false })
|
||||||
friend_sync: boolean;
|
friend_sync: boolean;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
@Column()
|
@Column({ select: false })
|
||||||
revoked: boolean;
|
revoked: boolean;
|
||||||
|
|
||||||
@Column()
|
@Column({ select: false })
|
||||||
show_activity: boolean;
|
show_activity: boolean;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
@ -24,6 +32,6 @@ export class ConnectedAccount extends BaseClass {
|
|||||||
@Column()
|
@Column()
|
||||||
verifie: boolean;
|
verifie: boolean;
|
||||||
|
|
||||||
@Column()
|
@Column({ select: false })
|
||||||
visibility: number;
|
visibility: number;
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ export class Emoji extends BaseClass {
|
|||||||
animated: boolean;
|
animated: boolean;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
available: boolean;
|
available: boolean; // whether this emoji can be used, may be false due to loss of Server Boosts
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
guild_id: string;
|
guild_id: string;
|
||||||
@ -27,9 +27,6 @@ export class Emoji extends BaseClass {
|
|||||||
@Column()
|
@Column()
|
||||||
require_colons: boolean;
|
require_colons: boolean;
|
||||||
|
|
||||||
@Column()
|
|
||||||
url: string;
|
|
||||||
|
|
||||||
@RelationId((emoji: Emoji) => emoji.roles)
|
@RelationId((emoji: Emoji) => emoji.roles)
|
||||||
role_ids: string[];
|
role_ids: string[];
|
||||||
|
|
||||||
|
@ -17,51 +17,51 @@ export class Guild extends BaseClass {
|
|||||||
@ManyToOne(() => Channel, (channel: Channel) => channel.id)
|
@ManyToOne(() => Channel, (channel: Channel) => channel.id)
|
||||||
afk_channel?: Channel;
|
afk_channel?: Channel;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
afk_timeout?: number;
|
afk_timeout?: number;
|
||||||
|
|
||||||
// * commented out -> use owner instead
|
// * commented out -> use owner instead
|
||||||
// application id of the guild creator if it is bot-created
|
// application id of the guild creator if it is bot-created
|
||||||
// @Column()
|
// @Column({ nullable: true })
|
||||||
// application?: string;
|
// application?: string;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
banner?: string;
|
banner?: string;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
default_message_notifications?: number;
|
default_message_notifications?: number;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
description?: string;
|
description?: string;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
discovery_splash?: string;
|
discovery_splash?: string;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
explicit_content_filter?: number;
|
explicit_content_filter?: number;
|
||||||
|
|
||||||
@Column("simple-array")
|
@Column({ type: "simple-array" })
|
||||||
features: string[];
|
features: string[];
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
icon?: string;
|
icon?: string;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
large?: boolean;
|
large?: boolean;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
max_members?: number; // e.g. default 100.000
|
max_members?: number; // e.g. default 100.000
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
max_presences?: number;
|
max_presences?: number;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
max_video_channel_users?: number; // ? default: 25, is this max 25 streaming or watching
|
max_video_channel_users?: number; // ? default: 25, is this max 25 streaming or watching
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
member_count?: number;
|
member_count?: number;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
presence_count?: number; // users online
|
presence_count?: number; // users online
|
||||||
|
|
||||||
@RelationId((guild: Guild) => guild.members)
|
@RelationId((guild: Guild) => guild.members)
|
||||||
@ -99,7 +99,7 @@ export class Guild extends BaseClass {
|
|||||||
@ManyToMany(() => VoiceState, (voicestate: VoiceState) => voicestate.id)
|
@ManyToMany(() => VoiceState, (voicestate: VoiceState) => voicestate.id)
|
||||||
voice_states: VoiceState[];
|
voice_states: VoiceState[];
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
mfa_level?: number;
|
mfa_level?: number;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
@ -112,13 +112,13 @@ export class Guild extends BaseClass {
|
|||||||
@ManyToOne(() => User, (user: User) => user.id)
|
@ManyToOne(() => User, (user: User) => user.id)
|
||||||
owner: User;
|
owner: User;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
preferred_locale?: string; // only community guilds can choose this
|
preferred_locale?: string; // only community guilds can choose this
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
premium_subscription_count?: number;
|
premium_subscription_count?: number;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
premium_tier?: number; // nitro boost level
|
premium_tier?: number; // nitro boost level
|
||||||
|
|
||||||
@RelationId((guild: Guild) => guild.public_updates_channel)
|
@RelationId((guild: Guild) => guild.public_updates_channel)
|
||||||
@ -135,10 +135,10 @@ export class Guild extends BaseClass {
|
|||||||
@ManyToOne(() => Channel, (channel: Channel) => channel.id)
|
@ManyToOne(() => Channel, (channel: Channel) => channel.id)
|
||||||
rules_channel?: string;
|
rules_channel?: string;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
region?: string;
|
region?: string;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
splash?: string;
|
splash?: string;
|
||||||
|
|
||||||
@RelationId((guild: Guild) => guild.system_channel)
|
@RelationId((guild: Guild) => guild.system_channel)
|
||||||
@ -148,10 +148,10 @@ export class Guild extends BaseClass {
|
|||||||
@ManyToMany(() => Channel, (channel: Channel) => channel.id)
|
@ManyToMany(() => Channel, (channel: Channel) => channel.id)
|
||||||
system_channel?: Channel;
|
system_channel?: Channel;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
system_channel_flags?: number;
|
system_channel_flags?: number;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
unavailable?: boolean;
|
unavailable?: boolean;
|
||||||
|
|
||||||
@RelationId((guild: Guild) => guild.vanity_url)
|
@RelationId((guild: Guild) => guild.vanity_url)
|
||||||
@ -161,10 +161,10 @@ export class Guild extends BaseClass {
|
|||||||
@OneToOne(() => Invite, (invite: Invite) => invite.code)
|
@OneToOne(() => Invite, (invite: Invite) => invite.code)
|
||||||
vanity_url?: Invite;
|
vanity_url?: Invite;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
verification_level?: number;
|
verification_level?: number;
|
||||||
|
|
||||||
@Column("simple-json")
|
@Column({ type: "simple-json" })
|
||||||
welcome_screen: {
|
welcome_screen: {
|
||||||
enabled: boolean;
|
enabled: boolean;
|
||||||
description: string;
|
description: string;
|
||||||
@ -183,6 +183,6 @@ export class Guild extends BaseClass {
|
|||||||
@ManyToOne(() => Channel, (channel: Channel) => channel.id)
|
@ManyToOne(() => Channel, (channel: Channel) => channel.id)
|
||||||
widget_channel?: Channel;
|
widget_channel?: Channel;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
widget_enabled?: boolean;
|
widget_enabled?: boolean;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
|
import { Column, Entity, JoinColumn, ManyToOne, PrimaryColumn, RelationId } from "typeorm";
|
||||||
import { BaseClass } from "./BaseClass";
|
import { BaseClass } from "./BaseClass";
|
||||||
import { Channel } from "./Channel";
|
import { Channel } from "./Channel";
|
||||||
import { Guild } from "./Guild";
|
import { Guild } from "./Guild";
|
||||||
@ -6,7 +6,7 @@ import { User } from "./User";
|
|||||||
|
|
||||||
@Entity("invites")
|
@Entity("invites")
|
||||||
export class Invite extends BaseClass {
|
export class Invite extends BaseClass {
|
||||||
@Column()
|
@PrimaryColumn()
|
||||||
code: string;
|
code: string;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
@ -55,6 +55,6 @@ export class Invite extends BaseClass {
|
|||||||
@ManyToOne(() => User, (user: User) => user.id)
|
@ManyToOne(() => User, (user: User) => user.id)
|
||||||
target_user?: string; // could be used for "User specific invites" https://github.com/fosscord/fosscord/issues/62
|
target_user?: string; // could be used for "User specific invites" https://github.com/fosscord/fosscord/issues/62
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
target_user_type?: number;
|
target_user_type?: number;
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,17 @@
|
|||||||
import { PublicUser, User } from "./User";
|
import { PublicUser, User } from "./User";
|
||||||
import { BaseClass } from "./BaseClass";
|
import { BaseClass } from "./BaseClass";
|
||||||
import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
|
import { Column, Entity, JoinColumn, ManyToMany, ManyToOne, RelationId } from "typeorm";
|
||||||
import { Guild } from "./Guild";
|
import { Guild } from "./Guild";
|
||||||
|
import { Config, emitEvent } from "../util";
|
||||||
|
import {
|
||||||
|
GuildCreateEvent,
|
||||||
|
GuildDeleteEvent,
|
||||||
|
GuildMemberAddEvent,
|
||||||
|
GuildMemberRemoveEvent,
|
||||||
|
GuildMemberUpdateEvent,
|
||||||
|
} from "../interfaces";
|
||||||
|
import { HTTPError } from "lambert-server";
|
||||||
|
import { Role } from "./Role";
|
||||||
|
|
||||||
@Entity("members")
|
@Entity("members")
|
||||||
export class Member extends BaseClass {
|
export class Member extends BaseClass {
|
||||||
@ -19,16 +29,20 @@ export class Member extends BaseClass {
|
|||||||
@ManyToOne(() => Guild, (guild: Guild) => guild.id)
|
@ManyToOne(() => Guild, (guild: Guild) => guild.id)
|
||||||
guild: Guild;
|
guild: Guild;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
nick?: string;
|
nick?: string;
|
||||||
|
|
||||||
@Column("simple-array")
|
@RelationId((member: Member) => member.roles)
|
||||||
roles: string[];
|
role_ids: string[];
|
||||||
|
|
||||||
|
@JoinColumn({ name: "role_ids" })
|
||||||
|
@ManyToMany(() => Role)
|
||||||
|
roles: Role[];
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
joined_at: Date;
|
joined_at: Date;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
premium_since?: number;
|
premium_since?: number;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
@ -40,12 +54,180 @@ export class Member extends BaseClass {
|
|||||||
@Column()
|
@Column()
|
||||||
pending: boolean;
|
pending: boolean;
|
||||||
|
|
||||||
@Column("simple-json")
|
@Column({ type: "simple-json" })
|
||||||
settings: UserGuildSettings;
|
settings: UserGuildSettings;
|
||||||
|
|
||||||
// TODO: update
|
// TODO: update
|
||||||
@Column("simple-json")
|
@Column({ type: "simple-json" })
|
||||||
read_state: Record<string, string | null>;
|
read_state: Record<string, string | null>;
|
||||||
|
|
||||||
|
static async IsInGuildOrFail(user_id: string, guild_id: string) {
|
||||||
|
if (await Member.count({ id: user_id, guild_id })) return true;
|
||||||
|
throw new HTTPError("You are not member of this guild", 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async removeFromGuild(user_id: string, guild_id: string) {
|
||||||
|
const guild = await Guild.findOneOrFail({ select: ["owner_id"], where: { id: guild_id } });
|
||||||
|
if (guild.owner_id === user_id) throw new Error("The owner cannot be removed of the guild");
|
||||||
|
const member = await Member.findOneOrFail({ where: { id: user_id, guild_id }, relations: ["user"] });
|
||||||
|
|
||||||
|
// use promise all to execute all promises at the same time -> save time
|
||||||
|
return Promise.all([
|
||||||
|
Member.delete({
|
||||||
|
id: user_id,
|
||||||
|
guild_id: guild_id,
|
||||||
|
}),
|
||||||
|
Guild.decrement({ id: guild_id }, "member_count", -1),
|
||||||
|
|
||||||
|
emitEvent({
|
||||||
|
event: "GUILD_DELETE",
|
||||||
|
data: {
|
||||||
|
id: guild_id,
|
||||||
|
},
|
||||||
|
user_id: user_id,
|
||||||
|
} as GuildDeleteEvent),
|
||||||
|
emitEvent({
|
||||||
|
event: "GUILD_MEMBER_REMOVE",
|
||||||
|
data: {
|
||||||
|
guild_id: guild_id,
|
||||||
|
user: member.user,
|
||||||
|
},
|
||||||
|
guild_id: guild_id,
|
||||||
|
} as GuildMemberRemoveEvent),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async addRole(user_id: string, guild_id: string, role_id: string) {
|
||||||
|
const [member] = await Promise.all([
|
||||||
|
Member.findOneOrFail({
|
||||||
|
where: { id: user_id, guild_id: guild_id },
|
||||||
|
relations: ["user"], // we don't want to load the role objects just the ids
|
||||||
|
}),
|
||||||
|
await Role.findOneOrFail({ id: role_id, guild_id: guild_id }),
|
||||||
|
]);
|
||||||
|
member.role_ids.push(role_id);
|
||||||
|
member.save();
|
||||||
|
|
||||||
|
await emitEvent({
|
||||||
|
event: "GUILD_MEMBER_UPDATE",
|
||||||
|
data: {
|
||||||
|
guild_id: guild_id,
|
||||||
|
user: member.user,
|
||||||
|
roles: member.role_ids,
|
||||||
|
},
|
||||||
|
guild_id: guild_id,
|
||||||
|
} as GuildMemberUpdateEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async removeRole(user_id: string, guild_id: string, role_id: string) {
|
||||||
|
const [member] = await Promise.all([
|
||||||
|
Member.findOneOrFail({
|
||||||
|
where: { id: user_id, guild_id: guild_id },
|
||||||
|
relations: ["user"], // we don't want to load the role objects just the ids
|
||||||
|
}),
|
||||||
|
await Role.findOneOrFail({ id: role_id, guild_id: guild_id }),
|
||||||
|
]);
|
||||||
|
member.role_ids.remove(role_id);
|
||||||
|
member.save();
|
||||||
|
|
||||||
|
await emitEvent({
|
||||||
|
event: "GUILD_MEMBER_UPDATE",
|
||||||
|
data: {
|
||||||
|
guild_id: guild_id,
|
||||||
|
user: member.user,
|
||||||
|
roles: member.role_ids,
|
||||||
|
},
|
||||||
|
guild_id: guild_id,
|
||||||
|
} as GuildMemberUpdateEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async changeNickname(user_id: string, guild_id: string, nickname: string) {
|
||||||
|
const member = await Member.findOneOrFail({
|
||||||
|
where: {
|
||||||
|
id: user_id,
|
||||||
|
guild_id: guild_id,
|
||||||
|
},
|
||||||
|
relations: ["user"],
|
||||||
|
});
|
||||||
|
member.nick = nickname;
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
member.save(),
|
||||||
|
|
||||||
|
emitEvent({
|
||||||
|
event: "GUILD_MEMBER_UPDATE",
|
||||||
|
data: {
|
||||||
|
guild_id: guild_id,
|
||||||
|
user: member.user,
|
||||||
|
nick: nickname,
|
||||||
|
},
|
||||||
|
guild_id: guild_id,
|
||||||
|
} as GuildMemberUpdateEvent),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async addToGuild(user_id: string, guild_id: string) {
|
||||||
|
const user = await User.getPublicUser(user_id);
|
||||||
|
|
||||||
|
const { maxGuilds } = Config.get().limits.user;
|
||||||
|
const guild_count = await Member.count({ id: user_id });
|
||||||
|
if (guild_count >= maxGuilds) {
|
||||||
|
throw new HTTPError(`You are at the ${maxGuilds} server limit.`, 403);
|
||||||
|
}
|
||||||
|
|
||||||
|
const guild = await Guild.findOneOrFail(guild_id, {
|
||||||
|
relations: ["channels", "emojis", "members", "roles", "stickers"],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (await Member.count({ id: user.id, guild_id }))
|
||||||
|
throw new HTTPError("You are already a member of this guild", 400);
|
||||||
|
|
||||||
|
const member = {
|
||||||
|
id: user_id,
|
||||||
|
guild_id: guild_id,
|
||||||
|
nick: undefined,
|
||||||
|
roles: [guild_id], // @everyone role
|
||||||
|
joined_at: new Date(),
|
||||||
|
premium_since: undefined,
|
||||||
|
deaf: false,
|
||||||
|
mute: false,
|
||||||
|
pending: false,
|
||||||
|
};
|
||||||
|
// @ts-ignore
|
||||||
|
guild.joined_at = member.joined_at;
|
||||||
|
|
||||||
|
await Promise.all([
|
||||||
|
new Member({
|
||||||
|
...member,
|
||||||
|
read_state: {},
|
||||||
|
settings: {
|
||||||
|
channel_overrides: [],
|
||||||
|
message_notifications: 0,
|
||||||
|
mobile_push: true,
|
||||||
|
mute_config: null,
|
||||||
|
muted: false,
|
||||||
|
suppress_everyone: false,
|
||||||
|
suppress_roles: false,
|
||||||
|
version: 0,
|
||||||
|
},
|
||||||
|
}).save(),
|
||||||
|
Guild.increment({ id: guild_id }, "member_count", 1),
|
||||||
|
emitEvent({
|
||||||
|
event: "GUILD_MEMBER_ADD",
|
||||||
|
data: {
|
||||||
|
...member,
|
||||||
|
user,
|
||||||
|
guild_id: guild_id,
|
||||||
|
},
|
||||||
|
guild_id: guild_id,
|
||||||
|
} as GuildMemberAddEvent),
|
||||||
|
emitEvent({
|
||||||
|
event: "GUILD_CREATE",
|
||||||
|
data: guild,
|
||||||
|
user_id,
|
||||||
|
} as GuildCreateEvent),
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface UserGuildSettings {
|
export interface UserGuildSettings {
|
||||||
@ -69,19 +251,31 @@ export interface MuteConfig {
|
|||||||
selected_time_window: number;
|
selected_time_window: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
export type PublicMemberKeys =
|
||||||
export interface PublicMember extends Omit<Member, "settings" | "id" | "read_state"> {
|
| "id"
|
||||||
user: PublicUser;
|
| "guild_id"
|
||||||
}
|
| "nick"
|
||||||
|
| "roles"
|
||||||
|
| "joined_at"
|
||||||
|
| "pending"
|
||||||
|
| "deaf"
|
||||||
|
| "mute"
|
||||||
|
| "premium_since";
|
||||||
|
|
||||||
export const PublicMemberProjection = {
|
export const PublicMemberProjection: PublicMemberKeys[] = [
|
||||||
id: true,
|
"id",
|
||||||
guild_id: true,
|
"guild_id",
|
||||||
nick: true,
|
"nick",
|
||||||
roles: true,
|
"roles",
|
||||||
joined_at: true,
|
"joined_at",
|
||||||
pending: true,
|
"pending",
|
||||||
deaf: true,
|
"deaf",
|
||||||
mute: true,
|
"mute",
|
||||||
premium_since: true,
|
"premium_since",
|
||||||
|
];
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
|
export type PublicMember = Pick<Member, Omit<PublicMemberKeys, "roles">> & {
|
||||||
|
user: PublicUser;
|
||||||
|
roles: string[]; // only role ids not objects
|
||||||
};
|
};
|
||||||
|
@ -17,6 +17,7 @@ import {
|
|||||||
import { BaseClass } from "./BaseClass";
|
import { BaseClass } from "./BaseClass";
|
||||||
import { Guild } from "./Guild";
|
import { Guild } from "./Guild";
|
||||||
import { Webhook } from "./Webhook";
|
import { Webhook } from "./Webhook";
|
||||||
|
import { Sticker } from "./Sticker";
|
||||||
|
|
||||||
export enum MessageType {
|
export enum MessageType {
|
||||||
DEFAULT = 0,
|
DEFAULT = 0,
|
||||||
@ -51,7 +52,7 @@ export class Message extends BaseClass {
|
|||||||
channel: Channel;
|
channel: Channel;
|
||||||
|
|
||||||
@RelationId((message: Message) => message.guild)
|
@RelationId((message: Message) => message.guild)
|
||||||
guild_id: string;
|
guild_id?: string;
|
||||||
|
|
||||||
@JoinColumn({ name: "guild_id" })
|
@JoinColumn({ name: "guild_id" })
|
||||||
@ManyToOne(() => Guild, (guild: Guild) => guild.id)
|
@ManyToOne(() => Guild, (guild: Guild) => guild.id)
|
||||||
@ -85,7 +86,7 @@ export class Message extends BaseClass {
|
|||||||
@ManyToOne(() => Application, (application: Application) => application.id)
|
@ManyToOne(() => Application, (application: Application) => application.id)
|
||||||
application?: Application;
|
application?: Application;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
content?: string;
|
content?: string;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
@ -96,18 +97,18 @@ export class Message extends BaseClass {
|
|||||||
@UpdateDateColumn()
|
@UpdateDateColumn()
|
||||||
edited_timestamp?: Date;
|
edited_timestamp?: Date;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
tts?: boolean;
|
tts?: boolean;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
mention_everyone?: boolean;
|
mention_everyone?: boolean;
|
||||||
|
|
||||||
@RelationId((message: Message) => message.mention_users)
|
@RelationId((message: Message) => message.mentions)
|
||||||
mention_user_ids: string[];
|
mention_user_ids: string[];
|
||||||
|
|
||||||
@JoinColumn({ name: "mention_user_ids" })
|
@JoinColumn({ name: "mention_user_ids" })
|
||||||
@ManyToMany(() => User, (user: User) => user.id)
|
@ManyToMany(() => User, (user: User) => user.id)
|
||||||
mention_users: User[];
|
mentions: User[];
|
||||||
|
|
||||||
@RelationId((message: Message) => message.mention_roles)
|
@RelationId((message: Message) => message.mention_roles)
|
||||||
mention_role_ids: string[];
|
mention_role_ids: string[];
|
||||||
@ -123,44 +124,52 @@ export class Message extends BaseClass {
|
|||||||
@ManyToMany(() => Channel, (channel: Channel) => channel.id)
|
@ManyToMany(() => Channel, (channel: Channel) => channel.id)
|
||||||
mention_channels: Channel[];
|
mention_channels: Channel[];
|
||||||
|
|
||||||
@Column("simple-json")
|
@Column({ type: "simple-json" })
|
||||||
attachments: Attachment[];
|
attachments: Attachment[];
|
||||||
|
|
||||||
@Column("simple-json")
|
@Column({ type: "simple-json" })
|
||||||
embeds: Embed[];
|
embeds: Embed[];
|
||||||
|
|
||||||
@Column("simple-json")
|
@Column({ type: "simple-json" })
|
||||||
reactions: Reaction[];
|
reactions: Reaction[];
|
||||||
|
|
||||||
@Column({ type: "text" })
|
@Column({ type: "text", nullable: true })
|
||||||
nonce?: string | number;
|
nonce?: string | number;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
pinned?: boolean;
|
pinned?: boolean;
|
||||||
|
|
||||||
@Column({ type: "simple-enum", enum: MessageType })
|
@Column({ type: "simple-enum", enum: MessageType })
|
||||||
type: MessageType;
|
type: MessageType;
|
||||||
|
|
||||||
@Column("simple-json")
|
@Column({ type: "simple-json", nullable: true })
|
||||||
activity?: {
|
activity?: {
|
||||||
type: number;
|
type: number;
|
||||||
party_id: string;
|
party_id: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@Column({ type: "bigint" })
|
@Column({ type: "bigint", nullable: true })
|
||||||
flags?: bigint;
|
flags?: bigint;
|
||||||
|
|
||||||
@Column("simple-json")
|
@RelationId((message: Message) => message.stickers)
|
||||||
stickers?: any[];
|
sticker_ids: string[];
|
||||||
|
|
||||||
@Column("simple-json")
|
@JoinColumn({ name: "sticker_ids" })
|
||||||
|
@ManyToMany(() => Sticker, (sticker: Sticker) => sticker.id)
|
||||||
|
stickers?: Sticker[];
|
||||||
|
|
||||||
|
@Column({ type: "simple-json", nullable: true })
|
||||||
message_reference?: {
|
message_reference?: {
|
||||||
message_id: string;
|
message_id: string;
|
||||||
channel_id?: string;
|
channel_id?: string;
|
||||||
guild_id?: string;
|
guild_id?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
@Column("simple-json")
|
@JoinColumn({ name: "message_reference_id" })
|
||||||
|
@ManyToOne(() => Message, (message: Message) => message.id)
|
||||||
|
referenced_message?: Message;
|
||||||
|
|
||||||
|
@Column({ type: "simple-json", nullable: true })
|
||||||
interaction?: {
|
interaction?: {
|
||||||
id: string;
|
id: string;
|
||||||
type: InteractionType;
|
type: InteractionType;
|
||||||
@ -169,7 +178,7 @@ export class Message extends BaseClass {
|
|||||||
// user: User; // TODO: autopopulate user
|
// user: User; // TODO: autopopulate user
|
||||||
};
|
};
|
||||||
|
|
||||||
@Column("simple-json")
|
@Column({ type: "simple-json" })
|
||||||
components: MessageComponent[];
|
components: MessageComponent[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ export class ReadState extends BaseClass {
|
|||||||
@ManyToOne(() => Message, (message: Message) => message.id)
|
@ManyToOne(() => Message, (message: Message) => message.id)
|
||||||
last_message?: Message;
|
last_message?: Message;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
last_pin_timestamp?: Date;
|
last_pin_timestamp?: Date;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm";
|
import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm";
|
||||||
import { BaseClass } from "./BaseClass";
|
import { BaseClass } from "./BaseClass";
|
||||||
import { User } from "./User";
|
import { User } from "./User";
|
||||||
|
|
||||||
@ -15,10 +15,10 @@ export class Relationship extends BaseClass {
|
|||||||
user_id: string;
|
user_id: string;
|
||||||
|
|
||||||
@JoinColumn({ name: "user_id" })
|
@JoinColumn({ name: "user_id" })
|
||||||
@ManyToOne(() => User, (user: User) => user.id)
|
@ManyToOne(() => User, (user: User) => user.relationships)
|
||||||
user: User;
|
user: User;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
nickname?: string;
|
nickname?: string;
|
||||||
|
|
||||||
@Column({ type: "simple-enum", enum: RelationshipType })
|
@Column({ type: "simple-enum", enum: RelationshipType })
|
||||||
|
@ -32,7 +32,7 @@ export class Role extends BaseClass {
|
|||||||
@Column()
|
@Column()
|
||||||
position: number;
|
position: number;
|
||||||
|
|
||||||
@Column({ type: "simple-json" })
|
@Column({ type: "simple-json", nullable: true })
|
||||||
tags?: {
|
tags?: {
|
||||||
bot_id?: string;
|
bot_id?: string;
|
||||||
integration_id?: string;
|
integration_id?: string;
|
||||||
|
42
util/src/entities/Sticker.ts
Normal file
42
util/src/entities/Sticker.ts
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { Column, Entity, JoinColumn, ManyToOne } from "typeorm";
|
||||||
|
import { BaseClass } from "./BaseClass";
|
||||||
|
import { Guild } from "./Guild";
|
||||||
|
|
||||||
|
export enum StickerType {
|
||||||
|
STANDARD = 1,
|
||||||
|
GUILD = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum StickerFormatType {
|
||||||
|
PNG = 1,
|
||||||
|
APNG = 2,
|
||||||
|
LOTTIE = 3,
|
||||||
|
}
|
||||||
|
|
||||||
|
@Entity("stickers")
|
||||||
|
export class Sticker extends BaseClass {
|
||||||
|
@Column()
|
||||||
|
name: string;
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
description?: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
tags: string;
|
||||||
|
|
||||||
|
@Column()
|
||||||
|
pack_id: string;
|
||||||
|
|
||||||
|
@Column({ nullable: true })
|
||||||
|
guild_id?: string;
|
||||||
|
|
||||||
|
@JoinColumn({ name: "guild_id" })
|
||||||
|
@ManyToOne(() => Guild, (guild: Guild) => guild.id)
|
||||||
|
guild?: Guild;
|
||||||
|
|
||||||
|
@Column({ type: "simple-enum", enum: StickerType })
|
||||||
|
type: StickerType;
|
||||||
|
|
||||||
|
@Column({ type: "simple-enum", enum: StickerFormatType })
|
||||||
|
format_type: StickerFormatType;
|
||||||
|
}
|
@ -5,7 +5,7 @@ import { User } from "./User";
|
|||||||
|
|
||||||
@Entity("teams")
|
@Entity("teams")
|
||||||
export class Team extends BaseClass {
|
export class Team extends BaseClass {
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
icon?: string;
|
icon?: string;
|
||||||
|
|
||||||
@RelationId((team: Team) => team.members)
|
@RelationId((team: Team) => team.members)
|
||||||
|
@ -12,7 +12,7 @@ export class TeamMember extends BaseClass {
|
|||||||
@Column({ type: "simple-enum", enum: TeamMemberState })
|
@Column({ type: "simple-enum", enum: TeamMemberState })
|
||||||
membership_state: TeamMemberState;
|
membership_state: TeamMemberState;
|
||||||
|
|
||||||
@Column("simple-array")
|
@Column({ type: "simple-array" })
|
||||||
permissions: string[];
|
permissions: string[];
|
||||||
|
|
||||||
@RelationId((member: TeamMember) => member.team)
|
@RelationId((member: TeamMember) => member.team)
|
||||||
|
@ -11,10 +11,10 @@ export class Template extends BaseClass {
|
|||||||
@Column()
|
@Column()
|
||||||
name: string;
|
name: string;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
description?: string;
|
description?: string;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
usage_count?: number;
|
usage_count?: number;
|
||||||
|
|
||||||
@RelationId((template: Template) => template.creator)
|
@RelationId((template: Template) => template.creator)
|
||||||
@ -37,6 +37,6 @@ export class Template extends BaseClass {
|
|||||||
@ManyToOne(() => Guild, (guild: Guild) => guild.id)
|
@ManyToOne(() => Guild, (guild: Guild) => guild.id)
|
||||||
source_guild: Guild;
|
source_guild: Guild;
|
||||||
|
|
||||||
@Column("simple-json")
|
@Column({ type: "simple-json" })
|
||||||
serialized_source_guild: Guild;
|
serialized_source_guild: Guild;
|
||||||
}
|
}
|
||||||
|
@ -1,22 +1,34 @@
|
|||||||
import { Column, Entity, JoinColumn, OneToMany, RelationId } from "typeorm";
|
import { Column, Entity, FindOneOptions, JoinColumn, OneToMany, RelationId } from "typeorm";
|
||||||
import { BaseClass } from "./BaseClass";
|
import { BaseClass } from "./BaseClass";
|
||||||
import { BitField } from "../util/BitField";
|
import { BitField } from "../util/BitField";
|
||||||
import { Relationship } from "./Relationship";
|
import { Relationship } from "./Relationship";
|
||||||
import { ConnectedAccount } from "./ConnectedAccount";
|
import { ConnectedAccount } from "./ConnectedAccount";
|
||||||
import { HTTPError } from "lambert-server";
|
import { HTTPError } from "lambert-server";
|
||||||
import { Guild } from "./Guild";
|
|
||||||
|
|
||||||
export const PublicUserProjection = {
|
type PublicUserKeys =
|
||||||
username: true,
|
| "username"
|
||||||
discriminator: true,
|
| "discriminator"
|
||||||
id: true,
|
| "id"
|
||||||
public_flags: true,
|
| "public_flags"
|
||||||
avatar: true,
|
| "avatar"
|
||||||
accent_color: true,
|
| "accent_color"
|
||||||
banner: true,
|
| "banner"
|
||||||
bio: true,
|
| "bio"
|
||||||
bot: true,
|
| "bot";
|
||||||
};
|
export const PublicUserProjection: PublicUserKeys[] = [
|
||||||
|
"username",
|
||||||
|
"discriminator",
|
||||||
|
"id",
|
||||||
|
"public_flags",
|
||||||
|
"avatar",
|
||||||
|
"accent_color",
|
||||||
|
"banner",
|
||||||
|
"bio",
|
||||||
|
"bot",
|
||||||
|
];
|
||||||
|
|
||||||
|
// Private user data that should never get sent to the client
|
||||||
|
export type PublicUser = Pick<User, PublicUserKeys>;
|
||||||
|
|
||||||
@Entity("users")
|
@Entity("users")
|
||||||
export class User extends BaseClass {
|
export class User extends BaseClass {
|
||||||
@ -30,115 +42,145 @@ export class User extends BaseClass {
|
|||||||
const number = Number(val);
|
const number = Number(val);
|
||||||
if (isNaN(number)) throw new Error("invalid discriminator");
|
if (isNaN(number)) throw new Error("invalid discriminator");
|
||||||
if (number <= 0 || number > 10000) throw new Error("discriminator must be between 1 and 9999");
|
if (number <= 0 || number > 10000) throw new Error("discriminator must be between 1 and 9999");
|
||||||
this.discriminator = val.toString();
|
this.discriminator = val.toString().padStart(4, "0");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
avatar?: string; // hash of the user avatar
|
avatar?: string; // hash of the user avatar
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
accent_color?: number; // banner color of user
|
accent_color?: number = 0; // banner color of user
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
banner?: string; // hash of the user banner
|
banner?: string; // hash of the user banner
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
phone?: string; // phone number of the user
|
phone?: string; // phone number of the user
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
desktop: boolean; // if the user has desktop app installed
|
desktop: boolean = false; // if the user has desktop app installed
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
mobile: boolean; // if the user has mobile app installed
|
mobile: boolean = false; // if the user has mobile app installed
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
premium: boolean; // if user bought nitro
|
premium: boolean = false; // if user bought nitro
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
premium_type: number; // nitro level
|
premium_type: number = 0; // nitro level
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
bot: boolean; // if user is bot
|
bot: boolean = false; // if user is bot
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
bio: string; // short description of the user (max 190 chars -> should be configurable)
|
bio: string = ""; // short description of the user (max 190 chars -> should be configurable)
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
system: boolean; // shouldn't be used, the api sents this field type true, if the generated message comes from a system generated author
|
system: boolean = false; // shouldn't be used, the api sents this field type true, if the generated message comes from a system generated author
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
nsfw_allowed: boolean; // if the user is older than 18 (resp. Config)
|
nsfw_allowed: boolean = false; // if the user is older than 18 (resp. Config)
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
mfa_enabled: boolean; // if multi factor authentication is enabled
|
mfa_enabled: boolean = false; // if multi factor authentication is enabled
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
created_at: Date; // registration date
|
created_at: Date = new Date(); // registration date
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
verified: boolean; // if the user is offically verified
|
verified: boolean = false; // if the user is offically verified
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
disabled: boolean; // if the account is disabled
|
disabled: boolean = false; // if the account is disabled
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
deleted: boolean; // if the user was deleted
|
deleted: boolean = false; // if the user was deleted
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
email?: string; // email of the user
|
email?: string; // email of the user
|
||||||
|
|
||||||
@Column({ type: "bigint" })
|
@Column({ type: "bigint" })
|
||||||
flags: bigint; // UserFlags
|
flags: bigint = BigInt(0); // UserFlags
|
||||||
|
|
||||||
@Column({ type: "bigint" })
|
@Column({ type: "bigint" })
|
||||||
public_flags: bigint;
|
public_flags: bigint = BigInt(0);
|
||||||
|
|
||||||
@RelationId((user: User) => user.guilds)
|
|
||||||
guild_ids: string[]; // array of guild ids the user is part of
|
|
||||||
|
|
||||||
@JoinColumn({ name: "guild_ids" })
|
|
||||||
@OneToMany(() => Guild, (guild: Guild) => guild.id)
|
|
||||||
guilds: Guild[];
|
|
||||||
|
|
||||||
@RelationId((user: User) => user.relationships)
|
@RelationId((user: User) => user.relationships)
|
||||||
relationship_ids: string[]; // array of guild ids the user is part of
|
relationship_ids: string[]; // array of guild ids the user is part of
|
||||||
|
|
||||||
@JoinColumn({ name: "relationship_ids" })
|
@JoinColumn({ name: "relationship_ids" })
|
||||||
@OneToMany(() => User, (user: User) => user.id)
|
@OneToMany(() => Relationship, (relationship: Relationship) => relationship.user, { cascade: true })
|
||||||
relationships: Relationship[];
|
relationships: Relationship[];
|
||||||
|
|
||||||
@RelationId((user: User) => user.connected_accounts)
|
@RelationId((user: User) => user.connected_accounts)
|
||||||
connected_account_ids: string[]; // array of guild ids the user is part of
|
connected_account_ids: string[]; // array of guild ids the user is part of
|
||||||
|
|
||||||
@JoinColumn({ name: "connected_account_ids" })
|
@JoinColumn({ name: "connected_account_ids" })
|
||||||
@OneToMany(() => ConnectedAccount, (account: ConnectedAccount) => account.id)
|
@OneToMany(() => ConnectedAccount, (account: ConnectedAccount) => account.user)
|
||||||
connected_accounts: ConnectedAccount[];
|
connected_accounts: ConnectedAccount[];
|
||||||
|
|
||||||
@Column({ type: "simple-json", select: false })
|
@Column({ type: "simple-json", select: false })
|
||||||
data: {
|
data: {
|
||||||
valid_tokens_since: Date; // all tokens with a previous issue date are invalid
|
valid_tokens_since: Date; // all tokens with a previous issue date are invalid
|
||||||
hash: string; // hash of the password, salt is saved in password (bcrypt)
|
hash?: string; // hash of the password, salt is saved in password (bcrypt)
|
||||||
};
|
} = { valid_tokens_since: new Date() };
|
||||||
|
|
||||||
@Column({ type: "simple-array" })
|
@Column({ type: "simple-array" })
|
||||||
fingerprints: string[]; // array of fingerprints -> used to prevent multiple accounts
|
fingerprints: string[] = []; // array of fingerprints -> used to prevent multiple accounts
|
||||||
|
|
||||||
@Column("simple-json")
|
@Column({ type: "simple-json" })
|
||||||
settings: UserSettings;
|
settings: UserSettings = defaultSettings;
|
||||||
|
|
||||||
static async getPublicUser(user_id: string, additional_fields?: any) {
|
static async getPublicUser(user_id: string, opts?: FindOneOptions<User>) {
|
||||||
const user = await User.findOne(
|
const user = await User.findOne(user_id, {
|
||||||
{ id: user_id },
|
...opts,
|
||||||
{
|
select: [...PublicUserProjection, ...(opts?.select || [])],
|
||||||
...PublicUserProjection,
|
});
|
||||||
...additional_fields,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (!user) throw new HTTPError("User not found", 404);
|
if (!user) throw new HTTPError("User not found", 404);
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const defaultSettings: UserSettings = {
|
||||||
|
afk_timeout: 300,
|
||||||
|
allow_accessibility_detection: true,
|
||||||
|
animate_emoji: true,
|
||||||
|
animate_stickers: 0,
|
||||||
|
contact_sync_enabled: false,
|
||||||
|
convert_emoticons: false,
|
||||||
|
custom_status: {
|
||||||
|
emoji_id: undefined,
|
||||||
|
emoji_name: undefined,
|
||||||
|
expires_at: undefined,
|
||||||
|
text: undefined,
|
||||||
|
},
|
||||||
|
default_guilds_restricted: false,
|
||||||
|
detect_platform_accounts: true,
|
||||||
|
developer_mode: false,
|
||||||
|
disable_games_tab: false,
|
||||||
|
enable_tts_command: true,
|
||||||
|
explicit_content_filter: 0,
|
||||||
|
friend_source_flags: { all: true },
|
||||||
|
gateway_connected: false,
|
||||||
|
gif_auto_play: true,
|
||||||
|
guild_folders: [],
|
||||||
|
guild_positions: [],
|
||||||
|
inline_attachment_media: true,
|
||||||
|
inline_embed_media: true,
|
||||||
|
locale: "en",
|
||||||
|
message_display_compact: false,
|
||||||
|
native_phone_integration_enabled: true,
|
||||||
|
render_embeds: true,
|
||||||
|
render_reactions: true,
|
||||||
|
restricted_guilds: [],
|
||||||
|
show_current_game: true,
|
||||||
|
status: "offline",
|
||||||
|
stream_notifications_enabled: true,
|
||||||
|
theme: "dark",
|
||||||
|
timezone_offset: 0,
|
||||||
|
// timezone_offset: // TODO: timezone from request
|
||||||
|
};
|
||||||
|
|
||||||
export interface UserSettings {
|
export interface UserSettings {
|
||||||
afk_timeout: number;
|
afk_timeout: number;
|
||||||
allow_accessibility_detection: boolean;
|
allow_accessibility_detection: boolean;
|
||||||
@ -184,18 +226,6 @@ export interface UserSettings {
|
|||||||
timezone_offset: number; // e.g -60
|
timezone_offset: number; // e.g -60
|
||||||
}
|
}
|
||||||
|
|
||||||
// Private user data that should never get sent to the client
|
|
||||||
export interface PublicUser {
|
|
||||||
id: string;
|
|
||||||
discriminator: string;
|
|
||||||
username: string;
|
|
||||||
avatar?: string;
|
|
||||||
accent_color?: number;
|
|
||||||
banner?: string;
|
|
||||||
public_flags: bigint;
|
|
||||||
bot: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class UserFlags extends BitField {
|
export class UserFlags extends BitField {
|
||||||
static FLAGS = {
|
static FLAGS = {
|
||||||
DISCORD_EMPLOYEE: BigInt(1) << BigInt(0),
|
DISCORD_EMPLOYEE: BigInt(1) << BigInt(0),
|
||||||
|
@ -42,7 +42,7 @@ export class VoiceState extends BaseClass {
|
|||||||
@Column()
|
@Column()
|
||||||
self_mute: boolean;
|
self_mute: boolean;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
self_stream?: boolean;
|
self_stream?: boolean;
|
||||||
|
|
||||||
@Column()
|
@Column()
|
||||||
|
@ -18,13 +18,13 @@ export class Webhook extends BaseClass {
|
|||||||
@Column({ type: "simple-enum", enum: WebhookType })
|
@Column({ type: "simple-enum", enum: WebhookType })
|
||||||
type: WebhookType;
|
type: WebhookType;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
name?: string;
|
name?: string;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
avatar?: string;
|
avatar?: string;
|
||||||
|
|
||||||
@Column()
|
@Column({ nullable: true })
|
||||||
token?: string;
|
token?: string;
|
||||||
|
|
||||||
@RelationId((webhook: Webhook) => webhook.guild)
|
@RelationId((webhook: Webhook) => webhook.guild)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -259,22 +259,14 @@ export interface InviteDeleteEvent extends Event {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MessagePayload = Omit<Message, "author_id"> & {
|
|
||||||
channel_id: string;
|
|
||||||
guild_id?: string;
|
|
||||||
author: PublicUser;
|
|
||||||
member: PublicMember;
|
|
||||||
mentions: (PublicUser & { member: PublicMember })[];
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface MessageCreateEvent extends Event {
|
export interface MessageCreateEvent extends Event {
|
||||||
event: "MESSAGE_CREATE";
|
event: "MESSAGE_CREATE";
|
||||||
data: MessagePayload;
|
data: Message;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MessageUpdateEvent extends Event {
|
export interface MessageUpdateEvent extends Event {
|
||||||
event: "MESSAGE_UPDATE";
|
event: "MESSAGE_UPDATE";
|
||||||
data: MessagePayload;
|
data: Message;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface MessageDeleteEvent extends Event {
|
export interface MessageDeleteEvent extends Event {
|
||||||
|
19
util/src/tes.ts
Normal file
19
util/src/tes.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { performance } from "perf_hooks";
|
||||||
|
import { Guild, Relationship, RelationshipType } from "./entities";
|
||||||
|
import { User } from "./entities/User";
|
||||||
|
import { initDatabase } from "./util";
|
||||||
|
|
||||||
|
initDatabase().then(async (x) => {
|
||||||
|
try {
|
||||||
|
const user = await new User(
|
||||||
|
{ guilds: [], discriminator: "1", username: "test", flags: "0", public_flags: "0" },
|
||||||
|
{ id: "0" }
|
||||||
|
).save();
|
||||||
|
|
||||||
|
user.relationships = [new Relationship({ type: RelationshipType.friends })];
|
||||||
|
|
||||||
|
user.save();
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
});
|
@ -40,6 +40,7 @@ export function enableAutoUpdate(opts: {
|
|||||||
console.log(`[Auto update] updating ...`);
|
console.log(`[Auto update] updating ...`);
|
||||||
download(opts.downloadUrl, opts.path);
|
download(opts.downloadUrl, opts.path);
|
||||||
} else {
|
} else {
|
||||||
|
console.log(`[Auto update] aborted`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -14,11 +14,17 @@ export function initDatabase() {
|
|||||||
console.log("[Database] connecting ...");
|
console.log("[Database] connecting ...");
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
promise = createConnection({
|
promise = createConnection({
|
||||||
type: "sqlite",
|
// type: "sqlite",
|
||||||
database: "database.db",
|
// database: "database.db",
|
||||||
|
type: "postgres",
|
||||||
|
url: "postgres://fosscord:wb94SmuURM2Syv&@localhost/fosscord",
|
||||||
|
//
|
||||||
entities: Object.values(Models).filter((x) => x.constructor.name !== "Object"),
|
entities: Object.values(Models).filter((x) => x.constructor.name !== "Object"),
|
||||||
synchronize: true,
|
synchronize: true,
|
||||||
logging: false,
|
logging: true,
|
||||||
|
cache: {
|
||||||
|
duration: 1000 * 3, // cache all find queries for 3 seconds
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
promise.then((connection) => {
|
promise.then((connection) => {
|
||||||
|
@ -198,50 +198,41 @@ export class Permissions extends BitField {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export type PermissionCache = {
|
export type PermissionCache = {
|
||||||
channel?: Channel | null;
|
channel?: Channel | undefined;
|
||||||
member?: Member | null;
|
member?: Member | undefined;
|
||||||
guild?: Guild | null;
|
guild?: Guild | undefined;
|
||||||
roles?: Role[] | null;
|
roles?: Role[] | undefined;
|
||||||
user_id?: string;
|
user_id?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function getPermission(
|
export async function getPermission(user_id?: string, guild_id?: string, channel_id?: string) {
|
||||||
user_id?: string,
|
|
||||||
guild_id?: string,
|
|
||||||
channel_id?: string,
|
|
||||||
cache: PermissionCache = {}
|
|
||||||
) {
|
|
||||||
var { channel, member, guild, roles } = cache;
|
|
||||||
|
|
||||||
if (!user_id) throw new HTTPError("User not found");
|
if (!user_id) throw new HTTPError("User not found");
|
||||||
|
var channel: Channel | undefined;
|
||||||
|
var member: Member | undefined;
|
||||||
|
var guild: Guild | undefined;
|
||||||
|
|
||||||
if (channel_id && !channel) {
|
if (channel_id) {
|
||||||
channel = await Channel.findOneOrFail(
|
channel = await Channel.findOneOrFail(
|
||||||
{ id: channel_id },
|
{ id: channel_id },
|
||||||
{ select: ["permission_overwrites", "recipients", "owner", "guild"] }
|
{ select: ["permission_overwrites", "recipients", "owner", "guild"] }
|
||||||
);
|
);
|
||||||
if (!channel) throw new HTTPError("Channel not found", 404);
|
if (channel.guild_id) guild_id = channel.guild_id; // derive guild_id from the channel
|
||||||
if (channel.guild_id) guild_id = channel.guild_id;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (guild_id) {
|
if (guild_id) {
|
||||||
if (!guild) guild = await Guild.findOneOrFail({ id: guild_id }, { select: ["owner"] });
|
guild = await Guild.findOneOrFail({ id: guild_id }, { select: ["owner"] });
|
||||||
if (!guild) throw new HTTPError("Guild not found");
|
|
||||||
if (guild.owner_id === user_id) return new Permissions(Permissions.FLAGS.ADMINISTRATOR);
|
if (guild.owner_id === user_id) return new Permissions(Permissions.FLAGS.ADMINISTRATOR);
|
||||||
|
|
||||||
if (!member) member = await Member.findOneOrFail({ guild_id, id: user_id }, { select: ["roles"] });
|
member = await Member.findOneOrFail({ guild_id, id: user_id }, { select: ["roles"] });
|
||||||
if (!member) throw new HTTPError("Member not found");
|
|
||||||
|
|
||||||
if (!roles) roles = await Role.find({ guild_id, id: In(member.roles) });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var permission = Permissions.finalPermission({
|
var permission = Permissions.finalPermission({
|
||||||
user: {
|
user: {
|
||||||
id: user_id,
|
id: user_id,
|
||||||
roles: member?.roles || [],
|
roles: member?.role_ids || [],
|
||||||
},
|
},
|
||||||
guild: {
|
guild: {
|
||||||
roles: roles || [],
|
roles: member?.roles || [],
|
||||||
},
|
},
|
||||||
channel: {
|
channel: {
|
||||||
overwrites: channel?.permission_overwrites,
|
overwrites: channel?.permission_overwrites,
|
||||||
@ -253,7 +244,7 @@ export async function getPermission(
|
|||||||
const obj = new Permissions(permission);
|
const obj = new Permissions(permission);
|
||||||
|
|
||||||
// pass cache to permission for possible future getPermission calls
|
// pass cache to permission for possible future getPermission calls
|
||||||
obj.cache = { guild, member, channel, roles, user_id };
|
obj.cache = { guild, member, channel, roles: member?.roles, user_id };
|
||||||
|
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
const { initDatabase, closeDatabase } = require("../dist/util/Database");
|
const { initDatabase, closeDatabase } = require("../dist/util/Database");
|
||||||
const { User } = require("../dist/entities/User");
|
const { User } = require("../dist/entities/User");
|
||||||
jest.setTimeout(10000);
|
jest.setTimeout(20000);
|
||||||
|
|
||||||
beforeAll((done) => {
|
beforeAll((done) => {
|
||||||
initDatabase().then(() => {
|
initDatabase().then(() => {
|
||||||
new User().validate(); // warm up schema/model
|
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -28,4 +27,17 @@ describe("User", () => {
|
|||||||
new User({ discriminator: "0" }).validate();
|
new User({ discriminator: "0" }).validate();
|
||||||
}).toThrow();
|
}).toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("add guild", async () => {
|
||||||
|
try {
|
||||||
|
await new User({ guilds: [], discriminator: "1" }, { id: "0" }).save();
|
||||||
|
const user = await User.find("0");
|
||||||
|
|
||||||
|
user.guilds.push(new Guild({ name: "test" }));
|
||||||
|
|
||||||
|
user.save();
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
const { performance } = require("perf_hooks");
|
const { performance } = require("perf_hooks");
|
||||||
|
const fs = require("fs");
|
||||||
|
const path = require("path");
|
||||||
|
|
||||||
|
// fs.unlinkSync(path.join(__dirname, "..", "database.db"));
|
||||||
|
|
||||||
global.expect.extend({
|
global.expect.extend({
|
||||||
toBeFasterThan: async (func, target) => {
|
toBeFasterThan: async (func, target) => {
|
||||||
|
@ -1,33 +0,0 @@
|
|||||||
const { initDatabase, closeDatabase } = require("../dist/util/Database");
|
|
||||||
const { User } = require("../dist/entities/User");
|
|
||||||
jest.setTimeout(10000);
|
|
||||||
|
|
||||||
beforeAll((done) => {
|
|
||||||
initDatabase().then(() => {
|
|
||||||
new User().validate(); // warm up schema/model
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
afterAll(() => {
|
|
||||||
closeDatabase();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Validate model class properties", () => {
|
|
||||||
test("object instead of string", async () => {
|
|
||||||
expect(() => {
|
|
||||||
new User({}, { id: {} }).validate();
|
|
||||||
}).toThrow();
|
|
||||||
});
|
|
||||||
|
|
||||||
test("validation should be faster than 20ms", () => {
|
|
||||||
expect(() => {
|
|
||||||
new User().validate();
|
|
||||||
}).toBeFasterThan(20);
|
|
||||||
});
|
|
||||||
|
|
||||||
test("should not set opts", () => {
|
|
||||||
const user = new User({ opts: { id: 0 } });
|
|
||||||
expect(user.opts.id).not.toBe(0);
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"include": ["src/**/*.ts"],
|
"include": ["src/**/*.ts", "tests/Test.ts"],
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
/* Visit https://aka.ms/tsconfig.json to read more about this file */
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user