Merge pull request #162 from fosscord/feat--rate-limit
[Feature] Rate Limit
This commit is contained in:
		
						commit
						7b31ca10b3
					
				
							
								
								
									
										349
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										349
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @ -9,7 +9,7 @@ | ||||
| 			"version": "1.0.0", | ||||
| 			"license": "ISC", | ||||
| 			"dependencies": { | ||||
| 				"@fosscord/server-util": "^1.3.20", | ||||
| 				"@fosscord/server-util": "^1.3.23", | ||||
| 				"@types/jest": "^26.0.22", | ||||
| 				"@types/json-schema": "^7.0.7", | ||||
| 				"ajv": "^8.4.0", | ||||
| @ -18,7 +18,6 @@ | ||||
| 				"atomically": "^1.7.0", | ||||
| 				"bcrypt": "^5.0.1", | ||||
| 				"body-parser": "^1.19.0", | ||||
| 				"canvas": "^2.8.0", | ||||
| 				"cheerio": "^1.0.0-rc.9", | ||||
| 				"dot-prop": "^6.0.1", | ||||
| 				"dotenv": "^8.2.0", | ||||
| @ -36,7 +35,9 @@ | ||||
| 				"mongoose": "^5.12.3", | ||||
| 				"mongoose-autopopulate": "^0.12.3", | ||||
| 				"mongoose-long": "^0.3.2", | ||||
| 				"multer": "^1.4.2" | ||||
| 				"multer": "^1.4.2", | ||||
| 				"node-fetch": "^2.6.1", | ||||
| 				"require_optional": "^1.0.1" | ||||
| 			}, | ||||
| 			"devDependencies": { | ||||
| 				"@types/bcrypt": "^3.0.0", | ||||
| @ -48,9 +49,7 @@ | ||||
| 				"@types/node-fetch": "^2.5.7", | ||||
| 				"@zerollup/ts-transform-paths": "^1.7.18", | ||||
| 				"0x": "^4.10.2", | ||||
| 				"ipdata": "^1.1.3", | ||||
| 				"jest": "^26.6.3", | ||||
| 				"node-fetch": "^2.6.1", | ||||
| 				"ts-node": "^9.1.1", | ||||
| 				"ts-node-dev": "^1.1.6", | ||||
| 				"typescript": "^4.1.2" | ||||
| @ -551,9 +550,9 @@ | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/@fosscord/server-util": { | ||||
| 			"version": "1.3.20", | ||||
| 			"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.3.20.tgz", | ||||
| 			"integrity": "sha512-3cIFSRYRXuy7/nUQZkWxutjX2JSBP/vXdVCGB6RrvLYMmPuil96klTezkNPRVhy/F2E4gdVIwuhdmtfacJRtxw==", | ||||
| 			"version": "1.3.23", | ||||
| 			"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.3.23.tgz", | ||||
| 			"integrity": "sha512-YxkuMwsJmMpCN4zGCq0LHvUuV9zlR8yTriquPqWfp5Sbj1DdFz7Qqo6wz6cRYb3WRIINouHhV60cbljmUqLIJQ==", | ||||
| 			"dependencies": { | ||||
| 				"@types/jsonwebtoken": "^8.5.0", | ||||
| 				"@types/mongoose-autopopulate": "^0.10.1", | ||||
| @ -1596,16 +1595,6 @@ | ||||
| 				"node": ">=10.12.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/axios": { | ||||
| 			"version": "0.19.2", | ||||
| 			"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", | ||||
| 			"integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", | ||||
| 			"deprecated": "Critical security vulnerability fixed in v0.21.1. For more information, see https://github.com/axios/axios/pull/3410", | ||||
| 			"dev": true, | ||||
| 			"dependencies": { | ||||
| 				"follow-redirects": "1.5.10" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/babel-jest": { | ||||
| 			"version": "26.6.3", | ||||
| 			"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz", | ||||
| @ -2208,19 +2197,6 @@ | ||||
| 			"integrity": "sha512-e4Gyp7P8vqC2qV2iHA+cJNf/yqUKOShXQOJHQt81OHxlIZl/j/j3soEA0adAQi8CPUQgvOdDENyQ5kd6a6mNSg==", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"node_modules/canvas": { | ||||
| 			"version": "2.8.0", | ||||
| 			"resolved": "https://registry.npmjs.org/canvas/-/canvas-2.8.0.tgz", | ||||
| 			"integrity": "sha512-gLTi17X8WY9Cf5GZ2Yns8T5lfBOcGgFehDFb+JQwDqdOoBOcECS9ZWMEAqMSVcMYwXD659J8NyzjRY/2aE+C2Q==", | ||||
| 			"dependencies": { | ||||
| 				"@mapbox/node-pre-gyp": "^1.0.0", | ||||
| 				"nan": "^2.14.0", | ||||
| 				"simple-get": "^3.0.3" | ||||
| 			}, | ||||
| 			"engines": { | ||||
| 				"node": ">=6" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/capture-exit": { | ||||
| 			"version": "2.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", | ||||
| @ -3055,17 +3031,6 @@ | ||||
| 				"node": ">=0.10" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/decompress-response": { | ||||
| 			"version": "4.2.1", | ||||
| 			"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", | ||||
| 			"integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", | ||||
| 			"dependencies": { | ||||
| 				"mimic-response": "^2.0.0" | ||||
| 			}, | ||||
| 			"engines": { | ||||
| 				"node": ">=8" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/deep-is": { | ||||
| 			"version": "0.1.3", | ||||
| 			"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", | ||||
| @ -4022,33 +3987,6 @@ | ||||
| 				"node": ">=8" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/follow-redirects": { | ||||
| 			"version": "1.5.10", | ||||
| 			"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", | ||||
| 			"integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", | ||||
| 			"dev": true, | ||||
| 			"dependencies": { | ||||
| 				"debug": "=3.1.0" | ||||
| 			}, | ||||
| 			"engines": { | ||||
| 				"node": ">=4.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/follow-redirects/node_modules/debug": { | ||||
| 			"version": "3.1.0", | ||||
| 			"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", | ||||
| 			"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", | ||||
| 			"dev": true, | ||||
| 			"dependencies": { | ||||
| 				"ms": "2.0.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/follow-redirects/node_modules/ms": { | ||||
| 			"version": "2.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | ||||
| 			"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"node_modules/for-in": { | ||||
| 			"version": "1.0.2", | ||||
| 			"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", | ||||
| @ -4713,15 +4651,6 @@ | ||||
| 			"integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"node_modules/ip-regex": { | ||||
| 			"version": "4.3.0", | ||||
| 			"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", | ||||
| 			"integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", | ||||
| 			"dev": true, | ||||
| 			"engines": { | ||||
| 				"node": ">=8" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/ipaddr.js": { | ||||
| 			"version": "1.9.1", | ||||
| 			"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", | ||||
| @ -4730,47 +4659,6 @@ | ||||
| 				"node": ">= 0.10" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/ipdata": { | ||||
| 			"version": "1.1.3", | ||||
| 			"resolved": "https://registry.npmjs.org/ipdata/-/ipdata-1.1.3.tgz", | ||||
| 			"integrity": "sha512-4txsxeDiA3cJHhtWT5I6+l7hfvowRf7uGijOhw4uP9R/LSmGFiAdC6GfVpFAFxUIlgq14dBvuSDJi3ufhR1/OQ==", | ||||
| 			"dev": true, | ||||
| 			"dependencies": { | ||||
| 				"axios": "^0.19.0", | ||||
| 				"is-ip": "^3.1.0", | ||||
| 				"lodash": "4.17.15", | ||||
| 				"lru-cache": "5.1.1", | ||||
| 				"tslib": "1.9.3", | ||||
| 				"url-join": "4.0.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/ipdata/node_modules/lodash": { | ||||
| 			"version": "4.17.15", | ||||
| 			"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", | ||||
| 			"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"node_modules/ipdata/node_modules/lru-cache": { | ||||
| 			"version": "5.1.1", | ||||
| 			"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", | ||||
| 			"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", | ||||
| 			"dev": true, | ||||
| 			"dependencies": { | ||||
| 				"yallist": "^3.0.2" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/ipdata/node_modules/tslib": { | ||||
| 			"version": "1.9.3", | ||||
| 			"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", | ||||
| 			"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"node_modules/ipdata/node_modules/yallist": { | ||||
| 			"version": "3.1.1", | ||||
| 			"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", | ||||
| 			"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"node_modules/is-accessor-descriptor": { | ||||
| 			"version": "1.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", | ||||
| @ -4935,18 +4823,6 @@ | ||||
| 				"node": ">=0.10.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/is-ip": { | ||||
| 			"version": "3.1.0", | ||||
| 			"resolved": "https://registry.npmjs.org/is-ip/-/is-ip-3.1.0.tgz", | ||||
| 			"integrity": "sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==", | ||||
| 			"dev": true, | ||||
| 			"dependencies": { | ||||
| 				"ip-regex": "^4.0.0" | ||||
| 			}, | ||||
| 			"engines": { | ||||
| 				"node": ">=8" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/is-number": { | ||||
| 			"version": "7.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", | ||||
| @ -6406,14 +6282,6 @@ | ||||
| 				"node": ">=6" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/mimic-response": { | ||||
| 			"version": "2.1.0", | ||||
| 			"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", | ||||
| 			"integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", | ||||
| 			"engines": { | ||||
| 				"node": ">=8" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/minimalistic-assert": { | ||||
| 			"version": "1.0.1", | ||||
| 			"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", | ||||
| @ -6678,11 +6546,6 @@ | ||||
| 			"integrity": "sha512-nU7mOEuaXiQIB/EgTIjYZJ7g8KqMm2D8l4qp+DqA4jxWOb/tnb1KEoqp+tlbdQIDIAiC1i7j7X/3yHDFXLxr9g==", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"node_modules/nan": { | ||||
| 			"version": "2.14.2", | ||||
| 			"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", | ||||
| 			"integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" | ||||
| 		}, | ||||
| 		"node_modules/nanoassert": { | ||||
| 			"version": "1.1.0", | ||||
| 			"resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-1.1.0.tgz", | ||||
| @ -7984,6 +7847,23 @@ | ||||
| 				"node": ">=0.10.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/require_optional": { | ||||
| 			"version": "1.0.1", | ||||
| 			"resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", | ||||
| 			"integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", | ||||
| 			"dependencies": { | ||||
| 				"resolve-from": "^2.0.0", | ||||
| 				"semver": "^5.1.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/require_optional/node_modules/resolve-from": { | ||||
| 			"version": "2.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", | ||||
| 			"integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=", | ||||
| 			"engines": { | ||||
| 				"node": ">=0.10.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/require-directory": { | ||||
| 			"version": "2.1.1", | ||||
| 			"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", | ||||
| @ -8598,17 +8478,8 @@ | ||||
| 		"node_modules/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==" | ||||
| 		}, | ||||
| 		"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==", | ||||
| 			"dependencies": { | ||||
| 				"decompress-response": "^4.2.0", | ||||
| 				"once": "^1.3.1", | ||||
| 				"simple-concat": "^1.0.0" | ||||
| 			} | ||||
| 			"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"node_modules/single-line-log": { | ||||
| 			"version": "1.1.2", | ||||
| @ -9921,12 +9792,6 @@ | ||||
| 				"querystring": "0.2.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"node_modules/url-join": { | ||||
| 			"version": "4.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz", | ||||
| 			"integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo=", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"node_modules/url/node_modules/punycode": { | ||||
| 			"version": "1.3.2", | ||||
| 			"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", | ||||
| @ -10788,9 +10653,9 @@ | ||||
| 			} | ||||
| 		}, | ||||
| 		"@fosscord/server-util": { | ||||
| 			"version": "1.3.20", | ||||
| 			"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.3.20.tgz", | ||||
| 			"integrity": "sha512-3cIFSRYRXuy7/nUQZkWxutjX2JSBP/vXdVCGB6RrvLYMmPuil96klTezkNPRVhy/F2E4gdVIwuhdmtfacJRtxw==", | ||||
| 			"version": "1.3.23", | ||||
| 			"resolved": "https://registry.npmjs.org/@fosscord/server-util/-/server-util-1.3.23.tgz", | ||||
| 			"integrity": "sha512-YxkuMwsJmMpCN4zGCq0LHvUuV9zlR8yTriquPqWfp5Sbj1DdFz7Qqo6wz6cRYb3WRIINouHhV60cbljmUqLIJQ==", | ||||
| 			"requires": { | ||||
| 				"@types/jsonwebtoken": "^8.5.0", | ||||
| 				"@types/mongoose-autopopulate": "^0.10.1", | ||||
| @ -11719,15 +11584,6 @@ | ||||
| 			"resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz", | ||||
| 			"integrity": "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==" | ||||
| 		}, | ||||
| 		"axios": { | ||||
| 			"version": "0.19.2", | ||||
| 			"resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", | ||||
| 			"integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", | ||||
| 			"dev": true, | ||||
| 			"requires": { | ||||
| 				"follow-redirects": "1.5.10" | ||||
| 			} | ||||
| 		}, | ||||
| 		"babel-jest": { | ||||
| 			"version": "26.6.3", | ||||
| 			"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-26.6.3.tgz", | ||||
| @ -12268,16 +12124,6 @@ | ||||
| 			"integrity": "sha512-e4Gyp7P8vqC2qV2iHA+cJNf/yqUKOShXQOJHQt81OHxlIZl/j/j3soEA0adAQi8CPUQgvOdDENyQ5kd6a6mNSg==", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"canvas": { | ||||
| 			"version": "2.8.0", | ||||
| 			"resolved": "https://registry.npmjs.org/canvas/-/canvas-2.8.0.tgz", | ||||
| 			"integrity": "sha512-gLTi17X8WY9Cf5GZ2Yns8T5lfBOcGgFehDFb+JQwDqdOoBOcECS9ZWMEAqMSVcMYwXD659J8NyzjRY/2aE+C2Q==", | ||||
| 			"requires": { | ||||
| 				"@mapbox/node-pre-gyp": "^1.0.0", | ||||
| 				"nan": "^2.14.0", | ||||
| 				"simple-get": "^3.0.3" | ||||
| 			} | ||||
| 		}, | ||||
| 		"capture-exit": { | ||||
| 			"version": "2.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", | ||||
| @ -13012,14 +12858,6 @@ | ||||
| 			"integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"decompress-response": { | ||||
| 			"version": "4.2.1", | ||||
| 			"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", | ||||
| 			"integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", | ||||
| 			"requires": { | ||||
| 				"mimic-response": "^2.0.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"deep-is": { | ||||
| 			"version": "0.1.3", | ||||
| 			"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", | ||||
| @ -13822,32 +13660,6 @@ | ||||
| 				"path-exists": "^4.0.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"follow-redirects": { | ||||
| 			"version": "1.5.10", | ||||
| 			"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", | ||||
| 			"integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", | ||||
| 			"dev": true, | ||||
| 			"requires": { | ||||
| 				"debug": "=3.1.0" | ||||
| 			}, | ||||
| 			"dependencies": { | ||||
| 				"debug": { | ||||
| 					"version": "3.1.0", | ||||
| 					"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", | ||||
| 					"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", | ||||
| 					"dev": true, | ||||
| 					"requires": { | ||||
| 						"ms": "2.0.0" | ||||
| 					} | ||||
| 				}, | ||||
| 				"ms": { | ||||
| 					"version": "2.0.0", | ||||
| 					"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", | ||||
| 					"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", | ||||
| 					"dev": true | ||||
| 				} | ||||
| 			} | ||||
| 		}, | ||||
| 		"for-in": { | ||||
| 			"version": "1.0.2", | ||||
| 			"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", | ||||
| @ -14389,60 +14201,11 @@ | ||||
| 			"integrity": "sha512-lDB5YccMydFBtasVtxnZ3MRBHuaoE8GKsppq+EchKL2U4nK/DmEpPHNH8MZe5HkMtpSiTSOZwfN0tzYjO/lJEw==", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"ip-regex": { | ||||
| 			"version": "4.3.0", | ||||
| 			"resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-4.3.0.tgz", | ||||
| 			"integrity": "sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"ipaddr.js": { | ||||
| 			"version": "1.9.1", | ||||
| 			"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", | ||||
| 			"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" | ||||
| 		}, | ||||
| 		"ipdata": { | ||||
| 			"version": "1.1.3", | ||||
| 			"resolved": "https://registry.npmjs.org/ipdata/-/ipdata-1.1.3.tgz", | ||||
| 			"integrity": "sha512-4txsxeDiA3cJHhtWT5I6+l7hfvowRf7uGijOhw4uP9R/LSmGFiAdC6GfVpFAFxUIlgq14dBvuSDJi3ufhR1/OQ==", | ||||
| 			"dev": true, | ||||
| 			"requires": { | ||||
| 				"axios": "^0.19.0", | ||||
| 				"is-ip": "^3.1.0", | ||||
| 				"lodash": "4.17.15", | ||||
| 				"lru-cache": "5.1.1", | ||||
| 				"tslib": "1.9.3", | ||||
| 				"url-join": "4.0.0" | ||||
| 			}, | ||||
| 			"dependencies": { | ||||
| 				"lodash": { | ||||
| 					"version": "4.17.15", | ||||
| 					"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", | ||||
| 					"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==", | ||||
| 					"dev": true | ||||
| 				}, | ||||
| 				"lru-cache": { | ||||
| 					"version": "5.1.1", | ||||
| 					"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", | ||||
| 					"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", | ||||
| 					"dev": true, | ||||
| 					"requires": { | ||||
| 						"yallist": "^3.0.2" | ||||
| 					} | ||||
| 				}, | ||||
| 				"tslib": { | ||||
| 					"version": "1.9.3", | ||||
| 					"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", | ||||
| 					"integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", | ||||
| 					"dev": true | ||||
| 				}, | ||||
| 				"yallist": { | ||||
| 					"version": "3.1.1", | ||||
| 					"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", | ||||
| 					"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", | ||||
| 					"dev": true | ||||
| 				} | ||||
| 			} | ||||
| 		}, | ||||
| 		"is-accessor-descriptor": { | ||||
| 			"version": "1.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", | ||||
| @ -14568,15 +14331,6 @@ | ||||
| 				"is-extglob": "^2.1.1" | ||||
| 			} | ||||
| 		}, | ||||
| 		"is-ip": { | ||||
| 			"version": "3.1.0", | ||||
| 			"resolved": "https://registry.npmjs.org/is-ip/-/is-ip-3.1.0.tgz", | ||||
| 			"integrity": "sha512-35vd5necO7IitFPjd/YBeqwWnyDWbuLH9ZXQdMfDA8TEo7pv5X8yfrvVO3xbJbLUlERCMvf6X0hTUamQxCYJ9Q==", | ||||
| 			"dev": true, | ||||
| 			"requires": { | ||||
| 				"ip-regex": "^4.0.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"is-number": { | ||||
| 			"version": "7.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", | ||||
| @ -15774,11 +15528,6 @@ | ||||
| 			"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"mimic-response": { | ||||
| 			"version": "2.1.0", | ||||
| 			"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", | ||||
| 			"integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==" | ||||
| 		}, | ||||
| 		"minimalistic-assert": { | ||||
| 			"version": "1.0.1", | ||||
| 			"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", | ||||
| @ -16004,11 +15753,6 @@ | ||||
| 			"integrity": "sha512-nU7mOEuaXiQIB/EgTIjYZJ7g8KqMm2D8l4qp+DqA4jxWOb/tnb1KEoqp+tlbdQIDIAiC1i7j7X/3yHDFXLxr9g==", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"nan": { | ||||
| 			"version": "2.14.2", | ||||
| 			"resolved": "https://registry.npmjs.org/nan/-/nan-2.14.2.tgz", | ||||
| 			"integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" | ||||
| 		}, | ||||
| 		"nanoassert": { | ||||
| 			"version": "1.1.0", | ||||
| 			"resolved": "https://registry.npmjs.org/nanoassert/-/nanoassert-1.1.0.tgz", | ||||
| @ -17090,6 +16834,22 @@ | ||||
| 				"is-finite": "^1.0.0" | ||||
| 			} | ||||
| 		}, | ||||
| 		"require_optional": { | ||||
| 			"version": "1.0.1", | ||||
| 			"resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", | ||||
| 			"integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", | ||||
| 			"requires": { | ||||
| 				"resolve-from": "^2.0.0", | ||||
| 				"semver": "^5.1.0" | ||||
| 			}, | ||||
| 			"dependencies": { | ||||
| 				"resolve-from": { | ||||
| 					"version": "2.0.0", | ||||
| 					"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", | ||||
| 					"integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" | ||||
| 				} | ||||
| 			} | ||||
| 		}, | ||||
| 		"require-directory": { | ||||
| 			"version": "2.1.1", | ||||
| 			"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", | ||||
| @ -17601,17 +17361,8 @@ | ||||
| 		"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==" | ||||
| 		}, | ||||
| 		"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==", | ||||
| 			"requires": { | ||||
| 				"decompress-response": "^4.2.0", | ||||
| 				"once": "^1.3.1", | ||||
| 				"simple-concat": "^1.0.0" | ||||
| 			} | ||||
| 			"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"single-line-log": { | ||||
| 			"version": "1.1.2", | ||||
| @ -18708,12 +18459,6 @@ | ||||
| 				} | ||||
| 			} | ||||
| 		}, | ||||
| 		"url-join": { | ||||
| 			"version": "4.0.0", | ||||
| 			"resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.0.tgz", | ||||
| 			"integrity": "sha1-TTNA6AfTdzvamZH4MFrNzCpmXSo=", | ||||
| 			"dev": true | ||||
| 		}, | ||||
| 		"use": { | ||||
| 			"version": "3.1.1", | ||||
| 			"resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", | ||||
|  | ||||
| @ -29,7 +29,7 @@ | ||||
| 	}, | ||||
| 	"homepage": "https://github.com/fosscord/fosscord-api#readme", | ||||
| 	"dependencies": { | ||||
| 		"@fosscord/server-util": "^1.3.20", | ||||
| 		"@fosscord/server-util": "^1.3.23", | ||||
| 		"@types/jest": "^26.0.22", | ||||
| 		"@types/json-schema": "^7.0.7", | ||||
| 		"ajv": "^8.4.0", | ||||
| @ -49,7 +49,6 @@ | ||||
| 		"i18next-http-middleware": "^3.1.3", | ||||
| 		"i18next-node-fs-backend": "^2.1.3", | ||||
| 		"image-size": "^1.0.0", | ||||
| 		"ipdata": "^1.1.3", | ||||
| 		"jsonwebtoken": "^8.5.1", | ||||
| 		"lambert-server": "^1.2.5", | ||||
| 		"missing-native-js-functions": "^1.2.6", | ||||
| @ -57,7 +56,8 @@ | ||||
| 		"mongoose-autopopulate": "^0.12.3", | ||||
| 		"mongoose-long": "^0.3.2", | ||||
| 		"multer": "^1.4.2", | ||||
| 		"node-fetch": "^2.6.1" | ||||
| 		"node-fetch": "^2.6.1", | ||||
| 		"require_optional": "^1.0.1" | ||||
| 	}, | ||||
| 	"devDependencies": { | ||||
| 		"@types/bcrypt": "^3.0.0", | ||||
|  | ||||
| @ -13,6 +13,7 @@ import express, { Router, Request, Response } from "express"; | ||||
| import fetch, { Response as FetchResponse } from "node-fetch"; | ||||
| import mongoose from "mongoose"; | ||||
| import path from "path"; | ||||
| import RateLimit from "./middlewares/RateLimit"; | ||||
| 
 | ||||
| // this will return the new updated document for findOneAndUpdate
 | ||||
| mongoose.set("returnOriginal", false); // https://mongoosejs.com/docs/api/model.html#model_Model.findOneAndUpdate
 | ||||
| @ -54,7 +55,8 @@ export class FosscordServer extends Server { | ||||
| 			db.collection("roles").createIndex({ id: 1 }, { unique: true }), | ||||
| 			db.collection("emojis").createIndex({ id: 1 }, { unique: true }), | ||||
| 			db.collection("invites").createIndex({ code: 1 }, { unique: true }), | ||||
| 			db.collection("invites").createIndex({ expires_at: 1 }, { expireAfterSeconds: 0 }) // after 0 seconds of expires_at the invite will get delete
 | ||||
| 			db.collection("invites").createIndex({ expires_at: 1 }, { expireAfterSeconds: 0 }), // after 0 seconds of expires_at the invite will get delete
 | ||||
| 			db.collection("ratelimits").createIndex({ expires_at: 1 }, { expireAfterSeconds: 0 }) | ||||
| 		]); | ||||
| 	} | ||||
| 
 | ||||
| @ -91,6 +93,10 @@ export class FosscordServer extends Server { | ||||
| 		const prefix = Router(); | ||||
| 		// @ts-ignore
 | ||||
| 		this.app = prefix; | ||||
| 		prefix.use(RateLimit({ bucket: "global", count: 10, error: 10, window: 5, bot: 250 })); | ||||
| 		prefix.use("/guilds/:id", RateLimit({ count: 10, window: 5 })); | ||||
| 		prefix.use("/webhooks/:id", RateLimit({ count: 10, window: 5 })); | ||||
| 		prefix.use("/channels/:id", RateLimit({ count: 10, window: 5 })); | ||||
| 
 | ||||
| 		this.routes = await this.registerRoutes(path.join(__dirname, "routes", "/")); | ||||
| 		app.use("/api", prefix); // allow unversioned requests
 | ||||
|  | ||||
| @ -11,10 +11,14 @@ export const NO_AUTHORIZATION_ROUTES = [ | ||||
| 	/^\/api(\/v\d+)?\/guilds\/\d+\/widget\.(json|png)/ | ||||
| ]; | ||||
| 
 | ||||
| export const API_PREFIX = /^\/api(\/v\d+)?/; | ||||
| export const API_PREFIX_TRAILING_SLASH = /^\/api(\/v\d+)?\//; | ||||
| 
 | ||||
| declare global { | ||||
| 	namespace Express { | ||||
| 		interface Request { | ||||
| 			user_id: any; | ||||
| 			user_bot: boolean; | ||||
| 			token: any; | ||||
| 		} | ||||
| 	} | ||||
| @ -23,17 +27,19 @@ declare global { | ||||
| export async function Authentication(req: Request, res: Response, next: NextFunction) { | ||||
| 	if (req.method === "OPTIONS") return res.sendStatus(204); | ||||
| 	if (!req.url.startsWith("/api")) return next(); | ||||
| 	if (req.url.startsWith("/api/v8/invites") && req.method === "GET") return next(); | ||||
| 	const apiPath = req.url.replace(API_PREFIX, ""); | ||||
| 	if (apiPath.startsWith("/invites") && req.method === "GET") return next(); | ||||
| 	if (NO_AUTHORIZATION_ROUTES.some((x) => x.test(req.url))) return next(); | ||||
| 	if (!req.headers.authorization) return next(new HTTPError("Missing Authorization Header", 401)); | ||||
| 
 | ||||
| 	try { | ||||
| 		const { jwtSecret } = Config.get().security; | ||||
| 
 | ||||
| 		const decoded: any = await checkToken(req.headers.authorization, jwtSecret); | ||||
| 		const { decoded, user }: any = await checkToken(req.headers.authorization, jwtSecret); | ||||
| 
 | ||||
| 		req.token = decoded; | ||||
| 		req.user_id = decoded.id; | ||||
| 		req.user_bot = user.bot; | ||||
| 		return next(); | ||||
| 	} catch (error) { | ||||
| 		return next(new HTTPError(error.toString(), 400)); | ||||
|  | ||||
| @ -1,7 +1,16 @@ | ||||
| import { db, MongooseCache } from "@fosscord/server-util"; | ||||
| import { db, MongooseCache, Bucket } from "@fosscord/server-util"; | ||||
| import { NextFunction, Request, Response } from "express"; | ||||
| import { getIpAdress } from "../util/ipAddress"; | ||||
| import { API_PREFIX_TRAILING_SLASH } from "./Authentication"; | ||||
| 
 | ||||
| const Cache = new MongooseCache(db.collection("ratelimits"), [{ $match: { blocked: true } }], { onlyEvents: false, array: true }); | ||||
| const Cache = new MongooseCache( | ||||
| 	db.collection("ratelimits"), | ||||
| 	[ | ||||
| 		// TODO: uncomment $match and fix error: not receiving change events
 | ||||
| 		// { $match: { blocked: true } }
 | ||||
| 	], | ||||
| 	{ onlyEvents: false, array: true } | ||||
| ); | ||||
| 
 | ||||
| // Docs: https://discord.com/developers/docs/topics/rate-limits
 | ||||
| 
 | ||||
| @ -22,10 +31,100 @@ TODO: use config values | ||||
| 
 | ||||
| */ | ||||
| 
 | ||||
| export default function RateLimit(opts: { bucket?: string; window: number; count: number }) { | ||||
| export default function RateLimit(opts: { | ||||
| 	bucket?: string; | ||||
| 	window: number; | ||||
| 	count: number; | ||||
| 	bot?: number; | ||||
| 	error?: number; | ||||
| 	webhook?: number; | ||||
| 	oauth?: number; | ||||
| 	GET?: number; | ||||
| 	MODIFY?: number; | ||||
| }) { | ||||
| 	Cache.init(); // will only initalize it once
 | ||||
| 
 | ||||
| 	return async (req: Request, res: Response, next: NextFunction) => { | ||||
| 		const bucket_id = opts.bucket || req.path.replace(API_PREFIX_TRAILING_SLASH, ""); | ||||
| 		const user_id = req.user_id || getIpAdress(req); | ||||
| 		var max_hits = opts.count; | ||||
| 		if (opts.bot && req.user_bot) max_hits = opts.bot; | ||||
| 		if (opts.GET && ["GET", "OPTIONS", "HEAD"].includes(req.method)) max_hits = opts.GET; | ||||
| 		else if (opts.MODIFY && ["POST", "DELETE", "PATCH", "PUT"].includes(req.method)) max_hits = opts.MODIFY; | ||||
| 
 | ||||
| 		const offender = Cache.data?.find((x: Bucket) => x.user_id == user_id && x.id === bucket_id) as Bucket | null; | ||||
| 
 | ||||
| 		if (offender && offender.blocked) { | ||||
| 			const reset = offender.expires_at.getTime(); | ||||
| 			const resetAfterMs = reset - Date.now(); | ||||
| 			const resetAfterSec = resetAfterMs / 1000; | ||||
| 			const global = bucket_id === "global"; | ||||
| 			console.log("blocked", { resetAfterMs }); | ||||
| 
 | ||||
| 			if (resetAfterMs > 0) { | ||||
| 				return ( | ||||
| 					res | ||||
| 						.status(429) | ||||
| 						.set("X-RateLimit-Limit", `${max_hits}`) | ||||
| 						.set("X-RateLimit-Remaining", "0") | ||||
| 						.set("X-RateLimit-Reset", `${reset}`) | ||||
| 						.set("X-RateLimit-Reset-After", `${resetAfterSec}`) | ||||
| 						.set("X-RateLimit-Global", `${global}`) | ||||
| 						.set("Retry-After", `${Math.ceil(resetAfterSec)}`) | ||||
| 						.set("X-RateLimit-Bucket", `${bucket_id}`) | ||||
| 						// TODO: error rate limit message translation
 | ||||
| 						.send({ message: "You are being rate limited.", retry_after: resetAfterSec, global }) | ||||
| 				); | ||||
| 			} else { | ||||
| 				// mongodb ttl didn't update yet -> manually update/delete
 | ||||
| 				db.collection("ratelimits").updateOne( | ||||
| 					{ id: bucket_id, user_id }, | ||||
| 					{ $set: { hits: 0, expires_at: new Date(Date.now() + opts.window * 1000), blocked: false } } | ||||
| 				); | ||||
| 			} | ||||
| 		} | ||||
| 		next(); | ||||
| 
 | ||||
| 		if (opts.error) { | ||||
| 			res.once("finish", () => { | ||||
| 				// check if error and increment error rate limit
 | ||||
| 				if (res.statusCode >= 400) { | ||||
| 					// TODO: use config rate limit values
 | ||||
| 					return hitRoute({ bucket_id: "error", user_id, max_hits: opts.error as number, window: opts.window }); | ||||
| 				} | ||||
| 			}); | ||||
| 		} | ||||
| 
 | ||||
| 		return hitRoute({ user_id, bucket_id, max_hits, window: opts.window }); | ||||
| 	}; | ||||
| } | ||||
| 
 | ||||
| function hitRoute(opts: { user_id: string; bucket_id: string; max_hits: number; window: number }) { | ||||
| 	return db.collection("ratelimits").updateOne( | ||||
| 		{ id: opts.bucket_id, user_id: opts.user_id }, | ||||
| 		[ | ||||
| 			{ | ||||
| 				$replaceRoot: { | ||||
| 					newRoot: { | ||||
| 						// similar to $setOnInsert
 | ||||
| 						$mergeObjects: [ | ||||
| 							{ | ||||
| 								id: opts.bucket_id, | ||||
| 								user_id: opts.user_id, | ||||
| 								expires_at: new Date(Date.now() + opts.window * 1000) | ||||
| 							}, | ||||
| 							"$$ROOT" | ||||
| 						] | ||||
| 					} | ||||
| 				} | ||||
| 			}, | ||||
| 			{ | ||||
| 				$set: { | ||||
| 					hits: { $sum: [{ $ifNull: ["$hits", 0] }, 1] }, | ||||
| 					blocked: { $gt: ["$hits", opts.max_hits] } | ||||
| 				} | ||||
| 			} | ||||
| 		], | ||||
| 		{ upsert: true } | ||||
| 	); | ||||
| } | ||||
|  | ||||
| @ -1,9 +1,8 @@ | ||||
| import { Request, Response, Router } from "express"; | ||||
| import { GuildModel } from "@fosscord/server-util"; | ||||
| import { HTTPError } from "lambert-server"; | ||||
| import { Image } from "canvas"; | ||||
| import fs from "fs"; | ||||
| import path from "path" | ||||
| import path from "path"; | ||||
| 
 | ||||
| const router: Router = Router(); | ||||
| 
 | ||||
| @ -35,7 +34,7 @@ router.get("/", async (req: Request, res: Response) => { | ||||
| 	const sizeOf = require("image-size"); | ||||
| 
 | ||||
| 	// TODO: Widget style templates need Fosscord branding
 | ||||
| 	const source = path.join(__dirname, "..", "..", "..", "..", "assets","widget", `${style}.png`) | ||||
| 	const source = path.join(__dirname, "..", "..", "..", "..", "assets", "widget", `${style}.png`); | ||||
| 	if (!fs.existsSync(source)) { | ||||
| 		throw new HTTPError("Widget template does not exist.", 400); | ||||
| 	} | ||||
| @ -85,7 +84,8 @@ router.get("/", async (req: Request, res: Response) => { | ||||
| }); | ||||
| 
 | ||||
| async function drawIcon(canvas: any, x: number, y: number, scale: number, icon: string) { | ||||
| 	const img = new Image(); | ||||
| 	// @ts-ignore
 | ||||
| 	const img = new require("canvas").Image(); | ||||
| 	img.src = icon; | ||||
| 
 | ||||
| 	// Do some canvas clipping magic!
 | ||||
|  | ||||
| @ -1,13 +1,7 @@ | ||||
| import { Config } from "@fosscord/server-util"; | ||||
| import { Request } from "express"; | ||||
| // use ipdata package instead of simple fetch because of integrated caching
 | ||||
| import IPData, { LookupResponse } from "ipdata"; | ||||
| 
 | ||||
| var ipdata: IPData; | ||||
| const cacheConfig = { | ||||
| 	max: 1000, // max size
 | ||||
| 	maxAge: 1000 * 60 * 60 * 24 // max age in ms (i.e. one day)
 | ||||
| }; | ||||
| import fetch from "node-fetch"; | ||||
| 
 | ||||
| const exampleData = { | ||||
| 	ip: "", | ||||
| @ -66,15 +60,14 @@ const exampleData = { | ||||
| 	status: 200 | ||||
| }; | ||||
| 
 | ||||
| export async function IPAnalysis(ip: string): Promise<LookupResponse> { | ||||
| export async function IPAnalysis(ip: string): Promise<typeof exampleData> { | ||||
| 	const { ipdataApiKey } = Config.get().security; | ||||
| 	if (!ipdataApiKey) return { ...exampleData, ip }; | ||||
| 	if (!ipdata) ipdata = new IPData(ipdataApiKey, cacheConfig); | ||||
| 
 | ||||
| 	return await ipdata.lookup(ip); | ||||
| 	return (await fetch(`https://api.ipdata.co/${ip}?api-key=${ipdataApiKey}`)).json(); | ||||
| } | ||||
| 
 | ||||
| export function isProxy(data: LookupResponse) { | ||||
| export function isProxy(data: typeof exampleData) { | ||||
| 	if (!data || !data.asn || !data.threat) return false; | ||||
| 	if (data.asn.type !== "isp") return true; | ||||
| 	if (Object.values(data.threat).some((x) => x)) return true; | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Flam3rboy
						Flam3rboy