discord-akairo
Version:
A highly customizable bot framework for Discord.js.
173 lines (152 loc) • 5.71 kB
JavaScript
const { APIMessage, Collection } = require('discord.js');
/**
* Command utilies.
* @param {CommandHandler} handler - The command handler.
* @param {Message} message - Message that triggered the command.
*/
class CommandUtil {
constructor(handler, message) {
/**
* The command handler.
* @type {CommandHandler}
*/
this.handler = handler;
/**
* Message that triggered the command.
* @type {Message}
*/
this.message = message;
/**
* The parsed components.
* @type {?ParsedComponentData}
*/
this.parsed = null;
/**
* Whether or not the last response should be edited.
* @type {boolean}
*/
this.shouldEdit = false;
/**
* The last response sent.
* @type {?Message}
*/
this.lastResponse = null;
if (this.handler.storeMessages) {
/**
* Messages stored from prompts and prompt replies.
* @type {Collection<Snowflake, Message>}
*/
this.messages = new Collection();
} else {
this.messages = null;
}
}
/**
* Sets the last repsonse.
* @param {Message|Message[]} message - Message to set.
* @returns {Message}
*/
setLastResponse(message) {
if (Array.isArray(message)) {
this.lastResponse = message.slice(-1)[0];
} else {
this.lastResponse = message;
}
return this.lastResponse;
}
/**
* Adds client prompt or user reply to messages.
* @param {Message|Message[]} message - Message to add.
* @returns {Message|Message[]}
*/
addMessage(message) {
if (this.handler.storeMessages) {
if (Array.isArray(message)) {
for (const msg of message) {
this.messages.set(msg.id, msg);
}
} else {
this.messages.set(message.id, message);
}
}
return message;
}
/**
* Changes if the message should be edited.
* @param {boolean} state - Change to editable or not.
* @returns {CommandUtil}
*/
setEditable(state) {
this.shouldEdit = Boolean(state);
return this;
}
/**
* Sends a response or edits an old response if available.
* @param {StringResolvable} [content=''] - Content to send.
* @param {MessageOptions|MessageAdditions} [options={}] - Options to use.
* @returns {Promise<Message|Message[]>}
*/
async send(content, options) {
const transformedOptions = this.constructor.transformOptions(content, options);
const hasFiles = (transformedOptions.files && transformedOptions.files.length > 0)
|| (transformedOptions.embed && transformedOptions.embed.files && transformedOptions.embed.files.length > 0);
if (this.shouldEdit && (this.command ? this.command.editable : true) && !hasFiles && !this.lastResponse.deleted && !this.lastResponse.attachments.size) {
return this.lastResponse.edit(transformedOptions);
}
const sent = await this.message.channel.send(transformedOptions);
const lastSent = this.setLastResponse(sent);
this.setEditable(!lastSent.attachments.size);
return sent;
}
/**
* Sends a response, overwriting the last response.
* @param {StringResolvable} [content=''] - Content to send.
* @param {MessageOptions|MessageAdditions} [options={}] - Options to use.
* @returns {Promise<Message|Message[]>}
*/
async sendNew(content, options) {
const sent = await this.message.channel.send(this.constructor.transformOptions(content, options));
const lastSent = this.setLastResponse(sent);
this.setEditable(!lastSent.attachments.size);
return sent;
}
/**
* Sends a response with a mention concantenated to it.
* @param {StringResolvable} [content=''] - Content to send.
* @param {MessageOptions|MessageAdditions} [options={}] - Options to use.
* @returns {Promise<Message|Message[]>}
*/
reply(content, options) {
return this.send(this.constructor.transformOptions(content, options, { reply: this.message.member || this.message.author }));
}
/**
* Edits the last response.
* @param {StringResolvable} [content=''] - Content to send.
* @param {MessageEditOptions|MessageEmbed} [options={}] - Options to use.
* @returns {Promise<Message>}
*/
edit(content, options) {
return this.lastResponse.edit(content, options);
}
/**
* Transform options for sending.
* @param {StringResolvable} [content=''] - Content to send.
* @param {MessageOptions|MessageAdditions} [options={}] - Options to use.
* @param {MessageOptions} [extra={}] - Extra options to add.
* @returns {MessageOptions}
*/
static transformOptions(content, options, extra) {
const transformedOptions = APIMessage.transformOptions(content, options, extra);
if (!transformedOptions.content) transformedOptions.content = null;
if (!transformedOptions.embed) transformedOptions.embed = null;
return transformedOptions;
}
}
module.exports = CommandUtil;
/**
* Extra properties applied to the Discord.js message object.
* @typedef {Object} MessageExtensions
* @prop {?CommandUtil} util - Utilities for command responding.
* Available on all messages after 'all' inhibitors and built-in inhibitors (bot, client).
* Not all properties of the util are available, depending on the input.
*/