feat: initial Papo bot scaffold
This commit is contained in:
46
node_modules/discord.js/src/structures/ActionRow.js
generated
vendored
Normal file
46
node_modules/discord.js/src/structures/ActionRow.js
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
'use strict';
|
||||
|
||||
const { deprecate } = require('node:util');
|
||||
const { isJSONEncodable } = require('@discordjs/util');
|
||||
const Component = require('./Component');
|
||||
const { createComponent } = require('../util/Components');
|
||||
|
||||
/**
|
||||
* Represents an action row
|
||||
* @extends {Component}
|
||||
*/
|
||||
class ActionRow extends Component {
|
||||
constructor({ components, ...data }) {
|
||||
super(data);
|
||||
|
||||
/**
|
||||
* The components in this action row
|
||||
* @type {Component[]}
|
||||
* @readonly
|
||||
*/
|
||||
this.components = components.map(component => createComponent(component));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new action row builder from JSON data
|
||||
* @method from
|
||||
* @memberof ActionRow
|
||||
* @param {ActionRowBuilder|ActionRow|APIActionRowComponent} other The other data
|
||||
* @returns {ActionRowBuilder}
|
||||
* @deprecated Use {@link ActionRowBuilder.from | ActionRowBuilder#from} instead.
|
||||
*/
|
||||
static from = deprecate(
|
||||
other => new this(isJSONEncodable(other) ? other.toJSON() : other),
|
||||
'ActionRow.from() is deprecated. Use ActionRowBuilder.from() instead.',
|
||||
);
|
||||
|
||||
/**
|
||||
* Returns the API-compatible JSON for this component
|
||||
* @returns {APIActionRowComponent}
|
||||
*/
|
||||
toJSON() {
|
||||
return { ...this.data, components: this.components.map(component => component.toJSON()) };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ActionRow;
|
||||
35
node_modules/discord.js/src/structures/ActionRowBuilder.js
generated
vendored
Normal file
35
node_modules/discord.js/src/structures/ActionRowBuilder.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
'use strict';
|
||||
|
||||
const { ActionRowBuilder: BuildersActionRow } = require('@discordjs/builders');
|
||||
const { isJSONEncodable } = require('@discordjs/util');
|
||||
const { createComponentBuilder } = require('../util/Components');
|
||||
const { toSnakeCase } = require('../util/Transformers');
|
||||
|
||||
/**
|
||||
* Represents an action row builder.
|
||||
* @extends {BuildersActionRow}
|
||||
*/
|
||||
class ActionRowBuilder extends BuildersActionRow {
|
||||
constructor({ components, ...data } = {}) {
|
||||
super({
|
||||
...toSnakeCase(data),
|
||||
components: components?.map(component => createComponentBuilder(component)),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new action row builder from JSON data
|
||||
* @param {ActionRow|ActionRowBuilder|APIActionRowComponent} other The other data
|
||||
* @returns {ActionRowBuilder}
|
||||
*/
|
||||
static from(other) {
|
||||
return new this(isJSONEncodable(other) ? other.toJSON() : other);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ActionRowBuilder;
|
||||
|
||||
/**
|
||||
* @external BuildersActionRow
|
||||
* @see {@link https://discord.js.org/docs/packages/builders/stable/ActionRowBuilder:Class}
|
||||
*/
|
||||
97
node_modules/discord.js/src/structures/AnonymousGuild.js
generated
vendored
Normal file
97
node_modules/discord.js/src/structures/AnonymousGuild.js
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
'use strict';
|
||||
|
||||
const BaseGuild = require('./BaseGuild');
|
||||
|
||||
/**
|
||||
* Bundles common attributes and methods between {@link Guild} and {@link InviteGuild}
|
||||
* @extends {BaseGuild}
|
||||
* @abstract
|
||||
*/
|
||||
class AnonymousGuild extends BaseGuild {
|
||||
constructor(client, data, immediatePatch = true) {
|
||||
super(client, data);
|
||||
if (immediatePatch) this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
if ('features' in data) this.features = data.features;
|
||||
|
||||
if ('splash' in data) {
|
||||
/**
|
||||
* The hash of the guild invite splash image
|
||||
* @type {?string}
|
||||
*/
|
||||
this.splash = data.splash;
|
||||
}
|
||||
|
||||
if ('banner' in data) {
|
||||
/**
|
||||
* The hash of the guild banner
|
||||
* @type {?string}
|
||||
*/
|
||||
this.banner = data.banner;
|
||||
}
|
||||
|
||||
if ('description' in data) {
|
||||
/**
|
||||
* The description of the guild, if any
|
||||
* @type {?string}
|
||||
*/
|
||||
this.description = data.description;
|
||||
}
|
||||
|
||||
if ('verification_level' in data) {
|
||||
/**
|
||||
* The verification level of the guild
|
||||
* @type {GuildVerificationLevel}
|
||||
*/
|
||||
this.verificationLevel = data.verification_level;
|
||||
}
|
||||
|
||||
if ('vanity_url_code' in data) {
|
||||
/**
|
||||
* The vanity invite code of the guild, if any
|
||||
* @type {?string}
|
||||
*/
|
||||
this.vanityURLCode = data.vanity_url_code;
|
||||
}
|
||||
|
||||
if ('nsfw_level' in data) {
|
||||
/**
|
||||
* The NSFW level of this guild
|
||||
* @type {GuildNSFWLevel}
|
||||
*/
|
||||
this.nsfwLevel = data.nsfw_level;
|
||||
}
|
||||
|
||||
if ('premium_subscription_count' in data) {
|
||||
/**
|
||||
* The total number of boosts for this server
|
||||
* @type {?number}
|
||||
*/
|
||||
this.premiumSubscriptionCount = data.premium_subscription_count;
|
||||
} else {
|
||||
this.premiumSubscriptionCount ??= null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL to this guild's banner.
|
||||
* @param {ImageURLOptions} [options={}] Options for the image URL
|
||||
* @returns {?string}
|
||||
*/
|
||||
bannerURL(options = {}) {
|
||||
return this.banner && this.client.rest.cdn.banner(this.id, this.banner, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL to this guild's invite splash image.
|
||||
* @param {ImageURLOptions} [options={}] Options for the image URL
|
||||
* @returns {?string}
|
||||
*/
|
||||
splashURL(options = {}) {
|
||||
return this.splash && this.client.rest.cdn.splash(this.id, this.splash, options);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AnonymousGuild;
|
||||
639
node_modules/discord.js/src/structures/ApplicationCommand.js
generated
vendored
Normal file
639
node_modules/discord.js/src/structures/ApplicationCommand.js
generated
vendored
Normal file
@@ -0,0 +1,639 @@
|
||||
'use strict';
|
||||
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const { ApplicationCommandOptionType } = require('discord-api-types/v10');
|
||||
const isEqual = require('fast-deep-equal');
|
||||
const Base = require('./Base');
|
||||
const ApplicationCommandPermissionsManager = require('../managers/ApplicationCommandPermissionsManager');
|
||||
const PermissionsBitField = require('../util/PermissionsBitField');
|
||||
|
||||
/**
|
||||
* Represents an application command.
|
||||
* @extends {Base}
|
||||
*/
|
||||
class ApplicationCommand extends Base {
|
||||
constructor(client, data, guild, guildId) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The command's id
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The parent application's id
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.applicationId = data.application_id;
|
||||
|
||||
/**
|
||||
* The guild this command is part of
|
||||
* @type {?Guild}
|
||||
*/
|
||||
this.guild = guild ?? null;
|
||||
|
||||
/**
|
||||
* The guild's id this command is part of, this may be non-null when `guild` is `null` if the command
|
||||
* was fetched from the `ApplicationCommandManager`
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.guildId = guild?.id ?? guildId ?? null;
|
||||
|
||||
/**
|
||||
* The manager for permissions of this command on its guild or arbitrary guilds when the command is global
|
||||
* @type {ApplicationCommandPermissionsManager}
|
||||
*/
|
||||
this.permissions = new ApplicationCommandPermissionsManager(this);
|
||||
|
||||
/**
|
||||
* The type of this application command
|
||||
* @type {ApplicationCommandType}
|
||||
*/
|
||||
this.type = data.type;
|
||||
|
||||
/**
|
||||
* Whether this command is age-restricted (18+)
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.nsfw = data.nsfw ?? false;
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
if ('name' in data) {
|
||||
/**
|
||||
* The name of this command
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
}
|
||||
|
||||
if ('name_localizations' in data) {
|
||||
/**
|
||||
* The name localizations for this command
|
||||
* @type {?LocalizationMap}
|
||||
*/
|
||||
this.nameLocalizations = data.name_localizations;
|
||||
} else {
|
||||
this.nameLocalizations ??= null;
|
||||
}
|
||||
|
||||
if ('name_localized' in data) {
|
||||
/**
|
||||
* The localized name for this command
|
||||
* @type {?string}
|
||||
*/
|
||||
this.nameLocalized = data.name_localized;
|
||||
} else {
|
||||
this.nameLocalized ??= null;
|
||||
}
|
||||
|
||||
if ('description' in data) {
|
||||
/**
|
||||
* The description of this command
|
||||
* @type {string}
|
||||
*/
|
||||
this.description = data.description;
|
||||
}
|
||||
|
||||
if ('description_localizations' in data) {
|
||||
/**
|
||||
* The description localizations for this command
|
||||
* @type {?LocalizationMap}
|
||||
*/
|
||||
this.descriptionLocalizations = data.description_localizations;
|
||||
} else {
|
||||
this.descriptionLocalizations ??= null;
|
||||
}
|
||||
|
||||
if ('description_localized' in data) {
|
||||
/**
|
||||
* The localized description for this command
|
||||
* @type {?string}
|
||||
*/
|
||||
this.descriptionLocalized = data.description_localized;
|
||||
} else {
|
||||
this.descriptionLocalized ??= null;
|
||||
}
|
||||
|
||||
if ('options' in data) {
|
||||
/**
|
||||
* The options of this command
|
||||
* @type {ApplicationCommandOption[]}
|
||||
*/
|
||||
this.options = data.options.map(option => this.constructor.transformOption(option, true));
|
||||
} else {
|
||||
this.options ??= [];
|
||||
}
|
||||
|
||||
if ('default_member_permissions' in data) {
|
||||
/**
|
||||
* The default bitfield used to determine whether this command be used in a guild
|
||||
* @type {?Readonly<PermissionsBitField>}
|
||||
*/
|
||||
this.defaultMemberPermissions = data.default_member_permissions
|
||||
? new PermissionsBitField(BigInt(data.default_member_permissions)).freeze()
|
||||
: null;
|
||||
} else {
|
||||
this.defaultMemberPermissions ??= null;
|
||||
}
|
||||
|
||||
if ('dm_permission' in data) {
|
||||
/**
|
||||
* Whether the command can be used in DMs
|
||||
* <info>This property is always `null` on guild commands</info>
|
||||
* @type {?boolean}
|
||||
* @deprecated Use {@link ApplicationCommand#contexts} instead.
|
||||
*/
|
||||
this.dmPermission = data.dm_permission;
|
||||
} else {
|
||||
this.dmPermission ??= null;
|
||||
}
|
||||
|
||||
if ('integration_types' in data) {
|
||||
/**
|
||||
* Installation context(s) where the command is available
|
||||
* <info>Only for globally-scoped commands</info>
|
||||
* @type {?ApplicationIntegrationType[]}
|
||||
*/
|
||||
this.integrationTypes = data.integration_types;
|
||||
} else {
|
||||
this.integrationTypes ??= null;
|
||||
}
|
||||
|
||||
if ('contexts' in data) {
|
||||
/**
|
||||
* Interaction context(s) where the command can be used
|
||||
* <info>Only for globally-scoped commands</info>
|
||||
* @type {?InteractionContextType[]}
|
||||
*/
|
||||
this.contexts = data.contexts;
|
||||
} else {
|
||||
this.contexts ??= null;
|
||||
}
|
||||
|
||||
if ('handler' in data) {
|
||||
/**
|
||||
* Determines whether the interaction is handled by the app's interactions handler or by Discord.
|
||||
* <info>Only available for {@link ApplicationCommandType.PrimaryEntryPoint} commands on
|
||||
* applications with the {@link ApplicationFlags.Embedded} flag (i.e, those that have an Activity)</info>
|
||||
* @type {?EntryPointCommandHandlerType}
|
||||
*/
|
||||
this.handler = data.handler;
|
||||
} else {
|
||||
this.handler ??= null;
|
||||
}
|
||||
|
||||
if ('version' in data) {
|
||||
/**
|
||||
* Autoincrementing version identifier updated during substantial record changes
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.version = data.version;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp the command was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the command was created at
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The manager that this command belongs to
|
||||
* @type {ApplicationCommandManager}
|
||||
* @readonly
|
||||
*/
|
||||
get manager() {
|
||||
return (this.guild ?? this.client.application).commands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data for creating or editing an application command.
|
||||
* @typedef {Object} ApplicationCommandData
|
||||
* @property {string} name The name of the command, must be in all lowercase if type is
|
||||
* {@link ApplicationCommandType.ChatInput}
|
||||
* @property {LocalizationMap} [nameLocalizations] The localizations for the command name
|
||||
* @property {string} description The description of the command,
|
||||
* if type is {@link ApplicationCommandType.ChatInput} or {@link ApplicationCommandType.PrimaryEntryPoint}
|
||||
* @property {boolean} [nsfw] Whether the command is age-restricted
|
||||
* @property {LocalizationMap} [descriptionLocalizations] The localizations for the command description,
|
||||
* if type is {@link ApplicationCommandType.ChatInput} or {@link ApplicationCommandType.PrimaryEntryPoint}
|
||||
* @property {ApplicationCommandType} [type=ApplicationCommandType.ChatInput] The type of the command
|
||||
* @property {ApplicationCommandOptionData[]} [options] Options for the command
|
||||
* @property {?PermissionResolvable} [defaultMemberPermissions] The bitfield used to determine the default permissions
|
||||
* a member needs in order to run the command
|
||||
* @property {boolean} [dmPermission] Whether the command is enabled in DMs
|
||||
* @property {ApplicationIntegrationType[]} [integrationTypes] Installation contexts where the command is available
|
||||
* @property {InteractionContextType[]} [contexts] Interaction contexts where the command can be used
|
||||
* @property {EntryPointCommandHandlerType} [handler] Whether the interaction is handled by the app's
|
||||
* interactions handler or by Discord.
|
||||
*/
|
||||
|
||||
/**
|
||||
* An option for an application command or subcommand.
|
||||
* <info>In addition to the listed properties, when used as a parameter,
|
||||
* API style `snake_case` properties can be used for compatibility with generators like `@discordjs/builders`.</info>
|
||||
* <warn>Note that providing a value for the `camelCase` counterpart for any `snake_case` property
|
||||
* will discard the provided `snake_case` property.</warn>
|
||||
* @typedef {Object} ApplicationCommandOptionData
|
||||
* @property {ApplicationCommandOptionType} type The type of the option
|
||||
* @property {string} name The name of the option
|
||||
* @property {LocalizationMap} [nameLocalizations] The name localizations for the option
|
||||
* @property {string} description The description of the option
|
||||
* @property {LocalizationMap} [descriptionLocalizations] The description localizations for the option
|
||||
* @property {boolean} [autocomplete] Whether the autocomplete interaction is enabled for a
|
||||
* {@link ApplicationCommandOptionType.String}, {@link ApplicationCommandOptionType.Integer} or
|
||||
* {@link ApplicationCommandOptionType.Number} option
|
||||
* @property {boolean} [required] Whether the option is required
|
||||
* @property {ApplicationCommandOptionChoiceData[]} [choices] The choices of the option for the user to pick from
|
||||
* @property {ApplicationCommandOptionData[]} [options] Additional options if this option is a subcommand (group)
|
||||
* @property {ChannelType[]} [channelTypes] When the option type is channel,
|
||||
* the allowed types of channels that can be selected
|
||||
* @property {number} [minValue] The minimum value for an {@link ApplicationCommandOptionType.Integer} or
|
||||
* {@link ApplicationCommandOptionType.Number} option
|
||||
* @property {number} [maxValue] The maximum value for an {@link ApplicationCommandOptionType.Integer} or
|
||||
* {@link ApplicationCommandOptionType.Number} option
|
||||
* @property {number} [minLength] The minimum length for an {@link ApplicationCommandOptionType.String} option
|
||||
* (maximum of `6000`)
|
||||
* @property {number} [maxLength] The maximum length for an {@link ApplicationCommandOptionType.String} option
|
||||
* (maximum of `6000`)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ApplicationCommandOptionChoiceData
|
||||
* @property {string} name The name of the choice
|
||||
* @property {LocalizationMap} [nameLocalizations] The localized names for this choice
|
||||
* @property {string|number} value The value of the choice
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits this application command.
|
||||
* @param {Partial<ApplicationCommandData>} data The data to update the command with
|
||||
* @returns {Promise<ApplicationCommand>}
|
||||
* @example
|
||||
* // Edit the description of this command
|
||||
* command.edit({
|
||||
* description: 'New description',
|
||||
* })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
edit(data) {
|
||||
return this.manager.edit(this, data, this.guildId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits the name of this ApplicationCommand
|
||||
* @param {string} name The new name of the command
|
||||
* @returns {Promise<ApplicationCommand>}
|
||||
*/
|
||||
setName(name) {
|
||||
return this.edit({ name });
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits the localized names of this ApplicationCommand
|
||||
* @param {LocalizationMap} nameLocalizations The new localized names for the command
|
||||
* @returns {Promise<ApplicationCommand>}
|
||||
* @example
|
||||
* // Edit the name localizations of this command
|
||||
* command.setNameLocalizations({
|
||||
* 'en-GB': 'test',
|
||||
* 'pt-BR': 'teste',
|
||||
* })
|
||||
* .then(console.log)
|
||||
* .catch(console.error)
|
||||
*/
|
||||
setNameLocalizations(nameLocalizations) {
|
||||
return this.edit({ nameLocalizations });
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits the description of this ApplicationCommand
|
||||
* @param {string} description The new description of the command
|
||||
* @returns {Promise<ApplicationCommand>}
|
||||
*/
|
||||
setDescription(description) {
|
||||
return this.edit({ description });
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits the localized descriptions of this ApplicationCommand
|
||||
* @param {LocalizationMap} descriptionLocalizations The new localized descriptions for the command
|
||||
* @returns {Promise<ApplicationCommand>}
|
||||
* @example
|
||||
* // Edit the description localizations of this command
|
||||
* command.setDescriptionLocalizations({
|
||||
* 'en-GB': 'A test command',
|
||||
* 'pt-BR': 'Um comando de teste',
|
||||
* })
|
||||
* .then(console.log)
|
||||
* .catch(console.error)
|
||||
*/
|
||||
setDescriptionLocalizations(descriptionLocalizations) {
|
||||
return this.edit({ descriptionLocalizations });
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits the default member permissions of this ApplicationCommand
|
||||
* @param {?PermissionResolvable} defaultMemberPermissions The default member permissions required to run this command
|
||||
* @returns {Promise<ApplicationCommand>}
|
||||
*/
|
||||
setDefaultMemberPermissions(defaultMemberPermissions) {
|
||||
return this.edit({ defaultMemberPermissions });
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits the DM permission of this ApplicationCommand
|
||||
* @param {boolean} [dmPermission=true] Whether the command can be used in DMs
|
||||
* @returns {Promise<ApplicationCommand>}
|
||||
*/
|
||||
setDMPermission(dmPermission = true) {
|
||||
return this.edit({ dmPermission });
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits the options of this ApplicationCommand
|
||||
* @param {ApplicationCommandOptionData[]} options The options to set for this command
|
||||
* @returns {Promise<ApplicationCommand>}
|
||||
*/
|
||||
setOptions(options) {
|
||||
return this.edit({ options });
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this command.
|
||||
* @returns {Promise<ApplicationCommand>}
|
||||
* @example
|
||||
* // Delete this command
|
||||
* command.delete()
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
delete() {
|
||||
return this.manager.delete(this, this.guildId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this command equals another command. It compares all properties, so for most operations
|
||||
* it is advisable to just compare `command.id === command2.id` as it is much faster and is often
|
||||
* what most users need.
|
||||
* @param {ApplicationCommand|ApplicationCommandData|APIApplicationCommand} command The command to compare with
|
||||
* @param {boolean} [enforceOptionOrder=false] Whether to strictly check that options and choices are in the same
|
||||
* order in the array <info>The client may not always respect this ordering!</info>
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(command, enforceOptionOrder = false) {
|
||||
// If given an id, check if the id matches
|
||||
if (command.id && this.id !== command.id) return false;
|
||||
|
||||
let defaultMemberPermissions = null;
|
||||
let dmPermission = command.dmPermission ?? command.dm_permission;
|
||||
|
||||
if ('default_member_permissions' in command) {
|
||||
defaultMemberPermissions = command.default_member_permissions
|
||||
? new PermissionsBitField(BigInt(command.default_member_permissions)).bitfield
|
||||
: null;
|
||||
}
|
||||
|
||||
if ('defaultMemberPermissions' in command) {
|
||||
defaultMemberPermissions =
|
||||
command.defaultMemberPermissions !== null
|
||||
? new PermissionsBitField(command.defaultMemberPermissions).bitfield
|
||||
: null;
|
||||
}
|
||||
|
||||
// Check top level parameters
|
||||
if (
|
||||
command.name !== this.name ||
|
||||
('description' in command && command.description !== this.description) ||
|
||||
('version' in command && command.version !== this.version) ||
|
||||
(command.type && command.type !== this.type) ||
|
||||
('nsfw' in command && command.nsfw !== this.nsfw) ||
|
||||
// Future proof for options being nullable
|
||||
// TODO: remove ?? 0 on each when nullable
|
||||
(command.options?.length ?? 0) !== (this.options?.length ?? 0) ||
|
||||
defaultMemberPermissions !== (this.defaultMemberPermissions?.bitfield ?? null) ||
|
||||
(dmPermission !== undefined && dmPermission !== this.dmPermission) ||
|
||||
!isEqual(command.nameLocalizations ?? command.name_localizations ?? {}, this.nameLocalizations ?? {}) ||
|
||||
!isEqual(
|
||||
command.descriptionLocalizations ?? command.description_localizations ?? {},
|
||||
this.descriptionLocalizations ?? {},
|
||||
) ||
|
||||
!isEqual(command.integrationTypes ?? command.integration_types ?? [], this.integrationTypes ?? []) ||
|
||||
!isEqual(command.contexts ?? [], this.contexts ?? []) ||
|
||||
('handler' in command && command.handler !== this.handler)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (command.options) {
|
||||
return this.constructor.optionsEqual(this.options, command.options, enforceOptionOrder);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively checks that all options for an {@link ApplicationCommand} are equal to the provided options.
|
||||
* In most cases it is better to compare using {@link ApplicationCommand#equals}
|
||||
* @param {ApplicationCommandOptionData[]} existing The options on the existing command,
|
||||
* should be {@link ApplicationCommand#options}
|
||||
* @param {ApplicationCommandOptionData[]|APIApplicationCommandOption[]} options The options to compare against
|
||||
* @param {boolean} [enforceOptionOrder=false] Whether to strictly check that options and choices are in the same
|
||||
* order in the array <info>The client may not always respect this ordering!</info>
|
||||
* @returns {boolean}
|
||||
*/
|
||||
static optionsEqual(existing, options, enforceOptionOrder = false) {
|
||||
if (existing.length !== options.length) return false;
|
||||
if (enforceOptionOrder) {
|
||||
return existing.every((option, index) => this._optionEquals(option, options[index], enforceOptionOrder));
|
||||
}
|
||||
const newOptions = new Map(options.map(option => [option.name, option]));
|
||||
for (const option of existing) {
|
||||
const foundOption = newOptions.get(option.name);
|
||||
if (!foundOption || !this._optionEquals(option, foundOption)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that an option for an {@link ApplicationCommand} is equal to the provided option
|
||||
* In most cases it is better to compare using {@link ApplicationCommand#equals}
|
||||
* @param {ApplicationCommandOptionData} existing The option on the existing command,
|
||||
* should be from {@link ApplicationCommand#options}
|
||||
* @param {ApplicationCommandOptionData|APIApplicationCommandOption} option The option to compare against
|
||||
* @param {boolean} [enforceOptionOrder=false] Whether to strictly check that options or choices are in the same
|
||||
* order in their array <info>The client may not always respect this ordering!</info>
|
||||
* @returns {boolean}
|
||||
* @private
|
||||
*/
|
||||
static _optionEquals(existing, option, enforceOptionOrder = false) {
|
||||
if (
|
||||
option.name !== existing.name ||
|
||||
option.type !== existing.type ||
|
||||
option.description !== existing.description ||
|
||||
option.autocomplete !== existing.autocomplete ||
|
||||
(option.required ??
|
||||
([ApplicationCommandOptionType.Subcommand, ApplicationCommandOptionType.SubcommandGroup].includes(option.type)
|
||||
? undefined
|
||||
: false)) !== existing.required ||
|
||||
option.choices?.length !== existing.choices?.length ||
|
||||
option.options?.length !== existing.options?.length ||
|
||||
(option.channelTypes ?? option.channel_types)?.length !== existing.channelTypes?.length ||
|
||||
(option.minValue ?? option.min_value) !== existing.minValue ||
|
||||
(option.maxValue ?? option.max_value) !== existing.maxValue ||
|
||||
(option.minLength ?? option.min_length) !== existing.minLength ||
|
||||
(option.maxLength ?? option.max_length) !== existing.maxLength ||
|
||||
!isEqual(option.nameLocalizations ?? option.name_localizations ?? {}, existing.nameLocalizations ?? {}) ||
|
||||
!isEqual(
|
||||
option.descriptionLocalizations ?? option.description_localizations ?? {},
|
||||
existing.descriptionLocalizations ?? {},
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (existing.choices) {
|
||||
if (
|
||||
enforceOptionOrder &&
|
||||
!existing.choices.every(
|
||||
(choice, index) =>
|
||||
choice.name === option.choices[index].name &&
|
||||
choice.value === option.choices[index].value &&
|
||||
isEqual(
|
||||
choice.nameLocalizations ?? {},
|
||||
option.choices[index].nameLocalizations ?? option.choices[index].name_localizations ?? {},
|
||||
),
|
||||
)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
if (!enforceOptionOrder) {
|
||||
const newChoices = new Map(option.choices.map(choice => [choice.name, choice]));
|
||||
for (const choice of existing.choices) {
|
||||
const foundChoice = newChoices.get(choice.name);
|
||||
if (!foundChoice || foundChoice.value !== choice.value) return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (existing.channelTypes) {
|
||||
const newTypes = option.channelTypes ?? option.channel_types;
|
||||
for (const type of existing.channelTypes) {
|
||||
if (!newTypes.includes(type)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (existing.options) {
|
||||
return this.optionsEqual(existing.options, option.options, enforceOptionOrder);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* An option for an application command or subcommand.
|
||||
* @typedef {Object} ApplicationCommandOption
|
||||
* @property {ApplicationCommandOptionType} type The type of the option
|
||||
* @property {string} name The name of the option
|
||||
* @property {LocalizationMap} [nameLocalizations] The localizations for the option name
|
||||
* @property {string} [nameLocalized] The localized name for this option
|
||||
* @property {string} description The description of the option
|
||||
* @property {LocalizationMap} [descriptionLocalizations] The localizations for the option description
|
||||
* @property {string} [descriptionLocalized] The localized description for this option
|
||||
* @property {boolean} [required] Whether the option is required
|
||||
* @property {boolean} [autocomplete] Whether the autocomplete interaction is enabled for a
|
||||
* {@link ApplicationCommandOptionType.String}, {@link ApplicationCommandOptionType.Integer} or
|
||||
* {@link ApplicationCommandOptionType.Number} option
|
||||
* @property {ApplicationCommandOptionChoice[]} [choices] The choices of the option for the user to pick from
|
||||
* @property {ApplicationCommandOption[]} [options] Additional options if this option is a subcommand (group)
|
||||
* @property {ApplicationCommandOptionAllowedChannelTypes[]} [channelTypes] When the option type is channel,
|
||||
* the allowed types of channels that can be selected
|
||||
* @property {number} [minValue] The minimum value for an {@link ApplicationCommandOptionType.Integer} or
|
||||
* {@link ApplicationCommandOptionType.Number} option
|
||||
* @property {number} [maxValue] The maximum value for an {@link ApplicationCommandOptionType.Integer} or
|
||||
* {@link ApplicationCommandOptionType.Number} option
|
||||
* @property {number} [minLength] The minimum length for an {@link ApplicationCommandOptionType.String} option
|
||||
* (maximum of `6000`)
|
||||
* @property {number} [maxLength] The maximum length for an {@link ApplicationCommandOptionType.String} option
|
||||
* (maximum of `6000`)
|
||||
*/
|
||||
|
||||
/**
|
||||
* A choice for an application command option.
|
||||
* @typedef {Object} ApplicationCommandOptionChoice
|
||||
* @property {string} name The name of the choice
|
||||
* @property {?string} nameLocalized The localized name of the choice in the provided locale, if any
|
||||
* @property {?Object<string, string>} [nameLocalizations] The localized names for this choice
|
||||
* @property {string|number} value The value of the choice
|
||||
*/
|
||||
|
||||
/**
|
||||
* Transforms an {@link ApplicationCommandOptionData} object into something that can be used with the API.
|
||||
* @param {ApplicationCommandOptionData|ApplicationCommandOption} option The option to transform
|
||||
* @param {boolean} [received] Whether this option has been received from Discord
|
||||
* @returns {APIApplicationCommandOption}
|
||||
* @private
|
||||
*/
|
||||
static transformOption(option, received) {
|
||||
const channelTypesKey = received ? 'channelTypes' : 'channel_types';
|
||||
const minValueKey = received ? 'minValue' : 'min_value';
|
||||
const maxValueKey = received ? 'maxValue' : 'max_value';
|
||||
const minLengthKey = received ? 'minLength' : 'min_length';
|
||||
const maxLengthKey = received ? 'maxLength' : 'max_length';
|
||||
const nameLocalizationsKey = received ? 'nameLocalizations' : 'name_localizations';
|
||||
const nameLocalizedKey = received ? 'nameLocalized' : 'name_localized';
|
||||
const descriptionLocalizationsKey = received ? 'descriptionLocalizations' : 'description_localizations';
|
||||
const descriptionLocalizedKey = received ? 'descriptionLocalized' : 'description_localized';
|
||||
return {
|
||||
type: option.type,
|
||||
name: option.name,
|
||||
[nameLocalizationsKey]: option.nameLocalizations ?? option.name_localizations,
|
||||
[nameLocalizedKey]: option.nameLocalized ?? option.name_localized,
|
||||
description: option.description,
|
||||
[descriptionLocalizationsKey]: option.descriptionLocalizations ?? option.description_localizations,
|
||||
[descriptionLocalizedKey]: option.descriptionLocalized ?? option.description_localized,
|
||||
required:
|
||||
option.required ??
|
||||
(option.type === ApplicationCommandOptionType.Subcommand ||
|
||||
option.type === ApplicationCommandOptionType.SubcommandGroup
|
||||
? undefined
|
||||
: false),
|
||||
autocomplete: option.autocomplete,
|
||||
choices: option.choices?.map(choice => ({
|
||||
name: choice.name,
|
||||
[nameLocalizedKey]: choice.nameLocalized ?? choice.name_localized,
|
||||
[nameLocalizationsKey]: choice.nameLocalizations ?? choice.name_localizations,
|
||||
value: choice.value,
|
||||
})),
|
||||
options: option.options?.map(opt => this.transformOption(opt, received)),
|
||||
[channelTypesKey]: option.channelTypes ?? option.channel_types,
|
||||
[minValueKey]: option.minValue ?? option.min_value,
|
||||
[maxValueKey]: option.maxValue ?? option.max_value,
|
||||
[minLengthKey]: option.minLength ?? option.min_length,
|
||||
[maxLengthKey]: option.maxLength ?? option.max_length,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ApplicationCommand;
|
||||
|
||||
/* eslint-disable max-len */
|
||||
/**
|
||||
* @external ApplicationCommandOptionAllowedChannelTypes
|
||||
* @see {@link https://discord.js.org/docs/packages/builders/stable/ApplicationCommandOptionAllowedChannelTypes:TypeAlias}
|
||||
*/
|
||||
169
node_modules/discord.js/src/structures/ApplicationEmoji.js
generated
vendored
Normal file
169
node_modules/discord.js/src/structures/ApplicationEmoji.js
generated
vendored
Normal file
@@ -0,0 +1,169 @@
|
||||
'use strict';
|
||||
|
||||
const { Emoji } = require('./Emoji');
|
||||
|
||||
/**
|
||||
* Represents a custom emoji.
|
||||
* @extends {Emoji}
|
||||
*/
|
||||
class ApplicationEmoji extends Emoji {
|
||||
constructor(client, data, application) {
|
||||
super(client, data);
|
||||
|
||||
/**
|
||||
* The application this emoji originates from
|
||||
* @type {ClientApplication}
|
||||
*/
|
||||
this.application = application;
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
if ('name' in data) this.name = data.name;
|
||||
if (data.user) {
|
||||
/**
|
||||
* The user who created this emoji
|
||||
* @type {User}
|
||||
*/
|
||||
this.author = this.client.users._add(data.user);
|
||||
}
|
||||
|
||||
if ('managed' in data) {
|
||||
/**
|
||||
* Whether this emoji is managed by an external service. Always `false` for application emojis
|
||||
* @type {false}
|
||||
*/
|
||||
this.managed = data.managed;
|
||||
}
|
||||
|
||||
if ('require_colons' in data) {
|
||||
/**
|
||||
* Whether this emoji requires colons surrounding it. Always `true` for application emojis
|
||||
* @type {true}
|
||||
*/
|
||||
this.requiresColons = data.require_colons;
|
||||
}
|
||||
|
||||
if ('available' in data) {
|
||||
/**
|
||||
* Whether this emoji is available. Always `true` for application emojis
|
||||
* @type {true}
|
||||
*/
|
||||
this.available = data.available;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the author for this emoji
|
||||
* @returns {Promise<User>}
|
||||
*/
|
||||
fetchAuthor() {
|
||||
return this.application.emojis.fetchAuthor(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data for editing an emoji.
|
||||
* @typedef {Object} ApplicationEmojiEditOptions
|
||||
* @property {string} [name] The name of the emoji
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits the emoji.
|
||||
* @param {ApplicationEmojiEditOptions} options The options to provide
|
||||
* @returns {Promise<ApplicationEmoji>}
|
||||
* @example
|
||||
* // Edit an emoji
|
||||
* emoji.edit({ name: 'newemoji' })
|
||||
* .then(emoji => console.log(`Edited emoji ${emoji}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
edit(options) {
|
||||
return this.application.emojis.edit(this.id, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the emoji.
|
||||
* @param {string} name The new name for the emoji
|
||||
* @returns {Promise<ApplicationEmoji>}
|
||||
*/
|
||||
setName(name) {
|
||||
return this.edit({ name });
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the emoji.
|
||||
* @returns {Promise<ApplicationEmoji>}
|
||||
*/
|
||||
async delete() {
|
||||
await this.application.emojis.delete(this.id);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this emoji is the same as another one.
|
||||
* @param {ApplicationEmoji|APIEmoji} other The emoji to compare it to
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(other) {
|
||||
if (other instanceof ApplicationEmoji) {
|
||||
return (
|
||||
other.animated === this.animated &&
|
||||
other.id === this.id &&
|
||||
other.name === this.name &&
|
||||
other.managed === this.managed &&
|
||||
other.requiresColons === this.requiresColons &&
|
||||
other.available === this.available
|
||||
);
|
||||
}
|
||||
|
||||
return other.id === this.id && other.name === this.name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The emoji's name
|
||||
* @name name
|
||||
* @memberof ApplicationEmoji
|
||||
* @instance
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
|
||||
/**
|
||||
* Whether the emoji is animated
|
||||
* @name animated
|
||||
* @memberof ApplicationEmoji
|
||||
* @instance
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns a URL for the emoji.
|
||||
* @method imageURL
|
||||
* @memberof ApplicationEmoji
|
||||
* @instance
|
||||
* @param {EmojiURLOptions} [options] Options for the image URL
|
||||
* @returns {string}
|
||||
*/
|
||||
|
||||
/**
|
||||
* The time the emoji was created at
|
||||
* @name createdAt
|
||||
* @memberof ApplicationEmoji
|
||||
* @instance
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
|
||||
/**
|
||||
* The timestamp the emoji was created at
|
||||
* @name createdTimestamp
|
||||
* @memberof ApplicationEmoji
|
||||
* @instance
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
|
||||
module.exports = ApplicationEmoji;
|
||||
46
node_modules/discord.js/src/structures/ApplicationRoleConnectionMetadata.js
generated
vendored
Normal file
46
node_modules/discord.js/src/structures/ApplicationRoleConnectionMetadata.js
generated
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Role connection metadata object for an application.
|
||||
*/
|
||||
class ApplicationRoleConnectionMetadata {
|
||||
constructor(data) {
|
||||
/**
|
||||
* The name of this metadata field
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* The name localizations for this metadata field
|
||||
* @type {?LocalizationMap}
|
||||
*/
|
||||
this.nameLocalizations = data.name_localizations ?? null;
|
||||
|
||||
/**
|
||||
* The description of this metadata field
|
||||
* @type {string}
|
||||
*/
|
||||
this.description = data.description;
|
||||
|
||||
/**
|
||||
* The description localizations for this metadata field
|
||||
* @type {?LocalizationMap}
|
||||
*/
|
||||
this.descriptionLocalizations = data.description_localizations ?? null;
|
||||
|
||||
/**
|
||||
* The dictionary key for this metadata field
|
||||
* @type {string}
|
||||
*/
|
||||
this.key = data.key;
|
||||
|
||||
/**
|
||||
* The type of this metadata field
|
||||
* @type {ApplicationRoleConnectionMetadataType}
|
||||
*/
|
||||
this.type = data.type;
|
||||
}
|
||||
}
|
||||
|
||||
exports.ApplicationRoleConnectionMetadata = ApplicationRoleConnectionMetadata;
|
||||
163
node_modules/discord.js/src/structures/Attachment.js
generated
vendored
Normal file
163
node_modules/discord.js/src/structures/Attachment.js
generated
vendored
Normal file
@@ -0,0 +1,163 @@
|
||||
'use strict';
|
||||
|
||||
const AttachmentFlagsBitField = require('../util/AttachmentFlagsBitField.js');
|
||||
const { basename, flatten } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* @typedef {Object} AttachmentPayload
|
||||
* @property {?string} name The name of the attachment
|
||||
* @property {Stream|BufferResolvable} attachment The attachment in this payload
|
||||
* @property {?string} description The description of the attachment
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents an attachment
|
||||
*/
|
||||
class Attachment {
|
||||
constructor(data) {
|
||||
this.attachment = data.url;
|
||||
/**
|
||||
* The name of this attachment
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.filename;
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
/**
|
||||
* The attachment's id
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
if ('size' in data) {
|
||||
/**
|
||||
* The size of this attachment in bytes
|
||||
* @type {number}
|
||||
*/
|
||||
this.size = data.size;
|
||||
}
|
||||
|
||||
if ('url' in data) {
|
||||
/**
|
||||
* The URL to this attachment
|
||||
* @type {string}
|
||||
*/
|
||||
this.url = data.url;
|
||||
}
|
||||
|
||||
if ('proxy_url' in data) {
|
||||
/**
|
||||
* The Proxy URL to this attachment
|
||||
* @type {string}
|
||||
*/
|
||||
this.proxyURL = data.proxy_url;
|
||||
}
|
||||
|
||||
if ('height' in data) {
|
||||
/**
|
||||
* The height of this attachment (if an image or video)
|
||||
* @type {?number}
|
||||
*/
|
||||
this.height = data.height;
|
||||
} else {
|
||||
this.height ??= null;
|
||||
}
|
||||
|
||||
if ('width' in data) {
|
||||
/**
|
||||
* The width of this attachment (if an image or video)
|
||||
* @type {?number}
|
||||
*/
|
||||
this.width = data.width;
|
||||
} else {
|
||||
this.width ??= null;
|
||||
}
|
||||
|
||||
if ('content_type' in data) {
|
||||
/**
|
||||
* The media (MIME) type of this attachment
|
||||
* @type {?string}
|
||||
* @see {@link https://developer.mozilla.org/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types}
|
||||
*/
|
||||
this.contentType = data.content_type;
|
||||
} else {
|
||||
this.contentType ??= null;
|
||||
}
|
||||
|
||||
if ('description' in data) {
|
||||
/**
|
||||
* The description (alt text) of this attachment
|
||||
* @type {?string}
|
||||
*/
|
||||
this.description = data.description;
|
||||
} else {
|
||||
this.description ??= null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this attachment is ephemeral
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.ephemeral = data.ephemeral ?? false;
|
||||
|
||||
if ('duration_secs' in data) {
|
||||
/**
|
||||
* The duration of this attachment in seconds
|
||||
* <info>This will only be available if the attachment is an audio file.</info>
|
||||
* @type {?number}
|
||||
*/
|
||||
this.duration = data.duration_secs;
|
||||
} else {
|
||||
this.duration ??= null;
|
||||
}
|
||||
|
||||
if ('waveform' in data) {
|
||||
/**
|
||||
* The base64 encoded byte array representing a sampled waveform
|
||||
* <info>This will only be available if the attachment is an audio file.</info>
|
||||
* @type {?string}
|
||||
*/
|
||||
this.waveform = data.waveform;
|
||||
} else {
|
||||
this.waveform ??= null;
|
||||
}
|
||||
|
||||
if ('flags' in data) {
|
||||
/**
|
||||
* The flags of this attachment
|
||||
* @type {Readonly<AttachmentFlagsBitField>}
|
||||
*/
|
||||
this.flags = new AttachmentFlagsBitField(data.flags).freeze();
|
||||
} else {
|
||||
this.flags ??= new AttachmentFlagsBitField().freeze();
|
||||
}
|
||||
|
||||
if ('title' in data) {
|
||||
/**
|
||||
* The title of this attachment
|
||||
* <info>This will only be available if the attachment name contains special characters.</info>
|
||||
* @type {?string}
|
||||
*/
|
||||
this.title = data.title;
|
||||
} else {
|
||||
this.title ??= null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this attachment has been marked as a spoiler
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get spoiler() {
|
||||
return basename(this.url ?? this.name).startsWith('SPOILER_');
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return flatten(this);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Attachment;
|
||||
111
node_modules/discord.js/src/structures/AttachmentBuilder.js
generated
vendored
Normal file
111
node_modules/discord.js/src/structures/AttachmentBuilder.js
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
'use strict';
|
||||
|
||||
const { basename, flatten } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents an attachment builder
|
||||
*/
|
||||
class AttachmentBuilder {
|
||||
/**
|
||||
* @param {BufferResolvable|Stream} attachment The file
|
||||
* @param {AttachmentData} [data] Extra data
|
||||
*/
|
||||
constructor(attachment, data = {}) {
|
||||
/**
|
||||
* The file associated with this attachment.
|
||||
* @type {BufferResolvable|Stream}
|
||||
*/
|
||||
this.attachment = attachment;
|
||||
/**
|
||||
* The name of this attachment
|
||||
* @type {?string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
/**
|
||||
* The description of the attachment
|
||||
* @type {?string}
|
||||
*/
|
||||
this.description = data.description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the description of this attachment.
|
||||
* @param {string} description The description of the file
|
||||
* @returns {AttachmentBuilder} This attachment
|
||||
*/
|
||||
setDescription(description) {
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the file of this attachment.
|
||||
* @param {BufferResolvable|Stream} attachment The file
|
||||
* @returns {AttachmentBuilder} This attachment
|
||||
*/
|
||||
setFile(attachment) {
|
||||
this.attachment = attachment;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of this attachment.
|
||||
* @param {string} name The name of the file
|
||||
* @returns {AttachmentBuilder} This attachment
|
||||
*/
|
||||
setName(name) {
|
||||
this.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this attachment is a spoiler
|
||||
* @param {boolean} [spoiler=true] Whether the attachment should be marked as a spoiler
|
||||
* @returns {AttachmentBuilder} This attachment
|
||||
*/
|
||||
setSpoiler(spoiler = true) {
|
||||
if (spoiler === this.spoiler) return this;
|
||||
|
||||
if (!spoiler) {
|
||||
while (this.spoiler) {
|
||||
this.name = this.name.slice('SPOILER_'.length);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
this.name = `SPOILER_${this.name}`;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this attachment has been marked as a spoiler
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get spoiler() {
|
||||
return basename(this.name).startsWith('SPOILER_');
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return flatten(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a new builder instance from a preexisting attachment structure.
|
||||
* @param {AttachmentBuilder|Attachment|AttachmentPayload} other The builder to construct a new instance from
|
||||
* @returns {AttachmentBuilder}
|
||||
*/
|
||||
static from(other) {
|
||||
return new AttachmentBuilder(other.attachment, {
|
||||
name: other.name,
|
||||
description: other.description,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AttachmentBuilder;
|
||||
|
||||
/**
|
||||
* @typedef {Object} AttachmentData
|
||||
* @property {string} [name] The name of the attachment
|
||||
* @property {string} [description] The description of the attachment
|
||||
*/
|
||||
116
node_modules/discord.js/src/structures/AutoModerationActionExecution.js
generated
vendored
Normal file
116
node_modules/discord.js/src/structures/AutoModerationActionExecution.js
generated
vendored
Normal file
@@ -0,0 +1,116 @@
|
||||
'use strict';
|
||||
|
||||
const { _transformAPIAutoModerationAction } = require('../util/Transformers');
|
||||
|
||||
/**
|
||||
* Represents the structure of an executed action when an {@link AutoModerationRule} is triggered.
|
||||
*/
|
||||
class AutoModerationActionExecution {
|
||||
constructor(data, guild) {
|
||||
/**
|
||||
* The guild where this action was executed from.
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
|
||||
/**
|
||||
* The action that was executed.
|
||||
* @type {AutoModerationAction}
|
||||
*/
|
||||
this.action = _transformAPIAutoModerationAction(data.action);
|
||||
|
||||
/**
|
||||
* The id of the auto moderation rule this action belongs to.
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.ruleId = data.rule_id;
|
||||
|
||||
/**
|
||||
* The trigger type of the auto moderation rule which was triggered.
|
||||
* @type {AutoModerationRuleTriggerType}
|
||||
*/
|
||||
this.ruleTriggerType = data.rule_trigger_type;
|
||||
|
||||
/**
|
||||
* The id of the user that triggered this action.
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.userId = data.user_id;
|
||||
|
||||
/**
|
||||
* The id of the channel where this action was triggered from.
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.channelId = data.channel_id ?? null;
|
||||
|
||||
/**
|
||||
* The id of the message that triggered this action.
|
||||
* <info>This will not be present if the message was blocked or the content was not part of any message.</info>
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.messageId = data.message_id ?? null;
|
||||
|
||||
/**
|
||||
* The id of any system auto moderation messages posted as a result of this action.
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.alertSystemMessageId = data.alert_system_message_id ?? null;
|
||||
|
||||
/**
|
||||
* The content that triggered this action.
|
||||
* <info>This property requires the {@link GatewayIntentBits.MessageContent} privileged gateway intent.</info>
|
||||
* @type {string}
|
||||
*/
|
||||
this.content = data.content;
|
||||
|
||||
/**
|
||||
* The word or phrase configured in the rule that triggered this action.
|
||||
* @type {?string}
|
||||
*/
|
||||
this.matchedKeyword = data.matched_keyword ?? null;
|
||||
|
||||
/**
|
||||
* The substring in content that triggered this action.
|
||||
* @type {?string}
|
||||
*/
|
||||
this.matchedContent = data.matched_content ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The auto moderation rule this action belongs to.
|
||||
* @type {?AutoModerationRule}
|
||||
* @readonly
|
||||
*/
|
||||
get autoModerationRule() {
|
||||
return this.guild.autoModerationRules.cache.get(this.ruleId) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The channel where this action was triggered from.
|
||||
* @type {?(GuildTextBasedChannel|ForumChannel|MediaChannel)}
|
||||
* @readonly
|
||||
*/
|
||||
get channel() {
|
||||
return this.guild.channels.cache.get(this.channelId) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The user that triggered this action.
|
||||
* @type {?User}
|
||||
* @readonly
|
||||
*/
|
||||
get user() {
|
||||
return this.guild.client.users.cache.get(this.userId) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The guild member that triggered this action.
|
||||
* @type {?GuildMember}
|
||||
* @readonly
|
||||
*/
|
||||
get member() {
|
||||
return this.guild.members.cache.get(this.userId) ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AutoModerationActionExecution;
|
||||
288
node_modules/discord.js/src/structures/AutoModerationRule.js
generated
vendored
Normal file
288
node_modules/discord.js/src/structures/AutoModerationRule.js
generated
vendored
Normal file
@@ -0,0 +1,288 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const Base = require('./Base');
|
||||
const { _transformAPIAutoModerationAction } = require('../util/Transformers');
|
||||
|
||||
/**
|
||||
* Represents an auto moderation rule.
|
||||
* @extends {Base}
|
||||
*/
|
||||
class AutoModerationRule extends Base {
|
||||
constructor(client, data, guild) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The id of this auto moderation rule.
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The guild this auto moderation rule is for.
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
|
||||
/**
|
||||
* The user that created this auto moderation rule.
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.creatorId = data.creator_id;
|
||||
|
||||
/**
|
||||
* The trigger type of this auto moderation rule.
|
||||
* @type {AutoModerationRuleTriggerType}
|
||||
*/
|
||||
this.triggerType = data.trigger_type;
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
if ('name' in data) {
|
||||
/**
|
||||
* The name of this auto moderation rule.
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
}
|
||||
|
||||
if ('event_type' in data) {
|
||||
/**
|
||||
* The event type of this auto moderation rule.
|
||||
* @type {AutoModerationRuleEventType}
|
||||
*/
|
||||
this.eventType = data.event_type;
|
||||
}
|
||||
|
||||
if ('trigger_metadata' in data) {
|
||||
/**
|
||||
* Additional data used to determine whether an auto moderation rule should be triggered.
|
||||
* @typedef {Object} AutoModerationTriggerMetadata
|
||||
* @property {string[]} keywordFilter The substrings that will be searched for in the content
|
||||
* @property {string[]} regexPatterns The regular expression patterns which will be matched against the content
|
||||
* <info>Only Rust-flavored regular expressions are supported.</info>
|
||||
* @property {AutoModerationRuleKeywordPresetType[]} presets
|
||||
* The internally pre-defined wordsets which will be searched for in the content
|
||||
* @property {string[]} allowList The substrings that will be exempt from triggering
|
||||
* {@link AutoModerationRuleTriggerType.Keyword},
|
||||
* {@link AutoModerationRuleTriggerType.KeywordPreset},
|
||||
* and {@link AutoModerationRuleTriggerType.MemberProfile}
|
||||
* @property {?number} mentionTotalLimit The total number of role & user mentions allowed per message
|
||||
* @property {boolean} mentionRaidProtectionEnabled Whether mention raid protection is enabled
|
||||
*/
|
||||
|
||||
/**
|
||||
* The trigger metadata of the rule.
|
||||
* @type {AutoModerationTriggerMetadata}
|
||||
*/
|
||||
this.triggerMetadata = {
|
||||
keywordFilter: data.trigger_metadata.keyword_filter ?? [],
|
||||
regexPatterns: data.trigger_metadata.regex_patterns ?? [],
|
||||
presets: data.trigger_metadata.presets ?? [],
|
||||
allowList: data.trigger_metadata.allow_list ?? [],
|
||||
mentionTotalLimit: data.trigger_metadata.mention_total_limit ?? null,
|
||||
mentionRaidProtectionEnabled: data.trigger_metadata.mention_raid_protection_enabled ?? false,
|
||||
};
|
||||
}
|
||||
|
||||
if ('actions' in data) {
|
||||
/**
|
||||
* An object containing information about an auto moderation rule action.
|
||||
* @typedef {Object} AutoModerationAction
|
||||
* @property {AutoModerationActionType} type The type of this auto moderation rule action
|
||||
* @property {AutoModerationActionMetadata} metadata Additional metadata needed during execution
|
||||
*/
|
||||
|
||||
/**
|
||||
* Additional data used when an auto moderation rule is executed.
|
||||
* @typedef {Object} AutoModerationActionMetadata
|
||||
* @property {?Snowflake} channelId The id of the channel to which content will be logged
|
||||
* @property {?number} durationSeconds The timeout duration in seconds
|
||||
* @property {?string} customMessage The custom message that is shown whenever a message is blocked
|
||||
*/
|
||||
|
||||
/**
|
||||
* The actions of this auto moderation rule.
|
||||
* @type {AutoModerationAction[]}
|
||||
*/
|
||||
this.actions = data.actions.map(action => _transformAPIAutoModerationAction(action));
|
||||
}
|
||||
|
||||
if ('enabled' in data) {
|
||||
/**
|
||||
* Whether this auto moderation rule is enabled.
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.enabled = data.enabled;
|
||||
}
|
||||
|
||||
if ('exempt_roles' in data) {
|
||||
/**
|
||||
* The roles exempt by this auto moderation rule.
|
||||
* @type {Collection<Snowflake, Role>}
|
||||
*/
|
||||
this.exemptRoles = new Collection(
|
||||
data.exempt_roles.map(exemptRole => [exemptRole, this.guild.roles.cache.get(exemptRole)]),
|
||||
);
|
||||
}
|
||||
|
||||
if ('exempt_channels' in data) {
|
||||
/**
|
||||
* The channels exempt by this auto moderation rule.
|
||||
* @type {Collection<Snowflake, GuildChannel|ThreadChannel>}
|
||||
*/
|
||||
this.exemptChannels = new Collection(
|
||||
data.exempt_channels.map(exemptChannel => [exemptChannel, this.guild.channels.cache.get(exemptChannel)]),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits this auto moderation rule.
|
||||
* @param {AutoModerationRuleEditOptions} options Options for editing this auto moderation rule
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
edit(options) {
|
||||
return this.guild.autoModerationRules.edit(this.id, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this auto moderation rule.
|
||||
* @param {string} [reason] The reason for deleting this auto moderation rule
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
delete(reason) {
|
||||
return this.guild.autoModerationRules.delete(this.id, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name for this auto moderation rule.
|
||||
* @param {string} name The name of this auto moderation rule
|
||||
* @param {string} [reason] The reason for changing the name of this auto moderation rule
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
setName(name, reason) {
|
||||
return this.edit({ name, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the event type for this auto moderation rule.
|
||||
* @param {AutoModerationRuleEventType} eventType The event type of this auto moderation rule
|
||||
* @param {string} [reason] The reason for changing the event type of this auto moderation rule
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
setEventType(eventType, reason) {
|
||||
return this.edit({ eventType, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the keyword filter for this auto moderation rule.
|
||||
* @param {string[]} keywordFilter The keyword filter of this auto moderation rule
|
||||
* @param {string} [reason] The reason for changing the keyword filter of this auto moderation rule
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
setKeywordFilter(keywordFilter, reason) {
|
||||
return this.edit({ triggerMetadata: { ...this.triggerMetadata, keywordFilter }, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the regular expression patterns for this auto moderation rule.
|
||||
* @param {string[]} regexPatterns The regular expression patterns of this auto moderation rule
|
||||
* <info>Only Rust-flavored regular expressions are supported.</info>
|
||||
* @param {string} [reason] The reason for changing the regular expression patterns of this auto moderation rule
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
setRegexPatterns(regexPatterns, reason) {
|
||||
return this.edit({ triggerMetadata: { ...this.triggerMetadata, regexPatterns }, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the presets for this auto moderation rule.
|
||||
* @param {AutoModerationRuleKeywordPresetType[]} presets The presets of this auto moderation rule
|
||||
* @param {string} [reason] The reason for changing the presets of this auto moderation rule
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
setPresets(presets, reason) {
|
||||
return this.edit({ triggerMetadata: { ...this.triggerMetadata, presets }, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the allow list for this auto moderation rule.
|
||||
* @param {string[]} allowList The substrings that will be exempt from triggering
|
||||
* {@link AutoModerationRuleTriggerType.Keyword},
|
||||
* {@link AutoModerationRuleTriggerType.KeywordPreset},
|
||||
* and {@link AutoModerationRuleTriggerType.MemberProfile}
|
||||
* @param {string} [reason] The reason for changing the allow list of this auto moderation rule
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
setAllowList(allowList, reason) {
|
||||
return this.edit({ triggerMetadata: { ...this.triggerMetadata, allowList }, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the mention total limit for this auto moderation rule.
|
||||
* @param {number} mentionTotalLimit The total number of unique role and user mentions allowed per message
|
||||
* @param {string} [reason] The reason for changing the mention total limit of this auto moderation rule
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
setMentionTotalLimit(mentionTotalLimit, reason) {
|
||||
return this.edit({ triggerMetadata: { ...this.triggerMetadata, mentionTotalLimit }, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether to enable mention raid protection for this auto moderation rule.
|
||||
* @param {boolean} mentionRaidProtectionEnabled
|
||||
* Whether to enable mention raid protection for this auto moderation rule
|
||||
* @param {string} [reason] The reason for changing the mention raid protection of this auto moderation rule
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
setMentionRaidProtectionEnabled(mentionRaidProtectionEnabled, reason) {
|
||||
return this.edit({ triggerMetadata: { ...this.triggerMetadata, mentionRaidProtectionEnabled }, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the actions for this auto moderation rule.
|
||||
* @param {AutoModerationActionOptions[]} actions The actions of this auto moderation rule
|
||||
* @param {string} [reason] The reason for changing the actions of this auto moderation rule
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
setActions(actions, reason) {
|
||||
return this.edit({ actions, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this auto moderation rule should be enabled.
|
||||
* @param {boolean} [enabled=true] Whether to enable this auto moderation rule
|
||||
* @param {string} [reason] The reason for enabling or disabling this auto moderation rule
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
setEnabled(enabled = true, reason) {
|
||||
return this.edit({ enabled, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the exempt roles for this auto moderation rule.
|
||||
* @param {Collection<Snowflake, Role>|RoleResolvable[]} [exemptRoles]
|
||||
* The roles that should not be affected by the auto moderation rule
|
||||
* @param {string} [reason] The reason for changing the exempt roles of this auto moderation rule
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
setExemptRoles(exemptRoles, reason) {
|
||||
return this.edit({ exemptRoles, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the exempt channels for this auto moderation rule.
|
||||
* @param {Collection<Snowflake, GuildChannel|ThreadChannel>|GuildChannelResolvable[]} [exemptChannels]
|
||||
* The channels that should not be affected by the auto moderation rule
|
||||
* @param {string} [reason] The reason for changing the exempt channels of this auto moderation rule
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
setExemptChannels(exemptChannels, reason) {
|
||||
return this.edit({ exemptChannels, reason });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AutoModerationRule;
|
||||
102
node_modules/discord.js/src/structures/AutocompleteInteraction.js
generated
vendored
Normal file
102
node_modules/discord.js/src/structures/AutocompleteInteraction.js
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
'use strict';
|
||||
|
||||
const { InteractionResponseType, Routes } = require('discord-api-types/v10');
|
||||
const BaseInteraction = require('./BaseInteraction');
|
||||
const CommandInteractionOptionResolver = require('./CommandInteractionOptionResolver');
|
||||
const { DiscordjsError, ErrorCodes } = require('../errors');
|
||||
|
||||
/**
|
||||
* Represents an autocomplete interaction.
|
||||
* @extends {BaseInteraction}
|
||||
*/
|
||||
class AutocompleteInteraction extends BaseInteraction {
|
||||
constructor(client, data) {
|
||||
super(client, data);
|
||||
|
||||
/**
|
||||
* The id of the channel this interaction was sent in
|
||||
* @type {Snowflake}
|
||||
* @name AutocompleteInteraction#channelId
|
||||
*/
|
||||
|
||||
/**
|
||||
* The invoked application command's id
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.commandId = data.data.id;
|
||||
|
||||
/**
|
||||
* The invoked application command's name
|
||||
* @type {string}
|
||||
*/
|
||||
this.commandName = data.data.name;
|
||||
|
||||
/**
|
||||
* The invoked application command's type
|
||||
* @type {ApplicationCommandType}
|
||||
*/
|
||||
this.commandType = data.data.type;
|
||||
|
||||
/**
|
||||
* The id of the guild the invoked application command is registered to
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.commandGuildId = data.data.guild_id ?? null;
|
||||
|
||||
/**
|
||||
* Whether this interaction has already received a response
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.responded = false;
|
||||
|
||||
/**
|
||||
* The options passed to the command
|
||||
* @type {CommandInteractionOptionResolver}
|
||||
*/
|
||||
this.options = new CommandInteractionOptionResolver(this.client, data.data.options ?? []);
|
||||
}
|
||||
|
||||
/**
|
||||
* The invoked application command, if it was fetched before
|
||||
* @type {?ApplicationCommand}
|
||||
*/
|
||||
get command() {
|
||||
const id = this.commandId;
|
||||
return this.guild?.commands.cache.get(id) ?? this.client.application.commands.cache.get(id) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends results for the autocomplete of this interaction.
|
||||
* @param {ApplicationCommandOptionChoiceData[]} options The options for the autocomplete
|
||||
* @returns {Promise<void>}
|
||||
* @example
|
||||
* // respond to autocomplete interaction
|
||||
* interaction.respond([
|
||||
* {
|
||||
* name: 'Option 1',
|
||||
* value: 'option1',
|
||||
* },
|
||||
* ])
|
||||
* .then(() => console.log('Successfully responded to the autocomplete interaction'))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async respond(options) {
|
||||
if (this.responded) throw new DiscordjsError(ErrorCodes.InteractionAlreadyReplied);
|
||||
|
||||
await this.client.rest.post(Routes.interactionCallback(this.id, this.token), {
|
||||
body: {
|
||||
type: InteractionResponseType.ApplicationCommandAutocompleteResult,
|
||||
data: {
|
||||
choices: options.map(({ nameLocalizations, ...option }) => ({
|
||||
...this.client.options.jsonTransformer(option),
|
||||
name_localizations: nameLocalizations,
|
||||
})),
|
||||
},
|
||||
},
|
||||
auth: false,
|
||||
});
|
||||
this.responded = true;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AutocompleteInteraction;
|
||||
43
node_modules/discord.js/src/structures/Base.js
generated
vendored
Normal file
43
node_modules/discord.js/src/structures/Base.js
generated
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
'use strict';
|
||||
|
||||
const { flatten } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents a data model that is identifiable by a Snowflake (i.e. Discord API data models).
|
||||
* @abstract
|
||||
*/
|
||||
class Base {
|
||||
constructor(client) {
|
||||
/**
|
||||
* The client that instantiated this
|
||||
* @name Base#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
}
|
||||
|
||||
_clone() {
|
||||
return Object.assign(Object.create(this), this);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
_update(data) {
|
||||
const clone = this._clone();
|
||||
this._patch(data);
|
||||
return clone;
|
||||
}
|
||||
|
||||
toJSON(...props) {
|
||||
return flatten(this, ...props);
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.id;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Base;
|
||||
171
node_modules/discord.js/src/structures/BaseChannel.js
generated
vendored
Normal file
171
node_modules/discord.js/src/structures/BaseChannel.js
generated
vendored
Normal file
@@ -0,0 +1,171 @@
|
||||
'use strict';
|
||||
|
||||
const { channelLink, channelMention } = require('@discordjs/formatters');
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const { ChannelType, Routes } = require('discord-api-types/v10');
|
||||
const Base = require('./Base');
|
||||
const ChannelFlagsBitField = require('../util/ChannelFlagsBitField');
|
||||
const { ThreadChannelTypes } = require('../util/Constants');
|
||||
|
||||
/**
|
||||
* Represents any channel on Discord.
|
||||
* @extends {Base}
|
||||
* @abstract
|
||||
*/
|
||||
class BaseChannel extends Base {
|
||||
constructor(client, data, immediatePatch = true) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The type of the channel
|
||||
* @type {ChannelType}
|
||||
*/
|
||||
this.type = data.type;
|
||||
|
||||
if (data && immediatePatch) this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
if ('flags' in data) {
|
||||
/**
|
||||
* The flags that are applied to the channel.
|
||||
* <info>This is only `null` in a {@link PartialGroupDMChannel}. In all other cases, it is not `null`.</info>
|
||||
* @type {?Readonly<ChannelFlagsBitField>}
|
||||
*/
|
||||
this.flags = new ChannelFlagsBitField(data.flags).freeze();
|
||||
} else {
|
||||
this.flags ??= new ChannelFlagsBitField().freeze();
|
||||
}
|
||||
|
||||
/**
|
||||
* The channel's id
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp the channel was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the channel was created at
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL to the channel
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get url() {
|
||||
return this.isDMBased() ? channelLink(this.id) : channelLink(this.id, this.guildId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this Channel is a partial
|
||||
* <info>This is always false outside of DM channels.</info>
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get partial() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically returns the channel's mention instead of the Channel object.
|
||||
* @returns {string}
|
||||
* @example
|
||||
* // Logs: Hello from <#123456789012345678>!
|
||||
* console.log(`Hello from ${channel}!`);
|
||||
*/
|
||||
toString() {
|
||||
return channelMention(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this channel.
|
||||
* @returns {Promise<BaseChannel>}
|
||||
* @example
|
||||
* // Delete the channel
|
||||
* channel.delete()
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async delete() {
|
||||
await this.client.rest.delete(Routes.channel(this.id));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches this channel.
|
||||
* @param {boolean} [force=true] Whether to skip the cache check and request the API
|
||||
* @returns {Promise<BaseChannel>}
|
||||
*/
|
||||
fetch(force = true) {
|
||||
return this.client.channels.fetch(this.id, { force });
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this channel is a {@link ThreadChannel}.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isThread() {
|
||||
return ThreadChannelTypes.includes(this.type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this channel is {@link TextBasedChannels text-based}.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isTextBased() {
|
||||
return 'messages' in this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this channel is DM-based (either a {@link DMChannel} or a {@link PartialGroupDMChannel}).
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isDMBased() {
|
||||
return [ChannelType.DM, ChannelType.GroupDM].includes(this.type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this channel is {@link BaseGuildVoiceChannel voice-based}.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isVoiceBased() {
|
||||
return 'bitrate' in this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this channel is {@link ThreadOnlyChannel thread-only}.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isThreadOnly() {
|
||||
return 'availableTags' in this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this channel is sendable.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isSendable() {
|
||||
return 'send' in this;
|
||||
}
|
||||
|
||||
toJSON(...props) {
|
||||
return super.toJSON({ createdTimestamp: true }, ...props);
|
||||
}
|
||||
}
|
||||
|
||||
exports.BaseChannel = BaseChannel;
|
||||
119
node_modules/discord.js/src/structures/BaseGuild.js
generated
vendored
Normal file
119
node_modules/discord.js/src/structures/BaseGuild.js
generated
vendored
Normal file
@@ -0,0 +1,119 @@
|
||||
'use strict';
|
||||
|
||||
const { makeURLSearchParams } = require('@discordjs/rest');
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const { Routes, GuildFeature } = require('discord-api-types/v10');
|
||||
const Base = require('./Base');
|
||||
|
||||
/**
|
||||
* The base class for {@link Guild}, {@link OAuth2Guild} and {@link InviteGuild}.
|
||||
* @extends {Base}
|
||||
* @abstract
|
||||
*/
|
||||
class BaseGuild extends Base {
|
||||
constructor(client, data) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The guild's id
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The name of this guild
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* The icon hash of this guild
|
||||
* @type {?string}
|
||||
*/
|
||||
this.icon = data.icon;
|
||||
|
||||
/**
|
||||
* An array of features available to this guild
|
||||
* @type {GuildFeature[]}
|
||||
*/
|
||||
this.features = data.features;
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp this guild was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time this guild was created at
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The acronym that shows up in place of a guild icon
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get nameAcronym() {
|
||||
return this.name
|
||||
.replace(/'s /g, ' ')
|
||||
.replace(/\w+/g, e => e[0])
|
||||
.replace(/\s/g, '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this guild is partnered
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get partnered() {
|
||||
return this.features.includes(GuildFeature.Partnered);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this guild is verified
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get verified() {
|
||||
return this.features.includes(GuildFeature.Verified);
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL to this guild's icon.
|
||||
* @param {ImageURLOptions} [options={}] Options for the image URL
|
||||
* @returns {?string}
|
||||
*/
|
||||
iconURL(options = {}) {
|
||||
return this.icon && this.client.rest.cdn.icon(this.id, this.icon, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches this guild.
|
||||
* @returns {Promise<Guild>}
|
||||
*/
|
||||
async fetch() {
|
||||
const data = await this.client.rest.get(Routes.guild(this.id), {
|
||||
query: makeURLSearchParams({ with_counts: true }),
|
||||
});
|
||||
return this.client.guilds._add(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically returns the guild's name instead of the Guild object.
|
||||
* @returns {string}
|
||||
*/
|
||||
toString() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BaseGuild;
|
||||
111
node_modules/discord.js/src/structures/BaseGuildEmoji.js
generated
vendored
Normal file
111
node_modules/discord.js/src/structures/BaseGuildEmoji.js
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
'use strict';
|
||||
|
||||
const { Emoji } = require('./Emoji');
|
||||
|
||||
/**
|
||||
* Parent class for {@link GuildEmoji} and {@link GuildPreviewEmoji}.
|
||||
* @extends {Emoji}
|
||||
* @abstract
|
||||
*/
|
||||
class BaseGuildEmoji extends Emoji {
|
||||
constructor(client, data, guild) {
|
||||
super(client, data);
|
||||
|
||||
/**
|
||||
* The guild this emoji is a part of
|
||||
* @type {Guild|GuildPreview}
|
||||
*/
|
||||
this.guild = guild;
|
||||
|
||||
this.requiresColons = null;
|
||||
this.managed = null;
|
||||
this.available = null;
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
if ('name' in data) this.name = data.name;
|
||||
|
||||
if ('require_colons' in data) {
|
||||
/**
|
||||
* Whether or not this emoji requires colons surrounding it
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.requiresColons = data.require_colons;
|
||||
}
|
||||
|
||||
if ('managed' in data) {
|
||||
/**
|
||||
* Whether this emoji is managed by an external service
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.managed = data.managed;
|
||||
}
|
||||
|
||||
if ('available' in data) {
|
||||
/**
|
||||
* Whether this emoji is available
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.available = data.available;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a URL for the emoji.
|
||||
* @method imageURL
|
||||
* @memberof BaseGuildEmoji
|
||||
* @instance
|
||||
* @param {EmojiURLOptions} [options] Options for the emoji URL
|
||||
* @returns {string}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns a URL for the emoji.
|
||||
* @name url
|
||||
* @memberof BaseGuildEmoji
|
||||
* @instance
|
||||
* @type {string}
|
||||
* @readonly
|
||||
* @deprecated Use {@link BaseGuildEmoji#imageURL} instead.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The emoji's name
|
||||
* @name name
|
||||
* @memberof BaseGuildEmoji
|
||||
* @instance
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
|
||||
/**
|
||||
* Whether or not the emoji is animated
|
||||
* @name animated
|
||||
* @memberof BaseGuildEmoji
|
||||
* @instance
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
|
||||
/**
|
||||
* The time the emoji was created at.
|
||||
* @name createdAt
|
||||
* @memberof BaseGuildEmoji
|
||||
* @instance
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
|
||||
/**
|
||||
* The timestamp the emoji was created at.
|
||||
* @name createdTimestamp
|
||||
* @memberof BaseGuildEmoji
|
||||
* @instance
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
|
||||
module.exports = BaseGuildEmoji;
|
||||
196
node_modules/discord.js/src/structures/BaseGuildTextChannel.js
generated
vendored
Normal file
196
node_modules/discord.js/src/structures/BaseGuildTextChannel.js
generated
vendored
Normal file
@@ -0,0 +1,196 @@
|
||||
'use strict';
|
||||
|
||||
const GuildChannel = require('./GuildChannel');
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const GuildMessageManager = require('../managers/GuildMessageManager');
|
||||
const GuildTextThreadManager = require('../managers/GuildTextThreadManager');
|
||||
|
||||
/**
|
||||
* Represents a text-based guild channel on Discord.
|
||||
* @extends {GuildChannel}
|
||||
* @implements {TextBasedChannel}
|
||||
*/
|
||||
class BaseGuildTextChannel extends GuildChannel {
|
||||
constructor(guild, data, client) {
|
||||
super(guild, data, client, false);
|
||||
|
||||
/**
|
||||
* A manager of the messages sent to this channel
|
||||
* @type {GuildMessageManager}
|
||||
*/
|
||||
this.messages = new GuildMessageManager(this);
|
||||
|
||||
/**
|
||||
* A manager of the threads belonging to this channel
|
||||
* @type {GuildTextThreadManager}
|
||||
*/
|
||||
this.threads = new GuildTextThreadManager(this);
|
||||
|
||||
/**
|
||||
* If the guild considers this channel NSFW
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.nsfw = Boolean(data.nsfw);
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
super._patch(data);
|
||||
|
||||
if ('topic' in data) {
|
||||
/**
|
||||
* The topic of the text channel
|
||||
* @type {?string}
|
||||
*/
|
||||
this.topic = data.topic;
|
||||
}
|
||||
|
||||
if ('nsfw' in data) {
|
||||
this.nsfw = Boolean(data.nsfw);
|
||||
}
|
||||
|
||||
if ('last_message_id' in data) {
|
||||
/**
|
||||
* The last message id sent in the channel, if one was sent
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.lastMessageId = data.last_message_id;
|
||||
}
|
||||
|
||||
if ('last_pin_timestamp' in data) {
|
||||
/**
|
||||
* The timestamp when the last pinned message was pinned, if there was one
|
||||
* @type {?number}
|
||||
*/
|
||||
this.lastPinTimestamp = data.last_pin_timestamp ? Date.parse(data.last_pin_timestamp) : null;
|
||||
}
|
||||
|
||||
if ('default_auto_archive_duration' in data) {
|
||||
/**
|
||||
* The default auto archive duration for newly created threads in this channel
|
||||
* @type {?ThreadAutoArchiveDuration}
|
||||
*/
|
||||
this.defaultAutoArchiveDuration = data.default_auto_archive_duration;
|
||||
}
|
||||
|
||||
if ('default_thread_rate_limit_per_user' in data) {
|
||||
/**
|
||||
* The initial rate limit per user (slowmode) to set on newly created threads in a channel.
|
||||
* @type {?number}
|
||||
*/
|
||||
this.defaultThreadRateLimitPerUser = data.default_thread_rate_limit_per_user;
|
||||
} else {
|
||||
this.defaultThreadRateLimitPerUser ??= null;
|
||||
}
|
||||
|
||||
if ('messages' in data) {
|
||||
for (const message of data.messages) this.messages._add(message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default auto archive duration for all newly created threads in this channel.
|
||||
* @param {ThreadAutoArchiveDuration} defaultAutoArchiveDuration The new default auto archive duration
|
||||
* @param {string} [reason] Reason for changing the channel's default auto archive duration
|
||||
* @returns {Promise<TextChannel>}
|
||||
*/
|
||||
setDefaultAutoArchiveDuration(defaultAutoArchiveDuration, reason) {
|
||||
return this.edit({ defaultAutoArchiveDuration, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type of this channel.
|
||||
* <info>Only conversion between {@link TextChannel} and {@link NewsChannel} is supported.</info>
|
||||
* @param {ChannelType.GuildText|ChannelType.GuildAnnouncement} type The new channel type
|
||||
* @param {string} [reason] Reason for changing the channel's type
|
||||
* @returns {Promise<GuildChannel>}
|
||||
*/
|
||||
setType(type, reason) {
|
||||
return this.edit({ type, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new topic for the guild channel.
|
||||
* @param {?string} topic The new topic for the guild channel
|
||||
* @param {string} [reason] Reason for changing the guild channel's topic
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Set a new channel topic
|
||||
* channel.setTopic('needs more rate limiting')
|
||||
* .then(newChannel => console.log(`Channel's new topic is ${newChannel.topic}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setTopic(topic, reason) {
|
||||
return this.edit({ topic, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to an Application. This can be:
|
||||
* * An Application
|
||||
* * An Activity with associated Application
|
||||
* * A Snowflake
|
||||
* @typedef {Application|Snowflake} ApplicationResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to create an invite to a guild channel.
|
||||
* @typedef {Object} InviteCreateOptions
|
||||
* @property {boolean} [temporary] Whether members that joined via the invite should be automatically
|
||||
* kicked after 24 hours if they have not yet received a role
|
||||
* @property {number} [maxAge] How long the invite should last (in seconds, 0 for forever)
|
||||
* @property {number} [maxUses] Maximum number of uses
|
||||
* @property {boolean} [unique] Create a unique invite, or use an existing one with similar settings
|
||||
* @property {UserResolvable} [targetUser] The user whose stream to display for this invite,
|
||||
* required if `targetType` is {@link InviteTargetType.Stream}, the user must be streaming in the channel
|
||||
* @property {ApplicationResolvable} [targetApplication] The embedded application to open for this invite,
|
||||
* required if `targetType` is {@link InviteTargetType.Stream}, the application must have the
|
||||
* {@link InviteTargetType.EmbeddedApplication} flag
|
||||
* @property {InviteTargetType} [targetType] The type of the target for this voice channel invite
|
||||
* @property {string} [reason] The reason for creating the invite
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates an invite to this guild channel.
|
||||
* @param {InviteCreateOptions} [options={}] The options for creating the invite
|
||||
* @returns {Promise<Invite>}
|
||||
* @example
|
||||
* // Create an invite to a channel
|
||||
* channel.createInvite()
|
||||
* .then(invite => console.log(`Created an invite with a code of ${invite.code}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
createInvite(options) {
|
||||
return this.guild.invites.create(this.id, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a collection of invites to this guild channel.
|
||||
* Resolves with a collection mapping invites by their codes.
|
||||
* @param {boolean} [cache=true] Whether or not to cache the fetched invites
|
||||
* @returns {Promise<Collection<string, Invite>>}
|
||||
*/
|
||||
fetchInvites(cache = true) {
|
||||
return this.guild.invites.fetch({ channelId: this.id, cache });
|
||||
}
|
||||
|
||||
// These are here only for documentation purposes - they are implemented by TextBasedChannel
|
||||
/* eslint-disable no-empty-function */
|
||||
get lastMessage() {}
|
||||
get lastPinAt() {}
|
||||
send() {}
|
||||
sendTyping() {}
|
||||
createMessageCollector() {}
|
||||
awaitMessages() {}
|
||||
createMessageComponentCollector() {}
|
||||
awaitMessageComponent() {}
|
||||
bulkDelete() {}
|
||||
fetchWebhooks() {}
|
||||
createWebhook() {}
|
||||
setRateLimitPerUser() {}
|
||||
setNSFW() {}
|
||||
}
|
||||
|
||||
TextBasedChannel.applyToClass(BaseGuildTextChannel, true);
|
||||
|
||||
module.exports = BaseGuildTextChannel;
|
||||
234
node_modules/discord.js/src/structures/BaseGuildVoiceChannel.js
generated
vendored
Normal file
234
node_modules/discord.js/src/structures/BaseGuildVoiceChannel.js
generated
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { PermissionFlagsBits } = require('discord-api-types/v10');
|
||||
const GuildChannel = require('./GuildChannel');
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const GuildMessageManager = require('../managers/GuildMessageManager');
|
||||
|
||||
/**
|
||||
* Represents a voice-based guild channel on Discord.
|
||||
* @extends {GuildChannel}
|
||||
* @implements {TextBasedChannel}
|
||||
*/
|
||||
class BaseGuildVoiceChannel extends GuildChannel {
|
||||
constructor(guild, data, client) {
|
||||
super(guild, data, client, false);
|
||||
/**
|
||||
* A manager of the messages sent to this channel
|
||||
* @type {GuildMessageManager}
|
||||
*/
|
||||
this.messages = new GuildMessageManager(this);
|
||||
|
||||
/**
|
||||
* If the guild considers this channel NSFW
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.nsfw = Boolean(data.nsfw);
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
super._patch(data);
|
||||
|
||||
if ('rtc_region' in data) {
|
||||
/**
|
||||
* The RTC region for this voice-based channel. This region is automatically selected if `null`.
|
||||
* @type {?string}
|
||||
*/
|
||||
this.rtcRegion = data.rtc_region;
|
||||
}
|
||||
|
||||
if ('bitrate' in data) {
|
||||
/**
|
||||
* The bitrate of this voice-based channel
|
||||
* @type {number}
|
||||
*/
|
||||
this.bitrate = data.bitrate;
|
||||
}
|
||||
|
||||
if ('user_limit' in data) {
|
||||
/**
|
||||
* The maximum amount of users allowed in this channel.
|
||||
* @type {number}
|
||||
*/
|
||||
this.userLimit = data.user_limit;
|
||||
}
|
||||
|
||||
if ('video_quality_mode' in data) {
|
||||
/**
|
||||
* The camera video quality mode of the channel.
|
||||
* @type {?VideoQualityMode}
|
||||
*/
|
||||
this.videoQualityMode = data.video_quality_mode;
|
||||
} else {
|
||||
this.videoQualityMode ??= null;
|
||||
}
|
||||
|
||||
if ('last_message_id' in data) {
|
||||
/**
|
||||
* The last message id sent in the channel, if one was sent
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.lastMessageId = data.last_message_id;
|
||||
}
|
||||
|
||||
if ('messages' in data) {
|
||||
for (const message of data.messages) this.messages._add(message);
|
||||
}
|
||||
|
||||
if ('rate_limit_per_user' in data) {
|
||||
/**
|
||||
* The rate limit per user (slowmode) for this channel in seconds
|
||||
* @type {number}
|
||||
*/
|
||||
this.rateLimitPerUser = data.rate_limit_per_user;
|
||||
}
|
||||
|
||||
if ('nsfw' in data) {
|
||||
this.nsfw = data.nsfw;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The members in this voice-based channel
|
||||
* @type {Collection<Snowflake, GuildMember>}
|
||||
* @readonly
|
||||
*/
|
||||
get members() {
|
||||
const coll = new Collection();
|
||||
for (const state of this.guild.voiceStates.cache.values()) {
|
||||
if (state.channelId === this.id && state.member) {
|
||||
coll.set(state.id, state.member);
|
||||
}
|
||||
}
|
||||
return coll;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the voice-based channel is full
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get full() {
|
||||
return this.userLimit > 0 && this.members.size >= this.userLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the channel is joinable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get joinable() {
|
||||
if (!this.viewable) return false;
|
||||
const permissions = this.permissionsFor(this.client.user);
|
||||
if (!permissions) return false;
|
||||
|
||||
// This flag allows joining even if timed out
|
||||
if (permissions.has(PermissionFlagsBits.Administrator, false)) return true;
|
||||
|
||||
return (
|
||||
this.guild.members.me.communicationDisabledUntilTimestamp < Date.now() &&
|
||||
permissions.has(PermissionFlagsBits.Connect, false)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an invite to this guild channel.
|
||||
* @param {InviteCreateOptions} [options={}] The options for creating the invite
|
||||
* @returns {Promise<Invite>}
|
||||
* @example
|
||||
* // Create an invite to a channel
|
||||
* channel.createInvite()
|
||||
* .then(invite => console.log(`Created an invite with a code of ${invite.code}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
createInvite(options) {
|
||||
return this.guild.invites.create(this.id, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a collection of invites to this guild channel.
|
||||
* @param {boolean} [cache=true] Whether to cache the fetched invites
|
||||
* @returns {Promise<Collection<string, Invite>>}
|
||||
*/
|
||||
fetchInvites(cache = true) {
|
||||
return this.guild.invites.fetch({ channelId: this.id, cache });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bitrate of the channel.
|
||||
* @param {number} bitrate The new bitrate
|
||||
* @param {string} [reason] Reason for changing the channel's bitrate
|
||||
* @returns {Promise<BaseGuildVoiceChannel>}
|
||||
* @example
|
||||
* // Set the bitrate of a voice channel
|
||||
* channel.setBitrate(48_000)
|
||||
* .then(channel => console.log(`Set bitrate to ${channel.bitrate}bps for ${channel.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setBitrate(bitrate, reason) {
|
||||
return this.edit({ bitrate, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the RTC region of the channel.
|
||||
* @param {?string} rtcRegion The new region of the channel. Set to `null` to remove a specific region for the channel
|
||||
* @param {string} [reason] The reason for modifying this region.
|
||||
* @returns {Promise<BaseGuildVoiceChannel>}
|
||||
* @example
|
||||
* // Set the RTC region to sydney
|
||||
* channel.setRTCRegion('sydney');
|
||||
* @example
|
||||
* // Remove a fixed region for this channel - let Discord decide automatically
|
||||
* channel.setRTCRegion(null, 'We want to let Discord decide.');
|
||||
*/
|
||||
setRTCRegion(rtcRegion, reason) {
|
||||
return this.edit({ rtcRegion, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the user limit of the channel.
|
||||
* @param {number} userLimit The new user limit
|
||||
* @param {string} [reason] Reason for changing the user limit
|
||||
* @returns {Promise<BaseGuildVoiceChannel>}
|
||||
* @example
|
||||
* // Set the user limit of a voice channel
|
||||
* channel.setUserLimit(42)
|
||||
* .then(channel => console.log(`Set user limit to ${channel.userLimit} for ${channel.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setUserLimit(userLimit, reason) {
|
||||
return this.edit({ userLimit, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the camera video quality mode of the channel.
|
||||
* @param {VideoQualityMode} videoQualityMode The new camera video quality mode.
|
||||
* @param {string} [reason] Reason for changing the camera video quality mode.
|
||||
* @returns {Promise<BaseGuildVoiceChannel>}
|
||||
*/
|
||||
setVideoQualityMode(videoQualityMode, reason) {
|
||||
return this.edit({ videoQualityMode, reason });
|
||||
}
|
||||
|
||||
// These are here only for documentation purposes - they are implemented by TextBasedChannel
|
||||
/* eslint-disable no-empty-function */
|
||||
get lastMessage() {}
|
||||
send() {}
|
||||
sendTyping() {}
|
||||
createMessageCollector() {}
|
||||
awaitMessages() {}
|
||||
createMessageComponentCollector() {}
|
||||
awaitMessageComponent() {}
|
||||
bulkDelete() {}
|
||||
fetchWebhooks() {}
|
||||
createWebhook() {}
|
||||
setRateLimitPerUser() {}
|
||||
setNSFW() {}
|
||||
}
|
||||
|
||||
TextBasedChannel.applyToClass(BaseGuildVoiceChannel, true, ['lastPinAt']);
|
||||
|
||||
module.exports = BaseGuildVoiceChannel;
|
||||
349
node_modules/discord.js/src/structures/BaseInteraction.js
generated
vendored
Normal file
349
node_modules/discord.js/src/structures/BaseInteraction.js
generated
vendored
Normal file
@@ -0,0 +1,349 @@
|
||||
'use strict';
|
||||
|
||||
const { deprecate } = require('node:util');
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const { InteractionType, ApplicationCommandType, ComponentType } = require('discord-api-types/v10');
|
||||
const Base = require('./Base');
|
||||
const { SelectMenuTypes } = require('../util/Constants');
|
||||
const PermissionsBitField = require('../util/PermissionsBitField');
|
||||
|
||||
/**
|
||||
* Represents an interaction.
|
||||
* @extends {Base}
|
||||
* @abstract
|
||||
*/
|
||||
class BaseInteraction extends Base {
|
||||
constructor(client, data) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The interaction's type
|
||||
* @type {InteractionType}
|
||||
*/
|
||||
this.type = data.type;
|
||||
|
||||
/**
|
||||
* The interaction's id
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The interaction's token
|
||||
* @type {string}
|
||||
* @name BaseInteraction#token
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'token', { value: data.token });
|
||||
|
||||
/**
|
||||
* The application's id
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.applicationId = data.application_id;
|
||||
|
||||
/**
|
||||
* The id of the channel this interaction was sent in
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.channelId = data.channel?.id ?? null;
|
||||
|
||||
/**
|
||||
* The id of the guild this interaction was sent in
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.guildId = data.guild_id ?? null;
|
||||
|
||||
/**
|
||||
* The user who created this interaction
|
||||
* @type {User}
|
||||
*/
|
||||
this.user = this.client.users._add(data.user ?? data.member.user);
|
||||
|
||||
/**
|
||||
* If this interaction was sent in a guild, the member which sent it
|
||||
* @type {?(GuildMember|APIInteractionGuildMember)}
|
||||
*/
|
||||
this.member = data.member ? (this.guild?.members._add(data.member) ?? data.member) : null;
|
||||
|
||||
/**
|
||||
* The version
|
||||
* @type {number}
|
||||
*/
|
||||
this.version = data.version;
|
||||
|
||||
/**
|
||||
* Set of permissions the application or bot has within the channel the interaction was sent from
|
||||
* @type {Readonly<PermissionsBitField>}
|
||||
*/
|
||||
this.appPermissions = new PermissionsBitField(data.app_permissions).freeze();
|
||||
|
||||
/**
|
||||
* The permissions of the member, if one exists, in the channel this interaction was executed in
|
||||
* @type {?Readonly<PermissionsBitField>}
|
||||
*/
|
||||
this.memberPermissions = data.member?.permissions
|
||||
? new PermissionsBitField(data.member.permissions).freeze()
|
||||
: null;
|
||||
|
||||
/**
|
||||
* The locale of the user who invoked this interaction
|
||||
* @type {Locale}
|
||||
*/
|
||||
this.locale = data.locale;
|
||||
|
||||
/**
|
||||
* The preferred locale from the guild this interaction was sent in
|
||||
* @type {?Locale}
|
||||
*/
|
||||
this.guildLocale = data.guild_locale ?? null;
|
||||
|
||||
/**
|
||||
* The entitlements for the invoking user, representing access to premium SKUs
|
||||
* @type {Collection<Snowflake, Entitlement>}
|
||||
*/
|
||||
this.entitlements = data.entitlements.reduce(
|
||||
(coll, entitlement) => coll.set(entitlement.id, this.client.application.entitlements._add(entitlement)),
|
||||
new Collection(),
|
||||
);
|
||||
|
||||
/* eslint-disable max-len */
|
||||
/**
|
||||
* Mapping of installation contexts that the interaction was authorized for the related user or guild ids
|
||||
* @type {APIAuthorizingIntegrationOwnersMap}
|
||||
* @see {@link https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-object-authorizing-integration-owners-object}
|
||||
*/
|
||||
this.authorizingIntegrationOwners = data.authorizing_integration_owners;
|
||||
/* eslint-enable max-len */
|
||||
|
||||
/**
|
||||
* Context where the interaction was triggered from
|
||||
* @type {?InteractionContextType}
|
||||
*/
|
||||
this.context = data.context ?? null;
|
||||
|
||||
/**
|
||||
* Attachment size limit in bytes
|
||||
* @type {number}
|
||||
*/
|
||||
this.attachmentSizeLimit = data.attachment_size_limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp the interaction was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the interaction was created at
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The channel this interaction was sent in
|
||||
* @type {?TextBasedChannels}
|
||||
* @readonly
|
||||
*/
|
||||
get channel() {
|
||||
return this.client.channels.cache.get(this.channelId) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The guild this interaction was sent in
|
||||
* @type {?Guild}
|
||||
* @readonly
|
||||
*/
|
||||
get guild() {
|
||||
return this.client.guilds.cache.get(this.guildId) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is received from a guild.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
inGuild() {
|
||||
return Boolean(this.guildId && this.member);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is received from a cached guild.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
inCachedGuild() {
|
||||
return Boolean(this.guild && this.member);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether or not this interaction is received from an uncached guild.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
inRawGuild() {
|
||||
return Boolean(this.guildId && !this.guild && this.member);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is an {@link AutocompleteInteraction}
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isAutocomplete() {
|
||||
return this.type === InteractionType.ApplicationCommandAutocomplete;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link CommandInteraction}
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isCommand() {
|
||||
return this.type === InteractionType.ApplicationCommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link ChatInputCommandInteraction}.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isChatInputCommand() {
|
||||
return this.type === InteractionType.ApplicationCommand && this.commandType === ApplicationCommandType.ChatInput;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link ContextMenuCommandInteraction}
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isContextMenuCommand() {
|
||||
return (
|
||||
this.type === InteractionType.ApplicationCommand &&
|
||||
[ApplicationCommandType.User, ApplicationCommandType.Message].includes(this.commandType)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link PrimaryEntryPointCommandInteraction}
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isPrimaryEntryPointCommand() {
|
||||
return (
|
||||
this.type === InteractionType.ApplicationCommand && this.commandType === ApplicationCommandType.PrimaryEntryPoint
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link MessageComponentInteraction}
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isMessageComponent() {
|
||||
return this.type === InteractionType.MessageComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link ModalSubmitInteraction}
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isModalSubmit() {
|
||||
return this.type === InteractionType.ModalSubmit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link UserContextMenuCommandInteraction}
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isUserContextMenuCommand() {
|
||||
return this.isContextMenuCommand() && this.commandType === ApplicationCommandType.User;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link MessageContextMenuCommandInteraction}
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isMessageContextMenuCommand() {
|
||||
return this.isContextMenuCommand() && this.commandType === ApplicationCommandType.Message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link ButtonInteraction}.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isButton() {
|
||||
return this.type === InteractionType.MessageComponent && this.componentType === ComponentType.Button;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link StringSelectMenuInteraction}.
|
||||
* @returns {boolean}
|
||||
* @deprecated Use {@link BaseInteraction#isStringSelectMenu} instead.
|
||||
*/
|
||||
isSelectMenu() {
|
||||
return this.isStringSelectMenu();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a select menu of any known type.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isAnySelectMenu() {
|
||||
return this.type === InteractionType.MessageComponent && SelectMenuTypes.includes(this.componentType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link StringSelectMenuInteraction}.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isStringSelectMenu() {
|
||||
return this.type === InteractionType.MessageComponent && this.componentType === ComponentType.StringSelect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link UserSelectMenuInteraction}
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isUserSelectMenu() {
|
||||
return this.type === InteractionType.MessageComponent && this.componentType === ComponentType.UserSelect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link RoleSelectMenuInteraction}
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isRoleSelectMenu() {
|
||||
return this.type === InteractionType.MessageComponent && this.componentType === ComponentType.RoleSelect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link ChannelSelectMenuInteraction}
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isChannelSelectMenu() {
|
||||
return this.type === InteractionType.MessageComponent && this.componentType === ComponentType.ChannelSelect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction is a {@link MentionableSelectMenuInteraction}
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isMentionableSelectMenu() {
|
||||
return this.type === InteractionType.MessageComponent && this.componentType === ComponentType.MentionableSelect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this interaction can be replied to.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isRepliable() {
|
||||
return ![InteractionType.Ping, InteractionType.ApplicationCommandAutocomplete].includes(this.type);
|
||||
}
|
||||
}
|
||||
|
||||
BaseInteraction.prototype.isSelectMenu = deprecate(
|
||||
BaseInteraction.prototype.isSelectMenu,
|
||||
'BaseInteraction#isSelectMenu() is deprecated. Use BaseInteraction#isStringSelectMenu() instead.',
|
||||
);
|
||||
|
||||
module.exports = BaseInteraction;
|
||||
56
node_modules/discord.js/src/structures/BaseSelectMenuComponent.js
generated
vendored
Normal file
56
node_modules/discord.js/src/structures/BaseSelectMenuComponent.js
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
'use strict';
|
||||
|
||||
const Component = require('./Component');
|
||||
|
||||
/**
|
||||
* Represents a select menu component
|
||||
* @extends {Component}
|
||||
*/
|
||||
class BaseSelectMenuComponent extends Component {
|
||||
/**
|
||||
* The placeholder for this select menu
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get placeholder() {
|
||||
return this.data.placeholder ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The maximum amount of options that can be selected
|
||||
* @type {?number}
|
||||
* @readonly
|
||||
*/
|
||||
get maxValues() {
|
||||
return this.data.max_values ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The minimum amount of options that must be selected
|
||||
* @type {?number}
|
||||
* @readonly
|
||||
*/
|
||||
get minValues() {
|
||||
return this.data.min_values ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The custom id of this select menu
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get customId() {
|
||||
return this.data.custom_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this select menu is disabled
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get disabled() {
|
||||
return this.data.disabled ?? false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BaseSelectMenuComponent;
|
||||
44
node_modules/discord.js/src/structures/ButtonBuilder.js
generated
vendored
Normal file
44
node_modules/discord.js/src/structures/ButtonBuilder.js
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
'use strict';
|
||||
|
||||
const { ButtonBuilder: BuildersButton } = require('@discordjs/builders');
|
||||
const { isJSONEncodable } = require('@discordjs/util');
|
||||
const { toSnakeCase } = require('../util/Transformers');
|
||||
const { resolvePartialEmoji } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents a button builder.
|
||||
* @extends {BuildersButton}
|
||||
*/
|
||||
class ButtonBuilder extends BuildersButton {
|
||||
constructor({ emoji, ...data } = {}) {
|
||||
super(toSnakeCase({ ...data, emoji: emoji && typeof emoji === 'string' ? resolvePartialEmoji(emoji) : emoji }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the emoji to display on this button
|
||||
* @param {string|APIMessageComponentEmoji} emoji The emoji to display on this button
|
||||
* @returns {ButtonBuilder}
|
||||
*/
|
||||
setEmoji(emoji) {
|
||||
if (typeof emoji === 'string') {
|
||||
return super.setEmoji(resolvePartialEmoji(emoji));
|
||||
}
|
||||
return super.setEmoji(emoji);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new button builder from JSON data
|
||||
* @param {ButtonBuilder|ButtonComponent|APIButtonComponent} other The other data
|
||||
* @returns {ButtonBuilder}
|
||||
*/
|
||||
static from(other) {
|
||||
return new this(isJSONEncodable(other) ? other.toJSON() : other);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ButtonBuilder;
|
||||
|
||||
/**
|
||||
* @external BuildersButton
|
||||
* @see {@link https://discord.js.org/docs/packages/builders/stable/ButtonBuilder:Class}
|
||||
*/
|
||||
65
node_modules/discord.js/src/structures/ButtonComponent.js
generated
vendored
Normal file
65
node_modules/discord.js/src/structures/ButtonComponent.js
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
'use strict';
|
||||
|
||||
const Component = require('./Component');
|
||||
|
||||
/**
|
||||
* Represents a button component
|
||||
* @extends {Component}
|
||||
*/
|
||||
class ButtonComponent extends Component {
|
||||
/**
|
||||
* The style of this button
|
||||
* @type {ButtonStyle}
|
||||
* @readonly
|
||||
*/
|
||||
get style() {
|
||||
return this.data.style;
|
||||
}
|
||||
|
||||
/**
|
||||
* The label of this button
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get label() {
|
||||
return this.data.label ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The emoji used in this button
|
||||
* @type {?APIMessageComponentEmoji}
|
||||
* @readonly
|
||||
*/
|
||||
get emoji() {
|
||||
return this.data.emoji ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this button is disabled
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get disabled() {
|
||||
return this.data.disabled ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* The custom id of this button (only defined on non-link buttons)
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get customId() {
|
||||
return this.data.custom_id ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL of this button (only defined on link buttons)
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get url() {
|
||||
return this.data.url ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ButtonComponent;
|
||||
11
node_modules/discord.js/src/structures/ButtonInteraction.js
generated
vendored
Normal file
11
node_modules/discord.js/src/structures/ButtonInteraction.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const MessageComponentInteraction = require('./MessageComponentInteraction');
|
||||
|
||||
/**
|
||||
* Represents a button interaction.
|
||||
* @extends {MessageComponentInteraction}
|
||||
*/
|
||||
class ButtonInteraction extends MessageComponentInteraction {}
|
||||
|
||||
module.exports = ButtonInteraction;
|
||||
45
node_modules/discord.js/src/structures/CategoryChannel.js
generated
vendored
Normal file
45
node_modules/discord.js/src/structures/CategoryChannel.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
'use strict';
|
||||
|
||||
const GuildChannel = require('./GuildChannel');
|
||||
const CategoryChannelChildManager = require('../managers/CategoryChannelChildManager');
|
||||
|
||||
/**
|
||||
* Represents a guild category channel on Discord.
|
||||
* @extends {GuildChannel}
|
||||
*/
|
||||
class CategoryChannel extends GuildChannel {
|
||||
/**
|
||||
* The id of the parent of this channel.
|
||||
* @name CategoryChannel#parentId
|
||||
* @type {null}
|
||||
*/
|
||||
|
||||
/**
|
||||
* The parent of this channel.
|
||||
* @name CategoryChannel#parent
|
||||
* @type {null}
|
||||
* @readonly
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sets the category parent of this channel.
|
||||
* <warn>It is not possible to set the parent of a CategoryChannel.</warn>
|
||||
* @method setParent
|
||||
* @memberof CategoryChannel
|
||||
* @instance
|
||||
* @param {?CategoryChannelResolvable} channel The channel to set as parent
|
||||
* @param {SetParentOptions} [options={}] The options for setting the parent
|
||||
* @returns {Promise<GuildChannel>}
|
||||
*/
|
||||
|
||||
/**
|
||||
* A manager of the channels belonging to this category
|
||||
* @type {CategoryChannelChildManager}
|
||||
* @readonly
|
||||
*/
|
||||
get children() {
|
||||
return new CategoryChannelChildManager(this);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CategoryChannel;
|
||||
31
node_modules/discord.js/src/structures/ChannelSelectMenuBuilder.js
generated
vendored
Normal file
31
node_modules/discord.js/src/structures/ChannelSelectMenuBuilder.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
const { ChannelSelectMenuBuilder: BuildersChannelSelectMenu } = require('@discordjs/builders');
|
||||
const { isJSONEncodable } = require('@discordjs/util');
|
||||
const { toSnakeCase } = require('../util/Transformers');
|
||||
|
||||
/**
|
||||
* Class used to build select menu components to be sent through the API
|
||||
* @extends {BuildersChannelSelectMenu}
|
||||
*/
|
||||
class ChannelSelectMenuBuilder extends BuildersChannelSelectMenu {
|
||||
constructor(data = {}) {
|
||||
super(toSnakeCase(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new select menu builder from JSON data
|
||||
* @param {ChannelSelectMenuBuilder|ChannelSelectMenuComponent|APIChannelSelectComponent} other The other data
|
||||
* @returns {ChannelSelectMenuBuilder}
|
||||
*/
|
||||
static from(other) {
|
||||
return new this(isJSONEncodable(other) ? other.toJSON() : other);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ChannelSelectMenuBuilder;
|
||||
|
||||
/**
|
||||
* @external BuildersChannelSelectMenu
|
||||
* @see {@link https://discord.js.org/docs/packages/builders/stable/ChannelSelectMenuBuilder:Class}
|
||||
*/
|
||||
20
node_modules/discord.js/src/structures/ChannelSelectMenuComponent.js
generated
vendored
Normal file
20
node_modules/discord.js/src/structures/ChannelSelectMenuComponent.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
const BaseSelectMenuComponent = require('./BaseSelectMenuComponent');
|
||||
|
||||
/**
|
||||
* Represents a channel select menu component
|
||||
* @extends {BaseSelectMenuComponent}
|
||||
*/
|
||||
class ChannelSelectMenuComponent extends BaseSelectMenuComponent {
|
||||
/**
|
||||
* The options in this select menu
|
||||
* @type {?(ChannelType[])}
|
||||
* @readonly
|
||||
*/
|
||||
get channelTypes() {
|
||||
return this.data.channel_types ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ChannelSelectMenuComponent;
|
||||
33
node_modules/discord.js/src/structures/ChannelSelectMenuInteraction.js
generated
vendored
Normal file
33
node_modules/discord.js/src/structures/ChannelSelectMenuInteraction.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const MessageComponentInteraction = require('./MessageComponentInteraction');
|
||||
|
||||
/**
|
||||
* Represents a {@link ComponentType.ChannelSelect} select menu interaction.
|
||||
* @extends {MessageComponentInteraction}
|
||||
*/
|
||||
class ChannelSelectMenuInteraction extends MessageComponentInteraction {
|
||||
constructor(client, data) {
|
||||
super(client, data);
|
||||
const { resolved, values } = data.data;
|
||||
|
||||
/**
|
||||
* An array of the selected channel ids
|
||||
* @type {Snowflake[]}
|
||||
*/
|
||||
this.values = values ?? [];
|
||||
|
||||
/**
|
||||
* Collection of the selected channels
|
||||
* @type {Collection<Snowflake, BaseChannel|APIChannel>}
|
||||
*/
|
||||
this.channels = new Collection();
|
||||
|
||||
for (const channel of Object.values(resolved?.channels ?? {})) {
|
||||
this.channels.set(channel.id, this.client.channels._add(channel, this.guild) ?? channel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ChannelSelectMenuInteraction;
|
||||
42
node_modules/discord.js/src/structures/ChatInputCommandInteraction.js
generated
vendored
Normal file
42
node_modules/discord.js/src/structures/ChatInputCommandInteraction.js
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
'use strict';
|
||||
|
||||
const CommandInteraction = require('./CommandInteraction');
|
||||
const CommandInteractionOptionResolver = require('./CommandInteractionOptionResolver');
|
||||
const { transformResolved } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents a command interaction.
|
||||
* @extends {CommandInteraction}
|
||||
*/
|
||||
class ChatInputCommandInteraction extends CommandInteraction {
|
||||
constructor(client, data) {
|
||||
super(client, data);
|
||||
|
||||
/**
|
||||
* The options passed to the command.
|
||||
* @type {CommandInteractionOptionResolver}
|
||||
*/
|
||||
this.options = new CommandInteractionOptionResolver(
|
||||
this.client,
|
||||
data.data.options?.map(option => this.transformOption(option, data.data.resolved)) ?? [],
|
||||
transformResolved({ client: this.client, guild: this.guild, channel: this.channel }, data.data.resolved),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the command interaction.
|
||||
* This can then be copied by a user and executed again in a new command while keeping the option order.
|
||||
* @returns {string}
|
||||
*/
|
||||
toString() {
|
||||
const properties = [
|
||||
this.commandName,
|
||||
this.options._group,
|
||||
this.options._subcommand,
|
||||
...this.options._hoistedOptions.map(option => `${option.name}:${option.value}`),
|
||||
];
|
||||
return `/${properties.filter(Boolean).join(' ')}`;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ChatInputCommandInteraction;
|
||||
415
node_modules/discord.js/src/structures/ClientApplication.js
generated
vendored
Normal file
415
node_modules/discord.js/src/structures/ClientApplication.js
generated
vendored
Normal file
@@ -0,0 +1,415 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const { ApplicationRoleConnectionMetadata } = require('./ApplicationRoleConnectionMetadata');
|
||||
const { SKU } = require('./SKU');
|
||||
const Team = require('./Team');
|
||||
const Application = require('./interfaces/Application');
|
||||
const ApplicationCommandManager = require('../managers/ApplicationCommandManager');
|
||||
const ApplicationEmojiManager = require('../managers/ApplicationEmojiManager');
|
||||
const { EntitlementManager } = require('../managers/EntitlementManager');
|
||||
const { SubscriptionManager } = require('../managers/SubscriptionManager');
|
||||
const ApplicationFlagsBitField = require('../util/ApplicationFlagsBitField');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
const PermissionsBitField = require('../util/PermissionsBitField');
|
||||
|
||||
/**
|
||||
* @typedef {Object} ClientApplicationInstallParams
|
||||
* @property {OAuth2Scopes[]} scopes Scopes that will be set upon adding this application
|
||||
* @property {Readonly<PermissionsBitField>} permissions Permissions that will be requested for the integrated role
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a client application.
|
||||
* @extends {Application}
|
||||
*/
|
||||
class ClientApplication extends Application {
|
||||
constructor(client, data) {
|
||||
super(client, data);
|
||||
|
||||
/**
|
||||
* The application command manager for this application
|
||||
* @type {ApplicationCommandManager}
|
||||
*/
|
||||
this.commands = new ApplicationCommandManager(this.client);
|
||||
|
||||
/**
|
||||
* The application emoji manager for this application
|
||||
* @type {ApplicationEmojiManager}
|
||||
*/
|
||||
this.emojis = new ApplicationEmojiManager(this);
|
||||
|
||||
/**
|
||||
* The entitlement manager for this application
|
||||
* @type {EntitlementManager}
|
||||
*/
|
||||
this.entitlements = new EntitlementManager(this.client);
|
||||
|
||||
/**
|
||||
* The subscription manager for this application
|
||||
* @type {SubscriptionManager}
|
||||
*/
|
||||
this.subscriptions = new SubscriptionManager(this.client);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
super._patch(data);
|
||||
|
||||
/**
|
||||
* The tags this application has (max of 5)
|
||||
* @type {string[]}
|
||||
*/
|
||||
this.tags = data.tags ?? [];
|
||||
|
||||
if ('install_params' in data) {
|
||||
/**
|
||||
* Settings for this application's default in-app authorization
|
||||
* @type {?ClientApplicationInstallParams}
|
||||
*/
|
||||
this.installParams = {
|
||||
scopes: data.install_params.scopes,
|
||||
permissions: new PermissionsBitField(data.install_params.permissions).freeze(),
|
||||
};
|
||||
} else {
|
||||
this.installParams ??= null;
|
||||
}
|
||||
|
||||
/**
|
||||
* OAuth2 installation parameters.
|
||||
* @typedef {Object} IntegrationTypesConfigurationParameters
|
||||
* @property {OAuth2Scopes[]} scopes Scopes that will be set upon adding this application
|
||||
* @property {Readonly<PermissionsBitField>} permissions Permissions that will be requested for the integrated role
|
||||
*/
|
||||
|
||||
/**
|
||||
* The application's supported installation context data.
|
||||
* @typedef {Object} IntegrationTypesConfigurationContext
|
||||
* @property {?IntegrationTypesConfigurationParameters} oauth2InstallParams
|
||||
* Scopes and permissions regarding the installation context
|
||||
*/
|
||||
|
||||
/**
|
||||
* The application's supported installation context data.
|
||||
* @typedef {Object} IntegrationTypesConfiguration
|
||||
* @property {IntegrationTypesConfigurationContext} [0] Scopes and permissions
|
||||
* regarding the guild-installation context
|
||||
* @property {IntegrationTypesConfigurationContext} [1] Scopes and permissions
|
||||
* regarding the user-installation context
|
||||
*/
|
||||
|
||||
if ('integration_types_config' in data) {
|
||||
/**
|
||||
* Default scopes and permissions for each supported installation context.
|
||||
* The keys are stringified variants of {@link ApplicationIntegrationType}.
|
||||
* @type {?IntegrationTypesConfiguration}
|
||||
*/
|
||||
this.integrationTypesConfig = Object.fromEntries(
|
||||
Object.entries(data.integration_types_config).map(([key, config]) => {
|
||||
let oauth2InstallParams = null;
|
||||
if (config.oauth2_install_params) {
|
||||
oauth2InstallParams = {
|
||||
scopes: config.oauth2_install_params.scopes,
|
||||
permissions: new PermissionsBitField(config.oauth2_install_params.permissions).freeze(),
|
||||
};
|
||||
}
|
||||
|
||||
const context = {
|
||||
oauth2InstallParams,
|
||||
};
|
||||
|
||||
return [key, context];
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
this.integrationTypesConfig ??= null;
|
||||
}
|
||||
|
||||
if ('custom_install_url' in data) {
|
||||
/**
|
||||
* This application's custom installation URL
|
||||
* @type {?string}
|
||||
*/
|
||||
this.customInstallURL = data.custom_install_url;
|
||||
} else {
|
||||
this.customInstallURL = null;
|
||||
}
|
||||
|
||||
if ('flags' in data) {
|
||||
/**
|
||||
* The flags this application has
|
||||
* @type {ApplicationFlagsBitField}
|
||||
*/
|
||||
this.flags = new ApplicationFlagsBitField(data.flags).freeze();
|
||||
}
|
||||
|
||||
if ('approximate_guild_count' in data) {
|
||||
/**
|
||||
* An approximate amount of guilds this application is in.
|
||||
* @type {?number}
|
||||
*/
|
||||
this.approximateGuildCount = data.approximate_guild_count;
|
||||
} else {
|
||||
this.approximateGuildCount ??= null;
|
||||
}
|
||||
|
||||
if ('approximate_user_install_count' in data) {
|
||||
/**
|
||||
* An approximate amount of users that have installed this application.
|
||||
* @type {?number}
|
||||
*/
|
||||
this.approximateUserInstallCount = data.approximate_user_install_count;
|
||||
} else {
|
||||
this.approximateUserInstallCount ??= null;
|
||||
}
|
||||
|
||||
if ('approximate_user_authorization_count' in data) {
|
||||
/**
|
||||
* An approximate amount of users that have OAuth2 authorizations for this application.
|
||||
*
|
||||
* @type {?number}
|
||||
*/
|
||||
this.approximateUserAuthorizationCount = data.approximate_user_authorization_count;
|
||||
} else {
|
||||
this.approximateUserAuthorizationCount ??= null;
|
||||
}
|
||||
|
||||
if ('guild_id' in data) {
|
||||
/**
|
||||
* The id of the guild associated with this application.
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.guildId = data.guild_id;
|
||||
} else {
|
||||
this.guildId ??= null;
|
||||
}
|
||||
|
||||
if ('bot_require_code_grant' in data) {
|
||||
/**
|
||||
* If this application's bot requires a code grant when using the OAuth2 flow
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.botRequireCodeGrant = data.bot_require_code_grant;
|
||||
} else {
|
||||
this.botRequireCodeGrant ??= null;
|
||||
}
|
||||
|
||||
if ('bot' in data) {
|
||||
/**
|
||||
* The bot associated with this application.
|
||||
* @type {?User}
|
||||
*/
|
||||
this.bot = this.client.users._add(data.bot);
|
||||
} else {
|
||||
this.bot ??= null;
|
||||
}
|
||||
|
||||
if ('bot_public' in data) {
|
||||
/**
|
||||
* If this application's bot is public
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.botPublic = data.bot_public;
|
||||
} else {
|
||||
this.botPublic ??= null;
|
||||
}
|
||||
|
||||
if ('interactions_endpoint_url' in data) {
|
||||
/**
|
||||
* This application's interaction endpoint URL.
|
||||
* @type {?string}
|
||||
*/
|
||||
this.interactionsEndpointURL = data.interactions_endpoint_url;
|
||||
} else {
|
||||
this.interactionsEndpointURL ??= null;
|
||||
}
|
||||
|
||||
if ('role_connections_verification_url' in data) {
|
||||
/**
|
||||
* This application's role connection verification entry point URL
|
||||
* @type {?string}
|
||||
*/
|
||||
this.roleConnectionsVerificationURL = data.role_connections_verification_url;
|
||||
} else {
|
||||
this.roleConnectionsVerificationURL ??= null;
|
||||
}
|
||||
|
||||
if ('event_webhooks_url' in data) {
|
||||
/**
|
||||
* This application's URL to receive event webhooks
|
||||
* @type {?string}
|
||||
*/
|
||||
this.eventWebhooksURL = data.event_webhooks_url;
|
||||
} else {
|
||||
this.eventWebhooksURL ??= null;
|
||||
}
|
||||
|
||||
if ('event_webhooks_status' in data) {
|
||||
/**
|
||||
* This application's event webhooks status
|
||||
* @type {?ApplicationWebhookEventStatus}
|
||||
*/
|
||||
this.eventWebhooksStatus = data.event_webhooks_status;
|
||||
} else {
|
||||
this.eventWebhooksStatus ??= null;
|
||||
}
|
||||
|
||||
if ('event_webhooks_types' in data) {
|
||||
/**
|
||||
* List of event webhooks types this application subscribes to
|
||||
* @type {?ApplicationWebhookEventType[]}
|
||||
*/
|
||||
this.eventWebhooksTypes = data.event_webhooks_types;
|
||||
} else {
|
||||
this.eventWebhooksTypes ??= null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The owner of this OAuth application
|
||||
* @type {?(User|Team)}
|
||||
*/
|
||||
this.owner = data.team
|
||||
? new Team(this.client, data.team)
|
||||
: data.owner
|
||||
? this.client.users._add(data.owner)
|
||||
: (this.owner ?? null);
|
||||
}
|
||||
|
||||
/**
|
||||
* The guild associated with this application.
|
||||
* @type {?Guild}
|
||||
* @readonly
|
||||
*/
|
||||
get guild() {
|
||||
return this.client.guilds.cache.get(this.guildId) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this application is partial
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get partial() {
|
||||
return !this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used for editing an application.
|
||||
* @typedef {Object} ClientApplicationEditOptions
|
||||
* @property {string} [customInstallURL] The application's custom installation URL
|
||||
* @property {string} [description] The application's description
|
||||
* @property {string} [roleConnectionsVerificationURL] The application's role connection verification URL
|
||||
* @property {ClientApplicationInstallParams} [installParams]
|
||||
* Settings for the application's default in-app authorization
|
||||
* @property {ApplicationFlagsResolvable} [flags] The flags for the application
|
||||
* @property {?(BufferResolvable|Base64Resolvable)} [icon] The application's icon
|
||||
* @property {?(BufferResolvable|Base64Resolvable)} [coverImage] The application's cover image
|
||||
* @property {string} [interactionsEndpointURL] The application's interaction endpoint URL
|
||||
* @property {string} [eventWebhooksURL] The application's event webhooks URL
|
||||
* @property {ApplicationWebhookEventStatus.Enabled|ApplicationWebhookEventStatus.Disabled} [eventWebhooksStatus]
|
||||
* The application's event webhooks status.
|
||||
* @property {ApplicationWebhookEventType[]} [eventWebhooksTypes] The application's event webhooks types
|
||||
* @property {string[]} [tags] The application's tags
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits this application.
|
||||
* @param {ClientApplicationEditOptions} [options] The options for editing this application
|
||||
* @returns {Promise<ClientApplication>}
|
||||
*/
|
||||
async edit({
|
||||
customInstallURL,
|
||||
description,
|
||||
roleConnectionsVerificationURL,
|
||||
installParams,
|
||||
flags,
|
||||
icon,
|
||||
coverImage,
|
||||
interactionsEndpointURL,
|
||||
eventWebhooksURL,
|
||||
eventWebhooksStatus,
|
||||
eventWebhooksTypes,
|
||||
tags,
|
||||
} = {}) {
|
||||
const data = await this.client.rest.patch(Routes.currentApplication(), {
|
||||
body: {
|
||||
custom_install_url: customInstallURL,
|
||||
description,
|
||||
role_connections_verification_url: roleConnectionsVerificationURL,
|
||||
install_params: installParams,
|
||||
flags: flags === undefined ? undefined : ApplicationFlagsBitField.resolve(flags),
|
||||
icon: icon && (await resolveImage(icon)),
|
||||
cover_image: coverImage && (await resolveImage(coverImage)),
|
||||
interactions_endpoint_url: interactionsEndpointURL,
|
||||
event_webhooks_url: eventWebhooksURL,
|
||||
event_webhooks_status: eventWebhooksStatus,
|
||||
event_webhooks_types: eventWebhooksTypes,
|
||||
tags,
|
||||
},
|
||||
});
|
||||
|
||||
this._patch(data);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains this application from Discord.
|
||||
* @returns {Promise<ClientApplication>}
|
||||
*/
|
||||
async fetch() {
|
||||
const data = await this.client.rest.get(Routes.currentApplication());
|
||||
this._patch(data);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this application's role connection metadata records
|
||||
* @returns {Promise<ApplicationRoleConnectionMetadata[]>}
|
||||
*/
|
||||
async fetchRoleConnectionMetadataRecords() {
|
||||
const metadata = await this.client.rest.get(Routes.applicationRoleConnectionMetadata(this.client.user.id));
|
||||
return metadata.map(data => new ApplicationRoleConnectionMetadata(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data for creating or editing an application role connection metadata.
|
||||
* @typedef {Object} ApplicationRoleConnectionMetadataEditOptions
|
||||
* @property {string} name The name of the metadata field
|
||||
* @property {?LocalizationMap} [nameLocalizations] The name localizations for the metadata field
|
||||
* @property {string} description The description of the metadata field
|
||||
* @property {?LocalizationMap} [descriptionLocalizations] The description localizations for the metadata field
|
||||
* @property {string} key The dictionary key of the metadata field
|
||||
* @property {ApplicationRoleConnectionMetadataType} type The type of the metadata field
|
||||
*/
|
||||
|
||||
/**
|
||||
* Updates this application's role connection metadata records
|
||||
* @param {ApplicationRoleConnectionMetadataEditOptions[]} records The new role connection metadata records
|
||||
* @returns {Promise<ApplicationRoleConnectionMetadata[]>}
|
||||
*/
|
||||
async editRoleConnectionMetadataRecords(records) {
|
||||
const newRecords = await this.client.rest.put(Routes.applicationRoleConnectionMetadata(this.client.user.id), {
|
||||
body: records.map(record => ({
|
||||
type: record.type,
|
||||
key: record.key,
|
||||
name: record.name,
|
||||
name_localizations: record.nameLocalizations,
|
||||
description: record.description,
|
||||
description_localizations: record.descriptionLocalizations,
|
||||
})),
|
||||
});
|
||||
|
||||
return newRecords.map(data => new ApplicationRoleConnectionMetadata(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets this application's SKUs
|
||||
* @returns {Promise<Collection<Snowflake, SKU>>}
|
||||
*/
|
||||
async fetchSKUs() {
|
||||
const skus = await this.client.rest.get(Routes.skus(this.id));
|
||||
return skus.reduce((coll, sku) => coll.set(sku.id, new SKU(this.client, sku)), new Collection());
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ClientApplication;
|
||||
84
node_modules/discord.js/src/structures/ClientPresence.js
generated
vendored
Normal file
84
node_modules/discord.js/src/structures/ClientPresence.js
generated
vendored
Normal file
@@ -0,0 +1,84 @@
|
||||
'use strict';
|
||||
|
||||
const { GatewayOpcodes, ActivityType } = require('discord-api-types/v10');
|
||||
const { Presence } = require('./Presence');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
|
||||
/**
|
||||
* Represents the client's presence.
|
||||
* @extends {Presence}
|
||||
*/
|
||||
class ClientPresence extends Presence {
|
||||
constructor(client, data = {}) {
|
||||
super(client, Object.assign(data, { status: data.status ?? 'online', user: { id: null } }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the client's presence
|
||||
* @param {PresenceData} presence The data to set the presence to
|
||||
* @returns {ClientPresence}
|
||||
*/
|
||||
set(presence) {
|
||||
const packet = this._parse(presence);
|
||||
this._patch(packet);
|
||||
if (presence.shardId === undefined) {
|
||||
this.client.ws.broadcast({ op: GatewayOpcodes.PresenceUpdate, d: packet });
|
||||
} else if (Array.isArray(presence.shardId)) {
|
||||
for (const shardId of presence.shardId) {
|
||||
this.client.ws.shards.get(shardId).send({ op: GatewayOpcodes.PresenceUpdate, d: packet });
|
||||
}
|
||||
} else {
|
||||
this.client.ws.shards.get(presence.shardId).send({ op: GatewayOpcodes.PresenceUpdate, d: packet });
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses presence data into a packet ready to be sent to Discord
|
||||
* @param {PresenceData} presence The data to parse
|
||||
* @returns {GatewayPresenceUpdateData}
|
||||
* @private
|
||||
*/
|
||||
_parse({ status, since, afk, activities }) {
|
||||
const data = {
|
||||
activities: [],
|
||||
afk: typeof afk === 'boolean' ? afk : false,
|
||||
since: typeof since === 'number' && !Number.isNaN(since) ? since : null,
|
||||
status: status ?? this.status,
|
||||
};
|
||||
if (activities?.length) {
|
||||
for (const [i, activity] of activities.entries()) {
|
||||
if (typeof activity.name !== 'string') {
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidType, `activities[${i}].name`, 'string');
|
||||
}
|
||||
|
||||
activity.type ??= ActivityType.Playing;
|
||||
|
||||
if (activity.type === ActivityType.Custom && !activity.state) {
|
||||
activity.state = activity.name;
|
||||
activity.name = 'Custom Status';
|
||||
}
|
||||
|
||||
data.activities.push({
|
||||
type: activity.type,
|
||||
name: activity.name,
|
||||
state: activity.state,
|
||||
url: activity.url,
|
||||
});
|
||||
}
|
||||
} else if (!activities && (status || afk || since) && this.activities.length) {
|
||||
data.activities.push(
|
||||
...this.activities.map(activity => ({
|
||||
name: activity.name,
|
||||
state: activity.state ?? undefined,
|
||||
type: activity.type,
|
||||
url: activity.url ?? undefined,
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ClientPresence;
|
||||
204
node_modules/discord.js/src/structures/ClientUser.js
generated
vendored
Normal file
204
node_modules/discord.js/src/structures/ClientUser.js
generated
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
'use strict';
|
||||
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const User = require('./User');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
|
||||
/**
|
||||
* Represents the logged in client's Discord user.
|
||||
* @extends {User}
|
||||
*/
|
||||
class ClientUser extends User {
|
||||
_patch(data) {
|
||||
super._patch(data);
|
||||
|
||||
if ('verified' in data) {
|
||||
/**
|
||||
* Whether or not this account has been verified
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.verified = data.verified;
|
||||
}
|
||||
|
||||
if ('mfa_enabled' in data) {
|
||||
/**
|
||||
* If the bot's {@link ClientApplication#owner Owner} has MFA enabled on their account
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.mfaEnabled = typeof data.mfa_enabled === 'boolean' ? data.mfa_enabled : null;
|
||||
} else {
|
||||
this.mfaEnabled ??= null;
|
||||
}
|
||||
|
||||
if ('token' in data) this.client.token = data.token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the client user's presence
|
||||
* @type {ClientPresence}
|
||||
* @readonly
|
||||
*/
|
||||
get presence() {
|
||||
return this.client.presence;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data used to edit the logged in client
|
||||
* @typedef {Object} ClientUserEditOptions
|
||||
* @property {string} [username] The new username
|
||||
* @property {?(BufferResolvable|Base64Resolvable)} [avatar] The new avatar
|
||||
* @property {?(BufferResolvable|Base64Resolvable)} [banner] The new banner
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits the logged in client.
|
||||
* @param {ClientUserEditOptions} options The options to provide
|
||||
* @returns {Promise<ClientUser>}
|
||||
*/
|
||||
async edit({ username, avatar, banner }) {
|
||||
const data = await this.client.rest.patch(Routes.user(), {
|
||||
body: {
|
||||
username,
|
||||
avatar: avatar && (await resolveImage(avatar)),
|
||||
banner: banner && (await resolveImage(banner)),
|
||||
},
|
||||
});
|
||||
|
||||
const { updated } = this.client.actions.UserUpdate.handle(data);
|
||||
return updated ?? this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the username of the logged in client.
|
||||
* <info>Changing usernames in Discord is heavily rate limited, with only 2 requests
|
||||
* every hour. Use this sparingly!</info>
|
||||
* @param {string} username The new username
|
||||
* @returns {Promise<ClientUser>}
|
||||
* @example
|
||||
* // Set username
|
||||
* client.user.setUsername('discordjs')
|
||||
* .then(user => console.log(`My new username is ${user.username}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setUsername(username) {
|
||||
return this.edit({ username });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the avatar of the logged in client.
|
||||
* @param {?(BufferResolvable|Base64Resolvable)} avatar The new avatar
|
||||
* @returns {Promise<ClientUser>}
|
||||
* @example
|
||||
* // Set avatar
|
||||
* client.user.setAvatar('./avatar.png')
|
||||
* .then(user => console.log(`New avatar set!`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setAvatar(avatar) {
|
||||
return this.edit({ avatar });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the banner of the logged in client.
|
||||
* @param {?(BufferResolvable|Base64Resolvable)} banner The new banner
|
||||
* @returns {Promise<ClientUser>}
|
||||
* @example
|
||||
* // Set banner
|
||||
* client.user.setBanner('./banner.png')
|
||||
* .then(user => console.log(`New banner set!`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setBanner(banner) {
|
||||
return this.edit({ banner });
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for setting activities
|
||||
* @typedef {Object} ActivitiesOptions
|
||||
* @property {string} name Name of the activity
|
||||
* @property {string} [state] State of the activity
|
||||
* @property {ActivityType} [type] Type of the activity
|
||||
* @property {string} [url] Twitch / YouTube stream URL
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data resembling a raw Discord presence.
|
||||
* @typedef {Object} PresenceData
|
||||
* @property {PresenceStatusData} [status] Status of the user
|
||||
* @property {boolean} [afk] Whether the user is AFK
|
||||
* @property {ActivitiesOptions[]} [activities] Activity the user is playing
|
||||
* @property {number|number[]} [shardId] Shard id(s) to have the activity set on
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sets the full presence of the client user.
|
||||
* @param {PresenceData} data Data for the presence
|
||||
* @returns {ClientPresence}
|
||||
* @example
|
||||
* // Set the client user's presence
|
||||
* client.user.setPresence({ activities: [{ name: 'with discord.js' }], status: 'idle' });
|
||||
*/
|
||||
setPresence(data) {
|
||||
return this.client.presence.set(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* A user's status. Must be one of:
|
||||
* * `online`
|
||||
* * `idle`
|
||||
* * `invisible`
|
||||
* * `dnd` (do not disturb)
|
||||
* @typedef {string} PresenceStatusData
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sets the status of the client user.
|
||||
* @param {PresenceStatusData} status Status to change to
|
||||
* @param {number|number[]} [shardId] Shard id(s) to have the activity set on
|
||||
* @returns {ClientPresence}
|
||||
* @example
|
||||
* // Set the client user's status
|
||||
* client.user.setStatus('idle');
|
||||
*/
|
||||
setStatus(status, shardId) {
|
||||
return this.setPresence({ status, shardId });
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for setting an activity.
|
||||
* @typedef {Object} ActivityOptions
|
||||
* @property {string} name Name of the activity
|
||||
* @property {string} [state] State of the activity
|
||||
* @property {string} [url] Twitch / YouTube stream URL
|
||||
* @property {ActivityType} [type] Type of the activity
|
||||
* @property {number|number[]} [shardId] Shard Id(s) to have the activity set on
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sets the activity the client user is playing.
|
||||
* @param {string|ActivityOptions} name Activity being played, or options for setting the activity
|
||||
* @param {ActivityOptions} [options] Options for setting the activity
|
||||
* @returns {ClientPresence}
|
||||
* @example
|
||||
* // Set the client user's activity
|
||||
* client.user.setActivity('discord.js', { type: ActivityType.Watching });
|
||||
*/
|
||||
setActivity(name, options = {}) {
|
||||
if (!name) return this.setPresence({ activities: [], shardId: options.shardId });
|
||||
|
||||
const activity = Object.assign({}, options, typeof name === 'object' ? name : { name });
|
||||
return this.setPresence({ activities: [activity], shardId: activity.shardId });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets/removes the AFK flag for the client user.
|
||||
* @param {boolean} [afk=true] Whether or not the user is AFK
|
||||
* @param {number|number[]} [shardId] Shard Id(s) to have the AFK flag set on
|
||||
* @returns {ClientPresence}
|
||||
*/
|
||||
setAFK(afk = true, shardId) {
|
||||
return this.setPresence({ afk, shardId });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ClientUser;
|
||||
168
node_modules/discord.js/src/structures/CommandInteraction.js
generated
vendored
Normal file
168
node_modules/discord.js/src/structures/CommandInteraction.js
generated
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
'use strict';
|
||||
|
||||
const Attachment = require('./Attachment');
|
||||
const BaseInteraction = require('./BaseInteraction');
|
||||
const InteractionWebhook = require('./InteractionWebhook');
|
||||
const InteractionResponses = require('./interfaces/InteractionResponses');
|
||||
|
||||
/**
|
||||
* Represents a command interaction.
|
||||
* @extends {BaseInteraction}
|
||||
* @implements {InteractionResponses}
|
||||
* @abstract
|
||||
*/
|
||||
class CommandInteraction extends BaseInteraction {
|
||||
constructor(client, data) {
|
||||
super(client, data);
|
||||
|
||||
/**
|
||||
* The id of the channel this interaction was sent in
|
||||
* @type {Snowflake}
|
||||
* @name CommandInteraction#channelId
|
||||
*/
|
||||
|
||||
/**
|
||||
* The invoked application command's id
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.commandId = data.data.id;
|
||||
|
||||
/**
|
||||
* The invoked application command's name
|
||||
* @type {string}
|
||||
*/
|
||||
this.commandName = data.data.name;
|
||||
|
||||
/**
|
||||
* The invoked application command's type
|
||||
* @type {ApplicationCommandType}
|
||||
*/
|
||||
this.commandType = data.data.type;
|
||||
|
||||
/**
|
||||
* The id of the guild the invoked application command is registered to
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.commandGuildId = data.data.guild_id ?? null;
|
||||
|
||||
/**
|
||||
* Whether the reply to this interaction has been deferred
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.deferred = false;
|
||||
|
||||
/**
|
||||
* Whether this interaction has already been replied to
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.replied = false;
|
||||
|
||||
/**
|
||||
* Whether the reply to this interaction is ephemeral
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.ephemeral = null;
|
||||
|
||||
/**
|
||||
* An associated interaction webhook, can be used to further interact with this interaction
|
||||
* @type {InteractionWebhook}
|
||||
*/
|
||||
this.webhook = new InteractionWebhook(this.client, this.applicationId, this.token);
|
||||
}
|
||||
|
||||
/**
|
||||
* The invoked application command, if it was fetched before
|
||||
* @type {?ApplicationCommand}
|
||||
*/
|
||||
get command() {
|
||||
const id = this.commandId;
|
||||
return this.guild?.commands.cache.get(id) ?? this.client.application.commands.cache.get(id) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} BaseInteractionResolvedData
|
||||
* @property {Collection<Snowflake, User>} [users] The resolved users
|
||||
* @property {Collection<Snowflake, GuildMember|APIGuildMember>} [members] The resolved guild members
|
||||
* @property {Collection<Snowflake, Role|APIRole>} [roles] The resolved roles
|
||||
* @property {Collection<Snowflake, BaseChannel|APIChannel>} [channels] The resolved channels
|
||||
* @property {Collection<Snowflake, Attachment>} [attachments] The resolved attachments
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents the resolved data of a received command interaction.
|
||||
*
|
||||
* @typedef {BaseInteractionResolvedData} CommandInteractionResolvedData
|
||||
* @property {Collection<Snowflake, Message|APIMessage>} [messages] The resolved messages
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents an option of a received command interaction.
|
||||
* @typedef {Object} CommandInteractionOption
|
||||
* @property {string} name The name of the option
|
||||
* @property {ApplicationCommandOptionType} type The type of the option
|
||||
* @property {boolean} [autocomplete] Whether the autocomplete interaction is enabled for a
|
||||
* {@link ApplicationCommandOptionType.String}, {@link ApplicationCommandOptionType.Integer} or
|
||||
* {@link ApplicationCommandOptionType.Number} option
|
||||
* @property {string|number|boolean} [value] The value of the option
|
||||
* @property {CommandInteractionOption[]} [options] Additional options if this option is a
|
||||
* subcommand (group)
|
||||
* @property {User} [user] The resolved user
|
||||
* @property {GuildMember|APIGuildMember} [member] The resolved member
|
||||
* @property {GuildChannel|ThreadChannel|APIChannel} [channel] The resolved channel
|
||||
* @property {Role|APIRole} [role] The resolved role
|
||||
* @property {Attachment} [attachment] The resolved attachment
|
||||
*/
|
||||
|
||||
/**
|
||||
* Transforms an option received from the API.
|
||||
* @param {APIApplicationCommandOption} option The received option
|
||||
* @param {APIInteractionDataResolved} resolved The resolved interaction data
|
||||
* @returns {CommandInteractionOption}
|
||||
* @private
|
||||
*/
|
||||
transformOption(option, resolved) {
|
||||
const result = {
|
||||
name: option.name,
|
||||
type: option.type,
|
||||
};
|
||||
|
||||
if ('value' in option) result.value = option.value;
|
||||
if ('options' in option) result.options = option.options.map(opt => this.transformOption(opt, resolved));
|
||||
|
||||
if (resolved) {
|
||||
const user = resolved.users?.[option.value];
|
||||
if (user) result.user = this.client.users._add(user);
|
||||
|
||||
const member = resolved.members?.[option.value];
|
||||
if (member) result.member = this.guild?.members._add({ user, ...member }) ?? member;
|
||||
|
||||
const channel = resolved.channels?.[option.value];
|
||||
if (channel) result.channel = this.client.channels._add(channel, this.guild) ?? channel;
|
||||
|
||||
const role = resolved.roles?.[option.value];
|
||||
if (role) result.role = this.guild?.roles._add(role) ?? role;
|
||||
|
||||
const attachment = resolved.attachments?.[option.value];
|
||||
if (attachment) result.attachment = new Attachment(attachment);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// These are here only for documentation purposes - they are implemented by InteractionResponses
|
||||
/* eslint-disable no-empty-function */
|
||||
deferReply() {}
|
||||
reply() {}
|
||||
fetchReply() {}
|
||||
editReply() {}
|
||||
deleteReply() {}
|
||||
followUp() {}
|
||||
launchActivity() {}
|
||||
showModal() {}
|
||||
sendPremiumRequired() {}
|
||||
awaitModalSubmit() {}
|
||||
}
|
||||
|
||||
InteractionResponses.applyToClass(CommandInteraction, ['deferUpdate', 'update']);
|
||||
|
||||
module.exports = CommandInteraction;
|
||||
308
node_modules/discord.js/src/structures/CommandInteractionOptionResolver.js
generated
vendored
Normal file
308
node_modules/discord.js/src/structures/CommandInteractionOptionResolver.js
generated
vendored
Normal file
@@ -0,0 +1,308 @@
|
||||
'use strict';
|
||||
|
||||
const { ApplicationCommandOptionType } = require('discord-api-types/v10');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
|
||||
/**
|
||||
* A resolver for command interaction options.
|
||||
*/
|
||||
class CommandInteractionOptionResolver {
|
||||
constructor(client, options, resolved) {
|
||||
/**
|
||||
* The client that instantiated this.
|
||||
* @name CommandInteractionOptionResolver#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
|
||||
/**
|
||||
* The name of the subcommand group.
|
||||
* @type {?string}
|
||||
* @private
|
||||
*/
|
||||
this._group = null;
|
||||
|
||||
/**
|
||||
* The name of the subcommand.
|
||||
* @type {?string}
|
||||
* @private
|
||||
*/
|
||||
this._subcommand = null;
|
||||
|
||||
/**
|
||||
* The bottom-level options for the interaction.
|
||||
* If there is a subcommand (or subcommand and group), this is the options for the subcommand.
|
||||
* @type {CommandInteractionOption[]}
|
||||
* @private
|
||||
*/
|
||||
this._hoistedOptions = options;
|
||||
|
||||
// Hoist subcommand group if present
|
||||
if (this._hoistedOptions[0]?.type === ApplicationCommandOptionType.SubcommandGroup) {
|
||||
this._group = this._hoistedOptions[0].name;
|
||||
this._hoistedOptions = this._hoistedOptions[0].options ?? [];
|
||||
}
|
||||
// Hoist subcommand if present
|
||||
if (this._hoistedOptions[0]?.type === ApplicationCommandOptionType.Subcommand) {
|
||||
this._subcommand = this._hoistedOptions[0].name;
|
||||
this._hoistedOptions = this._hoistedOptions[0].options ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* The interaction options array.
|
||||
* @name CommandInteractionOptionResolver#data
|
||||
* @type {ReadonlyArray<CommandInteractionOption>}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'data', { value: Object.freeze([...options]) });
|
||||
|
||||
/**
|
||||
* The interaction resolved data
|
||||
* @name CommandInteractionOptionResolver#resolved
|
||||
* @type {?Readonly<CommandInteractionResolvedData>}
|
||||
*/
|
||||
Object.defineProperty(this, 'resolved', { value: resolved ? Object.freeze(resolved) : null });
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an option by its name.
|
||||
* @param {string} name The name of the option.
|
||||
* @param {boolean} [required=false] Whether to throw an error if the option is not found.
|
||||
* @returns {?CommandInteractionOption} The option, if found.
|
||||
*/
|
||||
get(name, required = false) {
|
||||
const option = this._hoistedOptions.find(opt => opt.name === name);
|
||||
if (!option) {
|
||||
if (required) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.CommandInteractionOptionNotFound, name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return option;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an option by name and property and checks its type.
|
||||
* @param {string} name The name of the option.
|
||||
* @param {ApplicationCommandOptionType[]} allowedTypes The allowed types of the option.
|
||||
* @param {string[]} properties The properties to check for for `required`.
|
||||
* @param {boolean} required Whether to throw an error if the option is not found.
|
||||
* @returns {?CommandInteractionOption} The option, if found.
|
||||
* @private
|
||||
*/
|
||||
_getTypedOption(name, allowedTypes, properties, required) {
|
||||
const option = this.get(name, required);
|
||||
if (!option) {
|
||||
return null;
|
||||
} else if (!allowedTypes.includes(option.type)) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.CommandInteractionOptionType, name, option.type, allowedTypes.join(', '));
|
||||
} else if (required && properties.every(prop => option[prop] === null || option[prop] === undefined)) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.CommandInteractionOptionEmpty, name, option.type);
|
||||
}
|
||||
return option;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the selected subcommand.
|
||||
* @param {boolean} [required=true] Whether to throw an error if there is no subcommand.
|
||||
* @returns {?string} The name of the selected subcommand, or null if not set and not required.
|
||||
*/
|
||||
getSubcommand(required = true) {
|
||||
if (required && !this._subcommand) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.CommandInteractionOptionNoSubcommand);
|
||||
}
|
||||
return this._subcommand;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the selected subcommand group.
|
||||
* @param {boolean} [required=false] Whether to throw an error if there is no subcommand group.
|
||||
* @returns {?string} The name of the selected subcommand group, or null if not set and not required.
|
||||
*/
|
||||
getSubcommandGroup(required = false) {
|
||||
if (required && !this._group) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.CommandInteractionOptionNoSubcommandGroup);
|
||||
}
|
||||
return this._group;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a boolean option.
|
||||
* @param {string} name The name of the option.
|
||||
* @param {boolean} [required=false] Whether to throw an error if the option is not found.
|
||||
* @returns {?boolean} The value of the option, or null if not set and not required.
|
||||
*/
|
||||
getBoolean(name, required = false) {
|
||||
const option = this._getTypedOption(name, [ApplicationCommandOptionType.Boolean], ['value'], required);
|
||||
return option?.value ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a channel option.
|
||||
* @param {string} name The name of the option.
|
||||
* @param {boolean} [required=false] Whether to throw an error if the option is not found.
|
||||
* @param {ChannelType[]} [channelTypes=[]] The allowed types of channels. If empty, all channel types are allowed.
|
||||
* @returns {?(GuildChannel|ThreadChannel|APIChannel)}
|
||||
* The value of the option, or null if not set and not required.
|
||||
*/
|
||||
getChannel(name, required = false, channelTypes = []) {
|
||||
const option = this._getTypedOption(name, [ApplicationCommandOptionType.Channel], ['channel'], required);
|
||||
const channel = option?.channel ?? null;
|
||||
|
||||
if (channel && channelTypes.length > 0 && !channelTypes.includes(channel.type)) {
|
||||
throw new DiscordjsTypeError(
|
||||
ErrorCodes.CommandInteractionOptionInvalidChannelType,
|
||||
name,
|
||||
channel.type,
|
||||
channelTypes.join(', '),
|
||||
);
|
||||
}
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a string option.
|
||||
* @param {string} name The name of the option.
|
||||
* @param {boolean} [required=false] Whether to throw an error if the option is not found.
|
||||
* @returns {?string} The value of the option, or null if not set and not required.
|
||||
*/
|
||||
getString(name, required = false) {
|
||||
const option = this._getTypedOption(name, [ApplicationCommandOptionType.String], ['value'], required);
|
||||
return option?.value ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an integer option.
|
||||
* @param {string} name The name of the option.
|
||||
* @param {boolean} [required=false] Whether to throw an error if the option is not found.
|
||||
* @returns {?number} The value of the option, or null if not set and not required.
|
||||
*/
|
||||
getInteger(name, required = false) {
|
||||
const option = this._getTypedOption(name, [ApplicationCommandOptionType.Integer], ['value'], required);
|
||||
return option?.value ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a number option.
|
||||
* @param {string} name The name of the option.
|
||||
* @param {boolean} [required=false] Whether to throw an error if the option is not found.
|
||||
* @returns {?number} The value of the option, or null if not set and not required.
|
||||
*/
|
||||
getNumber(name, required = false) {
|
||||
const option = this._getTypedOption(name, [ApplicationCommandOptionType.Number], ['value'], required);
|
||||
return option?.value ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a user option.
|
||||
* @param {string} name The name of the option.
|
||||
* @param {boolean} [required=false] Whether to throw an error if the option is not found.
|
||||
* @returns {?User} The value of the option, or null if not set and not required.
|
||||
*/
|
||||
getUser(name, required = false) {
|
||||
const option = this._getTypedOption(
|
||||
name,
|
||||
[ApplicationCommandOptionType.User, ApplicationCommandOptionType.Mentionable],
|
||||
['user'],
|
||||
required,
|
||||
);
|
||||
return option?.user ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a member option.
|
||||
* @param {string} name The name of the option.
|
||||
* @returns {?(GuildMember|APIGuildMember)}
|
||||
* The value of the option, or null if the user is not present in the guild or the option is not set.
|
||||
*/
|
||||
getMember(name) {
|
||||
const option = this._getTypedOption(
|
||||
name,
|
||||
[ApplicationCommandOptionType.User, ApplicationCommandOptionType.Mentionable],
|
||||
['member'],
|
||||
false,
|
||||
);
|
||||
return option?.member ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a role option.
|
||||
* @param {string} name The name of the option.
|
||||
* @param {boolean} [required=false] Whether to throw an error if the option is not found.
|
||||
* @returns {?(Role|APIRole)} The value of the option, or null if not set and not required.
|
||||
*/
|
||||
getRole(name, required = false) {
|
||||
const option = this._getTypedOption(
|
||||
name,
|
||||
[ApplicationCommandOptionType.Role, ApplicationCommandOptionType.Mentionable],
|
||||
['role'],
|
||||
required,
|
||||
);
|
||||
return option?.role ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an attachment option.
|
||||
* @param {string} name The name of the option.
|
||||
* @param {boolean} [required=false] Whether to throw an error if the option is not found.
|
||||
* @returns {?Attachment} The value of the option, or null if not set and not required.
|
||||
*/
|
||||
getAttachment(name, required = false) {
|
||||
const option = this._getTypedOption(name, [ApplicationCommandOptionType.Attachment], ['attachment'], required);
|
||||
return option?.attachment ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a mentionable option.
|
||||
* @param {string} name The name of the option.
|
||||
* @param {boolean} [required=false] Whether to throw an error if the option is not found.
|
||||
* @returns {?(User|GuildMember|APIGuildMember|Role|APIRole)}
|
||||
* The value of the option, or null if not set and not required.
|
||||
*/
|
||||
getMentionable(name, required = false) {
|
||||
const option = this._getTypedOption(
|
||||
name,
|
||||
[ApplicationCommandOptionType.Mentionable],
|
||||
['user', 'member', 'role'],
|
||||
required,
|
||||
);
|
||||
return option?.member ?? option?.user ?? option?.role ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a message option.
|
||||
* @param {string} name The name of the option.
|
||||
* @param {boolean} [required=false] Whether to throw an error if the option is not found.
|
||||
* @returns {?Message}
|
||||
* The value of the option, or null if not set and not required.
|
||||
*/
|
||||
getMessage(name, required = false) {
|
||||
const option = this._getTypedOption(name, ['_MESSAGE'], ['message'], required);
|
||||
return option?.message ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The full autocomplete option object.
|
||||
* @typedef {Object} AutocompleteFocusedOption
|
||||
* @property {string} name The name of the option
|
||||
* @property {ApplicationCommandOptionType} type The type of the application command option
|
||||
* @property {string} value The value of the option
|
||||
* @property {boolean} focused Whether this option is currently in focus for autocomplete
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets the focused option.
|
||||
* @param {boolean} [getFull=false] Whether to get the full option object
|
||||
* @returns {string|AutocompleteFocusedOption}
|
||||
* The value of the option, or the whole option if getFull is true
|
||||
*/
|
||||
getFocused(getFull = false) {
|
||||
const focusedOption = this._hoistedOptions.find(option => option.focused);
|
||||
if (!focusedOption) throw new DiscordjsTypeError(ErrorCodes.AutocompleteInteractionOptionNoFocusedOption);
|
||||
return getFull ? focusedOption : focusedOption.value;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CommandInteractionOptionResolver;
|
||||
56
node_modules/discord.js/src/structures/Component.js
generated
vendored
Normal file
56
node_modules/discord.js/src/structures/Component.js
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
'use strict';
|
||||
|
||||
const isEqual = require('fast-deep-equal');
|
||||
|
||||
/**
|
||||
* Represents a component
|
||||
*/
|
||||
class Component {
|
||||
constructor(data) {
|
||||
/**
|
||||
* The API data associated with this component
|
||||
* @type {APIMessageComponent}
|
||||
*/
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* The id of this component
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get id() {
|
||||
return this.data.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of the component
|
||||
* @type {ComponentType}
|
||||
* @readonly
|
||||
*/
|
||||
get type() {
|
||||
return this.data.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the given components are equal
|
||||
* @param {Component|APIMessageComponent} other The component to compare against
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(other) {
|
||||
if (other instanceof Component) {
|
||||
return isEqual(other.data, this.data);
|
||||
}
|
||||
return isEqual(other, this.data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the API-compatible JSON for this component
|
||||
* @returns {APIMessageComponent}
|
||||
*/
|
||||
toJSON() {
|
||||
return { ...this.data };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Component;
|
||||
60
node_modules/discord.js/src/structures/ContainerComponent.js
generated
vendored
Normal file
60
node_modules/discord.js/src/structures/ContainerComponent.js
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
'use strict';
|
||||
|
||||
const Component = require('./Component');
|
||||
const { createComponent } = require('../util/Components');
|
||||
|
||||
/**
|
||||
* Represents a container component
|
||||
* @extends {Component}
|
||||
*/
|
||||
class ContainerComponent extends Component {
|
||||
constructor({ components, ...data }) {
|
||||
super(data);
|
||||
|
||||
/**
|
||||
* The components in this container
|
||||
* @type {Component[]}
|
||||
* @readonly
|
||||
*/
|
||||
this.components = components.map(component => createComponent(component));
|
||||
}
|
||||
|
||||
/**
|
||||
* The accent color of this container
|
||||
* @type {?number}
|
||||
* @readonly
|
||||
*/
|
||||
get accentColor() {
|
||||
return this.data.accent_color ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The hex accent color of this container
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get hexAccentColor() {
|
||||
return typeof this.data.accent_color === 'number'
|
||||
? `#${this.data.accent_color.toString(16).padStart(6, '0')}`
|
||||
: (this.data.accent_color ?? null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this container is spoilered
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get spoiler() {
|
||||
return this.data.spoiler ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the API-compatible JSON for this component
|
||||
* @returns {APIContainerComponent}
|
||||
*/
|
||||
toJSON() {
|
||||
return { ...this.data, components: this.components.map(component => component.toJSON()) };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ContainerComponent;
|
||||
65
node_modules/discord.js/src/structures/ContextMenuCommandInteraction.js
generated
vendored
Normal file
65
node_modules/discord.js/src/structures/ContextMenuCommandInteraction.js
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
'use strict';
|
||||
|
||||
const { lazy } = require('@discordjs/util');
|
||||
const { ApplicationCommandOptionType } = require('discord-api-types/v10');
|
||||
const CommandInteraction = require('./CommandInteraction');
|
||||
const CommandInteractionOptionResolver = require('./CommandInteractionOptionResolver');
|
||||
const { transformResolved } = require('../util/Util');
|
||||
|
||||
const getMessage = lazy(() => require('./Message').Message);
|
||||
|
||||
/**
|
||||
* Represents a context menu interaction.
|
||||
* @extends {CommandInteraction}
|
||||
*/
|
||||
class ContextMenuCommandInteraction extends CommandInteraction {
|
||||
constructor(client, data) {
|
||||
super(client, data);
|
||||
/**
|
||||
* The target of the interaction, parsed into options
|
||||
* @type {CommandInteractionOptionResolver}
|
||||
*/
|
||||
this.options = new CommandInteractionOptionResolver(
|
||||
this.client,
|
||||
this.resolveContextMenuOptions(data.data),
|
||||
transformResolved({ client: this.client, guild: this.guild, channel: this.channel }, data.data.resolved),
|
||||
);
|
||||
|
||||
/**
|
||||
* The id of the target of this interaction
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.targetId = data.data.target_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves and transforms options received from the API for a context menu interaction.
|
||||
* @param {APIApplicationCommandInteractionData} data The interaction data
|
||||
* @returns {CommandInteractionOption[]}
|
||||
* @private
|
||||
*/
|
||||
resolveContextMenuOptions({ target_id, resolved }) {
|
||||
const result = [];
|
||||
|
||||
if (resolved.users?.[target_id]) {
|
||||
result.push(
|
||||
this.transformOption({ name: 'user', type: ApplicationCommandOptionType.User, value: target_id }, resolved),
|
||||
);
|
||||
}
|
||||
|
||||
if (resolved.messages?.[target_id]) {
|
||||
result.push({
|
||||
name: 'message',
|
||||
type: '_MESSAGE',
|
||||
value: target_id,
|
||||
message:
|
||||
this.channel?.messages._add(resolved.messages[target_id]) ??
|
||||
new (getMessage())(this.client, resolved.messages[target_id]),
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ContextMenuCommandInteraction;
|
||||
129
node_modules/discord.js/src/structures/DMChannel.js
generated
vendored
Normal file
129
node_modules/discord.js/src/structures/DMChannel.js
generated
vendored
Normal file
@@ -0,0 +1,129 @@
|
||||
'use strict';
|
||||
|
||||
const { userMention } = require('@discordjs/formatters');
|
||||
const { ChannelType } = require('discord-api-types/v10');
|
||||
const { BaseChannel } = require('./BaseChannel');
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const DMMessageManager = require('../managers/DMMessageManager');
|
||||
const Partials = require('../util/Partials');
|
||||
|
||||
/**
|
||||
* Represents a direct message channel between two users.
|
||||
* @extends {BaseChannel}
|
||||
* @implements {TextBasedChannel}
|
||||
*/
|
||||
class DMChannel extends BaseChannel {
|
||||
constructor(client, data) {
|
||||
super(client, data);
|
||||
|
||||
// Override the channel type so partials have a known type
|
||||
this.type = ChannelType.DM;
|
||||
|
||||
/**
|
||||
* A manager of the messages belonging to this channel
|
||||
* @type {DMMessageManager}
|
||||
*/
|
||||
this.messages = new DMMessageManager(this);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
super._patch(data);
|
||||
|
||||
if (data.recipients) {
|
||||
const recipient = data.recipients[0];
|
||||
|
||||
/**
|
||||
* The recipient's id
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.recipientId = recipient.id;
|
||||
|
||||
if ('username' in recipient || this.client.options.partials.includes(Partials.User)) {
|
||||
this.client.users._add(recipient);
|
||||
}
|
||||
}
|
||||
|
||||
if ('last_message_id' in data) {
|
||||
/**
|
||||
* The channel's last message id, if one was sent
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.lastMessageId = data.last_message_id;
|
||||
}
|
||||
|
||||
if ('last_pin_timestamp' in data) {
|
||||
/**
|
||||
* The timestamp when the last pinned message was pinned, if there was one
|
||||
* @type {?number}
|
||||
*/
|
||||
this.lastPinTimestamp = Date.parse(data.last_pin_timestamp);
|
||||
} else {
|
||||
this.lastPinTimestamp ??= null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this DMChannel is a partial
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get partial() {
|
||||
return this.lastMessageId === undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* The recipient on the other end of the DM
|
||||
* @type {?User}
|
||||
* @readonly
|
||||
*/
|
||||
get recipient() {
|
||||
return this.client.users.resolve(this.recipientId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch this DMChannel.
|
||||
* @param {boolean} [force=true] Whether to skip the cache check and request the API
|
||||
* @returns {Promise<DMChannel>}
|
||||
*/
|
||||
fetch(force = true) {
|
||||
return this.client.users.createDM(this.recipientId, { force });
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically returns the recipient's mention instead of the
|
||||
* DMChannel object.
|
||||
* @returns {string}
|
||||
* @example
|
||||
* // Logs: Hello from <@123456789012345678>!
|
||||
* console.log(`Hello from ${channel}!`);
|
||||
*/
|
||||
toString() {
|
||||
return userMention(this.recipientId);
|
||||
}
|
||||
|
||||
// These are here only for documentation purposes - they are implemented by TextBasedChannel
|
||||
/* eslint-disable no-empty-function */
|
||||
get lastMessage() {}
|
||||
get lastPinAt() {}
|
||||
send() {}
|
||||
sendTyping() {}
|
||||
createMessageCollector() {}
|
||||
awaitMessages() {}
|
||||
createMessageComponentCollector() {}
|
||||
awaitMessageComponent() {}
|
||||
// Doesn't work on DM channels; bulkDelete() {}
|
||||
// Doesn't work on DM channels; fetchWebhooks() {}
|
||||
// Doesn't work on DM channels; createWebhook() {}
|
||||
// Doesn't work on DM channels; setRateLimitPerUser() {}
|
||||
// Doesn't work on DM channels; setNSFW() {}
|
||||
}
|
||||
|
||||
TextBasedChannel.applyToClass(DMChannel, true, [
|
||||
'bulkDelete',
|
||||
'fetchWebhooks',
|
||||
'createWebhook',
|
||||
'setRateLimitPerUser',
|
||||
'setNSFW',
|
||||
]);
|
||||
|
||||
module.exports = DMChannel;
|
||||
36
node_modules/discord.js/src/structures/DirectoryChannel.js
generated
vendored
Normal file
36
node_modules/discord.js/src/structures/DirectoryChannel.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
'use strict';
|
||||
|
||||
const { BaseChannel } = require('./BaseChannel');
|
||||
|
||||
/**
|
||||
* Represents a channel that displays a directory of guilds.
|
||||
* @extends {BaseChannel}
|
||||
*/
|
||||
class DirectoryChannel extends BaseChannel {
|
||||
constructor(guild, data, client) {
|
||||
super(client, data);
|
||||
|
||||
/**
|
||||
* The guild the channel is in
|
||||
* @type {InviteGuild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
|
||||
/**
|
||||
* The id of the guild the channel is in
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.guildId = guild.id;
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
super._patch(data);
|
||||
/**
|
||||
* The channel's name
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = DirectoryChannel;
|
||||
237
node_modules/discord.js/src/structures/Embed.js
generated
vendored
Normal file
237
node_modules/discord.js/src/structures/Embed.js
generated
vendored
Normal file
@@ -0,0 +1,237 @@
|
||||
'use strict';
|
||||
|
||||
const { embedLength } = require('@discordjs/builders');
|
||||
const isEqual = require('fast-deep-equal');
|
||||
|
||||
/**
|
||||
* Represents an embed.
|
||||
*/
|
||||
class Embed {
|
||||
constructor(data) {
|
||||
/**
|
||||
* The API embed data.
|
||||
* @type {APIEmbed}
|
||||
* @readonly
|
||||
*/
|
||||
this.data = { ...data };
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of fields of this embed.
|
||||
* @type {Array<APIEmbedField>}
|
||||
* @readonly
|
||||
*/
|
||||
get fields() {
|
||||
return this.data.fields ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* The title of this embed.
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get title() {
|
||||
return this.data.title ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The description of this embed.
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get description() {
|
||||
return this.data.description ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL of this embed.
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get url() {
|
||||
return this.data.url ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The color of this embed.
|
||||
* @type {?number}
|
||||
* @readonly
|
||||
*/
|
||||
get color() {
|
||||
return this.data.color ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp of this embed. This is in an ISO 8601 format.
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get timestamp() {
|
||||
return this.data.timestamp ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} EmbedAssetData
|
||||
* @property {?string} url The URL of the image
|
||||
* @property {?string} proxyURL The proxy URL of the image
|
||||
* @property {?number} height The height of the image
|
||||
* @property {?number} width The width of the image
|
||||
*/
|
||||
|
||||
/**
|
||||
* The thumbnail of this embed.
|
||||
* @type {?EmbedAssetData}
|
||||
* @readonly
|
||||
*/
|
||||
get thumbnail() {
|
||||
if (!this.data.thumbnail) return null;
|
||||
return {
|
||||
url: this.data.thumbnail.url,
|
||||
proxyURL: this.data.thumbnail.proxy_url,
|
||||
height: this.data.thumbnail.height,
|
||||
width: this.data.thumbnail.width,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The image of this embed.
|
||||
* @type {?EmbedAssetData}
|
||||
* @readonly
|
||||
*/
|
||||
get image() {
|
||||
if (!this.data.image) return null;
|
||||
return {
|
||||
url: this.data.image.url,
|
||||
proxyURL: this.data.image.proxy_url,
|
||||
height: this.data.image.height,
|
||||
width: this.data.image.width,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The video of this embed.
|
||||
* @type {?EmbedAssetData}
|
||||
* @readonly
|
||||
*/
|
||||
get video() {
|
||||
if (!this.data.video) return null;
|
||||
return {
|
||||
url: this.data.video.url,
|
||||
proxyURL: this.data.video.proxy_url,
|
||||
height: this.data.video.height,
|
||||
width: this.data.video.width,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} EmbedAuthorData
|
||||
* @property {string} name The name of the author
|
||||
* @property {?string} url The URL of the author
|
||||
* @property {?string} iconURL The icon URL of the author
|
||||
* @property {?string} proxyIconURL The proxy icon URL of the author
|
||||
*/
|
||||
|
||||
/**
|
||||
* The author of this embed.
|
||||
* @type {?EmbedAuthorData}
|
||||
* @readonly
|
||||
*/
|
||||
get author() {
|
||||
if (!this.data.author) return null;
|
||||
return {
|
||||
name: this.data.author.name,
|
||||
url: this.data.author.url,
|
||||
iconURL: this.data.author.icon_url,
|
||||
proxyIconURL: this.data.author.proxy_icon_url,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The provider of this embed.
|
||||
* @type {?APIEmbedProvider}
|
||||
* @readonly
|
||||
*/
|
||||
get provider() {
|
||||
return this.data.provider ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} EmbedFooterData
|
||||
* @property {string} text The text of the footer
|
||||
* @property {?string} iconURL The URL of the icon
|
||||
* @property {?string} proxyIconURL The proxy URL of the icon
|
||||
*/
|
||||
|
||||
/**
|
||||
* The footer of this embed.
|
||||
* @type {?EmbedFooterData}
|
||||
* @readonly
|
||||
*/
|
||||
get footer() {
|
||||
if (!this.data.footer) return null;
|
||||
return {
|
||||
text: this.data.footer.text,
|
||||
iconURL: this.data.footer.icon_url,
|
||||
proxyIconURL: this.data.footer.proxy_icon_url,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* The accumulated length for the embed title, description, fields, footer text, and author name.
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get length() {
|
||||
return embedLength(this.data);
|
||||
}
|
||||
|
||||
/**
|
||||
* The hex color of this embed.
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get hexColor() {
|
||||
return typeof this.data.color === 'number'
|
||||
? `#${this.data.color.toString(16).padStart(6, '0')}`
|
||||
: (this.data.color ?? null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the API-compatible JSON for this embed.
|
||||
* @returns {APIEmbed}
|
||||
*/
|
||||
toJSON() {
|
||||
return { ...this.data };
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the given embeds are equal.
|
||||
* @param {Embed|APIEmbed} other The embed to compare against
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(other) {
|
||||
if (other instanceof Embed) {
|
||||
return isEqual(this.data, other.data);
|
||||
}
|
||||
|
||||
return (
|
||||
this.author?.iconURL === other.author?.icon_url &&
|
||||
this.author?.name === other.author?.name &&
|
||||
this.author?.url === other.author?.url &&
|
||||
this.color === (other.color ?? null) &&
|
||||
this.description === (other.description ?? null) &&
|
||||
this.footer?.iconURL === other.footer?.icon_url &&
|
||||
this.footer?.text === other.footer?.text &&
|
||||
this.image?.url === other.image?.url &&
|
||||
this.thumbnail?.url === other.thumbnail?.url &&
|
||||
(this.timestamp && Date.parse(this.timestamp)) === (other.timestamp ? Date.parse(other.timestamp) : null) &&
|
||||
this.title === (other.title ?? null) &&
|
||||
this.url === (other.url ?? null) &&
|
||||
this.video?.url === other.video?.url &&
|
||||
isEqual(this.fields, other.fields?.map(field => ({ ...field, inline: field.inline ?? false })) ?? []) &&
|
||||
isEqual(this.provider, other.provider ?? null)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Embed;
|
||||
50
node_modules/discord.js/src/structures/EmbedBuilder.js
generated
vendored
Normal file
50
node_modules/discord.js/src/structures/EmbedBuilder.js
generated
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
'use strict';
|
||||
|
||||
const { EmbedBuilder: BuildersEmbed, embedLength } = require('@discordjs/builders');
|
||||
const { isJSONEncodable } = require('@discordjs/util');
|
||||
const { toSnakeCase } = require('../util/Transformers');
|
||||
const { resolveColor } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents an embed builder.
|
||||
* @extends {BuildersEmbed}
|
||||
*/
|
||||
class EmbedBuilder extends BuildersEmbed {
|
||||
constructor(data) {
|
||||
super(toSnakeCase(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color of this embed
|
||||
* @param {?ColorResolvable} color The color of the embed
|
||||
* @returns {EmbedBuilder}
|
||||
*/
|
||||
setColor(color) {
|
||||
return super.setColor(color && resolveColor(color));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new embed builder from JSON data
|
||||
* @param {EmbedBuilder|Embed|APIEmbed} other The other data
|
||||
* @returns {EmbedBuilder}
|
||||
*/
|
||||
static from(other) {
|
||||
return new this(isJSONEncodable(other) ? other.toJSON() : other);
|
||||
}
|
||||
|
||||
/**
|
||||
* The accumulated length for the embed title, description, fields, footer text, and author name.
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get length() {
|
||||
return embedLength(this.data);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = EmbedBuilder;
|
||||
|
||||
/**
|
||||
* @external BuildersEmbed
|
||||
* @see {@link https://discord.js.org/docs/packages/builders/stable/EmbedBuilder:Class}
|
||||
*/
|
||||
115
node_modules/discord.js/src/structures/Emoji.js
generated
vendored
Normal file
115
node_modules/discord.js/src/structures/Emoji.js
generated
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
'use strict';
|
||||
|
||||
const process = require('node:process');
|
||||
const { formatEmoji } = require('@discordjs/formatters');
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const Base = require('./Base');
|
||||
|
||||
let deprecationEmittedForURL = false;
|
||||
|
||||
/**
|
||||
* Represents an emoji, see {@link ApplicationEmoji}, {@link GuildEmoji} and {@link ReactionEmoji}.
|
||||
* @extends {Base}
|
||||
*/
|
||||
class Emoji extends Base {
|
||||
constructor(client, emoji) {
|
||||
super(client);
|
||||
/**
|
||||
* Whether or not the emoji is animated
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.animated = emoji.animated ?? null;
|
||||
|
||||
/**
|
||||
* The emoji's name
|
||||
* @type {?string}
|
||||
*/
|
||||
this.name = emoji.name ?? null;
|
||||
|
||||
/**
|
||||
* The emoji's id
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.id = emoji.id ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The identifier of this emoji, used for message reactions
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get identifier() {
|
||||
if (this.id) return `${this.animated ? 'a:' : ''}${this.name}:${this.id}`;
|
||||
return encodeURIComponent(this.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a URL for the emoji or `null` if this is not a custom emoji.
|
||||
* @param {EmojiURLOptions} [options] Options for the emoji URL
|
||||
* @returns {?string}
|
||||
*/
|
||||
imageURL(options) {
|
||||
return this.id && this.client.rest.cdn.emoji(this.id, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a URL for the emoji or `null` if this is not a custom emoji.
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
* @deprecated Use {@link Emoji#imageURL} instead.
|
||||
*/
|
||||
get url() {
|
||||
if (!deprecationEmittedForURL) {
|
||||
process.emitWarning('The Emoji#url getter is deprecated. Use Emoji#imageURL() instead.', 'DeprecationWarning');
|
||||
deprecationEmittedForURL = true;
|
||||
}
|
||||
|
||||
return this.imageURL({ extension: this.animated ? 'gif' : 'png' });
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp the emoji was created at, or null if unicode
|
||||
* @type {?number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return this.id && DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the emoji was created at, or null if unicode
|
||||
* @type {?Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return this.id && new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically returns the text required to form a graphical emoji on Discord
|
||||
* instead of the Emoji object.
|
||||
* @returns {string}
|
||||
* @example
|
||||
* // Send a custom emoji from a guild:
|
||||
* const emoji = guild.emojis.cache.first();
|
||||
* msg.channel.send(`Hello! ${emoji}`);
|
||||
* @example
|
||||
* // Send the emoji used in a reaction to the channel the reaction is part of
|
||||
* reaction.message.channel.send(`The emoji used was: ${reaction.emoji}`);
|
||||
*/
|
||||
toString() {
|
||||
return this.id ? formatEmoji({ animated: this.animated, id: this.id, name: this.name }) : this.name;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
const json = super.toJSON({
|
||||
guild: 'guildId',
|
||||
createdTimestamp: true,
|
||||
identifier: true,
|
||||
});
|
||||
json.imageURL = this.imageURL();
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
||||
exports.Emoji = Emoji;
|
||||
179
node_modules/discord.js/src/structures/Entitlement.js
generated
vendored
Normal file
179
node_modules/discord.js/src/structures/Entitlement.js
generated
vendored
Normal file
@@ -0,0 +1,179 @@
|
||||
'use strict';
|
||||
|
||||
const Base = require('./Base');
|
||||
|
||||
/**
|
||||
* Represents an Entitlement
|
||||
* @extends {Base}
|
||||
*/
|
||||
class Entitlement extends Base {
|
||||
constructor(client, data) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The id of the entitlement
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
if ('sku_id' in data) {
|
||||
/**
|
||||
* The id of the associated SKU
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.skuId = data.sku_id;
|
||||
}
|
||||
|
||||
if ('user_id' in data) {
|
||||
/**
|
||||
* The id of the user that is granted access to this entitlement's SKU
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.userId = data.user_id;
|
||||
}
|
||||
|
||||
if ('guild_id' in data) {
|
||||
/**
|
||||
* The id of the guild that is granted access to this entitlement's SKU
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.guildId = data.guild_id;
|
||||
} else {
|
||||
this.guildId ??= null;
|
||||
}
|
||||
|
||||
if ('application_id' in data) {
|
||||
/**
|
||||
* The id of the parent application
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.applicationId = data.application_id;
|
||||
}
|
||||
|
||||
if ('type' in data) {
|
||||
/**
|
||||
* The type of this entitlement
|
||||
* @type {EntitlementType}
|
||||
*/
|
||||
this.type = data.type;
|
||||
}
|
||||
|
||||
if ('deleted' in data) {
|
||||
/**
|
||||
* Whether this entitlement was deleted
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.deleted = data.deleted;
|
||||
}
|
||||
|
||||
if ('starts_at' in data) {
|
||||
/**
|
||||
* The timestamp at which this entitlement is valid
|
||||
* @type {?number}
|
||||
*/
|
||||
this.startsTimestamp = data.starts_at ? Date.parse(data.starts_at) : null;
|
||||
} else {
|
||||
this.startsTimestamp ??= null;
|
||||
}
|
||||
|
||||
if ('ends_at' in data) {
|
||||
/**
|
||||
* The timestamp at which this entitlement is no longer valid
|
||||
* @type {?number}
|
||||
*/
|
||||
this.endsTimestamp = data.ends_at ? Date.parse(data.ends_at) : null;
|
||||
} else {
|
||||
this.endsTimestamp ??= null;
|
||||
}
|
||||
|
||||
if ('consumed' in data) {
|
||||
/**
|
||||
* Whether this entitlement has been consumed
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.consumed = data.consumed;
|
||||
} else {
|
||||
this.consumed ??= false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The guild that is granted access to this entitlement's SKU
|
||||
* @type {?Guild}
|
||||
*/
|
||||
get guild() {
|
||||
if (!this.guildId) return null;
|
||||
return this.client.guilds.cache.get(this.guildId) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The start date at which this entitlement is valid
|
||||
* @type {?Date}
|
||||
*/
|
||||
get startsAt() {
|
||||
return this.startsTimestamp && new Date(this.startsTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The end date at which this entitlement is no longer valid
|
||||
* @type {?Date}
|
||||
*/
|
||||
get endsAt() {
|
||||
return this.endsTimestamp && new Date(this.endsTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this entitlement is active
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isActive() {
|
||||
return !this.deleted && (!this.endsTimestamp || this.endsTimestamp > Date.now());
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this entitlement is a test entitlement
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isTest() {
|
||||
return this.startsTimestamp === null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this entitlement is a user subscription
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isUserSubscription() {
|
||||
return this.guildId === null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this entitlement is a guild subscription
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isGuildSubscription() {
|
||||
return this.guildId !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the user that is granted access to this entitlement's SKU
|
||||
* @returns {Promise<User>}
|
||||
*/
|
||||
fetchUser() {
|
||||
return this.client.users.fetch(this.userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks this entitlement as consumed
|
||||
* <info>Only available for One-Time Purchase consumable SKUs.</info>
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async consume() {
|
||||
await this.client.application.entitlements.consume(this.id);
|
||||
}
|
||||
}
|
||||
|
||||
exports.Entitlement = Entitlement;
|
||||
40
node_modules/discord.js/src/structures/FileComponent.js
generated
vendored
Normal file
40
node_modules/discord.js/src/structures/FileComponent.js
generated
vendored
Normal file
@@ -0,0 +1,40 @@
|
||||
'use strict';
|
||||
|
||||
const Component = require('./Component');
|
||||
const UnfurledMediaItem = require('./UnfurledMediaItem');
|
||||
|
||||
/**
|
||||
* Represents a file component
|
||||
* @extends {Component}
|
||||
*/
|
||||
class FileComponent extends Component {
|
||||
constructor({ file, ...data }) {
|
||||
super(data);
|
||||
|
||||
/**
|
||||
* The media associated with this file
|
||||
* @type {UnfurledMediaItem}
|
||||
* @readonly
|
||||
*/
|
||||
this.file = new UnfurledMediaItem(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this thumbnail is spoilered
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get spoiler() {
|
||||
return this.data.spoiler ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the API-compatible JSON for this component
|
||||
* @returns {APIFileComponent}
|
||||
*/
|
||||
toJSON() {
|
||||
return { ...this.data, file: this.file.toJSON() };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FileComponent;
|
||||
31
node_modules/discord.js/src/structures/ForumChannel.js
generated
vendored
Normal file
31
node_modules/discord.js/src/structures/ForumChannel.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
const ThreadOnlyChannel = require('./ThreadOnlyChannel');
|
||||
|
||||
/**
|
||||
* Represents a forum channel.
|
||||
* @extends {ThreadOnlyChannel}
|
||||
*/
|
||||
class ForumChannel extends ThreadOnlyChannel {
|
||||
_patch(data) {
|
||||
super._patch(data);
|
||||
|
||||
/**
|
||||
* The default layout type used to display posts
|
||||
* @type {ForumLayoutType}
|
||||
*/
|
||||
this.defaultForumLayout = data.default_forum_layout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the default forum layout type used to display posts
|
||||
* @param {ForumLayoutType} defaultForumLayout The default forum layout type to set on this channel
|
||||
* @param {string} [reason] Reason for changing the default forum layout
|
||||
* @returns {Promise<ForumChannel>}
|
||||
*/
|
||||
setDefaultForumLayout(defaultForumLayout, reason) {
|
||||
return this.edit({ defaultForumLayout, reason });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ForumChannel;
|
||||
1496
node_modules/discord.js/src/structures/Guild.js
generated
vendored
Normal file
1496
node_modules/discord.js/src/structures/Guild.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
91
node_modules/discord.js/src/structures/GuildAuditLogs.js
generated
vendored
Normal file
91
node_modules/discord.js/src/structures/GuildAuditLogs.js
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const ApplicationCommand = require('./ApplicationCommand');
|
||||
const GuildAuditLogsEntry = require('./GuildAuditLogsEntry');
|
||||
const Integration = require('./Integration');
|
||||
const Webhook = require('./Webhook');
|
||||
const { flatten } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Audit logs entries are held in this class.
|
||||
*/
|
||||
class GuildAuditLogs {
|
||||
constructor(guild, data) {
|
||||
if (data.users) for (const user of data.users) guild.client.users._add(user);
|
||||
if (data.threads) for (const thread of data.threads) guild.client.channels._add(thread, guild);
|
||||
/**
|
||||
* Cached webhooks
|
||||
* @type {Collection<Snowflake, Webhook>}
|
||||
* @private
|
||||
*/
|
||||
this.webhooks = new Collection();
|
||||
if (data.webhooks) {
|
||||
for (const hook of data.webhooks) {
|
||||
this.webhooks.set(hook.id, new Webhook(guild.client, hook));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cached integrations
|
||||
* @type {Collection<Snowflake|string, Integration>}
|
||||
* @private
|
||||
*/
|
||||
this.integrations = new Collection();
|
||||
if (data.integrations) {
|
||||
for (const integration of data.integrations) {
|
||||
this.integrations.set(integration.id, new Integration(guild.client, integration, guild));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cached {@link GuildScheduledEvent}s.
|
||||
* @type {Collection<Snowflake, GuildScheduledEvent>}
|
||||
* @private
|
||||
*/
|
||||
this.guildScheduledEvents = data.guild_scheduled_events.reduce(
|
||||
(guildScheduledEvents, guildScheduledEvent) =>
|
||||
guildScheduledEvents.set(guildScheduledEvent.id, guild.scheduledEvents._add(guildScheduledEvent)),
|
||||
new Collection(),
|
||||
);
|
||||
|
||||
/**
|
||||
* Cached application commands, includes application commands from other applications
|
||||
* @type {Collection<Snowflake, ApplicationCommand>}
|
||||
* @private
|
||||
*/
|
||||
this.applicationCommands = new Collection();
|
||||
if (data.application_commands) {
|
||||
for (const command of data.application_commands) {
|
||||
this.applicationCommands.set(command.id, new ApplicationCommand(guild.client, command, guild));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cached auto moderation rules.
|
||||
* @type {Collection<Snowflake, AutoModerationRule>}
|
||||
* @private
|
||||
*/
|
||||
this.autoModerationRules = data.auto_moderation_rules.reduce(
|
||||
(autoModerationRules, autoModerationRule) =>
|
||||
autoModerationRules.set(autoModerationRule.id, guild.autoModerationRules._add(autoModerationRule)),
|
||||
new Collection(),
|
||||
);
|
||||
|
||||
/**
|
||||
* The entries for this guild's audit logs
|
||||
* @type {Collection<Snowflake, GuildAuditLogsEntry>}
|
||||
*/
|
||||
this.entries = new Collection();
|
||||
for (const item of data.audit_log_entries) {
|
||||
const entry = new GuildAuditLogsEntry(guild, item, this);
|
||||
this.entries.set(entry.id, entry);
|
||||
}
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return flatten(this);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildAuditLogs;
|
||||
527
node_modules/discord.js/src/structures/GuildAuditLogsEntry.js
generated
vendored
Normal file
527
node_modules/discord.js/src/structures/GuildAuditLogsEntry.js
generated
vendored
Normal file
@@ -0,0 +1,527 @@
|
||||
'use strict';
|
||||
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const { AuditLogOptionsType, AuditLogEvent } = require('discord-api-types/v10');
|
||||
const AutoModerationRule = require('./AutoModerationRule');
|
||||
const { GuildOnboardingPrompt } = require('./GuildOnboardingPrompt');
|
||||
const { GuildScheduledEvent } = require('./GuildScheduledEvent');
|
||||
const Integration = require('./Integration');
|
||||
const Invite = require('./Invite');
|
||||
const { StageInstance } = require('./StageInstance');
|
||||
const { Sticker } = require('./Sticker');
|
||||
const Webhook = require('./Webhook');
|
||||
const Partials = require('../util/Partials');
|
||||
const { flatten } = require('../util/Util');
|
||||
|
||||
const Targets = {
|
||||
All: 'All',
|
||||
Guild: 'Guild',
|
||||
GuildScheduledEvent: 'GuildScheduledEvent',
|
||||
Channel: 'Channel',
|
||||
User: 'User',
|
||||
Role: 'Role',
|
||||
Invite: 'Invite',
|
||||
Webhook: 'Webhook',
|
||||
Emoji: 'Emoji',
|
||||
Message: 'Message',
|
||||
Integration: 'Integration',
|
||||
StageInstance: 'StageInstance',
|
||||
Sticker: 'Sticker',
|
||||
Thread: 'Thread',
|
||||
ApplicationCommand: 'ApplicationCommand',
|
||||
AutoModeration: 'AutoModeration',
|
||||
GuildOnboarding: 'GuildOnboarding',
|
||||
GuildOnboardingPrompt: 'GuildOnboardingPrompt',
|
||||
SoundboardSound: 'SoundboardSound',
|
||||
Unknown: 'Unknown',
|
||||
};
|
||||
|
||||
/**
|
||||
* The target of a guild audit log entry. It can be one of:
|
||||
* * A guild
|
||||
* * A channel
|
||||
* * A user
|
||||
* * A role
|
||||
* * An invite
|
||||
* * A webhook
|
||||
* * An emoji
|
||||
* * A message
|
||||
* * An integration
|
||||
* * A stage instance
|
||||
* * A sticker
|
||||
* * A guild scheduled event
|
||||
* * A thread
|
||||
* * An application command
|
||||
* * An auto moderation rule
|
||||
* * A guild onboarding prompt
|
||||
* * A soundboard sound
|
||||
* * An object with an id key if target was deleted or fake entity
|
||||
* * An object where the keys represent either the new value or the old value
|
||||
* @typedef {?(Object|Guild|BaseChannel|User|Role|Invite|Webhook|GuildEmoji|Message|Integration|StageInstance|Sticker|
|
||||
* GuildScheduledEvent|ApplicationCommand|AutoModerationRule|GuildOnboardingPrompt|SoundboardSound)} AuditLogEntryTarget
|
||||
*/
|
||||
|
||||
/**
|
||||
* The action type of an entry, e.g. `Create`. Here are the available types:
|
||||
* * Create
|
||||
* * Delete
|
||||
* * Update
|
||||
* * All
|
||||
* @typedef {string} AuditLogActionType
|
||||
*/
|
||||
|
||||
/**
|
||||
* The target type of an entry. Here are the available types:
|
||||
* * Guild
|
||||
* * Channel
|
||||
* * User
|
||||
* * Role
|
||||
* * Invite
|
||||
* * Webhook
|
||||
* * Emoji
|
||||
* * Message
|
||||
* * Integration
|
||||
* * StageInstance
|
||||
* * Sticker
|
||||
* * Thread
|
||||
* * GuildScheduledEvent
|
||||
* * ApplicationCommandPermission
|
||||
* * GuildOnboarding
|
||||
* * GuildOnboardingPrompt
|
||||
* * SoundboardSound
|
||||
* * AutoModeration
|
||||
* * Unknown
|
||||
* @typedef {string} AuditLogTargetType
|
||||
*/
|
||||
|
||||
/**
|
||||
* Constructs an object of known properties for a structure from an array of changes.
|
||||
* @param {AuditLogChange[]} changes The array of changes
|
||||
* @param {Object} [initialData={}] The initial data passed to the function
|
||||
* @returns {Object}
|
||||
* @ignore
|
||||
*/
|
||||
function changesReduce(changes, initialData = {}) {
|
||||
return changes.reduce((accumulator, change) => {
|
||||
accumulator[change.key] = change.new ?? change.old;
|
||||
return accumulator;
|
||||
}, initialData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Audit logs entry.
|
||||
*/
|
||||
class GuildAuditLogsEntry {
|
||||
/**
|
||||
* Key mirror of all available audit log targets.
|
||||
* @type {Object<string, string>}
|
||||
* @memberof GuildAuditLogsEntry
|
||||
*/
|
||||
static Targets = Targets;
|
||||
|
||||
constructor(guild, data, logs) {
|
||||
/**
|
||||
* The target type of this entry
|
||||
* @type {AuditLogTargetType}
|
||||
*/
|
||||
this.targetType = GuildAuditLogsEntry.targetType(data.action_type);
|
||||
const targetType = this.targetType;
|
||||
|
||||
/**
|
||||
* The action type of this entry
|
||||
* @type {AuditLogActionType}
|
||||
*/
|
||||
this.actionType = GuildAuditLogsEntry.actionType(data.action_type);
|
||||
|
||||
/**
|
||||
* The type of action that occurred.
|
||||
* @type {AuditLogEvent}
|
||||
*/
|
||||
this.action = data.action_type;
|
||||
|
||||
/**
|
||||
* The reason of this entry
|
||||
* @type {?string}
|
||||
*/
|
||||
this.reason = data.reason ?? null;
|
||||
|
||||
/**
|
||||
* The id of the user that executed this entry
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.executorId = data.user_id;
|
||||
|
||||
/**
|
||||
* The user that executed this entry
|
||||
* @type {?User}
|
||||
*/
|
||||
this.executor = data.user_id
|
||||
? guild.client.options.partials.includes(Partials.User)
|
||||
? guild.client.users._add({ id: data.user_id })
|
||||
: (guild.client.users.cache.get(data.user_id) ?? null)
|
||||
: null;
|
||||
|
||||
/**
|
||||
* An entry in the audit log representing a specific change.
|
||||
* @typedef {Object} AuditLogChange
|
||||
* @property {string} key The property that was changed, e.g. `nick` for nickname changes
|
||||
* <warn>For application command permissions updates the key is the id of the user, channel,
|
||||
* role, or a permission constant that was updated instead of an actual property name</warn>
|
||||
* @property {*} [old] The old value of the change, e.g. for nicknames, the old nickname
|
||||
* @property {*} [new] The new value of the change, e.g. for nicknames, the new nickname
|
||||
*/
|
||||
|
||||
/**
|
||||
* Specific property changes
|
||||
* @type {AuditLogChange[]}
|
||||
*/
|
||||
this.changes =
|
||||
data.changes?.map(change => ({
|
||||
key: change.key,
|
||||
...('old_value' in change ? { old: change.old_value } : {}),
|
||||
...('new_value' in change ? { new: change.new_value } : {}),
|
||||
})) ?? [];
|
||||
|
||||
/**
|
||||
* The entry's id
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* Any extra data from the entry
|
||||
* @type {?(Object|Role|GuildMember)}
|
||||
*/
|
||||
this.extra = null;
|
||||
switch (data.action_type) {
|
||||
case AuditLogEvent.MemberPrune:
|
||||
this.extra = {
|
||||
removed: Number(data.options.members_removed),
|
||||
days: Number(data.options.delete_member_days),
|
||||
};
|
||||
break;
|
||||
|
||||
case AuditLogEvent.MemberMove:
|
||||
case AuditLogEvent.MessageDelete:
|
||||
this.extra = {
|
||||
channel: guild.channels.cache.get(data.options.channel_id) ?? { id: data.options.channel_id },
|
||||
count: Number(data.options.count),
|
||||
};
|
||||
break;
|
||||
|
||||
case AuditLogEvent.MessagePin:
|
||||
case AuditLogEvent.MessageUnpin:
|
||||
this.extra = {
|
||||
channel: guild.client.channels.cache.get(data.options.channel_id) ?? { id: data.options.channel_id },
|
||||
messageId: data.options.message_id,
|
||||
};
|
||||
break;
|
||||
|
||||
case AuditLogEvent.MessageBulkDelete:
|
||||
case AuditLogEvent.MemberDisconnect:
|
||||
this.extra = {
|
||||
count: Number(data.options.count),
|
||||
};
|
||||
break;
|
||||
|
||||
case AuditLogEvent.ChannelOverwriteCreate:
|
||||
case AuditLogEvent.ChannelOverwriteUpdate:
|
||||
case AuditLogEvent.ChannelOverwriteDelete:
|
||||
switch (data.options.type) {
|
||||
case AuditLogOptionsType.Role:
|
||||
this.extra = guild.roles.cache.get(data.options.id) ?? {
|
||||
id: data.options.id,
|
||||
name: data.options.role_name,
|
||||
type: AuditLogOptionsType.Role,
|
||||
};
|
||||
break;
|
||||
|
||||
case AuditLogOptionsType.Member:
|
||||
this.extra = guild.members.cache.get(data.options.id) ?? {
|
||||
id: data.options.id,
|
||||
type: AuditLogOptionsType.Member,
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case AuditLogEvent.StageInstanceCreate:
|
||||
case AuditLogEvent.StageInstanceDelete:
|
||||
case AuditLogEvent.StageInstanceUpdate:
|
||||
this.extra = {
|
||||
channel: guild.client.channels.cache.get(data.options?.channel_id) ?? { id: data.options?.channel_id },
|
||||
};
|
||||
break;
|
||||
|
||||
case AuditLogEvent.ApplicationCommandPermissionUpdate:
|
||||
this.extra = {
|
||||
applicationId: data.options.application_id,
|
||||
};
|
||||
break;
|
||||
|
||||
case AuditLogEvent.AutoModerationBlockMessage:
|
||||
case AuditLogEvent.AutoModerationFlagToChannel:
|
||||
case AuditLogEvent.AutoModerationUserCommunicationDisabled:
|
||||
this.extra = {
|
||||
autoModerationRuleName: data.options.auto_moderation_rule_name,
|
||||
autoModerationRuleTriggerType: data.options.auto_moderation_rule_trigger_type,
|
||||
channel: guild.client.channels.cache.get(data.options?.channel_id) ?? { id: data.options?.channel_id },
|
||||
};
|
||||
break;
|
||||
|
||||
case AuditLogEvent.MemberKick:
|
||||
case AuditLogEvent.MemberRoleUpdate: {
|
||||
if (data.integration_type) {
|
||||
this.extra = {
|
||||
integrationType: data.integration_type,
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/**
|
||||
* The id of the target of this entry
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.targetId = data.target_id;
|
||||
|
||||
/**
|
||||
* The target of this entry
|
||||
* @type {?AuditLogEntryTarget}
|
||||
*/
|
||||
this.target = null;
|
||||
if (targetType === Targets.Unknown) {
|
||||
this.target = changesReduce(this.changes);
|
||||
this.target.id = data.target_id;
|
||||
// MemberDisconnect and similar types do not provide a target_id.
|
||||
} else if (targetType === Targets.User && data.target_id) {
|
||||
this.target = guild.client.options.partials.includes(Partials.User)
|
||||
? guild.client.users._add({ id: data.target_id })
|
||||
: (guild.client.users.cache.get(data.target_id) ?? null);
|
||||
} else if (targetType === Targets.Guild) {
|
||||
this.target = guild.client.guilds.cache.get(data.target_id);
|
||||
} else if (targetType === Targets.Webhook) {
|
||||
this.target =
|
||||
logs?.webhooks.get(data.target_id) ??
|
||||
new Webhook(
|
||||
guild.client,
|
||||
changesReduce(this.changes, {
|
||||
id: data.target_id,
|
||||
guild_id: guild.id,
|
||||
}),
|
||||
);
|
||||
} else if (targetType === Targets.Invite) {
|
||||
const inviteChange = this.changes.find(({ key }) => key === 'code');
|
||||
|
||||
this.target =
|
||||
guild.invites.cache.get(inviteChange.new ?? inviteChange.old) ??
|
||||
new Invite(guild.client, changesReduce(this.changes, { guild }));
|
||||
} else if (targetType === Targets.Message) {
|
||||
// Discord sends a channel id for the MessageBulkDelete action type.
|
||||
this.target =
|
||||
data.action_type === AuditLogEvent.MessageBulkDelete
|
||||
? (guild.channels.cache.get(data.target_id) ?? { id: data.target_id })
|
||||
: (guild.client.users.cache.get(data.target_id) ?? null);
|
||||
} else if (targetType === Targets.Integration) {
|
||||
this.target =
|
||||
logs?.integrations.get(data.target_id) ??
|
||||
new Integration(guild.client, changesReduce(this.changes, { id: data.target_id }), guild);
|
||||
} else if (targetType === Targets.Channel || targetType === Targets.Thread) {
|
||||
this.target = guild.channels.cache.get(data.target_id) ?? changesReduce(this.changes, { id: data.target_id });
|
||||
} else if (targetType === Targets.StageInstance) {
|
||||
this.target =
|
||||
guild.stageInstances.cache.get(data.target_id) ??
|
||||
new StageInstance(
|
||||
guild.client,
|
||||
changesReduce(this.changes, {
|
||||
id: data.target_id,
|
||||
channel_id: data.options?.channel_id,
|
||||
guild_id: guild.id,
|
||||
}),
|
||||
);
|
||||
} else if (targetType === Targets.Sticker) {
|
||||
this.target =
|
||||
guild.stickers.cache.get(data.target_id) ??
|
||||
new Sticker(guild.client, changesReduce(this.changes, { id: data.target_id }));
|
||||
} else if (targetType === Targets.GuildScheduledEvent) {
|
||||
this.target =
|
||||
guild.scheduledEvents.cache.get(data.target_id) ??
|
||||
new GuildScheduledEvent(guild.client, changesReduce(this.changes, { id: data.target_id, guild_id: guild.id }));
|
||||
} else if (targetType === Targets.ApplicationCommand) {
|
||||
this.target = logs?.applicationCommands.get(data.target_id) ?? { id: data.target_id };
|
||||
} else if (targetType === Targets.AutoModeration) {
|
||||
this.target =
|
||||
guild.autoModerationRules.cache.get(data.target_id) ??
|
||||
new AutoModerationRule(
|
||||
guild.client,
|
||||
changesReduce(this.changes, { id: data.target_id, guild_id: guild.id }),
|
||||
guild,
|
||||
);
|
||||
} else if (targetType === Targets.GuildOnboardingPrompt) {
|
||||
this.target =
|
||||
data.action_type === AuditLogEvent.OnboardingPromptCreate
|
||||
? new GuildOnboardingPrompt(guild.client, changesReduce(this.changes, { id: data.target_id }), guild.id)
|
||||
: changesReduce(this.changes, { id: data.target_id });
|
||||
} else if (targetType === Targets.Role) {
|
||||
this.target = guild.roles.cache.get(data.target_id) ?? { id: data.target_id };
|
||||
} else if (targetType === Targets.Emoji) {
|
||||
this.target = guild.emojis.cache.get(data.target_id) ?? { id: data.target_id };
|
||||
} else if (targetType === Targets.SoundboardSound) {
|
||||
this.target = guild.soundboardSounds.cache.get(data.target_id) ?? { id: data.target_id };
|
||||
} else if (data.target_id) {
|
||||
this.target = { id: data.target_id };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the target type of a guild audit log entry.
|
||||
* @param {AuditLogEvent} target The action target
|
||||
* @returns {AuditLogTargetType}
|
||||
*/
|
||||
static targetType(target) {
|
||||
if (target < 10) return Targets.Guild;
|
||||
if (target < 20) return Targets.Channel;
|
||||
if (target < 30) return Targets.User;
|
||||
if (target < 40) return Targets.Role;
|
||||
if (target < 50) return Targets.Invite;
|
||||
if (target < 60) return Targets.Webhook;
|
||||
if (target < 70) return Targets.Emoji;
|
||||
if (target < 80) return Targets.Message;
|
||||
if (target < 83) return Targets.Integration;
|
||||
if (target < 86) return Targets.StageInstance;
|
||||
if (target < 100) return Targets.Sticker;
|
||||
if (target < 110) return Targets.GuildScheduledEvent;
|
||||
if (target < 120) return Targets.Thread;
|
||||
if (target < 130) return Targets.ApplicationCommand;
|
||||
if (target < 140) return Targets.SoundboardSound;
|
||||
if (target < 143) return Targets.AutoModeration;
|
||||
if (target < 146) return Targets.User;
|
||||
if (target >= 163 && target <= 165) return Targets.GuildOnboardingPrompt;
|
||||
if (target >= 160 && target < 170) return Targets.GuildOnboarding;
|
||||
return Targets.Unknown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the action type from the guild audit log entry action.
|
||||
* @param {AuditLogEvent} action The action target
|
||||
* @returns {AuditLogActionType}
|
||||
*/
|
||||
static actionType(action) {
|
||||
if (
|
||||
[
|
||||
AuditLogEvent.ChannelCreate,
|
||||
AuditLogEvent.ChannelOverwriteCreate,
|
||||
AuditLogEvent.MemberBanRemove,
|
||||
AuditLogEvent.BotAdd,
|
||||
AuditLogEvent.RoleCreate,
|
||||
AuditLogEvent.InviteCreate,
|
||||
AuditLogEvent.WebhookCreate,
|
||||
AuditLogEvent.EmojiCreate,
|
||||
AuditLogEvent.MessagePin,
|
||||
AuditLogEvent.IntegrationCreate,
|
||||
AuditLogEvent.StageInstanceCreate,
|
||||
AuditLogEvent.StickerCreate,
|
||||
AuditLogEvent.GuildScheduledEventCreate,
|
||||
AuditLogEvent.ThreadCreate,
|
||||
AuditLogEvent.SoundboardSoundCreate,
|
||||
AuditLogEvent.AutoModerationRuleCreate,
|
||||
AuditLogEvent.AutoModerationBlockMessage,
|
||||
AuditLogEvent.OnboardingPromptCreate,
|
||||
AuditLogEvent.OnboardingCreate,
|
||||
].includes(action)
|
||||
) {
|
||||
return 'Create';
|
||||
}
|
||||
|
||||
if (
|
||||
[
|
||||
AuditLogEvent.ChannelDelete,
|
||||
AuditLogEvent.ChannelOverwriteDelete,
|
||||
AuditLogEvent.MemberKick,
|
||||
AuditLogEvent.MemberPrune,
|
||||
AuditLogEvent.MemberBanAdd,
|
||||
AuditLogEvent.MemberDisconnect,
|
||||
AuditLogEvent.RoleDelete,
|
||||
AuditLogEvent.InviteDelete,
|
||||
AuditLogEvent.WebhookDelete,
|
||||
AuditLogEvent.EmojiDelete,
|
||||
AuditLogEvent.MessageDelete,
|
||||
AuditLogEvent.MessageBulkDelete,
|
||||
AuditLogEvent.MessageUnpin,
|
||||
AuditLogEvent.IntegrationDelete,
|
||||
AuditLogEvent.StageInstanceDelete,
|
||||
AuditLogEvent.StickerDelete,
|
||||
AuditLogEvent.GuildScheduledEventDelete,
|
||||
AuditLogEvent.ThreadDelete,
|
||||
AuditLogEvent.SoundboardSoundDelete,
|
||||
AuditLogEvent.AutoModerationRuleDelete,
|
||||
AuditLogEvent.OnboardingPromptDelete,
|
||||
].includes(action)
|
||||
) {
|
||||
return 'Delete';
|
||||
}
|
||||
|
||||
if (
|
||||
[
|
||||
AuditLogEvent.GuildUpdate,
|
||||
AuditLogEvent.ChannelUpdate,
|
||||
AuditLogEvent.ChannelOverwriteUpdate,
|
||||
AuditLogEvent.MemberUpdate,
|
||||
AuditLogEvent.MemberRoleUpdate,
|
||||
AuditLogEvent.MemberMove,
|
||||
AuditLogEvent.RoleUpdate,
|
||||
AuditLogEvent.InviteUpdate,
|
||||
AuditLogEvent.WebhookUpdate,
|
||||
AuditLogEvent.EmojiUpdate,
|
||||
AuditLogEvent.IntegrationUpdate,
|
||||
AuditLogEvent.StageInstanceUpdate,
|
||||
AuditLogEvent.StickerUpdate,
|
||||
AuditLogEvent.GuildScheduledEventUpdate,
|
||||
AuditLogEvent.ThreadUpdate,
|
||||
AuditLogEvent.SoundboardSoundUpdate,
|
||||
AuditLogEvent.ApplicationCommandPermissionUpdate,
|
||||
AuditLogEvent.AutoModerationRuleUpdate,
|
||||
AuditLogEvent.AutoModerationBlockMessage,
|
||||
AuditLogEvent.AutoModerationFlagToChannel,
|
||||
AuditLogEvent.AutoModerationUserCommunicationDisabled,
|
||||
AuditLogEvent.OnboardingPromptUpdate,
|
||||
AuditLogEvent.OnboardingUpdate,
|
||||
].includes(action)
|
||||
) {
|
||||
return 'Update';
|
||||
}
|
||||
|
||||
return 'All';
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp this entry was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time this entry was created at
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return flatten(this, { createdTimestamp: true });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildAuditLogsEntry;
|
||||
59
node_modules/discord.js/src/structures/GuildBan.js
generated
vendored
Normal file
59
node_modules/discord.js/src/structures/GuildBan.js
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
'use strict';
|
||||
|
||||
const Base = require('./Base');
|
||||
|
||||
/**
|
||||
* Represents a ban in a guild on Discord.
|
||||
* @extends {Base}
|
||||
*/
|
||||
class GuildBan extends Base {
|
||||
constructor(client, data, guild) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The guild in which the ban is
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
if ('user' in data) {
|
||||
/**
|
||||
* The user this ban applies to
|
||||
* @type {User}
|
||||
*/
|
||||
this.user = this.client.users._add(data.user, true);
|
||||
}
|
||||
|
||||
if ('reason' in data) {
|
||||
/**
|
||||
* The reason for the ban
|
||||
* @type {?string}
|
||||
*/
|
||||
this.reason = data.reason;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this GuildBan is partial. If the reason is not provided the value is null
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get partial() {
|
||||
return !('reason' in this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches this GuildBan.
|
||||
* @param {boolean} [force=true] Whether to skip the cache check and request the API
|
||||
* @returns {Promise<GuildBan>}
|
||||
*/
|
||||
fetch(force = true) {
|
||||
return this.guild.bans.fetch({ user: this.user, cache: true, force });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildBan;
|
||||
476
node_modules/discord.js/src/structures/GuildChannel.js
generated
vendored
Normal file
476
node_modules/discord.js/src/structures/GuildChannel.js
generated
vendored
Normal file
@@ -0,0 +1,476 @@
|
||||
'use strict';
|
||||
|
||||
const { Snowflake } = require('@sapphire/snowflake');
|
||||
const { PermissionFlagsBits, ChannelType } = require('discord-api-types/v10');
|
||||
const { BaseChannel } = require('./BaseChannel');
|
||||
const { DiscordjsError, ErrorCodes } = require('../errors');
|
||||
const PermissionOverwriteManager = require('../managers/PermissionOverwriteManager');
|
||||
const { VoiceBasedChannelTypes } = require('../util/Constants');
|
||||
const PermissionsBitField = require('../util/PermissionsBitField');
|
||||
const { getSortableGroupTypes } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents a guild channel from any of the following:
|
||||
* - {@link TextChannel}
|
||||
* - {@link VoiceChannel}
|
||||
* - {@link CategoryChannel}
|
||||
* - {@link NewsChannel}
|
||||
* - {@link StageChannel}
|
||||
* - {@link ForumChannel}
|
||||
* - {@link MediaChannel}
|
||||
* @extends {BaseChannel}
|
||||
* @abstract
|
||||
*/
|
||||
class GuildChannel extends BaseChannel {
|
||||
constructor(guild, data, client, immediatePatch = true) {
|
||||
super(client, data, false);
|
||||
|
||||
/**
|
||||
* The guild the channel is in
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
|
||||
/**
|
||||
* The id of the guild the channel is in
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.guildId = guild?.id ?? data.guild_id;
|
||||
/**
|
||||
* A manager of permission overwrites that belong to this channel
|
||||
* @type {PermissionOverwriteManager}
|
||||
*/
|
||||
this.permissionOverwrites = new PermissionOverwriteManager(this);
|
||||
|
||||
if (data && immediatePatch) this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
super._patch(data);
|
||||
|
||||
if ('name' in data) {
|
||||
/**
|
||||
* The name of the guild channel
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
}
|
||||
|
||||
if ('position' in data) {
|
||||
/**
|
||||
* The raw position of the channel from Discord
|
||||
* @type {number}
|
||||
*/
|
||||
this.rawPosition = data.position;
|
||||
}
|
||||
|
||||
if ('guild_id' in data) {
|
||||
this.guildId = data.guild_id;
|
||||
}
|
||||
|
||||
if ('parent_id' in data) {
|
||||
/**
|
||||
* The id of the category parent of this channel
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.parentId = data.parent_id;
|
||||
} else {
|
||||
this.parentId ??= null;
|
||||
}
|
||||
|
||||
if ('permission_overwrites' in data) {
|
||||
this.permissionOverwrites.cache.clear();
|
||||
for (const overwrite of data.permission_overwrites) {
|
||||
this.permissionOverwrites._add(overwrite);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_clone() {
|
||||
const clone = super._clone();
|
||||
clone.permissionOverwrites = new PermissionOverwriteManager(clone, this.permissionOverwrites.cache.values());
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* The category parent of this channel
|
||||
* @type {?CategoryChannel}
|
||||
* @readonly
|
||||
*/
|
||||
get parent() {
|
||||
return this.guild.channels.resolve(this.parentId);
|
||||
}
|
||||
|
||||
/**
|
||||
* If the permissionOverwrites match the parent channel, null if no parent
|
||||
* @type {?boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get permissionsLocked() {
|
||||
if (!this.parent) return null;
|
||||
|
||||
// Get all overwrites
|
||||
const overwriteIds = new Set([
|
||||
...this.permissionOverwrites.cache.keys(),
|
||||
...this.parent.permissionOverwrites.cache.keys(),
|
||||
]);
|
||||
|
||||
// Compare all overwrites
|
||||
return [...overwriteIds].every(key => {
|
||||
const channelVal = this.permissionOverwrites.cache.get(key);
|
||||
const parentVal = this.parent.permissionOverwrites.cache.get(key);
|
||||
|
||||
// Handle empty overwrite
|
||||
if (
|
||||
(!channelVal &&
|
||||
parentVal.deny.bitfield === PermissionsBitField.DefaultBit &&
|
||||
parentVal.allow.bitfield === PermissionsBitField.DefaultBit) ||
|
||||
(!parentVal &&
|
||||
channelVal.deny.bitfield === PermissionsBitField.DefaultBit &&
|
||||
channelVal.allow.bitfield === PermissionsBitField.DefaultBit)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Compare overwrites
|
||||
return (
|
||||
channelVal !== undefined &&
|
||||
parentVal !== undefined &&
|
||||
channelVal.deny.bitfield === parentVal.deny.bitfield &&
|
||||
channelVal.allow.bitfield === parentVal.allow.bitfield
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The position of the channel
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get position() {
|
||||
const selfIsCategory = this.type === ChannelType.GuildCategory;
|
||||
const types = getSortableGroupTypes(this.type);
|
||||
|
||||
let count = 0;
|
||||
for (const channel of this.guild.channels.cache.values()) {
|
||||
if (!types.includes(channel.type)) continue;
|
||||
if (!selfIsCategory && channel.parentId !== this.parentId) continue;
|
||||
if (this.rawPosition === channel.rawPosition) {
|
||||
if (Snowflake.compare(channel.id, this.id) === -1) count++;
|
||||
} else if (this.rawPosition > channel.rawPosition) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the overall set of permissions for a member or role in this channel, taking into account channel overwrites.
|
||||
* @param {GuildMemberResolvable|RoleResolvable} memberOrRole The member or role to obtain the overall permissions for
|
||||
* @param {boolean} [checkAdmin=true] Whether having the {@link PermissionFlagsBits.Administrator} permission
|
||||
* will return all permissions
|
||||
* @returns {?Readonly<PermissionsBitField>}
|
||||
*/
|
||||
permissionsFor(memberOrRole, checkAdmin = true) {
|
||||
const member = this.guild.members.resolve(memberOrRole);
|
||||
if (member) return this.memberPermissions(member, checkAdmin);
|
||||
const role = this.guild.roles.resolve(memberOrRole);
|
||||
return role && this.rolePermissions(role, checkAdmin);
|
||||
}
|
||||
|
||||
overwritesFor(member, verified = false, roles = null) {
|
||||
if (!verified) member = this.guild.members.resolve(member);
|
||||
if (!member) return [];
|
||||
|
||||
roles ??= member.roles.cache;
|
||||
const roleOverwrites = [];
|
||||
let memberOverwrites;
|
||||
let everyoneOverwrites;
|
||||
|
||||
for (const overwrite of this.permissionOverwrites.cache.values()) {
|
||||
if (overwrite.id === this.guild.id) {
|
||||
everyoneOverwrites = overwrite;
|
||||
} else if (roles.has(overwrite.id)) {
|
||||
roleOverwrites.push(overwrite);
|
||||
} else if (overwrite.id === member.id) {
|
||||
memberOverwrites = overwrite;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
everyone: everyoneOverwrites,
|
||||
roles: roleOverwrites,
|
||||
member: memberOverwrites,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the overall set of permissions for a member in this channel, taking into account channel overwrites.
|
||||
* @param {GuildMember} member The member to obtain the overall permissions for
|
||||
* @param {boolean} checkAdmin Whether having the {@link PermissionFlagsBits.Administrator} permission
|
||||
* will return all permissions
|
||||
* @returns {Readonly<PermissionsBitField>}
|
||||
* @private
|
||||
*/
|
||||
memberPermissions(member, checkAdmin) {
|
||||
if (checkAdmin && member.id === this.guild.ownerId) {
|
||||
return new PermissionsBitField(PermissionsBitField.All).freeze();
|
||||
}
|
||||
|
||||
const roles = member.roles.cache;
|
||||
const permissions = new PermissionsBitField(roles.map(role => role.permissions));
|
||||
|
||||
if (checkAdmin && permissions.has(PermissionFlagsBits.Administrator)) {
|
||||
return new PermissionsBitField(PermissionsBitField.All).freeze();
|
||||
}
|
||||
|
||||
const overwrites = this.overwritesFor(member, true, roles);
|
||||
|
||||
return permissions
|
||||
.remove(overwrites.everyone?.deny ?? PermissionsBitField.DefaultBit)
|
||||
.add(overwrites.everyone?.allow ?? PermissionsBitField.DefaultBit)
|
||||
.remove(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.deny) : PermissionsBitField.DefaultBit)
|
||||
.add(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.allow) : PermissionsBitField.DefaultBit)
|
||||
.remove(overwrites.member?.deny ?? PermissionsBitField.DefaultBit)
|
||||
.add(overwrites.member?.allow ?? PermissionsBitField.DefaultBit)
|
||||
.freeze();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the overall set of permissions for a role in this channel, taking into account channel overwrites.
|
||||
* @param {Role} role The role to obtain the overall permissions for
|
||||
* @param {boolean} checkAdmin Whether having the {@link PermissionFlagsBits.Administrator} permission
|
||||
* will return all permissions
|
||||
* @returns {Readonly<PermissionsBitField>}
|
||||
* @private
|
||||
*/
|
||||
rolePermissions(role, checkAdmin) {
|
||||
if (checkAdmin && role.permissions.has(PermissionFlagsBits.Administrator)) {
|
||||
return new PermissionsBitField(PermissionsBitField.All).freeze();
|
||||
}
|
||||
|
||||
const basePermissions = new PermissionsBitField([role.permissions, role.guild.roles.everyone.permissions]);
|
||||
const everyoneOverwrites = this.permissionOverwrites.cache.get(this.guild.id);
|
||||
const roleOverwrites = this.permissionOverwrites.cache.get(role.id);
|
||||
|
||||
return basePermissions
|
||||
.remove(everyoneOverwrites?.deny ?? PermissionsBitField.DefaultBit)
|
||||
.add(everyoneOverwrites?.allow ?? PermissionsBitField.DefaultBit)
|
||||
.remove(roleOverwrites?.deny ?? PermissionsBitField.DefaultBit)
|
||||
.add(roleOverwrites?.allow ?? PermissionsBitField.DefaultBit)
|
||||
.freeze();
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks in the permission overwrites from the parent channel.
|
||||
* @returns {Promise<GuildChannel>}
|
||||
*/
|
||||
async lockPermissions() {
|
||||
if (!this.parent) throw new DiscordjsError(ErrorCodes.GuildChannelOrphan);
|
||||
const permissionOverwrites = this.parent.permissionOverwrites.cache.map(overwrite => overwrite.toJSON());
|
||||
return this.edit({ permissionOverwrites });
|
||||
}
|
||||
|
||||
/**
|
||||
* A collection of cached members of this channel, mapped by their ids.
|
||||
* Members that can view this channel, if the channel is text-based.
|
||||
* Members in the channel, if the channel is voice-based.
|
||||
* @type {Collection<Snowflake, GuildMember>}
|
||||
* @readonly
|
||||
*/
|
||||
get members() {
|
||||
return this.guild.members.cache.filter(member =>
|
||||
this.permissionsFor(member).has(PermissionFlagsBits.ViewChannel, false),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits the channel.
|
||||
* @param {GuildChannelEditOptions} options The options to provide
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Edit a channel
|
||||
* channel.edit({ name: 'new-channel' })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
edit(options) {
|
||||
return this.guild.channels.edit(this, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new name for the guild channel.
|
||||
* @param {string} name The new name for the guild channel
|
||||
* @param {string} [reason] Reason for changing the guild channel's name
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Set a new channel name
|
||||
* channel.setName('not_general')
|
||||
* .then(newChannel => console.log(`Channel's new name is ${newChannel.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setName(name, reason) {
|
||||
return this.edit({ name, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to set the parent of a channel.
|
||||
* @typedef {Object} SetParentOptions
|
||||
* @property {boolean} [lockPermissions=true] Whether to lock the permissions to what the parent's permissions are
|
||||
* @property {string} [reason] The reason for modifying the parent of the channel
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sets the parent of this channel.
|
||||
* @param {?CategoryChannelResolvable} channel The category channel to set as the parent
|
||||
* @param {SetParentOptions} [options={}] The options for setting the parent
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Add a parent to a channel
|
||||
* message.channel.setParent('355908108431917066', { lockPermissions: false })
|
||||
* .then(channel => console.log(`New parent of ${message.channel.name}: ${channel.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setParent(channel, { lockPermissions = true, reason } = {}) {
|
||||
return this.edit({
|
||||
parent: channel ?? null,
|
||||
lockPermissions,
|
||||
reason,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to set the position of a channel.
|
||||
* @typedef {Object} SetChannelPositionOptions
|
||||
* @property {boolean} [relative=false] Whether or not to change the position relative to its current value
|
||||
* @property {string} [reason] The reason for changing the position
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sets a new position for the guild channel.
|
||||
* @param {number} position The new position for the guild channel
|
||||
* @param {SetChannelPositionOptions} [options] Options for setting position
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Set a new channel position
|
||||
* channel.setPosition(2)
|
||||
* .then(newChannel => console.log(`Channel's new position is ${newChannel.position}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setPosition(position, options = {}) {
|
||||
return this.guild.channels.setPosition(this, position, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to clone a guild channel.
|
||||
* @typedef {GuildChannelCreateOptions} GuildChannelCloneOptions
|
||||
* @property {string} [name=this.name] Name of the new channel
|
||||
*/
|
||||
|
||||
/**
|
||||
* Clones this channel.
|
||||
* @param {GuildChannelCloneOptions} [options] The options for cloning this channel
|
||||
* @returns {Promise<GuildChannel>}
|
||||
*/
|
||||
clone(options = {}) {
|
||||
return this.guild.channels.create({
|
||||
name: options.name ?? this.name,
|
||||
permissionOverwrites: this.permissionOverwrites.cache,
|
||||
topic: this.topic,
|
||||
type: this.type,
|
||||
nsfw: this.nsfw,
|
||||
parent: this.parent,
|
||||
bitrate: this.bitrate,
|
||||
userLimit: this.userLimit,
|
||||
rateLimitPerUser: this.rateLimitPerUser,
|
||||
position: this.rawPosition,
|
||||
reason: null,
|
||||
...options,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this channel has the same type, topic, position, name, overwrites, and id as another channel.
|
||||
* In most cases, a simple `channel.id === channel2.id` will do, and is much faster too.
|
||||
* @param {GuildChannel} channel Channel to compare with
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(channel) {
|
||||
let equal =
|
||||
channel &&
|
||||
this.id === channel.id &&
|
||||
this.type === channel.type &&
|
||||
this.topic === channel.topic &&
|
||||
this.position === channel.position &&
|
||||
this.name === channel.name;
|
||||
|
||||
if (equal) {
|
||||
if (this.permissionOverwrites && channel.permissionOverwrites) {
|
||||
equal = this.permissionOverwrites.cache.equals(channel.permissionOverwrites.cache);
|
||||
} else {
|
||||
equal = !this.permissionOverwrites && !channel.permissionOverwrites;
|
||||
}
|
||||
}
|
||||
|
||||
return equal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the channel is deletable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get deletable() {
|
||||
return this.manageable && this.guild.rulesChannelId !== this.id && this.guild.publicUpdatesChannelId !== this.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the channel is manageable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get manageable() {
|
||||
if (this.client.user.id === this.guild.ownerId) return true;
|
||||
const permissions = this.permissionsFor(this.client.user);
|
||||
if (!permissions) return false;
|
||||
|
||||
// This flag allows managing even if timed out
|
||||
if (permissions.has(PermissionFlagsBits.Administrator, false)) return true;
|
||||
if (this.guild.members.me.communicationDisabledUntilTimestamp > Date.now()) return false;
|
||||
|
||||
const bitfield = VoiceBasedChannelTypes.includes(this.type)
|
||||
? PermissionFlagsBits.ManageChannels | PermissionFlagsBits.Connect
|
||||
: PermissionFlagsBits.ViewChannel | PermissionFlagsBits.ManageChannels;
|
||||
return permissions.has(bitfield, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the channel is viewable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get viewable() {
|
||||
if (this.client.user.id === this.guild.ownerId) return true;
|
||||
const permissions = this.permissionsFor(this.client.user);
|
||||
if (!permissions) return false;
|
||||
return permissions.has(PermissionFlagsBits.ViewChannel, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this channel.
|
||||
* @param {string} [reason] Reason for deleting this channel
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Delete the channel
|
||||
* channel.delete('making room for new channels')
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async delete(reason) {
|
||||
await this.guild.channels.delete(this.id, reason);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildChannel;
|
||||
148
node_modules/discord.js/src/structures/GuildEmoji.js
generated
vendored
Normal file
148
node_modules/discord.js/src/structures/GuildEmoji.js
generated
vendored
Normal file
@@ -0,0 +1,148 @@
|
||||
'use strict';
|
||||
|
||||
const { PermissionFlagsBits } = require('discord-api-types/v10');
|
||||
const BaseGuildEmoji = require('./BaseGuildEmoji');
|
||||
const { DiscordjsError, ErrorCodes } = require('../errors');
|
||||
const GuildEmojiRoleManager = require('../managers/GuildEmojiRoleManager');
|
||||
|
||||
/**
|
||||
* Represents a custom emoji.
|
||||
* @extends {BaseGuildEmoji}
|
||||
*/
|
||||
class GuildEmoji extends BaseGuildEmoji {
|
||||
constructor(client, data, guild) {
|
||||
super(client, data, guild);
|
||||
|
||||
/**
|
||||
* The user who created this emoji
|
||||
* @type {?User}
|
||||
*/
|
||||
this.author = null;
|
||||
|
||||
/**
|
||||
* Array of role ids this emoji is active for
|
||||
* @name GuildEmoji#_roles
|
||||
* @type {Snowflake[]}
|
||||
* @private
|
||||
*/
|
||||
Object.defineProperty(this, '_roles', { value: [], writable: true });
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* The guild this emoji is part of
|
||||
* @type {Guild}
|
||||
* @name GuildEmoji#guild
|
||||
*/
|
||||
|
||||
_clone() {
|
||||
const clone = super._clone();
|
||||
clone._roles = this._roles.slice();
|
||||
return clone;
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
super._patch(data);
|
||||
|
||||
if (data.user) this.author = this.client.users._add(data.user);
|
||||
if (data.roles) this._roles = data.roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the emoji is deletable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get deletable() {
|
||||
if (!this.guild.members.me) throw new DiscordjsError(ErrorCodes.GuildUncachedMe);
|
||||
return !this.managed && this.guild.members.me.permissions.has(PermissionFlagsBits.ManageGuildExpressions);
|
||||
}
|
||||
|
||||
/**
|
||||
* A manager for roles this emoji is active for.
|
||||
* @type {GuildEmojiRoleManager}
|
||||
* @readonly
|
||||
*/
|
||||
get roles() {
|
||||
return new GuildEmojiRoleManager(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the author for this emoji
|
||||
* @returns {Promise<User>}
|
||||
*/
|
||||
fetchAuthor() {
|
||||
return this.guild.emojis.fetchAuthor(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data for editing an emoji.
|
||||
* @typedef {Object} GuildEmojiEditOptions
|
||||
* @property {string} [name] The name of the emoji
|
||||
* @property {Collection<Snowflake, Role>|RoleResolvable[]} [roles] Roles to restrict emoji to
|
||||
* @property {string} [reason] Reason for editing this emoji
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits the emoji.
|
||||
* @param {GuildEmojiEditOptions} options The options to provide
|
||||
* @returns {Promise<GuildEmoji>}
|
||||
* @example
|
||||
* // Edit an emoji
|
||||
* emoji.edit({ name: 'newemoji' })
|
||||
* .then(emoji => console.log(`Edited emoji ${emoji}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
edit(options) {
|
||||
return this.guild.emojis.edit(this.id, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the emoji.
|
||||
* @param {string} name The new name for the emoji
|
||||
* @param {string} [reason] Reason for changing the emoji's name
|
||||
* @returns {Promise<GuildEmoji>}
|
||||
*/
|
||||
setName(name, reason) {
|
||||
return this.edit({ name, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the emoji.
|
||||
* @param {string} [reason] Reason for deleting the emoji
|
||||
* @returns {Promise<GuildEmoji>}
|
||||
*/
|
||||
async delete(reason) {
|
||||
await this.guild.emojis.delete(this.id, reason);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this emoji is the same as another one.
|
||||
* @param {GuildEmoji|APIEmoji} other The emoji to compare it to
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(other) {
|
||||
if (other instanceof GuildEmoji) {
|
||||
return (
|
||||
other.id === this.id &&
|
||||
other.name === this.name &&
|
||||
other.managed === this.managed &&
|
||||
other.available === this.available &&
|
||||
other.requiresColons === this.requiresColons &&
|
||||
other.roles.cache.size === this.roles.cache.size &&
|
||||
other.roles.cache.every(role => this.roles.cache.has(role.id))
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
other.id === this.id &&
|
||||
other.name === this.name &&
|
||||
other.roles.length === this.roles.cache.size &&
|
||||
other.roles.every(role => this.roles.cache.has(role))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildEmoji;
|
||||
591
node_modules/discord.js/src/structures/GuildMember.js
generated
vendored
Normal file
591
node_modules/discord.js/src/structures/GuildMember.js
generated
vendored
Normal file
@@ -0,0 +1,591 @@
|
||||
'use strict';
|
||||
|
||||
const { PermissionFlagsBits } = require('discord-api-types/v10');
|
||||
const Base = require('./Base');
|
||||
const VoiceState = require('./VoiceState');
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const { DiscordjsError, ErrorCodes } = require('../errors');
|
||||
const GuildMemberRoleManager = require('../managers/GuildMemberRoleManager');
|
||||
const { GuildMemberFlagsBitField } = require('../util/GuildMemberFlagsBitField');
|
||||
const PermissionsBitField = require('../util/PermissionsBitField');
|
||||
|
||||
/**
|
||||
* Represents a member of a guild on Discord.
|
||||
* @implements {TextBasedChannel}
|
||||
* @extends {Base}
|
||||
*/
|
||||
class GuildMember extends Base {
|
||||
constructor(client, data, guild) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The guild that this member is part of
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
|
||||
/**
|
||||
* The last timestamp this member started boosting the guild
|
||||
* @type {?number}
|
||||
*/
|
||||
this.premiumSinceTimestamp = null;
|
||||
|
||||
/**
|
||||
* The nickname of this member, if they have one
|
||||
* @type {?string}
|
||||
*/
|
||||
this.nickname = null;
|
||||
|
||||
/**
|
||||
* Whether this member has yet to pass the guild's membership gate
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.pending = null;
|
||||
|
||||
/**
|
||||
* The timestamp this member's timeout will be removed
|
||||
* @type {?number}
|
||||
*/
|
||||
this.communicationDisabledUntilTimestamp = null;
|
||||
|
||||
/**
|
||||
* The role ids of the member
|
||||
* @name GuildMember#_roles
|
||||
* @type {Snowflake[]}
|
||||
* @private
|
||||
*/
|
||||
Object.defineProperty(this, '_roles', { value: [], writable: true });
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
if ('user' in data) {
|
||||
/**
|
||||
* The user that this guild member instance represents
|
||||
* @type {?User}
|
||||
*/
|
||||
this.user = this.client.users._add(data.user, true);
|
||||
}
|
||||
|
||||
if ('nick' in data) this.nickname = data.nick;
|
||||
if ('avatar' in data) {
|
||||
/**
|
||||
* The guild member's avatar hash
|
||||
* @type {?string}
|
||||
*/
|
||||
this.avatar = data.avatar;
|
||||
} else if (typeof this.avatar !== 'string') {
|
||||
this.avatar = null;
|
||||
}
|
||||
|
||||
if ('banner' in data) {
|
||||
/**
|
||||
* The guild member's banner hash.
|
||||
* @type {?string}
|
||||
*/
|
||||
this.banner = data.banner;
|
||||
} else {
|
||||
this.banner ??= null;
|
||||
}
|
||||
|
||||
if ('joined_at' in data) {
|
||||
/**
|
||||
* The timestamp the member joined the guild at
|
||||
*
|
||||
* @type {?number}
|
||||
*/
|
||||
this.joinedTimestamp = data.joined_at && Date.parse(data.joined_at);
|
||||
} else {
|
||||
this.joinedTimestamp ??= null;
|
||||
}
|
||||
|
||||
if ('premium_since' in data) {
|
||||
this.premiumSinceTimestamp = data.premium_since ? Date.parse(data.premium_since) : null;
|
||||
}
|
||||
if ('roles' in data) this._roles = data.roles;
|
||||
|
||||
if ('pending' in data) {
|
||||
this.pending = data.pending;
|
||||
} else if (!this.partial) {
|
||||
// See https://github.com/discordjs/discord.js/issues/6546 for more info.
|
||||
this.pending ??= false;
|
||||
}
|
||||
|
||||
if ('communication_disabled_until' in data) {
|
||||
this.communicationDisabledUntilTimestamp =
|
||||
data.communication_disabled_until && Date.parse(data.communication_disabled_until);
|
||||
}
|
||||
|
||||
if ('flags' in data) {
|
||||
/**
|
||||
* The flags of this member
|
||||
* @type {Readonly<GuildMemberFlagsBitField>}
|
||||
*/
|
||||
this.flags = new GuildMemberFlagsBitField(data.flags).freeze();
|
||||
} else {
|
||||
this.flags ??= new GuildMemberFlagsBitField().freeze();
|
||||
}
|
||||
|
||||
if (data.avatar_decoration_data) {
|
||||
/**
|
||||
* The member avatar decoration's data
|
||||
*
|
||||
* @type {?AvatarDecorationData}
|
||||
*/
|
||||
this.avatarDecorationData = {
|
||||
asset: data.avatar_decoration_data.asset,
|
||||
skuId: data.avatar_decoration_data.sku_id,
|
||||
};
|
||||
} else {
|
||||
this.avatarDecorationData = null;
|
||||
}
|
||||
}
|
||||
|
||||
_clone() {
|
||||
const clone = super._clone();
|
||||
clone._roles = this._roles.slice();
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this GuildMember is a partial
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get partial() {
|
||||
return this.joinedTimestamp === null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A manager for the roles belonging to this member
|
||||
* @type {GuildMemberRoleManager}
|
||||
* @readonly
|
||||
*/
|
||||
get roles() {
|
||||
return new GuildMemberRoleManager(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* The voice state of this member
|
||||
* @type {VoiceState}
|
||||
* @readonly
|
||||
*/
|
||||
get voice() {
|
||||
return this.guild.voiceStates.cache.get(this.id) ?? new VoiceState(this.guild, { user_id: this.id });
|
||||
}
|
||||
|
||||
/**
|
||||
* A link to the member's guild avatar.
|
||||
* @param {ImageURLOptions} [options={}] Options for the image URL
|
||||
* @returns {?string}
|
||||
*/
|
||||
avatarURL(options = {}) {
|
||||
return this.avatar && this.client.rest.cdn.guildMemberAvatar(this.guild.id, this.id, this.avatar, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* A link to the member's avatar decoration.
|
||||
*
|
||||
* @returns {?string}
|
||||
*/
|
||||
avatarDecorationURL() {
|
||||
return this.avatarDecorationData ? this.client.rest.cdn.avatarDecoration(this.avatarDecorationData.asset) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A link to the member's banner.
|
||||
* @param {ImageURLOptions} [options={}] Options for the banner URL
|
||||
* @returns {?string}
|
||||
*/
|
||||
bannerURL(options = {}) {
|
||||
return this.banner && this.client.rest.cdn.guildMemberBanner(this.guild.id, this.id, this.banner, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* A link to the member's guild avatar if they have one.
|
||||
* Otherwise, a link to their {@link User#displayAvatarURL} will be returned.
|
||||
* @param {ImageURLOptions} [options={}] Options for the image URL
|
||||
* @returns {string}
|
||||
*/
|
||||
displayAvatarURL(options) {
|
||||
return this.avatarURL(options) ?? this.user.displayAvatarURL(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* A link to the member's guild banner if they have one.
|
||||
* Otherwise, a link to their {@link User#bannerURL} will be returned.
|
||||
* @param {ImageURLOptions} [options={}] Options for the image URL
|
||||
* @returns {?string}
|
||||
*/
|
||||
displayBannerURL(options) {
|
||||
return this.bannerURL(options) ?? this.user.bannerURL(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* A link to the member's guild avatar decoration if they have one.
|
||||
* Otherwise, a link to their {@link User#avatarDecorationURL} will be returned.
|
||||
*
|
||||
* @returns {?string}
|
||||
*/
|
||||
displayAvatarDecorationURL() {
|
||||
return this.avatarDecorationURL() ?? this.user.avatarDecorationURL();
|
||||
}
|
||||
|
||||
/**
|
||||
* The time this member joined the guild
|
||||
* @type {?Date}
|
||||
* @readonly
|
||||
*/
|
||||
get joinedAt() {
|
||||
return this.joinedTimestamp && new Date(this.joinedTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time this member's timeout will be removed
|
||||
* @type {?Date}
|
||||
* @readonly
|
||||
*/
|
||||
get communicationDisabledUntil() {
|
||||
return this.communicationDisabledUntilTimestamp && new Date(this.communicationDisabledUntilTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The last time this member started boosting the guild
|
||||
* @type {?Date}
|
||||
* @readonly
|
||||
*/
|
||||
get premiumSince() {
|
||||
return this.premiumSinceTimestamp && new Date(this.premiumSinceTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The presence of this guild member
|
||||
* @type {?Presence}
|
||||
* @readonly
|
||||
*/
|
||||
get presence() {
|
||||
return this.guild.presences.cache.get(this.id) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The displayed role color of this member in base 10
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get displayColor() {
|
||||
return this.roles.color?.colors.primaryColor ?? 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The displayed role color of this member in hexadecimal
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get displayHexColor() {
|
||||
return this.roles.color?.hexColor ?? '#000000';
|
||||
}
|
||||
|
||||
/**
|
||||
* The member's id
|
||||
* @type {Snowflake}
|
||||
* @readonly
|
||||
*/
|
||||
get id() {
|
||||
return this.user.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* The DM between the client's user and this member
|
||||
* @type {?DMChannel}
|
||||
* @readonly
|
||||
*/
|
||||
get dmChannel() {
|
||||
return this.client.users.dmChannel(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The nickname of this member, or their user display name if they don't have one
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get displayName() {
|
||||
return this.nickname ?? this.user.displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* The overall set of permissions for this member, taking only roles and owner status into account
|
||||
* @type {Readonly<PermissionsBitField>}
|
||||
* @readonly
|
||||
*/
|
||||
get permissions() {
|
||||
if (this.user.id === this.guild.ownerId) return new PermissionsBitField(PermissionsBitField.All).freeze();
|
||||
return new PermissionsBitField(this.roles.cache.map(role => role.permissions)).freeze();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the client user is above this user in the hierarchy, according to role position and guild ownership.
|
||||
* This is a prerequisite for many moderative actions.
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get manageable() {
|
||||
if (this.user.id === this.guild.ownerId) return false;
|
||||
if (this.user.id === this.client.user.id) return false;
|
||||
if (this.client.user.id === this.guild.ownerId) return true;
|
||||
if (!this.guild.members.me) throw new DiscordjsError(ErrorCodes.GuildUncachedMe);
|
||||
return this.guild.members.me.roles.highest.comparePositionTo(this.roles.highest) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this member is kickable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get kickable() {
|
||||
if (!this.guild.members.me) throw new DiscordjsError(ErrorCodes.GuildUncachedMe);
|
||||
return this.manageable && this.guild.members.me.permissions.has(PermissionFlagsBits.KickMembers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this member is bannable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get bannable() {
|
||||
if (!this.guild.members.me) throw new DiscordjsError(ErrorCodes.GuildUncachedMe);
|
||||
return this.manageable && this.guild.members.me.permissions.has(PermissionFlagsBits.BanMembers);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this member is moderatable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get moderatable() {
|
||||
return (
|
||||
!this.permissions.has(PermissionFlagsBits.Administrator) &&
|
||||
this.manageable &&
|
||||
(this.guild.members.me?.permissions.has(PermissionFlagsBits.ModerateMembers) ?? false)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this member is currently timed out
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isCommunicationDisabled() {
|
||||
return this.communicationDisabledUntilTimestamp > Date.now();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `channel.permissionsFor(guildMember)`. Returns permissions for a member in a guild channel,
|
||||
* taking into account roles and permission overwrites.
|
||||
* @param {GuildChannelResolvable} channel The guild channel to use as context
|
||||
* @returns {Readonly<PermissionsBitField>}
|
||||
*/
|
||||
permissionsIn(channel) {
|
||||
channel = this.guild.channels.resolve(channel);
|
||||
if (!channel) throw new DiscordjsError(ErrorCodes.GuildChannelResolve);
|
||||
return channel.permissionsFor(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits this member.
|
||||
* @param {GuildMemberEditOptions} options The options to provide
|
||||
* @returns {Promise<GuildMember>}
|
||||
*/
|
||||
edit(options) {
|
||||
return this.guild.members.edit(this, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the flags for this member.
|
||||
* @param {GuildMemberFlagsResolvable} flags The flags to set
|
||||
* @param {string} [reason] Reason for setting the flags
|
||||
* @returns {Promise<GuildMember>}
|
||||
*/
|
||||
setFlags(flags, reason) {
|
||||
return this.edit({ flags, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the nickname for this member.
|
||||
* @param {?string} nick The nickname for the guild member, or `null` if you want to reset their nickname
|
||||
* @param {string} [reason] Reason for setting the nickname
|
||||
* @returns {Promise<GuildMember>}
|
||||
* @example
|
||||
* // Set a nickname for a guild member
|
||||
* guildMember.setNickname('cool nickname', 'Needed a new nickname')
|
||||
* .then(member => console.log(`Set nickname of ${member.user.username}`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Remove a nickname for a guild member
|
||||
* guildMember.setNickname(null, 'No nicknames allowed!')
|
||||
* .then(member => console.log(`Removed nickname for ${member.user.username}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setNickname(nick, reason) {
|
||||
return this.user.id === this.client.user.id
|
||||
? this.guild.members.editMe({ nick, reason })
|
||||
: this.edit({ nick, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DM channel between the client and this member.
|
||||
* @param {boolean} [force=false] Whether to skip the cache check and request the API
|
||||
* @returns {Promise<DMChannel>}
|
||||
*/
|
||||
createDM(force = false) {
|
||||
return this.user.createDM(force);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes any DMs with this member.
|
||||
* @returns {Promise<DMChannel>}
|
||||
*/
|
||||
deleteDM() {
|
||||
return this.user.deleteDM();
|
||||
}
|
||||
|
||||
/**
|
||||
* Kicks this member from the guild.
|
||||
* @param {string} [reason] Reason for kicking user
|
||||
* @returns {Promise<GuildMember>}
|
||||
*/
|
||||
kick(reason) {
|
||||
return this.guild.members.kick(this, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bans this guild member.
|
||||
* @param {BanOptions} [options] Options for the ban
|
||||
* @returns {Promise<GuildMember>}
|
||||
* @example
|
||||
* // Ban a guild member, deleting a week's worth of messages
|
||||
* guildMember.ban({ deleteMessageSeconds: 60 * 60 * 24 * 7, reason: 'They deserved it' })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
ban(options) {
|
||||
return this.guild.bans.create(this, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Times this guild member out.
|
||||
* @param {?DateResolvable} communicationDisabledUntil The date or timestamp
|
||||
* for the member's communication to be disabled until. Provide `null` to remove the timeout.
|
||||
* @param {string} [reason] The reason for this timeout.
|
||||
* @returns {Promise<GuildMember>}
|
||||
* @example
|
||||
* // Time a guild member out for 5 minutes
|
||||
* guildMember.disableCommunicationUntil(Date.now() + (5 * 60 * 1000), 'They deserved it')
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Remove the timeout of a guild member
|
||||
* guildMember.disableCommunicationUntil(null)
|
||||
* .then(member => console.log(`Removed timeout for ${member.displayName}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
disableCommunicationUntil(communicationDisabledUntil, reason) {
|
||||
return this.edit({ communicationDisabledUntil, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Times this guild member out.
|
||||
* @param {?number} timeout The duration in milliseconds
|
||||
* for the member's communication to be disabled. Provide `null` to remove the timeout.
|
||||
* @param {string} [reason] The reason for this timeout.
|
||||
* @returns {Promise<GuildMember>}
|
||||
* @example
|
||||
* // Time a guild member out for 5 minutes
|
||||
* guildMember.timeout(5 * 60 * 1000, 'They deserved it')
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
timeout(timeout, reason) {
|
||||
return this.disableCommunicationUntil(timeout && Date.now() + timeout, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches this GuildMember.
|
||||
* @param {boolean} [force=true] Whether to skip the cache check and request the API
|
||||
* @returns {Promise<GuildMember>}
|
||||
*/
|
||||
fetch(force = true) {
|
||||
return this.guild.members.fetch({ user: this.id, cache: true, force });
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this guild member equals another guild member. It compares all properties, so for most
|
||||
* comparison it is advisable to just compare `member.id === member2.id` as it is significantly faster
|
||||
* and is often what most users need.
|
||||
* @param {GuildMember} member The member to compare with
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(member) {
|
||||
return (
|
||||
member instanceof this.constructor &&
|
||||
this.id === member.id &&
|
||||
this.partial === member.partial &&
|
||||
this.guild.id === member.guild.id &&
|
||||
this.joinedTimestamp === member.joinedTimestamp &&
|
||||
this.nickname === member.nickname &&
|
||||
this.avatar === member.avatar &&
|
||||
this.banner === member.banner &&
|
||||
this.pending === member.pending &&
|
||||
this.communicationDisabledUntilTimestamp === member.communicationDisabledUntilTimestamp &&
|
||||
this.flags.bitfield === member.flags.bitfield &&
|
||||
(this._roles === member._roles ||
|
||||
(this._roles.length === member._roles.length &&
|
||||
this._roles.every((role, index) => role === member._roles[index]))) &&
|
||||
this.avatarDecorationData?.asset === member.avatarDecorationData?.asset &&
|
||||
this.avatarDecorationData?.skuId === member.avatarDecorationData?.skuId
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically returns the user's mention instead of the GuildMember object.
|
||||
* @returns {string}
|
||||
* @example
|
||||
* // Logs: Hello from <@123456789012345678>!
|
||||
* console.log(`Hello from ${member}!`);
|
||||
*/
|
||||
toString() {
|
||||
return this.user.toString();
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
const json = super.toJSON({
|
||||
guild: 'guildId',
|
||||
user: 'userId',
|
||||
displayName: true,
|
||||
roles: true,
|
||||
});
|
||||
json.avatarURL = this.avatarURL();
|
||||
json.bannerURL = this.bannerURL();
|
||||
json.displayAvatarURL = this.displayAvatarURL();
|
||||
json.displayBannerURL = this.displayBannerURL();
|
||||
json.avatarDecorationURL = this.avatarDecorationURL();
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to this user.
|
||||
* @method send
|
||||
* @memberof GuildMember
|
||||
* @instance
|
||||
* @param {string|MessagePayload|MessageCreateOptions} options The options to provide
|
||||
* @returns {Promise<Message>}
|
||||
* @example
|
||||
* // Send a direct message
|
||||
* guildMember.send('Hello!')
|
||||
* .then(message => console.log(`Sent message: ${message.content} to ${guildMember.displayName}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
|
||||
TextBasedChannel.applyToClass(GuildMember);
|
||||
|
||||
exports.GuildMember = GuildMember;
|
||||
64
node_modules/discord.js/src/structures/GuildOnboarding.js
generated
vendored
Normal file
64
node_modules/discord.js/src/structures/GuildOnboarding.js
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const Base = require('./Base');
|
||||
const { GuildOnboardingPrompt } = require('./GuildOnboardingPrompt');
|
||||
|
||||
/**
|
||||
* Represents the onboarding data of a guild.
|
||||
* @extends {Base}
|
||||
*/
|
||||
class GuildOnboarding extends Base {
|
||||
constructor(client, data) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The id of the guild this onboarding data is for
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.guildId = data.guild_id;
|
||||
|
||||
const guild = this.guild;
|
||||
|
||||
/**
|
||||
* The prompts shown during onboarding and in customize community
|
||||
* @type {Collection<Snowflake, GuildOnboardingPrompt>}
|
||||
*/
|
||||
this.prompts = data.prompts.reduce(
|
||||
(prompts, prompt) => prompts.set(prompt.id, new GuildOnboardingPrompt(client, prompt, this.guildId)),
|
||||
new Collection(),
|
||||
);
|
||||
|
||||
/**
|
||||
* The ids of the channels that new members get opted into automatically
|
||||
* @type {Collection<Snowflake, GuildChannel>}
|
||||
*/
|
||||
this.defaultChannels = data.default_channel_ids.reduce(
|
||||
(channels, channelId) => channels.set(channelId, guild.channels.cache.get(channelId)),
|
||||
new Collection(),
|
||||
);
|
||||
|
||||
/**
|
||||
* Whether onboarding is enabled
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.enabled = data.enabled;
|
||||
|
||||
/**
|
||||
* The mode of this onboarding
|
||||
* @type {GuildOnboardingMode}
|
||||
*/
|
||||
this.mode = data.mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* The guild this onboarding is from
|
||||
* @type {Guild}
|
||||
* @readonly
|
||||
*/
|
||||
get guild() {
|
||||
return this.client.guilds.cache.get(this.guildId);
|
||||
}
|
||||
}
|
||||
|
||||
exports.GuildOnboarding = GuildOnboarding;
|
||||
78
node_modules/discord.js/src/structures/GuildOnboardingPrompt.js
generated
vendored
Normal file
78
node_modules/discord.js/src/structures/GuildOnboardingPrompt.js
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const Base = require('./Base');
|
||||
const { GuildOnboardingPromptOption } = require('./GuildOnboardingPromptOption');
|
||||
|
||||
/**
|
||||
* Represents the data of a prompt of a guilds onboarding.
|
||||
* @extends {Base}
|
||||
*/
|
||||
class GuildOnboardingPrompt extends Base {
|
||||
constructor(client, data, guildId) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The id of the guild this onboarding prompt is from
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.guildId = guildId;
|
||||
|
||||
/**
|
||||
* The id of the prompt
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The options available within the prompt
|
||||
* @type {Collection<Snowflake, GuildOnboardingPromptOption>}
|
||||
*/
|
||||
this.options = data.options.reduce(
|
||||
(options, option) => options.set(option.id, new GuildOnboardingPromptOption(client, option, guildId)),
|
||||
new Collection(),
|
||||
);
|
||||
|
||||
/**
|
||||
* The title of the prompt
|
||||
* @type {string}
|
||||
*/
|
||||
this.title = data.title;
|
||||
|
||||
/**
|
||||
* Whether users are limited to selecting one option for the prompt
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.singleSelect = data.single_select;
|
||||
|
||||
/**
|
||||
* Whether the prompt is required before a user completes the onboarding flow
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.required = data.required;
|
||||
|
||||
/**
|
||||
* Whether the prompt is present in the onboarding flow.
|
||||
* If `false`, the prompt will only appear in the Channels & Roles tab
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.inOnboarding = data.in_onboarding;
|
||||
|
||||
/**
|
||||
* The type of the prompt
|
||||
* @type {GuildOnboardingPromptType}
|
||||
*/
|
||||
this.type = data.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* The guild this onboarding prompt is from
|
||||
* @type {Guild}
|
||||
* @readonly
|
||||
*/
|
||||
get guild() {
|
||||
return this.client.guilds.cache.get(this.guildId);
|
||||
}
|
||||
}
|
||||
|
||||
exports.GuildOnboardingPrompt = GuildOnboardingPrompt;
|
||||
86
node_modules/discord.js/src/structures/GuildOnboardingPromptOption.js
generated
vendored
Normal file
86
node_modules/discord.js/src/structures/GuildOnboardingPromptOption.js
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const Base = require('./Base');
|
||||
const { Emoji } = require('./Emoji.js');
|
||||
|
||||
/**
|
||||
* Represents the data of an option from a prompt of a guilds onboarding.
|
||||
* @extends {Base}
|
||||
*/
|
||||
class GuildOnboardingPromptOption extends Base {
|
||||
constructor(client, data, guildId) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The id of the guild this onboarding prompt option is from
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.guildId = guildId;
|
||||
|
||||
const guild = this.guild;
|
||||
|
||||
/**
|
||||
* The id of the option
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The channels a member is added to when the option is selected
|
||||
* @type {Collection<Snowflake, GuildChannel>}
|
||||
*/
|
||||
this.channels = data.channel_ids.reduce(
|
||||
(channels, channelId) => channels.set(channelId, guild.channels.cache.get(channelId)),
|
||||
new Collection(),
|
||||
);
|
||||
|
||||
/**
|
||||
* The roles assigned to a member when the option is selected
|
||||
* @type {Collection<Snowflake, Role>}
|
||||
*/
|
||||
this.roles = data.role_ids.reduce(
|
||||
(roles, roleId) => roles.set(roleId, guild.roles.cache.get(roleId)),
|
||||
new Collection(),
|
||||
);
|
||||
|
||||
/**
|
||||
* The raw emoji of the option
|
||||
* @type {APIPartialEmoji}
|
||||
* @private
|
||||
*/
|
||||
this._emoji = data.emoji;
|
||||
|
||||
/**
|
||||
* The title of the option
|
||||
* @type {string}
|
||||
*/
|
||||
this.title = data.title;
|
||||
|
||||
/**
|
||||
* The description of the option
|
||||
* @type {?string}
|
||||
*/
|
||||
this.description = data.description;
|
||||
}
|
||||
|
||||
/**
|
||||
* The guild this onboarding prompt option is from
|
||||
* @type {Guild}
|
||||
* @readonly
|
||||
*/
|
||||
get guild() {
|
||||
return this.client.guilds.cache.get(this.guildId);
|
||||
}
|
||||
|
||||
/**
|
||||
* The emoji of this onboarding prompt option
|
||||
* @type {?(GuildEmoji|Emoji)}
|
||||
*/
|
||||
get emoji() {
|
||||
if (!this._emoji.id && !this._emoji.name) return null;
|
||||
return this.client.emojis.cache.get(this._emoji.id) ?? new Emoji(this.client, this._emoji);
|
||||
}
|
||||
}
|
||||
|
||||
exports.GuildOnboardingPromptOption = GuildOnboardingPromptOption;
|
||||
193
node_modules/discord.js/src/structures/GuildPreview.js
generated
vendored
Normal file
193
node_modules/discord.js/src/structures/GuildPreview.js
generated
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const Base = require('./Base');
|
||||
const GuildPreviewEmoji = require('./GuildPreviewEmoji');
|
||||
const { Sticker } = require('./Sticker');
|
||||
|
||||
/**
|
||||
* Represents the data about the guild any bot can preview, connected to the specified guild.
|
||||
* @extends {Base}
|
||||
*/
|
||||
class GuildPreview extends Base {
|
||||
constructor(client, data) {
|
||||
super(client);
|
||||
|
||||
if (!data) return;
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
/**
|
||||
* The id of this guild
|
||||
* @type {string}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
if ('name' in data) {
|
||||
/**
|
||||
* The name of this guild
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
}
|
||||
|
||||
if ('icon' in data) {
|
||||
/**
|
||||
* The icon of this guild
|
||||
* @type {?string}
|
||||
*/
|
||||
this.icon = data.icon;
|
||||
}
|
||||
|
||||
if ('splash' in data) {
|
||||
/**
|
||||
* The splash icon of this guild
|
||||
* @type {?string}
|
||||
*/
|
||||
this.splash = data.splash;
|
||||
}
|
||||
|
||||
if ('discovery_splash' in data) {
|
||||
/**
|
||||
* The discovery splash icon of this guild
|
||||
* @type {?string}
|
||||
*/
|
||||
this.discoverySplash = data.discovery_splash;
|
||||
}
|
||||
|
||||
if ('features' in data) {
|
||||
/**
|
||||
* An array of enabled guild features
|
||||
* @type {GuildFeature[]}
|
||||
*/
|
||||
this.features = data.features;
|
||||
}
|
||||
|
||||
if ('approximate_member_count' in data) {
|
||||
/**
|
||||
* The approximate count of members in this guild
|
||||
* @type {number}
|
||||
*/
|
||||
this.approximateMemberCount = data.approximate_member_count;
|
||||
}
|
||||
|
||||
if ('approximate_presence_count' in data) {
|
||||
/**
|
||||
* The approximate count of online members in this guild
|
||||
* @type {number}
|
||||
*/
|
||||
this.approximatePresenceCount = data.approximate_presence_count;
|
||||
}
|
||||
|
||||
if ('description' in data) {
|
||||
/**
|
||||
* The description for this guild
|
||||
* @type {?string}
|
||||
*/
|
||||
this.description = data.description;
|
||||
} else {
|
||||
this.description ??= null;
|
||||
}
|
||||
|
||||
if (!this.emojis) {
|
||||
/**
|
||||
* Collection of emojis belonging to this guild
|
||||
* @type {Collection<Snowflake, GuildPreviewEmoji>}
|
||||
*/
|
||||
this.emojis = new Collection();
|
||||
} else {
|
||||
this.emojis.clear();
|
||||
}
|
||||
for (const emoji of data.emojis) {
|
||||
this.emojis.set(emoji.id, new GuildPreviewEmoji(this.client, emoji, this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Collection of stickers belonging to this guild
|
||||
* @type {Collection<Snowflake, Sticker>}
|
||||
*/
|
||||
this.stickers = data.stickers.reduce(
|
||||
(stickers, sticker) => stickers.set(sticker.id, new Sticker(this.client, sticker)),
|
||||
new Collection(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp this guild was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time this guild was created at
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL to this guild's splash.
|
||||
* @param {ImageURLOptions} [options={}] Options for the image URL
|
||||
* @returns {?string}
|
||||
*/
|
||||
splashURL(options = {}) {
|
||||
return this.splash && this.client.rest.cdn.splash(this.id, this.splash, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL to this guild's discovery splash.
|
||||
* @param {ImageURLOptions} [options={}] Options for the image URL
|
||||
* @returns {?string}
|
||||
*/
|
||||
discoverySplashURL(options = {}) {
|
||||
return this.discoverySplash && this.client.rest.cdn.discoverySplash(this.id, this.discoverySplash, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL to this guild's icon.
|
||||
* @param {ImageURLOptions} [options={}] Options for the image URL
|
||||
* @returns {?string}
|
||||
*/
|
||||
iconURL(options = {}) {
|
||||
return this.icon && this.client.rest.cdn.icon(this.id, this.icon, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches this guild.
|
||||
* @returns {Promise<GuildPreview>}
|
||||
*/
|
||||
async fetch() {
|
||||
const data = await this.client.rest.get(Routes.guildPreview(this.id));
|
||||
this._patch(data);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically returns the guild's name instead of the Guild object.
|
||||
* @returns {string}
|
||||
* @example
|
||||
* // Logs: Hello from My Guild!
|
||||
* console.log(`Hello from ${previewGuild}!`);
|
||||
*/
|
||||
toString() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
const json = super.toJSON();
|
||||
json.iconURL = this.iconURL();
|
||||
json.splashURL = this.splashURL();
|
||||
return json;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildPreview;
|
||||
27
node_modules/discord.js/src/structures/GuildPreviewEmoji.js
generated
vendored
Normal file
27
node_modules/discord.js/src/structures/GuildPreviewEmoji.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
'use strict';
|
||||
|
||||
const BaseGuildEmoji = require('./BaseGuildEmoji');
|
||||
|
||||
/**
|
||||
* Represents an instance of an emoji belonging to a public guild obtained through Discord's preview endpoint.
|
||||
* @extends {BaseGuildEmoji}
|
||||
*/
|
||||
class GuildPreviewEmoji extends BaseGuildEmoji {
|
||||
/**
|
||||
* The public guild this emoji is part of
|
||||
* @type {GuildPreview}
|
||||
* @name GuildPreviewEmoji#guild
|
||||
*/
|
||||
|
||||
constructor(client, data, guild) {
|
||||
super(client, data, guild);
|
||||
|
||||
/**
|
||||
* The roles this emoji is active for
|
||||
* @type {Snowflake[]}
|
||||
*/
|
||||
this.roles = data.roles;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildPreviewEmoji;
|
||||
534
node_modules/discord.js/src/structures/GuildScheduledEvent.js
generated
vendored
Normal file
534
node_modules/discord.js/src/structures/GuildScheduledEvent.js
generated
vendored
Normal file
@@ -0,0 +1,534 @@
|
||||
'use strict';
|
||||
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const { GuildScheduledEventStatus, GuildScheduledEventEntityType, RouteBases } = require('discord-api-types/v10');
|
||||
const Base = require('./Base');
|
||||
const { DiscordjsError, ErrorCodes } = require('../errors');
|
||||
|
||||
/**
|
||||
* Represents a scheduled event in a {@link Guild}.
|
||||
* @extends {Base}
|
||||
*/
|
||||
class GuildScheduledEvent extends Base {
|
||||
constructor(client, data) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The id of the guild scheduled event
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The id of the guild this guild scheduled event belongs to
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.guildId = data.guild_id;
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
if ('channel_id' in data) {
|
||||
/**
|
||||
* The channel id in which the scheduled event will be hosted,
|
||||
* or `null` if entity type is {@link GuildScheduledEventEntityType.External}
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.channelId = data.channel_id;
|
||||
} else {
|
||||
this.channelId ??= null;
|
||||
}
|
||||
|
||||
if ('creator_id' in data) {
|
||||
/**
|
||||
* The id of the user that created this guild scheduled event
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.creatorId = data.creator_id;
|
||||
} else {
|
||||
this.creatorId ??= null;
|
||||
}
|
||||
|
||||
if ('name' in data) {
|
||||
/**
|
||||
* The name of the guild scheduled event
|
||||
* @type {?string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
} else {
|
||||
// Only if partial.
|
||||
this.name ??= null;
|
||||
}
|
||||
|
||||
if ('description' in data) {
|
||||
/**
|
||||
* The description of the guild scheduled event
|
||||
* @type {?string}
|
||||
*/
|
||||
this.description = data.description;
|
||||
} else {
|
||||
this.description ??= null;
|
||||
}
|
||||
|
||||
if ('scheduled_start_time' in data) {
|
||||
/**
|
||||
* The timestamp the guild scheduled event will start at
|
||||
* @type {?number}
|
||||
*/
|
||||
this.scheduledStartTimestamp = Date.parse(data.scheduled_start_time);
|
||||
} else {
|
||||
this.scheduledStartTimestamp ??= null;
|
||||
}
|
||||
|
||||
if ('scheduled_end_time' in data) {
|
||||
/**
|
||||
* The timestamp the guild scheduled event will end at
|
||||
* or `null` if the event does not have a scheduled time to end
|
||||
* @type {?number}
|
||||
*/
|
||||
this.scheduledEndTimestamp = data.scheduled_end_time ? Date.parse(data.scheduled_end_time) : null;
|
||||
} else {
|
||||
this.scheduledEndTimestamp ??= null;
|
||||
}
|
||||
|
||||
if ('privacy_level' in data) {
|
||||
/**
|
||||
* The privacy level of the guild scheduled event
|
||||
* @type {?GuildScheduledEventPrivacyLevel}
|
||||
*/
|
||||
this.privacyLevel = data.privacy_level;
|
||||
} else {
|
||||
// Only if partial.
|
||||
this.privacyLevel ??= null;
|
||||
}
|
||||
|
||||
if ('status' in data) {
|
||||
/**
|
||||
* The status of the guild scheduled event
|
||||
* @type {?GuildScheduledEventStatus}
|
||||
*/
|
||||
this.status = data.status;
|
||||
} else {
|
||||
// Only if partial.
|
||||
this.status ??= null;
|
||||
}
|
||||
|
||||
if ('entity_type' in data) {
|
||||
/**
|
||||
* The type of hosting entity associated with the scheduled event
|
||||
* @type {?GuildScheduledEventEntityType}
|
||||
*/
|
||||
this.entityType = data.entity_type;
|
||||
} else {
|
||||
// Only if partial.
|
||||
this.entityType ??= null;
|
||||
}
|
||||
|
||||
if ('entity_id' in data) {
|
||||
/**
|
||||
* The id of the hosting entity associated with the scheduled event
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.entityId = data.entity_id;
|
||||
} else {
|
||||
this.entityId ??= null;
|
||||
}
|
||||
|
||||
if ('user_count' in data) {
|
||||
/**
|
||||
* The number of users who are subscribed to this guild scheduled event
|
||||
* @type {?number}
|
||||
*/
|
||||
this.userCount = data.user_count;
|
||||
} else {
|
||||
this.userCount ??= null;
|
||||
}
|
||||
|
||||
if ('creator' in data) {
|
||||
/**
|
||||
* The user that created this guild scheduled event
|
||||
* @type {?User}
|
||||
*/
|
||||
this.creator = this.client.users._add(data.creator);
|
||||
} else {
|
||||
this.creator ??= this.client.users.resolve(this.creatorId);
|
||||
}
|
||||
|
||||
/* eslint-disable max-len */
|
||||
/**
|
||||
* Represents the additional metadata for a {@link GuildScheduledEvent}
|
||||
* @see {@link https://discord.com/developers/docs/resources/guild-scheduled-event#guild-scheduled-event-object-guild-scheduled-event-entity-metadata}
|
||||
* @typedef {Object} GuildScheduledEventEntityMetadata
|
||||
* @property {?string} location The location of the guild scheduled event
|
||||
*/
|
||||
/* eslint-enable max-len */
|
||||
|
||||
if ('entity_metadata' in data) {
|
||||
if (data.entity_metadata) {
|
||||
/**
|
||||
* Additional metadata
|
||||
* @type {?GuildScheduledEventEntityMetadata}
|
||||
*/
|
||||
this.entityMetadata = {
|
||||
location: data.entity_metadata.location ?? this.entityMetadata?.location ?? null,
|
||||
};
|
||||
} else {
|
||||
this.entityMetadata = null;
|
||||
}
|
||||
} else {
|
||||
this.entityMetadata ??= null;
|
||||
}
|
||||
|
||||
if ('image' in data) {
|
||||
/**
|
||||
* The cover image hash for this scheduled event
|
||||
* @type {?string}
|
||||
*/
|
||||
this.image = data.image;
|
||||
} else {
|
||||
this.image ??= null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the recurrence rule for a {@link GuildScheduledEvent}.
|
||||
* @typedef {Object} GuildScheduledEventRecurrenceRule
|
||||
* @property {number} startTimestamp The timestamp the recurrence rule interval starts at
|
||||
* @property {Date} startAt The time the recurrence rule interval starts at
|
||||
* @property {?number} endTimestamp The timestamp the recurrence rule interval ends at
|
||||
* @property {?Date} endAt The time the recurrence rule interval ends at
|
||||
* @property {GuildScheduledEventRecurrenceRuleFrequency} frequency How often the event occurs
|
||||
* @property {number} interval The spacing between the events
|
||||
* @property {?GuildScheduledEventRecurrenceRuleWeekday[]} byWeekday The days within a week to recur on
|
||||
* @property {?GuildScheduledEventRecurrenceRuleNWeekday[]} byNWeekday The days within a week to recur on
|
||||
* @property {?GuildScheduledEventRecurrenceRuleMonth[]} byMonth The months to recur on
|
||||
* @property {?number[]} byMonthDay The days within a month to recur on
|
||||
* @property {?number[]} byYearDay The days within a year to recur on
|
||||
* @property {?number} count The total amount of times the event is allowed to recur before stopping
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} GuildScheduledEventRecurrenceRuleNWeekday
|
||||
* @property {number} n The week to recur on
|
||||
* @property {GuildScheduledEventRecurrenceRuleWeekday} day The day within the week to recur on
|
||||
*/
|
||||
|
||||
if ('recurrence_rule' in data) {
|
||||
/**
|
||||
* The recurrence rule for this scheduled event
|
||||
* @type {?GuildScheduledEventRecurrenceRule}
|
||||
*/
|
||||
this.recurrenceRule = data.recurrence_rule && {
|
||||
startTimestamp: Date.parse(data.recurrence_rule.start),
|
||||
get startAt() {
|
||||
return new Date(this.startTimestamp);
|
||||
},
|
||||
endTimestamp: data.recurrence_rule.end && Date.parse(data.recurrence_rule.end),
|
||||
get endAt() {
|
||||
return this.endTimestamp && new Date(this.endTimestamp);
|
||||
},
|
||||
frequency: data.recurrence_rule.frequency,
|
||||
interval: data.recurrence_rule.interval,
|
||||
byWeekday: data.recurrence_rule.by_weekday,
|
||||
byNWeekday: data.recurrence_rule.by_n_weekday,
|
||||
byMonth: data.recurrence_rule.by_month,
|
||||
byMonthDay: data.recurrence_rule.by_month_day,
|
||||
byYearDay: data.recurrence_rule.by_year_day,
|
||||
count: data.recurrence_rule.count,
|
||||
};
|
||||
} else {
|
||||
this.recurrenceRule ??= null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this guild scheduled event is partial.
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get partial() {
|
||||
return this.name === null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL of this scheduled event's cover image
|
||||
* @param {BaseImageURLOptions} [options={}] Options for image URL
|
||||
* @returns {?string}
|
||||
*/
|
||||
coverImageURL(options = {}) {
|
||||
return this.image && this.client.rest.cdn.guildScheduledEventCover(this.id, this.image, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp the guild scheduled event was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the guild scheduled event was created at
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the guild scheduled event will start at
|
||||
* <info>This can be potentially `null` only when it's an {@link GuildAuditLogsEntry#target}</info>
|
||||
* @type {?Date}
|
||||
* @readonly
|
||||
*/
|
||||
get scheduledStartAt() {
|
||||
return this.scheduledStartTimestamp && new Date(this.scheduledStartTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the guild scheduled event will end at,
|
||||
* or `null` if the event does not have a scheduled time to end
|
||||
* @type {?Date}
|
||||
* @readonly
|
||||
*/
|
||||
get scheduledEndAt() {
|
||||
return this.scheduledEndTimestamp && new Date(this.scheduledEndTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The channel associated with this scheduled event
|
||||
* @type {?(VoiceChannel|StageChannel)}
|
||||
* @readonly
|
||||
*/
|
||||
get channel() {
|
||||
return this.client.channels.resolve(this.channelId);
|
||||
}
|
||||
|
||||
/**
|
||||
* The guild this scheduled event belongs to
|
||||
* @type {?Guild}
|
||||
* @readonly
|
||||
*/
|
||||
get guild() {
|
||||
return this.client.guilds.resolve(this.guildId);
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL to the guild scheduled event
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get url() {
|
||||
return `${RouteBases.scheduledEvent}/${this.guildId}/${this.id}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to create an invite URL to a {@link GuildScheduledEvent}
|
||||
* @typedef {InviteCreateOptions} GuildScheduledEventInviteURLCreateOptions
|
||||
* @property {GuildInvitableChannelResolvable} [channel] The channel to create the invite in.
|
||||
* <warn>This is required when the `entityType` of `GuildScheduledEvent` is
|
||||
* {@link GuildScheduledEventEntityType.External}, gets ignored otherwise</warn>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates an invite URL to this guild scheduled event.
|
||||
* @param {GuildScheduledEventInviteURLCreateOptions} [options] The options to create the invite
|
||||
* @returns {Promise<string>}
|
||||
*/
|
||||
async createInviteURL(options) {
|
||||
let channelId = this.channelId;
|
||||
if (this.entityType === GuildScheduledEventEntityType.External) {
|
||||
if (!options?.channel) throw new DiscordjsError(ErrorCodes.InviteOptionsMissingChannel);
|
||||
channelId = this.guild.channels.resolveId(options.channel);
|
||||
if (!channelId) throw new DiscordjsError(ErrorCodes.GuildChannelResolve);
|
||||
}
|
||||
const invite = await this.guild.invites.create(channelId, options);
|
||||
return `${RouteBases.invite}/${invite.code}?event=${this.id}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits this guild scheduled event.
|
||||
* @param {GuildScheduledEventEditOptions} options The options to edit the guild scheduled event
|
||||
* @returns {Promise<GuildScheduledEvent>}
|
||||
* @example
|
||||
* // Edit a guild scheduled event
|
||||
* guildScheduledEvent.edit({ name: 'Party' })
|
||||
* .then(guildScheduledEvent => console.log(guildScheduledEvent))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
edit(options) {
|
||||
return this.guild.scheduledEvents.edit(this.id, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches this guild scheduled event.
|
||||
* @param {boolean} [force=true] Whether to skip the cache check and request the API
|
||||
* @returns {Promise<GuildScheduledEvent>}
|
||||
*/
|
||||
fetch(force = true) {
|
||||
return this.guild.scheduledEvents.fetch({ guildScheduledEvent: this.id, force });
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this guild scheduled event.
|
||||
* @returns {Promise<GuildScheduledEvent>}
|
||||
* @example
|
||||
* // Delete a guild scheduled event
|
||||
* guildScheduledEvent.delete()
|
||||
* .then(guildScheduledEvent => console.log(guildScheduledEvent))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async delete() {
|
||||
await this.guild.scheduledEvents.delete(this.id);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new name for the guild scheduled event.
|
||||
* @param {string} name The new name of the guild scheduled event
|
||||
* @param {string} [reason] The reason for changing the name
|
||||
* @returns {Promise<GuildScheduledEvent>}
|
||||
* @example
|
||||
* // Set name of a guild scheduled event
|
||||
* guildScheduledEvent.setName('Birthday Party')
|
||||
* .then(guildScheduledEvent => console.log(`Set the name to: ${guildScheduledEvent.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setName(name, reason) {
|
||||
return this.edit({ name, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new time to schedule the event at.
|
||||
* @param {DateResolvable} scheduledStartTime The time to schedule the event at
|
||||
* @param {string} [reason] The reason for changing the scheduled start time
|
||||
* @returns {Promise<GuildScheduledEvent>}
|
||||
* @example
|
||||
* // Set start time of a guild scheduled event
|
||||
* guildScheduledEvent.setScheduledStartTime('2022-09-24T00:00:00+05:30')
|
||||
* .then(guildScheduledEvent => console.log(`Set the start time to: ${guildScheduledEvent.scheduledStartTime}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setScheduledStartTime(scheduledStartTime, reason) {
|
||||
return this.edit({ scheduledStartTime, reason });
|
||||
}
|
||||
|
||||
// TODO: scheduledEndTime gets reset on passing null but it hasn't been documented
|
||||
/**
|
||||
* Sets a new time to end the event at.
|
||||
* @param {DateResolvable} scheduledEndTime The time to end the event at
|
||||
* @param {string} [reason] The reason for changing the scheduled end time
|
||||
* @returns {Promise<GuildScheduledEvent>}
|
||||
* @example
|
||||
* // Set end time of a guild scheduled event
|
||||
* guildScheduledEvent.setScheduledEndTime('2022-09-25T00:00:00+05:30')
|
||||
* .then(guildScheduledEvent => console.log(`Set the end time to: ${guildScheduledEvent.scheduledEndTime}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setScheduledEndTime(scheduledEndTime, reason) {
|
||||
return this.edit({ scheduledEndTime, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new description of the guild scheduled event.
|
||||
* @param {string} description The description of the guild scheduled event
|
||||
* @param {string} [reason] The reason for changing the description
|
||||
* @returns {Promise<GuildScheduledEvent>}
|
||||
* @example
|
||||
* // Set description of a guild scheduled event
|
||||
* guildScheduledEvent.setDescription('A virtual birthday party')
|
||||
* .then(guildScheduledEvent => console.log(`Set the description to: ${guildScheduledEvent.description}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setDescription(description, reason) {
|
||||
return this.edit({ description, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new status of the guild scheduled event.
|
||||
* <info>If you're working with TypeScript, use this method in conjunction with status type-guards
|
||||
* like {@link GuildScheduledEvent#isScheduled} to get only valid status as suggestion</info>
|
||||
* @param {GuildScheduledEventStatus} status The status of the guild scheduled event
|
||||
* @param {string} [reason] The reason for changing the status
|
||||
* @returns {Promise<GuildScheduledEvent>}
|
||||
* @example
|
||||
* // Set status of a guild scheduled event
|
||||
* guildScheduledEvent.setStatus(GuildScheduledEventStatus.Active)
|
||||
* .then(guildScheduledEvent => console.log(`Set the status to: ${guildScheduledEvent.status}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setStatus(status, reason) {
|
||||
return this.edit({ status, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new location of the guild scheduled event.
|
||||
* @param {string} location The location of the guild scheduled event
|
||||
* @param {string} [reason] The reason for changing the location
|
||||
* @returns {Promise<GuildScheduledEvent>}
|
||||
* @example
|
||||
* // Set location of a guild scheduled event
|
||||
* guildScheduledEvent.setLocation('Earth')
|
||||
* .then(guildScheduledEvent => console.log(`Set the location to: ${guildScheduledEvent.entityMetadata.location}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setLocation(location, reason) {
|
||||
return this.edit({ entityMetadata: { location }, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches subscribers of this guild scheduled event.
|
||||
* @param {FetchGuildScheduledEventSubscribersOptions} [options] Options for fetching the subscribers
|
||||
* @returns {Promise<Collection<Snowflake, GuildScheduledEventUser>>}
|
||||
*/
|
||||
fetchSubscribers(options) {
|
||||
return this.guild.scheduledEvents.fetchSubscribers(this.id, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically concatenates the event's URL instead of the object.
|
||||
* @returns {string}
|
||||
* @example
|
||||
* // Logs: Event: https://discord.com/events/412345678901234567/499876543211234567
|
||||
* console.log(`Event: ${guildScheduledEvent}`);
|
||||
*/
|
||||
toString() {
|
||||
return this.url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this guild scheduled event has an {@link GuildScheduledEventStatus.Active} status.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isActive() {
|
||||
return this.status === GuildScheduledEventStatus.Active;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this guild scheduled event has a {@link GuildScheduledEventStatus.Canceled} status.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isCanceled() {
|
||||
return this.status === GuildScheduledEventStatus.Canceled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this guild scheduled event has a {@link GuildScheduledEventStatus.Completed} status.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isCompleted() {
|
||||
return this.status === GuildScheduledEventStatus.Completed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this guild scheduled event has a {@link GuildScheduledEventStatus.Scheduled} status.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isScheduled() {
|
||||
return this.status === GuildScheduledEventStatus.Scheduled;
|
||||
}
|
||||
}
|
||||
|
||||
exports.GuildScheduledEvent = GuildScheduledEvent;
|
||||
242
node_modules/discord.js/src/structures/GuildTemplate.js
generated
vendored
Normal file
242
node_modules/discord.js/src/structures/GuildTemplate.js
generated
vendored
Normal file
@@ -0,0 +1,242 @@
|
||||
'use strict';
|
||||
|
||||
const { setTimeout, clearTimeout } = require('node:timers');
|
||||
const { RouteBases, Routes } = require('discord-api-types/v10');
|
||||
const Base = require('./Base');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
const Events = require('../util/Events');
|
||||
|
||||
/**
|
||||
* Represents the template for a guild.
|
||||
* @extends {Base}
|
||||
*/
|
||||
class GuildTemplate extends Base {
|
||||
/**
|
||||
* A regular expression that matches guild template links.
|
||||
* The `code` group property is present on the `exec()` result of this expression.
|
||||
* @type {RegExp}
|
||||
* @memberof GuildTemplate
|
||||
*/
|
||||
static GuildTemplatesPattern = /discord(?:app)?\.(?:com\/template|new)\/(?<code>[\w-]{2,255})/i;
|
||||
|
||||
constructor(client, data) {
|
||||
super(client);
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
if ('code' in data) {
|
||||
/**
|
||||
* The unique code of this template
|
||||
* @type {string}
|
||||
*/
|
||||
this.code = data.code;
|
||||
}
|
||||
|
||||
if ('name' in data) {
|
||||
/**
|
||||
* The name of this template
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
}
|
||||
|
||||
if ('description' in data) {
|
||||
/**
|
||||
* The description of this template
|
||||
* @type {?string}
|
||||
*/
|
||||
this.description = data.description;
|
||||
}
|
||||
|
||||
if ('usage_count' in data) {
|
||||
/**
|
||||
* The amount of times this template has been used
|
||||
* @type {number}
|
||||
*/
|
||||
this.usageCount = data.usage_count;
|
||||
}
|
||||
|
||||
if ('creator_id' in data) {
|
||||
/**
|
||||
* The id of the user that created this template
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.creatorId = data.creator_id;
|
||||
}
|
||||
|
||||
if ('creator' in data) {
|
||||
/**
|
||||
* The user that created this template
|
||||
* @type {User}
|
||||
*/
|
||||
this.creator = this.client.users._add(data.creator);
|
||||
}
|
||||
|
||||
if ('created_at' in data) {
|
||||
/**
|
||||
* The timestamp of when this template was created at
|
||||
* @type {number}
|
||||
*/
|
||||
this.createdTimestamp = Date.parse(data.created_at);
|
||||
}
|
||||
|
||||
if ('updated_at' in data) {
|
||||
/**
|
||||
* The timestamp of when this template was last synced to the guild
|
||||
* @type {number}
|
||||
*/
|
||||
this.updatedTimestamp = Date.parse(data.updated_at);
|
||||
}
|
||||
|
||||
if ('source_guild_id' in data) {
|
||||
/**
|
||||
* The id of the guild that this template belongs to
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.guildId = data.source_guild_id;
|
||||
}
|
||||
|
||||
if ('serialized_source_guild' in data) {
|
||||
/**
|
||||
* The data of the guild that this template would create
|
||||
* @type {APIGuild}
|
||||
*/
|
||||
this.serializedGuild = data.serialized_source_guild;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this template has unsynced changes
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.unSynced = 'is_dirty' in data ? Boolean(data.is_dirty) : null;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a guild based on this template.
|
||||
* <warn>This is only available to bots in fewer than 10 guilds.</warn>
|
||||
* @param {string} name The name of the guild
|
||||
* @param {BufferResolvable|Base64Resolvable} [icon] The icon for the guild
|
||||
* @returns {Promise<Guild>}
|
||||
* @deprecated API related to guild ownership may no longer be used.
|
||||
*/
|
||||
async createGuild(name, icon) {
|
||||
const { client } = this;
|
||||
const data = await client.rest.post(Routes.template(this.code), {
|
||||
body: {
|
||||
name,
|
||||
icon: await resolveImage(icon),
|
||||
},
|
||||
});
|
||||
|
||||
if (client.guilds.cache.has(data.id)) return client.guilds.cache.get(data.id);
|
||||
|
||||
return new Promise(resolve => {
|
||||
const resolveGuild = guild => {
|
||||
client.off(Events.GuildCreate, handleGuild);
|
||||
client.decrementMaxListeners();
|
||||
resolve(guild);
|
||||
};
|
||||
|
||||
const handleGuild = guild => {
|
||||
if (guild.id === data.id) {
|
||||
clearTimeout(timeout);
|
||||
resolveGuild(guild);
|
||||
}
|
||||
};
|
||||
|
||||
client.incrementMaxListeners();
|
||||
client.on(Events.GuildCreate, handleGuild);
|
||||
|
||||
const timeout = setTimeout(() => resolveGuild(client.guilds._add(data)), 10_000).unref();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to edit a guild template.
|
||||
* @typedef {Object} GuildTemplateEditOptions
|
||||
* @property {string} [name] The name of this template
|
||||
* @property {string} [description] The description of this template
|
||||
*/
|
||||
|
||||
/**
|
||||
* Updates the metadata of this template.
|
||||
* @param {GuildTemplateEditOptions} [options] Options for editing the template
|
||||
* @returns {Promise<GuildTemplate>}
|
||||
*/
|
||||
async edit({ name, description } = {}) {
|
||||
const data = await this.client.rest.patch(Routes.guildTemplate(this.guildId, this.code), {
|
||||
body: { name, description },
|
||||
});
|
||||
return this._patch(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this template.
|
||||
* @returns {Promise<GuildTemplate>}
|
||||
*/
|
||||
async delete() {
|
||||
await this.client.rest.delete(Routes.guildTemplate(this.guildId, this.code));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs this template to the current state of the guild.
|
||||
* @returns {Promise<GuildTemplate>}
|
||||
*/
|
||||
async sync() {
|
||||
const data = await this.client.rest.put(Routes.guildTemplate(this.guildId, this.code));
|
||||
return this._patch(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time when this template was created at
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time when this template was last synced to the guild
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get updatedAt() {
|
||||
return new Date(this.updatedTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The guild that this template belongs to
|
||||
* @type {?Guild}
|
||||
* @readonly
|
||||
*/
|
||||
get guild() {
|
||||
return this.client.guilds.resolve(this.guildId);
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL of this template
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get url() {
|
||||
return `${RouteBases.template}/${this.code}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically returns the template's code instead of the template object.
|
||||
* @returns {string}
|
||||
* @example
|
||||
* // Logs: Template: FKvmczH2HyUf
|
||||
* console.log(`Template: ${guildTemplate}!`);
|
||||
*/
|
||||
toString() {
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildTemplate;
|
||||
220
node_modules/discord.js/src/structures/Integration.js
generated
vendored
Normal file
220
node_modules/discord.js/src/structures/Integration.js
generated
vendored
Normal file
@@ -0,0 +1,220 @@
|
||||
'use strict';
|
||||
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const Base = require('./Base');
|
||||
const IntegrationApplication = require('./IntegrationApplication');
|
||||
|
||||
/**
|
||||
* The information account for an integration
|
||||
* @typedef {Object} IntegrationAccount
|
||||
* @property {Snowflake|string} id The id of the account
|
||||
* @property {string} name The name of the account
|
||||
*/
|
||||
|
||||
/**
|
||||
* The type of an {@link Integration}. This can be:
|
||||
* * `twitch`
|
||||
* * `youtube`
|
||||
* * `discord`
|
||||
* * `guild_subscription`
|
||||
* @typedef {string} IntegrationType
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a guild integration.
|
||||
* @extends {Base}
|
||||
*/
|
||||
class Integration extends Base {
|
||||
constructor(client, data, guild) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The guild this integration belongs to
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
|
||||
/**
|
||||
* The integration id
|
||||
* @type {Snowflake|string}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The integration name
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* The integration type
|
||||
* @type {IntegrationType}
|
||||
*/
|
||||
this.type = data.type;
|
||||
|
||||
/**
|
||||
* Whether this integration is enabled
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.enabled = data.enabled ?? null;
|
||||
|
||||
if ('syncing' in data) {
|
||||
/**
|
||||
* Whether this integration is syncing
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.syncing = data.syncing;
|
||||
} else {
|
||||
this.syncing ??= null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The role that this integration uses for subscribers
|
||||
* @type {?Role}
|
||||
*/
|
||||
this.role = this.guild.roles.resolve(data.role_id);
|
||||
|
||||
if ('enable_emoticons' in data) {
|
||||
/**
|
||||
* Whether emoticons should be synced for this integration (twitch only currently)
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.enableEmoticons = data.enable_emoticons;
|
||||
} else {
|
||||
this.enableEmoticons ??= null;
|
||||
}
|
||||
|
||||
if (data.user) {
|
||||
/**
|
||||
* The user for this integration
|
||||
* @type {?User}
|
||||
*/
|
||||
this.user = this.client.users._add(data.user);
|
||||
} else {
|
||||
this.user ??= null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The account integration information
|
||||
* @type {IntegrationAccount}
|
||||
*/
|
||||
this.account = data.account;
|
||||
|
||||
if ('synced_at' in data) {
|
||||
/**
|
||||
* The timestamp at which this integration was last synced at
|
||||
* @type {?number}
|
||||
*/
|
||||
this.syncedTimestamp = Date.parse(data.synced_at);
|
||||
} else {
|
||||
this.syncedTimestamp ??= null;
|
||||
}
|
||||
|
||||
if ('subscriber_count' in data) {
|
||||
/**
|
||||
* How many subscribers this integration has
|
||||
* @type {?number}
|
||||
*/
|
||||
this.subscriberCount = data.subscriber_count;
|
||||
} else {
|
||||
this.subscriberCount ??= null;
|
||||
}
|
||||
|
||||
if ('revoked' in data) {
|
||||
/**
|
||||
* Whether this integration has been revoked
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.revoked = data.revoked;
|
||||
} else {
|
||||
this.revoked ??= null;
|
||||
}
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* The date at which this integration was last synced at
|
||||
* @type {?Date}
|
||||
* @readonly
|
||||
*/
|
||||
get syncedAt() {
|
||||
return this.syncedTimestamp && new Date(this.syncedTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* All roles that are managed by this integration
|
||||
* @type {Collection<Snowflake, Role>}
|
||||
* @readonly
|
||||
*/
|
||||
get roles() {
|
||||
const roles = this.guild.roles.cache;
|
||||
return roles.filter(role => role.tags?.integrationId === this.id);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
if ('expire_behavior' in data) {
|
||||
/**
|
||||
* The behavior of expiring subscribers
|
||||
* @type {?IntegrationExpireBehavior}
|
||||
*/
|
||||
this.expireBehavior = data.expire_behavior;
|
||||
} else {
|
||||
this.expireBehavior ??= null;
|
||||
}
|
||||
|
||||
if ('expire_grace_period' in data) {
|
||||
/**
|
||||
* The grace period (in days) before expiring subscribers
|
||||
* @type {?number}
|
||||
*/
|
||||
this.expireGracePeriod = data.expire_grace_period;
|
||||
} else {
|
||||
this.expireGracePeriod ??= null;
|
||||
}
|
||||
|
||||
if ('application' in data) {
|
||||
if (this.application) {
|
||||
this.application._patch(data.application);
|
||||
} else {
|
||||
/**
|
||||
* The application for this integration
|
||||
* @type {?IntegrationApplication}
|
||||
*/
|
||||
this.application = new IntegrationApplication(this.client, data.application);
|
||||
}
|
||||
} else {
|
||||
this.application ??= null;
|
||||
}
|
||||
|
||||
if ('scopes' in data) {
|
||||
/**
|
||||
* The scopes this application has been authorized for
|
||||
* @type {OAuth2Scopes[]}
|
||||
*/
|
||||
this.scopes = data.scopes;
|
||||
} else {
|
||||
this.scopes ??= [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this integration.
|
||||
* @returns {Promise<Integration>}
|
||||
* @param {string} [reason] Reason for deleting this integration
|
||||
*/
|
||||
async delete(reason) {
|
||||
await this.client.rest.delete(Routes.guildIntegration(this.guild.id, this.id), { reason });
|
||||
return this;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return super.toJSON({
|
||||
role: 'roleId',
|
||||
guild: 'guildId',
|
||||
user: 'userId',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Integration;
|
||||
85
node_modules/discord.js/src/structures/IntegrationApplication.js
generated
vendored
Normal file
85
node_modules/discord.js/src/structures/IntegrationApplication.js
generated
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
'use strict';
|
||||
|
||||
const Application = require('./interfaces/Application');
|
||||
|
||||
/**
|
||||
* Represents an Integration's OAuth2 Application.
|
||||
* @extends {Application}
|
||||
*/
|
||||
class IntegrationApplication extends Application {
|
||||
_patch(data) {
|
||||
super._patch(data);
|
||||
|
||||
if ('bot' in data) {
|
||||
/**
|
||||
* The bot user for this application
|
||||
* @type {?User}
|
||||
*/
|
||||
this.bot = this.client.users._add(data.bot);
|
||||
} else {
|
||||
this.bot ??= null;
|
||||
}
|
||||
|
||||
if ('terms_of_service_url' in data) {
|
||||
/**
|
||||
* The URL of the application's terms of service
|
||||
* @type {?string}
|
||||
*/
|
||||
this.termsOfServiceURL = data.terms_of_service_url;
|
||||
} else {
|
||||
this.termsOfServiceURL ??= null;
|
||||
}
|
||||
|
||||
if ('privacy_policy_url' in data) {
|
||||
/**
|
||||
* The URL of the application's privacy policy
|
||||
* @type {?string}
|
||||
*/
|
||||
this.privacyPolicyURL = data.privacy_policy_url;
|
||||
} else {
|
||||
this.privacyPolicyURL ??= null;
|
||||
}
|
||||
|
||||
if ('rpc_origins' in data) {
|
||||
/**
|
||||
* The Array of RPC origin URLs
|
||||
* @type {string[]}
|
||||
*/
|
||||
this.rpcOrigins = data.rpc_origins;
|
||||
} else {
|
||||
this.rpcOrigins ??= [];
|
||||
}
|
||||
|
||||
if ('hook' in data) {
|
||||
/**
|
||||
* Whether the application can be default hooked by the client
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.hook = data.hook;
|
||||
} else {
|
||||
this.hook ??= null;
|
||||
}
|
||||
|
||||
if ('cover_image' in data) {
|
||||
/**
|
||||
* The hash of the application's cover image
|
||||
* @type {?string}
|
||||
*/
|
||||
this.cover = data.cover_image;
|
||||
} else {
|
||||
this.cover ??= null;
|
||||
}
|
||||
|
||||
if ('verify_key' in data) {
|
||||
/**
|
||||
* The hex-encoded key for verification in interactions and the GameSDK's GetTicket
|
||||
* @type {?string}
|
||||
*/
|
||||
this.verifyKey = data.verify_key;
|
||||
} else {
|
||||
this.verifyKey ??= null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = IntegrationApplication;
|
||||
74
node_modules/discord.js/src/structures/InteractionCallback.js
generated
vendored
Normal file
74
node_modules/discord.js/src/structures/InteractionCallback.js
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
'use strict';
|
||||
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
|
||||
/**
|
||||
* Represents an interaction callback response from Discord
|
||||
*/
|
||||
class InteractionCallback {
|
||||
constructor(client, data) {
|
||||
/**
|
||||
* The client that instantiated this.
|
||||
* @name InteractionCallback#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
|
||||
/**
|
||||
* The id of the original interaction response
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The type of the original interaction
|
||||
* @type {InteractionType}
|
||||
*/
|
||||
this.type = data.type;
|
||||
|
||||
/**
|
||||
* The instance id of the Activity if one was launched or joined
|
||||
* @type {?string}
|
||||
*/
|
||||
this.activityInstanceId = data.activity_instance_id ?? null;
|
||||
|
||||
/**
|
||||
* The id of the message that was created by the interaction
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.responseMessageId = data.response_message_id ?? null;
|
||||
|
||||
/**
|
||||
* Whether the message is in a loading state
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.responseMessageLoading = data.response_message_loading ?? null;
|
||||
|
||||
/**
|
||||
* Whether the response message was ephemeral
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.responseMessageEphemeral = data.response_message_ephemeral ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp the original interaction was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the original interaction was created at
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = InteractionCallback;
|
||||
52
node_modules/discord.js/src/structures/InteractionCallbackResource.js
generated
vendored
Normal file
52
node_modules/discord.js/src/structures/InteractionCallbackResource.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
'use strict';
|
||||
|
||||
const { lazy } = require('@discordjs/util');
|
||||
|
||||
const getMessage = lazy(() => require('./Message').Message);
|
||||
|
||||
/**
|
||||
* Represents the resource that was created by the interaction response.
|
||||
*/
|
||||
class InteractionCallbackResource {
|
||||
constructor(client, data) {
|
||||
/**
|
||||
* The client that instantiated this
|
||||
* @name InteractionCallbackResource#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
|
||||
/**
|
||||
* The interaction callback type
|
||||
* @type {InteractionResponseType}
|
||||
*/
|
||||
this.type = data.type;
|
||||
|
||||
/**
|
||||
* The Activity launched by an interaction
|
||||
* @typedef {Object} ActivityInstance
|
||||
* @property {string} id The instance id of the Activity
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents the Activity launched by this interaction
|
||||
* @type {?ActivityInstance}
|
||||
*/
|
||||
this.activityInstance = data.activity_instance ?? null;
|
||||
|
||||
if ('message' in data) {
|
||||
/**
|
||||
* The message created by the interaction
|
||||
* @type {?Message}
|
||||
*/
|
||||
this.message =
|
||||
this.client.channels.cache.get(data.message.channel_id)?.messages._add(data.message) ??
|
||||
new (getMessage())(client, data.message);
|
||||
} else {
|
||||
this.message = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = InteractionCallbackResource;
|
||||
33
node_modules/discord.js/src/structures/InteractionCallbackResponse.js
generated
vendored
Normal file
33
node_modules/discord.js/src/structures/InteractionCallbackResponse.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
'use strict';
|
||||
|
||||
const InteractionCallback = require('./InteractionCallback');
|
||||
const InteractionCallbackResource = require('./InteractionCallbackResource');
|
||||
|
||||
/**
|
||||
* Represents an interaction's response
|
||||
*/
|
||||
class InteractionCallbackResponse {
|
||||
constructor(client, data) {
|
||||
/**
|
||||
* The client that instantiated this
|
||||
* @name InteractionCallbackResponse#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
|
||||
/**
|
||||
* The interaction object associated with the interaction callback response
|
||||
* @type {InteractionCallback}
|
||||
*/
|
||||
this.interaction = new InteractionCallback(client, data.interaction);
|
||||
|
||||
/**
|
||||
* The resource that was created by the interaction response
|
||||
* @type {?InteractionCallbackResource}
|
||||
*/
|
||||
this.resource = data.resource ? new InteractionCallbackResource(client, data.resource) : null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = InteractionCallbackResponse;
|
||||
269
node_modules/discord.js/src/structures/InteractionCollector.js
generated
vendored
Normal file
269
node_modules/discord.js/src/structures/InteractionCollector.js
generated
vendored
Normal file
@@ -0,0 +1,269 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const Collector = require('./interfaces/Collector');
|
||||
const Events = require('../util/Events');
|
||||
|
||||
/**
|
||||
* @typedef {CollectorOptions} InteractionCollectorOptions
|
||||
* @property {TextBasedChannelsResolvable} [channel] The channel to listen to interactions from
|
||||
* @property {ComponentType} [componentType] The type of component to listen for
|
||||
* @property {GuildResolvable} [guild] The guild to listen to interactions from
|
||||
* @property {InteractionType} [interactionType] The type of interaction to listen for
|
||||
* @property {number} [max] The maximum total amount of interactions to collect
|
||||
* @property {number} [maxComponents] The maximum number of components to collect
|
||||
* @property {number} [maxUsers] The maximum number of users to interact
|
||||
* @property {Message|APIMessage} [message] The message to listen to interactions from
|
||||
* @property {InteractionResponse} [interactionResponse] The interaction response to listen
|
||||
* to message component interactions from
|
||||
*/
|
||||
|
||||
/**
|
||||
* Collects interactions.
|
||||
* Will automatically stop if the message ({@link Client#event:messageDelete messageDelete} or
|
||||
* {@link Client#event:messageDeleteBulk messageDeleteBulk}),
|
||||
* channel ({@link Client#event:channelDelete channelDelete}), or
|
||||
* guild ({@link Client#event:guildDelete guildDelete}) is deleted.
|
||||
* <info>Interaction collectors that do not specify `time` or `idle` may be prone to always running.
|
||||
* Ensure your interaction collectors end via either of these options or manual cancellation.</info>
|
||||
* @extends {Collector}
|
||||
*/
|
||||
class InteractionCollector extends Collector {
|
||||
/**
|
||||
* @param {Client} client The client on which to collect interactions
|
||||
* @param {InteractionCollectorOptions} [options={}] The options to apply to this collector
|
||||
*/
|
||||
constructor(client, options = {}) {
|
||||
super(client, options);
|
||||
|
||||
/**
|
||||
* The message from which to collect interactions, if provided
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.messageId = options.message?.id ?? options.interactionResponse?.interaction.message?.id ?? null;
|
||||
|
||||
/**
|
||||
* The message interaction id from which to collect interactions, if provided
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.messageInteractionId = options.interactionResponse?.id ?? null;
|
||||
|
||||
/**
|
||||
* The channel from which to collect interactions, if provided
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.channelId =
|
||||
options.interactionResponse?.interaction.channelId ??
|
||||
options.message?.channelId ??
|
||||
options.message?.channel_id ??
|
||||
this.client.channels.resolveId(options.channel);
|
||||
|
||||
/**
|
||||
* The guild from which to collect interactions, if provided
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.guildId =
|
||||
options.interactionResponse?.interaction.guildId ??
|
||||
options.message?.guildId ??
|
||||
options.message?.guild_id ??
|
||||
this.client.guilds.resolveId(options.channel?.guild) ??
|
||||
this.client.guilds.resolveId(options.guild);
|
||||
|
||||
/**
|
||||
* The type of interaction to collect
|
||||
* @type {?InteractionType}
|
||||
*/
|
||||
this.interactionType = options.interactionType ?? null;
|
||||
|
||||
/**
|
||||
* The type of component to collect
|
||||
* @type {?ComponentType}
|
||||
*/
|
||||
this.componentType = options.componentType ?? null;
|
||||
|
||||
/**
|
||||
* The users that have interacted with this collector
|
||||
* @type {Collection<Snowflake, User>}
|
||||
*/
|
||||
this.users = new Collection();
|
||||
|
||||
/**
|
||||
* The total number of interactions collected
|
||||
* @type {number}
|
||||
*/
|
||||
this.total = 0;
|
||||
|
||||
this.client.incrementMaxListeners();
|
||||
|
||||
const bulkDeleteListener = messages => {
|
||||
if (messages.has(this.messageId)) this.stop('messageDelete');
|
||||
};
|
||||
|
||||
if (this.messageId || this.messageInteractionId) {
|
||||
this._handleMessageDeletion = this._handleMessageDeletion.bind(this);
|
||||
this.client.on(Events.MessageDelete, this._handleMessageDeletion);
|
||||
this.client.on(Events.MessageBulkDelete, bulkDeleteListener);
|
||||
}
|
||||
|
||||
if (this.channelId) {
|
||||
this._handleChannelDeletion = this._handleChannelDeletion.bind(this);
|
||||
this._handleThreadDeletion = this._handleThreadDeletion.bind(this);
|
||||
this.client.on(Events.ChannelDelete, this._handleChannelDeletion);
|
||||
this.client.on(Events.ThreadDelete, this._handleThreadDeletion);
|
||||
}
|
||||
|
||||
if (this.guildId) {
|
||||
this._handleGuildDeletion = this._handleGuildDeletion.bind(this);
|
||||
this.client.on(Events.GuildDelete, this._handleGuildDeletion);
|
||||
}
|
||||
|
||||
this.client.on(Events.InteractionCreate, this.handleCollect);
|
||||
|
||||
this.once('end', () => {
|
||||
this.client.removeListener(Events.InteractionCreate, this.handleCollect);
|
||||
this.client.removeListener(Events.MessageDelete, this._handleMessageDeletion);
|
||||
this.client.removeListener(Events.MessageBulkDelete, bulkDeleteListener);
|
||||
this.client.removeListener(Events.ChannelDelete, this._handleChannelDeletion);
|
||||
this.client.removeListener(Events.ThreadDelete, this._handleThreadDeletion);
|
||||
this.client.removeListener(Events.GuildDelete, this._handleGuildDeletion);
|
||||
this.client.decrementMaxListeners();
|
||||
});
|
||||
|
||||
this.on('collect', interaction => {
|
||||
this.total++;
|
||||
this.users.set(interaction.user.id, interaction.user);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an incoming interaction for possible collection.
|
||||
* @param {BaseInteraction} interaction The interaction to possibly collect
|
||||
* @returns {?Snowflake}
|
||||
* @private
|
||||
*/
|
||||
collect(interaction) {
|
||||
/**
|
||||
* Emitted whenever an interaction is collected.
|
||||
* @event InteractionCollector#collect
|
||||
* @param {BaseInteraction} interaction The interaction that was collected
|
||||
*/
|
||||
|
||||
if (this.interactionType && interaction.type !== this.interactionType) return null;
|
||||
if (this.componentType && interaction.componentType !== this.componentType) return null;
|
||||
if (this.messageId && interaction.message?.id !== this.messageId) return null;
|
||||
if (
|
||||
this.messageInteractionId &&
|
||||
interaction.message?.interactionMetadata?.id &&
|
||||
interaction.message.interactionMetadata.id !== this.messageInteractionId
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
if (this.channelId && interaction.channelId !== this.channelId) return null;
|
||||
if (this.guildId && interaction.guildId !== this.guildId) return null;
|
||||
|
||||
return interaction.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an interaction for possible disposal.
|
||||
* @param {BaseInteraction} interaction The interaction that could be disposed of
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
dispose(interaction) {
|
||||
/**
|
||||
* Emitted whenever an interaction is disposed of.
|
||||
* @event InteractionCollector#dispose
|
||||
* @param {BaseInteraction} interaction The interaction that was disposed of
|
||||
*/
|
||||
if (this.type && interaction.type !== this.type) return null;
|
||||
if (this.componentType && interaction.componentType !== this.componentType) return null;
|
||||
if (this.messageId && interaction.message?.id !== this.messageId) return null;
|
||||
if (
|
||||
this.messageInteractionId &&
|
||||
interaction.message?.interactionMetadata?.id &&
|
||||
interaction.message.interactionMetadata.id !== this.messageInteractionId
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
if (this.channelId && interaction.channelId !== this.channelId) return null;
|
||||
if (this.guildId && interaction.guildId !== this.guildId) return null;
|
||||
|
||||
return interaction.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties this interaction collector.
|
||||
*/
|
||||
empty() {
|
||||
this.total = 0;
|
||||
this.collected.clear();
|
||||
this.users.clear();
|
||||
this.checkEnd();
|
||||
}
|
||||
|
||||
/**
|
||||
* The reason this collector has ended with, or null if it hasn't ended yet
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get endReason() {
|
||||
if (this.options.max && this.total >= this.options.max) return 'limit';
|
||||
if (this.options.maxComponents && this.collected.size >= this.options.maxComponents) return 'componentLimit';
|
||||
if (this.options.maxUsers && this.users.size >= this.options.maxUsers) return 'userLimit';
|
||||
return super.endReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles checking if the message has been deleted, and if so, stops the collector with the reason 'messageDelete'.
|
||||
* @private
|
||||
* @param {Message} message The message that was deleted
|
||||
* @returns {void}
|
||||
*/
|
||||
_handleMessageDeletion(message) {
|
||||
if (message.id === this.messageId) {
|
||||
this.stop('messageDelete');
|
||||
}
|
||||
|
||||
if (message.interactionMetadata?.id === this.messageInteractionId) {
|
||||
this.stop('messageDelete');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles checking if the channel has been deleted, and if so, stops the collector with the reason 'channelDelete'.
|
||||
* @private
|
||||
* @param {GuildChannel} channel The channel that was deleted
|
||||
* @returns {void}
|
||||
*/
|
||||
_handleChannelDeletion(channel) {
|
||||
if (channel.id === this.channelId || channel.threads?.cache.has(this.channelId)) {
|
||||
this.stop('channelDelete');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles checking if the thread has been deleted, and if so, stops the collector with the reason 'threadDelete'.
|
||||
* @private
|
||||
* @param {ThreadChannel} thread The thread that was deleted
|
||||
* @returns {void}
|
||||
*/
|
||||
_handleThreadDeletion(thread) {
|
||||
if (thread.id === this.channelId) {
|
||||
this.stop('threadDelete');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles checking if the guild has been deleted, and if so, stops the collector with the reason 'guildDelete'.
|
||||
* @private
|
||||
* @param {Guild} guild The guild that was deleted
|
||||
* @returns {void}
|
||||
*/
|
||||
_handleGuildDeletion(guild) {
|
||||
if (guild.id === this.guildId) {
|
||||
this.stop('guildDelete');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = InteractionCollector;
|
||||
102
node_modules/discord.js/src/structures/InteractionResponse.js
generated
vendored
Normal file
102
node_modules/discord.js/src/structures/InteractionResponse.js
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
'use strict';
|
||||
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const { InteractionType } = require('discord-api-types/v10');
|
||||
const { DiscordjsError, ErrorCodes } = require('../errors');
|
||||
|
||||
/**
|
||||
* Represents an interaction's response
|
||||
*/
|
||||
class InteractionResponse {
|
||||
constructor(interaction, id) {
|
||||
/**
|
||||
* The interaction associated with the interaction response
|
||||
* @type {BaseInteraction}
|
||||
*/
|
||||
this.interaction = interaction;
|
||||
/**
|
||||
* The id of the original interaction response
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = id ?? interaction.id;
|
||||
this.client = interaction.client;
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp the interaction response was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the interaction response was created at
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects a single component interaction that passes the filter.
|
||||
* The Promise will reject if the time expires.
|
||||
* @param {AwaitMessageComponentOptions} [options={}] Options to pass to the internal collector
|
||||
* @returns {Promise<MessageComponentInteraction>}
|
||||
*/
|
||||
awaitMessageComponent(options = {}) {
|
||||
const _options = { ...options, max: 1 };
|
||||
return new Promise((resolve, reject) => {
|
||||
const collector = this.createMessageComponentCollector(_options);
|
||||
collector.once('end', (interactions, reason) => {
|
||||
const interaction = interactions.first();
|
||||
if (interaction) resolve(interaction);
|
||||
else reject(new DiscordjsError(ErrorCodes.InteractionCollectorError, reason));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a message component interaction collector
|
||||
* @param {MessageComponentCollectorOptions} [options={}] Options to send to the collector
|
||||
* @returns {InteractionCollector}
|
||||
*/
|
||||
createMessageComponentCollector(options = {}) {
|
||||
return new InteractionCollector(this.client, {
|
||||
...options,
|
||||
interactionResponse: this,
|
||||
interactionType: InteractionType.MessageComponent,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the response as a {@link Message} object.
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
fetch() {
|
||||
return this.interaction.fetchReply();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the response.
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
delete() {
|
||||
return this.interaction.deleteReply();
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits the response.
|
||||
* @param {string|MessagePayload|WebhookMessageEditOptions} options The new options for the response.
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
edit(options) {
|
||||
return this.interaction.editReply(options);
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line import/order
|
||||
const InteractionCollector = require('./InteractionCollector');
|
||||
module.exports = InteractionResponse;
|
||||
59
node_modules/discord.js/src/structures/InteractionWebhook.js
generated
vendored
Normal file
59
node_modules/discord.js/src/structures/InteractionWebhook.js
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
'use strict';
|
||||
|
||||
const Webhook = require('./Webhook');
|
||||
|
||||
/**
|
||||
* Represents a webhook for an Interaction
|
||||
* @implements {Webhook}
|
||||
*/
|
||||
class InteractionWebhook {
|
||||
/**
|
||||
* @param {Client} client The instantiating client
|
||||
* @param {Snowflake} id The application's id
|
||||
* @param {string} token The interaction's token
|
||||
*/
|
||||
constructor(client, id, token) {
|
||||
/**
|
||||
* The client that instantiated the interaction webhook
|
||||
* @name InteractionWebhook#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
this.id = id;
|
||||
Object.defineProperty(this, 'token', { value: token, writable: true, configurable: true });
|
||||
}
|
||||
|
||||
// These are here only for documentation purposes - they are implemented by Webhook
|
||||
/* eslint-disable no-empty-function */
|
||||
/**
|
||||
* Sends a message with this webhook.
|
||||
* @param {string|MessagePayload|InteractionReplyOptions} options The content for the reply
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
|
||||
send() {}
|
||||
|
||||
/**
|
||||
* Gets a message that was sent by this webhook.
|
||||
* @param {Snowflake|'@original'} message The id of the message to fetch
|
||||
* @returns {Promise<Message>} Returns the message sent by this webhook
|
||||
*/
|
||||
|
||||
fetchMessage() {}
|
||||
|
||||
/**
|
||||
* Edits a message that was sent by this webhook.
|
||||
* @param {MessageResolvable|'@original'} message The message to edit
|
||||
* @param {string|MessagePayload|WebhookMessageEditOptions} options The options to provide
|
||||
* @returns {Promise<Message>} Returns the message edited by this webhook
|
||||
*/
|
||||
|
||||
editMessage() {}
|
||||
deleteMessage() {}
|
||||
get url() {}
|
||||
}
|
||||
|
||||
Webhook.applyToClass(InteractionWebhook, ['sendSlackMessage', 'edit', 'delete', 'createdTimestamp', 'createdAt']);
|
||||
|
||||
module.exports = InteractionWebhook;
|
||||
341
node_modules/discord.js/src/structures/Invite.js
generated
vendored
Normal file
341
node_modules/discord.js/src/structures/Invite.js
generated
vendored
Normal file
@@ -0,0 +1,341 @@
|
||||
'use strict';
|
||||
|
||||
const { RouteBases, Routes, PermissionFlagsBits } = require('discord-api-types/v10');
|
||||
const Base = require('./Base');
|
||||
const { GuildScheduledEvent } = require('./GuildScheduledEvent');
|
||||
const IntegrationApplication = require('./IntegrationApplication');
|
||||
const InviteStageInstance = require('./InviteStageInstance');
|
||||
const { DiscordjsError, ErrorCodes } = require('../errors');
|
||||
const { InviteFlagsBitField } = require('../util/InviteFlagsBitField.js');
|
||||
|
||||
/**
|
||||
* Represents an invitation to a guild channel.
|
||||
* @extends {Base}
|
||||
*/
|
||||
class Invite extends Base {
|
||||
/**
|
||||
* A regular expression that matches Discord invite links.
|
||||
* The `code` group property is present on the `exec()` result of this expression.
|
||||
* @type {RegExp}
|
||||
* @memberof Invite
|
||||
*/
|
||||
static InvitesPattern = /discord(?:(?:app)?\.com\/invite|\.gg(?:\/invite)?)\/(?<code>[\w-]{2,255})/i;
|
||||
|
||||
constructor(client, data) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The type of this invite
|
||||
* @type {InviteType}
|
||||
*/
|
||||
this.type = data.type;
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
const InviteGuild = require('./InviteGuild');
|
||||
/**
|
||||
* The guild the invite is for including welcome screen data if present
|
||||
* @type {?(Guild|InviteGuild)}
|
||||
*/
|
||||
this.guild ??= null;
|
||||
if (data.guild) {
|
||||
this.guild = this.client.guilds.cache.get(data.guild.id) ?? new InviteGuild(this.client, data.guild);
|
||||
}
|
||||
|
||||
if ('code' in data) {
|
||||
/**
|
||||
* The code for this invite
|
||||
* @type {string}
|
||||
*/
|
||||
this.code = data.code;
|
||||
}
|
||||
|
||||
if ('approximate_presence_count' in data) {
|
||||
/**
|
||||
* The approximate number of online members of the guild this invite is for
|
||||
* <info>This is only available when the invite was fetched through {@link Client#fetchInvite}.</info>
|
||||
* @type {?number}
|
||||
*/
|
||||
this.presenceCount = data.approximate_presence_count;
|
||||
} else {
|
||||
this.presenceCount ??= null;
|
||||
}
|
||||
|
||||
if ('approximate_member_count' in data) {
|
||||
/**
|
||||
* The approximate total number of members of the guild this invite is for
|
||||
* <info>This is only available when the invite was fetched through {@link Client#fetchInvite}.</info>
|
||||
* @type {?number}
|
||||
*/
|
||||
this.memberCount = data.approximate_member_count;
|
||||
} else {
|
||||
this.memberCount ??= null;
|
||||
}
|
||||
|
||||
if ('temporary' in data) {
|
||||
/**
|
||||
* Whether or not this invite only grants temporary membership
|
||||
* <info>This is only available when the invite was fetched through {@link GuildInviteManager#fetch}
|
||||
* or created through {@link GuildInviteManager#create}.</info>
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.temporary = data.temporary ?? null;
|
||||
} else {
|
||||
this.temporary ??= null;
|
||||
}
|
||||
|
||||
if ('max_age' in data) {
|
||||
/**
|
||||
* The maximum age of the invite, in seconds, 0 if never expires
|
||||
* <info>This is only available when the invite was fetched through {@link GuildInviteManager#fetch}
|
||||
* or created through {@link GuildInviteManager#create}.</info>
|
||||
* @type {?number}
|
||||
*/
|
||||
this.maxAge = data.max_age;
|
||||
} else {
|
||||
this.maxAge ??= null;
|
||||
}
|
||||
|
||||
if ('uses' in data) {
|
||||
/**
|
||||
* How many times this invite has been used
|
||||
* <info>This is only available when the invite was fetched through {@link GuildInviteManager#fetch}
|
||||
* or created through {@link GuildInviteManager#create}.</info>
|
||||
* @type {?number}
|
||||
*/
|
||||
this.uses = data.uses;
|
||||
} else {
|
||||
this.uses ??= null;
|
||||
}
|
||||
|
||||
if ('max_uses' in data) {
|
||||
/**
|
||||
* The maximum uses of this invite
|
||||
* <info>This is only available when the invite was fetched through {@link GuildInviteManager#fetch}
|
||||
* or created through {@link GuildInviteManager#create}.</info>
|
||||
* @type {?number}
|
||||
*/
|
||||
this.maxUses = data.max_uses;
|
||||
} else {
|
||||
this.maxUses ??= null;
|
||||
}
|
||||
|
||||
if ('inviter_id' in data) {
|
||||
/**
|
||||
* The user's id who created this invite
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.inviterId = data.inviter_id;
|
||||
} else {
|
||||
this.inviterId ??= null;
|
||||
}
|
||||
|
||||
if ('inviter' in data) {
|
||||
this.client.users._add(data.inviter);
|
||||
this.inviterId = data.inviter.id;
|
||||
}
|
||||
|
||||
if ('target_user' in data) {
|
||||
/**
|
||||
* The user whose stream to display for this voice channel stream invite
|
||||
* @type {?User}
|
||||
*/
|
||||
this.targetUser = this.client.users._add(data.target_user);
|
||||
} else {
|
||||
this.targetUser ??= null;
|
||||
}
|
||||
|
||||
if ('target_application' in data) {
|
||||
/**
|
||||
* The embedded application to open for this voice channel embedded application invite
|
||||
* @type {?IntegrationApplication}
|
||||
*/
|
||||
this.targetApplication = new IntegrationApplication(this.client, data.target_application);
|
||||
} else {
|
||||
this.targetApplication ??= null;
|
||||
}
|
||||
|
||||
if ('target_type' in data) {
|
||||
/**
|
||||
* The target type
|
||||
* @type {?InviteTargetType}
|
||||
*/
|
||||
this.targetType = data.target_type;
|
||||
} else {
|
||||
this.targetType ??= null;
|
||||
}
|
||||
|
||||
if ('channel_id' in data) {
|
||||
/**
|
||||
* The id of the channel this invite is for
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.channelId = data.channel_id;
|
||||
}
|
||||
|
||||
if ('channel' in data) {
|
||||
/**
|
||||
* The channel this invite is for
|
||||
* @type {?BaseChannel}
|
||||
*/
|
||||
this.channel =
|
||||
this.client.channels._add(data.channel, this.guild, { cache: false }) ??
|
||||
this.client.channels.resolve(this.channelId);
|
||||
|
||||
this.channelId ??= data.channel.id;
|
||||
}
|
||||
|
||||
if ('created_at' in data) {
|
||||
/**
|
||||
* The timestamp this invite was created at
|
||||
* @type {?number}
|
||||
*/
|
||||
this.createdTimestamp = Date.parse(data.created_at);
|
||||
} else {
|
||||
this.createdTimestamp ??= null;
|
||||
}
|
||||
|
||||
if ('expires_at' in data) {
|
||||
this._expiresTimestamp = data.expires_at && Date.parse(data.expires_at);
|
||||
} else {
|
||||
this._expiresTimestamp ??= null;
|
||||
}
|
||||
|
||||
if ('stage_instance' in data) {
|
||||
/**
|
||||
* The stage instance data if there is a public {@link StageInstance} in the stage channel this invite is for
|
||||
* @type {?InviteStageInstance}
|
||||
* @deprecated
|
||||
*/
|
||||
this.stageInstance = new InviteStageInstance(this.client, data.stage_instance, this.channel.id, this.guild.id);
|
||||
} else {
|
||||
this.stageInstance ??= null;
|
||||
}
|
||||
|
||||
if ('guild_scheduled_event' in data) {
|
||||
/**
|
||||
* The guild scheduled event data if there is a {@link GuildScheduledEvent} in the channel this invite is for
|
||||
* @type {?GuildScheduledEvent}
|
||||
*/
|
||||
this.guildScheduledEvent = new GuildScheduledEvent(this.client, data.guild_scheduled_event);
|
||||
} else {
|
||||
this.guildScheduledEvent ??= null;
|
||||
}
|
||||
|
||||
if ('flags' in data) {
|
||||
/**
|
||||
* The flags of this invite.
|
||||
*
|
||||
* @type {Readonly<InviteFlagsBitField>}
|
||||
*/
|
||||
this.flags = new InviteFlagsBitField(data.flags).freeze();
|
||||
} else {
|
||||
this.flags ??= new InviteFlagsBitField().freeze();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the invite was created at
|
||||
* @type {?Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return this.createdTimestamp && new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the invite is deletable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get deletable() {
|
||||
const guild = this.guild;
|
||||
if (!guild || !this.client.guilds.cache.has(guild.id)) return false;
|
||||
if (!guild.members.me) throw new DiscordjsError(ErrorCodes.GuildUncachedMe);
|
||||
return Boolean(
|
||||
this.channel?.permissionsFor(this.client.user).has(PermissionFlagsBits.ManageChannels, false) ||
|
||||
guild.members.me.permissions.has(PermissionFlagsBits.ManageGuild),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp the invite will expire at
|
||||
* @type {?number}
|
||||
* @readonly
|
||||
*/
|
||||
get expiresTimestamp() {
|
||||
return (
|
||||
this._expiresTimestamp ??
|
||||
(this.createdTimestamp && this.maxAge ? this.createdTimestamp + this.maxAge * 1_000 : null)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the invite will expire at
|
||||
* @type {?Date}
|
||||
* @readonly
|
||||
*/
|
||||
get expiresAt() {
|
||||
return this.expiresTimestamp && new Date(this.expiresTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The user who created this invite
|
||||
* @type {?User}
|
||||
* @readonly
|
||||
*/
|
||||
get inviter() {
|
||||
return this.inviterId && this.client.users.resolve(this.inviterId);
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL to the invite
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get url() {
|
||||
return `${RouteBases.invite}/${this.code}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this invite.
|
||||
* @param {string} [reason] Reason for deleting this invite
|
||||
* @returns {Promise<Invite>}
|
||||
*/
|
||||
async delete(reason) {
|
||||
await this.client.rest.delete(Routes.invite(this.code), { reason });
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically concatenates the invite's URL instead of the object.
|
||||
* @returns {string}
|
||||
* @example
|
||||
* // Logs: Invite: https://discord.gg/A1b2C3
|
||||
* console.log(`Invite: ${invite}`);
|
||||
*/
|
||||
toString() {
|
||||
return this.url;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return super.toJSON({
|
||||
url: true,
|
||||
expiresTimestamp: true,
|
||||
presenceCount: false,
|
||||
memberCount: false,
|
||||
uses: false,
|
||||
channel: 'channelId',
|
||||
inviter: 'inviterId',
|
||||
guild: 'guildId',
|
||||
});
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.code;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Invite;
|
||||
22
node_modules/discord.js/src/structures/InviteGuild.js
generated
vendored
Normal file
22
node_modules/discord.js/src/structures/InviteGuild.js
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
'use strict';
|
||||
|
||||
const AnonymousGuild = require('./AnonymousGuild');
|
||||
const WelcomeScreen = require('./WelcomeScreen');
|
||||
|
||||
/**
|
||||
* Represents a guild received from an invite, includes welcome screen data if available.
|
||||
* @extends {AnonymousGuild}
|
||||
*/
|
||||
class InviteGuild extends AnonymousGuild {
|
||||
constructor(client, data) {
|
||||
super(client, data);
|
||||
|
||||
/**
|
||||
* The welcome screen for this invite guild
|
||||
* @type {?WelcomeScreen}
|
||||
*/
|
||||
this.welcomeScreen = data.welcome_screen !== undefined ? new WelcomeScreen(this, data.welcome_screen) : null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = InviteGuild;
|
||||
87
node_modules/discord.js/src/structures/InviteStageInstance.js
generated
vendored
Normal file
87
node_modules/discord.js/src/structures/InviteStageInstance.js
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const Base = require('./Base');
|
||||
|
||||
/**
|
||||
* Represents the data about a public {@link StageInstance} in an {@link Invite}.
|
||||
* @extends {Base}
|
||||
* @deprecated
|
||||
*/
|
||||
class InviteStageInstance extends Base {
|
||||
constructor(client, data, channelId, guildId) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The id of the stage channel this invite is for
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.channelId = channelId;
|
||||
|
||||
/**
|
||||
* The stage channel's guild id
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.guildId = guildId;
|
||||
|
||||
/**
|
||||
* The members speaking in the stage channel
|
||||
* @type {Collection<Snowflake, GuildMember>}
|
||||
*/
|
||||
this.members = new Collection();
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
if ('topic' in data) {
|
||||
/**
|
||||
* The topic of the stage instance
|
||||
* @type {string}
|
||||
*/
|
||||
this.topic = data.topic;
|
||||
}
|
||||
|
||||
if ('participant_count' in data) {
|
||||
/**
|
||||
* The number of users in the stage channel
|
||||
* @type {number}
|
||||
*/
|
||||
this.participantCount = data.participant_count;
|
||||
}
|
||||
|
||||
if ('speaker_count' in data) {
|
||||
/**
|
||||
* The number of users speaking in the stage channel
|
||||
* @type {number}
|
||||
*/
|
||||
this.speakerCount = data.speaker_count;
|
||||
}
|
||||
|
||||
this.members.clear();
|
||||
for (const rawMember of data.members) {
|
||||
const member = this.guild.members._add(rawMember);
|
||||
this.members.set(member.id, member);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The stage channel this invite is for
|
||||
* @type {?StageChannel}
|
||||
* @readonly
|
||||
*/
|
||||
get channel() {
|
||||
return this.client.channels.resolve(this.channelId);
|
||||
}
|
||||
|
||||
/**
|
||||
* The guild of the stage channel this invite is for
|
||||
* @type {?Guild}
|
||||
* @readonly
|
||||
*/
|
||||
get guild() {
|
||||
return this.client.guilds.resolve(this.guildId);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = InviteStageInstance;
|
||||
54
node_modules/discord.js/src/structures/LabelComponent.js
generated
vendored
Normal file
54
node_modules/discord.js/src/structures/LabelComponent.js
generated
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
'use strict';
|
||||
|
||||
const Component = require('./Component');
|
||||
const { createComponent } = require('../util/Components');
|
||||
|
||||
/**
|
||||
* Represents a label component
|
||||
*
|
||||
* @extends {Component}
|
||||
*/
|
||||
class LabelComponent extends Component {
|
||||
constructor({ component, ...data }) {
|
||||
super(data);
|
||||
|
||||
/**
|
||||
* The component in this label
|
||||
*
|
||||
* @type {Component}
|
||||
* @readonly
|
||||
*/
|
||||
this.component = createComponent(component);
|
||||
}
|
||||
|
||||
/**
|
||||
* The label of the component
|
||||
*
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get label() {
|
||||
return this.data.label;
|
||||
}
|
||||
|
||||
/**
|
||||
* The description of this component
|
||||
*
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get description() {
|
||||
return this.data.description ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the API-compatible JSON for this component
|
||||
*
|
||||
* @returns {APILabelComponent}
|
||||
*/
|
||||
toJSON() {
|
||||
return { ...this.data, component: this.component.toJSON() };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = LabelComponent;
|
||||
11
node_modules/discord.js/src/structures/MediaChannel.js
generated
vendored
Normal file
11
node_modules/discord.js/src/structures/MediaChannel.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const ThreadOnlyChannel = require('./ThreadOnlyChannel');
|
||||
|
||||
/**
|
||||
* Represents a media channel.
|
||||
* @extends {ThreadOnlyChannel}
|
||||
*/
|
||||
class MediaChannel extends ThreadOnlyChannel {}
|
||||
|
||||
module.exports = MediaChannel;
|
||||
31
node_modules/discord.js/src/structures/MediaGalleryComponent.js
generated
vendored
Normal file
31
node_modules/discord.js/src/structures/MediaGalleryComponent.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
const Component = require('./Component');
|
||||
const MediaGalleryItem = require('./MediaGalleryItem');
|
||||
|
||||
/**
|
||||
* Represents a media gallery component
|
||||
* @extends {Component}
|
||||
*/
|
||||
class MediaGalleryComponent extends Component {
|
||||
constructor({ items, ...data }) {
|
||||
super(data);
|
||||
|
||||
/**
|
||||
* The items in this media gallery
|
||||
* @type {MediaGalleryItem[]}
|
||||
* @readonly
|
||||
*/
|
||||
this.items = items.map(item => new MediaGalleryItem(item));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the API-compatible JSON for this component
|
||||
* @returns {APIMediaGalleryComponent}
|
||||
*/
|
||||
toJSON() {
|
||||
return { ...this.data, items: this.items.map(item => item.toJSON()) };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MediaGalleryComponent;
|
||||
51
node_modules/discord.js/src/structures/MediaGalleryItem.js
generated
vendored
Normal file
51
node_modules/discord.js/src/structures/MediaGalleryItem.js
generated
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
'use strict';
|
||||
|
||||
const UnfurledMediaItem = require('./UnfurledMediaItem');
|
||||
|
||||
/**
|
||||
* Represents an item in a media gallery
|
||||
*/
|
||||
class MediaGalleryItem {
|
||||
constructor({ media, ...data }) {
|
||||
/**
|
||||
* The API data associated with this component
|
||||
* @type {APIMediaGalleryItem}
|
||||
*/
|
||||
this.data = data;
|
||||
|
||||
/**
|
||||
* The media associated with this media gallery item
|
||||
* @type {UnfurledMediaItem}
|
||||
* @readonly
|
||||
*/
|
||||
this.media = new UnfurledMediaItem(media);
|
||||
}
|
||||
|
||||
/**
|
||||
* The description of this media gallery item
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get description() {
|
||||
return this.data.description ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this media gallery item is spoilered
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get spoiler() {
|
||||
return this.data.spoiler ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the API-compatible JSON for this component
|
||||
* @returns {APIMediaGalleryItem}
|
||||
*/
|
||||
toJSON() {
|
||||
return { ...this.data, media: this.media.toJSON() };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MediaGalleryItem;
|
||||
32
node_modules/discord.js/src/structures/MentionableSelectMenuBuilder.js
generated
vendored
Normal file
32
node_modules/discord.js/src/structures/MentionableSelectMenuBuilder.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
|
||||
const { MentionableSelectMenuBuilder: BuildersMentionableSelectMenu } = require('@discordjs/builders');
|
||||
const { isJSONEncodable } = require('@discordjs/util');
|
||||
const { toSnakeCase } = require('../util/Transformers');
|
||||
|
||||
/**
|
||||
* Class used to build select menu components to be sent through the API
|
||||
* @extends {BuildersMentionableSelectMenu}
|
||||
*/
|
||||
class MentionableSelectMenuBuilder extends BuildersMentionableSelectMenu {
|
||||
constructor(data = {}) {
|
||||
super(toSnakeCase(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new select menu builder from JSON data
|
||||
* @param {MentionableSelectMenuBuilder|MentionableSelectMenuComponent|APIMentionableSelectComponent} other
|
||||
* The other data
|
||||
* @returns {MentionableSelectMenuBuilder}
|
||||
*/
|
||||
static from(other) {
|
||||
return new this(isJSONEncodable(other) ? other.toJSON() : other);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MentionableSelectMenuBuilder;
|
||||
|
||||
/**
|
||||
* @external BuildersMentionableSelectMenu
|
||||
* @see {@link https://discord.js.org/docs/packages/builders/stable/MentionableSelectMenuBuilder:Class}
|
||||
*/
|
||||
11
node_modules/discord.js/src/structures/MentionableSelectMenuComponent.js
generated
vendored
Normal file
11
node_modules/discord.js/src/structures/MentionableSelectMenuComponent.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const BaseSelectMenuComponent = require('./BaseSelectMenuComponent');
|
||||
|
||||
/**
|
||||
* Represents a mentionable select menu component
|
||||
* @extends {BaseSelectMenuComponent}
|
||||
*/
|
||||
class MentionableSelectMenuComponent extends BaseSelectMenuComponent {}
|
||||
|
||||
module.exports = MentionableSelectMenuComponent;
|
||||
71
node_modules/discord.js/src/structures/MentionableSelectMenuInteraction.js
generated
vendored
Normal file
71
node_modules/discord.js/src/structures/MentionableSelectMenuInteraction.js
generated
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const MessageComponentInteraction = require('./MessageComponentInteraction');
|
||||
const Events = require('../util/Events');
|
||||
|
||||
/**
|
||||
* Represents a {@link ComponentType.MentionableSelect} select menu interaction.
|
||||
* @extends {MessageComponentInteraction}
|
||||
*/
|
||||
class MentionableSelectMenuInteraction extends MessageComponentInteraction {
|
||||
constructor(client, data) {
|
||||
super(client, data);
|
||||
const { resolved, values } = data.data;
|
||||
const { members, users, roles } = resolved ?? {};
|
||||
|
||||
/**
|
||||
* An array of the selected user and role ids
|
||||
* @type {Snowflake[]}
|
||||
*/
|
||||
this.values = values ?? [];
|
||||
|
||||
/**
|
||||
* Collection of the selected users
|
||||
* @type {Collection<Snowflake, User>}
|
||||
*/
|
||||
this.users = new Collection();
|
||||
|
||||
/**
|
||||
* Collection of the selected users
|
||||
* @type {Collection<Snowflake, GuildMember|APIGuildMember>}
|
||||
*/
|
||||
this.members = new Collection();
|
||||
|
||||
/**
|
||||
* Collection of the selected roles
|
||||
* @type {Collection<Snowflake, Role|APIRole>}
|
||||
*/
|
||||
this.roles = new Collection();
|
||||
|
||||
if (members) {
|
||||
for (const [id, member] of Object.entries(members)) {
|
||||
const user = users[id];
|
||||
if (!user) {
|
||||
this.client.emit(
|
||||
Events.Debug,
|
||||
`[MentionableSelectMenuInteraction] Received a member without a user, skipping ${id}`,
|
||||
);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
this.members.set(id, this.guild?.members._add({ user, ...member }) ?? { user, ...member });
|
||||
}
|
||||
}
|
||||
|
||||
if (users) {
|
||||
for (const user of Object.values(users)) {
|
||||
this.users.set(user.id, this.client.users._add(user));
|
||||
}
|
||||
}
|
||||
|
||||
if (roles) {
|
||||
for (const role of Object.values(roles)) {
|
||||
this.roles.set(role.id, this.guild?.roles._add(role) ?? role);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MentionableSelectMenuInteraction;
|
||||
1137
node_modules/discord.js/src/structures/Message.js
generated
vendored
Normal file
1137
node_modules/discord.js/src/structures/Message.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
146
node_modules/discord.js/src/structures/MessageCollector.js
generated
vendored
Normal file
146
node_modules/discord.js/src/structures/MessageCollector.js
generated
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
'use strict';
|
||||
|
||||
const Collector = require('./interfaces/Collector');
|
||||
const Events = require('../util/Events');
|
||||
|
||||
/**
|
||||
* @typedef {CollectorOptions} MessageCollectorOptions
|
||||
* @property {number} max The maximum amount of messages to collect
|
||||
* @property {number} maxProcessed The maximum amount of messages to process
|
||||
*/
|
||||
|
||||
/**
|
||||
* Collects messages on a channel.
|
||||
* Will automatically stop if the channel ({@link Client#event:channelDelete channelDelete}),
|
||||
* thread ({@link Client#event:threadDelete threadDelete}), or
|
||||
* guild ({@link Client#event:guildDelete guildDelete}) is deleted.
|
||||
* @extends {Collector}
|
||||
*/
|
||||
class MessageCollector extends Collector {
|
||||
/**
|
||||
* @param {TextBasedChannels} channel The channel
|
||||
* @param {MessageCollectorOptions} options The options to be applied to this collector
|
||||
* @emits MessageCollector#message
|
||||
*/
|
||||
constructor(channel, options = {}) {
|
||||
super(channel.client, options);
|
||||
|
||||
/**
|
||||
* The channel
|
||||
* @type {TextBasedChannels}
|
||||
*/
|
||||
this.channel = channel;
|
||||
|
||||
/**
|
||||
* Total number of messages that were received in the channel during message collection
|
||||
* @type {number}
|
||||
*/
|
||||
this.received = 0;
|
||||
|
||||
const bulkDeleteListener = messages => {
|
||||
for (const message of messages.values()) this.handleDispose(message);
|
||||
};
|
||||
|
||||
this._handleChannelDeletion = this._handleChannelDeletion.bind(this);
|
||||
this._handleThreadDeletion = this._handleThreadDeletion.bind(this);
|
||||
this._handleGuildDeletion = this._handleGuildDeletion.bind(this);
|
||||
|
||||
this.client.incrementMaxListeners();
|
||||
this.client.on(Events.MessageCreate, this.handleCollect);
|
||||
this.client.on(Events.MessageDelete, this.handleDispose);
|
||||
this.client.on(Events.MessageBulkDelete, bulkDeleteListener);
|
||||
this.client.on(Events.ChannelDelete, this._handleChannelDeletion);
|
||||
this.client.on(Events.ThreadDelete, this._handleThreadDeletion);
|
||||
this.client.on(Events.GuildDelete, this._handleGuildDeletion);
|
||||
|
||||
this.once('end', () => {
|
||||
this.client.removeListener(Events.MessageCreate, this.handleCollect);
|
||||
this.client.removeListener(Events.MessageDelete, this.handleDispose);
|
||||
this.client.removeListener(Events.MessageBulkDelete, bulkDeleteListener);
|
||||
this.client.removeListener(Events.ChannelDelete, this._handleChannelDeletion);
|
||||
this.client.removeListener(Events.ThreadDelete, this._handleThreadDeletion);
|
||||
this.client.removeListener(Events.GuildDelete, this._handleGuildDeletion);
|
||||
this.client.decrementMaxListeners();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a message for possible collection.
|
||||
* @param {Message} message The message that could be collected
|
||||
* @returns {?Snowflake}
|
||||
* @private
|
||||
*/
|
||||
collect(message) {
|
||||
/**
|
||||
* Emitted whenever a message is collected.
|
||||
* @event MessageCollector#collect
|
||||
* @param {Message} message The message that was collected
|
||||
*/
|
||||
if (message.channelId !== this.channel.id) return null;
|
||||
this.received++;
|
||||
return message.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a message for possible disposal.
|
||||
* @param {Message} message The message that could be disposed of
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
dispose(message) {
|
||||
/**
|
||||
* Emitted whenever a message is disposed of.
|
||||
* @event MessageCollector#dispose
|
||||
* @param {Message} message The message that was disposed of
|
||||
*/
|
||||
return message.channelId === this.channel.id ? message.id : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The reason this collector has ended with, or null if it hasn't ended yet
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get endReason() {
|
||||
if (this.options.max && this.collected.size >= this.options.max) return 'limit';
|
||||
if (this.options.maxProcessed && this.received === this.options.maxProcessed) return 'processedLimit';
|
||||
return super.endReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles checking if the channel has been deleted, and if so, stops the collector with the reason 'channelDelete'.
|
||||
* @private
|
||||
* @param {GuildChannel} channel The channel that was deleted
|
||||
* @returns {void}
|
||||
*/
|
||||
_handleChannelDeletion(channel) {
|
||||
if (channel.id === this.channel.id || channel.id === this.channel.parentId) {
|
||||
this.stop('channelDelete');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles checking if the thread has been deleted, and if so, stops the collector with the reason 'threadDelete'.
|
||||
* @private
|
||||
* @param {ThreadChannel} thread The thread that was deleted
|
||||
* @returns {void}
|
||||
*/
|
||||
_handleThreadDeletion(thread) {
|
||||
if (thread.id === this.channel.id) {
|
||||
this.stop('threadDelete');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles checking if the guild has been deleted, and if so, stops the collector with the reason 'guildDelete'.
|
||||
* @private
|
||||
* @param {Guild} guild The guild that was deleted
|
||||
* @returns {void}
|
||||
*/
|
||||
_handleGuildDeletion(guild) {
|
||||
if (guild.id === this.channel.guild?.id) {
|
||||
this.stop('guildDelete');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MessageCollector;
|
||||
108
node_modules/discord.js/src/structures/MessageComponentInteraction.js
generated
vendored
Normal file
108
node_modules/discord.js/src/structures/MessageComponentInteraction.js
generated
vendored
Normal file
@@ -0,0 +1,108 @@
|
||||
'use strict';
|
||||
|
||||
const { lazy } = require('@discordjs/util');
|
||||
const BaseInteraction = require('./BaseInteraction');
|
||||
const InteractionWebhook = require('./InteractionWebhook');
|
||||
const InteractionResponses = require('./interfaces/InteractionResponses');
|
||||
const { findComponentByCustomId } = require('../util/Components');
|
||||
|
||||
const getMessage = lazy(() => require('./Message').Message);
|
||||
|
||||
/**
|
||||
* Represents a message component interaction.
|
||||
* @extends {BaseInteraction}
|
||||
* @implements {InteractionResponses}
|
||||
*/
|
||||
class MessageComponentInteraction extends BaseInteraction {
|
||||
constructor(client, data) {
|
||||
super(client, data);
|
||||
|
||||
/**
|
||||
* The id of the channel this interaction was sent in
|
||||
* @type {Snowflake}
|
||||
* @name MessageComponentInteraction#channelId
|
||||
*/
|
||||
|
||||
/**
|
||||
* The message to which the component was attached
|
||||
* @type {Message}
|
||||
*/
|
||||
this.message = this.channel?.messages._add(data.message) ?? new (getMessage())(client, data.message);
|
||||
|
||||
/**
|
||||
* The custom id of the component which was interacted with
|
||||
* @type {string}
|
||||
*/
|
||||
this.customId = data.data.custom_id;
|
||||
|
||||
/**
|
||||
* The type of component which was interacted with
|
||||
* @type {ComponentType}
|
||||
*/
|
||||
this.componentType = data.data.component_type;
|
||||
|
||||
/**
|
||||
* Whether the reply to this interaction has been deferred
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.deferred = false;
|
||||
|
||||
/**
|
||||
* Whether the reply to this interaction is ephemeral
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.ephemeral = null;
|
||||
|
||||
/**
|
||||
* Whether this interaction has already been replied to
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.replied = false;
|
||||
|
||||
/**
|
||||
* An associated interaction webhook, can be used to further interact with this interaction
|
||||
* @type {InteractionWebhook}
|
||||
*/
|
||||
this.webhook = new InteractionWebhook(this.client, this.applicationId, this.token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Components that can be placed in an action row for messages.
|
||||
* * ButtonComponent
|
||||
* * StringSelectMenuComponent
|
||||
* * UserSelectMenuComponent
|
||||
* * RoleSelectMenuComponent
|
||||
* * MentionableSelectMenuComponent
|
||||
* * ChannelSelectMenuComponent
|
||||
* @typedef {ButtonComponent|StringSelectMenuComponent|UserSelectMenuComponent|
|
||||
* RoleSelectMenuComponent|MentionableSelectMenuComponent|ChannelSelectMenuComponent} MessageActionRowComponent
|
||||
*/
|
||||
|
||||
/**
|
||||
* The component which was interacted with
|
||||
* @type {MessageActionRowComponent|APIComponentInMessageActionRow}
|
||||
* @readonly
|
||||
*/
|
||||
get component() {
|
||||
return findComponentByCustomId(this.message.components, this.customId);
|
||||
}
|
||||
|
||||
// These are here only for documentation purposes - they are implemented by InteractionResponses
|
||||
/* eslint-disable no-empty-function */
|
||||
deferReply() {}
|
||||
reply() {}
|
||||
fetchReply() {}
|
||||
editReply() {}
|
||||
deleteReply() {}
|
||||
followUp() {}
|
||||
deferUpdate() {}
|
||||
update() {}
|
||||
launchActivity() {}
|
||||
showModal() {}
|
||||
sendPremiumRequired() {}
|
||||
awaitModalSubmit() {}
|
||||
}
|
||||
|
||||
InteractionResponses.applyToClass(MessageComponentInteraction);
|
||||
|
||||
module.exports = MessageComponentInteraction;
|
||||
20
node_modules/discord.js/src/structures/MessageContextMenuCommandInteraction.js
generated
vendored
Normal file
20
node_modules/discord.js/src/structures/MessageContextMenuCommandInteraction.js
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
'use strict';
|
||||
|
||||
const ContextMenuCommandInteraction = require('./ContextMenuCommandInteraction');
|
||||
|
||||
/**
|
||||
* Represents a message context menu interaction.
|
||||
* @extends {ContextMenuCommandInteraction}
|
||||
*/
|
||||
class MessageContextMenuCommandInteraction extends ContextMenuCommandInteraction {
|
||||
/**
|
||||
* The message this interaction was sent from
|
||||
* @type {Message|APIMessage}
|
||||
* @readonly
|
||||
*/
|
||||
get targetMessage() {
|
||||
return this.options.getMessage('message');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MessageContextMenuCommandInteraction;
|
||||
297
node_modules/discord.js/src/structures/MessageMentions.js
generated
vendored
Normal file
297
node_modules/discord.js/src/structures/MessageMentions.js
generated
vendored
Normal file
@@ -0,0 +1,297 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { FormattingPatterns } = require('discord-api-types/v10');
|
||||
const { flatten } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Keeps track of mentions in a {@link Message}.
|
||||
*/
|
||||
class MessageMentions {
|
||||
/**
|
||||
* A regular expression that matches `@everyone` and `@here`.
|
||||
* The `mention` group property is present on the `exec` result of this expression.
|
||||
* @type {RegExp}
|
||||
* @memberof MessageMentions
|
||||
*/
|
||||
static EveryonePattern = /@(?<mention>everyone|here)/;
|
||||
|
||||
/**
|
||||
* A regular expression that matches user mentions like `<@81440962496172032>`.
|
||||
* The `id` group property is present on the `exec` result of this expression.
|
||||
* @type {RegExp}
|
||||
* @memberof MessageMentions
|
||||
*/
|
||||
static UsersPattern = FormattingPatterns.UserWithOptionalNickname;
|
||||
|
||||
/**
|
||||
* A regular expression that matches role mentions like `<@&297577916114403338>`.
|
||||
* The `id` group property is present on the `exec` result of this expression.
|
||||
* @type {RegExp}
|
||||
* @memberof MessageMentions
|
||||
*/
|
||||
static RolesPattern = FormattingPatterns.Role;
|
||||
|
||||
/**
|
||||
* A regular expression that matches channel mentions like `<#222079895583457280>`.
|
||||
* The `id` group property is present on the `exec` result of this expression.
|
||||
* @type {RegExp}
|
||||
* @memberof MessageMentions
|
||||
*/
|
||||
static ChannelsPattern = FormattingPatterns.Channel;
|
||||
|
||||
/**
|
||||
* A global regular expression variant of {@link MessageMentions.ChannelsPattern}.
|
||||
* @type {RegExp}
|
||||
* @memberof MessageMentions
|
||||
* @private
|
||||
*/
|
||||
static GlobalChannelsPattern = new RegExp(this.ChannelsPattern.source, 'g');
|
||||
|
||||
/**
|
||||
* A global regular expression variant of {@link MessageMentions.UsersPattern}.
|
||||
* @type {RegExp}
|
||||
* @memberof MessageMentions
|
||||
* @private
|
||||
*/
|
||||
static GlobalUsersPattern = new RegExp(this.UsersPattern.source, 'g');
|
||||
|
||||
constructor(message, users, roles, everyone, crosspostedChannels, repliedUser) {
|
||||
/**
|
||||
* The client the message is from
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: message.client });
|
||||
|
||||
/**
|
||||
* The guild the message is in
|
||||
* @type {?Guild}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'guild', { value: message.guild });
|
||||
|
||||
/**
|
||||
* The initial message content
|
||||
* @type {string}
|
||||
* @readonly
|
||||
* @private
|
||||
*/
|
||||
Object.defineProperty(this, '_content', { value: message.content });
|
||||
|
||||
/**
|
||||
* Whether `@everyone` or `@here` were mentioned
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.everyone = Boolean(everyone);
|
||||
|
||||
if (users) {
|
||||
if (users instanceof Collection) {
|
||||
/**
|
||||
* Any users that were mentioned
|
||||
* <info>Order as received from the API, not as they appear in the message content</info>
|
||||
* @type {Collection<Snowflake, User>}
|
||||
*/
|
||||
this.users = new Collection(users);
|
||||
} else {
|
||||
this.users = new Collection();
|
||||
for (const mention of users) {
|
||||
if (mention.member && message.guild) {
|
||||
message.guild.members._add(Object.assign(mention.member, { user: mention }));
|
||||
}
|
||||
const user = message.client.users._add(mention);
|
||||
this.users.set(user.id, user);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.users = new Collection();
|
||||
}
|
||||
|
||||
if (roles instanceof Collection) {
|
||||
/**
|
||||
* Any roles that were mentioned
|
||||
* <info>Order as received from the API, not as they appear in the message content</info>
|
||||
* @type {Collection<Snowflake, Role>}
|
||||
*/
|
||||
this.roles = new Collection(roles);
|
||||
} else if (roles) {
|
||||
this.roles = new Collection();
|
||||
const guild = message.guild;
|
||||
if (guild) {
|
||||
for (const mention of roles) {
|
||||
const role = guild.roles.cache.get(mention);
|
||||
if (role) this.roles.set(role.id, role);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.roles = new Collection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Cached members for {@link MessageMentions#members}
|
||||
* @type {?Collection<Snowflake, GuildMember>}
|
||||
* @private
|
||||
*/
|
||||
this._members = null;
|
||||
|
||||
/**
|
||||
* Cached channels for {@link MessageMentions#channels}
|
||||
* @type {?Collection<Snowflake, BaseChannel>}
|
||||
* @private
|
||||
*/
|
||||
this._channels = null;
|
||||
|
||||
/**
|
||||
* Cached users for {@link MessageMentions#parsedUsers}
|
||||
* @type {?Collection<Snowflake, User>}
|
||||
* @private
|
||||
*/
|
||||
this._parsedUsers = null;
|
||||
|
||||
/**
|
||||
* Crossposted channel data.
|
||||
* @typedef {Object} CrosspostedChannel
|
||||
* @property {Snowflake} channelId The mentioned channel's id
|
||||
* @property {Snowflake} guildId The id of the guild that has the channel
|
||||
* @property {ChannelType} type The channel's type
|
||||
* @property {string} name The channel's name
|
||||
*/
|
||||
|
||||
if (crosspostedChannels) {
|
||||
if (crosspostedChannels instanceof Collection) {
|
||||
/**
|
||||
* A collection of crossposted channels
|
||||
* <info>Order as received from the API, not as they appear in the message content</info>
|
||||
* @type {Collection<Snowflake, CrosspostedChannel>}
|
||||
*/
|
||||
this.crosspostedChannels = new Collection(crosspostedChannels);
|
||||
} else {
|
||||
this.crosspostedChannels = new Collection();
|
||||
for (const crosspostedChannel of crosspostedChannels) {
|
||||
this.crosspostedChannels.set(crosspostedChannel.id, {
|
||||
channelId: crosspostedChannel.id,
|
||||
guildId: crosspostedChannel.guild_id,
|
||||
type: crosspostedChannel.type,
|
||||
name: crosspostedChannel.name,
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.crosspostedChannels = new Collection();
|
||||
}
|
||||
|
||||
/**
|
||||
* The author of the message that this message is a reply to
|
||||
* @type {?User}
|
||||
*/
|
||||
this.repliedUser = repliedUser ? this.client.users._add(repliedUser) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Any members that were mentioned (only in {@link Guild}s)
|
||||
* <info>Order as received from the API, not as they appear in the message content</info>
|
||||
* @type {?Collection<Snowflake, GuildMember>}
|
||||
* @readonly
|
||||
*/
|
||||
get members() {
|
||||
if (this._members) return this._members;
|
||||
if (!this.guild) return null;
|
||||
this._members = new Collection();
|
||||
this.users.forEach(user => {
|
||||
const member = this.guild.members.resolve(user);
|
||||
if (member) this._members.set(member.user.id, member);
|
||||
});
|
||||
return this._members;
|
||||
}
|
||||
|
||||
/**
|
||||
* Any channels that were mentioned
|
||||
* <info>Order as they appear first in the message content</info>
|
||||
* @type {Collection<Snowflake, BaseChannel>}
|
||||
* @readonly
|
||||
*/
|
||||
get channels() {
|
||||
if (this._channels) return this._channels;
|
||||
this._channels = new Collection();
|
||||
let matches;
|
||||
|
||||
while ((matches = this.constructor.GlobalChannelsPattern.exec(this._content)) !== null) {
|
||||
const channel = this.client.channels.cache.get(matches.groups.id);
|
||||
if (channel) this._channels.set(channel.id, channel);
|
||||
}
|
||||
|
||||
return this._channels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Any user mentions that were included in the message content
|
||||
* <info>Order as they appear first in the message content</info>
|
||||
* @type {Collection<Snowflake, User>}
|
||||
* @readonly
|
||||
*/
|
||||
get parsedUsers() {
|
||||
if (this._parsedUsers) return this._parsedUsers;
|
||||
this._parsedUsers = new Collection();
|
||||
let matches;
|
||||
while ((matches = this.constructor.GlobalUsersPattern.exec(this._content)) !== null) {
|
||||
const user = this.client.users.cache.get(matches[1]);
|
||||
if (user) this._parsedUsers.set(user.id, user);
|
||||
}
|
||||
return this._parsedUsers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to check for a mention.
|
||||
* @typedef {Object} MessageMentionsHasOptions
|
||||
* @property {boolean} [ignoreDirect=false] Whether to ignore direct mentions to the item
|
||||
* @property {boolean} [ignoreRoles=false] Whether to ignore role mentions to a guild member
|
||||
* @property {boolean} [ignoreRepliedUser=false] Whether to ignore replied user mention to an user
|
||||
* @property {boolean} [ignoreEveryone=false] Whether to ignore `@everyone`/`@here` mentions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Checks if a user, guild member, thread member, role, or channel is mentioned.
|
||||
* Takes into account user mentions, role mentions, channel mentions,
|
||||
* replied user mention, and `@everyone`/`@here` mentions.
|
||||
* @param {UserResolvable|RoleResolvable|ChannelResolvable} data The User/Role/Channel to check for
|
||||
* @param {MessageMentionsHasOptions} [options] The options for the check
|
||||
* @returns {boolean}
|
||||
*/
|
||||
has(data, { ignoreDirect = false, ignoreRoles = false, ignoreRepliedUser = false, ignoreEveryone = false } = {}) {
|
||||
const user = this.client.users.resolve(data);
|
||||
|
||||
if (!ignoreEveryone && user && this.everyone) return true;
|
||||
|
||||
const userWasRepliedTo = user && this.repliedUser?.id === user.id;
|
||||
|
||||
if (!ignoreRepliedUser && userWasRepliedTo && this.users.has(user.id)) return true;
|
||||
|
||||
if (!ignoreDirect) {
|
||||
if (user && (!ignoreRepliedUser || this.parsedUsers.has(user.id)) && this.users.has(user.id)) return true;
|
||||
|
||||
const role = this.guild?.roles.resolve(data);
|
||||
if (role && this.roles.has(role.id)) return true;
|
||||
|
||||
const channel = this.client.channels.resolve(data);
|
||||
if (channel && this.channels.has(channel.id)) return true;
|
||||
}
|
||||
|
||||
if (!ignoreRoles) {
|
||||
const member = this.guild?.members.resolve(data);
|
||||
if (member) {
|
||||
for (const mentionedRole of this.roles.values()) if (member.roles.cache.has(mentionedRole.id)) return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return flatten(this, {
|
||||
members: true,
|
||||
channels: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MessageMentions;
|
||||
344
node_modules/discord.js/src/structures/MessagePayload.js
generated
vendored
Normal file
344
node_modules/discord.js/src/structures/MessagePayload.js
generated
vendored
Normal file
@@ -0,0 +1,344 @@
|
||||
'use strict';
|
||||
|
||||
const { Buffer } = require('node:buffer');
|
||||
const { lazy, isJSONEncodable } = require('@discordjs/util');
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const { MessageFlags, MessageReferenceType } = require('discord-api-types/v10');
|
||||
const { DiscordjsError, DiscordjsRangeError, ErrorCodes } = require('../errors');
|
||||
const { resolveFile } = require('../util/DataResolver');
|
||||
const MessageFlagsBitField = require('../util/MessageFlagsBitField');
|
||||
const { basename, verifyString, resolvePartialEmoji } = require('../util/Util');
|
||||
|
||||
const getBaseInteraction = lazy(() => require('./BaseInteraction'));
|
||||
|
||||
/**
|
||||
* Represents a message to be sent to the API.
|
||||
*/
|
||||
class MessagePayload {
|
||||
/**
|
||||
* @param {MessageTarget} target The target for this message to be sent to
|
||||
* @param {MessagePayloadOption} options The payload of this message
|
||||
*/
|
||||
constructor(target, options) {
|
||||
/**
|
||||
* The target for this message to be sent to
|
||||
* @type {MessageTarget}
|
||||
*/
|
||||
this.target = target;
|
||||
|
||||
/**
|
||||
* The payload of this message.
|
||||
* @type {MessagePayloadOption}
|
||||
*/
|
||||
this.options = options;
|
||||
|
||||
/**
|
||||
* Body sendable to the API
|
||||
* @type {?APIMessage}
|
||||
*/
|
||||
this.body = null;
|
||||
|
||||
/**
|
||||
* Files sendable to the API
|
||||
* @type {?RawFile[]}
|
||||
*/
|
||||
this.files = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the target is a {@link Webhook} or a {@link WebhookClient}
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get isWebhook() {
|
||||
const Webhook = require('./Webhook');
|
||||
const WebhookClient = require('../client/WebhookClient');
|
||||
return this.target instanceof Webhook || this.target instanceof WebhookClient;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the target is a {@link User}
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get isUser() {
|
||||
const User = require('./User');
|
||||
const { GuildMember } = require('./GuildMember');
|
||||
return this.target instanceof User || this.target instanceof GuildMember;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the target is a {@link Message}
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get isMessage() {
|
||||
const { Message } = require('./Message');
|
||||
return this.target instanceof Message;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the target is a {@link MessageManager}
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get isMessageManager() {
|
||||
const MessageManager = require('../managers/MessageManager');
|
||||
return this.target instanceof MessageManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the target is an {@link BaseInteraction} or an {@link InteractionWebhook}
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
* @deprecated This will no longer serve a purpose in the next major version.
|
||||
*/
|
||||
get isInteraction() {
|
||||
const BaseInteraction = getBaseInteraction();
|
||||
const InteractionWebhook = require('./InteractionWebhook');
|
||||
return this.target instanceof BaseInteraction || this.target instanceof InteractionWebhook;
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the content of this message.
|
||||
* @returns {?string}
|
||||
*/
|
||||
makeContent() {
|
||||
let content;
|
||||
if (this.options.content === null) {
|
||||
content = '';
|
||||
} else if (this.options.content !== undefined) {
|
||||
content = verifyString(this.options.content, DiscordjsRangeError, ErrorCodes.MessageContentType, true);
|
||||
}
|
||||
|
||||
return content;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the body.
|
||||
* @returns {MessagePayload}
|
||||
*/
|
||||
resolveBody() {
|
||||
if (this.body) return this;
|
||||
const isInteraction = this.isInteraction;
|
||||
const isWebhook = this.isWebhook;
|
||||
|
||||
const content = this.makeContent();
|
||||
const tts = Boolean(this.options.tts);
|
||||
|
||||
let nonce;
|
||||
if (this.options.nonce !== undefined) {
|
||||
nonce = this.options.nonce;
|
||||
if (typeof nonce === 'number' ? !Number.isInteger(nonce) : typeof nonce !== 'string') {
|
||||
throw new DiscordjsRangeError(ErrorCodes.MessageNonceType);
|
||||
}
|
||||
}
|
||||
|
||||
let enforce_nonce = Boolean(this.options.enforceNonce);
|
||||
|
||||
// If `nonce` isn't provided, generate one & set `enforceNonce`
|
||||
// Unless `enforceNonce` is explicitly set to `false`(not just falsy)
|
||||
if (nonce === undefined) {
|
||||
if (this.options.enforceNonce !== false && this.target.client.options.enforceNonce) {
|
||||
nonce = DiscordSnowflake.generate().toString();
|
||||
enforce_nonce = true;
|
||||
} else if (enforce_nonce) {
|
||||
throw new DiscordjsError(ErrorCodes.MessageNonceRequired);
|
||||
}
|
||||
}
|
||||
|
||||
const components = this.options.components?.map(component =>
|
||||
isJSONEncodable(component) ? component.toJSON() : this.target.client.options.jsonTransformer(component),
|
||||
);
|
||||
|
||||
let username;
|
||||
let avatarURL;
|
||||
let threadName;
|
||||
let appliedTags;
|
||||
if (isWebhook) {
|
||||
username = this.options.username ?? this.target.name;
|
||||
if (this.options.avatarURL) avatarURL = this.options.avatarURL;
|
||||
if (this.options.threadName) threadName = this.options.threadName;
|
||||
if (this.options.appliedTags) appliedTags = this.options.appliedTags;
|
||||
}
|
||||
|
||||
let flags;
|
||||
if (
|
||||
// eslint-disable-next-line eqeqeq
|
||||
this.options.flags != null
|
||||
) {
|
||||
flags = new MessageFlagsBitField(this.options.flags).bitfield;
|
||||
}
|
||||
|
||||
if (isInteraction && this.options.ephemeral) {
|
||||
flags |= MessageFlags.Ephemeral;
|
||||
}
|
||||
|
||||
let allowedMentions =
|
||||
this.options.allowedMentions === undefined
|
||||
? this.target.client.options.allowedMentions
|
||||
: this.options.allowedMentions;
|
||||
|
||||
if (allowedMentions?.repliedUser !== undefined) {
|
||||
allowedMentions = { ...allowedMentions, replied_user: allowedMentions.repliedUser };
|
||||
delete allowedMentions.repliedUser;
|
||||
}
|
||||
|
||||
let message_reference;
|
||||
if (typeof this.options.reply === 'object') {
|
||||
const reference = this.options.reply.messageReference;
|
||||
const message_id = this.isMessage ? (reference.id ?? reference) : this.target.messages.resolveId(reference);
|
||||
if (message_id) {
|
||||
message_reference = {
|
||||
message_id,
|
||||
fail_if_not_exists: this.options.reply.failIfNotExists ?? this.target.client.options.failIfNotExists,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof this.options.forward === 'object') {
|
||||
const reference = this.options.forward.message;
|
||||
const channel_id = reference.channelId ?? this.target.client.channels.resolveId(this.options.forward.channel);
|
||||
const guild_id = reference.guildId ?? this.target.client.guilds.resolveId(this.options.forward.guild);
|
||||
const message_id = this.target.messages.resolveId(reference);
|
||||
if (message_id) {
|
||||
if (!channel_id) throw new DiscordjsError(ErrorCodes.InvalidType, 'channelId', 'TextBasedChannelResolvable');
|
||||
message_reference = {
|
||||
type: MessageReferenceType.Forward,
|
||||
message_id,
|
||||
channel_id,
|
||||
guild_id: guild_id ?? undefined,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
const attachments = this.options.files?.map((file, index) => ({
|
||||
id: index.toString(),
|
||||
description: file.description,
|
||||
}));
|
||||
if (Array.isArray(this.options.attachments)) {
|
||||
this.options.attachments.push(...(attachments ?? []));
|
||||
} else {
|
||||
this.options.attachments = attachments;
|
||||
}
|
||||
|
||||
let poll;
|
||||
if (this.options.poll) {
|
||||
poll = {
|
||||
question: {
|
||||
text: this.options.poll.question.text,
|
||||
},
|
||||
answers: this.options.poll.answers.map(answer => ({
|
||||
poll_media: { text: answer.text, emoji: resolvePartialEmoji(answer.emoji) },
|
||||
})),
|
||||
duration: this.options.poll.duration,
|
||||
allow_multiselect: this.options.poll.allowMultiselect,
|
||||
layout_type: this.options.poll.layoutType,
|
||||
};
|
||||
}
|
||||
|
||||
this.body = {
|
||||
content,
|
||||
tts,
|
||||
nonce,
|
||||
enforce_nonce,
|
||||
embeds: this.options.embeds?.map(embed =>
|
||||
isJSONEncodable(embed) ? embed.toJSON() : this.target.client.options.jsonTransformer(embed),
|
||||
),
|
||||
components,
|
||||
username,
|
||||
avatar_url: avatarURL,
|
||||
allowed_mentions:
|
||||
this.isMessage && message_reference === undefined && this.target.author.id !== this.target.client.user.id
|
||||
? undefined
|
||||
: allowedMentions,
|
||||
flags,
|
||||
message_reference,
|
||||
attachments: this.options.attachments,
|
||||
sticker_ids: this.options.stickers?.map(sticker => sticker.id ?? sticker),
|
||||
thread_name: threadName,
|
||||
applied_tags: appliedTags,
|
||||
poll,
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves files.
|
||||
* @returns {Promise<MessagePayload>}
|
||||
*/
|
||||
async resolveFiles() {
|
||||
if (this.files) return this;
|
||||
|
||||
this.files = await Promise.all(this.options.files?.map(file => this.constructor.resolveFile(file)) ?? []);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a single file into an object sendable to the API.
|
||||
* @param {AttachmentPayload|BufferResolvable|Stream} fileLike Something that could be resolved to a file
|
||||
* @returns {Promise<RawFile>}
|
||||
*/
|
||||
static async resolveFile(fileLike) {
|
||||
let attachment;
|
||||
let name;
|
||||
|
||||
const findName = thing => {
|
||||
if (typeof thing === 'string') {
|
||||
return basename(thing);
|
||||
}
|
||||
|
||||
if (thing.path) {
|
||||
return basename(thing.path);
|
||||
}
|
||||
|
||||
return 'file.jpg';
|
||||
};
|
||||
|
||||
const ownAttachment =
|
||||
typeof fileLike === 'string' || fileLike instanceof Buffer || typeof fileLike.pipe === 'function';
|
||||
if (ownAttachment) {
|
||||
attachment = fileLike;
|
||||
name = findName(attachment);
|
||||
} else {
|
||||
attachment = fileLike.attachment;
|
||||
name = fileLike.name ?? findName(attachment);
|
||||
}
|
||||
|
||||
const { data, contentType } = await resolveFile(attachment);
|
||||
return { data, name, contentType };
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link MessagePayload} from user-level arguments.
|
||||
* @param {MessageTarget} target Target to send to
|
||||
* @param {string|MessagePayloadOption} options Options or content to use
|
||||
* @param {MessagePayloadOption} [extra={}] Extra options to add onto specified options
|
||||
* @returns {MessagePayload}
|
||||
*/
|
||||
static create(target, options, extra = {}) {
|
||||
return new this(
|
||||
target,
|
||||
typeof options !== 'object' || options === null ? { content: options, ...extra } : { ...options, ...extra },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MessagePayload;
|
||||
|
||||
/**
|
||||
* A target for a message.
|
||||
* @typedef {TextBasedChannels|User|GuildMember|Webhook|WebhookClient|BaseInteraction|InteractionWebhook|
|
||||
* Message|MessageManager} MessageTarget
|
||||
*/
|
||||
|
||||
/**
|
||||
* A possible payload option.
|
||||
* @typedef {MessageCreateOptions|MessageEditOptions|WebhookMessageCreateOptions|WebhookMessageEditOptions|
|
||||
* InteractionReplyOptions|InteractionUpdateOptions} MessagePayloadOption
|
||||
*/
|
||||
|
||||
/**
|
||||
* @external RawFile
|
||||
* @see {@link https://discord.js.org/docs/packages/rest/stable/RawFile:Interface}
|
||||
*/
|
||||
200
node_modules/discord.js/src/structures/MessageReaction.js
generated
vendored
Normal file
200
node_modules/discord.js/src/structures/MessageReaction.js
generated
vendored
Normal file
@@ -0,0 +1,200 @@
|
||||
'use strict';
|
||||
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const ApplicationEmoji = require('./ApplicationEmoji');
|
||||
const GuildEmoji = require('./GuildEmoji');
|
||||
const ReactionEmoji = require('./ReactionEmoji');
|
||||
const ReactionUserManager = require('../managers/ReactionUserManager');
|
||||
const { flatten } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents a reaction to a message.
|
||||
*/
|
||||
class MessageReaction {
|
||||
constructor(client, data, message) {
|
||||
/**
|
||||
* The client that instantiated this message reaction
|
||||
* @name MessageReaction#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
|
||||
/**
|
||||
* The message that this reaction refers to
|
||||
* @type {Message}
|
||||
*/
|
||||
this.message = message;
|
||||
|
||||
/**
|
||||
* Whether the client has given this reaction
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.me = data.me;
|
||||
|
||||
/**
|
||||
* Whether the client has super-reacted using this emoji
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.meBurst = Boolean(data.me_burst);
|
||||
|
||||
/**
|
||||
* A manager of the users that have given this reaction
|
||||
* @type {ReactionUserManager}
|
||||
*/
|
||||
this.users = new ReactionUserManager(this, this.me ? [client.user] : []);
|
||||
|
||||
this._emoji = new ReactionEmoji(this, data.emoji);
|
||||
|
||||
this.burstColors = null;
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
if (data.burst_colors) {
|
||||
/**
|
||||
* Hexadecimal colors used for this super reaction
|
||||
* @type {?string[]}
|
||||
*/
|
||||
this.burstColors = data.burst_colors;
|
||||
}
|
||||
|
||||
if ('count' in data) {
|
||||
/**
|
||||
* The number of people that have given the same reaction
|
||||
* @type {?number}
|
||||
*/
|
||||
this.count ??= data.count;
|
||||
}
|
||||
|
||||
if ('count_details' in data) {
|
||||
/**
|
||||
* The reaction count details object contains information about super and normal reaction counts.
|
||||
* @typedef {Object} ReactionCountDetailsData
|
||||
* @property {number} burst Count of super reactions
|
||||
* @property {number} normal Count of normal reactions
|
||||
*/
|
||||
|
||||
/**
|
||||
* The reaction count details object contains information about super and normal reaction counts.
|
||||
* @type {ReactionCountDetailsData}
|
||||
*/
|
||||
this.countDetails = {
|
||||
burst: data.count_details.burst,
|
||||
normal: data.count_details.normal,
|
||||
};
|
||||
} else {
|
||||
this.countDetails ??= { burst: 0, normal: 0 };
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the client user react with this reaction
|
||||
* @returns {Promise<MessageReaction>}
|
||||
*/
|
||||
react() {
|
||||
return this.message.react(this.emoji);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all users from this reaction.
|
||||
* @returns {Promise<MessageReaction>}
|
||||
*/
|
||||
async remove() {
|
||||
await this.client.rest.delete(
|
||||
Routes.channelMessageReaction(this.message.channelId, this.message.id, this._emoji.identifier),
|
||||
);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The emoji of this reaction. Either a {@link GuildEmoji} object for known custom emojis,
|
||||
* {@link ApplicationEmoji} for application emojis, or a {@link ReactionEmoji} object
|
||||
* which has fewer properties. Whatever the prototype of the emoji, it will still have
|
||||
* `name`, `id`, `identifier` and `toString()`
|
||||
* @type {GuildEmoji|ReactionEmoji|ApplicationEmoji}
|
||||
* @readonly
|
||||
*/
|
||||
get emoji() {
|
||||
if (this._emoji instanceof GuildEmoji) return this._emoji;
|
||||
if (this._emoji instanceof ApplicationEmoji) return this._emoji;
|
||||
// Check to see if the emoji has become known to the client
|
||||
if (this._emoji.id) {
|
||||
const applicationEmojis = this.message.client.application.emojis.cache;
|
||||
if (applicationEmojis.has(this._emoji.id)) {
|
||||
const emoji = applicationEmojis.get(this._emoji.id);
|
||||
this._emoji = emoji;
|
||||
return emoji;
|
||||
}
|
||||
const emojis = this.message.client.emojis.cache;
|
||||
if (emojis.has(this._emoji.id)) {
|
||||
const emoji = emojis.get(this._emoji.id);
|
||||
this._emoji = emoji;
|
||||
return emoji;
|
||||
}
|
||||
}
|
||||
return this._emoji;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not this reaction is a partial
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get partial() {
|
||||
return this.count === null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch this reaction.
|
||||
* @returns {Promise<MessageReaction>}
|
||||
*/
|
||||
async fetch() {
|
||||
const message = await this.message.fetch();
|
||||
const existing = message.reactions.cache.get(this.emoji.id ?? this.emoji.name);
|
||||
// The reaction won't get set when it has been completely removed
|
||||
this._patch(existing ?? { count: 0 });
|
||||
return this;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return flatten(this, { emoji: 'emojiId', message: 'messageId' });
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this._emoji.id ?? this._emoji.name;
|
||||
}
|
||||
|
||||
_add(user, burst) {
|
||||
if (this.partial) return;
|
||||
this.users.cache.set(user.id, user);
|
||||
if (!this.me || user.id !== this.message.client.user.id || this.count === 0) {
|
||||
this.count++;
|
||||
if (burst) this.countDetails.burst++;
|
||||
else this.countDetails.normal++;
|
||||
}
|
||||
if (user.id === this.message.client.user.id) {
|
||||
if (burst) this.meBurst = true;
|
||||
else this.me = true;
|
||||
}
|
||||
}
|
||||
_remove(user, burst) {
|
||||
if (this.partial) return;
|
||||
this.users.cache.delete(user.id);
|
||||
if (!this.me || user.id !== this.message.client.user.id) {
|
||||
this.count--;
|
||||
if (burst) this.countDetails.burst--;
|
||||
else this.countDetails.normal--;
|
||||
}
|
||||
if (user.id === this.message.client.user.id) {
|
||||
if (burst) this.meBurst = false;
|
||||
else this.me = false;
|
||||
}
|
||||
if (this.count <= 0 && this.users.cache.size === 0) {
|
||||
this.message.reactions.cache.delete(this.emoji.id ?? this.emoji.name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MessageReaction;
|
||||
36
node_modules/discord.js/src/structures/ModalBuilder.js
generated
vendored
Normal file
36
node_modules/discord.js/src/structures/ModalBuilder.js
generated
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
'use strict';
|
||||
|
||||
const { ModalBuilder: BuildersModal, ComponentBuilder } = require('@discordjs/builders');
|
||||
const { isJSONEncodable } = require('@discordjs/util');
|
||||
const { toSnakeCase } = require('../util/Transformers');
|
||||
|
||||
/**
|
||||
* Represents a modal builder.
|
||||
* @extends {BuildersModal}
|
||||
*/
|
||||
class ModalBuilder extends BuildersModal {
|
||||
constructor({ components, ...data } = {}) {
|
||||
super({
|
||||
...toSnakeCase(data),
|
||||
components: components?.map(component =>
|
||||
component instanceof ComponentBuilder ? component : toSnakeCase(component),
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new modal builder from JSON data
|
||||
* @param {ModalBuilder|APIModalComponent} other The other data
|
||||
* @returns {ModalBuilder}
|
||||
*/
|
||||
static from(other) {
|
||||
return new this(isJSONEncodable(other) ? other.toJSON() : other);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ModalBuilder;
|
||||
|
||||
/**
|
||||
* @external BuildersModal
|
||||
* @see {@link https://discord.js.org/docs/packages/builders/stable/ModalBuilder:Class}
|
||||
*/
|
||||
232
node_modules/discord.js/src/structures/ModalSubmitFields.js
generated
vendored
Normal file
232
node_modules/discord.js/src/structures/ModalSubmitFields.js
generated
vendored
Normal file
@@ -0,0 +1,232 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { ComponentType } = require('discord-api-types/v10');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
|
||||
/**
|
||||
* @typedef {Object} ModalSelectedMentionables
|
||||
* @property {Collection<Snowflake, User>} users The selected users
|
||||
* @property {Collection<Snowflake, GuildMember | APIGuildMember>} members The selected members
|
||||
* @property {Collection<Snowflake, Role | APIRole>} roles The selected roles
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents the serialized fields from a modal submit interaction
|
||||
*/
|
||||
class ModalSubmitFields {
|
||||
constructor(components, resolved) {
|
||||
/**
|
||||
* The components within the modal
|
||||
*
|
||||
* @type {Array<ActionRowModalData|LabelModalData|TextDisplayModalData>}
|
||||
*/
|
||||
this.components = components;
|
||||
|
||||
/**
|
||||
* The interaction resolved data
|
||||
*
|
||||
* @name ModalSubmitFields#resolved
|
||||
* @type {?Readonly<BaseInteractionResolvedData>}
|
||||
*/
|
||||
Object.defineProperty(this, 'resolved', { value: resolved ? Object.freeze(resolved) : null });
|
||||
|
||||
/**
|
||||
* The extracted fields from the modal
|
||||
* @type {Collection<string, ModalData>}
|
||||
*/
|
||||
this.fields = components.reduce((accumulator, next) => {
|
||||
// For legacy support of action rows
|
||||
if ('components' in next) {
|
||||
for (const component of next.components) accumulator.set(component.customId, component);
|
||||
}
|
||||
|
||||
// For label components
|
||||
if ('component' in next) {
|
||||
accumulator.set(next.component.customId, next.component);
|
||||
}
|
||||
|
||||
return accumulator;
|
||||
}, new Collection());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a field given a custom id from a component
|
||||
* @param {string} customId The custom id of the component
|
||||
* @param {ComponentType} [type] The type of the component
|
||||
* @returns {ModalData}
|
||||
*/
|
||||
getField(customId, type) {
|
||||
const field = this.fields.get(customId);
|
||||
if (!field) throw new DiscordjsTypeError(ErrorCodes.ModalSubmitInteractionFieldNotFound, customId);
|
||||
|
||||
if (type !== undefined && type !== field.type) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.ModalSubmitInteractionFieldType, customId, field.type, type);
|
||||
}
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a component by custom id and property and checks its type.
|
||||
*
|
||||
* @param {string} customId The custom id of the component.
|
||||
* @param {ComponentType[]} allowedTypes The allowed types of the component.
|
||||
* @param {string[]} properties The properties to check for for `required`.
|
||||
* @param {boolean} required Whether to throw an error if the component value(s) are not found.
|
||||
* @returns {ModalData} The option, if found.
|
||||
* @private
|
||||
*/
|
||||
_getTypedComponent(customId, allowedTypes, properties, required) {
|
||||
const component = this.getField(customId);
|
||||
if (!allowedTypes.includes(component.type)) {
|
||||
throw new DiscordjsTypeError(
|
||||
ErrorCodes.ModalSubmitInteractionFieldNotFound,
|
||||
customId,
|
||||
component.type,
|
||||
allowedTypes.join(', '),
|
||||
);
|
||||
} else if (required && properties.every(prop => component[prop] === null || component[prop] === undefined)) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.ModalSubmitInteractionFieldEmpty, customId, component.type);
|
||||
}
|
||||
|
||||
return component;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of a text input component given a custom id
|
||||
* @param {string} customId The custom id of the text input component
|
||||
* @returns {string}
|
||||
*/
|
||||
getTextInputValue(customId) {
|
||||
return this._getTypedComponent(customId, [ComponentType.TextInput]).value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the values of a string select component given a custom id
|
||||
*
|
||||
* @param {string} customId The custom id of the string select component
|
||||
* @returns {string[]}
|
||||
*/
|
||||
getStringSelectValues(customId) {
|
||||
return this._getTypedComponent(customId, [ComponentType.StringSelect]).values;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets users component
|
||||
*
|
||||
* @param {string} customId The custom id of the component
|
||||
* @param {boolean} [required=false] Whether to throw an error if the component value is not found or empty
|
||||
* @returns {?Collection<Snowflake, User>} The selected users, or null if none were selected and not required
|
||||
*/
|
||||
getSelectedUsers(customId, required = false) {
|
||||
const component = this._getTypedComponent(
|
||||
customId,
|
||||
[ComponentType.UserSelect, ComponentType.MentionableSelect],
|
||||
['users'],
|
||||
required,
|
||||
);
|
||||
return component.users ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets roles component
|
||||
*
|
||||
* @param {string} customId The custom id of the component
|
||||
* @param {boolean} [required=false] Whether to throw an error if the component value is not found or empty
|
||||
* @returns {?Collection<Snowflake, Role|APIRole>} The selected roles, or null if none were selected and not required
|
||||
*/
|
||||
getSelectedRoles(customId, required = false) {
|
||||
const component = this._getTypedComponent(
|
||||
customId,
|
||||
[ComponentType.RoleSelect, ComponentType.MentionableSelect],
|
||||
['roles'],
|
||||
required,
|
||||
);
|
||||
return component.roles ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets channels component
|
||||
*
|
||||
* @param {string} customId The custom id of the component
|
||||
* @param {boolean} [required=false] Whether to throw an error if the component value is not found or empty
|
||||
* @param {ChannelType[]} [channelTypes=[]] The allowed types of channels. If empty, all channel types are allowed.
|
||||
* @returns {?Collection<Snowflake, GuildChannel|ThreadChannel|APIChannel>} The selected channels,
|
||||
* or null if none were selected and not required
|
||||
*/
|
||||
getSelectedChannels(customId, required = false, channelTypes = []) {
|
||||
const component = this._getTypedComponent(customId, [ComponentType.ChannelSelect], ['channels'], required);
|
||||
const channels = component.channels;
|
||||
if (channels && channelTypes.length > 0) {
|
||||
for (const channel of channels.values()) {
|
||||
if (!channelTypes.includes(channel.type)) {
|
||||
throw new DiscordjsTypeError(
|
||||
ErrorCodes.ModalSubmitInteractionComponentInvalidChannelType,
|
||||
customId,
|
||||
channel.type,
|
||||
channelTypes.join(', '),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return channels ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets members component
|
||||
*
|
||||
* @param {string} customId The custom id of the component
|
||||
* @returns {?Collection<Snowflake, GuildMember|APIGuildMember>} The selected members,
|
||||
* or null if none were selected or the users were not present in the guild
|
||||
*/
|
||||
getSelectedMembers(customId) {
|
||||
const component = this._getTypedComponent(
|
||||
customId,
|
||||
[ComponentType.UserSelect, ComponentType.MentionableSelect],
|
||||
['members'],
|
||||
false,
|
||||
);
|
||||
return component.members ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets mentionables component
|
||||
*
|
||||
* @param {string} customId The custom id of the component
|
||||
* @param {boolean} [required=false] Whether to throw an error if the component value is not found or empty
|
||||
* @returns {?ModalSelectedMentionables} The selected mentionables, or null if none were selected and not required
|
||||
*/
|
||||
getSelectedMentionables(customId, required = false) {
|
||||
const component = this._getTypedComponent(
|
||||
customId,
|
||||
[ComponentType.MentionableSelect],
|
||||
['users', 'members', 'roles'],
|
||||
required,
|
||||
);
|
||||
|
||||
if (component.users || component.members || component.roles) {
|
||||
return {
|
||||
users: component.users ?? new Collection(),
|
||||
members: component.members ?? new Collection(),
|
||||
roles: component.roles ?? new Collection(),
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets file upload component
|
||||
*
|
||||
* @param {string} customId The custom id of the component
|
||||
* @param {boolean} [required=false] Whether to throw an error if the component value is not found or empty
|
||||
* @returns {?Collection<Snowflake, Attachment>} The uploaded files, or null if none were uploaded and not required
|
||||
*/
|
||||
getUploadedFiles(customId, required = false) {
|
||||
return this._getTypedComponent(customId, [ComponentType.FileUpload], ['attachments'], required).attachments ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ModalSubmitFields;
|
||||
256
node_modules/discord.js/src/structures/ModalSubmitInteraction.js
generated
vendored
Normal file
256
node_modules/discord.js/src/structures/ModalSubmitInteraction.js
generated
vendored
Normal file
@@ -0,0 +1,256 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { lazy } = require('@discordjs/util');
|
||||
const BaseInteraction = require('./BaseInteraction');
|
||||
const InteractionWebhook = require('./InteractionWebhook');
|
||||
const ModalSubmitFields = require('./ModalSubmitFields');
|
||||
const InteractionResponses = require('./interfaces/InteractionResponses');
|
||||
const { transformResolved } = require('../util/Util');
|
||||
|
||||
const getMessage = lazy(() => require('./Message').Message);
|
||||
const getAttachment = lazy(() => require('./Attachment'));
|
||||
|
||||
/**
|
||||
* @typedef {Object} BaseModalData
|
||||
* @property {ComponentType} type The component type of the field
|
||||
* @property {number} id The id of the field
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {BaseModalData} FileUploadModalData
|
||||
* @property {string} customId The custom id of the file upload
|
||||
* @property {Snowflake[]} values The values of the file upload
|
||||
* @property {Collection<Snowflake, Attachment>} [attachments] The resolved attachments
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {BaseModalData} TextInputModalData
|
||||
* @property {string} customId The custom id of the field
|
||||
* @property {string} value The value of the field
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {BaseModalData} SelectMenuModalData
|
||||
* @property {string} customId The custom id of the field
|
||||
* @property {string[]} values The values of the field
|
||||
* @property {Collection<Snowflake, GuildMember|APIGuildMember>} [members] The resolved members
|
||||
* @property {Collection<Snowflake, User|APIUser>} [users] The resolved users
|
||||
* @property {Collection<Snowflake, Role|APIRole>} [roles] The resolved roles
|
||||
* @property {Collection<Snowflake, BaseChannel|APIChannel>} [channels] The resolved channels
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {BaseModalData} TextDisplayModalData
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {SelectMenuModalData|TextInputModalData|FileUploadModalData} ModalData
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {BaseModalData} LabelModalData
|
||||
* @property {ModalData} component The component within the label
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {BaseModalData} ActionRowModalData
|
||||
* @property {TextInputModalData[]} components The components of this action row
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a modal interaction
|
||||
* @extends {BaseInteraction}
|
||||
* @implements {InteractionResponses}
|
||||
*/
|
||||
class ModalSubmitInteraction extends BaseInteraction {
|
||||
constructor(client, data) {
|
||||
super(client, data);
|
||||
/**
|
||||
* The custom id of the modal.
|
||||
* @type {string}
|
||||
*/
|
||||
this.customId = data.data.custom_id;
|
||||
|
||||
if ('message' in data) {
|
||||
/**
|
||||
* The message associated with this interaction
|
||||
* @type {?Message}
|
||||
*/
|
||||
this.message = this.channel?.messages._add(data.message) ?? new (getMessage())(this.client, data.message);
|
||||
} else {
|
||||
this.message = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The components within the modal
|
||||
*
|
||||
* @type {Array<ActionRowModalData | LabelModalData | TextDisplayModalData>}
|
||||
*/
|
||||
this.components = data.data.components?.map(component =>
|
||||
ModalSubmitInteraction.transformComponent(component, data.data.resolved, {
|
||||
client: this.client,
|
||||
guild: this.guild,
|
||||
}),
|
||||
);
|
||||
|
||||
/**
|
||||
* The fields within the modal
|
||||
* @type {ModalSubmitFields}
|
||||
*/
|
||||
this.fields = new ModalSubmitFields(
|
||||
this.components,
|
||||
transformResolved({ client: this.client, guild: this.guild, channel: this.channel }, data.data.resolved),
|
||||
);
|
||||
|
||||
/**
|
||||
* Whether the reply to this interaction has been deferred
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.deferred = false;
|
||||
|
||||
/**
|
||||
* Whether this interaction has already been replied to
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.replied = false;
|
||||
|
||||
/**
|
||||
* Whether the reply to this interaction is ephemeral
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.ephemeral = null;
|
||||
|
||||
/**
|
||||
* An associated interaction webhook, can be used to further interact with this interaction
|
||||
* @type {InteractionWebhook}
|
||||
*/
|
||||
this.webhook = new InteractionWebhook(this.client, this.applicationId, this.token);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms component data to discord.js-compatible data
|
||||
* @param {*} rawComponent The data to transform
|
||||
* @param {APIInteractionDataResolved} [resolved] The resolved data for the interaction
|
||||
* @param {*} [extra] Extra data required for the transformation
|
||||
* @returns {ModalData[]}
|
||||
*/
|
||||
static transformComponent(rawComponent, resolved, { client, guild } = {}) {
|
||||
if ('components' in rawComponent) {
|
||||
return {
|
||||
type: rawComponent.type,
|
||||
id: rawComponent.id,
|
||||
components: rawComponent.components.map(component =>
|
||||
this.transformComponent(component, resolved, { client, guild }),
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
if ('component' in rawComponent) {
|
||||
return {
|
||||
type: rawComponent.type,
|
||||
id: rawComponent.id,
|
||||
component: this.transformComponent(rawComponent.component, resolved, { client, guild }),
|
||||
};
|
||||
}
|
||||
|
||||
const data = {
|
||||
type: rawComponent.type,
|
||||
id: rawComponent.id,
|
||||
};
|
||||
|
||||
// Text display components do not have custom ids.
|
||||
if ('custom_id' in rawComponent) data.customId = rawComponent.custom_id;
|
||||
|
||||
if ('value' in rawComponent) data.value = rawComponent.value;
|
||||
|
||||
if (rawComponent.values) {
|
||||
data.values = rawComponent.values;
|
||||
|
||||
/* eslint-disable max-depth */
|
||||
if (resolved) {
|
||||
const { members, users, channels, roles, attachments } = resolved;
|
||||
const valueSet = new Set(rawComponent.values);
|
||||
|
||||
if (users) {
|
||||
data.users = new Collection();
|
||||
|
||||
for (const [id, user] of Object.entries(users)) {
|
||||
if (valueSet.has(id)) {
|
||||
data.users.set(id, client.users._add(user));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (channels) {
|
||||
data.channels = new Collection();
|
||||
|
||||
for (const [id, apiChannel] of Object.entries(channels)) {
|
||||
if (valueSet.has(id)) {
|
||||
data.channels.set(id, client.channels._add(apiChannel, guild) ?? apiChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (members) {
|
||||
data.members = new Collection();
|
||||
|
||||
for (const [id, member] of Object.entries(members)) {
|
||||
if (valueSet.has(id)) {
|
||||
const user = users?.[id];
|
||||
data.members.set(id, guild?.members._add({ user, ...member }) ?? member);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (roles) {
|
||||
data.roles = new Collection();
|
||||
|
||||
for (const [id, role] of Object.entries(roles)) {
|
||||
if (valueSet.has(id)) {
|
||||
data.roles.set(id, guild?.roles._add(role) ?? role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (attachments) {
|
||||
data.attachments = new Collection();
|
||||
for (const [id, attachment] of Object.entries(attachments)) {
|
||||
if (valueSet.has(id)) {
|
||||
data.attachments.set(id, new (getAttachment())(attachment));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* eslint-enable max-depth */
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this is from a {@link MessageComponentInteraction}.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isFromMessage() {
|
||||
return Boolean(this.message);
|
||||
}
|
||||
|
||||
// These are here only for documentation purposes - they are implemented by InteractionResponses
|
||||
/* eslint-disable no-empty-function */
|
||||
deferReply() {}
|
||||
reply() {}
|
||||
fetchReply() {}
|
||||
editReply() {}
|
||||
deleteReply() {}
|
||||
followUp() {}
|
||||
deferUpdate() {}
|
||||
update() {}
|
||||
sendPremiumRequired() {}
|
||||
launchActivity() {}
|
||||
}
|
||||
|
||||
InteractionResponses.applyToClass(ModalSubmitInteraction, 'showModal');
|
||||
|
||||
module.exports = ModalSubmitInteraction;
|
||||
32
node_modules/discord.js/src/structures/NewsChannel.js
generated
vendored
Normal file
32
node_modules/discord.js/src/structures/NewsChannel.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
'use strict';
|
||||
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const BaseGuildTextChannel = require('./BaseGuildTextChannel');
|
||||
const { DiscordjsError, ErrorCodes } = require('../errors');
|
||||
|
||||
/**
|
||||
* Represents a guild news channel on Discord.
|
||||
* @extends {BaseGuildTextChannel}
|
||||
*/
|
||||
class NewsChannel extends BaseGuildTextChannel {
|
||||
/**
|
||||
* Adds the target to this channel's followers.
|
||||
* @param {TextChannelResolvable} channel The channel where the webhook should be created
|
||||
* @param {string} [reason] Reason for creating the webhook
|
||||
* @returns {Promise<NewsChannel>}
|
||||
* @example
|
||||
* if (channel.type === ChannelType.GuildAnnouncement) {
|
||||
* channel.addFollower('222197033908436994', 'Important announcements')
|
||||
* .then(() => console.log('Added follower'))
|
||||
* .catch(console.error);
|
||||
* }
|
||||
*/
|
||||
async addFollower(channel, reason) {
|
||||
const channelId = this.guild.channels.resolveId(channel);
|
||||
if (!channelId) throw new DiscordjsError(ErrorCodes.GuildChannelResolve);
|
||||
await this.client.rest.post(Routes.channelFollowers(this.id), { body: { webhook_channel_id: channelId }, reason });
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = NewsChannel;
|
||||
28
node_modules/discord.js/src/structures/OAuth2Guild.js
generated
vendored
Normal file
28
node_modules/discord.js/src/structures/OAuth2Guild.js
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
'use strict';
|
||||
|
||||
const BaseGuild = require('./BaseGuild');
|
||||
const PermissionsBitField = require('../util/PermissionsBitField');
|
||||
|
||||
/**
|
||||
* A partial guild received when using {@link GuildManager#fetch} to fetch multiple guilds.
|
||||
* @extends {BaseGuild}
|
||||
*/
|
||||
class OAuth2Guild extends BaseGuild {
|
||||
constructor(client, data) {
|
||||
super(client, data);
|
||||
|
||||
/**
|
||||
* Whether the client user is the owner of the guild
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.owner = data.owner;
|
||||
|
||||
/**
|
||||
* The permissions that the client user has in this guild
|
||||
* @type {Readonly<PermissionsBitField>}
|
||||
*/
|
||||
this.permissions = new PermissionsBitField(BigInt(data.permissions)).freeze();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = OAuth2Guild;
|
||||
131
node_modules/discord.js/src/structures/PartialGroupDMChannel.js
generated
vendored
Normal file
131
node_modules/discord.js/src/structures/PartialGroupDMChannel.js
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
'use strict';
|
||||
|
||||
const { BaseChannel } = require('./BaseChannel');
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const { DiscordjsError, ErrorCodes } = require('../errors');
|
||||
const PartialGroupDMMessageManager = require('../managers/PartialGroupDMMessageManager');
|
||||
|
||||
/**
|
||||
* Represents a Partial Group DM Channel on Discord.
|
||||
* @extends {BaseChannel}
|
||||
* @implements {TextBasedChannel}
|
||||
*/
|
||||
class PartialGroupDMChannel extends BaseChannel {
|
||||
constructor(client, data) {
|
||||
super(client, data);
|
||||
|
||||
// No flags are present when fetching partial group DM channels.
|
||||
this.flags = null;
|
||||
|
||||
/**
|
||||
* The name of this Group DM Channel
|
||||
* @type {?string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* The hash of the channel icon
|
||||
* @type {?string}
|
||||
*/
|
||||
this.icon = data.icon ?? null;
|
||||
|
||||
/**
|
||||
* Recipient data received in a {@link PartialGroupDMChannel}.
|
||||
* @typedef {Object} PartialRecipient
|
||||
* @property {string} username The username of the recipient
|
||||
*/
|
||||
|
||||
/**
|
||||
* The recipients of this Group DM Channel.
|
||||
* @type {PartialRecipient[]}
|
||||
*/
|
||||
this.recipients = data.recipients ?? [];
|
||||
|
||||
/**
|
||||
* A manager of the messages belonging to this channel
|
||||
* @type {PartialGroupDMMessageManager}
|
||||
*/
|
||||
this.messages = new PartialGroupDMMessageManager(this);
|
||||
|
||||
if ('owner_id' in data) {
|
||||
/**
|
||||
* The user id of the owner of this Group DM Channel
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.ownerId = data.owner_id;
|
||||
} else {
|
||||
this.ownerId ??= null;
|
||||
}
|
||||
|
||||
if ('last_message_id' in data) {
|
||||
/**
|
||||
* The channel's last message id, if one was sent
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.lastMessageId = data.last_message_id;
|
||||
} else {
|
||||
this.lastMessageId ??= null;
|
||||
}
|
||||
|
||||
if ('last_pin_timestamp' in data) {
|
||||
/**
|
||||
* The timestamp when the last pinned message was pinned, if there was one
|
||||
* @type {?number}
|
||||
*/
|
||||
this.lastPinTimestamp = data.last_pin_timestamp ? Date.parse(data.last_pin_timestamp) : null;
|
||||
} else {
|
||||
this.lastPinTimestamp ??= null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL to this channel's icon.
|
||||
* @param {ImageURLOptions} [options={}] Options for the image URL
|
||||
* @returns {?string}
|
||||
*/
|
||||
iconURL(options = {}) {
|
||||
return this.icon && this.client.rest.cdn.channelIcon(this.id, this.icon, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the owner of this Group DM Channel.
|
||||
* @param {BaseFetchOptions} [options] The options for fetching the user
|
||||
* @returns {Promise<User>}
|
||||
*/
|
||||
async fetchOwner(options) {
|
||||
if (!this.ownerId) {
|
||||
throw new DiscordjsError(ErrorCodes.FetchOwnerId, 'group DM');
|
||||
}
|
||||
|
||||
return this.client.users.fetch(this.ownerId, options);
|
||||
}
|
||||
|
||||
async delete() {
|
||||
throw new DiscordjsError(ErrorCodes.DeleteGroupDMChannel);
|
||||
}
|
||||
|
||||
async fetch() {
|
||||
throw new DiscordjsError(ErrorCodes.FetchGroupDMChannel);
|
||||
}
|
||||
|
||||
// These are here only for documentation purposes - they are implemented by TextBasedChannel
|
||||
/* eslint-disable no-empty-function */
|
||||
get lastMessage() {}
|
||||
get lastPinAt() {}
|
||||
createMessageComponentCollector() {}
|
||||
awaitMessageComponent() {}
|
||||
}
|
||||
|
||||
TextBasedChannel.applyToClass(PartialGroupDMChannel, true, [
|
||||
'bulkDelete',
|
||||
'send',
|
||||
'sendTyping',
|
||||
'createMessageCollector',
|
||||
'awaitMessages',
|
||||
'fetchWebhooks',
|
||||
'createWebhook',
|
||||
'setRateLimitPerUser',
|
||||
'setNSFW',
|
||||
]);
|
||||
|
||||
module.exports = PartialGroupDMChannel;
|
||||
199
node_modules/discord.js/src/structures/PermissionOverwrites.js
generated
vendored
Normal file
199
node_modules/discord.js/src/structures/PermissionOverwrites.js
generated
vendored
Normal file
@@ -0,0 +1,199 @@
|
||||
'use strict';
|
||||
|
||||
const { OverwriteType } = require('discord-api-types/v10');
|
||||
const Base = require('./Base');
|
||||
const { Role } = require('./Role');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
const PermissionsBitField = require('../util/PermissionsBitField');
|
||||
|
||||
/**
|
||||
* Represents a permission overwrite for a role or member in a guild channel.
|
||||
* @extends {Base}
|
||||
*/
|
||||
class PermissionOverwrites extends Base {
|
||||
constructor(client, data, channel) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The GuildChannel this overwrite is for
|
||||
* @name PermissionOverwrites#channel
|
||||
* @type {GuildChannel}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'channel', { value: channel });
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
/**
|
||||
* The overwrite's id, either a {@link User} or a {@link Role} id
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
if ('type' in data) {
|
||||
/**
|
||||
* The type of this overwrite
|
||||
* @type {OverwriteType}
|
||||
*/
|
||||
this.type = data.type;
|
||||
}
|
||||
|
||||
if ('deny' in data) {
|
||||
/**
|
||||
* The permissions that are denied for the user or role.
|
||||
* @type {Readonly<PermissionsBitField>}
|
||||
*/
|
||||
this.deny = new PermissionsBitField(BigInt(data.deny)).freeze();
|
||||
}
|
||||
|
||||
if ('allow' in data) {
|
||||
/**
|
||||
* The permissions that are allowed for the user or role.
|
||||
* @type {Readonly<PermissionsBitField>}
|
||||
*/
|
||||
this.allow = new PermissionsBitField(BigInt(data.allow)).freeze();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits this Permission Overwrite.
|
||||
* @param {PermissionOverwriteOptions} options The options for the update
|
||||
* @param {string} [reason] Reason for creating/editing this overwrite
|
||||
* @returns {Promise<PermissionOverwrites>}
|
||||
* @example
|
||||
* // Update permission overwrites
|
||||
* permissionOverwrites.edit({
|
||||
* SendMessages: false
|
||||
* })
|
||||
* .then(channel => console.log(channel.permissionOverwrites.get(message.author.id)))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async edit(options, reason) {
|
||||
await this.channel.permissionOverwrites.upsert(this.id, options, { type: this.type, reason }, this);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this Permission Overwrite.
|
||||
* @param {string} [reason] Reason for deleting this overwrite
|
||||
* @returns {Promise<PermissionOverwrites>}
|
||||
*/
|
||||
async delete(reason) {
|
||||
await this.channel.permissionOverwrites.delete(this.id, reason);
|
||||
return this;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return {
|
||||
id: this.id,
|
||||
type: this.type,
|
||||
allow: this.allow,
|
||||
deny: this.deny,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* An object mapping permission flags to `true` (enabled), `null` (unset) or `false` (disabled).
|
||||
* ```js
|
||||
* {
|
||||
* 'SendMessages': true,
|
||||
* 'EmbedLinks': null,
|
||||
* 'AttachFiles': false,
|
||||
* }
|
||||
* ```
|
||||
* @typedef {Object} PermissionOverwriteOptions
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ResolvedOverwriteOptions
|
||||
* @property {PermissionsBitField} allow The allowed permissions
|
||||
* @property {PermissionsBitField} deny The denied permissions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves bitfield permissions overwrites from an object.
|
||||
* @param {PermissionOverwriteOptions} options The options for the update
|
||||
* @param {ResolvedOverwriteOptions} initialPermissions The initial permissions
|
||||
* @returns {ResolvedOverwriteOptions}
|
||||
*/
|
||||
static resolveOverwriteOptions(options, { allow, deny } = {}) {
|
||||
allow = new PermissionsBitField(allow);
|
||||
deny = new PermissionsBitField(deny);
|
||||
|
||||
for (const [perm, value] of Object.entries(options)) {
|
||||
if (value === true) {
|
||||
allow.add(perm);
|
||||
deny.remove(perm);
|
||||
} else if (value === false) {
|
||||
allow.remove(perm);
|
||||
deny.add(perm);
|
||||
} else if (value === null) {
|
||||
allow.remove(perm);
|
||||
deny.remove(perm);
|
||||
}
|
||||
}
|
||||
|
||||
return { allow, deny };
|
||||
}
|
||||
|
||||
/**
|
||||
* The raw data for a permission overwrite
|
||||
* @typedef {Object} RawOverwriteData
|
||||
* @property {Snowflake} id The id of the {@link Role} or {@link User} this overwrite belongs to
|
||||
* @property {string} allow The permissions to allow
|
||||
* @property {string} deny The permissions to deny
|
||||
* @property {number} type The type of this OverwriteData
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data that can be resolved into {@link APIOverwrite}. This can be:
|
||||
* * PermissionOverwrites
|
||||
* * OverwriteData
|
||||
* @typedef {PermissionOverwrites|OverwriteData} OverwriteResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data that can be used for a permission overwrite
|
||||
* @typedef {Object} OverwriteData
|
||||
* @property {GuildMemberResolvable|RoleResolvable} id Member or role this overwrite is for
|
||||
* @property {PermissionResolvable} [allow] The permissions to allow
|
||||
* @property {PermissionResolvable} [deny] The permissions to deny
|
||||
* @property {OverwriteType} [type] The type of this OverwriteData
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves an overwrite into {@link APIOverwrite}.
|
||||
* @param {OverwriteResolvable} overwrite The overwrite-like data to resolve
|
||||
* @param {Guild} [guild] The guild to resolve from
|
||||
* @returns {RawOverwriteData}
|
||||
*/
|
||||
static resolve(overwrite, guild) {
|
||||
if (overwrite instanceof this) return overwrite.toJSON();
|
||||
if (typeof overwrite.id === 'string' && overwrite.type in OverwriteType) {
|
||||
return {
|
||||
id: overwrite.id,
|
||||
type: overwrite.type,
|
||||
allow: PermissionsBitField.resolve(overwrite.allow ?? PermissionsBitField.DefaultBit).toString(),
|
||||
deny: PermissionsBitField.resolve(overwrite.deny ?? PermissionsBitField.DefaultBit).toString(),
|
||||
};
|
||||
}
|
||||
|
||||
const userOrRole = guild.roles.resolve(overwrite.id) ?? guild.client.users.resolve(overwrite.id);
|
||||
if (!userOrRole) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'parameter', 'cached User or Role');
|
||||
}
|
||||
|
||||
const type = userOrRole instanceof Role ? OverwriteType.Role : OverwriteType.Member;
|
||||
|
||||
return {
|
||||
id: userOrRole.id,
|
||||
type,
|
||||
allow: PermissionsBitField.resolve(overwrite.allow ?? PermissionsBitField.DefaultBit).toString(),
|
||||
deny: PermissionsBitField.resolve(overwrite.deny ?? PermissionsBitField.DefaultBit).toString(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PermissionOverwrites;
|
||||
175
node_modules/discord.js/src/structures/Poll.js
generated
vendored
Normal file
175
node_modules/discord.js/src/structures/Poll.js
generated
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const Base = require('./Base');
|
||||
const { PollAnswer } = require('./PollAnswer');
|
||||
const { DiscordjsError } = require('../errors/DJSError');
|
||||
const { ErrorCodes } = require('../errors/index');
|
||||
|
||||
/**
|
||||
* Represents a Poll
|
||||
* @extends {Base}
|
||||
*/
|
||||
class Poll extends Base {
|
||||
constructor(client, data, message, channel) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The id of the channel that this poll is in
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.channelId = data.channel_id ?? channel.id;
|
||||
|
||||
/**
|
||||
* The channel that this poll is in
|
||||
* @name Poll#channel
|
||||
* @type {TextBasedChannel}
|
||||
* @readonly
|
||||
*/
|
||||
|
||||
Object.defineProperty(this, 'channel', { value: channel });
|
||||
|
||||
/**
|
||||
* The id of the message that started this poll
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.messageId = data.message_id ?? message.id;
|
||||
|
||||
/**
|
||||
* The message that started this poll
|
||||
* @name Poll#message
|
||||
* @type {Message}
|
||||
* @readonly
|
||||
*/
|
||||
|
||||
Object.defineProperty(this, 'message', { value: message });
|
||||
|
||||
/**
|
||||
* The answers of this poll
|
||||
* @type {Collection<number, PollAnswer|PartialPollAnswer>}
|
||||
*/
|
||||
this.answers = new Collection();
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
if (data.answers) {
|
||||
for (const answer of data.answers) {
|
||||
const existing = this.answers.get(answer.answer_id);
|
||||
if (existing) {
|
||||
existing._patch(answer);
|
||||
} else {
|
||||
this.answers.set(answer.answer_id, new PollAnswer(this.client, answer, this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (data.results) {
|
||||
/**
|
||||
* Whether this poll's results have been precisely counted
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.resultsFinalized = data.results.is_finalized;
|
||||
|
||||
for (const answerResult of data.results.answer_counts) {
|
||||
const answer = this.answers.get(answerResult.id);
|
||||
answer?._patch(answerResult);
|
||||
}
|
||||
} else {
|
||||
this.resultsFinalized ??= false;
|
||||
}
|
||||
|
||||
if ('allow_multiselect' in data) {
|
||||
/**
|
||||
* Whether this poll allows multiple answers
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.allowMultiselect = data.allow_multiselect;
|
||||
} else {
|
||||
this.allowMultiselect ??= null;
|
||||
}
|
||||
|
||||
if ('layout_type' in data) {
|
||||
/**
|
||||
* The layout type of this poll
|
||||
* @type {PollLayoutType}
|
||||
*/
|
||||
this.layoutType = data.layout_type;
|
||||
} else {
|
||||
this.layoutType ??= null;
|
||||
}
|
||||
|
||||
if ('expiry' in data) {
|
||||
/**
|
||||
* The timestamp when this poll expires
|
||||
* @type {?number}
|
||||
*/
|
||||
this.expiresTimestamp = data.expiry && Date.parse(data.expiry);
|
||||
} else {
|
||||
this.expiresTimestamp ??= null;
|
||||
}
|
||||
|
||||
if (data.question) {
|
||||
/**
|
||||
* The media for a poll's question
|
||||
* @typedef {Object} PollQuestionMedia
|
||||
* @property {?string} text The text of this question
|
||||
*/
|
||||
|
||||
/**
|
||||
* The media for this poll's question
|
||||
* @type {PollQuestionMedia}
|
||||
*/
|
||||
this.question = {
|
||||
text: data.question.text,
|
||||
};
|
||||
} else {
|
||||
this.question ??= {
|
||||
text: null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The date when this poll expires
|
||||
* @type {?Date}
|
||||
* @readonly
|
||||
*/
|
||||
get expiresAt() {
|
||||
return this.expiresTimestamp && new Date(this.expiresTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this poll is a partial
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get partial() {
|
||||
return this.allowMultiselect === null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the message that started this poll, then updates the poll from the fetched message.
|
||||
* @returns {Promise<Poll>}
|
||||
*/
|
||||
async fetch() {
|
||||
await this.channel.messages.fetch(this.messageId);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends this poll.
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
async end() {
|
||||
if (this.expiresTimestamp !== null && Date.now() > this.expiresTimestamp) {
|
||||
throw new DiscordjsError(ErrorCodes.PollAlreadyExpired);
|
||||
}
|
||||
|
||||
return this.channel.messages.endPoll(this.messageId);
|
||||
}
|
||||
}
|
||||
|
||||
exports.Poll = Poll;
|
||||
114
node_modules/discord.js/src/structures/PollAnswer.js
generated
vendored
Normal file
114
node_modules/discord.js/src/structures/PollAnswer.js
generated
vendored
Normal file
@@ -0,0 +1,114 @@
|
||||
'use strict';
|
||||
|
||||
const process = require('node:process');
|
||||
const Base = require('./Base.js');
|
||||
const { Emoji } = require('./Emoji.js');
|
||||
const { PollAnswerVoterManager } = require('../managers/PollAnswerVoterManager.js');
|
||||
|
||||
let deprecationEmittedForFetchVoters = false;
|
||||
|
||||
/**
|
||||
* Represents an answer to a {@link Poll}
|
||||
* @extends {Base}
|
||||
*/
|
||||
class PollAnswer extends Base {
|
||||
constructor(client, data, poll) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The {@link Poll} this answer is part of
|
||||
* @name PollAnswer#poll
|
||||
* @type {Poll|PartialPoll}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'poll', { value: poll });
|
||||
|
||||
/**
|
||||
* The id of this answer
|
||||
* @type {number}
|
||||
*/
|
||||
this.id = data.answer_id;
|
||||
|
||||
/**
|
||||
* The manager of the voters for this answer
|
||||
* @type {PollAnswerVoterManager}
|
||||
*/
|
||||
this.voters = new PollAnswerVoterManager(this);
|
||||
|
||||
/**
|
||||
* The raw emoji of this answer
|
||||
* @name PollAnswer#_emoji
|
||||
* @type {?APIPartialEmoji}
|
||||
* @private
|
||||
*/
|
||||
Object.defineProperty(this, '_emoji', { value: null, writable: true });
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
// This `count` field comes from `poll.results.answer_counts`
|
||||
if ('count' in data) {
|
||||
/**
|
||||
* The amount of votes this answer has
|
||||
* @type {number}
|
||||
*/
|
||||
this.voteCount = data.count;
|
||||
} else {
|
||||
this.voteCount ??= this.voters.cache.size;
|
||||
}
|
||||
|
||||
/**
|
||||
* The text of this answer
|
||||
* @type {?string}
|
||||
*/
|
||||
this.text ??= data.poll_media?.text ?? null;
|
||||
|
||||
if (data.poll_media?.emoji) {
|
||||
this._emoji = data.poll_media.emoji;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The emoji of this answer
|
||||
* @type {?(GuildEmoji|Emoji)}
|
||||
*/
|
||||
get emoji() {
|
||||
if (!this._emoji || (!this._emoji.id && !this._emoji.name)) return null;
|
||||
return this.client.emojis.cache.get(this._emoji.id) ?? new Emoji(this.client, this._emoji);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this poll answer is a partial.
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get partial() {
|
||||
return this.poll.partial || (this.text === null && this.emoji === null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used for fetching voters of a poll answer.
|
||||
* @typedef {Object} BaseFetchPollAnswerVotersOptions
|
||||
* @property {number} [limit] The maximum number of voters to fetch
|
||||
* @property {Snowflake} [after] The user id to fetch voters after
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetches the users that voted for this answer.
|
||||
* @param {BaseFetchPollAnswerVotersOptions} [options={}] The options for fetching voters
|
||||
* @returns {Promise<Collection<Snowflake, User>>}
|
||||
* @deprecated Use {@link PollAnswerVoterManager#fetch} instead
|
||||
*/
|
||||
fetchVoters({ after, limit } = {}) {
|
||||
if (!deprecationEmittedForFetchVoters) {
|
||||
process.emitWarning('PollAnswer#fetchVoters is deprecated. Use PollAnswer#voters#fetch instead.');
|
||||
|
||||
deprecationEmittedForFetchVoters = true;
|
||||
}
|
||||
|
||||
return this.voters.fetch({ after, limit });
|
||||
}
|
||||
}
|
||||
|
||||
exports.PollAnswer = PollAnswer;
|
||||
385
node_modules/discord.js/src/structures/Presence.js
generated
vendored
Normal file
385
node_modules/discord.js/src/structures/Presence.js
generated
vendored
Normal file
@@ -0,0 +1,385 @@
|
||||
'use strict';
|
||||
|
||||
const Base = require('./Base');
|
||||
const { Emoji } = require('./Emoji');
|
||||
const ActivityFlagsBitField = require('../util/ActivityFlagsBitField');
|
||||
const { flatten } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Activity sent in a message.
|
||||
* @typedef {Object} MessageActivity
|
||||
* @property {string} [partyId] Id of the party represented in activity
|
||||
* @property {MessageActivityType} type Type of activity sent
|
||||
*/
|
||||
|
||||
/**
|
||||
* The status of this presence:
|
||||
* * **`online`** - user is online
|
||||
* * **`idle`** - user is AFK
|
||||
* * **`offline`** - user is offline or invisible
|
||||
* * **`dnd`** - user is in Do Not Disturb
|
||||
* @typedef {string} PresenceStatus
|
||||
*/
|
||||
|
||||
/**
|
||||
* The status of this presence:
|
||||
* * **`online`** - user is online
|
||||
* * **`idle`** - user is AFK
|
||||
* * **`dnd`** - user is in Do Not Disturb
|
||||
* @typedef {string} ClientPresenceStatus
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a user's presence.
|
||||
* @extends {Base}
|
||||
*/
|
||||
class Presence extends Base {
|
||||
constructor(client, data = {}) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The presence's user id
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.userId = data.user.id;
|
||||
|
||||
/**
|
||||
* The guild this presence is in
|
||||
* @type {?Guild}
|
||||
*/
|
||||
this.guild = data.guild ?? null;
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* The user of this presence
|
||||
* @type {?User}
|
||||
* @readonly
|
||||
*/
|
||||
get user() {
|
||||
return this.client.users.resolve(this.userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* The member of this presence
|
||||
* @type {?GuildMember}
|
||||
* @readonly
|
||||
*/
|
||||
get member() {
|
||||
return this.guild.members.resolve(this.userId);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
if ('status' in data) {
|
||||
/**
|
||||
* The status of this presence
|
||||
* @type {PresenceStatus}
|
||||
*/
|
||||
this.status = data.status;
|
||||
} else {
|
||||
this.status ??= 'offline';
|
||||
}
|
||||
|
||||
if ('activities' in data) {
|
||||
/**
|
||||
* The activities of this presence
|
||||
* @type {Activity[]}
|
||||
*/
|
||||
this.activities = data.activities.map(activity => new Activity(this, activity));
|
||||
} else {
|
||||
this.activities ??= [];
|
||||
}
|
||||
|
||||
if ('client_status' in data) {
|
||||
/**
|
||||
* The devices this presence is on
|
||||
* @type {?Object}
|
||||
* @property {?ClientPresenceStatus} web The current presence in the web application
|
||||
* @property {?ClientPresenceStatus} mobile The current presence in the mobile application
|
||||
* @property {?ClientPresenceStatus} desktop The current presence in the desktop application
|
||||
*/
|
||||
this.clientStatus = data.client_status;
|
||||
} else {
|
||||
this.clientStatus ??= null;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
_clone() {
|
||||
const clone = Object.assign(Object.create(this), this);
|
||||
clone.activities = this.activities.map(activity => activity._clone());
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this presence is equal to another.
|
||||
* @param {Presence} presence The presence to compare with
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(presence) {
|
||||
return (
|
||||
this === presence ||
|
||||
(presence &&
|
||||
this.status === presence.status &&
|
||||
this.clientStatus?.web === presence.clientStatus?.web &&
|
||||
this.clientStatus?.mobile === presence.clientStatus?.mobile &&
|
||||
this.clientStatus?.desktop === presence.clientStatus?.desktop &&
|
||||
this.activities.length === presence.activities.length &&
|
||||
this.activities.every((activity, index) => activity.equals(presence.activities[index])))
|
||||
);
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return flatten(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an activity that is part of a user's presence.
|
||||
*/
|
||||
class Activity {
|
||||
constructor(presence, data) {
|
||||
/**
|
||||
* The presence of the Activity
|
||||
* @type {Presence}
|
||||
* @readonly
|
||||
* @name Activity#presence
|
||||
*/
|
||||
Object.defineProperty(this, 'presence', { value: presence });
|
||||
|
||||
/**
|
||||
* The activity's name
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* The activity status's type
|
||||
* @type {ActivityType}
|
||||
*/
|
||||
this.type = data.type;
|
||||
|
||||
/**
|
||||
* If the activity is being streamed, a link to the stream
|
||||
* @type {?string}
|
||||
*/
|
||||
this.url = data.url ?? null;
|
||||
|
||||
/**
|
||||
* Details about the activity
|
||||
* @type {?string}
|
||||
*/
|
||||
this.details = data.details ?? null;
|
||||
|
||||
/**
|
||||
* State of the activity
|
||||
* @type {?string}
|
||||
*/
|
||||
this.state = data.state ?? null;
|
||||
|
||||
/**
|
||||
* The id of the application associated with this activity
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.applicationId = data.application_id ?? null;
|
||||
|
||||
/**
|
||||
* Represents timestamps of an activity
|
||||
* @typedef {Object} ActivityTimestamps
|
||||
* @property {?Date} start When the activity started
|
||||
* @property {?Date} end When the activity will end
|
||||
*/
|
||||
|
||||
/**
|
||||
* Timestamps for the activity
|
||||
* @type {?ActivityTimestamps}
|
||||
*/
|
||||
this.timestamps = data.timestamps
|
||||
? {
|
||||
start: data.timestamps.start ? new Date(Number(data.timestamps.start)) : null,
|
||||
end: data.timestamps.end ? new Date(Number(data.timestamps.end)) : null,
|
||||
}
|
||||
: null;
|
||||
|
||||
/**
|
||||
* Represents a party of an activity
|
||||
* @typedef {Object} ActivityParty
|
||||
* @property {?string} id The party's id
|
||||
* @property {number[]} size Size of the party as `[current, max]`
|
||||
*/
|
||||
|
||||
/**
|
||||
* Party of the activity
|
||||
* @type {?ActivityParty}
|
||||
*/
|
||||
this.party = data.party ?? null;
|
||||
|
||||
/**
|
||||
* The sync id of the activity
|
||||
* <info>This property is not documented by Discord and represents the track id in spotify activities.</info>
|
||||
* @type {?string}
|
||||
*/
|
||||
this.syncId = data.sync_id ?? null;
|
||||
|
||||
/**
|
||||
* Assets for rich presence
|
||||
* @type {?RichPresenceAssets}
|
||||
*/
|
||||
this.assets = data.assets ? new RichPresenceAssets(this, data.assets) : null;
|
||||
|
||||
/**
|
||||
* Flags that describe the activity
|
||||
* @type {Readonly<ActivityFlagsBitField>}
|
||||
*/
|
||||
this.flags = new ActivityFlagsBitField(data.flags).freeze();
|
||||
|
||||
/**
|
||||
* Emoji for a custom activity
|
||||
* @type {?Emoji}
|
||||
*/
|
||||
this.emoji = data.emoji ? new Emoji(presence.client, data.emoji) : null;
|
||||
|
||||
/**
|
||||
* The labels of the buttons of this rich presence
|
||||
* @type {string[]}
|
||||
*/
|
||||
this.buttons = data.buttons ?? [];
|
||||
|
||||
/**
|
||||
* Creation date of the activity
|
||||
* @type {number}
|
||||
*/
|
||||
this.createdTimestamp = data.created_at;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this activity is equal to another activity.
|
||||
* @param {Activity} activity The activity to compare with
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(activity) {
|
||||
return (
|
||||
this === activity ||
|
||||
(activity &&
|
||||
this.name === activity.name &&
|
||||
this.type === activity.type &&
|
||||
this.url === activity.url &&
|
||||
this.state === activity.state &&
|
||||
this.details === activity.details &&
|
||||
this.emoji?.id === activity.emoji?.id &&
|
||||
this.emoji?.name === activity.emoji?.name)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the activity was created at
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically returns the activity's name instead of the Activity object.
|
||||
* @returns {string}
|
||||
*/
|
||||
toString() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
_clone() {
|
||||
return Object.assign(Object.create(this), this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assets for a rich presence
|
||||
*/
|
||||
class RichPresenceAssets {
|
||||
constructor(activity, assets) {
|
||||
/**
|
||||
* The activity of the RichPresenceAssets
|
||||
* @type {Activity}
|
||||
* @readonly
|
||||
* @name RichPresenceAssets#activity
|
||||
*/
|
||||
Object.defineProperty(this, 'activity', { value: activity });
|
||||
|
||||
/**
|
||||
* Hover text for the large image
|
||||
* @type {?string}
|
||||
*/
|
||||
this.largeText = assets.large_text ?? null;
|
||||
|
||||
/**
|
||||
* Hover text for the small image
|
||||
* @type {?string}
|
||||
*/
|
||||
this.smallText = assets.small_text ?? null;
|
||||
|
||||
/**
|
||||
* The large image asset's id
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.largeImage = assets.large_image ?? null;
|
||||
|
||||
/**
|
||||
* The small image asset's id
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.smallImage = assets.small_image ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL of the small image asset
|
||||
* @param {ImageURLOptions} [options={}] Options for the image URL
|
||||
* @returns {?string}
|
||||
*/
|
||||
smallImageURL(options = {}) {
|
||||
if (!this.smallImage) return null;
|
||||
if (this.smallImage.includes(':')) {
|
||||
const [platform, id] = this.smallImage.split(':');
|
||||
switch (platform) {
|
||||
case 'mp':
|
||||
return `https://media.discordapp.net/${id}`;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return this.activity.presence.client.rest.cdn.appAsset(this.activity.applicationId, this.smallImage, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the URL of the large image asset
|
||||
* @param {ImageURLOptions} [options={}] Options for the image URL
|
||||
* @returns {?string}
|
||||
*/
|
||||
largeImageURL(options = {}) {
|
||||
if (!this.largeImage) return null;
|
||||
if (this.largeImage.includes(':')) {
|
||||
const [platform, id] = this.largeImage.split(':');
|
||||
switch (platform) {
|
||||
case 'mp':
|
||||
return `https://media.discordapp.net/${id}`;
|
||||
case 'spotify':
|
||||
return `https://i.scdn.co/image/${id}`;
|
||||
case 'youtube':
|
||||
return `https://i.ytimg.com/vi/${id}/hqdefault_live.jpg`;
|
||||
case 'twitch':
|
||||
return `https://static-cdn.jtvnw.net/previews-ttv/live_user_${id}.png`;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return this.activity.presence.client.rest.cdn.appAsset(this.activity.applicationId, this.largeImage, options);
|
||||
}
|
||||
}
|
||||
|
||||
exports.Presence = Presence;
|
||||
exports.Activity = Activity;
|
||||
exports.RichPresenceAssets = RichPresenceAssets;
|
||||
11
node_modules/discord.js/src/structures/PrimaryEntryPointCommandInteraction.js
generated
vendored
Normal file
11
node_modules/discord.js/src/structures/PrimaryEntryPointCommandInteraction.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const CommandInteraction = require('./CommandInteraction.js');
|
||||
|
||||
/**
|
||||
* Represents a primary entry point command interaction.
|
||||
* @extends {CommandInteraction}
|
||||
*/
|
||||
class PrimaryEntryPointCommandInteraction extends CommandInteraction {}
|
||||
|
||||
module.exports = PrimaryEntryPointCommandInteraction;
|
||||
229
node_modules/discord.js/src/structures/ReactionCollector.js
generated
vendored
Normal file
229
node_modules/discord.js/src/structures/ReactionCollector.js
generated
vendored
Normal file
@@ -0,0 +1,229 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const Collector = require('./interfaces/Collector');
|
||||
const Events = require('../util/Events');
|
||||
|
||||
/**
|
||||
* @typedef {CollectorOptions} ReactionCollectorOptions
|
||||
* @property {number} max The maximum total amount of reactions to collect
|
||||
* @property {number} maxEmojis The maximum number of emojis to collect
|
||||
* @property {number} maxUsers The maximum number of users to react
|
||||
*/
|
||||
|
||||
/**
|
||||
* Collects reactions on messages.
|
||||
* Will automatically stop if the message ({@link Client#event:messageDelete messageDelete} or
|
||||
* {@link Client#event:messageDeleteBulk messageDeleteBulk}),
|
||||
* channel ({@link Client#event:channelDelete channelDelete}),
|
||||
* thread ({@link Client#event:threadDelete threadDelete}), or
|
||||
* guild ({@link Client#event:guildDelete guildDelete}) is deleted.
|
||||
* @extends {Collector}
|
||||
*/
|
||||
class ReactionCollector extends Collector {
|
||||
/**
|
||||
* @param {Message} message The message upon which to collect reactions
|
||||
* @param {ReactionCollectorOptions} [options={}] The options to apply to this collector
|
||||
*/
|
||||
constructor(message, options = {}) {
|
||||
super(message.client, options);
|
||||
|
||||
/**
|
||||
* The message upon which to collect reactions
|
||||
* @type {Message}
|
||||
*/
|
||||
this.message = message;
|
||||
|
||||
/**
|
||||
* The users that have reacted to this message
|
||||
* @type {Collection}
|
||||
*/
|
||||
this.users = new Collection();
|
||||
|
||||
/**
|
||||
* The total number of reactions collected
|
||||
* @type {number}
|
||||
*/
|
||||
this.total = 0;
|
||||
|
||||
this.empty = this.empty.bind(this);
|
||||
this._handleChannelDeletion = this._handleChannelDeletion.bind(this);
|
||||
this._handleThreadDeletion = this._handleThreadDeletion.bind(this);
|
||||
this._handleGuildDeletion = this._handleGuildDeletion.bind(this);
|
||||
this._handleMessageDeletion = this._handleMessageDeletion.bind(this);
|
||||
|
||||
const bulkDeleteListener = messages => {
|
||||
if (messages.has(this.message.id)) this.stop('messageDelete');
|
||||
};
|
||||
|
||||
this.client.incrementMaxListeners();
|
||||
this.client.on(Events.MessageReactionAdd, this.handleCollect);
|
||||
this.client.on(Events.MessageReactionRemove, this.handleDispose);
|
||||
this.client.on(Events.MessageReactionRemoveAll, this.empty);
|
||||
this.client.on(Events.MessageDelete, this._handleMessageDeletion);
|
||||
this.client.on(Events.MessageBulkDelete, bulkDeleteListener);
|
||||
this.client.on(Events.ChannelDelete, this._handleChannelDeletion);
|
||||
this.client.on(Events.ThreadDelete, this._handleThreadDeletion);
|
||||
this.client.on(Events.GuildDelete, this._handleGuildDeletion);
|
||||
|
||||
this.once('end', () => {
|
||||
this.client.removeListener(Events.MessageReactionAdd, this.handleCollect);
|
||||
this.client.removeListener(Events.MessageReactionRemove, this.handleDispose);
|
||||
this.client.removeListener(Events.MessageReactionRemoveAll, this.empty);
|
||||
this.client.removeListener(Events.MessageDelete, this._handleMessageDeletion);
|
||||
this.client.removeListener(Events.MessageBulkDelete, bulkDeleteListener);
|
||||
this.client.removeListener(Events.ChannelDelete, this._handleChannelDeletion);
|
||||
this.client.removeListener(Events.ThreadDelete, this._handleThreadDeletion);
|
||||
this.client.removeListener(Events.GuildDelete, this._handleGuildDeletion);
|
||||
this.client.decrementMaxListeners();
|
||||
});
|
||||
|
||||
this.on('collect', (reaction, user) => {
|
||||
/**
|
||||
* Emitted whenever a reaction is newly created on a message. Will emit only when a new reaction is
|
||||
* added to the message, as opposed to {@link Collector#event:collect} which will
|
||||
* be emitted even when a reaction has already been added to the message.
|
||||
* @event ReactionCollector#create
|
||||
* @param {MessageReaction} reaction The reaction that was added
|
||||
* @param {User} user The user that added the reaction
|
||||
*/
|
||||
if (reaction.count === 1) {
|
||||
this.emit('create', reaction, user);
|
||||
}
|
||||
this.total++;
|
||||
this.users.set(user.id, user);
|
||||
});
|
||||
|
||||
this.on('remove', (_reaction, user) => {
|
||||
this.total--;
|
||||
if (!this.collected.some(reaction => reaction.users.cache.has(user.id))) this.users.delete(user.id);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles an incoming reaction for possible collection.
|
||||
* @param {MessageReaction} reaction The reaction to possibly collect
|
||||
* @param {User} user The user that added the reaction
|
||||
* @returns {?(Snowflake|string)}
|
||||
* @private
|
||||
*/
|
||||
collect(reaction) {
|
||||
/**
|
||||
* Emitted whenever a reaction is collected.
|
||||
* @event ReactionCollector#collect
|
||||
* @param {MessageReaction} reaction The reaction that was collected
|
||||
* @param {User} user The user that added the reaction
|
||||
*/
|
||||
if (reaction.message.id !== this.message.id) return null;
|
||||
|
||||
return ReactionCollector.key(reaction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles a reaction deletion for possible disposal.
|
||||
* @param {MessageReaction} reaction The reaction to possibly dispose of
|
||||
* @param {User} user The user that removed the reaction
|
||||
* @returns {?(Snowflake|string)}
|
||||
*/
|
||||
dispose(reaction, user) {
|
||||
/**
|
||||
* Emitted when the reaction had all the users removed and the `dispose` option is set to true.
|
||||
* @event ReactionCollector#dispose
|
||||
* @param {MessageReaction} reaction The reaction that was disposed of
|
||||
* @param {User} user The user that removed the reaction
|
||||
*/
|
||||
if (reaction.message.id !== this.message.id) return null;
|
||||
|
||||
/**
|
||||
* Emitted when the reaction had one user removed and the `dispose` option is set to true.
|
||||
* @event ReactionCollector#remove
|
||||
* @param {MessageReaction} reaction The reaction that was removed
|
||||
* @param {User} user The user that removed the reaction
|
||||
*/
|
||||
if (this.collected.has(ReactionCollector.key(reaction)) && this.users.has(user.id)) {
|
||||
this.emit('remove', reaction, user);
|
||||
}
|
||||
return reaction.count ? null : ReactionCollector.key(reaction);
|
||||
}
|
||||
|
||||
/**
|
||||
* Empties this reaction collector.
|
||||
*/
|
||||
empty() {
|
||||
this.total = 0;
|
||||
this.collected.clear();
|
||||
this.users.clear();
|
||||
this.checkEnd();
|
||||
}
|
||||
|
||||
/**
|
||||
* The reason this collector has ended with, or null if it hasn't ended yet
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get endReason() {
|
||||
if (this.options.max && this.total >= this.options.max) return 'limit';
|
||||
if (this.options.maxEmojis && this.collected.size >= this.options.maxEmojis) return 'emojiLimit';
|
||||
if (this.options.maxUsers && this.users.size >= this.options.maxUsers) return 'userLimit';
|
||||
return super.endReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles checking if the message has been deleted, and if so, stops the collector with the reason 'messageDelete'.
|
||||
* @private
|
||||
* @param {Message} message The message that was deleted
|
||||
* @returns {void}
|
||||
*/
|
||||
_handleMessageDeletion(message) {
|
||||
if (message.id === this.message.id) {
|
||||
this.stop('messageDelete');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles checking if the channel has been deleted, and if so, stops the collector with the reason 'channelDelete'.
|
||||
* @private
|
||||
* @param {GuildChannel} channel The channel that was deleted
|
||||
* @returns {void}
|
||||
*/
|
||||
_handleChannelDeletion(channel) {
|
||||
if (channel.id === this.message.channelId || channel.threads?.cache.has(this.message.channelId)) {
|
||||
this.stop('channelDelete');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles checking if the thread has been deleted, and if so, stops the collector with the reason 'threadDelete'.
|
||||
* @private
|
||||
* @param {ThreadChannel} thread The thread that was deleted
|
||||
* @returns {void}
|
||||
*/
|
||||
_handleThreadDeletion(thread) {
|
||||
if (thread.id === this.message.channelId) {
|
||||
this.stop('threadDelete');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles checking if the guild has been deleted, and if so, stops the collector with the reason 'guildDelete'.
|
||||
* @private
|
||||
* @param {Guild} guild The guild that was deleted
|
||||
* @returns {void}
|
||||
*/
|
||||
_handleGuildDeletion(guild) {
|
||||
if (guild.id === this.message.guild?.id) {
|
||||
this.stop('guildDelete');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the collector key for a reaction.
|
||||
* @param {MessageReaction} reaction The message reaction to get the key for
|
||||
* @returns {Snowflake|string}
|
||||
*/
|
||||
static key(reaction) {
|
||||
return reaction.emoji.id ?? reaction.emoji.name;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ReactionCollector;
|
||||
31
node_modules/discord.js/src/structures/ReactionEmoji.js
generated
vendored
Normal file
31
node_modules/discord.js/src/structures/ReactionEmoji.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
const { Emoji } = require('./Emoji');
|
||||
const { flatten } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents a limited emoji set used for both custom and unicode emojis. Custom emojis
|
||||
* will use this class opposed to the Emoji class when the client doesn't know enough
|
||||
* information about them.
|
||||
* @extends {Emoji}
|
||||
*/
|
||||
class ReactionEmoji extends Emoji {
|
||||
constructor(reaction, emoji) {
|
||||
super(reaction.message.client, emoji);
|
||||
/**
|
||||
* The message reaction this emoji refers to
|
||||
* @type {MessageReaction}
|
||||
*/
|
||||
this.reaction = reaction;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return flatten(this, { identifier: true });
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.id;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ReactionEmoji;
|
||||
519
node_modules/discord.js/src/structures/Role.js
generated
vendored
Normal file
519
node_modules/discord.js/src/structures/Role.js
generated
vendored
Normal file
@@ -0,0 +1,519 @@
|
||||
'use strict';
|
||||
|
||||
const { roleMention } = require('@discordjs/formatters');
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const { PermissionFlagsBits } = require('discord-api-types/v10');
|
||||
const Base = require('./Base');
|
||||
const { DiscordjsError, ErrorCodes } = require('../errors');
|
||||
const PermissionsBitField = require('../util/PermissionsBitField');
|
||||
const RoleFlagsBitField = require('../util/RoleFlagsBitField');
|
||||
|
||||
/**
|
||||
* Represents a role on Discord.
|
||||
* @extends {Base}
|
||||
*/
|
||||
class Role extends Base {
|
||||
constructor(client, data, guild) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The guild that the role belongs to
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
|
||||
/**
|
||||
* The icon hash of the role
|
||||
* @type {?string}
|
||||
*/
|
||||
this.icon = null;
|
||||
|
||||
/**
|
||||
* The unicode emoji for the role
|
||||
* @type {?string}
|
||||
*/
|
||||
this.unicodeEmoji = null;
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
/**
|
||||
* The role's id (unique to the guild it is part of)
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
if ('name' in data) {
|
||||
/**
|
||||
* The name of the role
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
}
|
||||
|
||||
if ('color' in data) {
|
||||
/**
|
||||
* The base 10 color of the role
|
||||
*
|
||||
* @type {number}
|
||||
* @deprecated Use {@link Role#colors} instead.
|
||||
*/
|
||||
this.color = data.color;
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} RoleColors
|
||||
* @property {number} primaryColor The primary color of the role
|
||||
* @property {?number} secondaryColor The secondary color of the role.
|
||||
* This will make the role a gradient between the other provided colors
|
||||
* @property {?number} tertiaryColor The tertiary color of the role.
|
||||
* When sending `tertiaryColor` the API enforces the role color to be a holographic style
|
||||
* with values of `primaryColor = 11127295`, `secondaryColor = 16759788`, and `tertiaryColor = 16761760`.
|
||||
* These values are available as a constant: `Constants.HolographicStyle`
|
||||
*/
|
||||
|
||||
if ('colors' in data) {
|
||||
/**
|
||||
* The colors of the role
|
||||
*
|
||||
* @type {RoleColors}
|
||||
*/
|
||||
this.colors = {
|
||||
primaryColor: data.colors.primary_color,
|
||||
secondaryColor: data.colors.secondary_color,
|
||||
tertiaryColor: data.colors.tertiary_color,
|
||||
};
|
||||
}
|
||||
|
||||
if ('hoist' in data) {
|
||||
/**
|
||||
* If true, users that are part of this role will appear in a separate category in the users list
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.hoist = data.hoist;
|
||||
}
|
||||
|
||||
if ('position' in data) {
|
||||
/**
|
||||
* The raw position of the role from the API
|
||||
* @type {number}
|
||||
*/
|
||||
this.rawPosition = data.position;
|
||||
}
|
||||
|
||||
if ('permissions' in data) {
|
||||
/**
|
||||
* The permissions of the role
|
||||
* @type {Readonly<PermissionsBitField>}
|
||||
*/
|
||||
this.permissions = new PermissionsBitField(BigInt(data.permissions)).freeze();
|
||||
}
|
||||
|
||||
if ('managed' in data) {
|
||||
/**
|
||||
* Whether or not the role is managed by an external service
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.managed = data.managed;
|
||||
}
|
||||
|
||||
if ('mentionable' in data) {
|
||||
/**
|
||||
* Whether or not the role can be mentioned by anyone
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.mentionable = data.mentionable;
|
||||
}
|
||||
|
||||
if ('icon' in data) this.icon = data.icon;
|
||||
|
||||
if ('unicode_emoji' in data) this.unicodeEmoji = data.unicode_emoji;
|
||||
|
||||
if ('flags' in data) {
|
||||
/**
|
||||
* The flags of this role
|
||||
* @type {Readonly<RoleFlagsBitField>}
|
||||
*/
|
||||
this.flags = new RoleFlagsBitField(data.flags).freeze();
|
||||
} else {
|
||||
this.flags ??= new RoleFlagsBitField().freeze();
|
||||
}
|
||||
|
||||
/**
|
||||
* The tags this role has
|
||||
* @type {?Object}
|
||||
* @property {Snowflake} [botId] The id of the bot this role belongs to
|
||||
* @property {Snowflake|string} [integrationId] The id of the integration this role belongs to
|
||||
* @property {true} [premiumSubscriberRole] Whether this is the guild's premium subscription role
|
||||
* @property {Snowflake} [subscriptionListingId] The id of this role's subscription SKU and listing
|
||||
* @property {true} [availableForPurchase] Whether this role is available for purchase
|
||||
* @property {true} [guildConnections] Whether this role is a guild's linked role
|
||||
*/
|
||||
this.tags = data.tags ? {} : null;
|
||||
if (data.tags) {
|
||||
if ('bot_id' in data.tags) {
|
||||
this.tags.botId = data.tags.bot_id;
|
||||
}
|
||||
if ('integration_id' in data.tags) {
|
||||
this.tags.integrationId = data.tags.integration_id;
|
||||
}
|
||||
if ('premium_subscriber' in data.tags) {
|
||||
this.tags.premiumSubscriberRole = true;
|
||||
}
|
||||
if ('subscription_listing_id' in data.tags) {
|
||||
this.tags.subscriptionListingId = data.tags.subscription_listing_id;
|
||||
}
|
||||
if ('available_for_purchase' in data.tags) {
|
||||
this.tags.availableForPurchase = true;
|
||||
}
|
||||
if ('guild_connections' in data.tags) {
|
||||
this.tags.guildConnections = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp the role was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the role was created at
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The hexadecimal version of the role color, with a leading hashtag
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get hexColor() {
|
||||
return `#${this.colors.primaryColor.toString(16).padStart(6, '0')}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* The cached guild members that have this role
|
||||
* @type {Collection<Snowflake, GuildMember>}
|
||||
* @readonly
|
||||
*/
|
||||
get members() {
|
||||
return this.id === this.guild.id
|
||||
? this.guild.members.cache.clone()
|
||||
: this.guild.members.cache.filter(member => member._roles.includes(this.id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the role is editable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get editable() {
|
||||
if (this.managed) return false;
|
||||
const clientMember = this.guild.members.resolve(this.client.user);
|
||||
if (!clientMember.permissions.has(PermissionFlagsBits.ManageRoles)) return false;
|
||||
return clientMember.roles.highest.comparePositionTo(this) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The position of the role in the role manager
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get position() {
|
||||
return this.guild.roles.cache.reduce(
|
||||
(acc, role) =>
|
||||
acc +
|
||||
(this.rawPosition === role.rawPosition
|
||||
? BigInt(this.id) < BigInt(role.id)
|
||||
: this.rawPosition > role.rawPosition),
|
||||
0,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this role's position to another role's.
|
||||
* @param {RoleResolvable} role Role to compare to this one
|
||||
* @returns {number} Negative number if this role's position is lower (other role's is higher),
|
||||
* positive number if this one is higher (other's is lower), 0 if equal
|
||||
* @example
|
||||
* // Compare the position of a role to another
|
||||
* const roleCompare = role.comparePositionTo(otherRole);
|
||||
* if (roleCompare >= 1) console.log(`${role.name} is higher than ${otherRole.name}`);
|
||||
*/
|
||||
comparePositionTo(role) {
|
||||
return this.guild.roles.comparePositions(this, role);
|
||||
}
|
||||
|
||||
/**
|
||||
* The data for a role.
|
||||
* @typedef {Object} RoleData
|
||||
* @property {string} [name] The name of the role
|
||||
* @property {ColorResolvable} [color] The color of the role, either a hex string or a base 10 number
|
||||
* <warn>This property is deprecated. Use `colors` instead.</warn>
|
||||
* @property {RoleColorsResolvable} [colors] The colors of the role
|
||||
* @property {boolean} [hoist] Whether or not the role should be hoisted
|
||||
* @property {number} [position] The position of the role
|
||||
* @property {PermissionResolvable} [permissions] The permissions of the role
|
||||
* @property {boolean} [mentionable] Whether or not the role should be mentionable
|
||||
* @property {?(BufferResolvable|Base64Resolvable|EmojiResolvable)} [icon] The icon for the role
|
||||
* <warn>The `EmojiResolvable` should belong to the same guild as the role.
|
||||
* If not, pass the emoji's URL directly</warn>
|
||||
* @property {?string} [unicodeEmoji] The unicode emoji for the role
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits the role.
|
||||
* @param {RoleEditOptions} options The options to provide
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Edit a role
|
||||
* role.edit({ name: 'new role' })
|
||||
* .then(updated => console.log(`Edited role name to ${updated.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
edit(options) {
|
||||
return this.guild.roles.edit(this, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `channel.permissionsFor(role)`. Returns permissions for a role in a guild channel,
|
||||
* taking into account permission overwrites.
|
||||
* @param {GuildChannel|Snowflake} channel The guild channel to use as context
|
||||
* @param {boolean} [checkAdmin=true] Whether having the {@link PermissionFlagsBits.Administrator} permission
|
||||
* will return all permissions
|
||||
* @returns {Readonly<PermissionsBitField>}
|
||||
*/
|
||||
permissionsIn(channel, checkAdmin = true) {
|
||||
channel = this.guild.channels.resolve(channel);
|
||||
if (!channel) throw new DiscordjsError(ErrorCodes.GuildChannelResolve);
|
||||
return channel.rolePermissions(this, checkAdmin);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new name for the role.
|
||||
* @param {string} name The new name of the role
|
||||
* @param {string} [reason] Reason for changing the role's name
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Set the name of the role
|
||||
* role.setName('new role')
|
||||
* .then(updated => console.log(`Updated role name to ${updated.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setName(name, reason) {
|
||||
return this.edit({ name, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new color for the role.
|
||||
*
|
||||
* @param {ColorResolvable} color The color of the role
|
||||
* @param {string} [reason] Reason for changing the role's color
|
||||
* @returns {Promise<Role>}
|
||||
* @deprecated Use {@link Role#setColors} instead.
|
||||
*/
|
||||
async setColor(color, reason) {
|
||||
return this.edit({ color, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets new colors for the role.
|
||||
*
|
||||
* @param {RoleColorsResolvable} colors The colors of the role
|
||||
* @param {string} [reason] Reason for changing the role's colors
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Set the colors of a role
|
||||
* role.setColors({ primaryColor: '#FF0000', secondaryColor: '#00FF00', tertiaryColor: '#0000FF' })
|
||||
* .then(updated => console.log(`Set colors of role to ${updated.colors}`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Set holographic colors using constants
|
||||
* role.setColors({
|
||||
* primaryColor: Constants.HolographicStyle.Primary,
|
||||
* secondaryColor: Constants.HolographicStyle.Secondary,
|
||||
* tertiaryColor: Constants.HolographicStyle.Tertiary,
|
||||
* })
|
||||
* .then(updated => console.log(`Set holographic colors for role ${updated.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async setColors(colors, reason) {
|
||||
return this.edit({ colors, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether or not the role should be hoisted.
|
||||
* @param {boolean} [hoist=true] Whether or not to hoist the role
|
||||
* @param {string} [reason] Reason for setting whether or not the role should be hoisted
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Set the hoist of the role
|
||||
* role.setHoist(true)
|
||||
* .then(updated => console.log(`Role hoisted: ${updated.hoist}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setHoist(hoist = true, reason) {
|
||||
return this.edit({ hoist, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the permissions of the role.
|
||||
* @param {PermissionResolvable} permissions The permissions of the role
|
||||
* @param {string} [reason] Reason for changing the role's permissions
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Set the permissions of the role
|
||||
* role.setPermissions([PermissionFlagsBits.KickMembers, PermissionFlagsBits.BanMembers])
|
||||
* .then(updated => console.log(`Updated permissions to ${updated.permissions.bitfield}`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Remove all permissions from a role
|
||||
* role.setPermissions(0n)
|
||||
* .then(updated => console.log(`Updated permissions to ${updated.permissions.bitfield}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setPermissions(permissions, reason) {
|
||||
return this.edit({ permissions, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this role is mentionable.
|
||||
* @param {boolean} [mentionable=true] Whether this role should be mentionable
|
||||
* @param {string} [reason] Reason for setting whether or not this role should be mentionable
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Make the role mentionable
|
||||
* role.setMentionable(true)
|
||||
* .then(updated => console.log(`Role updated ${updated.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setMentionable(mentionable = true, reason) {
|
||||
return this.edit({ mentionable, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new icon for the role.
|
||||
* @param {?(BufferResolvable|Base64Resolvable|EmojiResolvable)} icon The icon for the role
|
||||
* <warn>The `EmojiResolvable` should belong to the same guild as the role.
|
||||
* If not, pass the emoji's URL directly</warn>
|
||||
* @param {string} [reason] Reason for changing the role's icon
|
||||
* @returns {Promise<Role>}
|
||||
*/
|
||||
setIcon(icon, reason) {
|
||||
return this.edit({ icon, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new unicode emoji for the role.
|
||||
* @param {?string} unicodeEmoji The new unicode emoji for the role
|
||||
* @param {string} [reason] Reason for changing the role's unicode emoji
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Set a new unicode emoji for the role
|
||||
* role.setUnicodeEmoji('🤖')
|
||||
* .then(updated => console.log(`Set unicode emoji for the role to ${updated.unicodeEmoji}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setUnicodeEmoji(unicodeEmoji, reason) {
|
||||
return this.edit({ unicodeEmoji, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to set the position of a role.
|
||||
* @typedef {Object} SetRolePositionOptions
|
||||
* @property {boolean} [relative=false] Whether to change the position relative to its current value or not
|
||||
* @property {string} [reason] The reason for changing the position
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sets the new position of the role.
|
||||
* @param {number} position The new position for the role
|
||||
* @param {SetRolePositionOptions} [options] Options for setting the position
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Set the position of the role
|
||||
* role.setPosition(1)
|
||||
* .then(updated => console.log(`Role position: ${updated.position}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setPosition(position, options = {}) {
|
||||
return this.guild.roles.setPosition(this, position, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the role.
|
||||
* @param {string} [reason] Reason for deleting this role
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Delete a role
|
||||
* role.delete('The role needed to go')
|
||||
* .then(deleted => console.log(`Deleted role ${deleted.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async delete(reason) {
|
||||
await this.guild.roles.delete(this.id, reason);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A link to the role's icon
|
||||
* @param {ImageURLOptions} [options={}] Options for the image URL
|
||||
* @returns {?string}
|
||||
*/
|
||||
iconURL(options = {}) {
|
||||
return this.icon && this.client.rest.cdn.roleIcon(this.id, this.icon, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this role equals another role. It compares all properties, so for most operations
|
||||
* it is advisable to just compare `role.id === role2.id` as it is much faster and is often
|
||||
* what most users need.
|
||||
* @param {Role} role Role to compare with
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(role) {
|
||||
return (
|
||||
role &&
|
||||
this.id === role.id &&
|
||||
this.name === role.name &&
|
||||
this.colors.primaryColor === role.colors.primaryColor &&
|
||||
this.colors.secondaryColor === role.colors.secondaryColor &&
|
||||
this.colors.tertiaryColor === role.colors.tertiaryColor &&
|
||||
this.hoist === role.hoist &&
|
||||
this.position === role.position &&
|
||||
this.permissions.bitfield === role.permissions.bitfield &&
|
||||
this.managed === role.managed &&
|
||||
this.icon === role.icon &&
|
||||
this.unicodeEmoji === role.unicodeEmoji
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically returns the role's mention instead of the Role object.
|
||||
* @returns {string}
|
||||
* @example
|
||||
* // Logs: Role: <@&123456789012345678>
|
||||
* console.log(`Role: ${role}`);
|
||||
*/
|
||||
toString() {
|
||||
if (this.id === this.guild.id) return '@everyone';
|
||||
return roleMention(this.id);
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return {
|
||||
...super.toJSON({ createdTimestamp: true }),
|
||||
permissions: this.permissions.toJSON(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
exports.Role = Role;
|
||||
31
node_modules/discord.js/src/structures/RoleSelectMenuBuilder.js
generated
vendored
Normal file
31
node_modules/discord.js/src/structures/RoleSelectMenuBuilder.js
generated
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
'use strict';
|
||||
|
||||
const { RoleSelectMenuBuilder: BuildersRoleSelectMenu } = require('@discordjs/builders');
|
||||
const { isJSONEncodable } = require('@discordjs/util');
|
||||
const { toSnakeCase } = require('../util/Transformers');
|
||||
|
||||
/**
|
||||
* Class used to build select menu components to be sent through the API
|
||||
* @extends {BuildersRoleSelectMenu}
|
||||
*/
|
||||
class RoleSelectMenuBuilder extends BuildersRoleSelectMenu {
|
||||
constructor(data = {}) {
|
||||
super(toSnakeCase(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new select menu builder from JSON data
|
||||
* @param {RoleSelectMenuBuilder|RoleSelectMenuComponent|APIRoleSelectComponent} other The other data
|
||||
* @returns {RoleSelectMenuBuilder}
|
||||
*/
|
||||
static from(other) {
|
||||
return new this(isJSONEncodable(other) ? other.toJSON() : other);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = RoleSelectMenuBuilder;
|
||||
|
||||
/**
|
||||
* @external BuildersRoleSelectMenu
|
||||
* @see {@link https://discord.js.org/docs/packages/builders/stable/RoleSelectMenuBuilder:Class}
|
||||
*/
|
||||
11
node_modules/discord.js/src/structures/RoleSelectMenuComponent.js
generated
vendored
Normal file
11
node_modules/discord.js/src/structures/RoleSelectMenuComponent.js
generated
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const BaseSelectMenuComponent = require('./BaseSelectMenuComponent');
|
||||
|
||||
/**
|
||||
* Represents a role select menu component
|
||||
* @extends {BaseSelectMenuComponent}
|
||||
*/
|
||||
class RoleSelectMenuComponent extends BaseSelectMenuComponent {}
|
||||
|
||||
module.exports = RoleSelectMenuComponent;
|
||||
33
node_modules/discord.js/src/structures/RoleSelectMenuInteraction.js
generated
vendored
Normal file
33
node_modules/discord.js/src/structures/RoleSelectMenuInteraction.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const MessageComponentInteraction = require('./MessageComponentInteraction');
|
||||
|
||||
/**
|
||||
* Represents a {@link ComponentType.RoleSelect} select menu interaction.
|
||||
* @extends {MessageComponentInteraction}
|
||||
*/
|
||||
class RoleSelectMenuInteraction extends MessageComponentInteraction {
|
||||
constructor(client, data) {
|
||||
super(client, data);
|
||||
const { resolved, values } = data.data;
|
||||
|
||||
/**
|
||||
* An array of the selected role ids
|
||||
* @type {Snowflake[]}
|
||||
*/
|
||||
this.values = values ?? [];
|
||||
|
||||
/**
|
||||
* Collection of the selected roles
|
||||
* @type {Collection<Snowflake, Role|APIRole>}
|
||||
*/
|
||||
this.roles = new Collection();
|
||||
|
||||
for (const role of Object.values(resolved?.roles ?? {})) {
|
||||
this.roles.set(role.id, this.guild?.roles._add(role) ?? role);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = RoleSelectMenuInteraction;
|
||||
52
node_modules/discord.js/src/structures/SKU.js
generated
vendored
Normal file
52
node_modules/discord.js/src/structures/SKU.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
'use strict';
|
||||
|
||||
const Base = require('./Base');
|
||||
const { SKUFlagsBitField } = require('../util/SKUFlagsBitField');
|
||||
|
||||
/**
|
||||
* Represents a premium application SKU.
|
||||
* @extends {Base}
|
||||
*/
|
||||
class SKU extends Base {
|
||||
constructor(client, data) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The id of the SKU
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The type of the SKU
|
||||
* @type {SKUType}
|
||||
*/
|
||||
this.type = data.type;
|
||||
|
||||
/**
|
||||
* The id of the parent application
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.applicationId = data.application_id;
|
||||
|
||||
/**
|
||||
* The customer-facing name of the premium offering
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* The system-generated URL slug based on this SKU's name
|
||||
* @type {string}
|
||||
*/
|
||||
this.slug = data.slug;
|
||||
|
||||
/**
|
||||
* Flags that describe the SKU
|
||||
* @type {Readonly<SKUFlagsBitField>}
|
||||
*/
|
||||
this.flags = new SKUFlagsBitField(data.flags).freeze();
|
||||
}
|
||||
}
|
||||
|
||||
exports.SKU = SKU;
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user