structures/handler.js

const discord = require("discord.js");
const logger = require("./Logger");
const { stripIndents } = require("common-tags");
/** The command handler for the client */
class CommandHandler {
  /**
   * @param {ModzClient} client - The client this command handler is for
   * @param {CommandDatabase} commandDatabase - The commands the handler will use
   */
  constructor(client, commandDatabase) {
    /**
     * The client this command handler is for
     * @name CommandHandler#client
     * @type {ModzClient}
     * @readonly
     */
    Object.defineProperty(this, "client", { value: client });

    /**
     * The command collection the handler uses
     * @type {Collection}
     */
    this.commandDatabase = commandDatabase;
  }
  // eslint-disable-next-line valid-jsdoc
  /**
   * Handle a new message or a message update
   * @param {Message} msg - The message to handle
   * @return {Promise<void>}
   * @private
   */
  async handleCommand(msg) {
    // Logging
    if (this.client.options.logging
        && (msg.mentions.users.first() || msg.mentions.roles.first() || msg.mentions.everyone)
        && (msg.mentions.users.has(this.client.user.id) || msg.mentions.everyone)) { this.handleLogging(msg); }

    // Check if it should handle the message if it doesn't contain a ClientUser mention
    if (!this.shouldHandleCommand(msg)) return;

    // Shortcut to the prefix
    let prefix = this.client.commandPrefix; // eslint-disable-line prefer-destructuring

    // Get the arguments from the message
    const args = this.constructor.createParams(msg);

    // Get the command from the message
    const command = this.constructor.getCommand(msg, prefix);

    // Check if the command exists in the commands collection
    let cmd;
    if (this.client.loader.commands.has(command)) {
      cmd = this.client.loader.commands.get(command);
    } else if (this.client.loader.aliases.has(command)) {
      cmd = this.client.loader.commands.get(this.client.loader.aliases.get(command));
    }
    if (cmd) {
      try {
        /**
        * Emitted when running a command
        * @event ModzClient#commandRun
        * @param {Command} command - Command that is being run
        * @param {Message} message - Command message that the command is running from
        * @param {Object|string|string[]} args - Arguments for the command
        */
        this.client.emit("commandRun", cmd, msg, args);
        await cmd.run(msg, args, prefix);
      } catch (error) {
        /**
        * Emitted when an error occurs while running a command
        * @event ModzClient#commandError
        * @param {Error} error - The occurred error
        * @param {Command} command - Command that is being run
        * @param {Message} message - Command message that the command is running from
        * @param {Object|string|string[]} args - Arguments for the command
        */
        this.client.emit("commandError", error, cmd, msg, args);
      }
    }
  }
  /**
   * Check whether a message should be handled
   * @param {Message} msg - The message to handle
   * @return {boolean}
   * @private
   */
  shouldHandleCommand(msg) {
    if (msg.author.bot) return false;
    if (this.client.options.selfbot && msg.author.id !== this.client.user.id) return false;
    if (!msg.content.startsWith(this.client.commandPrefix)) return false;

    return true;
  }
  /**
   * Handles mention logging
   * @param {Message} msg - The message to handle
   * @private
   */
  handleLogging(msg) {
    this.client.channels.get(this.client.options.logchannel)
      .send(new discord.MessageEmbed()
        .setAuthor(`${msg.author.tag} (${msg.author.id})`, msg.author.displayAvatarURL())
        .setTitle(`Mentioned in ${msg.guild.name} (${msg.guild.id})`)
        .setDescription(msg.content)
        .setTimestamp(new Date())
      )
      .catch(err => logger.error(`[DISCORD] ${err}`));
    logger.info(stripIndents`
        Mentioned by: ${msg.author.tag} (${msg.author.id})
        Server: ${msg.guild.name} (${msg.guild.id}) 
        Message content: (${msg.content})
    `);
  }
  /**
   * Gets the arguments from a command message
   * @param {Message} message - The message to handle
   * @return {string[]}
   * @private
   */
  static createParams(message) {
    const params = message.content.split(" ").slice(1);
    return params;
  }
  /**
   * Gets the command from a message
   * @param {Message} message - The message to handle
   * @param {string} prefix - The client's prefix
   * @return {string}
   * @private
   */
  static getCommand(message, prefix) {
    const command = message.content.split(" ")[0].slice(prefix.length).toLowerCase();
    return command;
  }
}

module.exports = CommandHandler;