@ayanaware/bentocord
Version:
Bentocord is a Bento plugin designed to rapidly build fully functional Discord Bots.
147 lines • 5.84 kB
JavaScript
"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