This commit is contained in:
kajvan
2023-10-10 18:37:21 +02:00
parent f7e668c8fb
commit 7c739cb3fe
5 changed files with 396 additions and 54 deletions
+126 -52
View File
@@ -1,73 +1,147 @@
class RateLimit{
constructor(maxRequests, timeFrame){
this.maxRequests = maxRequests;
this.timeFrame = timeFrame;
class RateLimiter {
constructor(events){
if(events) {
for(const event in events){
events[event]["attempttimestamp"] = [];
events[event]["lastAttempt"] = 0;
}
}
this.events = events;
this.users = {};
}
async addUser(user){
this.users[user] = {
requests: this.maxRequests,
lastRequest: Date.now()
};
}
addUser(user){
this.users[user] = {};
for(const event in this.events){
this.users[user][event] = this.events[event];
}
async removeUser(user){
delete this.users[user];
}
async checkUser(user){
if(!this.users[user]) await this.addUser(user);
return this.users[user];
}
async checkRateLimit(user){
const { requests, lastRequest } = await this.checkUser(user);
addEvent(event, max, timespan){
this.events[event] = {
"max": max,
"timespan": timespan,
"lastAttempt": 0,
"attempttimestamp": [],
};
for(const user in this.users){
this.users[user][event] = this.events[event];
}
return this.events[event];
}
removeUser(user){
delete this.users[user];
}
attemptEvent(user, event){
if(!this.users.has(user)) return "User not found.";
if(!this.users[user].has(event)) return "Event not found.";
const now = Date.now();
if(now - lastRequest > this.timeFrame) {
this.users[user].requests = this.maxRequests;
this.users[user].lastRequest = now;
const max = this.users[user][event].max;
const timespan = this.users[user][event].timespan;
const attempttimestamp = this.users[user][event].attempttimestamp;
for(let i = 0; i < attempttimestamp.length; i++){
if(attempttimestamp[i] < now - timespan){
attempttimestamp.splice(i, 1);
}
else {
break;
}
}
const attempts = attempttimestamp.length;
if(attempts >= max){
return [false, "limit reached"];
}
else {
attempttimestamp.push(now);
this.users[user][event].attempttimestamp = attempttimestamp;
this.users[user][event].lastAttempt = now;
return true;
}
if(requests > 0) {
this.users[user].requests--;
return true;
}
return false;
}
async getRateLimit(user){
const { requests, lastRequest } = await this.checkUser(user);
const now = Date.now();
if(now - lastRequest > this.timeFrame) {
this.users[user].requests = this.maxRequests;
this.users[user].lastRequest = now;
return this.maxRequests;
}
return requests;
resetEventUser(user, event){
if(!this.users.has(user)) return "User not found.";
if(!this.users[user].has(event)) return "Event not found.";
this.users[user][event].attempttimestamp = [];
this.users[user][event].lastAttempt = 0;
}
async getRateLimitReset(user){
const { requests, lastRequest } = await this.checkUser(user);
const now = Date.now();
if(now - lastRequest > this.timeFrame) {
this.users[user].requests = this.maxRequests;
this.users[user].lastRequest = now;
return this.timeFrame;
resetEvent(event){
if(!this.events.has(event)) return "Event not found.";
for(const user in this.users){
if(this.users[user].has(event)){
this.users[user][event].attempttimestamp = [];
this.users[user][event].lastAttempt = 0;
}
}
return this.timeFrame - (now - lastRequest);
}
async getRateLimitRemaining(user){
const { requests, lastRequest } = await this.checkUser(user);
const now = Date.now();
if(now - lastRequest > this.timeFrame) {
this.users[user].requests = this.maxRequests;
this.users[user].lastRequest = now;
return this.maxRequests;
resetUser(user){
if(!this.users.has(user)) return "User not found.";
for(const event in this.users[user]){
this.users[user][event].attempttimestamp = [];
this.users[user][event].lastAttempt = 0;
}
return requests;
}
resetAll(){
for(const user in this.users){
for(const event in this.users[user]){
this.users[user][event].attempttimestamp = [];
this.users[user][event].lastAttempt = 0;
}
}
}
lastAttempt(user, event){
if(!this.users.has(user)) return "User not found.";
if(!this.users[user].has(event)) return "Event not found.";
return this.users[user][event].lastAttempt;
}
userAttempts(user, event){
if(!this.users.has(user)) return "User not found.";
if(!this.users[user].has(event)) return "Event not found.";
return this.users[user][event].attempttimestamp;
}
remainingAttempts(user, event){
if(!this.users.has(user)) return "User not found.";
if(!this.users[user].has(event)) return "Event not found.";
const now = Date.now();
const max = this.users[user][event].max;
const timespan = this.users[user][event].timespan;
const attempttimestamp = this.users[user][event].attempttimestamp;
for(let i = 0; i < attempttimestamp.length; i++){
if(attempttimestamp[i] < now - timespan){
attempttimestamp.splice(i, 1);
}
else {
break;
}
}
const attempts = attempttimestamp.length;
return max - attempts;
}
}
module.exports = RateLimit;
module.exports = RateLimiter;