structures/Client.js

const discord = require("discord.js");
const CommandHandler = require("./handler");
const CommandLoader = require("./loader");

/**
 * Discord.js command handler made by myself
 * @extends {Client}
 */
class ModzClient extends discord.Client {
  /**
   * Options for a Client
   * @typedef {ModzClientOptions} ModzClientOptions
   * @property {string} [owner] - The owner of the client
   * @property {string} [prefix] - The prefix used for the client
   * @property {boolean} [selfbot=false] - Whether the client is in selfbot mode
   * @property {boolean} [logging=false] - Whether the client should log mentions
   * @property {string} [logchannel] - The channel to log mentions in, if the option logging is enabled
   */

  /**
   * @param {ModzClientOptions} [options] - Options for the client
   */
  constructor(options) {
    if (typeof options.owner === "undefined") throw new Error("A bot owner must be provided");
    if (typeof options.prefix === "undefined") throw new Error("A prefix must be provided");
    if (typeof options.selfbot === "undefined") options.selfbot = false;
    if (typeof options.logging === "undefined") options.logging = false;
    if (options.logging && typeof options.logchannel === "undefined") throw new Error("A logging channel must be provided.");

    super(options);

    /**
     * The command database of the client
     * @type {Collection}
     */
    this.loader = new CommandLoader(this);

    /**
     * The command handler
     * @type {CommandHandler}
     */
    this.handler = new CommandHandler(this, this.commandDatabase);

    /**
     * The command prefix
     * @type {string}
     */
    this.commandPrefix = options.prefix;

    /**
     * The client owner
     * @type {string}
     */
    this.owner = options.owner;

    if (options.logging) {
      this.once("ready", () => {
        // Check if the logging channel exists
        if (!this.channels.has(this.options.logchannel)) {
          throw new TypeError("The supplied logging channel is an invalid channel or does not exist.");
        }
      });
    }

    if (options.owner) {
      this.once("ready", () => {
        this.users.fetch(options.owner).catch(err => {
          this.emit("warn", `Unable to fetch owner ${options.owner}.`);
          this.emit("error", err);
        });
      });
    }

    // Handle the messages
    this.on("message", msg => {
      this.handler.handleCommand(msg);
    });
  }
}

module.exports = ModzClient;