const { RateLimiter } = require("limiter"); const { log } = require("../src/util"); class KumaRateLimiter { /** * @param {object} config Rate limiter configuration object */ constructor(config) { this.errorMessage = config.errorMessage; this.rateLimiter = new RateLimiter(config); } /** * Callback for pass * @callback passCB * @param {object} err Too many requests */ /** * Should the request be passed through * @param {passCB} callback Callback function to call with decision * @param {number} num Number of tokens to remove * @returns {Promise} Should the request be allowed? */ async pass(callback, num = 1) { const remainingRequests = await this.removeTokens(num); log.info("rate-limit", "remaining requests: " + remainingRequests); if (remainingRequests < 0) { if (callback) { callback({ ok: false, msg: this.errorMessage, }); } return false; } return true; } /** * Remove a given number of tokens * @param {number} num Number of tokens to remove * @returns {Promise} Number of remaining tokens */ async removeTokens(num = 1) { return await this.rateLimiter.removeTokens(num); } } const loginRateLimiter = new KumaRateLimiter({ tokensPerInterval: 20, interval: "minute", fireImmediately: true, errorMessage: "Too frequently, try again later." }); const apiRateLimiter = new KumaRateLimiter({ tokensPerInterval: 60, interval: "minute", fireImmediately: true, errorMessage: "Too frequently, try again later." }); const twoFaRateLimiter = new KumaRateLimiter({ tokensPerInterval: 30, interval: "minute", fireImmediately: true, errorMessage: "Too frequently, try again later." }); module.exports = { loginRateLimiter, apiRateLimiter, twoFaRateLimiter, };