diff options
Diffstat (limited to 'node_modules/discord.js/src/managers/ApplicationCommandManager.js')
-rw-r--r-- | node_modules/discord.js/src/managers/ApplicationCommandManager.js | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/node_modules/discord.js/src/managers/ApplicationCommandManager.js b/node_modules/discord.js/src/managers/ApplicationCommandManager.js new file mode 100644 index 0000000..417afc4 --- /dev/null +++ b/node_modules/discord.js/src/managers/ApplicationCommandManager.js @@ -0,0 +1,263 @@ +'use strict'; + +const { Collection } = require('@discordjs/collection'); +const { makeURLSearchParams } = require('@discordjs/rest'); +const { isJSONEncodable } = require('@discordjs/util'); +const { Routes } = require('discord-api-types/v10'); +const ApplicationCommandPermissionsManager = require('./ApplicationCommandPermissionsManager'); +const CachedManager = require('./CachedManager'); +const { DiscordjsTypeError, ErrorCodes } = require('../errors'); +const ApplicationCommand = require('../structures/ApplicationCommand'); +const PermissionsBitField = require('../util/PermissionsBitField'); + +/** + * Manages API methods for application commands and stores their cache. + * @extends {CachedManager} + */ +class ApplicationCommandManager extends CachedManager { + constructor(client, iterable) { + super(client, ApplicationCommand, iterable); + + /** + * The manager for permissions of arbitrary commands on arbitrary guilds + * @type {ApplicationCommandPermissionsManager} + */ + this.permissions = new ApplicationCommandPermissionsManager(this); + } + + /** + * The cache of this manager + * @type {Collection<Snowflake, ApplicationCommand>} + * @name ApplicationCommandManager#cache + */ + + _add(data, cache, guildId) { + return super._add(data, cache, { extras: [this.guild, guildId] }); + } + + /** + * The APIRouter path to the commands + * @param {Snowflake} [options.id] The application command's id + * @param {Snowflake} [options.guildId] The guild's id to use in the path, + * ignored when using a {@link GuildApplicationCommandManager} + * @returns {string} + * @private + */ + commandPath({ id, guildId } = {}) { + if (this.guild ?? guildId) { + if (id) { + return Routes.applicationGuildCommand(this.client.application.id, this.guild?.id ?? guildId, id); + } + + return Routes.applicationGuildCommands(this.client.application.id, this.guild?.id ?? guildId); + } + + if (id) { + return Routes.applicationCommand(this.client.application.id, id); + } + + return Routes.applicationCommands(this.client.application.id); + } + + /** + * Data that resolves to give an ApplicationCommand object. This can be: + * * An ApplicationCommand object + * * A Snowflake + * @typedef {ApplicationCommand|Snowflake} ApplicationCommandResolvable + */ + + /** + * Data that resolves to the data of an ApplicationCommand + * @typedef {ApplicationCommandData|APIApplicationCommand} ApplicationCommandDataResolvable + */ + + /** + * Options used to fetch data from Discord + * @typedef {Object} BaseFetchOptions + * @property {boolean} [cache=true] Whether to cache the fetched data if it wasn't already + * @property {boolean} [force=false] Whether to skip the cache check and request the API + */ + + /** + * Options used to fetch Application Commands from Discord + * @typedef {BaseFetchOptions} FetchApplicationCommandOptions + * @property {Snowflake} [guildId] The guild's id to fetch commands for, for when the guild is not cached + * @property {LocaleString} [locale] The locale to use when fetching this command + * @property {boolean} [withLocalizations] Whether to fetch all localization data + */ + + /** + * Obtains one or multiple application commands from Discord, or the cache if it's already available. + * @param {Snowflake} [id] The application command's id + * @param {FetchApplicationCommandOptions} [options] Additional options for this fetch + * @returns {Promise<ApplicationCommand|Collection<Snowflake, ApplicationCommand>>} + * @example + * // Fetch a single command + * client.application.commands.fetch('123456789012345678') + * .then(command => console.log(`Fetched command ${command.name}`)) + * .catch(console.error); + * @example + * // Fetch all commands + * guild.commands.fetch() + * .then(commands => console.log(`Fetched ${commands.size} commands`)) + * .catch(console.error); + */ + async fetch(id, { guildId, cache = true, force = false, locale, withLocalizations } = {}) { + if (typeof id === 'object') { + ({ guildId, cache = true, locale, withLocalizations } = id); + } else if (id) { + if (!force) { + const existing = this.cache.get(id); + if (existing) return existing; + } + const command = await this.client.rest.get(this.commandPath({ id, guildId })); + return this._add(command, cache); + } + + const data = await this.client.rest.get(this.commandPath({ guildId }), { + headers: { + 'X-Discord-Locale': locale, + }, + query: makeURLSearchParams({ with_localizations: withLocalizations }), + }); + return data.reduce((coll, command) => coll.set(command.id, this._add(command, cache, guildId)), new Collection()); + } + + /** + * Creates an application command. + * @param {ApplicationCommandDataResolvable} command The command + * @param {Snowflake} [guildId] The guild's id to create this command in, + * ignored when using a {@link GuildApplicationCommandManager} + * @returns {Promise<ApplicationCommand>} + * @example + * // Create a new command + * client.application.commands.create({ + * name: 'test', + * description: 'A test command', + * }) + * .then(console.log) + * .catch(console.error); + */ + async create(command, guildId) { + const data = await this.client.rest.post(this.commandPath({ guildId }), { + body: this.constructor.transformCommand(command), + }); + return this._add(data, true, guildId); + } + + /** + * Sets all the commands for this application or guild. + * @param {ApplicationCommandDataResolvable[]} commands The commands + * @param {Snowflake} [guildId] The guild's id to create the commands in, + * ignored when using a {@link GuildApplicationCommandManager} + * @returns {Promise<Collection<Snowflake, ApplicationCommand>>} + * @example + * // Set all commands to just this one + * client.application.commands.set([ + * { + * name: 'test', + * description: 'A test command', + * }, + * ]) + * .then(console.log) + * .catch(console.error); + * @example + * // Remove all commands + * guild.commands.set([]) + * .then(console.log) + * .catch(console.error); + */ + async set(commands, guildId) { + const data = await this.client.rest.put(this.commandPath({ guildId }), { + body: commands.map(c => this.constructor.transformCommand(c)), + }); + return data.reduce((coll, command) => coll.set(command.id, this._add(command, true, guildId)), new Collection()); + } + + /** + * Edits an application command. + * @param {ApplicationCommandResolvable} command The command to edit + * @param {Partial<ApplicationCommandDataResolvable>} data The data to update the command with + * @param {Snowflake} [guildId] The guild's id where the command registered, + * ignored when using a {@link GuildApplicationCommandManager} + * @returns {Promise<ApplicationCommand>} + * @example + * // Edit an existing command + * client.application.commands.edit('123456789012345678', { + * description: 'New description', + * }) + * .then(console.log) + * .catch(console.error); + */ + async edit(command, data, guildId) { + const id = this.resolveId(command); + if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'command', 'ApplicationCommandResolvable'); + + const patched = await this.client.rest.patch(this.commandPath({ id, guildId }), { + body: this.constructor.transformCommand(data), + }); + return this._add(patched, true, guildId); + } + + /** + * Deletes an application command. + * @param {ApplicationCommandResolvable} command The command to delete + * @param {Snowflake} [guildId] The guild's id where the command is registered, + * ignored when using a {@link GuildApplicationCommandManager} + * @returns {Promise<?ApplicationCommand>} + * @example + * // Delete a command + * guild.commands.delete('123456789012345678') + * .then(console.log) + * .catch(console.error); + */ + async delete(command, guildId) { + const id = this.resolveId(command); + if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'command', 'ApplicationCommandResolvable'); + + await this.client.rest.delete(this.commandPath({ id, guildId })); + + const cached = this.cache.get(id); + this.cache.delete(id); + return cached ?? null; + } + + /** + * Transforms an {@link ApplicationCommandData} object into something that can be used with the API. + * @param {ApplicationCommandDataResolvable} command The command to transform + * @returns {APIApplicationCommand} + * @private + */ + static transformCommand(command) { + if (isJSONEncodable(command)) return command.toJSON(); + + let default_member_permissions; + + if ('default_member_permissions' in command) { + default_member_permissions = command.default_member_permissions + ? new PermissionsBitField(BigInt(command.default_member_permissions)).bitfield.toString() + : command.default_member_permissions; + } + + if ('defaultMemberPermissions' in command) { + default_member_permissions = + command.defaultMemberPermissions !== null + ? new PermissionsBitField(command.defaultMemberPermissions).bitfield.toString() + : command.defaultMemberPermissions; + } + + return { + name: command.name, + name_localizations: command.nameLocalizations ?? command.name_localizations, + description: command.description, + nsfw: command.nsfw, + description_localizations: command.descriptionLocalizations ?? command.description_localizations, + type: command.type, + options: command.options?.map(o => ApplicationCommand.transformOption(o)), + default_member_permissions, + dm_permission: command.dmPermission ?? command.dm_permission, + }; + } +} + +module.exports = ApplicationCommandManager; |