UNPKG

detritus-client

Version:

A Typescript NodeJS library to interact with Discord's API, both Rest and Gateway.

133 lines (132 loc) 4.49 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CommandRatelimiter = exports.CommandRatelimit = exports.KEY_SPLITTER = void 0; const detritus_utils_1 = require("detritus-utils"); const basecollection_1 = require("../collections/basecollection"); const constants_1 = require("../constants"); const interaction_1 = require("../interaction"); exports.KEY_SPLITTER = ':'; /** * Command Ratelimit Options and Cache * @category Command Ratelimit */ class CommandRatelimit { constructor(options = {}, command) { this.duration = 5000; this.limit = 5; this.type = constants_1.CommandRatelimitTypes.USER; options = Object.assign({}, options); this.command = command || this.command; this.duration = options.duration || this.duration; this.limit = options.limit || this.limit; if (options.type) { if (typeof (options.type) === 'string') { this.type = options.type.toLowerCase(); } else { this.type = options.type; } } if (typeof (this.type) === 'string' && !constants_1.COMMAND_RATELIMIT_TYPES.includes(this.type)) { // maybe error instead? this.type = constants_1.CommandRatelimitTypes.USER; } this.key = options.key || this.key; } get uniqueKey() { if (this.key) { return 'KEY' + exports.KEY_SPLITTER + this.key; } if (this.command) { if (this.command instanceof interaction_1.InteractionCommand) { return 'INTERACTION-COMMAND' + exports.KEY_SPLITTER + this.command.fullName; } else { return 'COMMAND' + exports.KEY_SPLITTER + this.command.fullName; } } return ''; } createKey(context) { let key; if (typeof (this.type) === 'function') { key = this.type(context); } else { switch (this.type) { case constants_1.CommandRatelimitTypes.CHANNEL: { key = context.channelId || ''; } ; break; case constants_1.CommandRatelimitTypes.GUILD: { key = context.guildId || context.channelId || ''; } ; break; case constants_1.CommandRatelimitTypes.USER: { key = context.userId; } ; break; default: { key = context.userId; this.type = constants_1.CommandRatelimitTypes.USER; } ; } const uniqueKey = this.uniqueKey; if (uniqueKey) { key += exports.KEY_SPLITTER + this.type + exports.KEY_SPLITTER + uniqueKey; } else { key += exports.KEY_SPLITTER + this.type; } } return key; } } exports.CommandRatelimit = CommandRatelimit; class CommandRatelimiter { constructor() { this.cache = new basecollection_1.BaseCollection(); } getExceeded(context, ratelimits, now = Date.now()) { const exceeded = []; for (const ratelimit of ratelimits) { const item = this.getOrCreate(context, ratelimit); if (ratelimit.limit <= item.usages++) { const remaining = (item.start + ratelimit.duration) - now; exceeded.push({ item, ratelimit, remaining }); } } return exceeded; } getOrCreate(context, ratelimit) { const key = ratelimit.createKey(context); let item; if (this.cache.has(key)) { item = this.cache.get(key); } else { const timeout = new detritus_utils_1.Timers.Timeout(); timeout.start(ratelimit.duration, () => { this.cache.delete(key); }); item = { key, replied: false, start: Date.now(), timeout, usages: 0, }; this.cache.set(key, item); } return item; } } exports.CommandRatelimiter = CommandRatelimiter;