UNPKG

@ayanaware/bentocord

Version:

Bentocord is a Bento plugin designed to rapidly build fully functional Discord Bots.

147 lines 5.84 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Prompt = exports.TEXT_CLOSE = void 0; const eris_1 = require("eris"); const CommandManager_1 = require("../commands/constants/CommandManager"); const ComponentOperation_1 = require("../components/ComponentOperation"); const DiscordPermission_1 = require("../discord/constants/DiscordPermission"); const { MessageFlags } = eris_1.Constants; exports.TEXT_CLOSE = ['exit', 'x', 'close', 'c', ':q']; class Prompt extends ComponentOperation_1.ComponentOperation { constructor(ctx, validator, options = {}) { super(ctx); this.hasHandler = false; this.selfMessages = []; this.attempts = 0; // using entity name to prevent circular depends this.pm = ctx.api.getEntity('@ayanaware/bentocord:PromptManager'); if (validator) this.validator = validator; this.options = options; } async render() { // add handler if need be if (!this.hasHandler) { await this.pm.addPrompt(this.ctx.channelId, this.ctx.userId, this.handleResponse.bind(this), this.cleanup.bind(this)); this.hasHandler = true; } return super.render(); } async handleInteraction(ctx) { // constrain interaction to prompt owner if (ctx.userId !== this.ctx.userId) { await ctx.createResponse({ content: 'This component does not belong to you', flags: MessageFlags.EPHEMERAL, }); return; } return super.handleInteraction(ctx); } async handleResponse(response, message) { // delete message if we have one and can const deleteMessage = async () => { const hasManage = this.ctx.selfHasPermission(DiscordPermission_1.DiscordPermission.MANAGE_MESSAGES); if (message && hasManage) { try { await message.delete(); } catch { /* NO-OP */ } } }; const close = exports.TEXT_CLOSE.some(c => c.toLocaleLowerCase() === response.toLocaleLowerCase()); if (close) { // User requested close await deleteMessage(); await this.cleanup(); this.reject(CommandManager_1.NON_ERROR_HALT); return; } // no validator, just resolve if (typeof this.validator !== 'function') { await deleteMessage(); await this.cleanup(); return this.resolve(); } try { const [result, value] = await this.validator(response) ?? []; // a non-boolean result means we just fully ignore the message, no refresh, no resolve, no error if (typeof result !== 'boolean') return; // passed validator, resolve if (result) { await deleteMessage(); await this.cleanup(); return this.resolve(value); } // failed validator, display error and refresh timeout this.refreshTimeout(); // max attempts if (++this.attempts >= 3) { await this.close({ key: 'BENTOCORD_PROMPT_CANCELED_MAX_ATTEMPTS', backup: 'Max invalid attempts reached.' }); return this.reject(CommandManager_1.NON_ERROR_HALT); } const content = await this.ctx.formatTranslation('BENTOCORD_PROMPT_VALIDATE_ERROR', {}, 'Failed to validate input. Please try again'); const errorMessage = await this.ctx.createMessage({ content }); // auto-delete errorMessage setTimeout(() => { errorMessage.delete().catch(e => { }); }, 3 * 1000); } catch (e) { await this.close(e.toString()); this.reject(e); } } async handleTimeout() { await this.close({ key: 'BENTOCORD_PROMPT_CANCELED_TIMEOUT', backup: 'You took too much time to respond.' }); this.reject(new Error('Timeout')); } async start() { return super.start(); } async close(reason) { // Handle close reason, respect PromptOptions if (reason) { if (typeof reason === 'object') reason = await this.ctx.formatTranslation(reason); if (this.options.showCloseError) { if (this.options.closeErrorFollowup) await this.ctx.createMessage(reason); else this.content(reason); } } await this.cleanup(); this.reject(CommandManager_1.NON_ERROR_HALT); } async cleanup() { // detach handler if (this.hasHandler) await this.pm.removePrompt(this.ctx.channelId, this.ctx.userId); // Remove components this.clearRows(); // cleanup components, final render, timeouts, etc await super.cleanup(); // clean up selfMessages if (this.selfMessages.length > 0) { const client = this.ctx.discord.client; if (this.ctx.selfHasPermission(DiscordPermission_1.DiscordPermission.MANAGE_MESSAGES)) { const messageIds = this.selfMessages.map(m => m.id); await client.deleteMessages(this.ctx.channelId, messageIds); } else { // No manage message, attempt to delete one by one for (const message of this.selfMessages) { try { await message.delete(); } catch { /* NO-OP */ } } } this.selfMessages = []; } } } exports.Prompt = Prompt; //# sourceMappingURL=Prompt.js.map