1
|
|
|
"use strict"; |
2
|
|
|
Object.defineProperty(exports, "__esModule", { value: true }); |
3
|
|
|
/** |
4
|
|
|
* Manages the ratelimit |
5
|
|
|
*/ |
6
|
|
|
class RateManager { |
7
|
|
|
/** |
8
|
|
|
* Manages the ratelimit |
9
|
|
|
* |
10
|
|
|
* @param calls The total amount of calls allowed to be made to an API |
11
|
|
|
* @param period The period of which the ratelimit lasts in seconds |
12
|
|
|
* @param callsMade Prior amount of calls made while the ratelimit was running |
13
|
|
|
* @param timePassed time already passed if the ratelimiter has already |
14
|
|
|
* been initiated before in seconds |
15
|
|
|
*/ |
16
|
|
|
constructor(calls, period, callsMade = 0, timePassed = 0) { |
17
|
|
|
this.callsMax = calls; |
18
|
|
|
this.period = period * 1000; |
19
|
|
|
this.callsMade = callsMade; |
20
|
|
|
this.startTime = ((new Date()).getTime() - (timePassed * 1000)); |
21
|
|
|
} |
22
|
|
|
/** |
23
|
|
|
* Checks if any calls are left and performs an action based on that result |
24
|
|
|
* |
25
|
|
|
* @param type |
26
|
|
|
* performs an action based on the input |
27
|
|
|
* - "time": gives an error if ratelimit is exceeded and returns the time left |
28
|
|
|
* until the period reset |
29
|
|
|
* - "wait": waits until the period resets |
30
|
|
|
* |
31
|
|
|
* @param callback returns a callback containing the calls left, period reset |
32
|
|
|
* and error in this particular order |
33
|
|
|
* - example: (callsLeft, periodLeft, err) |
34
|
|
|
*/ |
35
|
|
|
call(type, callback) { |
36
|
|
|
//if period expired |
37
|
|
|
if (this.periodExpired()) { |
38
|
|
|
//reset the manager |
39
|
|
|
this.reset(); |
40
|
|
|
callback(this.callsMax - 1, this.getTimeUntilReset()); |
41
|
|
|
} |
42
|
|
|
else { |
43
|
|
|
//if call is still within bounds |
44
|
|
|
if (this.callsUnderLimit()) { |
45
|
|
|
//increment calls made |
46
|
|
|
this.callsMade++; |
47
|
|
|
callback(this.callsLeft(), this.getTimeUntilReset()); |
48
|
|
|
} |
49
|
|
|
else { |
50
|
|
|
//if ratelimit is exceeded |
51
|
|
|
if (type === 'time') { |
52
|
|
|
//return an error |
53
|
|
|
let err = new Error(`ratelimit exceeded,` |
54
|
|
|
+ `${this.getTimeUntilReset()}` |
55
|
|
|
+ ` milliseconds left until period resets`); |
56
|
|
|
callback(0, this.getTimeUntilReset(), err); |
57
|
|
|
} |
58
|
|
|
if (type === 'wait') { |
59
|
|
|
//wait for the manager to reset |
60
|
|
|
setTimeout(() => { |
61
|
|
|
callback(this.callsMax - 1, this.getTimeUntilReset()); |
62
|
|
|
}, (this.getTimeUntilReset() + 50)); |
63
|
|
|
} |
64
|
|
|
} |
65
|
|
|
} |
66
|
|
|
} |
67
|
|
|
periodExpired() { |
68
|
|
|
return (this.startTime + this.period) > (new Date()).getTime() ? |
69
|
|
|
false : true; |
70
|
|
|
} |
71
|
|
|
callsUnderLimit() { |
72
|
|
|
return this.callsMade >= this.callsMax ? false : true; |
73
|
|
|
} |
74
|
|
|
reset() { |
75
|
|
|
this.callsMade = 1; |
76
|
|
|
this.startTime = (new Date()).getTime(); |
77
|
|
|
} |
78
|
|
|
getTimeUntilReset() { |
79
|
|
|
return ((this.startTime + this.period) - (new Date()).getTime()); |
80
|
|
|
} |
81
|
|
|
callsLeft() { |
82
|
|
|
return (this.callsMax - this.callsMade); |
83
|
|
|
} |
84
|
|
|
} |
85
|
|
|
exports.default = RateManager; |
86
|
|
|
|