UNPKG

rashi-discord-bot-lib

Version:

🚀 Powerful Discord bot framework with built-in database, event handling, and utilities

170 lines • 7.02 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.CooldownManager = void 0; exports.isOwner = isOwner; exports.isDev = isDev; exports.checkContext = checkContext; exports.checkPermsSlash = checkPermsSlash; exports.checkPermsPrefix = checkPermsPrefix; exports.enforceSlashGuards = enforceSlashGuards; exports.enforcePrefixGuards = enforcePrefixGuards; const discord_js_1 = require("discord.js"); class CooldownManager { backend; store = new Map(); constructor(backend) { this.backend = backend; } key(userId, command) { return `${userId}:${command}`; } async getRemaining(userId, command) { const now = Date.now(); const key = this.key(userId, command); if (!this.backend) { const expires = this.store.get(key) ?? 0; return expires <= now ? 0 : Math.ceil((expires - now) / 1000); } const raw = this.backend.instance.get(`cooldowns.${key}`); if (!raw || raw <= now) return 0; return Math.ceil((raw - now) / 1000); } async set(userId, command, seconds) { const key = this.key(userId, command); const expiresAt = Date.now() + seconds * 1000; if (!this.backend) { this.store.set(key, expiresAt); setTimeout(() => this.store.delete(key), seconds * 1000 + 1000); return; } await this.backend.instance.set(`cooldowns.${key}`, expiresAt); } async checkAndSet(userId, command, seconds) { const remaining = await this.getRemaining(userId, command); if (remaining > 0) return remaining; await this.set(userId, command, seconds); return 0; } async clear(userId, command) { const key = this.key(userId, command); if (!this.backend) { this.store.delete(key); return; } await this.backend.instance.delete(`cooldowns.${key}`); } } exports.CooldownManager = CooldownManager; /* ----------------------------- Owner / Dev check -------------------------- */ function isOwner(userId) { return process.env.BOT_OWNER_ID?.trim() === userId; } function isDev(userId) { return (process.env.DEVS?.split(',').map(s => s.trim()) ?? []).includes(userId); } /* ------------------------------- Context check ---------------------------- */ function checkContext(inGuild, options) { if (options.guildOnly && !inGuild) return { ok: false, message: 'This command can only be used in a server.' }; if (options.dmOnly && inGuild) return { ok: false, message: 'This command can only be used in Direct Messages.' }; return { ok: true }; } /* --------------------------- Permission utilities ------------------------- */ function hasAll(member, perms) { if (!perms || perms.length === 0) return { ok: true, missing: [] }; if (!member) return { ok: false, missing: perms.map(String) }; const bits = new discord_js_1.PermissionsBitField(member.permissions); const missing = perms.filter(p => !bits.has(p)); return { ok: missing.length === 0, missing: missing.map(String) }; } function checkPermsSlash(interaction, options) { const guild = interaction.guild ?? null; const me = guild?.members.me ?? null; const member = guild ? interaction.member : null; const user = hasAll(member, options.permissions); const bot = hasAll(me, options.permissions); return { ok: user.ok && bot.ok, userMissing: user.missing, botMissing: bot.missing }; } function checkPermsPrefix(message, options) { const guild = message.guild ?? null; const me = guild?.members.me ?? null; const member = guild ? message.member : null; const user = hasAll(member ?? null, options.permissions); const bot = hasAll(me ?? null, options.permissions); return { ok: user.ok && bot.ok, userMissing: user.missing, botMissing: bot.missing }; } /* ------------------------------ Guard wrappers ---------------------------- */ async function enforceSlashGuards(interaction, commandName, options, cooldowns) { if (options.ownerOnly && !isOwner(interaction.user.id)) { await interaction.reply({ content: 'This command is for the bot owner only.', ephemeral: true }); return false; } if (options.devOnly && !isDev(interaction.user.id)) { await interaction.reply({ content: 'This command is for developers only.', ephemeral: true }); return false; } const ctx = checkContext(!!interaction.guild, options); if (!ctx.ok) { await interaction.reply({ content: ctx.message, ephemeral: true }); return false; } const perms = checkPermsSlash(interaction, options); if (!perms.ok) { const parts = []; if (perms.userMissing.length) parts.push(`Missing **user** permissions: \`${perms.userMissing.join(', ')}\``); if (perms.botMissing.length) parts.push(`Missing **bot** permissions: \`${perms.botMissing.join(', ')}\``); await interaction.reply({ content: parts.join('\n'), ephemeral: true }); return false; } if (options.cooldown && options.cooldown > 0) { const remain = await cooldowns.getRemaining(interaction.user.id, commandName); if (remain > 0) { await interaction.reply({ content: `\u23F3 Please wait **${remain}s** before using this command again.`, ephemeral: true }); return false; } await cooldowns.set(interaction.user.id, commandName, options.cooldown); } return true; } async function enforcePrefixGuards(message, commandName, options, cooldowns) { if (options.ownerOnly && !isOwner(message.author.id)) { await message.reply('This command is for the bot owner only.'); return false; } if (options.devOnly && !isDev(message.author.id)) { await message.reply('This command is for developers only.'); return false; } const ctx = checkContext(!!message.guild, options); if (!ctx.ok) { await message.reply(ctx.message); return false; } const perms = checkPermsPrefix(message, options); if (!perms.ok) { const parts = []; if (perms.userMissing.length) parts.push(`Missing **user** permissions: \`${perms.userMissing.join(', ')}\``); if (perms.botMissing.length) parts.push(`Missing **bot** permissions: \`${perms.botMissing.join(', ')}\``); await message.reply(parts.join('\n')); return false; } if (options.cooldown && options.cooldown > 0) { const remain = await cooldowns.getRemaining(message.author.id, commandName); if (remain > 0) { await message.reply(`\u23F3 Please wait **${remain}s** before using this command again.`); return false; } await cooldowns.set(message.author.id, commandName, options.cooldown); } return true; } //# sourceMappingURL=commandGuards.js.map