discordx
Version: 
Create a discord bot with TypeScript and Decorators!
1,859 lines (1,827 loc) • 95.7 kB
JavaScript
// src/classes/Mixin/ApplicationCommandMixin.ts
var ApplicationCommandMixin = class {
  constructor(command, instance) {
    this.command = command;
    this.instance = instance;
  }
  get name() {
    return this.command.name;
  }
  get description() {
    return this.command.description;
  }
};
// src/classes/SimpleCommandMessage.ts
import crypto from "crypto";
import { EmbedBuilder } from "discord.js";
var SimpleCommandMessage = class {
  constructor(prefix, argString, message, info, splitter) {
    this.prefix = prefix;
    this.argString = argString;
    this.message = message;
    this.info = info;
    this.splitter = splitter;
  }
  options = [];
  get name() {
    return this.info.name;
  }
  get description() {
    return this.info.description;
  }
  /**
   * Resolve options
   */
  resolveOptions() {
    return this.info.parseParamsEx(this);
  }
  /**
   * Verify that all options are valid
   *
   * @returns
   */
  isValid() {
    return !this.options.includes(null);
  }
  /**
   * Get related commands
   *
   * @returns
   */
  getRelatedCommands() {
    const commandName = this.info.name.split(" ")[0];
    if (!commandName) {
      return [];
    }
    return MetadataStorage.instance.simpleCommands.filter(
      (cmd) => cmd.name.startsWith(commandName) && cmd.name !== this.info.name
    );
  }
  /**
   * Send usage syntax for command
   *
   * @returns
   */
  sendUsageSyntax() {
    const maxLength = !this.info.options.length ? 0 : this.info.options.reduce(
      (a, b) => a.name.length > b.name.length ? a : b
    ).name.length;
    const embed = new EmbedBuilder();
    embed.setColor(crypto.randomInt(654321));
    embed.setTitle("Command Info");
    embed.addFields({ name: "Name", value: this.info.name });
    embed.addFields({ name: "Description", value: this.info.description });
    if (this.info.aliases.length) {
      embed.addFields({ name: "Aliases", value: this.info.aliases.join(", ") });
    }
    embed.addFields({
      name: "Command Usage",
      value: `\`\`\`${this.prefix}${this.name} ${this.info.options.map((op) => `{${op.name}: ${SimpleCommandOptionType[op.type]}}`).join(" ")}\`\`\``
    });
    if (this.info.options.length) {
      embed.addFields({
        name: "Options",
        value: `\`\`\`${this.info.options.map((op) => `${op.name.padEnd(maxLength + 2)}: ${op.description}`).join("\n")}\`\`\``
      });
    }
    return this.message.reply({ embeds: [embed] });
  }
};
// src/Client.ts
import {
  Client as ClientJS
} from "discord.js";
var Client = class _Client extends ClientJS {
  // Core properties
  _botId;
  _isBuilt = false;
  _prefix;
  _simpleCommandConfig;
  _silent;
  _botGuilds = [];
  _guards = [];
  logger;
  // Managers
  applicationCommandManager;
  interactionHandler;
  simpleCommandManager;
  reactionManager;
  debugManager;
  // Core getters/setters
  get botId() {
    return this._botId;
  }
  set botId(value) {
    this._botId = value;
  }
  get silent() {
    return this._silent;
  }
  set silent(value) {
    this._silent = value;
  }
  get guards() {
    return this._guards;
  }
  set guards(value) {
    this._guards = value;
  }
  get prefix() {
    return this._prefix;
  }
  set prefix(value) {
    this._prefix = value;
  }
  get simpleCommandConfig() {
    return this._simpleCommandConfig;
  }
  set simpleCommandConfig(value) {
    this._simpleCommandConfig = value;
  }
  get botGuilds() {
    return this._botGuilds;
  }
  set botGuilds(value) {
    this._botGuilds = value;
  }
  get botResolvedGuilds() {
    return resolveIGuilds(this, void 0, this._botGuilds);
  }
  get instance() {
    return MetadataStorage.instance;
  }
  // Proxy getters to MetadataStorage (static)
  static get applicationCommands() {
    return MetadataStorage.instance.applicationCommands;
  }
  static get applicationCommandSlashes() {
    return MetadataStorage.instance.applicationCommandSlashes;
  }
  static get applicationCommandSlashesFlat() {
    return MetadataStorage.instance.applicationCommandSlashesFlat;
  }
  static get applicationCommandSlashOptions() {
    return MetadataStorage.instance.applicationCommandSlashOptions;
  }
  static get applicationCommandSlashGroups() {
    return MetadataStorage.instance.applicationCommandSlashGroups;
  }
  static get applicationCommandSlashSubGroups() {
    return MetadataStorage.instance.applicationCommandSlashSubGroups;
  }
  static get applicationCommandUsers() {
    return MetadataStorage.instance.applicationCommandUsers;
  }
  static get applicationCommandMessages() {
    return MetadataStorage.instance.applicationCommandMessages;
  }
  static get events() {
    return MetadataStorage.instance.events;
  }
  static get discords() {
    return MetadataStorage.instance.discords;
  }
  static get buttonComponents() {
    return MetadataStorage.instance.buttonComponents;
  }
  static get modalComponents() {
    return MetadataStorage.instance.modalComponents;
  }
  static get selectMenuComponents() {
    return MetadataStorage.instance.selectMenuComponents;
  }
  static get reactions() {
    return MetadataStorage.instance.reactions;
  }
  static get simpleCommands() {
    return MetadataStorage.instance.simpleCommands;
  }
  static get simpleCommandsByName() {
    return MetadataStorage.instance.simpleCommandsByName;
  }
  static get simpleCommandMappedPrefix() {
    return MetadataStorage.instance.simpleCommandMappedPrefix;
  }
  static get instance() {
    return MetadataStorage.instance;
  }
  // Proxy getters to MetadataStorage (instance)
  get applicationCommands() {
    return _Client.applicationCommands;
  }
  get applicationCommandSlashes() {
    return _Client.applicationCommandSlashes;
  }
  get applicationCommandSlashesFlat() {
    return _Client.applicationCommandSlashesFlat;
  }
  get applicationCommandSlashOptions() {
    return _Client.applicationCommandSlashOptions;
  }
  get applicationCommandSlashGroups() {
    return _Client.applicationCommandSlashGroups;
  }
  get applicationCommandSlashSubGroups() {
    return _Client.applicationCommandSlashSubGroups;
  }
  get applicationCommandUsers() {
    return _Client.applicationCommandUsers;
  }
  get applicationCommandMessages() {
    return _Client.applicationCommandMessages;
  }
  get events() {
    return _Client.events;
  }
  get discords() {
    return _Client.discords;
  }
  get buttonComponents() {
    return _Client.buttonComponents;
  }
  get modalComponents() {
    return _Client.modalComponents;
  }
  get selectMenuComponents() {
    return _Client.selectMenuComponents;
  }
  get reactions() {
    return _Client.reactions;
  }
  get simpleCommands() {
    return _Client.simpleCommands;
  }
  get simpleCommandsByName() {
    return _Client.simpleCommandsByName;
  }
  get simpleCommandMappedPrefix() {
    return _Client.simpleCommandMappedPrefix;
  }
  constructor(options) {
    super(options);
    this._silent = options.silent ?? true;
    this._guards = options.guards ?? [];
    this._botGuilds = options.botGuilds ?? [];
    this._botId = options.botId ?? "bot";
    this._prefix = options.simpleCommand?.prefix ?? ["!"];
    this._simpleCommandConfig = options.simpleCommand;
    this.logger = options.logger ?? console;
    this.applicationCommandManager = new ApplicationCommandManager(this);
    this.interactionHandler = new InteractionHandler(this);
    this.simpleCommandManager = new SimpleCommandManager(this);
    this.reactionManager = new ReactionManager(this);
    this.debugManager = new DebugManager(this);
  }
  /**
   * Start bot
   */
  async login(token) {
    await this.build();
    if (!this.silent) {
      this.logger.log(
        `${this.user?.username ?? this.botId} >> connecting discord...
`
      );
    }
    return super.login(token);
  }
  /**
   * Build the client and initialize all systems
   */
  async build() {
    if (this._isBuilt) return;
    this._isBuilt = true;
    await this.instance.build();
    this.instance.eventManager.initEvents(this);
    if (!this.silent) {
      this.debugManager.printDebug();
    }
  }
  // === Application Command Management ===
  async initApplicationCommands(retainDeleted = false) {
    return this.applicationCommandManager.initApplicationCommands(
      retainDeleted
    );
  }
  async clearApplicationCommands(...guilds) {
    return this.applicationCommandManager.clearApplicationCommands(...guilds);
  }
  // === Interaction Handling ===
  executeInteraction(interaction) {
    return this.interactionHandler.executeInteraction(interaction);
  }
  // === Simple Command Management ===
  async parseCommand(message, caseSensitive = false) {
    return this.simpleCommandManager.parseCommand(message, caseSensitive);
  }
  async executeCommand(message, caseSensitive) {
    return this.simpleCommandManager.executeCommand(message, caseSensitive);
  }
  // === Reaction Management ===
  async executeReaction(reaction, user) {
    return this.reactionManager.executeReaction(reaction, user);
  }
  // === Event Management ===
  trigger(options, params) {
    const triggerFn = this.instance.eventManager.trigger(this, options);
    return triggerFn(params);
  }
  /**
   * Bind discordx events to client
   */
  initEvents() {
    this.instance.eventManager.initEvents(this);
  }
  /**
   * Unbind all discordx events initialized by the initEvents method.
   */
  removeEvents() {
    this.instance.eventManager.removeEvents();
  }
  // === Debug ===
  printDebug() {
    this.debugManager.printDebug();
  }
};
// src/decorators/classes/DApplicationCommand.ts
import {
  ApplicationCommandOptionType,
  ApplicationIntegrationType
} from "discord.js";
// src/decorators/classes/Method.ts
import { Decorator } from "@discordx/internal";
var Method = class extends Decorator {
  _discord;
  _guards = [];
  get discord() {
    return this._discord;
  }
  set discord(value) {
    this._discord = value;
  }
  /**
   * Creates an executable function that runs all guards followed by the main method.
   *
   * The execution flow follows this pattern:
   * ```typescript
   * async (params, client) => {
   *   await guard1(params, client, next, sharedData)
   *   await guard2(params, client, next, sharedData)
   *   await guard3(params, client, next, sharedData)
   *   await mainMethod(parsedParams, params, client, sharedData)
   * }
   * ```
   *
   * @returns Function that executes the complete guard chain
   */
  get execute() {
    return (guards, ...params) => {
      const globalGuards = guards.map(
        (guard) => DGuard.create(guard.bind(void 0))
      );
      return this.createGuardChain(globalGuards)(...params);
    };
  }
  /**
   * Gets all guards that will be executed for this method.
   *
   * Combines guards in this order:
   * 1. Global guards from the Discord client
   * 2. Class-level guards from @Discord decorator
   * 3. Method-specific guards from this method
   * 4. The main method itself (as the final "guard")
   */
  get guards() {
    return [
      ...this.discord.guards,
      ...this._guards,
      DGuard.create(this._methodReference?.bind(this._discord.instance))
    ];
  }
  set guards(value) {
    this._guards = value;
  }
  /**
   * Creates a guard execution chain that processes guards sequentially.
   *
   * Each guard receives:
   * - Original parameters (interaction, client, etc.)
   * - Next function to continue the chain
   * - Shared data object for passing data between guards
   *
   * The final method receives:
   * - Parsed parameters (command options, etc.)
   * - Original parameters (interaction, client, etc.)
   * - Shared data object
   *
   * @param globalGuards - Guards to prepend to the execution chain
   * @returns Function that executes the complete guard chain
   */
  createGuardChain(globalGuards) {
    const allGuards = [...globalGuards, ...this.guards];
    const executeNext = async (params, index, sharedData) => {
      const currentGuard = allGuards[index];
      const isLastGuard = index >= allGuards.length - 1;
      let result;
      if (isLastGuard) {
        const parsedParams = await this.parseParams(...params);
        const allArgs = [...parsedParams, ...params, sharedData];
        result = await currentGuard?.fn.apply(null, allArgs);
      } else {
        const nextFn = () => executeNext(params, index + 1, sharedData);
        const allArgs = [...params, nextFn, sharedData];
        result = await currentGuard?.fn.apply(null, allArgs);
      }
      return result ?? sharedData;
    };
    return (...params) => executeNext(params, 0, {});
  }
};
// src/decorators/classes/DApplicationCommand.ts
var DApplicationCommand = class _DApplicationCommand extends Method {
  _botIds;
  _contexts;
  _defaultMemberPermissions;
  _description;
  _descriptionLocalizations;
  _dmPermission;
  _group;
  _guilds;
  _integrationTypes;
  _name;
  _nameLocalizations;
  _nsfw;
  _options = [];
  _subgroup;
  _type;
  get botIds() {
    return this._botIds;
  }
  set botIds(value) {
    this._botIds = value;
  }
  get description() {
    return this._description;
  }
  set description(value) {
    this._description = value;
  }
  get defaultMemberPermissions() {
    return this._defaultMemberPermissions;
  }
  set defaultMemberPermissions(value) {
    this._defaultMemberPermissions = value;
  }
  get dmPermission() {
    return this._dmPermission;
  }
  set dmPermission(value) {
    this._dmPermission = value;
  }
  get contexts() {
    return this._contexts;
  }
  set contexts(value) {
    this._contexts = value;
  }
  get integrationTypes() {
    return this._integrationTypes;
  }
  set integrationTypes(value) {
    this._integrationTypes = value;
  }
  get descriptionLocalizations() {
    return this._descriptionLocalizations;
  }
  set descriptionLocalizations(value) {
    this._descriptionLocalizations = value;
  }
  get group() {
    return this._group;
  }
  set group(value) {
    this._group = value;
  }
  get guilds() {
    return this._guilds;
  }
  set guilds(value) {
    this._guilds = value;
  }
  get name() {
    return this._name;
  }
  set name(value) {
    this._name = value;
  }
  get nameLocalizations() {
    return this._nameLocalizations;
  }
  set nameLocalizations(value) {
    this._nameLocalizations = value;
  }
  get nsfw() {
    return this._nsfw;
  }
  set nsfw(value) {
    this._nsfw = value;
  }
  get options() {
    return this._options;
  }
  set options(value) {
    this._options = value;
  }
  get subgroup() {
    return this._subgroup;
  }
  set subgroup(value) {
    this._subgroup = value;
  }
  get type() {
    return this._type;
  }
  set type(value) {
    this._type = value;
  }
  constructor(data) {
    super();
    this._botIds = data.botIds ?? [];
    this._contexts = data.contexts ?? null;
    this._defaultMemberPermissions = data.defaultMemberPermissions ?? null;
    this._description = data.description;
    this._descriptionLocalizations = data.descriptionLocalizations ?? null;
    this._dmPermission = data.dmPermission ?? true;
    this._guilds = data.guilds ?? [];
    this._integrationTypes = data.integrationTypes ?? [
      ApplicationIntegrationType.GuildInstall
    ];
    this._name = data.name;
    this._nameLocalizations = data.nameLocalizations ?? null;
    this._nsfw = data.nsfw ?? false;
    this._type = data.type;
  }
  static create(data) {
    return new _DApplicationCommand(data);
  }
  isBotAllowed(botId) {
    if (!this.botIds.length) {
      return true;
    }
    return this.botIds.includes(botId);
  }
  async getGuilds(client) {
    const guilds = await resolveIGuilds(client, this, [
      ...client.botGuilds,
      ...this.guilds
    ]);
    return guilds;
  }
  async isGuildAllowed(client, guildId) {
    if (!guildId) {
      return true;
    }
    const guilds = await this.getGuilds(client);
    if (!guilds.length) {
      return true;
    }
    return guilds.includes(guildId);
  }
  toSubCommand() {
    const option = DApplicationCommandOption.create({
      description: this.description,
      descriptionLocalizations: this.descriptionLocalizations,
      name: this.name,
      nameLocalizations: this.nameLocalizations,
      type: ApplicationCommandOptionType.Subcommand
    }).decorate(this.classRef, this.key, this.method, this.from, this.index);
    option.options = this.options;
    return option;
  }
  toJSON() {
    const options = [...this.options].reverse().sort((a, b) => {
      if ((a.type === ApplicationCommandOptionType.Subcommand || a.type === ApplicationCommandOptionType.SubcommandGroup) && (b.type === ApplicationCommandOptionType.Subcommand || b.type === ApplicationCommandOptionType.SubcommandGroup)) {
        return a.name < b.name ? -1 : 1;
      }
      return 0;
    }).map((option) => option.toJSON());
    const data = {
      contexts: this.contexts,
      defaultMemberPermissions: this.defaultMemberPermissions,
      description: this.description,
      descriptionLocalizations: this.descriptionLocalizations,
      dmPermission: this.dmPermission,
      integrationTypes: this.integrationTypes,
      name: this.name,
      nameLocalizations: this.nameLocalizations,
      nsfw: this.nsfw,
      options,
      type: this.type
    };
    return data;
  }
  parseParams(interaction) {
    return Promise.all(
      [...this.options].reverse().map((op) => op.parse(interaction))
    );
  }
};
// src/decorators/classes/DApplicationCommandGroup.ts
import { Decorator as Decorator2 } from "@discordx/internal";
var DApplicationCommandGroup = class _DApplicationCommandGroup extends Decorator2 {
  name;
  root;
  payload;
  constructor(options) {
    super();
    this.name = options.name;
    this.root = options.root;
    this.payload = options.payload;
  }
  static create(options) {
    return new _DApplicationCommandGroup(options);
  }
};
// src/decorators/classes/DApplicationCommandOption.ts
import { Decorator as Decorator3 } from "@discordx/internal";
import {
  ApplicationCommandOptionType as ApplicationCommandOptionType2
} from "discord.js";
var DApplicationCommandOption = class _DApplicationCommandOption extends Decorator3 {
  _autocomplete;
  _channelTypes = void 0;
  _choices = [];
  _description;
  _descriptionLocalizations;
  _name;
  _nameLocalizations;
  _maxValue;
  _minValue;
  _maxLength;
  _minLength;
  _options = [];
  _required = true;
  _type;
  _transformer;
  get autocomplete() {
    return this._autocomplete;
  }
  set autocomplete(value) {
    this._autocomplete = value;
  }
  get channelTypes() {
    return this._channelTypes;
  }
  set channelTypes(value) {
    this._channelTypes = value;
  }
  get choices() {
    return this._choices;
  }
  set choices(value) {
    this._choices = value;
  }
  get description() {
    return this._description;
  }
  set description(value) {
    this._description = value;
  }
  get descriptionLocalizations() {
    return this._descriptionLocalizations;
  }
  set descriptionLocalizations(value) {
    this._descriptionLocalizations = value;
  }
  get isNode() {
    return this.type === ApplicationCommandOptionType2.Subcommand || this.type === ApplicationCommandOptionType2.SubcommandGroup;
  }
  get maxValue() {
    return this._maxValue;
  }
  set maxValue(value) {
    this._maxValue = value;
  }
  get minValue() {
    return this._minValue;
  }
  set minValue(value) {
    this._minValue = value;
  }
  get maxLength() {
    return this._maxLength;
  }
  set maxLength(value) {
    this._maxLength = value;
  }
  get minLength() {
    return this._minLength;
  }
  set minLength(value) {
    this._minLength = value;
  }
  get name() {
    return this._name;
  }
  set name(value) {
    this._name = value;
  }
  get nameLocalizations() {
    return this._nameLocalizations;
  }
  set nameLocalizations(value) {
    this._nameLocalizations = value;
  }
  get options() {
    return this._options;
  }
  set options(value) {
    this._options = value;
  }
  get required() {
    return this._required;
  }
  set required(value) {
    this._required = value;
  }
  get type() {
    return this._type;
  }
  set type(value) {
    this._type = value;
  }
  constructor(data) {
    super();
    this._name = data.name;
    this._autocomplete = data.autocomplete;
    this._channelTypes = data.channelType?.sort();
    this._choices = data.choices ?? [];
    this._description = data.description;
    this._parameterIndex = data.index;
    this._maxValue = data.maxValue;
    this._minValue = data.minValue;
    this._maxLength = data.maxLength;
    this._minLength = data.minLength;
    this._required = data.required ?? false;
    this._type = data.type;
    this._descriptionLocalizations = data.descriptionLocalizations ?? null;
    this._nameLocalizations = data.nameLocalizations ?? null;
    this._transformer = data.transformer;
  }
  static create(data) {
    return new _DApplicationCommandOption(data);
  }
  toJSON() {
    const options = [...this.options].reverse().map((option) => option.toJSON());
    const data = {
      autocomplete: this.autocomplete ? true : void 0,
      channelTypes: this.channelTypes,
      choices: this.isNode ? void 0 : this.choices.length === 0 ? void 0 : this.choices.map((choice) => choice.toJSON()),
      description: this.description,
      descriptionLocalizations: this.descriptionLocalizations,
      maxLength: this.maxLength,
      maxValue: this.maxValue,
      minLength: this.minLength,
      minValue: this.minValue,
      name: this.name,
      nameLocalizations: this.nameLocalizations,
      options: options.length === 0 ? void 0 : options,
      required: this.isNode ? void 0 : this.required,
      type: this.type
    };
    return data;
  }
  parseType(interaction) {
    switch (this.type) {
      case ApplicationCommandOptionType2.Attachment:
        return interaction.options.getAttachment(this.name) ?? void 0;
      case ApplicationCommandOptionType2.String:
        return interaction.options.getString(this.name) ?? void 0;
      case ApplicationCommandOptionType2.Boolean:
        return interaction.options.getBoolean(this.name) ?? void 0;
      case ApplicationCommandOptionType2.Number:
        return interaction.options.getNumber(this.name) ?? void 0;
      case ApplicationCommandOptionType2.Integer:
        return interaction.options.getInteger(this.name) ?? void 0;
      case ApplicationCommandOptionType2.Role:
        return interaction.options.getRole(this.name) ?? void 0;
      case ApplicationCommandOptionType2.Channel:
        return interaction.options.getChannel(this.name) ?? void 0;
      case ApplicationCommandOptionType2.Mentionable:
        return interaction.options.getMentionable(this.name) ?? void 0;
      case ApplicationCommandOptionType2.User:
        return interaction.options.getMember(this.name) ?? interaction.options.getUser(this.name) ?? void 0;
      default:
        return interaction.options.getString(this.name) ?? void 0;
    }
  }
  parse(interaction) {
    if (this._transformer !== void 0) {
      return this._transformer(this.parseType(interaction), interaction);
    }
    return this.parseType(interaction);
  }
};
// src/decorators/classes/DApplicationCommandOptionChoice.ts
import { Decorator as Decorator4 } from "@discordx/internal";
var DApplicationCommandOptionChoice = class _DApplicationCommandOptionChoice extends Decorator4 {
  _name;
  _nameLocalizations;
  _value;
  get name() {
    return this._name;
  }
  set name(value) {
    this._name = value;
  }
  get nameLocalizations() {
    return this._nameLocalizations;
  }
  set nameLocalizations(value) {
    this._nameLocalizations = value;
  }
  get value() {
    return this._value;
  }
  set value(value) {
    this._value = value;
  }
  constructor(data) {
    super();
    this._name = data.name;
    this._nameLocalizations = data.nameLocalizations ?? null;
    this._value = data.value ?? data.name;
  }
  static create(data) {
    return new _DApplicationCommandOptionChoice(data);
  }
  toJSON() {
    return {
      name: this.name,
      nameLocalizations: this.nameLocalizations,
      value: this.value
    };
  }
};
// src/decorators/classes/DComponent.ts
var DComponent = class _DComponent extends Method {
  _type;
  _id;
  _guilds;
  _botIds;
  get type() {
    return this._type;
  }
  get botIds() {
    return this._botIds;
  }
  set botIds(value) {
    this._botIds = value;
  }
  get id() {
    return this._id;
  }
  set id(value) {
    this._id = value;
  }
  get guilds() {
    return this._guilds;
  }
  set guilds(value) {
    this._guilds = value;
  }
  constructor(data) {
    super();
    this._type = data.type;
    this._id = data.id;
    this._guilds = data.guilds ?? [];
    this._botIds = data.botIds ?? [];
  }
  static create(data) {
    return new _DComponent(data);
  }
  isBotAllowed(botId) {
    if (!this.botIds.length) {
      return true;
    }
    return this.botIds.includes(botId);
  }
  async getGuilds(client) {
    const guilds = await resolveIGuilds(client, this, [
      ...client.botGuilds,
      ...this.guilds
    ]);
    return guilds;
  }
  async isGuildAllowed(client, guildId) {
    if (!guildId) {
      return true;
    }
    const guilds = await this.getGuilds(client);
    if (!guilds.length) {
      return true;
    }
    return guilds.includes(guildId);
  }
  isId(text) {
    return typeof this.id === "string" ? this.id === text : this.id.test(text);
  }
  parseParams() {
    return [];
  }
};
// src/decorators/classes/DDiscord.ts
import { DIService } from "@discordx/di";
import { Decorator as Decorator5 } from "@discordx/internal";
var DDiscord = class _DDiscord extends Decorator5 {
  _applicationCommands = [];
  _botIds = [];
  _buttonComponents = [];
  _description;
  _events = [];
  _guards = [];
  _guilds = [];
  _modalComponents = [];
  _name;
  _reactions = [];
  _selectMenuComponents = [];
  _simpleCommands = [];
  get applicationCommands() {
    return this._applicationCommands;
  }
  set applicationCommands(value) {
    this._applicationCommands = value;
  }
  get botIds() {
    return this._botIds;
  }
  set botIds(value) {
    this._botIds = value;
  }
  get buttons() {
    return this._buttonComponents;
  }
  set buttons(value) {
    this._buttonComponents = value;
  }
  get description() {
    return this._description;
  }
  set description(value) {
    this._description = value;
  }
  get events() {
    return this._events;
  }
  set events(value) {
    this._events = value;
  }
  get guards() {
    return this._guards;
  }
  set guards(value) {
    this._guards = value;
  }
  get guilds() {
    return this._guilds;
  }
  set guilds(value) {
    this._guilds = value;
  }
  get instance() {
    return DIService.engine.getService(this.from);
  }
  get modal() {
    return this._modalComponents;
  }
  set modal(value) {
    this._modalComponents = value;
  }
  get name() {
    return this._name;
  }
  set name(value) {
    this._name = value;
  }
  get reactions() {
    return this._reactions;
  }
  set reactions(value) {
    this._reactions = value;
  }
  get selectMenus() {
    return this._selectMenuComponents;
  }
  set selectMenus(value) {
    this._selectMenuComponents = value;
  }
  get simpleCommands() {
    return this._simpleCommands;
  }
  set simpleCommands(value) {
    this._simpleCommands = value;
  }
  constructor(name, description) {
    super();
    this._name = name;
    this._description = description ?? name;
  }
  static create(name, description) {
    return new _DDiscord(name, description);
  }
};
// src/decorators/classes/DGuard.ts
import { Decorator as Decorator6 } from "@discordx/internal";
var DGuard = class _DGuard extends Decorator6 {
  _fn;
  get fn() {
    return this._fn;
  }
  constructor(fn) {
    super();
    this._fn = fn;
  }
  static create(fn) {
    return new _DGuard(fn);
  }
};
// src/decorators/classes/DOn.ts
var DOn = class _DOn extends Method {
  _event;
  _once;
  _rest;
  _priority;
  _botIds;
  get botIds() {
    return this._botIds;
  }
  set botIds(value) {
    this._botIds = value;
  }
  get event() {
    return this._event;
  }
  set event(value) {
    this._event = value;
  }
  get once() {
    return this._once;
  }
  set once(value) {
    this._once = value;
  }
  get priority() {
    return this._priority;
  }
  set priority(value) {
    this._priority = value;
  }
  get rest() {
    return this._rest;
  }
  set rest(value) {
    this._rest = value;
  }
  constructor(data) {
    super();
    this._event = data.event;
    this._once = data.once;
    this._priority = data.priority ?? Number.MAX_SAFE_INTEGER;
    this._rest = data.rest;
    this._botIds = data.botIds ?? [];
  }
  static create(data) {
    return new _DOn(data);
  }
  isBotAllowed(botId) {
    if (!this.botIds.length) {
      return true;
    }
    return this.botIds.includes(botId);
  }
  parseParams() {
    return [];
  }
};
// src/decorators/classes/DReaction.ts
var DReaction = class _DReaction extends Method {
  _emoji;
  _description;
  _directMessage;
  _guilds;
  _botIds;
  _aliases;
  _remove;
  _partial;
  get aliases() {
    return this._aliases;
  }
  set aliases(value) {
    this._aliases = value;
  }
  get botIds() {
    return this._botIds;
  }
  set botIds(value) {
    this._botIds = value;
  }
  get guilds() {
    return this._guilds;
  }
  set guilds(value) {
    this._guilds = value;
  }
  get directMessage() {
    return this._directMessage;
  }
  set directMessage(value) {
    this._directMessage = value;
  }
  get emoji() {
    return this._emoji;
  }
  set emoji(value) {
    this._emoji = value;
  }
  get description() {
    return this._description;
  }
  set description(value) {
    this._description = value;
  }
  get remove() {
    return this._remove;
  }
  set remove(value) {
    this._remove = value;
  }
  get partial() {
    return this._partial;
  }
  set partial(value) {
    this._partial = value;
  }
  constructor(data) {
    super();
    this._emoji = data.emoji;
    this._description = data.description ?? this.emoji;
    this._directMessage = data.directMessage ?? true;
    this._guilds = data.guilds ?? [];
    this._botIds = data.botIds ?? [];
    this._aliases = data.aliases ?? [];
    this._remove = data.remove ?? false;
    this._partial = data.partial ?? false;
  }
  static create(data) {
    return new _DReaction(data);
  }
  isBotAllowed(botId) {
    if (!this.botIds.length) {
      return true;
    }
    return this.botIds.includes(botId);
  }
  async getGuilds(client) {
    const guilds = await resolveIGuilds(client, this, [
      ...client.botGuilds,
      ...this.guilds
    ]);
    return guilds;
  }
  async isGuildAllowed(client, guildId) {
    if (!guildId) {
      return true;
    }
    const guilds = await this.getGuilds(client);
    if (!guilds.length) {
      return true;
    }
    return guilds.includes(guildId);
  }
  parseParams() {
    return [];
  }
};
// src/decorators/classes/DSimpleCommand.ts
import { ChannelType } from "discord.js";
var DSimpleCommand = class _DSimpleCommand extends Method {
  _description;
  _name;
  _prefix;
  _directMessage;
  _argSplitter;
  _options = [];
  _guilds;
  _botIds;
  _aliases;
  get aliases() {
    return this._aliases;
  }
  set aliases(value) {
    this._aliases = value;
  }
  get botIds() {
    return this._botIds;
  }
  set botIds(value) {
    this._botIds = value;
  }
  get prefix() {
    return this._prefix;
  }
  set prefix(value) {
    this._prefix = value;
  }
  get guilds() {
    return this._guilds;
  }
  set guilds(value) {
    this._guilds = value;
  }
  get argSplitter() {
    return this._argSplitter;
  }
  set argSplitter(value) {
    this._argSplitter = value;
  }
  get directMessage() {
    return this._directMessage;
  }
  set directMessage(value) {
    this._directMessage = value;
  }
  get name() {
    return this._name;
  }
  set name(value) {
    this._name = value;
  }
  get description() {
    return this._description;
  }
  set description(value) {
    this._description = value;
  }
  get options() {
    return this._options;
  }
  set options(value) {
    this._options = value;
  }
  constructor(data) {
    super();
    this._name = data.name;
    this._description = data.description ?? this.name;
    this._directMessage = data.directMessage ?? true;
    this._argSplitter = data.argSplitter;
    this._options = [];
    this._prefix = data.prefix;
    this._guilds = data.guilds ?? [];
    this._botIds = data.botIds ?? [];
    this._aliases = data.aliases ?? [];
  }
  static create(data) {
    return new _DSimpleCommand(data);
  }
  isBotAllowed(botId) {
    if (!this.botIds.length) {
      return true;
    }
    return this.botIds.includes(botId);
  }
  async getGuilds(client, command) {
    const guilds = await resolveIGuilds(client, command, [
      ...client.botGuilds,
      ...this.guilds
    ]);
    return guilds;
  }
  async isGuildAllowed(client, command, guildId) {
    if (!guildId) {
      return true;
    }
    const guilds = await this.getGuilds(client, command);
    if (!guilds.length) {
      return true;
    }
    return guilds.includes(guildId);
  }
  parseParams(command) {
    return command.options;
  }
  parseParamsEx(command) {
    if (!this.options.length) {
      return Promise.resolve([]);
    }
    const splitterEx = this.argSplitter ?? command.splitter ?? " ";
    const args = typeof splitterEx === "function" ? splitterEx(command) : command.argString.split(splitterEx).filter((op) => op.length).map((op) => op.trim());
    return Promise.all(
      this.options.sort((a, b) => (a.index ?? 0) - (b.index ?? 0)).map(async (op, index) => {
        const option = args[index];
        const id = option?.replace(/\D/g, "");
        const validId = id !== void 0 && id.length >= 16 && id.length <= 20;
        if (!option?.length) {
          return null;
        }
        if (op.type === 2 /* Boolean */) {
          if (option.toLocaleLowerCase() === "false" || option.toLocaleLowerCase() === "0") {
            return false;
          }
          return Boolean(option);
        }
        if (op.type === 1 /* Number */) {
          return Number(option);
        }
        if (op.type === 4 /* Channel */) {
          if (!validId || !command.message.guild) {
            return null;
          }
          return command.message.guild.channels.fetch(id).catch(() => null);
        }
        if (op.type === 5 /* Role */) {
          if (!validId || !command.message.guild) {
            return null;
          }
          return command.message.guild.roles.fetch(id).catch(() => null);
        }
        if (op.type === 3 /* User */) {
          if (!validId) {
            return null;
          }
          if (command.message.channel.type === ChannelType.DM) {
            if (command.message.client.user.id === id) {
              return command.message.client.user;
            }
            if (command.message.author.id === id) {
              return command.message.author;
            }
            return null;
          }
          if (!command.message.guild) {
            return null;
          }
          return command.message.guild.members.fetch(id).catch(() => null);
        }
        if (op.type === 6 /* Mentionable */) {
          if (!validId) {
            return null;
          }
          if (command.message.channel.type === ChannelType.DM) {
            if (command.message.client.user.id === id) {
              return command.message.client.user;
            }
            if (command.message.author.id === id) {
              return command.message.author;
            }
            return null;
          }
          if (!command.message.guild) {
            return null;
          }
          const member = await command.message.guild.members.fetch(id).catch(() => null);
          if (member) {
            return member;
          }
          const role = await command.message.guild.roles.fetch(id).catch(() => null);
          return role;
        }
        return option;
      })
    );
  }
};
// src/decorators/classes/DSimpleCommandOption.ts
import { Decorator as Decorator7 } from "@discordx/internal";
var DSimpleCommandOption = class _DSimpleCommandOption extends Decorator7 {
  _name;
  _description;
  _type;
  get name() {
    return this._name;
  }
  set name(value) {
    this._name = value;
  }
  get type() {
    return this._type;
  }
  set type(value) {
    this._type = value;
  }
  get description() {
    return this._description;
  }
  set description(value) {
    this._description = value;
  }
  constructor(data) {
    super();
    this._name = data.name;
    this._type = data.type ?? 0 /* String */;
    this._description = data.description ?? SimpleCommandOptionType[this._type].toLowerCase();
  }
  static create(data) {
    return new _DSimpleCommandOption(data);
  }
};
// src/decorators/decorators/Bot.ts
import { Modifier } from "@discordx/internal";
function Bot(...botIds) {
  return function(target, key, descriptor) {
    MetadataStorage.instance.addModifier(
      Modifier.create(
        (original) => {
          original.botIds = [
            ...original.botIds,
            ...botIds.filter((botId) => !original.botIds.includes(botId))
          ];
          if (original instanceof DDiscord) {
            [
              ...original.applicationCommands,
              ...original.simpleCommands,
              ...original.buttons,
              ...original.selectMenus,
              ...original.events
            ].forEach((ob) => {
              ob.botIds = [
                ...ob.botIds,
                ...botIds.filter((botId) => !ob.botIds.includes(botId))
              ];
            });
          }
        },
        DApplicationCommand,
        DSimpleCommand,
        DDiscord,
        DComponent,
        DOn,
        DReaction
      ).attachToTarget(target, key, descriptor)
    );
  };
}
// src/decorators/decorators/ButtonComponent.ts
function ButtonComponent(options) {
  return function(target, key) {
    const button = DComponent.create({
      botIds: options?.botIds,
      guilds: options?.guilds,
      id: options?.id ?? key,
      type: 0 /* Button */
    }).decorate(target.constructor, key, target[key]);
    MetadataStorage.instance.addComponentButton(button);
  };
}
// src/decorators/decorators/ContextMenu.ts
import { ApplicationCommandType } from "discord.js";
function ContextMenu(options) {
  return function(target, key) {
    const applicationCommand = DApplicationCommand.create({
      botIds: options.botIds,
      contexts: options.contexts,
      defaultMemberPermissions: options.defaultMemberPermissions,
      description: "",
      dmPermission: options.dmPermission,
      guilds: options.guilds,
      integrationTypes: options.integrationTypes,
      name: options.name ?? key,
      nameLocalizations: options.nameLocalizations,
      type: options.type
    }).decorate(target.constructor, key, target[key]);
    if (options.type === ApplicationCommandType.Message) {
      MetadataStorage.instance.addApplicationCommandMessage(applicationCommand);
    } else {
      MetadataStorage.instance.addApplicationCommandUser(applicationCommand);
    }
  };
}
// src/decorators/decorators/Discord.ts
function Discord() {
  return function(target) {
    const clazz = target;
    const instance = DDiscord.create(clazz.name).decorate(clazz, clazz.name);
    MetadataStorage.instance.addDiscord(instance);
  };
}
// src/decorators/decorators/Guard.ts
import { Modifier as Modifier2 } from "@discordx/internal";
function Guard(...fns) {
  return function(target, key, descriptor) {
    const guards = fns.map((fn) => {
      return DGuard.create(fn).attachToTarget(
        target,
        key,
        descriptor
      );
    });
    MetadataStorage.instance.addModifier(
      Modifier2.create(
        (original) => {
          original.guards = guards;
        },
        DComponent,
        DApplicationCommand,
        DSimpleCommand,
        DOn,
        DDiscord,
        DReaction
      ).attachToTarget(target, key, descriptor)
    );
  };
}
// src/decorators/decorators/Guild.ts
import { Modifier as Modifier3 } from "@discordx/internal";
function Guild(...guildIds) {
  return function(target, key, descriptor) {
    MetadataStorage.instance.addModifier(
      Modifier3.create(
        (original) => {
          original.guilds = [...original.guilds, ...guildIds];
          if (original instanceof DDiscord) {
            [
              ...original.applicationCommands,
              ...original.simpleCommands,
              ...original.buttons,
              ...original.selectMenus
            ].forEach((obj) => {
              obj.guilds = [...obj.guilds, ...guildIds];
            });
          }
        },
        DApplicationCommand,
        DSimpleCommand,
        DDiscord,
        DComponent,
        DReaction
      ).attachToTarget(target, key, descriptor)
    );
  };
}
// src/decorators/decorators/ModalComponent.ts
function ModalComponent(options) {
  return function(target, key) {
    const button = DComponent.create({
      botIds: options?.botIds,
      guilds: options?.guilds,
      id: options?.id ?? key,
      type: 2 /* Modal */
    }).decorate(target.constructor, key, target[key]);
    MetadataStorage.instance.addComponentModal(button);
  };
}
// src/decorators/decorators/On.ts
function On(options) {
  return function(target, key, descriptor) {
    const clazz = target;
    const on = DOn.create({
      botIds: options?.botIds,
      event: options?.event ?? key,
      once: false,
      priority: options?.priority,
      rest: false
    }).decorate(clazz.constructor, key, descriptor?.value);
    MetadataStorage.instance.addOn(on);
  };
}
On.rest = function(options) {
  return function(target, key, descriptor) {
    const clazz = target;
    const on = DOn.create({
      botIds: options?.botIds,
      event: options?.event ?? key,
      once: false,
      priority: options?.priority,
      rest: true
    }).decorate(clazz.constructor, key, descriptor?.value);
    MetadataStorage.instance.addOn(on);
  };
};
// src/decorators/decorators/Once.ts
function Once(options) {
  return function(target, key, descriptor) {
    const clazz = target;
    const on = DOn.create({
      botIds: options?.botIds,
      event: options?.event ?? key,
      once: true,
      priority: options?.priority,
      rest: false
    }).decorate(clazz.constructor, key, descriptor.value);
    MetadataStorage.instance.addOn(on);
  };
}
Once.rest = function(options) {
  return function(target, key, descriptor) {
    const clazz = target;
    const on = DOn.create({
      botIds: options?.botIds,
      event: options?.event ?? key,
      once: true,
      priority: options?.priority,
      rest: true
    }).decorate(clazz.constructor, key, descriptor?.value);
    MetadataStorage.instance.addOn(on);
  };
};
// src/decorators/decorators/Reaction.ts
function Reaction(options) {
  return function(target, key) {
    const react = DReaction.create({
      aliases: options?.aliases,
      botIds: options?.botIds,
      description: options?.description,
      directMessage: options?.directMessage,
      emoji: options?.emoji ?? key,
      guilds: options?.guilds,
      partial: options?.partial,
      remove: options?.remove
    }).decorate(target.constructor, key, target[key]);
    MetadataStorage.instance.addReaction(react);
  };
}
// src/decorators/decorators/SelectMenuComponent.ts
function SelectMenuComponent(options) {
  return function(target, key) {
    const button = DComponent.create({
      botIds: options?.botIds,
      guilds: options?.guilds,
      id: options?.id ?? key,
      type: 1 /* SelectMenu */
    }).decorate(target.constructor, key, target[key]);
    MetadataStorage.instance.addComponentSelectMenu(button);
  };
}
// src/decorators/decorators/SimpleCommand.ts
function SimpleCommand(options) {
  return function(target, key) {
    const cmd = DSimpleCommand.create({
      aliases: options?.aliases,
      argSplitter: options?.argSplitter,
      botIds: options?.botIds,
      description: options?.description,
      directMessage: options?.directMessage,
      guilds: options?.guilds,
      name: options?.name ?? key,
      prefix: options?.prefix
    }).decorate(target.constructor, key, target[key]);
    MetadataStorage.instance.addSimpleCommand(cmd);
  };
}
// src/decorators/decorators/SimpleCommandOption.ts
import { Modifier as Modifier4 } from "@discordx/internal";
function SimpleCommandOption(options) {
  return function(target, key, index) {
    const option = DSimpleCommandOption.create(options).decorate(
      target.constructor,
      key,
      target[key],
      target.constructor,
      index
    );
    MetadataStorage.instance.addModifier(
      Modifier4.create((original) => {
        original.options = [...original.options, option];
      }, DSimpleCommand).decorate(
        target.constructor,
        key,
        target[key],
        target.constructor,
        index
      )
    );
    MetadataStorage.instance.addSimpleCommandOption(option);
  };
}
// src/decorators/decorators/Slash.ts
import { ApplicationCommandType as ApplicationCommandType2, SlashCommandBuilder } from "discord.js";
function Slash(options) {
  return function(target, key) {
    const name = options.name ?? key;
    SlashNameValidator(name);
    let applicationCommand;
    if (options instanceof SlashCommandBuilder) {
      if (options.options.length > 0) {
        throw Error(
          "The builder options feature is not supported in discordx."
        );
      }
      applicationCommand = DApplicationCommand.create({
        defaultMemberPermissions: options.default_member_permissions,
        description: options.description,
        descriptionLocalizations: options.description_localizations,
        // eslint-disable-next-line @typescript-eslint/no-deprecated
        dmPermission: options.dm_permission ?? true,
        contexts: options.contexts,
        integrationTypes: options.integration_types,
        name,
        nameLocalizations: options.name_localizations,
        nsfw: options.nsfw,
        type: ApplicationCommandType2.ChatInput
      });
    } else {
      applicationCommand = DApplicationCommand.create({
        botIds: options.botIds,
        defaultMemberPermissions: options.defaultMemberPermissions,
        description: options.description,
        descriptionLocalizations: options.descriptionLocalizations,
        dmPermission: options.dmPermission ?? true,
        contexts: options.contexts,
        integrationTypes: options.integrationTypes,
        guilds: options.guilds,
        name,
        nameLocalizations: options.nameLocalizations,
        nsfw: options.nsfw,
        type: ApplicationCommandType2.ChatInput
      });
    }
    applicationCommand.decorate(target.constructor, key, target[key]);
    MetadataStorage.instance.addApplicationCommandSlash(applicationCommand);
  };
}
// src/decorators/decorators/SlashChoice.ts
import { Modifier as Modifier5 } from "@discordx/internal";
function SlashChoice(...choices) {
  return function(target, key, index) {
    MetadataStorage.instance.addModifier(
      Modifier5.create((original) => {
        const allChoices = choices.map((choice) => {
          const resolveChoice = typeof choice === "number" ? { name: choice.toString(), value: choice } : typeof choice === "string" ? { name: choice, value: choice } : choice;
          return DApplicationCommandOptionChoice.create(resolveChoice);
        });
        original.choices = [...allChoices, ...original.choices];
      }, DApplicationCommandOption).decorate(
        target.constructor,
        key,
        target[key],
        target.constructor,
        index
      )
    );
  };
}
// src/decorators/decorators/SlashGroup.ts
import {
  Modifier as Modifier6
} from "@discordx/internal";
function SlashGroup(options, root) {
  return function(target, key, descriptor) {
    if (typeof options === "string") {
      MetadataStorage.instance.addModifier(
        Modifier6.create(
          (original) => {
            if (original instanceof DDiscord) {
              [...original.applicationCommands].forEach((obj) => {
                obj.group = root ?? options;
                obj.subgroup = root ? options : void 0;
              });
            } else {
              original.group = root ?? options;
              original.subgroup = root ? options : void 0;
            }
          },
          DApplicationCommand,
          DDiscord
        ).attachToTarget(target, key, descriptor)
      );
    } else {
      SlashNameValidator(options.name);
      const clazz = target;
      if (options.root) {
        MetadataStorage.instance.addApplicationCommandSlashSubGroups(
          DApplicationCommandGroup.create({
            name: options.name,
            payload: {
              description: options.description,
              descriptionLocalizations: options.descriptionLocalizations,
              nameLocalizations: options.nameLocalizations
            },
            root: options.root
          }).decorate(clazz, clazz.name)
        );
      } else {
        MetadataStorage.instance.addApplicationCommandSlashGroups(
          DApplicationCommandGroup.create({
            name: options.name,
            payload: {
              contexts: options.contexts,
              defaultMemberPermissions: options.defaultMemberPermissions,
              description: options.description,
              descriptionLocalizations: options.descriptionLocalizations,
              dmPermission: options.dmPermission,
              integrationTypes: options.integrationTypes,
              nameLocalizations: options.nameLocalizations
            }
          }).decorate(clazz, key ?? clazz.name)
        );
      }
    }
  };
}
// src/decorators/decorators/SlashOption.ts
import { Modifier as Modifier7 } from "@discordx/internal";
import {
  SlashCommandAttachmentOption,
  SlashCommandBooleanOption,
  SlashCommandChannelOption,
  SlashCommandIntegerOption,
  SlashCommandMen