Initial commit of Discord bot
This commit is contained in:
268
node_modules/discord.js/src/managers/ApplicationCommandManager.js
generated
vendored
Normal file
268
node_modules/discord.js/src/managers/ApplicationCommandManager.js
generated
vendored
Normal file
@@ -0,0 +1,268 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { makeURLSearchParams } = require('@discordjs/rest');
|
||||
const { isJSONEncodable } = require('@discordjs/util');
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const ApplicationCommandPermissionsManager = require('./ApplicationCommandPermissionsManager');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
const ApplicationCommand = require('../structures/ApplicationCommand');
|
||||
const PermissionsBitField = require('../util/PermissionsBitField');
|
||||
|
||||
/**
|
||||
* Manages API methods for application commands and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class ApplicationCommandManager extends CachedManager {
|
||||
constructor(client, iterable) {
|
||||
super(client, ApplicationCommand, iterable);
|
||||
|
||||
/**
|
||||
* The manager for permissions of arbitrary commands on arbitrary guilds
|
||||
* @type {ApplicationCommandPermissionsManager}
|
||||
*/
|
||||
this.permissions = new ApplicationCommandPermissionsManager(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of this manager
|
||||
* @type {Collection<Snowflake, ApplicationCommand>}
|
||||
* @name ApplicationCommandManager#cache
|
||||
*/
|
||||
|
||||
_add(data, cache, guildId) {
|
||||
return super._add(data, cache, { extras: [this.guild, guildId] });
|
||||
}
|
||||
|
||||
/**
|
||||
* The APIRouter path to the commands
|
||||
* @param {Snowflake} [options.id] The application command's id
|
||||
* @param {Snowflake} [options.guildId] The guild's id to use in the path,
|
||||
* ignored when using a {@link GuildApplicationCommandManager}
|
||||
* @returns {string}
|
||||
* @private
|
||||
*/
|
||||
commandPath({ id, guildId } = {}) {
|
||||
if (this.guild ?? guildId) {
|
||||
if (id) {
|
||||
return Routes.applicationGuildCommand(this.client.application.id, this.guild?.id ?? guildId, id);
|
||||
}
|
||||
|
||||
return Routes.applicationGuildCommands(this.client.application.id, this.guild?.id ?? guildId);
|
||||
}
|
||||
|
||||
if (id) {
|
||||
return Routes.applicationCommand(this.client.application.id, id);
|
||||
}
|
||||
|
||||
return Routes.applicationCommands(this.client.application.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that resolves to give an ApplicationCommand object. This can be:
|
||||
* * An ApplicationCommand object
|
||||
* * A Snowflake
|
||||
* @typedef {ApplicationCommand|Snowflake} ApplicationCommandResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data that resolves to the data of an ApplicationCommand
|
||||
* @typedef {ApplicationCommandData|APIApplicationCommand} ApplicationCommandDataResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch data from Discord
|
||||
* @typedef {Object} BaseFetchOptions
|
||||
* @property {boolean} [cache=true] Whether to cache the fetched data if it wasn't already
|
||||
* @property {boolean} [force=false] Whether to skip the cache check and request the API
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch Application Commands from Discord
|
||||
* @typedef {BaseFetchOptions} FetchApplicationCommandOptions
|
||||
* @property {Snowflake} [guildId] The guild's id to fetch commands for, for when the guild is not cached
|
||||
* @property {LocaleString} [locale] The locale to use when fetching this command
|
||||
* @property {boolean} [withLocalizations] Whether to fetch all localization data
|
||||
*/
|
||||
|
||||
/**
|
||||
* Obtains one or multiple application commands from Discord, or the cache if it's already available.
|
||||
* @param {Snowflake|FetchApplicationCommandOptions} [id] Options for fetching application command(s)
|
||||
* @param {FetchApplicationCommandOptions} [options] Additional options for this fetch
|
||||
* @returns {Promise<ApplicationCommand|Collection<Snowflake, ApplicationCommand>>}
|
||||
* @example
|
||||
* // Fetch a single command
|
||||
* client.application.commands.fetch('123456789012345678')
|
||||
* .then(command => console.log(`Fetched command ${command.name}`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch all commands
|
||||
* guild.commands.fetch()
|
||||
* .then(commands => console.log(`Fetched ${commands.size} commands`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetch(id, { guildId, cache = true, force = false, locale, withLocalizations } = {}) {
|
||||
if (typeof id === 'object') {
|
||||
({ guildId, cache = true, locale, withLocalizations } = id);
|
||||
} else if (id) {
|
||||
if (!force) {
|
||||
const existing = this.cache.get(id);
|
||||
if (existing) return existing;
|
||||
}
|
||||
const command = await this.client.rest.get(this.commandPath({ id, guildId }));
|
||||
return this._add(command, cache);
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(this.commandPath({ guildId }), {
|
||||
headers: {
|
||||
'X-Discord-Locale': locale,
|
||||
},
|
||||
query: makeURLSearchParams({ with_localizations: withLocalizations }),
|
||||
});
|
||||
return data.reduce((coll, command) => coll.set(command.id, this._add(command, cache, guildId)), new Collection());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an application command.
|
||||
* @param {ApplicationCommandDataResolvable} command The command
|
||||
* @param {Snowflake} [guildId] The guild's id to create this command in,
|
||||
* ignored when using a {@link GuildApplicationCommandManager}
|
||||
* @returns {Promise<ApplicationCommand>}
|
||||
* @example
|
||||
* // Create a new command
|
||||
* client.application.commands.create({
|
||||
* name: 'test',
|
||||
* description: 'A test command',
|
||||
* })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async create(command, guildId) {
|
||||
const data = await this.client.rest.post(this.commandPath({ guildId }), {
|
||||
body: this.constructor.transformCommand(command),
|
||||
});
|
||||
return this._add(data, true, guildId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets all the commands for this application or guild.
|
||||
* @param {ApplicationCommandDataResolvable[]} commands The commands
|
||||
* @param {Snowflake} [guildId] The guild's id to create the commands in,
|
||||
* ignored when using a {@link GuildApplicationCommandManager}
|
||||
* @returns {Promise<Collection<Snowflake, ApplicationCommand>>}
|
||||
* @example
|
||||
* // Set all commands to just this one
|
||||
* client.application.commands.set([
|
||||
* {
|
||||
* name: 'test',
|
||||
* description: 'A test command',
|
||||
* },
|
||||
* ])
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Remove all commands
|
||||
* guild.commands.set([])
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async set(commands, guildId) {
|
||||
const data = await this.client.rest.put(this.commandPath({ guildId }), {
|
||||
body: commands.map(command => this.constructor.transformCommand(command)),
|
||||
});
|
||||
return data.reduce(
|
||||
(collection, command) => collection.set(command.id, this._add(command, true, guildId)),
|
||||
new Collection(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits an application command.
|
||||
* @param {ApplicationCommandResolvable} command The command to edit
|
||||
* @param {Partial<ApplicationCommandDataResolvable>} data The data to update the command with
|
||||
* @param {Snowflake} [guildId] The guild's id where the command registered,
|
||||
* ignored when using a {@link GuildApplicationCommandManager}
|
||||
* @returns {Promise<ApplicationCommand>}
|
||||
* @example
|
||||
* // Edit an existing command
|
||||
* client.application.commands.edit('123456789012345678', {
|
||||
* description: 'New description',
|
||||
* })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async edit(command, data, guildId) {
|
||||
const id = this.resolveId(command);
|
||||
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'command', 'ApplicationCommandResolvable');
|
||||
|
||||
const patched = await this.client.rest.patch(this.commandPath({ id, guildId }), {
|
||||
body: this.constructor.transformCommand(data),
|
||||
});
|
||||
return this._add(patched, true, guildId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an application command.
|
||||
* @param {ApplicationCommandResolvable} command The command to delete
|
||||
* @param {Snowflake} [guildId] The guild's id where the command is registered,
|
||||
* ignored when using a {@link GuildApplicationCommandManager}
|
||||
* @returns {Promise<?ApplicationCommand>}
|
||||
* @example
|
||||
* // Delete a command
|
||||
* guild.commands.delete('123456789012345678')
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async delete(command, guildId) {
|
||||
const id = this.resolveId(command);
|
||||
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'command', 'ApplicationCommandResolvable');
|
||||
|
||||
await this.client.rest.delete(this.commandPath({ id, guildId }));
|
||||
|
||||
const cached = this.cache.get(id);
|
||||
this.cache.delete(id);
|
||||
return cached ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms an {@link ApplicationCommandData} object into something that can be used with the API.
|
||||
* @param {ApplicationCommandDataResolvable} command The command to transform
|
||||
* @returns {APIApplicationCommand}
|
||||
* @private
|
||||
*/
|
||||
static transformCommand(command) {
|
||||
if (isJSONEncodable(command)) return command.toJSON();
|
||||
|
||||
let default_member_permissions;
|
||||
|
||||
if ('default_member_permissions' in command) {
|
||||
default_member_permissions = command.default_member_permissions
|
||||
? new PermissionsBitField(BigInt(command.default_member_permissions)).bitfield.toString()
|
||||
: command.default_member_permissions;
|
||||
}
|
||||
|
||||
if ('defaultMemberPermissions' in command) {
|
||||
default_member_permissions =
|
||||
command.defaultMemberPermissions !== null
|
||||
? new PermissionsBitField(command.defaultMemberPermissions).bitfield.toString()
|
||||
: command.defaultMemberPermissions;
|
||||
}
|
||||
|
||||
return {
|
||||
name: command.name,
|
||||
name_localizations: command.nameLocalizations ?? command.name_localizations,
|
||||
description: command.description,
|
||||
nsfw: command.nsfw,
|
||||
description_localizations: command.descriptionLocalizations ?? command.description_localizations,
|
||||
type: command.type,
|
||||
options: command.options?.map(option => ApplicationCommand.transformOption(option)),
|
||||
default_member_permissions,
|
||||
dm_permission: command.dmPermission ?? command.dm_permission,
|
||||
integration_types: command.integrationTypes ?? command.integration_types,
|
||||
contexts: command.contexts,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ApplicationCommandManager;
|
||||
428
node_modules/discord.js/src/managers/ApplicationCommandPermissionsManager.js
generated
vendored
Normal file
428
node_modules/discord.js/src/managers/ApplicationCommandPermissionsManager.js
generated
vendored
Normal file
@@ -0,0 +1,428 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { ApplicationCommandPermissionType, RESTJSONErrorCodes, Routes } = require('discord-api-types/v10');
|
||||
const BaseManager = require('./BaseManager');
|
||||
const { DiscordjsError, DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
|
||||
/**
|
||||
* Manages API methods for permissions of Application Commands.
|
||||
* @extends {BaseManager}
|
||||
*/
|
||||
class ApplicationCommandPermissionsManager extends BaseManager {
|
||||
constructor(manager) {
|
||||
super(manager.client);
|
||||
|
||||
/**
|
||||
* The manager or command that this manager belongs to
|
||||
* @type {ApplicationCommandManager|ApplicationCommand}
|
||||
* @private
|
||||
*/
|
||||
this.manager = manager;
|
||||
|
||||
/**
|
||||
* The guild that this manager acts on
|
||||
* @type {?Guild}
|
||||
*/
|
||||
this.guild = manager.guild ?? null;
|
||||
|
||||
/**
|
||||
* The id of the guild that this manager acts on
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.guildId = manager.guildId ?? manager.guild?.id ?? null;
|
||||
|
||||
/**
|
||||
* The id of the command this manager acts on
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.commandId = manager.id ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The APIRouter path to the commands
|
||||
* @param {Snowflake} guildId The guild's id to use in the path,
|
||||
* @param {Snowflake} [commandId] The application command's id
|
||||
* @returns {string}
|
||||
* @private
|
||||
*/
|
||||
permissionsPath(guildId, commandId) {
|
||||
if (commandId) {
|
||||
return Routes.applicationCommandPermissions(this.client.application.id, guildId, commandId);
|
||||
}
|
||||
|
||||
return Routes.guildApplicationCommandsPermissions(this.client.application.id, guildId);
|
||||
}
|
||||
|
||||
/* eslint-disable max-len */
|
||||
/**
|
||||
* The object returned when fetching permissions for an application command.
|
||||
* @typedef {Object} ApplicationCommandPermissions
|
||||
* @property {Snowflake} id The role, user, or channel's id. Can also be a
|
||||
* {@link https://discord.com/developers/docs/interactions/application-commands#application-command-permissions-object-application-command-permissions-constants permission constant}.
|
||||
* @property {ApplicationCommandPermissionType} type Whether this permission is for a role or a user
|
||||
* @property {boolean} permission Whether the role or user has the permission to use this command
|
||||
*/
|
||||
/* eslint-enable max-len */
|
||||
|
||||
/**
|
||||
* Options for managing permissions for one or more Application Commands
|
||||
* <warn>When passing these options to a manager where `guildId` is `null`,
|
||||
* `guild` is a required parameter</warn>
|
||||
* @typedef {Object} BaseApplicationCommandPermissionsOptions
|
||||
* @property {GuildResolvable} [guild] The guild to modify / check permissions for
|
||||
* <warn>Ignored when the manager has a non-null `guildId` property</warn>
|
||||
* @property {ApplicationCommandResolvable} [command] The command to modify / check permissions for
|
||||
* <warn>Ignored when the manager has a non-null `commandId` property</warn>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetches the permissions for one or multiple commands. Providing the client's id as the "command id" will fetch
|
||||
* *only* the guild level permissions
|
||||
* @param {BaseApplicationCommandPermissionsOptions} [options] Options used to fetch permissions
|
||||
* @returns {Promise<ApplicationCommandPermissions[]|Collection<Snowflake, ApplicationCommandPermissions[]>>}
|
||||
* @example
|
||||
* // Fetch permissions for one command
|
||||
* guild.commands.permissions.fetch({ command: '123456789012345678' })
|
||||
* .then(perms => console.log(`Fetched ${perms.length} overwrites`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch permissions for all commands in a guild
|
||||
* client.application.commands.permissions.fetch({ guild: '123456789012345678' })
|
||||
* .then(perms => console.log(`Fetched permissions for ${perms.size} commands`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch guild level permissions
|
||||
* guild.commands.permissions.fetch({ command: client.user.id })
|
||||
* .then(perms => console.log(`Fetched ${perms.length} guild level permissions`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetch({ guild, command } = {}) {
|
||||
const { guildId, commandId } = this._validateOptions(guild, command);
|
||||
if (commandId) {
|
||||
const data = await this.client.rest.get(this.permissionsPath(guildId, commandId));
|
||||
return data.permissions;
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(this.permissionsPath(guildId));
|
||||
return data.reduce((coll, perm) => coll.set(perm.id, perm.permissions), new Collection());
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to set permissions for one or more Application Commands in a guild
|
||||
* <warn>Omitting the `command` parameter edits the guild wide permissions
|
||||
* when the manager's `commandId` is `null`</warn>
|
||||
* @typedef {BaseApplicationCommandPermissionsOptions} ApplicationCommandPermissionsEditOptions
|
||||
* @property {ApplicationCommandPermissions[]} permissions The new permissions for the guild or overwrite
|
||||
* @property {string} token The bearer token to use that authorizes the permission edit
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sets the permissions for the guild or a command overwrite.
|
||||
* @param {ApplicationCommandPermissionsEditOptions} options Options used to set permissions
|
||||
* @returns {Promise<ApplicationCommandPermissions[]|Collection<Snowflake, ApplicationCommandPermissions[]>>}
|
||||
* @example
|
||||
* // Set a permission overwrite for a command
|
||||
* client.application.commands.permissions.set({
|
||||
* guild: '892455839386304532',
|
||||
* command: '123456789012345678',
|
||||
* token: 'TotallyRealToken',
|
||||
* permissions: [
|
||||
* {
|
||||
* id: '876543210987654321',
|
||||
* type: ApplicationCommandPermissionType.User,
|
||||
* permission: false,
|
||||
* },
|
||||
* ]})
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Set the permissions used for the guild (commands without overwrites)
|
||||
* guild.commands.permissions.set({ token: 'TotallyRealToken', permissions: [
|
||||
* {
|
||||
* id: '123456789012345678',
|
||||
* permissions: [{
|
||||
* id: '876543210987654321',
|
||||
* type: ApplicationCommandPermissionType.User,
|
||||
* permission: false,
|
||||
* }],
|
||||
* },
|
||||
* ]})
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async set({ guild, command, permissions, token } = {}) {
|
||||
if (!token) {
|
||||
throw new DiscordjsError(ErrorCodes.ApplicationCommandPermissionsTokenMissing);
|
||||
}
|
||||
let { guildId, commandId } = this._validateOptions(guild, command);
|
||||
|
||||
if (!Array.isArray(permissions)) {
|
||||
throw new DiscordjsTypeError(
|
||||
ErrorCodes.InvalidType,
|
||||
'permissions',
|
||||
'Array of ApplicationCommandPermissions',
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
if (!commandId) {
|
||||
commandId = this.client.user.id;
|
||||
}
|
||||
const data = await this.client.rest.put(this.permissionsPath(guildId, commandId), {
|
||||
body: { permissions },
|
||||
auth: false,
|
||||
headers: { Authorization: `Bearer ${token}` },
|
||||
});
|
||||
return data.permissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add permissions to a command.
|
||||
* @param {ApplicationCommandPermissionsEditOptions} options Options used to add permissions
|
||||
* @returns {Promise<ApplicationCommandPermissions[]>}
|
||||
* @example
|
||||
* // Add a rule to block a role from using a command
|
||||
* guild.commands.permissions.add({ command: '123456789012345678', token: 'TotallyRealToken', permissions: [
|
||||
* {
|
||||
* id: '876543211234567890',
|
||||
* type: ApplicationCommandPermissionType.Role,
|
||||
* permission: false
|
||||
* },
|
||||
* ]})
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async add({ guild, command, permissions, token } = {}) {
|
||||
if (!token) {
|
||||
throw new DiscordjsError(ErrorCodes.ApplicationCommandPermissionsTokenMissing);
|
||||
}
|
||||
let { guildId, commandId } = this._validateOptions(guild, command);
|
||||
if (!commandId) {
|
||||
commandId = this.client.user.id;
|
||||
}
|
||||
if (!Array.isArray(permissions)) {
|
||||
throw new DiscordjsTypeError(
|
||||
ErrorCodes.InvalidType,
|
||||
'permissions',
|
||||
'Array of ApplicationCommandPermissions',
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
let existingPermissions = [];
|
||||
try {
|
||||
existingPermissions = await this.fetch({ guild: guildId, command: commandId });
|
||||
} catch (error) {
|
||||
if (error.code !== RESTJSONErrorCodes.UnknownApplicationCommandPermissions) throw error;
|
||||
}
|
||||
|
||||
const newPermissions = permissions.slice();
|
||||
for (const existingPermission of existingPermissions) {
|
||||
if (!newPermissions.some(newPermission => newPermission.id === existingPermission.id)) {
|
||||
newPermissions.push(existingPermission);
|
||||
}
|
||||
}
|
||||
|
||||
return this.set({ guild: guildId, command: commandId, permissions: newPermissions, token });
|
||||
}
|
||||
|
||||
/**
|
||||
* A static snowflake that identifies the everyone role for application command permissions.
|
||||
* It is the same as the guild id
|
||||
* @typedef {Snowflake} RolePermissionConstant
|
||||
*/
|
||||
|
||||
/**
|
||||
* A static snowflake that identifies the "all channels" entity for application command permissions.
|
||||
* It will be the result of the calculation `guildId - 1`
|
||||
* @typedef {Snowflake} ChannelPermissionConstant
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to remove permissions from a command
|
||||
* <warn>Omitting the `command` parameter removes from the guild wide permissions
|
||||
* when the managers `commandId` is `null`</warn>
|
||||
* <warn>At least one of `users`, `roles`, and `channels` is required</warn>
|
||||
* @typedef {BaseApplicationCommandPermissionsOptions} RemoveApplicationCommandPermissionsOptions
|
||||
* @property {string} token The bearer token to use that authorizes the permission removal
|
||||
* @property {UserResolvable[]} [users] The user(s) to remove
|
||||
* @property {Array<RoleResolvable|RolePermissionConstant>} [roles] The role(s) to remove
|
||||
* @property {Array<GuildChannelResolvable|ChannelPermissionConstant>} [channels] The channel(s) to remove
|
||||
*/
|
||||
|
||||
/**
|
||||
* Remove permissions from a command.
|
||||
* @param {RemoveApplicationCommandPermissionsOptions} options Options used to remove permissions
|
||||
* @returns {Promise<ApplicationCommandPermissions[]>}
|
||||
* @example
|
||||
* // Remove a user permission from this command
|
||||
* guild.commands.permissions.remove({
|
||||
* command: '123456789012345678', users: '876543210123456789', token: 'TotallyRealToken',
|
||||
* })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Remove multiple roles from this command
|
||||
* guild.commands.permissions.remove({
|
||||
* command: '123456789012345678', roles: ['876543210123456789', '765432101234567890'], token: 'TotallyRealToken',
|
||||
* })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async remove({ guild, command, users, roles, channels, token } = {}) {
|
||||
if (!token) {
|
||||
throw new DiscordjsError(ErrorCodes.ApplicationCommandPermissionsTokenMissing);
|
||||
}
|
||||
let { guildId, commandId } = this._validateOptions(guild, command);
|
||||
if (!commandId) {
|
||||
commandId = this.client.user.id;
|
||||
}
|
||||
|
||||
if (!users && !roles && !channels) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'users OR roles OR channels', 'Array or Resolvable', true);
|
||||
}
|
||||
|
||||
let resolvedUserIds = [];
|
||||
if (Array.isArray(users)) {
|
||||
for (const user of users) {
|
||||
const userId = this.client.users.resolveId(user);
|
||||
if (!userId) throw new DiscordjsTypeError(ErrorCodes.InvalidElement, 'Array', 'users', user);
|
||||
resolvedUserIds.push(userId);
|
||||
}
|
||||
}
|
||||
|
||||
let resolvedRoleIds = [];
|
||||
if (Array.isArray(roles)) {
|
||||
for (const role of roles) {
|
||||
if (typeof role === 'string') {
|
||||
resolvedRoleIds.push(role);
|
||||
continue;
|
||||
}
|
||||
if (!this.guild) throw new DiscordjsError(ErrorCodes.GuildUncachedEntityResolve, 'roles');
|
||||
const roleId = this.guild.roles.resolveId(role);
|
||||
if (!roleId) throw new DiscordjsTypeError(ErrorCodes.InvalidElement, 'Array', 'users', role);
|
||||
resolvedRoleIds.push(roleId);
|
||||
}
|
||||
}
|
||||
|
||||
let resolvedChannelIds = [];
|
||||
if (Array.isArray(channels)) {
|
||||
for (const channel of channels) {
|
||||
if (typeof channel === 'string') {
|
||||
resolvedChannelIds.push(channel);
|
||||
continue;
|
||||
}
|
||||
if (!this.guild) throw new DiscordjsError(ErrorCodes.GuildUncachedEntityResolve, 'channels');
|
||||
const channelId = this.guild.channels.resolveId(channel);
|
||||
if (!channelId) throw new DiscordjsTypeError(ErrorCodes.InvalidElement, 'Array', 'channels', channel);
|
||||
resolvedChannelIds.push(channelId);
|
||||
}
|
||||
}
|
||||
|
||||
let existing = [];
|
||||
try {
|
||||
existing = await this.fetch({ guild: guildId, command: commandId });
|
||||
} catch (error) {
|
||||
if (error.code !== RESTJSONErrorCodes.UnknownApplicationCommandPermissions) throw error;
|
||||
}
|
||||
|
||||
const permissions = existing.filter(perm => {
|
||||
switch (perm.type) {
|
||||
case ApplicationCommandPermissionType.Role:
|
||||
return !resolvedRoleIds.includes(perm.id);
|
||||
case ApplicationCommandPermissionType.User:
|
||||
return !resolvedUserIds.includes(perm.id);
|
||||
case ApplicationCommandPermissionType.Channel:
|
||||
return !resolvedChannelIds.includes(perm.id);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
return this.set({ guild: guildId, command: commandId, permissions, token });
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to check the existence of permissions on a command
|
||||
* <warn>The `command` parameter is not optional when the managers `commandId` is `null`</warn>
|
||||
* @typedef {BaseApplicationCommandPermissionsOptions} HasApplicationCommandPermissionsOptions
|
||||
* @property {ApplicationCommandPermissionIdResolvable} permissionId The entity to check if a permission exists for
|
||||
* on this command.
|
||||
* @property {ApplicationCommandPermissionType} [permissionType] Check for a specific type of permission
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check whether a permission exists for a user, role, or channel
|
||||
* @param {HasApplicationCommandPermissionsOptions} options Options used to check permissions
|
||||
* @returns {Promise<boolean>}
|
||||
* @example
|
||||
* guild.commands.permissions.has({ command: '123456789012345678', permissionId: '876543210123456789' })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async has({ guild, command, permissionId, permissionType }) {
|
||||
const { guildId, commandId } = this._validateOptions(guild, command);
|
||||
if (!commandId) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'command', 'ApplicationCommandResolvable');
|
||||
|
||||
if (!permissionId) {
|
||||
throw new DiscordjsTypeError(
|
||||
ErrorCodes.InvalidType,
|
||||
'permissionId',
|
||||
'UserResolvable, RoleResolvable, ChannelResolvable, or Permission Constant',
|
||||
);
|
||||
}
|
||||
let resolvedId = permissionId;
|
||||
if (typeof permissionId !== 'string') {
|
||||
resolvedId = this.client.users.resolveId(permissionId);
|
||||
if (!resolvedId) {
|
||||
if (!this.guild) throw new DiscordjsError(ErrorCodes.GuildUncachedEntityResolve, 'roles');
|
||||
resolvedId = this.guild.roles.resolveId(permissionId);
|
||||
}
|
||||
if (!resolvedId) {
|
||||
resolvedId = this.guild.channels.resolveId(permissionId);
|
||||
}
|
||||
if (!resolvedId) {
|
||||
throw new DiscordjsTypeError(
|
||||
ErrorCodes.InvalidType,
|
||||
'permissionId',
|
||||
'UserResolvable, RoleResolvable, ChannelResolvable, or Permission Constant',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let existing = [];
|
||||
try {
|
||||
existing = await this.fetch({ guild: guildId, command: commandId });
|
||||
} catch (error) {
|
||||
if (error.code !== RESTJSONErrorCodes.UnknownApplicationCommandPermissions) throw error;
|
||||
}
|
||||
|
||||
// Check permission type if provided for the single edge case where a channel id is the same as the everyone role id
|
||||
return existing.some(perm => perm.id === resolvedId && (permissionType ?? perm.type) === perm.type);
|
||||
}
|
||||
|
||||
_validateOptions(guild, command) {
|
||||
const guildId = this.guildId ?? this.client.guilds.resolveId(guild);
|
||||
if (!guildId) throw new DiscordjsError(ErrorCodes.GlobalCommandPermissions);
|
||||
let commandId = this.commandId;
|
||||
if (command && !commandId) {
|
||||
commandId = this.manager.resolveId?.(command);
|
||||
if (!commandId && this.guild) {
|
||||
commandId = this.guild.commands.resolveId(command);
|
||||
}
|
||||
commandId ??= this.client.application?.commands.resolveId(command);
|
||||
if (!commandId) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'command', 'ApplicationCommandResolvable', true);
|
||||
}
|
||||
}
|
||||
return { guildId, commandId };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ApplicationCommandPermissionsManager;
|
||||
|
||||
/* eslint-disable max-len */
|
||||
/**
|
||||
* Data that resolves to an id used for an application command permission
|
||||
* @typedef {UserResolvable|RoleResolvable|GuildChannelResolvable|RolePermissionConstant|ChannelPermissionConstant} ApplicationCommandPermissionIdResolvable
|
||||
*/
|
||||
142
node_modules/discord.js/src/managers/ApplicationEmojiManager.js
generated
vendored
Normal file
142
node_modules/discord.js/src/managers/ApplicationEmojiManager.js
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
const ApplicationEmoji = require('../structures/ApplicationEmoji');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
|
||||
/**
|
||||
* Manages API methods for ApplicationEmojis and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class ApplicationEmojiManager extends CachedManager {
|
||||
constructor(application, iterable) {
|
||||
super(application.client, ApplicationEmoji, iterable);
|
||||
|
||||
/**
|
||||
* The application this manager belongs to
|
||||
* @type {ClientApplication}
|
||||
*/
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
_add(data, cache) {
|
||||
return super._add(data, cache, { extras: [this.application] });
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used for creating an emoji of the application
|
||||
* @typedef {Object} ApplicationEmojiCreateOptions
|
||||
* @property {BufferResolvable|Base64Resolvable} attachment The image for the emoji
|
||||
* @property {string} name The name for the emoji
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new custom emoji of the application.
|
||||
* @param {ApplicationEmojiCreateOptions} options Options for creating the emoji
|
||||
* @returns {Promise<Emoji>} The created emoji
|
||||
* @example
|
||||
* // Create a new emoji from a URL
|
||||
* application.emojis.create({ attachment: 'https://i.imgur.com/w3duR07.png', name: 'rip' })
|
||||
* .then(emoji => console.log(`Created new emoji with name ${emoji.name}!`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Create a new emoji from a file on your computer
|
||||
* application.emojis.create({ attachment: './memes/banana.png', name: 'banana' })
|
||||
* .then(emoji => console.log(`Created new emoji with name ${emoji.name}!`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async create({ attachment, name }) {
|
||||
attachment = await resolveImage(attachment);
|
||||
if (!attachment) throw new DiscordjsTypeError(ErrorCodes.ReqResourceType);
|
||||
|
||||
const body = { image: attachment, name };
|
||||
|
||||
const emoji = await this.client.rest.post(Routes.applicationEmojis(this.application.id), { body });
|
||||
return this._add(emoji);
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains one or more emojis from Discord, or the emoji cache if they're already available.
|
||||
* @param {Snowflake} [id] The emoji's id
|
||||
* @param {BaseFetchOptions} [options] Additional options for this fetch
|
||||
* @returns {Promise<ApplicationEmoji|Collection<Snowflake, ApplicationEmoji>>}
|
||||
* @example
|
||||
* // Fetch all emojis from the application
|
||||
* application.emojis.fetch()
|
||||
* .then(emojis => console.log(`There are ${emojis.size} emojis.`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch a single emoji
|
||||
* application.emojis.fetch('222078108977594368')
|
||||
* .then(emoji => console.log(`The emoji name is: ${emoji.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetch(id, { cache = true, force = false } = {}) {
|
||||
if (id) {
|
||||
if (!force) {
|
||||
const existing = this.cache.get(id);
|
||||
if (existing) return existing;
|
||||
}
|
||||
const emoji = await this.client.rest.get(Routes.applicationEmoji(this.application.id, id));
|
||||
return this._add(emoji, cache);
|
||||
}
|
||||
|
||||
const { items: data } = await this.client.rest.get(Routes.applicationEmojis(this.application.id));
|
||||
const emojis = new Collection();
|
||||
for (const emoji of data) emojis.set(emoji.id, this._add(emoji, cache));
|
||||
return emojis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an emoji.
|
||||
* @param {EmojiResolvable} emoji The Emoji resolvable to delete
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async delete(emoji) {
|
||||
const id = this.resolveId(emoji);
|
||||
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'emoji', 'EmojiResolvable', true);
|
||||
await this.client.rest.delete(Routes.applicationEmoji(this.application.id, id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits an emoji.
|
||||
* @param {EmojiResolvable} emoji The Emoji resolvable to edit
|
||||
* @param {ApplicationEmojiEditOptions} options The options to provide
|
||||
* @returns {Promise<ApplicationEmoji>}
|
||||
*/
|
||||
async edit(emoji, options) {
|
||||
const id = this.resolveId(emoji);
|
||||
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'emoji', 'EmojiResolvable', true);
|
||||
|
||||
const newData = await this.client.rest.patch(Routes.applicationEmoji(this.application.id, id), {
|
||||
body: {
|
||||
name: options.name,
|
||||
},
|
||||
});
|
||||
const existing = this.cache.get(id);
|
||||
if (existing) {
|
||||
existing._patch(newData);
|
||||
return existing;
|
||||
}
|
||||
return this._add(newData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the author for this emoji
|
||||
* @param {EmojiResolvable} emoji The emoji to fetch the author of
|
||||
* @returns {Promise<User>}
|
||||
*/
|
||||
async fetchAuthor(emoji) {
|
||||
const id = this.resolveId(emoji);
|
||||
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'emoji', 'EmojiResolvable', true);
|
||||
|
||||
const data = await this.client.rest.get(Routes.applicationEmoji(this.application.id, id));
|
||||
|
||||
return this._add(data).author;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ApplicationEmojiManager;
|
||||
292
node_modules/discord.js/src/managers/AutoModerationRuleManager.js
generated
vendored
Normal file
292
node_modules/discord.js/src/managers/AutoModerationRuleManager.js
generated
vendored
Normal file
@@ -0,0 +1,292 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const AutoModerationRule = require('../structures/AutoModerationRule');
|
||||
|
||||
/**
|
||||
* Manages API methods for auto moderation rules and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class AutoModerationRuleManager extends CachedManager {
|
||||
constructor(guild, iterable) {
|
||||
super(guild.client, AutoModerationRule, iterable);
|
||||
|
||||
/**
|
||||
* The guild this manager belongs to.
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of this manager
|
||||
* @type {Collection<Snowflake, AutoModerationRule>}
|
||||
* @name AutoModerationRuleManager#cache
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves an {@link AutoModerationRuleResolvable} to an {@link AutoModerationRule} object.
|
||||
* @method resolve
|
||||
* @memberof AutoModerationRuleManager
|
||||
* @instance
|
||||
* @param {AutoModerationRuleResolvable} autoModerationRule The AutoModerationRule resolvable to resolve
|
||||
* @returns {?AutoModerationRule}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves an {@link AutoModerationRuleResolvable} to a {@link AutoModerationRule} id.
|
||||
* @method resolveId
|
||||
* @memberof AutoModerationRuleManager
|
||||
* @instance
|
||||
* @param {AutoModerationRuleResolvable} autoModerationRule The AutoModerationRule resolvable to resolve
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
|
||||
_add(data, cache) {
|
||||
return super._add(data, cache, { extras: [this.guild] });
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to set the trigger metadata of an auto moderation rule.
|
||||
* @typedef {Object} AutoModerationTriggerMetadataOptions
|
||||
* @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 to automatically detect mention raids
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to set the actions of an auto moderation rule.
|
||||
* @typedef {Object} AutoModerationActionOptions
|
||||
* @property {AutoModerationActionType} type The type of this auto moderation rule action
|
||||
* @property {AutoModerationActionMetadataOptions} [metadata] Additional metadata needed during execution
|
||||
* <info>This property is required if using a `type` of
|
||||
* {@link AutoModerationActionType.SendAlertMessage} or {@link AutoModerationActionType.Timeout}.</info>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to set the metadata of an auto moderation rule action.
|
||||
* @typedef {Object} AutoModerationActionMetadataOptions
|
||||
* @property {GuildTextChannelResolvable|ThreadChannel} [channel] 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
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to create an auto moderation rule.
|
||||
* @typedef {Object} AutoModerationRuleCreateOptions
|
||||
* @property {string} name The name of the auto moderation rule
|
||||
* @property {AutoModerationRuleEventType} eventType The event type of the auto moderation rule
|
||||
* @property {AutoModerationRuleTriggerType} triggerType The trigger type of the auto moderation rule
|
||||
* @property {AutoModerationTriggerMetadataOptions} [triggerMetadata] The trigger metadata of the auto moderation rule
|
||||
* <info>This property is required if using a `triggerType` of
|
||||
* {@link AutoModerationRuleTriggerType.Keyword},
|
||||
* {@link AutoModerationRuleTriggerType.KeywordPreset},
|
||||
* {@link AutoModerationRuleTriggerType.MentionSpam},
|
||||
* or {@link AutoModerationRuleTriggerType.MemberProfile}.</info>
|
||||
* @property {AutoModerationActionOptions[]} actions
|
||||
* The actions that will execute when the auto moderation rule is triggered
|
||||
* @property {boolean} [enabled] Whether the auto moderation rule should be enabled
|
||||
* @property {Collection<Snowflake, Role>|RoleResolvable[]} [exemptRoles]
|
||||
* The roles that should not be affected by the auto moderation rule
|
||||
* @property {Collection<Snowflake, GuildChannel|ThreadChannel>|GuildChannelResolvable[]} [exemptChannels]
|
||||
* The channels that should not be affected by the auto moderation rule
|
||||
* @property {string} [reason] The reason for creating the auto moderation rule
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new auto moderation rule.
|
||||
* @param {AutoModerationRuleCreateOptions} options Options for creating the auto moderation rule
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
async create({
|
||||
name,
|
||||
eventType,
|
||||
triggerType,
|
||||
triggerMetadata,
|
||||
actions,
|
||||
enabled,
|
||||
exemptRoles,
|
||||
exemptChannels,
|
||||
reason,
|
||||
}) {
|
||||
const data = await this.client.rest.post(Routes.guildAutoModerationRules(this.guild.id), {
|
||||
body: {
|
||||
name,
|
||||
event_type: eventType,
|
||||
trigger_type: triggerType,
|
||||
trigger_metadata: triggerMetadata && {
|
||||
keyword_filter: triggerMetadata.keywordFilter,
|
||||
regex_patterns: triggerMetadata.regexPatterns,
|
||||
presets: triggerMetadata.presets,
|
||||
allow_list: triggerMetadata.allowList,
|
||||
mention_total_limit: triggerMetadata.mentionTotalLimit,
|
||||
mention_raid_protection_enabled: triggerMetadata.mentionRaidProtectionEnabled,
|
||||
},
|
||||
actions: actions.map(action => ({
|
||||
type: action.type,
|
||||
metadata: {
|
||||
duration_seconds: action.metadata?.durationSeconds,
|
||||
channel_id: action.metadata?.channel && this.guild.channels.resolveId(action.metadata.channel),
|
||||
custom_message: action.metadata?.customMessage,
|
||||
},
|
||||
})),
|
||||
enabled,
|
||||
exempt_roles: exemptRoles?.map(exemptRole => this.guild.roles.resolveId(exemptRole)),
|
||||
exempt_channels: exemptChannels?.map(exemptChannel => this.guild.channels.resolveId(exemptChannel)),
|
||||
},
|
||||
reason,
|
||||
});
|
||||
|
||||
return this._add(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to edit an auto moderation rule.
|
||||
* @typedef {Object} AutoModerationRuleEditOptions
|
||||
* @property {string} [name] The name of the auto moderation rule
|
||||
* @property {AutoModerationRuleEventType} [eventType] The event type of the auto moderation rule
|
||||
* @property {AutoModerationTriggerMetadataOptions} [triggerMetadata] The trigger metadata of the auto moderation rule
|
||||
* @property {AutoModerationActionOptions[]} [actions]
|
||||
* The actions that will execute when the auto moderation rule is triggered
|
||||
* @property {boolean} [enabled] Whether the auto moderation rule should be enabled
|
||||
* @property {Collection<Snowflake, Role>|RoleResolvable[]} [exemptRoles]
|
||||
* The roles that should not be affected by the auto moderation rule
|
||||
* @property {Collection<Snowflake, GuildChannel|ThreadChannel>|GuildChannelResolvable[]} [exemptChannels]
|
||||
* The channels that should not be affected by the auto moderation rule
|
||||
* @property {string} [reason] The reason for creating the auto moderation rule
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits an auto moderation rule.
|
||||
* @param {AutoModerationRuleResolvable} autoModerationRule The auto moderation rule to edit
|
||||
* @param {AutoModerationRuleEditOptions} options Options for editing the auto moderation rule
|
||||
* @returns {Promise<AutoModerationRule>}
|
||||
*/
|
||||
async edit(
|
||||
autoModerationRule,
|
||||
{ name, eventType, triggerMetadata, actions, enabled, exemptRoles, exemptChannels, reason },
|
||||
) {
|
||||
const autoModerationRuleId = this.resolveId(autoModerationRule);
|
||||
|
||||
const data = await this.client.rest.patch(Routes.guildAutoModerationRule(this.guild.id, autoModerationRuleId), {
|
||||
body: {
|
||||
name,
|
||||
event_type: eventType,
|
||||
trigger_metadata: triggerMetadata && {
|
||||
keyword_filter: triggerMetadata.keywordFilter,
|
||||
regex_patterns: triggerMetadata.regexPatterns,
|
||||
presets: triggerMetadata.presets,
|
||||
allow_list: triggerMetadata.allowList,
|
||||
mention_total_limit: triggerMetadata.mentionTotalLimit,
|
||||
mention_raid_protection_enabled: triggerMetadata.mentionRaidProtectionEnabled,
|
||||
},
|
||||
actions: actions?.map(action => ({
|
||||
type: action.type,
|
||||
metadata: {
|
||||
duration_seconds: action.metadata?.durationSeconds,
|
||||
channel_id: action.metadata?.channel && this.guild.channels.resolveId(action.metadata.channel),
|
||||
custom_message: action.metadata?.customMessage,
|
||||
},
|
||||
})),
|
||||
enabled,
|
||||
exempt_roles: exemptRoles?.map(exemptRole => this.guild.roles.resolveId(exemptRole)),
|
||||
exempt_channels: exemptChannels?.map(exemptChannel => this.guild.channels.resolveId(exemptChannel)),
|
||||
},
|
||||
reason,
|
||||
});
|
||||
|
||||
return this._add(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to give an AutoModerationRule object. This can be:
|
||||
* * An AutoModerationRule
|
||||
* * A Snowflake
|
||||
* @typedef {AutoModerationRule|Snowflake} AutoModerationRuleResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch a single auto moderation rule from a guild.
|
||||
* @typedef {BaseFetchOptions} FetchAutoModerationRuleOptions
|
||||
* @property {AutoModerationRuleResolvable} autoModerationRule The auto moderation rule to fetch
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch all auto moderation rules from a guild.
|
||||
* @typedef {Object} FetchAutoModerationRulesOptions
|
||||
* @property {boolean} [cache] Whether to cache the fetched auto moderation rules
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetches auto moderation rules from Discord.
|
||||
* @param {AutoModerationRuleResolvable|FetchAutoModerationRuleOptions|FetchAutoModerationRulesOptions} [options]
|
||||
* Options for fetching auto moderation rule(s)
|
||||
* @returns {Promise<AutoModerationRule|Collection<Snowflake, AutoModerationRule>>}
|
||||
* @example
|
||||
* // Fetch all auto moderation rules from a guild without caching
|
||||
* guild.autoModerationRules.fetch({ cache: false })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch a single auto moderation rule
|
||||
* guild.autoModerationRules.fetch('979083472868098119')
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch a single auto moderation rule without checking cache and without caching
|
||||
* guild.autoModerationRules.fetch({ autoModerationRule: '979083472868098119', cache: false, force: true })
|
||||
* .then(console.log)
|
||||
* .catch(console.error)
|
||||
*/
|
||||
fetch(options) {
|
||||
if (!options) return this._fetchMany();
|
||||
const { autoModerationRule, cache, force } = options;
|
||||
const resolvedAutoModerationRule = this.resolveId(autoModerationRule ?? options);
|
||||
if (resolvedAutoModerationRule) {
|
||||
return this._fetchSingle({ autoModerationRule: resolvedAutoModerationRule, cache, force });
|
||||
}
|
||||
return this._fetchMany(options);
|
||||
}
|
||||
|
||||
async _fetchSingle({ autoModerationRule, cache, force = false }) {
|
||||
if (!force) {
|
||||
const existing = this.cache.get(autoModerationRule);
|
||||
if (existing) return existing;
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(Routes.guildAutoModerationRule(this.guild.id, autoModerationRule));
|
||||
return this._add(data, cache);
|
||||
}
|
||||
|
||||
async _fetchMany(options = {}) {
|
||||
const data = await this.client.rest.get(Routes.guildAutoModerationRules(this.guild.id));
|
||||
|
||||
return data.reduce(
|
||||
(col, autoModerationRule) => col.set(autoModerationRule.id, this._add(autoModerationRule, options.cache)),
|
||||
new Collection(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an auto moderation rule.
|
||||
* @param {AutoModerationRuleResolvable} autoModerationRule The auto moderation rule to delete
|
||||
* @param {string} [reason] The reason for deleting the auto moderation rule
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async delete(autoModerationRule, reason) {
|
||||
const autoModerationRuleId = this.resolveId(autoModerationRule);
|
||||
await this.client.rest.delete(Routes.guildAutoModerationRule(this.guild.id, autoModerationRuleId), { reason });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AutoModerationRuleManager;
|
||||
80
node_modules/discord.js/src/managers/BaseGuildEmojiManager.js
generated
vendored
Normal file
80
node_modules/discord.js/src/managers/BaseGuildEmojiManager.js
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
'use strict';
|
||||
|
||||
const CachedManager = require('./CachedManager');
|
||||
const GuildEmoji = require('../structures/GuildEmoji');
|
||||
const ReactionEmoji = require('../structures/ReactionEmoji');
|
||||
const { parseEmoji } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Holds methods to resolve GuildEmojis and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class BaseGuildEmojiManager extends CachedManager {
|
||||
constructor(client, iterable) {
|
||||
super(client, GuildEmoji, iterable);
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of GuildEmojis
|
||||
* @type {Collection<Snowflake, GuildEmoji>}
|
||||
* @name BaseGuildEmojiManager#cache
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data that can be resolved into a GuildEmoji object. This can be:
|
||||
* * A Snowflake
|
||||
* * A GuildEmoji object
|
||||
* * A ReactionEmoji object
|
||||
* @typedef {Snowflake|GuildEmoji|ReactionEmoji} EmojiResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves an EmojiResolvable to an Emoji object.
|
||||
* @param {EmojiResolvable} emoji The Emoji resolvable to identify
|
||||
* @returns {?GuildEmoji}
|
||||
*/
|
||||
resolve(emoji) {
|
||||
if (emoji instanceof ReactionEmoji) return super.resolve(emoji.id);
|
||||
return super.resolve(emoji);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves an EmojiResolvable to an Emoji id string.
|
||||
* @param {EmojiResolvable} emoji The Emoji resolvable to identify
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
resolveId(emoji) {
|
||||
if (emoji instanceof ReactionEmoji) return emoji.id;
|
||||
return super.resolveId(emoji);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to give an emoji identifier. This can be:
|
||||
* * An EmojiResolvable
|
||||
* * The `<a:name:id>`, `<:name:id>`, `a:name:id` or `name:id` emoji identifier string of an emoji
|
||||
* * The Unicode representation of an emoji
|
||||
* @typedef {string|EmojiResolvable} EmojiIdentifierResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves an EmojiResolvable to an emoji identifier.
|
||||
* @param {EmojiIdentifierResolvable} emoji The emoji resolvable to resolve
|
||||
* @returns {?string}
|
||||
*/
|
||||
resolveIdentifier(emoji) {
|
||||
const emojiResolvable = this.resolve(emoji);
|
||||
if (emojiResolvable) return emojiResolvable.identifier;
|
||||
if (emoji instanceof ReactionEmoji) return emoji.identifier;
|
||||
if (typeof emoji === 'string') {
|
||||
const res = parseEmoji(emoji);
|
||||
if (res?.name.length) {
|
||||
emoji = `${res.animated ? 'a:' : ''}${res.name}${res.id ? `:${res.id}` : ''}`;
|
||||
}
|
||||
if (!emoji.includes('%')) return encodeURIComponent(emoji);
|
||||
return emoji;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BaseGuildEmojiManager;
|
||||
19
node_modules/discord.js/src/managers/BaseManager.js
generated
vendored
Normal file
19
node_modules/discord.js/src/managers/BaseManager.js
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Manages the API methods of a data model.
|
||||
* @abstract
|
||||
*/
|
||||
class BaseManager {
|
||||
constructor(client) {
|
||||
/**
|
||||
* The client that instantiated this Manager
|
||||
* @name BaseManager#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BaseManager;
|
||||
64
node_modules/discord.js/src/managers/CachedManager.js
generated
vendored
Normal file
64
node_modules/discord.js/src/managers/CachedManager.js
generated
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
'use strict';
|
||||
|
||||
const DataManager = require('./DataManager');
|
||||
const { MakeCacheOverrideSymbol } = require('../util/Symbols');
|
||||
|
||||
/**
|
||||
* Manages the API methods of a data model with a mutable cache of instances.
|
||||
* @extends {DataManager}
|
||||
* @abstract
|
||||
*/
|
||||
class CachedManager extends DataManager {
|
||||
constructor(client, holds, iterable) {
|
||||
super(client, holds);
|
||||
|
||||
/**
|
||||
* The private cache of items for this manager.
|
||||
* @type {Collection}
|
||||
* @private
|
||||
* @readonly
|
||||
* @name CachedManager#_cache
|
||||
*/
|
||||
Object.defineProperty(this, '_cache', {
|
||||
value: this.client.options.makeCache(
|
||||
this.constructor[MakeCacheOverrideSymbol] ?? this.constructor,
|
||||
this.holds,
|
||||
this.constructor,
|
||||
),
|
||||
});
|
||||
|
||||
if (iterable) {
|
||||
for (const item of iterable) {
|
||||
this._add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of items for this manager.
|
||||
* @type {Collection}
|
||||
* @abstract
|
||||
*/
|
||||
get cache() {
|
||||
return this._cache;
|
||||
}
|
||||
|
||||
_add(data, cache = true, { id, extras = [] } = {}) {
|
||||
const existing = this.cache.get(id ?? data.id);
|
||||
if (existing) {
|
||||
if (cache) {
|
||||
existing._patch(data);
|
||||
return existing;
|
||||
}
|
||||
const clone = existing._clone();
|
||||
clone._patch(data);
|
||||
return clone;
|
||||
}
|
||||
|
||||
const entry = this.holds ? new this.holds(this.client, data, ...extras) : data;
|
||||
if (cache) this.cache.set(id ?? entry.id, entry);
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CachedManager;
|
||||
79
node_modules/discord.js/src/managers/CategoryChannelChildManager.js
generated
vendored
Normal file
79
node_modules/discord.js/src/managers/CategoryChannelChildManager.js
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
'use strict';
|
||||
|
||||
const DataManager = require('./DataManager');
|
||||
const GuildChannel = require('../structures/GuildChannel');
|
||||
|
||||
/**
|
||||
* Manages API methods for CategoryChannels' children.
|
||||
* @extends {DataManager}
|
||||
*/
|
||||
class CategoryChannelChildManager extends DataManager {
|
||||
constructor(channel) {
|
||||
super(channel.client, GuildChannel);
|
||||
/**
|
||||
* The category channel this manager belongs to
|
||||
* @type {CategoryChannel}
|
||||
*/
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* The channels that are a part of this category
|
||||
* @type {Collection<Snowflake, GuildChannel>}
|
||||
* @readonly
|
||||
*/
|
||||
get cache() {
|
||||
return this.guild.channels.cache.filter(channel => channel.parentId === this.channel.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The guild this manager belongs to
|
||||
* @type {Guild}
|
||||
* @readonly
|
||||
*/
|
||||
get guild() {
|
||||
return this.channel.guild;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for creating a channel using {@link CategoryChannelChildManager#create}.
|
||||
* @typedef {Object} CategoryCreateChannelOptions
|
||||
* @property {string} name The name for the new channel
|
||||
* @property {ChannelType} [type=ChannelType.GuildText] The type of the new channel.
|
||||
* @property {string} [topic] The topic for the new channel
|
||||
* @property {boolean} [nsfw] Whether the new channel is NSFW
|
||||
* @property {number} [bitrate] Bitrate of the new channel in bits (only voice)
|
||||
* @property {number} [userLimit] Maximum amount of users allowed in the new channel (only voice)
|
||||
* @property {OverwriteResolvable[]|Collection<Snowflake, OverwriteResolvable>} [permissionOverwrites]
|
||||
* Permission overwrites of the new channel
|
||||
* @property {number} [position] Position of the new channel
|
||||
* @property {number} [rateLimitPerUser] The rate limit per user (slowmode) for the new channel in seconds
|
||||
* @property {string} [rtcRegion] The specific region of the new channel.
|
||||
* @property {VideoQualityMode} [videoQualityMode] The camera video quality mode of the voice channel
|
||||
* @property {number} [defaultThreadRateLimitPerUser] The initial rate limit per user (slowmode)
|
||||
* to set on newly created threads in a channel.
|
||||
* @property {GuildForumTagData[]} [availableTags] The tags that can be used in this channel (forum only).
|
||||
* @property {DefaultReactionEmoji} [defaultReactionEmoji]
|
||||
* The emoji to show in the add reaction button on a thread in a guild forum channel.
|
||||
* @property {ThreadAutoArchiveDuration} [defaultAutoArchiveDuration]
|
||||
* The default auto archive duration for all new threads in this channel
|
||||
* @property {SortOrderType} [defaultSortOrder] The default sort order mode used to order posts (forum only).
|
||||
* @property {ForumLayoutType} [defaultForumLayout] The default layout used to display posts (forum only).
|
||||
* @property {string} [reason] Reason for creating the new channel
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new channel within this category.
|
||||
* <info>You cannot create a channel of type {@link ChannelType.GuildCategory} inside a CategoryChannel.</info>
|
||||
* @param {CategoryCreateChannelOptions} options Options for creating the new channel
|
||||
* @returns {Promise<GuildChannel>}
|
||||
*/
|
||||
create(options) {
|
||||
return this.guild.channels.create({
|
||||
...options,
|
||||
parent: this.channel.id,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CategoryChannelChildManager;
|
||||
128
node_modules/discord.js/src/managers/ChannelManager.js
generated
vendored
Normal file
128
node_modules/discord.js/src/managers/ChannelManager.js
generated
vendored
Normal file
@@ -0,0 +1,128 @@
|
||||
'use strict';
|
||||
|
||||
const process = require('node:process');
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { BaseChannel } = require('../structures/BaseChannel');
|
||||
const { createChannel } = require('../util/Channels');
|
||||
const { ThreadChannelTypes } = require('../util/Constants');
|
||||
const Events = require('../util/Events');
|
||||
|
||||
let cacheWarningEmitted = false;
|
||||
|
||||
/**
|
||||
* A manager of channels belonging to a client
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class ChannelManager extends CachedManager {
|
||||
constructor(client, iterable) {
|
||||
super(client, BaseChannel, iterable);
|
||||
const defaultCaching =
|
||||
this._cache.constructor.name === 'Collection' ||
|
||||
this._cache.maxSize === undefined ||
|
||||
this._cache.maxSize === Infinity;
|
||||
if (!cacheWarningEmitted && !defaultCaching) {
|
||||
cacheWarningEmitted = true;
|
||||
process.emitWarning(
|
||||
`Overriding the cache handling for ${this.constructor.name} is unsupported and breaks functionality.`,
|
||||
'UnsupportedCacheOverwriteWarning',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of Channels
|
||||
* @type {Collection<Snowflake, BaseChannel>}
|
||||
* @name ChannelManager#cache
|
||||
*/
|
||||
|
||||
_add(data, guild, { cache = true, allowUnknownGuild = false } = {}) {
|
||||
const existing = this.cache.get(data.id);
|
||||
if (existing) {
|
||||
if (cache) existing._patch(data);
|
||||
guild?.channels?._add(existing);
|
||||
if (ThreadChannelTypes.includes(existing.type)) {
|
||||
existing.parent?.threads?._add(existing);
|
||||
}
|
||||
return existing;
|
||||
}
|
||||
|
||||
const channel = createChannel(this.client, data, guild, { allowUnknownGuild });
|
||||
|
||||
if (!channel) {
|
||||
this.client.emit(Events.Debug, `Failed to find guild, or unknown type for channel ${data.id} ${data.type}`);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (cache && !allowUnknownGuild) this.cache.set(channel.id, channel);
|
||||
|
||||
return channel;
|
||||
}
|
||||
|
||||
_remove(id) {
|
||||
const channel = this.cache.get(id);
|
||||
channel?.guild?.channels.cache.delete(id);
|
||||
|
||||
for (const [code, invite] of channel?.guild?.invites.cache ?? []) {
|
||||
if (invite.channelId === id) channel.guild.invites.cache.delete(code);
|
||||
}
|
||||
|
||||
channel?.parent?.threads?.cache.delete(id);
|
||||
this.cache.delete(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to give a Channel object. This can be:
|
||||
* * A Channel object
|
||||
* * A Snowflake
|
||||
* @typedef {BaseChannel|Snowflake} ChannelResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a ChannelResolvable to a Channel object.
|
||||
* @method resolve
|
||||
* @memberof ChannelManager
|
||||
* @instance
|
||||
* @param {ChannelResolvable} channel The channel resolvable to resolve
|
||||
* @returns {?BaseChannel}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a ChannelResolvable to a channel id string.
|
||||
* @method resolveId
|
||||
* @memberof ChannelManager
|
||||
* @instance
|
||||
* @param {ChannelResolvable} channel The channel resolvable to resolve
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options for fetching a channel from Discord
|
||||
* @typedef {BaseFetchOptions} FetchChannelOptions
|
||||
* @property {boolean} [allowUnknownGuild=false] Allows the channel to be returned even if the guild is not in cache,
|
||||
* it will not be cached. <warn>Many of the properties and methods on the returned channel will throw errors</warn>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Obtains a channel from Discord, or the channel cache if it's already available.
|
||||
* @param {Snowflake} id The channel's id
|
||||
* @param {FetchChannelOptions} [options] Additional options for this fetch
|
||||
* @returns {Promise<?BaseChannel>}
|
||||
* @example
|
||||
* // Fetch a channel by its id
|
||||
* client.channels.fetch('222109930545610754')
|
||||
* .then(channel => console.log(channel.name))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetch(id, { allowUnknownGuild = false, cache = true, force = false } = {}) {
|
||||
if (!force) {
|
||||
const existing = this.cache.get(id);
|
||||
if (existing && !existing.partial) return existing;
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(Routes.channel(id));
|
||||
return this._add(data, null, { cache, allowUnknownGuild });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ChannelManager;
|
||||
17
node_modules/discord.js/src/managers/DMMessageManager.js
generated
vendored
Normal file
17
node_modules/discord.js/src/managers/DMMessageManager.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
const MessageManager = require('./MessageManager');
|
||||
|
||||
/**
|
||||
* Manages API methods for messages in direct message channels and holds their cache.
|
||||
* @extends {MessageManager}
|
||||
*/
|
||||
class DMMessageManager extends MessageManager {
|
||||
/**
|
||||
* The channel that the messages belong to
|
||||
* @name DMMessageManager#channel
|
||||
* @type {DMChannel}
|
||||
*/
|
||||
}
|
||||
|
||||
module.exports = DMMessageManager;
|
||||
61
node_modules/discord.js/src/managers/DataManager.js
generated
vendored
Normal file
61
node_modules/discord.js/src/managers/DataManager.js
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const { DiscordjsError, ErrorCodes } = require('../errors');
|
||||
|
||||
/**
|
||||
* Manages the API methods of a data model along with a collection of instances.
|
||||
* @extends {BaseManager}
|
||||
* @abstract
|
||||
*/
|
||||
class DataManager extends BaseManager {
|
||||
constructor(client, holds) {
|
||||
super(client);
|
||||
|
||||
/**
|
||||
* The data structure belonging to this manager.
|
||||
* @name DataManager#holds
|
||||
* @type {Function}
|
||||
* @private
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'holds', { value: holds });
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of items for this manager.
|
||||
* @type {Collection}
|
||||
* @abstract
|
||||
*/
|
||||
get cache() {
|
||||
throw new DiscordjsError(ErrorCodes.NotImplemented, 'get cache', this.constructor.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a data entry to a data Object.
|
||||
* @param {string|Object} idOrInstance The id or instance of something in this Manager
|
||||
* @returns {?Object} An instance from this Manager
|
||||
*/
|
||||
resolve(idOrInstance) {
|
||||
if (idOrInstance instanceof this.holds) return idOrInstance;
|
||||
if (typeof idOrInstance === 'string') return this.cache.get(idOrInstance) ?? null;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a data entry to an instance id.
|
||||
* @param {string|Object} idOrInstance The id or instance of something in this Manager
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
resolveId(idOrInstance) {
|
||||
if (idOrInstance instanceof this.holds) return idOrInstance.id;
|
||||
if (typeof idOrInstance === 'string') return idOrInstance;
|
||||
return null;
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.cache;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = DataManager;
|
||||
139
node_modules/discord.js/src/managers/EntitlementManager.js
generated
vendored
Normal file
139
node_modules/discord.js/src/managers/EntitlementManager.js
generated
vendored
Normal file
@@ -0,0 +1,139 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { makeURLSearchParams } = require('@discordjs/rest');
|
||||
const { Routes, EntitlementOwnerType } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { ErrorCodes, DiscordjsTypeError } = require('../errors/index');
|
||||
const { Entitlement } = require('../structures/Entitlement');
|
||||
const { resolveSKUId } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Manages API methods for entitlements and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class EntitlementManager extends CachedManager {
|
||||
constructor(client, iterable) {
|
||||
super(client, Entitlement, iterable);
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of this manager
|
||||
* @type {Collection<Snowflake, Entitlement>}
|
||||
* @name EntitlementManager#cache
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data that resolves to give an Entitlement object. This can be:
|
||||
* * An Entitlement object
|
||||
* * A Snowflake
|
||||
* @typedef {Entitlement|Snowflake} EntitlementResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data that resolves to give a SKU object. This can be:
|
||||
* * A SKU object
|
||||
* * A Snowflake
|
||||
* @typedef {SKU|Snowflake} SKUResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch entitlements
|
||||
* @typedef {Object} FetchEntitlementsOptions
|
||||
* @property {number} [limit] The maximum number of entitlements to fetch
|
||||
* @property {GuildResolvable} [guild] The guild to fetch entitlements for
|
||||
* @property {UserResolvable} [user] The user to fetch entitlements for
|
||||
* @property {SKUResolvable[]} [skus] The SKUs to fetch entitlements for
|
||||
* @property {boolean} [excludeEnded] Whether to exclude ended entitlements
|
||||
* @property {boolean} [cache=true] Whether to cache the fetched entitlements
|
||||
* @property {Snowflake} [before] Consider only entitlements before this entitlement id
|
||||
* @property {Snowflake} [after] Consider only entitlements after this entitlement id
|
||||
* <warn>If both `before` and `after` are provided, only `before` is respected</warn>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetches entitlements for this application
|
||||
* @param {FetchEntitlementsOptions} [options={}] Options for fetching the entitlements
|
||||
* @returns {Promise<Collection<Snowflake, Entitlement>>}
|
||||
*/
|
||||
async fetch({ limit, guild, user, skus, excludeEnded, cache = true, before, after } = {}) {
|
||||
const query = makeURLSearchParams({
|
||||
limit,
|
||||
guild_id: guild && this.client.guilds.resolveId(guild),
|
||||
user_id: user && this.client.users.resolveId(user),
|
||||
sku_ids: skus?.map(sku => resolveSKUId(sku)).join(','),
|
||||
exclude_ended: excludeEnded,
|
||||
before,
|
||||
after,
|
||||
});
|
||||
|
||||
const entitlements = await this.client.rest.get(Routes.entitlements(this.client.application.id), { query });
|
||||
return entitlements.reduce(
|
||||
(coll, entitlement) => coll.set(entitlement.id, this._add(entitlement, cache)),
|
||||
new Collection(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to create a test entitlement
|
||||
* <info>Either `guild` or `user` must be provided, but not both</info>
|
||||
* @typedef {Object} EntitlementCreateOptions
|
||||
* @property {SKUResolvable} sku The id of the SKU to create the entitlement for
|
||||
* @property {GuildResolvable} [guild] The guild to create the entitlement for
|
||||
* @property {UserResolvable} [user] The user to create the entitlement for
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a test entitlement
|
||||
* @param {EntitlementCreateOptions} options Options for creating the test entitlement
|
||||
* @returns {Promise<Entitlement>}
|
||||
*/
|
||||
async createTest({ sku, guild, user }) {
|
||||
const skuId = resolveSKUId(sku);
|
||||
if (!skuId) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'sku', 'SKUResolvable');
|
||||
|
||||
if ((guild && user) || (!guild && !user)) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.EntitlementCreateInvalidOwner);
|
||||
}
|
||||
|
||||
const resolved = guild ? this.client.guilds.resolveId(guild) : this.client.users.resolveId(user);
|
||||
if (!resolved) {
|
||||
const name = guild ? 'guild' : 'user';
|
||||
const type = guild ? 'GuildResolvable' : 'UserResolvable';
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidType, name, type);
|
||||
}
|
||||
|
||||
const entitlement = await this.client.rest.post(Routes.entitlements(this.client.application.id), {
|
||||
body: {
|
||||
sku_id: skuId,
|
||||
owner_id: resolved,
|
||||
owner_type: guild ? EntitlementOwnerType.Guild : EntitlementOwnerType.User,
|
||||
},
|
||||
});
|
||||
return new Entitlement(this.client, entitlement);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a test entitlement
|
||||
* @param {EntitlementResolvable} entitlement The entitlement to delete
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async deleteTest(entitlement) {
|
||||
const resolved = this.resolveId(entitlement);
|
||||
if (!resolved) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'entitlement', 'EntitlementResolvable');
|
||||
|
||||
await this.client.rest.delete(Routes.entitlement(this.client.application.id, resolved));
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks an entitlement as consumed
|
||||
* <info>Only available for One-Time Purchase consumable SKUs.</info>
|
||||
* @param {Snowflake} entitlementId The id of the entitlement to consume
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async consume(entitlementId) {
|
||||
await this.client.rest.post(Routes.consumeEntitlement(this.client.application.id, entitlementId));
|
||||
}
|
||||
}
|
||||
|
||||
exports.EntitlementManager = EntitlementManager;
|
||||
28
node_modules/discord.js/src/managers/GuildApplicationCommandManager.js
generated
vendored
Normal file
28
node_modules/discord.js/src/managers/GuildApplicationCommandManager.js
generated
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
'use strict';
|
||||
|
||||
const ApplicationCommandManager = require('./ApplicationCommandManager');
|
||||
const ApplicationCommandPermissionsManager = require('./ApplicationCommandPermissionsManager');
|
||||
|
||||
/**
|
||||
* An extension for guild-specific application commands.
|
||||
* @extends {ApplicationCommandManager}
|
||||
*/
|
||||
class GuildApplicationCommandManager extends ApplicationCommandManager {
|
||||
constructor(guild, iterable) {
|
||||
super(guild.client, iterable);
|
||||
|
||||
/**
|
||||
* The guild that this manager belongs to
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
|
||||
/**
|
||||
* The manager for permissions of arbitrary commands on this guild
|
||||
* @type {ApplicationCommandPermissionsManager}
|
||||
*/
|
||||
this.permissions = new ApplicationCommandPermissionsManager(this);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildApplicationCommandManager;
|
||||
249
node_modules/discord.js/src/managers/GuildBanManager.js
generated
vendored
Normal file
249
node_modules/discord.js/src/managers/GuildBanManager.js
generated
vendored
Normal file
@@ -0,0 +1,249 @@
|
||||
'use strict';
|
||||
|
||||
const process = require('node:process');
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { makeURLSearchParams } = require('@discordjs/rest');
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsTypeError, DiscordjsError, ErrorCodes } = require('../errors');
|
||||
const GuildBan = require('../structures/GuildBan');
|
||||
const { GuildMember } = require('../structures/GuildMember');
|
||||
|
||||
let deprecationEmittedForDeleteMessageDays = false;
|
||||
|
||||
/**
|
||||
* Manages API methods for guild bans and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class GuildBanManager extends CachedManager {
|
||||
constructor(guild, iterable) {
|
||||
super(guild.client, GuildBan, iterable);
|
||||
|
||||
/**
|
||||
* The guild this Manager belongs to
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of this Manager
|
||||
* @type {Collection<Snowflake, GuildBan>}
|
||||
* @name GuildBanManager#cache
|
||||
*/
|
||||
|
||||
_add(data, cache) {
|
||||
return super._add(data, cache, { id: data.user.id, extras: [this.guild] });
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that resolves to give a GuildBan object. This can be:
|
||||
* * A GuildBan object
|
||||
* * A User resolvable
|
||||
* @typedef {GuildBan|UserResolvable} GuildBanResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a GuildBanResolvable to a GuildBan object.
|
||||
* @param {GuildBanResolvable} ban The ban that is in the guild
|
||||
* @returns {?GuildBan}
|
||||
*/
|
||||
resolve(ban) {
|
||||
return super.resolve(ban) ?? super.resolve(this.client.users.resolveId(ban));
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to fetch a single ban from a guild.
|
||||
* @typedef {BaseFetchOptions} FetchBanOptions
|
||||
* @property {UserResolvable} user The ban to fetch
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch multiple bans from a guild.
|
||||
* @typedef {Object} FetchBansOptions
|
||||
* @property {number} [limit] The maximum number of bans to return
|
||||
* @property {Snowflake} [before] Consider only bans before this id
|
||||
* @property {Snowflake} [after] Consider only bans after this id
|
||||
* @property {boolean} [cache] Whether to cache the fetched bans
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetches ban(s) from Discord.
|
||||
* @param {UserResolvable|FetchBanOptions|FetchBansOptions} [options] Options for fetching guild ban(s)
|
||||
* @returns {Promise<GuildBan|Collection<Snowflake, GuildBan>>}
|
||||
* @example
|
||||
* // Fetch multiple bans from a guild
|
||||
* guild.bans.fetch()
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch a maximum of 5 bans from a guild without caching
|
||||
* guild.bans.fetch({ limit: 5, cache: false })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch a single ban
|
||||
* guild.bans.fetch('351871113346809860')
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch a single ban without checking cache
|
||||
* guild.bans.fetch({ user, force: true })
|
||||
* .then(console.log)
|
||||
* .catch(console.error)
|
||||
* @example
|
||||
* // Fetch a single ban without caching
|
||||
* guild.bans.fetch({ user, cache: false })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetch(options) {
|
||||
if (!options) return this._fetchMany();
|
||||
const { user, cache, force, limit, before, after } = options;
|
||||
const resolvedUser = this.client.users.resolveId(user ?? options);
|
||||
if (resolvedUser) return this._fetchSingle({ user: resolvedUser, cache, force });
|
||||
|
||||
if (!before && !after && !limit && cache === undefined) {
|
||||
return Promise.reject(new DiscordjsError(ErrorCodes.FetchBanResolveId));
|
||||
}
|
||||
|
||||
return this._fetchMany(options);
|
||||
}
|
||||
|
||||
async _fetchSingle({ user, cache, force = false }) {
|
||||
if (!force) {
|
||||
const existing = this.cache.get(user);
|
||||
if (existing && !existing.partial) return existing;
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(Routes.guildBan(this.guild.id, user));
|
||||
return this._add(data, cache);
|
||||
}
|
||||
|
||||
async _fetchMany(options = {}) {
|
||||
const data = await this.client.rest.get(Routes.guildBans(this.guild.id), {
|
||||
query: makeURLSearchParams(options),
|
||||
});
|
||||
|
||||
return data.reduce((col, ban) => col.set(ban.user.id, this._add(ban, options.cache)), new Collection());
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to ban a user from a guild.
|
||||
* @typedef {Object} BanOptions
|
||||
* @property {number} [deleteMessageDays] Number of days of messages to delete, must be between 0 and 7, inclusive
|
||||
* <warn>This property is deprecated. Use `deleteMessageSeconds` instead.</warn>
|
||||
* @property {number} [deleteMessageSeconds] Number of seconds of messages to delete,
|
||||
* must be between 0 and 604800 (7 days), inclusive
|
||||
* @property {string} [reason] The reason for the ban
|
||||
*/
|
||||
|
||||
/**
|
||||
* Bans a user from the guild.
|
||||
* @param {UserResolvable} user The user to ban
|
||||
* @param {BanOptions} [options] Options for the ban
|
||||
* @returns {Promise<GuildMember|User|Snowflake>} Result object will be resolved as specifically as possible.
|
||||
* If the GuildMember cannot be resolved, the User will instead be attempted to be resolved. If that also cannot
|
||||
* be resolved, the user id will be the result.
|
||||
* @example
|
||||
* // Ban a user by id (or with a user/guild member object)
|
||||
* guild.bans.create('84484653687267328')
|
||||
* .then(banInfo => console.log(`Banned ${banInfo.user?.tag ?? banInfo.tag ?? banInfo}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async create(user, options = {}) {
|
||||
if (typeof options !== 'object') throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'options', 'object', true);
|
||||
const id = this.client.users.resolveId(user);
|
||||
if (!id) throw new DiscordjsError(ErrorCodes.BanResolveId, true);
|
||||
|
||||
if (options.deleteMessageDays !== undefined && !deprecationEmittedForDeleteMessageDays) {
|
||||
process.emitWarning(
|
||||
// eslint-disable-next-line max-len
|
||||
'The deleteMessageDays option for GuildBanManager#create() is deprecated. Use the deleteMessageSeconds option instead.',
|
||||
'DeprecationWarning',
|
||||
);
|
||||
|
||||
deprecationEmittedForDeleteMessageDays = true;
|
||||
}
|
||||
|
||||
await this.client.rest.put(Routes.guildBan(this.guild.id, id), {
|
||||
body: {
|
||||
delete_message_seconds:
|
||||
options.deleteMessageSeconds ??
|
||||
(options.deleteMessageDays ? options.deleteMessageDays * 24 * 60 * 60 : undefined),
|
||||
},
|
||||
reason: options.reason,
|
||||
});
|
||||
if (user instanceof GuildMember) return user;
|
||||
const _user = this.client.users.resolve(id);
|
||||
if (_user) {
|
||||
return this.guild.members.resolve(_user) ?? _user;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbans a user from the guild.
|
||||
* @param {UserResolvable} user The user to unban
|
||||
* @param {string} [reason] Reason for unbanning user
|
||||
* @returns {Promise<?User>}
|
||||
* @example
|
||||
* // Unban a user by id (or with a user/guild member object)
|
||||
* guild.bans.remove('84484653687267328')
|
||||
* .then(user => console.log(`Unbanned ${user.username} from ${guild.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async remove(user, reason) {
|
||||
const id = this.client.users.resolveId(user);
|
||||
if (!id) throw new DiscordjsError(ErrorCodes.BanResolveId);
|
||||
await this.client.rest.delete(Routes.guildBan(this.guild.id, id), { reason });
|
||||
return this.client.users.resolve(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used for bulk banning users from a guild.
|
||||
* @typedef {Object} BulkBanOptions
|
||||
* @property {number} [deleteMessageSeconds] Number of seconds of messages to delete,
|
||||
* must be between 0 and 604800 (7 days), inclusive
|
||||
* @property {string} [reason] The reason for the bans
|
||||
*/
|
||||
|
||||
/**
|
||||
* Result of bulk banning users from a guild.
|
||||
* @typedef {Object} BulkBanResult
|
||||
* @property {Snowflake[]} bannedUsers IDs of the banned users
|
||||
* @property {Snowflake[]} failedUsers IDs of the users that could not be banned or were already banned
|
||||
*/
|
||||
|
||||
/**
|
||||
* Bulk ban users from a guild, and optionally delete previous messages sent by them.
|
||||
* @param {Collection<Snowflake, UserResolvable>|UserResolvable[]} users The users to ban
|
||||
* @param {BulkBanOptions} [options] The options for bulk banning users
|
||||
* @returns {Promise<BulkBanResult>} Returns an object with `bannedUsers` key containing the IDs of the banned users
|
||||
* and the key `failedUsers` with the IDs that could not be banned or were already banned.
|
||||
* @example
|
||||
* // Bulk ban users by ids (or with user/guild member objects) and delete all their messages from the past 7 days
|
||||
* guild.bans.bulkCreate(['84484653687267328'], { deleteMessageSeconds: 7 * 24 * 60 * 60 })
|
||||
* .then(result => {
|
||||
* console.log(`Banned ${result.bannedUsers.length} users, failed to ban ${result.failedUsers.length} users.`)
|
||||
* })
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async bulkCreate(users, options = {}) {
|
||||
if (!users || !(Array.isArray(users) || users instanceof Collection)) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'users', 'Array or Collection of UserResolvable', true);
|
||||
}
|
||||
if (typeof options !== 'object') throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'options', 'object', true);
|
||||
|
||||
const userIds = users.map(user => this.client.users.resolveId(user));
|
||||
if (userIds.length === 0) throw new DiscordjsError(ErrorCodes.BulkBanUsersOptionEmpty);
|
||||
|
||||
const result = await this.client.rest.post(Routes.guildBulkBan(this.guild.id), {
|
||||
body: { delete_message_seconds: options.deleteMessageSeconds, user_ids: userIds },
|
||||
reason: options.reason,
|
||||
});
|
||||
return { bannedUsers: result.banned_users, failedUsers: result.failed_users };
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildBanManager;
|
||||
519
node_modules/discord.js/src/managers/GuildChannelManager.js
generated
vendored
Normal file
519
node_modules/discord.js/src/managers/GuildChannelManager.js
generated
vendored
Normal file
@@ -0,0 +1,519 @@
|
||||
'use strict';
|
||||
|
||||
const process = require('node:process');
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { ChannelType, Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const GuildTextThreadManager = require('./GuildTextThreadManager');
|
||||
const { DiscordjsError, DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
const GuildChannel = require('../structures/GuildChannel');
|
||||
const PermissionOverwrites = require('../structures/PermissionOverwrites');
|
||||
const ThreadChannel = require('../structures/ThreadChannel');
|
||||
const Webhook = require('../structures/Webhook');
|
||||
const ChannelFlagsBitField = require('../util/ChannelFlagsBitField');
|
||||
const { transformGuildForumTag, transformGuildDefaultReaction } = require('../util/Channels');
|
||||
const { ThreadChannelTypes } = require('../util/Constants');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
const { setPosition } = require('../util/Util');
|
||||
|
||||
let cacheWarningEmitted = false;
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildChannels and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class GuildChannelManager extends CachedManager {
|
||||
constructor(guild, iterable) {
|
||||
super(guild.client, GuildChannel, iterable);
|
||||
const defaultCaching =
|
||||
this._cache.constructor.name === 'Collection' ||
|
||||
this._cache.maxSize === undefined ||
|
||||
this._cache.maxSize === Infinity;
|
||||
if (!cacheWarningEmitted && !defaultCaching) {
|
||||
cacheWarningEmitted = true;
|
||||
process.emitWarning(
|
||||
`Overriding the cache handling for ${this.constructor.name} is unsupported and breaks functionality.`,
|
||||
'UnsupportedCacheOverwriteWarning',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The guild this Manager belongs to
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
}
|
||||
|
||||
/**
|
||||
* The number of channels in this managers cache excluding thread channels
|
||||
* that do not count towards a guild's maximum channels restriction.
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get channelCountWithoutThreads() {
|
||||
return this.cache.reduce((acc, channel) => {
|
||||
if (ThreadChannelTypes.includes(channel.type)) return acc;
|
||||
return ++acc;
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of this Manager
|
||||
* @type {Collection<Snowflake, GuildChannel|ThreadChannel>}
|
||||
* @name GuildChannelManager#cache
|
||||
*/
|
||||
|
||||
_add(channel) {
|
||||
const existing = this.cache.get(channel.id);
|
||||
if (existing) return existing;
|
||||
this.cache.set(channel.id, channel);
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to give a Guild Channel object. This can be:
|
||||
* * A GuildChannel object
|
||||
* * A ThreadChannel object
|
||||
* * A Snowflake
|
||||
* @typedef {GuildChannel|ThreadChannel|Snowflake} GuildChannelResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a GuildChannelResolvable to a Channel object.
|
||||
* @param {GuildChannelResolvable} channel The GuildChannel resolvable to resolve
|
||||
* @returns {?(GuildChannel|ThreadChannel)}
|
||||
*/
|
||||
resolve(channel) {
|
||||
if (channel instanceof ThreadChannel) return super.resolve(channel.id);
|
||||
return super.resolve(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a GuildChannelResolvable to a channel id.
|
||||
* @param {GuildChannelResolvable} channel The GuildChannel resolvable to resolve
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
resolveId(channel) {
|
||||
if (channel instanceof ThreadChannel) return super.resolveId(channel.id);
|
||||
return super.resolveId(channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to a News Channel object. This can be:
|
||||
* * A NewsChannel object
|
||||
* * A Snowflake
|
||||
* @typedef {NewsChannel|Snowflake} NewsChannelResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Adds the target channel to a channel's followers.
|
||||
* @param {NewsChannelResolvable} channel The channel to follow
|
||||
* @param {TextChannelResolvable} targetChannel The channel where published announcements will be posted at
|
||||
* @param {string} [reason] Reason for creating the webhook
|
||||
* @returns {Promise<Snowflake>} Returns created target webhook id.
|
||||
*/
|
||||
async addFollower(channel, targetChannel, reason) {
|
||||
const channelId = this.resolveId(channel);
|
||||
if (!channelId) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'channel', 'NewsChannelResolvable');
|
||||
}
|
||||
const targetChannelId = this.resolveId(targetChannel);
|
||||
if (!targetChannelId) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'targetChannel', 'TextChannelResolvable');
|
||||
}
|
||||
const { webhook_id } = await this.client.rest.post(Routes.channelFollowers(channelId), {
|
||||
body: { webhook_channel_id: targetChannelId },
|
||||
reason,
|
||||
});
|
||||
return webhook_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to create a new channel in a guild.
|
||||
* @typedef {CategoryCreateChannelOptions} GuildChannelCreateOptions
|
||||
* @property {?CategoryChannelResolvable} [parent] Parent of the new channel
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new channel in the guild.
|
||||
* @param {GuildChannelCreateOptions} options Options for creating the new channel
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Create a new text channel
|
||||
* guild.channels.create({ name: 'new-general', reason: 'Needed a cool new channel' })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Create a new channel with permission overwrites
|
||||
* guild.channels.create({
|
||||
* name: 'new-general',
|
||||
* type: ChannelType.GuildVoice,
|
||||
* permissionOverwrites: [
|
||||
* {
|
||||
* id: message.author.id,
|
||||
* deny: [PermissionFlagsBits.ViewChannel],
|
||||
* },
|
||||
* ],
|
||||
* })
|
||||
*/
|
||||
async create({
|
||||
name,
|
||||
type,
|
||||
topic,
|
||||
nsfw,
|
||||
bitrate,
|
||||
userLimit,
|
||||
parent,
|
||||
permissionOverwrites,
|
||||
position,
|
||||
rateLimitPerUser,
|
||||
rtcRegion,
|
||||
videoQualityMode,
|
||||
defaultThreadRateLimitPerUser,
|
||||
availableTags,
|
||||
defaultReactionEmoji,
|
||||
defaultAutoArchiveDuration,
|
||||
defaultSortOrder,
|
||||
defaultForumLayout,
|
||||
reason,
|
||||
}) {
|
||||
parent &&= this.client.channels.resolveId(parent);
|
||||
permissionOverwrites &&= permissionOverwrites.map(overwrite => PermissionOverwrites.resolve(overwrite, this.guild));
|
||||
|
||||
const data = await this.client.rest.post(Routes.guildChannels(this.guild.id), {
|
||||
body: {
|
||||
name,
|
||||
topic,
|
||||
type,
|
||||
nsfw,
|
||||
bitrate,
|
||||
user_limit: userLimit,
|
||||
parent_id: parent,
|
||||
position,
|
||||
permission_overwrites: permissionOverwrites,
|
||||
rate_limit_per_user: rateLimitPerUser,
|
||||
rtc_region: rtcRegion,
|
||||
video_quality_mode: videoQualityMode,
|
||||
default_thread_rate_limit_per_user: defaultThreadRateLimitPerUser,
|
||||
available_tags: availableTags?.map(availableTag => transformGuildForumTag(availableTag)),
|
||||
default_reaction_emoji: defaultReactionEmoji && transformGuildDefaultReaction(defaultReactionEmoji),
|
||||
default_auto_archive_duration: defaultAutoArchiveDuration,
|
||||
default_sort_order: defaultSortOrder,
|
||||
default_forum_layout: defaultForumLayout,
|
||||
},
|
||||
reason,
|
||||
});
|
||||
return this.client.actions.ChannelCreate.handle(data).channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {ChannelWebhookCreateOptions} WebhookCreateOptions
|
||||
* @property {TextChannel|NewsChannel|VoiceChannel|StageChannel|ForumChannel|MediaChannel|Snowflake} channel
|
||||
* The channel to create the webhook for
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a webhook for the channel.
|
||||
* @param {WebhookCreateOptions} options Options for creating the webhook
|
||||
* @returns {Promise<Webhook>} Returns the created Webhook
|
||||
* @example
|
||||
* // Create a webhook for the current channel
|
||||
* guild.channels.createWebhook({
|
||||
* channel: '222197033908436994',
|
||||
* name: 'Snek',
|
||||
* avatar: 'https://i.imgur.com/mI8XcpG.jpg',
|
||||
* reason: 'Needed a cool new Webhook'
|
||||
* })
|
||||
* .then(console.log)
|
||||
* .catch(console.error)
|
||||
*/
|
||||
async createWebhook({ channel, name, avatar, reason }) {
|
||||
const id = this.resolveId(channel);
|
||||
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'channel', 'GuildChannelResolvable');
|
||||
if (typeof avatar === 'string' && !avatar.startsWith('data:')) {
|
||||
avatar = await resolveImage(avatar);
|
||||
}
|
||||
const data = await this.client.rest.post(Routes.channelWebhooks(id), {
|
||||
body: {
|
||||
name,
|
||||
avatar,
|
||||
},
|
||||
reason,
|
||||
});
|
||||
return new Webhook(this.client, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to edit a guild channel.
|
||||
* @typedef {Object} GuildChannelEditOptions
|
||||
* @property {string} [name] The name of the channel
|
||||
* @property {ChannelType} [type] The type of the channel (only conversion between text and news is supported)
|
||||
* @property {number} [position] The position of the channel
|
||||
* @property {?string} [topic] The topic of the text channel
|
||||
* @property {boolean} [nsfw] Whether the channel is NSFW
|
||||
* @property {number} [bitrate] The bitrate of the voice channel
|
||||
* @property {number} [userLimit] The user limit of the voice channel
|
||||
* @property {?CategoryChannelResolvable} [parent] The parent of the channel
|
||||
* @property {boolean} [lockPermissions]
|
||||
* Lock the permissions of the channel to what the parent's permissions are
|
||||
* @property {OverwriteResolvable[]|Collection<Snowflake, OverwriteResolvable>} [permissionOverwrites]
|
||||
* Permission overwrites for the channel
|
||||
* @property {number} [rateLimitPerUser] The rate limit per user (slowmode) for the channel in seconds
|
||||
* @property {ThreadAutoArchiveDuration} [defaultAutoArchiveDuration]
|
||||
* The default auto archive duration for all new threads in this channel
|
||||
* @property {?string} [rtcRegion] The RTC region of the channel
|
||||
* @property {?VideoQualityMode} [videoQualityMode] The camera video quality mode of the channel
|
||||
* @property {GuildForumTagData[]} [availableTags] The tags to set as available in a forum channel
|
||||
* @property {?DefaultReactionEmoji} [defaultReactionEmoji] The emoji to set as the default reaction emoji
|
||||
* @property {number} [defaultThreadRateLimitPerUser] The rate limit per user (slowmode) to set on forum posts
|
||||
* @property {ChannelFlagsResolvable} [flags] The flags to set on the channel
|
||||
* @property {?SortOrderType} [defaultSortOrder] The default sort order mode to set on the channel
|
||||
* @property {ForumLayoutType} [defaultForumLayout] The default forum layout to set on the channel
|
||||
* @property {string} [reason] Reason for editing this channel
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits the channel.
|
||||
* @param {GuildChannelResolvable} channel The channel to edit
|
||||
* @param {GuildChannelEditOptions} options Options for editing the channel
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Edit a channel
|
||||
* guild.channels.edit('222197033908436994', { name: 'new-channel' })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async edit(channel, options) {
|
||||
const resolvedChannel = this.resolve(channel);
|
||||
if (!resolvedChannel) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'channel', 'GuildChannelResolvable');
|
||||
|
||||
const parent = options.parent && this.client.channels.resolveId(options.parent);
|
||||
|
||||
if (options.position !== undefined) {
|
||||
await this.setPosition(resolvedChannel, options.position, { position: options.position, reason: options.reason });
|
||||
}
|
||||
|
||||
let permission_overwrites = options.permissionOverwrites?.map(overwrite =>
|
||||
PermissionOverwrites.resolve(overwrite, this.guild),
|
||||
);
|
||||
|
||||
if (options.lockPermissions) {
|
||||
if (parent) {
|
||||
const newParent = this.guild.channels.resolve(parent);
|
||||
if (newParent?.type === ChannelType.GuildCategory) {
|
||||
permission_overwrites = newParent.permissionOverwrites.cache.map(overwrite =>
|
||||
PermissionOverwrites.resolve(overwrite, this.guild),
|
||||
);
|
||||
}
|
||||
} else if (resolvedChannel.parent) {
|
||||
permission_overwrites = resolvedChannel.parent.permissionOverwrites.cache.map(overwrite =>
|
||||
PermissionOverwrites.resolve(overwrite, this.guild),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const newData = await this.client.rest.patch(Routes.channel(resolvedChannel.id), {
|
||||
body: {
|
||||
name: options.name,
|
||||
type: options.type,
|
||||
topic: options.topic,
|
||||
nsfw: options.nsfw,
|
||||
bitrate: options.bitrate,
|
||||
user_limit: options.userLimit,
|
||||
rtc_region: options.rtcRegion,
|
||||
video_quality_mode: options.videoQualityMode,
|
||||
parent_id: parent,
|
||||
lock_permissions: options.lockPermissions,
|
||||
rate_limit_per_user: options.rateLimitPerUser,
|
||||
default_auto_archive_duration: options.defaultAutoArchiveDuration,
|
||||
permission_overwrites,
|
||||
available_tags: options.availableTags?.map(availableTag => transformGuildForumTag(availableTag)),
|
||||
default_reaction_emoji:
|
||||
options.defaultReactionEmoji && transformGuildDefaultReaction(options.defaultReactionEmoji),
|
||||
default_thread_rate_limit_per_user: options.defaultThreadRateLimitPerUser,
|
||||
flags: 'flags' in options ? ChannelFlagsBitField.resolve(options.flags) : undefined,
|
||||
default_sort_order: options.defaultSortOrder,
|
||||
default_forum_layout: options.defaultForumLayout,
|
||||
},
|
||||
reason: options.reason,
|
||||
});
|
||||
|
||||
return this.client.actions.ChannelUpdate.handle(newData).updated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new position for the guild channel.
|
||||
* @param {GuildChannelResolvable} channel The channel to set the position for
|
||||
* @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
|
||||
* guild.channels.setPosition('222078374472843266', 2)
|
||||
* .then(newChannel => console.log(`Channel's new position is ${newChannel.position}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async setPosition(channel, position, { relative, reason } = {}) {
|
||||
channel = this.resolve(channel);
|
||||
if (!channel) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'channel', 'GuildChannelResolvable');
|
||||
const updatedChannels = await setPosition(
|
||||
channel,
|
||||
position,
|
||||
relative,
|
||||
this.guild._sortedChannels(channel),
|
||||
this.client,
|
||||
Routes.guildChannels(this.guild.id),
|
||||
reason,
|
||||
);
|
||||
|
||||
this.client.actions.GuildChannelsPositionUpdate.handle({
|
||||
guild_id: this.guild.id,
|
||||
channels: updatedChannels,
|
||||
});
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains one or more guild channels from Discord, or the channel cache if they're already available.
|
||||
* @param {Snowflake} [id] The channel's id
|
||||
* @param {BaseFetchOptions} [options] Additional options for this fetch
|
||||
* @returns {Promise<?GuildChannel|ThreadChannel|Collection<Snowflake, ?GuildChannel>>}
|
||||
* @example
|
||||
* // Fetch all channels from the guild (excluding threads)
|
||||
* message.guild.channels.fetch()
|
||||
* .then(channels => console.log(`There are ${channels.size} channels.`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch a single channel
|
||||
* message.guild.channels.fetch('222197033908436994')
|
||||
* .then(channel => console.log(`The channel name is: ${channel.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetch(id, { cache = true, force = false } = {}) {
|
||||
if (id && !force) {
|
||||
const existing = this.cache.get(id);
|
||||
if (existing) return existing;
|
||||
}
|
||||
|
||||
if (id) {
|
||||
const data = await this.client.rest.get(Routes.channel(id));
|
||||
// Since this is the guild manager, throw if on a different guild
|
||||
if (this.guild.id !== data.guild_id) throw new DiscordjsError(ErrorCodes.GuildChannelUnowned);
|
||||
return this.client.channels._add(data, this.guild, { cache });
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(Routes.guildChannels(this.guild.id));
|
||||
const channels = new Collection();
|
||||
for (const channel of data) channels.set(channel.id, this.client.channels._add(channel, this.guild, { cache }));
|
||||
return channels;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches all webhooks for the channel.
|
||||
* @param {GuildChannelResolvable} channel The channel to fetch webhooks for
|
||||
* @returns {Promise<Collection<Snowflake, Webhook>>}
|
||||
* @example
|
||||
* // Fetch webhooks
|
||||
* guild.channels.fetchWebhooks('769862166131245066')
|
||||
* .then(hooks => console.log(`This channel has ${hooks.size} hooks`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetchWebhooks(channel) {
|
||||
const id = this.resolveId(channel);
|
||||
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'channel', 'GuildChannelResolvable');
|
||||
const data = await this.client.rest.get(Routes.channelWebhooks(id));
|
||||
return data.reduce((hooks, hook) => hooks.set(hook.id, new Webhook(this.client, hook)), new Collection());
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to give a Category Channel object. This can be:
|
||||
* * A CategoryChannel object
|
||||
* * A Snowflake
|
||||
* @typedef {CategoryChannel|Snowflake} CategoryChannelResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* The data needed for updating a channel's position.
|
||||
* @typedef {Object} ChannelPosition
|
||||
* @property {GuildChannel|Snowflake} channel Channel to update
|
||||
* @property {number} [position] New position for the channel
|
||||
* @property {CategoryChannelResolvable} [parent] Parent channel for this channel
|
||||
* @property {boolean} [lockPermissions] If the overwrites should be locked to the parents overwrites
|
||||
*/
|
||||
|
||||
/**
|
||||
* Batch-updates the guild's channels' positions.
|
||||
* <info>Only one channel's parent can be changed at a time</info>
|
||||
* @param {ChannelPosition[]} channelPositions Channel positions to update
|
||||
* @returns {Promise<Guild>}
|
||||
* @example
|
||||
* guild.channels.setPositions([{ channel: channelId, position: newChannelIndex }])
|
||||
* .then(guild => console.log(`Updated channel positions for ${guild}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async setPositions(channelPositions) {
|
||||
channelPositions = channelPositions.map(channelPosition => ({
|
||||
id: this.client.channels.resolveId(channelPosition.channel),
|
||||
position: channelPosition.position,
|
||||
lock_permissions: channelPosition.lockPermissions,
|
||||
parent_id: channelPosition.parent !== undefined ? this.resolveId(channelPosition.parent) : undefined,
|
||||
}));
|
||||
|
||||
await this.client.rest.patch(Routes.guildChannels(this.guild.id), { body: channelPositions });
|
||||
return this.client.actions.GuildChannelsPositionUpdate.handle({
|
||||
guild_id: this.guild.id,
|
||||
channels: channelPositions,
|
||||
}).guild;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data returned from fetching threads.
|
||||
* @typedef {Object} FetchedThreads
|
||||
* @property {Collection<Snowflake, ThreadChannel>} threads The threads that were fetched
|
||||
* @property {Collection<Snowflake, ThreadMember>} members The thread members in the received threads
|
||||
*/
|
||||
|
||||
/**
|
||||
* Obtains all active thread channels in the guild.
|
||||
* @param {boolean} [cache=true] Whether to cache the fetched data
|
||||
* @returns {Promise<FetchedThreads>}
|
||||
* @example
|
||||
* // Fetch all threads from the guild
|
||||
* message.guild.channels.fetchActiveThreads()
|
||||
* .then(fetched => console.log(`There are ${fetched.threads.size} threads.`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetchActiveThreads(cache = true) {
|
||||
const data = await this.rawFetchGuildActiveThreads();
|
||||
return GuildTextThreadManager._mapThreads(data, this.client, { guild: this.guild, cache });
|
||||
}
|
||||
|
||||
/**
|
||||
* `GET /guilds/{guild.id}/threads/active`
|
||||
* @private
|
||||
* @returns {Promise<RESTGetAPIGuildThreadsResult>}
|
||||
*/
|
||||
rawFetchGuildActiveThreads() {
|
||||
return this.client.rest.get(Routes.guildActiveThreads(this.guild.id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the channel.
|
||||
* @param {GuildChannelResolvable} channel The channel to delete
|
||||
* @param {string} [reason] Reason for deleting this channel
|
||||
* @returns {Promise<void>}
|
||||
* @example
|
||||
* // Delete the channel
|
||||
* guild.channels.delete('858850993013260338', 'making room for new channels')
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async delete(channel, reason) {
|
||||
const id = this.resolveId(channel);
|
||||
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'channel', 'GuildChannelResolvable');
|
||||
await this.client.rest.delete(Routes.channel(id), { reason });
|
||||
this.client.actions.ChannelDelete.handle({ id });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildChannelManager;
|
||||
174
node_modules/discord.js/src/managers/GuildEmojiManager.js
generated
vendored
Normal file
174
node_modules/discord.js/src/managers/GuildEmojiManager.js
generated
vendored
Normal file
@@ -0,0 +1,174 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { Routes, PermissionFlagsBits } = require('discord-api-types/v10');
|
||||
const BaseGuildEmojiManager = require('./BaseGuildEmojiManager');
|
||||
const { DiscordjsError, DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildEmojis and stores their cache.
|
||||
* @extends {BaseGuildEmojiManager}
|
||||
*/
|
||||
class GuildEmojiManager extends BaseGuildEmojiManager {
|
||||
constructor(guild, iterable) {
|
||||
super(guild.client, iterable);
|
||||
|
||||
/**
|
||||
* The guild this manager belongs to
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
}
|
||||
|
||||
_add(data, cache) {
|
||||
return super._add(data, cache, { extras: [this.guild] });
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used for creating an emoji in a guild.
|
||||
* @typedef {Object} GuildEmojiCreateOptions
|
||||
* @property {BufferResolvable|Base64Resolvable} attachment The image for the emoji
|
||||
* @property {string} name The name for the emoji
|
||||
* @property {Collection<Snowflake, Role>|RoleResolvable[]} [roles] The roles to limit the emoji to
|
||||
* @property {string} [reason] The reason for creating the emoji
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new custom emoji in the guild.
|
||||
* @param {GuildEmojiCreateOptions} options Options for creating the emoji
|
||||
* @returns {Promise<Emoji>} The created emoji
|
||||
* @example
|
||||
* // Create a new emoji from a URL
|
||||
* guild.emojis.create({ attachment: 'https://i.imgur.com/w3duR07.png', name: 'rip' })
|
||||
* .then(emoji => console.log(`Created new emoji with name ${emoji.name}!`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Create a new emoji from a file on your computer
|
||||
* guild.emojis.create({ attachment: './memes/banana.png', name: 'banana' })
|
||||
* .then(emoji => console.log(`Created new emoji with name ${emoji.name}!`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async create({ attachment, name, roles, reason }) {
|
||||
attachment = await resolveImage(attachment);
|
||||
if (!attachment) throw new DiscordjsTypeError(ErrorCodes.ReqResourceType);
|
||||
|
||||
const body = { image: attachment, name };
|
||||
if (roles) {
|
||||
if (!Array.isArray(roles) && !(roles instanceof Collection)) {
|
||||
throw new DiscordjsTypeError(
|
||||
ErrorCodes.InvalidType,
|
||||
'options.roles',
|
||||
'Array or Collection of Roles or Snowflakes',
|
||||
true,
|
||||
);
|
||||
}
|
||||
body.roles = [];
|
||||
for (const role of roles.values()) {
|
||||
const resolvedRole = this.guild.roles.resolveId(role);
|
||||
if (!resolvedRole) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidElement, 'Array or Collection', 'options.roles', role);
|
||||
}
|
||||
body.roles.push(resolvedRole);
|
||||
}
|
||||
}
|
||||
|
||||
const emoji = await this.client.rest.post(Routes.guildEmojis(this.guild.id), { body, reason });
|
||||
return this.client.actions.GuildEmojiCreate.handle(this.guild, emoji).emoji;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains one or more emojis from Discord, or the emoji cache if they're already available.
|
||||
* @param {Snowflake} [id] The emoji's id
|
||||
* @param {BaseFetchOptions} [options] Additional options for this fetch
|
||||
* @returns {Promise<GuildEmoji|Collection<Snowflake, GuildEmoji>>}
|
||||
* @example
|
||||
* // Fetch all emojis from the guild
|
||||
* message.guild.emojis.fetch()
|
||||
* .then(emojis => console.log(`There are ${emojis.size} emojis.`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch a single emoji
|
||||
* message.guild.emojis.fetch('222078108977594368')
|
||||
* .then(emoji => console.log(`The emoji name is: ${emoji.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetch(id, { cache = true, force = false } = {}) {
|
||||
if (id) {
|
||||
if (!force) {
|
||||
const existing = this.cache.get(id);
|
||||
if (existing) return existing;
|
||||
}
|
||||
const emoji = await this.client.rest.get(Routes.guildEmoji(this.guild.id, id));
|
||||
return this._add(emoji, cache);
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(Routes.guildEmojis(this.guild.id));
|
||||
const emojis = new Collection();
|
||||
for (const emoji of data) emojis.set(emoji.id, this._add(emoji, cache));
|
||||
return emojis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an emoji.
|
||||
* @param {EmojiResolvable} emoji The Emoji resolvable to delete
|
||||
* @param {string} [reason] Reason for deleting the emoji
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async delete(emoji, reason) {
|
||||
const id = this.resolveId(emoji);
|
||||
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'emoji', 'EmojiResolvable', true);
|
||||
await this.client.rest.delete(Routes.guildEmoji(this.guild.id, id), { reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits an emoji.
|
||||
* @param {EmojiResolvable} emoji The Emoji resolvable to edit
|
||||
* @param {GuildEmojiEditOptions} options The options to provide
|
||||
* @returns {Promise<GuildEmoji>}
|
||||
*/
|
||||
async edit(emoji, options) {
|
||||
const id = this.resolveId(emoji);
|
||||
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'emoji', 'EmojiResolvable', true);
|
||||
const roles = options.roles?.map(role => this.guild.roles.resolveId(role));
|
||||
const newData = await this.client.rest.patch(Routes.guildEmoji(this.guild.id, id), {
|
||||
body: {
|
||||
name: options.name,
|
||||
roles,
|
||||
},
|
||||
reason: options.reason,
|
||||
});
|
||||
const existing = this.cache.get(id);
|
||||
if (existing) {
|
||||
const clone = existing._clone();
|
||||
clone._patch(newData);
|
||||
return clone;
|
||||
}
|
||||
return this._add(newData);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the author for this emoji
|
||||
* @param {EmojiResolvable} emoji The emoji to fetch the author of
|
||||
* @returns {Promise<User>}
|
||||
*/
|
||||
async fetchAuthor(emoji) {
|
||||
emoji = this.resolve(emoji);
|
||||
if (!emoji) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'emoji', 'EmojiResolvable', true);
|
||||
if (emoji.managed) {
|
||||
throw new DiscordjsError(ErrorCodes.EmojiManaged);
|
||||
}
|
||||
|
||||
const { me } = this.guild.members;
|
||||
if (!me) throw new DiscordjsError(ErrorCodes.GuildUncachedMe);
|
||||
if (!me.permissions.has(PermissionFlagsBits.ManageGuildExpressions)) {
|
||||
throw new DiscordjsError(ErrorCodes.MissingManageGuildExpressionsPermission, this.guild);
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(Routes.guildEmoji(this.guild.id, emoji.id));
|
||||
emoji._patch(data);
|
||||
return emoji.author;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildEmojiManager;
|
||||
118
node_modules/discord.js/src/managers/GuildEmojiRoleManager.js
generated
vendored
Normal file
118
node_modules/discord.js/src/managers/GuildEmojiRoleManager.js
generated
vendored
Normal file
@@ -0,0 +1,118 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const DataManager = require('./DataManager');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
const { Role } = require('../structures/Role');
|
||||
|
||||
/**
|
||||
* Manages API methods for roles belonging to emojis and stores their cache.
|
||||
* @extends {DataManager}
|
||||
*/
|
||||
class GuildEmojiRoleManager extends DataManager {
|
||||
constructor(emoji) {
|
||||
super(emoji.client, Role);
|
||||
|
||||
/**
|
||||
* The emoji belonging to this manager
|
||||
* @type {GuildEmoji}
|
||||
*/
|
||||
this.emoji = emoji;
|
||||
/**
|
||||
* The guild belonging to this manager
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = emoji.guild;
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of roles belonging to this emoji
|
||||
* @type {Collection<Snowflake, Role>}
|
||||
* @readonly
|
||||
*/
|
||||
get cache() {
|
||||
return this.guild.roles.cache.filter(role => this.emoji._roles.includes(role.id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a role (or multiple roles) to the list of roles that can use this emoji.
|
||||
* @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to add
|
||||
* @returns {Promise<GuildEmoji>}
|
||||
*/
|
||||
add(roleOrRoles) {
|
||||
if (!Array.isArray(roleOrRoles) && !(roleOrRoles instanceof Collection)) roleOrRoles = [roleOrRoles];
|
||||
|
||||
const resolvedRoles = [];
|
||||
for (const role of roleOrRoles.values()) {
|
||||
const resolvedRole = this.guild.roles.resolveId(role);
|
||||
if (!resolvedRole) {
|
||||
return Promise.reject(new DiscordjsTypeError(ErrorCodes.InvalidElement, 'Array or Collection', 'roles', role));
|
||||
}
|
||||
resolvedRoles.push(resolvedRole);
|
||||
}
|
||||
|
||||
const newRoles = [...new Set(resolvedRoles.concat(...this.cache.keys()))];
|
||||
return this.set(newRoles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a role (or multiple roles) from the list of roles that can use this emoji.
|
||||
* @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to remove
|
||||
* @returns {Promise<GuildEmoji>}
|
||||
*/
|
||||
remove(roleOrRoles) {
|
||||
if (!Array.isArray(roleOrRoles) && !(roleOrRoles instanceof Collection)) roleOrRoles = [roleOrRoles];
|
||||
|
||||
const resolvedRoleIds = [];
|
||||
for (const role of roleOrRoles.values()) {
|
||||
const roleId = this.guild.roles.resolveId(role);
|
||||
if (!roleId) {
|
||||
return Promise.reject(new DiscordjsTypeError(ErrorCodes.InvalidElement, 'Array or Collection', 'roles', role));
|
||||
}
|
||||
resolvedRoleIds.push(roleId);
|
||||
}
|
||||
|
||||
const newRoles = [...this.cache.keys()].filter(id => !resolvedRoleIds.includes(id));
|
||||
return this.set(newRoles);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the role(s) that can use this emoji.
|
||||
* @param {Collection<Snowflake, Role>|RoleResolvable[]} roles The roles or role ids to apply
|
||||
* @returns {Promise<GuildEmoji>}
|
||||
* @example
|
||||
* // Set the emoji's roles to a single role
|
||||
* guildEmoji.roles.set(['391156570408615936'])
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Remove all roles from an emoji
|
||||
* guildEmoji.roles.set([])
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
set(roles) {
|
||||
return this.emoji.edit({ roles });
|
||||
}
|
||||
|
||||
clone() {
|
||||
const clone = new this.constructor(this.emoji);
|
||||
clone._patch([...this.cache.keys()]);
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Patches the roles for this manager's cache
|
||||
* @param {Snowflake[]} roles The new roles
|
||||
* @private
|
||||
*/
|
||||
_patch(roles) {
|
||||
this.emoji._roles = roles;
|
||||
}
|
||||
|
||||
valueOf() {
|
||||
return this.cache;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildEmojiRoleManager;
|
||||
83
node_modules/discord.js/src/managers/GuildForumThreadManager.js
generated
vendored
Normal file
83
node_modules/discord.js/src/managers/GuildForumThreadManager.js
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
'use strict';
|
||||
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const ThreadManager = require('./ThreadManager');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
const MessagePayload = require('../structures/MessagePayload');
|
||||
|
||||
/**
|
||||
* Manages API methods for threads in forum channels and stores their cache.
|
||||
* @extends {ThreadManager}
|
||||
*/
|
||||
class GuildForumThreadManager extends ThreadManager {
|
||||
/**
|
||||
* The channel this Manager belongs to
|
||||
* @name GuildForumThreadManager#channel
|
||||
* @type {ForumChannel}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {BaseMessageOptions} GuildForumThreadMessageCreateOptions
|
||||
* @property {StickerResolvable} [stickers] The stickers to send with the message
|
||||
* @property {BitFieldResolvable} [flags] The flags to send with the message
|
||||
* <info>Only `MessageFlags.SuppressEmbeds` and `MessageFlags.SuppressNotifications` can be set.</info>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options for creating a thread.
|
||||
* @typedef {StartThreadOptions} GuildForumThreadCreateOptions
|
||||
* @property {GuildForumThreadMessageCreateOptions|MessagePayload} message The message associated with the thread post
|
||||
* @property {Snowflake[]} [appliedTags] The tags to apply to the thread
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new thread in the channel.
|
||||
* @param {GuildForumThreadCreateOptions} [options] Options to create a new thread
|
||||
* @returns {Promise<ThreadChannel>}
|
||||
* @example
|
||||
* // Create a new forum post
|
||||
* forum.threads
|
||||
* .create({
|
||||
* name: 'Food Talk',
|
||||
* autoArchiveDuration: ThreadAutoArchiveDuration.OneHour,
|
||||
* message: {
|
||||
* content: 'Discuss your favorite food!',
|
||||
* },
|
||||
* reason: 'Needed a separate thread for food',
|
||||
* })
|
||||
* .then(threadChannel => console.log(threadChannel))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async create({
|
||||
name,
|
||||
autoArchiveDuration = this.channel.defaultAutoArchiveDuration,
|
||||
message,
|
||||
reason,
|
||||
rateLimitPerUser,
|
||||
appliedTags,
|
||||
} = {}) {
|
||||
if (!message) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.GuildForumMessageRequired);
|
||||
}
|
||||
|
||||
const { body, files } = await (message instanceof MessagePayload ? message : MessagePayload.create(this, message))
|
||||
.resolveBody()
|
||||
.resolveFiles();
|
||||
|
||||
const data = await this.client.rest.post(Routes.threads(this.channel.id), {
|
||||
body: {
|
||||
name,
|
||||
auto_archive_duration: autoArchiveDuration,
|
||||
rate_limit_per_user: rateLimitPerUser,
|
||||
applied_tags: appliedTags,
|
||||
message: body,
|
||||
},
|
||||
files,
|
||||
reason,
|
||||
});
|
||||
|
||||
return this.client.actions.ThreadCreate.handle(data).thread;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildForumThreadManager;
|
||||
215
node_modules/discord.js/src/managers/GuildInviteManager.js
generated
vendored
Normal file
215
node_modules/discord.js/src/managers/GuildInviteManager.js
generated
vendored
Normal file
@@ -0,0 +1,215 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsError, ErrorCodes } = require('../errors');
|
||||
const Invite = require('../structures/Invite');
|
||||
const { resolveInviteCode } = require('../util/DataResolver');
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildInvites and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class GuildInviteManager extends CachedManager {
|
||||
constructor(guild, iterable) {
|
||||
super(guild.client, Invite, iterable);
|
||||
|
||||
/**
|
||||
* The guild this Manager belongs to
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of this Manager
|
||||
* @type {Collection<string, Invite>}
|
||||
* @name GuildInviteManager#cache
|
||||
*/
|
||||
|
||||
_add(data, cache) {
|
||||
return super._add(data, cache, { id: data.code, extras: [this.guild] });
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that resolves to give an Invite object. This can be:
|
||||
* * An invite code
|
||||
* * An invite URL
|
||||
* @typedef {string} InviteResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data that can be resolved to a channel that an invite can be created on. This can be:
|
||||
* * TextChannel
|
||||
* * VoiceChannel
|
||||
* * NewsChannel
|
||||
* * StageChannel
|
||||
* * ForumChannel
|
||||
* * MediaChannel
|
||||
* * Snowflake
|
||||
* @typedef {TextChannel|VoiceChannel|NewsChannel|StageChannel|ForumChannel|MediaChannel|Snowflake}
|
||||
* GuildInvitableChannelResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves an InviteResolvable to an Invite object.
|
||||
* @method resolve
|
||||
* @memberof GuildInviteManager
|
||||
* @instance
|
||||
* @param {InviteResolvable} invite The invite resolvable to resolve
|
||||
* @returns {?Invite}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves an InviteResolvable to an invite code string.
|
||||
* @method resolveId
|
||||
* @memberof GuildInviteManager
|
||||
* @instance
|
||||
* @param {InviteResolvable} invite The invite resolvable to resolve
|
||||
* @returns {?string}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch a single invite from a guild.
|
||||
* @typedef {Object} FetchInviteOptions
|
||||
* @property {InviteResolvable} code The invite to fetch
|
||||
* @property {boolean} [cache=true] Whether or not to cache the fetched invite
|
||||
* @property {boolean} [force=false] Whether to skip the cache check and request the API
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch all invites from a guild.
|
||||
* @typedef {Object} FetchInvitesOptions
|
||||
* @property {GuildInvitableChannelResolvable} [channelId]
|
||||
* The channel to fetch all invites from
|
||||
* @property {boolean} [cache=true] Whether or not to cache the fetched invites
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetches invite(s) from Discord.
|
||||
* @param {InviteResolvable|FetchInviteOptions|FetchInvitesOptions} [options] Options for fetching guild invite(s)
|
||||
* @returns {Promise<Invite|Collection<string, Invite>>}
|
||||
* @example
|
||||
* // Fetch all invites from a guild
|
||||
* guild.invites.fetch()
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch all invites from a guild without caching
|
||||
* guild.invites.fetch({ cache: false })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch all invites from a channel
|
||||
* guild.invites.fetch({ channelId: '222197033908436994' })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch a single invite
|
||||
* guild.invites.fetch('bRCvFy9')
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch a single invite without checking cache
|
||||
* guild.invites.fetch({ code: 'bRCvFy9', force: true })
|
||||
* .then(console.log)
|
||||
* .catch(console.error)
|
||||
* @example
|
||||
* // Fetch a single invite without caching
|
||||
* guild.invites.fetch({ code: 'bRCvFy9', cache: false })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetch(options) {
|
||||
if (!options) return this._fetchMany();
|
||||
if (typeof options === 'string') {
|
||||
const code = resolveInviteCode(options);
|
||||
if (!code) return Promise.reject(new DiscordjsError(ErrorCodes.InviteResolveCode));
|
||||
return this._fetchSingle({ code, cache: true });
|
||||
}
|
||||
if (!options.code) {
|
||||
if (options.channelId) {
|
||||
const id = this.guild.channels.resolveId(options.channelId);
|
||||
if (!id) return Promise.reject(new DiscordjsError(ErrorCodes.GuildChannelResolve));
|
||||
return this._fetchChannelMany(id, options.cache);
|
||||
}
|
||||
|
||||
if ('cache' in options) return this._fetchMany(options.cache);
|
||||
return Promise.reject(new DiscordjsError(ErrorCodes.InviteResolveCode));
|
||||
}
|
||||
return this._fetchSingle({
|
||||
...options,
|
||||
code: resolveInviteCode(options.code),
|
||||
});
|
||||
}
|
||||
|
||||
async _fetchSingle({ code, cache, force = false }) {
|
||||
if (!force) {
|
||||
const existing = this.cache.get(code);
|
||||
if (existing) return existing;
|
||||
}
|
||||
|
||||
const invites = await this._fetchMany(cache);
|
||||
const invite = invites.get(code);
|
||||
if (!invite) throw new DiscordjsError(ErrorCodes.InviteNotFound);
|
||||
return invite;
|
||||
}
|
||||
|
||||
async _fetchMany(cache) {
|
||||
const data = await this.client.rest.get(Routes.guildInvites(this.guild.id));
|
||||
return data.reduce((col, invite) => col.set(invite.code, this._add(invite, cache)), new Collection());
|
||||
}
|
||||
|
||||
async _fetchChannelMany(channelId, cache) {
|
||||
const data = await this.client.rest.get(Routes.channelInvites(channelId));
|
||||
return data.reduce((col, invite) => col.set(invite.code, this._add(invite, cache)), new Collection());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an invite to the guild from the provided channel.
|
||||
* @param {GuildInvitableChannelResolvable} channel The options for creating the invite from a channel.
|
||||
* @param {InviteCreateOptions} [options={}] The options for creating the invite from a channel.
|
||||
* @returns {Promise<Invite>}
|
||||
* @example
|
||||
* // Create an invite to a selected channel
|
||||
* guild.invites.create('599942732013764608')
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async create(
|
||||
channel,
|
||||
{ temporary, maxAge, maxUses, unique, targetUser, targetApplication, targetType, reason } = {},
|
||||
) {
|
||||
const id = this.guild.channels.resolveId(channel);
|
||||
if (!id) throw new DiscordjsError(ErrorCodes.GuildChannelResolve);
|
||||
|
||||
const invite = await this.client.rest.post(Routes.channelInvites(id), {
|
||||
body: {
|
||||
temporary,
|
||||
max_age: maxAge,
|
||||
max_uses: maxUses,
|
||||
unique,
|
||||
target_user_id: this.client.users.resolveId(targetUser),
|
||||
target_application_id: targetApplication?.id ?? targetApplication?.applicationId ?? targetApplication,
|
||||
target_type: targetType,
|
||||
},
|
||||
reason,
|
||||
});
|
||||
return new Invite(this.client, invite);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an invite.
|
||||
* @param {InviteResolvable} invite The invite to delete
|
||||
* @param {string} [reason] Reason for deleting the invite
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async delete(invite, reason) {
|
||||
const code = resolveInviteCode(invite);
|
||||
|
||||
await this.client.rest.delete(Routes.invite(code), { reason });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildInviteManager;
|
||||
299
node_modules/discord.js/src/managers/GuildManager.js
generated
vendored
Normal file
299
node_modules/discord.js/src/managers/GuildManager.js
generated
vendored
Normal file
@@ -0,0 +1,299 @@
|
||||
'use strict';
|
||||
|
||||
const process = require('node:process');
|
||||
const { setTimeout, clearTimeout } = require('node:timers');
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { makeURLSearchParams } = require('@discordjs/rest');
|
||||
const { Routes, RouteBases } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const ShardClientUtil = require('../sharding/ShardClientUtil');
|
||||
const { Guild } = require('../structures/Guild');
|
||||
const GuildChannel = require('../structures/GuildChannel');
|
||||
const GuildEmoji = require('../structures/GuildEmoji');
|
||||
const { GuildMember } = require('../structures/GuildMember');
|
||||
const Invite = require('../structures/Invite');
|
||||
const OAuth2Guild = require('../structures/OAuth2Guild');
|
||||
const { Role } = require('../structures/Role');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
const Events = require('../util/Events');
|
||||
const PermissionsBitField = require('../util/PermissionsBitField');
|
||||
const SystemChannelFlagsBitField = require('../util/SystemChannelFlagsBitField');
|
||||
const { resolveColor } = require('../util/Util');
|
||||
|
||||
let cacheWarningEmitted = false;
|
||||
|
||||
/**
|
||||
* Manages API methods for Guilds and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class GuildManager extends CachedManager {
|
||||
constructor(client, iterable) {
|
||||
super(client, Guild, iterable);
|
||||
if (!cacheWarningEmitted && this._cache.constructor.name !== 'Collection') {
|
||||
cacheWarningEmitted = true;
|
||||
process.emitWarning(
|
||||
`Overriding the cache handling for ${this.constructor.name} is unsupported and breaks functionality.`,
|
||||
'UnsupportedCacheOverwriteWarning',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of this Manager
|
||||
* @type {Collection<Snowflake, Guild>}
|
||||
* @name GuildManager#cache
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data that resolves to give a Guild object. This can be:
|
||||
* * A Guild object
|
||||
* * A GuildChannel object
|
||||
* * A GuildEmoji object
|
||||
* * A Role object
|
||||
* * A Snowflake
|
||||
* * An Invite object
|
||||
* @typedef {Guild|GuildChannel|GuildMember|GuildEmoji|Role|Snowflake|Invite} GuildResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Partial data for a Role.
|
||||
* @typedef {Object} PartialRoleData
|
||||
* @property {Snowflake|number} [id] The role's id, used to set channel overrides.
|
||||
* This is a placeholder and will be replaced by the API after consumption
|
||||
* @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
|
||||
* @property {boolean} [hoist] Whether 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 the role should be mentionable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Partial overwrite data.
|
||||
* @typedef {Object} PartialOverwriteData
|
||||
* @property {Snowflake|number} id The id of the {@link Role} or {@link User} this overwrite belongs to
|
||||
* @property {OverwriteType} [type] The type of this overwrite
|
||||
* @property {PermissionResolvable} [allow] The permissions to allow
|
||||
* @property {PermissionResolvable} [deny] The permissions to deny
|
||||
*/
|
||||
|
||||
/**
|
||||
* Partial data for a Channel.
|
||||
* @typedef {Object} PartialChannelData
|
||||
* @property {Snowflake|number} [id] The channel's id, used to set its parent.
|
||||
* This is a placeholder and will be replaced by the API after consumption
|
||||
* @property {Snowflake|number} [parentId] The parent id for this channel
|
||||
* @property {ChannelType.GuildText|ChannelType.GuildVoice|ChannelType.GuildCategory} [type] The type of the channel
|
||||
* @property {string} name The name of the channel
|
||||
* @property {?string} [topic] The topic of the text channel
|
||||
* @property {boolean} [nsfw] Whether the channel is NSFW
|
||||
* @property {number} [bitrate] The bitrate of the voice channel
|
||||
* @property {number} [userLimit] The user limit of the channel
|
||||
* @property {?string} [rtcRegion] The RTC region of the channel
|
||||
* @property {VideoQualityMode} [videoQualityMode] The camera video quality mode of the channel
|
||||
* @property {PartialOverwriteData[]} [permissionOverwrites]
|
||||
* Overwrites of the channel
|
||||
* @property {number} [rateLimitPerUser] The rate limit per user (slowmode) of the channel in seconds
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a {@link GuildResolvable} to a {@link Guild} object.
|
||||
* @method resolve
|
||||
* @memberof GuildManager
|
||||
* @instance
|
||||
* @param {GuildResolvable} guild The guild resolvable to identify
|
||||
* @returns {?Guild}
|
||||
*/
|
||||
resolve(guild) {
|
||||
if (
|
||||
guild instanceof GuildChannel ||
|
||||
guild instanceof GuildMember ||
|
||||
guild instanceof GuildEmoji ||
|
||||
guild instanceof Role ||
|
||||
(guild instanceof Invite && guild.guild)
|
||||
) {
|
||||
return super.resolve(guild.guild);
|
||||
}
|
||||
return super.resolve(guild);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a {@link GuildResolvable} to a {@link Guild} id string.
|
||||
* @method resolveId
|
||||
* @memberof GuildManager
|
||||
* @instance
|
||||
* @param {GuildResolvable} guild The guild resolvable to identify
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
resolveId(guild) {
|
||||
if (
|
||||
guild instanceof GuildChannel ||
|
||||
guild instanceof GuildMember ||
|
||||
guild instanceof GuildEmoji ||
|
||||
guild instanceof Role ||
|
||||
(guild instanceof Invite && guild.guild)
|
||||
) {
|
||||
return super.resolveId(guild.guild.id);
|
||||
}
|
||||
return super.resolveId(guild);
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to create a guild.
|
||||
* @typedef {Object} GuildCreateOptions
|
||||
* @property {string} name The name of the guild
|
||||
* @property {?(BufferResolvable|Base64Resolvable)} [icon=null] The icon for the guild
|
||||
* @property {GuildVerificationLevel} [verificationLevel] The verification level for the guild
|
||||
* @property {GuildDefaultMessageNotifications} [defaultMessageNotifications] The default message notifications
|
||||
* for the guild
|
||||
* @property {GuildExplicitContentFilter} [explicitContentFilter] The explicit content filter level for the guild
|
||||
* @property {PartialRoleData[]} [roles=[]] The roles for this guild,
|
||||
* @property {PartialChannelData[]} [channels=[]] The channels for this guild
|
||||
* @property {Snowflake|number} [afkChannelId] The AFK channel's id
|
||||
* @property {number} [afkTimeout] The AFK timeout in seconds
|
||||
* the first element of this array is used to change properties of the guild's everyone role.
|
||||
* @property {Snowflake|number} [systemChannelId] The system channel's id
|
||||
* @property {SystemChannelFlagsResolvable} [systemChannelFlags] The flags of the system channel
|
||||
*/
|
||||
/* eslint-enable max-len */
|
||||
|
||||
/**
|
||||
* Creates a guild.
|
||||
* <warn>This is only available to bots in fewer than 10 guilds.</warn>
|
||||
* @param {GuildCreateOptions} options Options for creating the guild
|
||||
* @returns {Promise<Guild>} The guild that was created
|
||||
*/
|
||||
async create({
|
||||
name,
|
||||
icon = null,
|
||||
verificationLevel,
|
||||
defaultMessageNotifications,
|
||||
explicitContentFilter,
|
||||
roles = [],
|
||||
channels = [],
|
||||
afkChannelId,
|
||||
afkTimeout,
|
||||
systemChannelId,
|
||||
systemChannelFlags,
|
||||
}) {
|
||||
const data = await this.client.rest.post(Routes.guilds(), {
|
||||
body: {
|
||||
name,
|
||||
icon: icon && (await resolveImage(icon)),
|
||||
verification_level: verificationLevel,
|
||||
default_message_notifications: defaultMessageNotifications,
|
||||
explicit_content_filter: explicitContentFilter,
|
||||
roles: roles.map(({ color, permissions, ...options }) => ({
|
||||
...options,
|
||||
color: color && resolveColor(color),
|
||||
permissions: permissions === undefined ? undefined : PermissionsBitField.resolve(permissions).toString(),
|
||||
})),
|
||||
channels: channels.map(
|
||||
({
|
||||
parentId,
|
||||
userLimit,
|
||||
rtcRegion,
|
||||
videoQualityMode,
|
||||
permissionOverwrites,
|
||||
rateLimitPerUser,
|
||||
...options
|
||||
}) => ({
|
||||
...options,
|
||||
parent_id: parentId,
|
||||
user_limit: userLimit,
|
||||
rtc_region: rtcRegion,
|
||||
video_quality_mode: videoQualityMode,
|
||||
permission_overwrites: permissionOverwrites?.map(({ allow, deny, ...permissionOverwriteOptions }) => ({
|
||||
...permissionOverwriteOptions,
|
||||
allow: allow === undefined ? undefined : PermissionsBitField.resolve(allow).toString(),
|
||||
deny: deny === undefined ? undefined : PermissionsBitField.resolve(deny).toString(),
|
||||
})),
|
||||
rate_limit_per_user: rateLimitPerUser,
|
||||
}),
|
||||
),
|
||||
afk_channel_id: afkChannelId,
|
||||
afk_timeout: afkTimeout,
|
||||
system_channel_id: systemChannelId,
|
||||
system_channel_flags:
|
||||
systemChannelFlags === undefined ? undefined : SystemChannelFlagsBitField.resolve(systemChannelFlags),
|
||||
},
|
||||
});
|
||||
|
||||
return (
|
||||
this.client.guilds.cache.get(data.id) ??
|
||||
new Promise(resolve => {
|
||||
const handleGuild = guild => {
|
||||
if (guild.id === data.id) {
|
||||
clearTimeout(timeout);
|
||||
this.client.decrementMaxListeners();
|
||||
resolve(guild);
|
||||
}
|
||||
};
|
||||
this.client.incrementMaxListeners();
|
||||
this.client.once(Events.GuildCreate, handleGuild);
|
||||
|
||||
const timeout = setTimeout(() => {
|
||||
this.client.removeListener(Events.GuildCreate, handleGuild);
|
||||
this.client.decrementMaxListeners();
|
||||
resolve(this.client.guilds._add(data));
|
||||
}, 10_000).unref();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to fetch a single guild.
|
||||
* @typedef {BaseFetchOptions} FetchGuildOptions
|
||||
* @property {GuildResolvable} guild The guild to fetch
|
||||
* @property {boolean} [withCounts=true] Whether the approximate member and presence counts should be returned
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch multiple guilds.
|
||||
* @typedef {Object} FetchGuildsOptions
|
||||
* @property {Snowflake} [before] Get guilds before this guild id
|
||||
* @property {Snowflake} [after] Get guilds after this guild id
|
||||
* @property {number} [limit] Maximum number of guilds to request (1-200)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Obtains one or multiple guilds from Discord, or the guild cache if it's already available.
|
||||
* @param {GuildResolvable|FetchGuildOptions|FetchGuildsOptions} [options] The guild's id or options
|
||||
* @returns {Promise<Guild|Collection<Snowflake, OAuth2Guild>>}
|
||||
*/
|
||||
async fetch(options = {}) {
|
||||
const id = this.resolveId(options) ?? this.resolveId(options.guild);
|
||||
|
||||
if (id) {
|
||||
if (!options.force) {
|
||||
const existing = this.cache.get(id);
|
||||
if (existing) return existing;
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(Routes.guild(id), {
|
||||
query: makeURLSearchParams({ with_counts: options.withCounts ?? true }),
|
||||
});
|
||||
data.shardId = ShardClientUtil.shardIdForGuildId(id, this.client.options.shardCount);
|
||||
return this._add(data, options.cache);
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(Routes.userGuilds(), { query: makeURLSearchParams(options) });
|
||||
return data.reduce((coll, guild) => coll.set(guild.id, new OAuth2Guild(this.client, guild)), new Collection());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a URL for the PNG widget of a guild.
|
||||
* @param {GuildResolvable} guild The guild of the widget image
|
||||
* @param {GuildWidgetStyle} [style] The style for the widget image
|
||||
* @returns {string}
|
||||
*/
|
||||
widgetImageURL(guild, style) {
|
||||
const urlSearchParams = String(makeURLSearchParams({ style }));
|
||||
|
||||
return `${RouteBases.api}${Routes.guildWidgetImage(this.resolveId(guild))}${
|
||||
urlSearchParams ? `?${urlSearchParams}` : ''
|
||||
}`;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildManager;
|
||||
560
node_modules/discord.js/src/managers/GuildMemberManager.js
generated
vendored
Normal file
560
node_modules/discord.js/src/managers/GuildMemberManager.js
generated
vendored
Normal file
@@ -0,0 +1,560 @@
|
||||
'use strict';
|
||||
|
||||
const { setTimeout, clearTimeout } = require('node:timers');
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { makeURLSearchParams } = require('@discordjs/rest');
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const { Routes, GatewayOpcodes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsError, DiscordjsTypeError, DiscordjsRangeError, ErrorCodes } = require('../errors');
|
||||
const BaseGuildVoiceChannel = require('../structures/BaseGuildVoiceChannel');
|
||||
const { GuildMember } = require('../structures/GuildMember');
|
||||
const { Role } = require('../structures/Role');
|
||||
const Events = require('../util/Events');
|
||||
const { GuildMemberFlagsBitField } = require('../util/GuildMemberFlagsBitField');
|
||||
const Partials = require('../util/Partials');
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildMembers and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class GuildMemberManager extends CachedManager {
|
||||
constructor(guild, iterable) {
|
||||
super(guild.client, GuildMember, iterable);
|
||||
|
||||
/**
|
||||
* The guild this manager belongs to
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of this Manager
|
||||
* @type {Collection<Snowflake, GuildMember>}
|
||||
* @name GuildMemberManager#cache
|
||||
*/
|
||||
|
||||
_add(data, cache = true) {
|
||||
return super._add(data, cache, { id: data.user.id, extras: [this.guild] });
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that resolves to give a GuildMember object. This can be:
|
||||
* * A GuildMember object
|
||||
* * A User resolvable
|
||||
* @typedef {GuildMember|UserResolvable} GuildMemberResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a {@link GuildMemberResolvable} to a {@link GuildMember} object.
|
||||
* @param {GuildMemberResolvable} member The user that is part of the guild
|
||||
* @returns {?GuildMember}
|
||||
*/
|
||||
resolve(member) {
|
||||
const memberResolvable = super.resolve(member);
|
||||
if (memberResolvable) return memberResolvable;
|
||||
const userResolvable = this.client.users.resolveId(member);
|
||||
if (userResolvable) return super.resolve(userResolvable);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a {@link GuildMemberResolvable} to a member id.
|
||||
* @param {GuildMemberResolvable} member The user that is part of the guild
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
resolveId(member) {
|
||||
const memberResolvable = super.resolveId(member);
|
||||
if (memberResolvable) return memberResolvable;
|
||||
const userResolvable = this.client.users.resolveId(member);
|
||||
return this.cache.has(userResolvable) ? userResolvable : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to add a user to a guild using OAuth2.
|
||||
* @typedef {Object} AddGuildMemberOptions
|
||||
* @property {string} accessToken An OAuth2 access token for the user with the {@link OAuth2Scopes.GuildsJoin}
|
||||
* scope granted to the bot's application
|
||||
* @property {string} [nick] The nickname to give to the member
|
||||
* <info>This property requires the {@link PermissionFlagsBits.ManageNicknames} permission.</info>
|
||||
* @property {Collection<Snowflake, Role>|RoleResolvable[]} [roles] The roles to add to the member
|
||||
* <info>This property requires the {@link PermissionFlagsBits.ManageRoles} permission.</info>
|
||||
* @property {boolean} [mute] Whether the member should be muted
|
||||
* <info>This property requires the {@link PermissionFlagsBits.MuteMembers} permission.</info>
|
||||
* @property {boolean} [deaf] Whether the member should be deafened
|
||||
* <info>This property requires the {@link PermissionFlagsBits.MuteMembers} permission.</info>
|
||||
* @property {boolean} [force] Whether to skip the cache check and request the API directly
|
||||
* @property {boolean} [fetchWhenExisting=true] Whether to fetch the user if not cached and already a member
|
||||
*/
|
||||
|
||||
/**
|
||||
* Adds a user to the guild using OAuth2.
|
||||
* <info>This method requires the {@link PermissionFlagsBits.CreateInstantInvite} permission.
|
||||
* @param {UserResolvable} user The user to add to the guild
|
||||
* @param {AddGuildMemberOptions} options Options for adding the user to the guild
|
||||
* @returns {Promise<?GuildMember>}
|
||||
*/
|
||||
async add(user, options) {
|
||||
const userId = this.client.users.resolveId(user);
|
||||
if (!userId) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'user', 'UserResolvable');
|
||||
if (!options.force) {
|
||||
const cachedUser = this.cache.get(userId);
|
||||
if (cachedUser) return cachedUser;
|
||||
}
|
||||
const resolvedOptions = {
|
||||
access_token: options.accessToken,
|
||||
nick: options.nick,
|
||||
mute: options.mute,
|
||||
deaf: options.deaf,
|
||||
};
|
||||
if (options.roles) {
|
||||
if (!Array.isArray(options.roles) && !(options.roles instanceof Collection)) {
|
||||
throw new DiscordjsTypeError(
|
||||
ErrorCodes.InvalidType,
|
||||
'options.roles',
|
||||
'Array or Collection of Roles or Snowflakes',
|
||||
true,
|
||||
);
|
||||
}
|
||||
const resolvedRoles = [];
|
||||
for (const role of options.roles.values()) {
|
||||
const resolvedRole = this.guild.roles.resolveId(role);
|
||||
if (!resolvedRole) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidElement, 'Array or Collection', 'options.roles', role);
|
||||
}
|
||||
resolvedRoles.push(resolvedRole);
|
||||
}
|
||||
resolvedOptions.roles = resolvedRoles;
|
||||
}
|
||||
const data = await this.client.rest.put(Routes.guildMember(this.guild.id, userId), { body: resolvedOptions });
|
||||
|
||||
// Data is an empty array buffer if the member is already part of the guild.
|
||||
return data instanceof ArrayBuffer
|
||||
? options.fetchWhenExisting === false
|
||||
? null
|
||||
: this.fetch(userId)
|
||||
: this._add(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* The client user as a GuildMember of this guild
|
||||
* @type {?GuildMember}
|
||||
* @readonly
|
||||
*/
|
||||
get me() {
|
||||
return (
|
||||
this.resolve(this.client.user.id) ??
|
||||
(this.client.options.partials.includes(Partials.GuildMember)
|
||||
? this._add({ user: { id: this.client.user.id } }, true)
|
||||
: null)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to fetch a single member from a guild.
|
||||
* @typedef {BaseFetchOptions} FetchMemberOptions
|
||||
* @property {UserResolvable} user The user to fetch
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch multiple members from a guild.
|
||||
* @typedef {Object} FetchMembersOptions
|
||||
* @property {UserResolvable|UserResolvable[]} [user] The user(s) to fetch
|
||||
* @property {?string} [query] Limit fetch to members with similar usernames
|
||||
* @property {number} [limit=0] Maximum number of members to request
|
||||
* @property {boolean} [withPresences=false] Whether to include the presences
|
||||
* @property {number} [time=120e3] Timeout for receipt of members
|
||||
* @property {?string} [nonce] Nonce for this request (32 characters max - default to base 16 now timestamp)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetches member(s) from a guild.
|
||||
* @param {UserResolvable|FetchMemberOptions|FetchMembersOptions} [options] Options for fetching member(s).
|
||||
* Omitting the parameter or providing `undefined` will fetch all members.
|
||||
* @returns {Promise<GuildMember|Collection<Snowflake, GuildMember>>}
|
||||
* @example
|
||||
* // Fetch all members from a guild
|
||||
* guild.members.fetch()
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch a single member
|
||||
* guild.members.fetch('66564597481480192')
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch a single member without checking cache
|
||||
* guild.members.fetch({ user, force: true })
|
||||
* .then(console.log)
|
||||
* .catch(console.error)
|
||||
* @example
|
||||
* // Fetch a single member without caching
|
||||
* guild.members.fetch({ user, cache: false })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch by an array of users including their presences
|
||||
* guild.members.fetch({ user: ['66564597481480192', '191615925336670208'], withPresences: true })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch by query
|
||||
* guild.members.fetch({ query: 'hydra', limit: 1 })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetch(options) {
|
||||
if (!options) return this._fetchMany();
|
||||
const { user: users, limit, withPresences, cache, force } = options;
|
||||
const resolvedUser = this.client.users.resolveId(users ?? options);
|
||||
if (resolvedUser && !limit && !withPresences) return this._fetchSingle({ user: resolvedUser, cache, force });
|
||||
const resolvedUsers = users?.map?.(user => this.client.users.resolveId(user)) ?? resolvedUser ?? undefined;
|
||||
return this._fetchMany({ ...options, users: resolvedUsers });
|
||||
}
|
||||
|
||||
async _fetchSingle({ user, cache, force = false }) {
|
||||
if (!force) {
|
||||
const existing = this.cache.get(user);
|
||||
if (existing && !existing.partial) return existing;
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(Routes.guildMember(this.guild.id, user));
|
||||
return this._add(data, cache);
|
||||
}
|
||||
|
||||
_fetchMany({
|
||||
limit = 0,
|
||||
withPresences: presences,
|
||||
users,
|
||||
query,
|
||||
time = 120e3,
|
||||
nonce = DiscordSnowflake.generate().toString(),
|
||||
} = {}) {
|
||||
if (nonce.length > 32) return Promise.reject(new DiscordjsRangeError(ErrorCodes.MemberFetchNonceLength));
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!query && !users) query = '';
|
||||
this.guild.shard.send({
|
||||
op: GatewayOpcodes.RequestGuildMembers,
|
||||
d: {
|
||||
guild_id: this.guild.id,
|
||||
presences,
|
||||
user_ids: users,
|
||||
query,
|
||||
nonce,
|
||||
limit,
|
||||
},
|
||||
});
|
||||
const fetchedMembers = new Collection();
|
||||
let i = 0;
|
||||
const handler = (members, _, chunk) => {
|
||||
if (chunk.nonce !== nonce) return;
|
||||
timeout.refresh();
|
||||
i++;
|
||||
for (const member of members.values()) {
|
||||
fetchedMembers.set(member.id, member);
|
||||
}
|
||||
if (members.size < 1_000 || (limit && fetchedMembers.size >= limit) || i === chunk.count) {
|
||||
clearTimeout(timeout);
|
||||
this.client.removeListener(Events.GuildMembersChunk, handler);
|
||||
this.client.decrementMaxListeners();
|
||||
resolve(users && !Array.isArray(users) && fetchedMembers.size ? fetchedMembers.first() : fetchedMembers);
|
||||
}
|
||||
};
|
||||
const timeout = setTimeout(() => {
|
||||
this.client.removeListener(Events.GuildMembersChunk, handler);
|
||||
this.client.decrementMaxListeners();
|
||||
reject(new DiscordjsError(ErrorCodes.GuildMembersTimeout));
|
||||
}, time).unref();
|
||||
this.client.incrementMaxListeners();
|
||||
this.client.on(Events.GuildMembersChunk, handler);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the client user as a GuildMember of the guild.
|
||||
* @param {BaseFetchOptions} [options] The options for fetching the member
|
||||
* @returns {Promise<GuildMember>}
|
||||
*/
|
||||
fetchMe(options) {
|
||||
return this.fetch({ ...options, user: this.client.user.id });
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used for searching guild members.
|
||||
* @typedef {Object} GuildSearchMembersOptions
|
||||
* @property {string} query Filter members whose username or nickname start with this query
|
||||
* @property {number} [limit] Maximum number of members to search
|
||||
* @property {boolean} [cache=true] Whether or not to cache the fetched member(s)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Searches for members in the guild based on a query.
|
||||
* @param {GuildSearchMembersOptions} options Options for searching members
|
||||
* @returns {Promise<Collection<Snowflake, GuildMember>>}
|
||||
*/
|
||||
async search({ query, limit, cache = true } = {}) {
|
||||
const data = await this.client.rest.get(Routes.guildMembersSearch(this.guild.id), {
|
||||
query: makeURLSearchParams({ query, limit }),
|
||||
});
|
||||
return data.reduce((col, member) => col.set(member.user.id, this._add(member, cache)), new Collection());
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used for listing guild members.
|
||||
* @typedef {Object} GuildListMembersOptions
|
||||
* @property {Snowflake} [after] Limit fetching members to those with an id greater than the supplied id
|
||||
* @property {number} [limit] Maximum number of members to list
|
||||
* @property {boolean} [cache=true] Whether or not to cache the fetched member(s)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Lists up to 1000 members of the guild.
|
||||
* @param {GuildListMembersOptions} [options] Options for listing members
|
||||
* @returns {Promise<Collection<Snowflake, GuildMember>>}
|
||||
*/
|
||||
async list({ after, limit, cache = true } = {}) {
|
||||
const query = makeURLSearchParams({ limit, after });
|
||||
const data = await this.client.rest.get(Routes.guildMembers(this.guild.id), { query });
|
||||
return data.reduce((col, member) => col.set(member.user.id, this._add(member, cache)), new Collection());
|
||||
}
|
||||
|
||||
/**
|
||||
* The data for editing a guild member.
|
||||
* @typedef {Object} GuildMemberEditOptions
|
||||
* @property {?string} [nick] The nickname to set for the member
|
||||
* @property {Collection<Snowflake, Role>|RoleResolvable[]} [roles] The roles or role ids to apply
|
||||
* @property {boolean} [mute] Whether or not the member should be muted
|
||||
* @property {boolean} [deaf] Whether or not the member should be deafened
|
||||
* @property {?GuildVoiceChannelResolvable} [channel] Channel to move the member to
|
||||
* (if they are connected to voice), or `null` if you want to disconnect them from voice
|
||||
* @property {?DateResolvable} [communicationDisabledUntil] The date or timestamp
|
||||
* for the member's communication to be disabled until. Provide `null` to enable communication again.
|
||||
* @property {GuildMemberFlagsResolvable} [flags] The flags to set for the member
|
||||
* @property {string} [reason] Reason for editing this user
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits a member of the guild.
|
||||
* <info>The user must be a member of the guild</info>
|
||||
* @param {UserResolvable} user The member to edit
|
||||
* @param {GuildMemberEditOptions} options The options to provide
|
||||
* @returns {Promise<GuildMember>}
|
||||
*/
|
||||
async edit(user, { reason, ...options }) {
|
||||
const id = this.client.users.resolveId(user);
|
||||
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'user', 'UserResolvable');
|
||||
|
||||
if (options.channel) {
|
||||
options.channel = this.guild.channels.resolve(options.channel);
|
||||
if (!(options.channel instanceof BaseGuildVoiceChannel)) {
|
||||
throw new DiscordjsError(ErrorCodes.GuildVoiceChannelResolve);
|
||||
}
|
||||
options.channel_id = options.channel.id;
|
||||
options.channel = undefined;
|
||||
} else if (options.channel === null) {
|
||||
options.channel_id = null;
|
||||
options.channel = undefined;
|
||||
}
|
||||
options.roles &&= options.roles.map(role => (role instanceof Role ? role.id : role));
|
||||
|
||||
if (options.communicationDisabledUntil !== undefined) {
|
||||
options.communication_disabled_until =
|
||||
// eslint-disable-next-line eqeqeq
|
||||
options.communicationDisabledUntil != null
|
||||
? new Date(options.communicationDisabledUntil).toISOString()
|
||||
: options.communicationDisabledUntil;
|
||||
}
|
||||
|
||||
if (options.flags !== undefined) {
|
||||
options.flags = GuildMemberFlagsBitField.resolve(options.flags);
|
||||
}
|
||||
|
||||
let endpoint;
|
||||
if (id === this.client.user.id) {
|
||||
const keys = Object.keys(options);
|
||||
if (keys.length === 1 && keys[0] === 'nick') endpoint = Routes.guildMember(this.guild.id);
|
||||
else endpoint = Routes.guildMember(this.guild.id, id);
|
||||
} else {
|
||||
endpoint = Routes.guildMember(this.guild.id, id);
|
||||
}
|
||||
const d = await this.client.rest.patch(endpoint, { body: options, reason });
|
||||
|
||||
const clone = this.cache.get(id)?._clone();
|
||||
clone?._patch(d);
|
||||
return clone ?? this._add(d, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used for pruning guild members.
|
||||
* <info>It's recommended to set {@link GuildPruneMembersOptions#count options.count}
|
||||
* to `false` for large guilds.</info>
|
||||
* @typedef {Object} GuildPruneMembersOptions
|
||||
* @property {number} [days] Number of days of inactivity required to kick
|
||||
* @property {boolean} [dry=false] Get the number of users that will be kicked, without actually kicking them
|
||||
* @property {boolean} [count] Whether or not to return the number of users that have been kicked.
|
||||
* @property {RoleResolvable[]} [roles] Array of roles to bypass the "...and no roles" constraint when pruning
|
||||
* @property {string} [reason] Reason for this prune
|
||||
*/
|
||||
|
||||
/**
|
||||
* Prunes members from the guild based on how long they have been inactive.
|
||||
* @param {GuildPruneMembersOptions} [options] Options for pruning
|
||||
* @returns {Promise<?number>} The number of members that were/will be kicked
|
||||
* @example
|
||||
* // See how many members will be pruned
|
||||
* guild.members.prune({ dry: true })
|
||||
* .then(pruned => console.log(`This will prune ${pruned} people!`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Actually prune the members
|
||||
* guild.members.prune({ days: 1, reason: 'too many people!' })
|
||||
* .then(pruned => console.log(`I just pruned ${pruned} people!`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Include members with a specified role
|
||||
* guild.members.prune({ days: 7, roles: ['657259391652855808'] })
|
||||
* .then(pruned => console.log(`I just pruned ${pruned} people!`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async prune({ days, dry = false, count: compute_prune_count, roles = [], reason } = {}) {
|
||||
if (typeof days !== 'number') throw new DiscordjsTypeError(ErrorCodes.PruneDaysType);
|
||||
|
||||
const query = { days };
|
||||
const resolvedRoles = [];
|
||||
|
||||
for (const role of roles) {
|
||||
const resolvedRole = this.guild.roles.resolveId(role);
|
||||
if (!resolvedRole) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidElement, 'Array', 'options.roles', role);
|
||||
}
|
||||
resolvedRoles.push(resolvedRole);
|
||||
}
|
||||
|
||||
if (resolvedRoles.length) {
|
||||
query.include_roles = dry ? resolvedRoles.join(',') : resolvedRoles;
|
||||
}
|
||||
|
||||
const endpoint = Routes.guildPrune(this.guild.id);
|
||||
|
||||
const { pruned } = await (dry
|
||||
? this.client.rest.get(endpoint, { query: makeURLSearchParams(query), reason })
|
||||
: this.client.rest.post(endpoint, { body: { ...query, compute_prune_count }, reason }));
|
||||
|
||||
return pruned;
|
||||
}
|
||||
|
||||
/**
|
||||
* Kicks a user from the guild.
|
||||
* <info>The user must be a member of the guild</info>
|
||||
* @param {UserResolvable} user The member to kick
|
||||
* @param {string} [reason] Reason for kicking
|
||||
* @returns {Promise<GuildMember|User|Snowflake>} Result object will be resolved as specifically as possible.
|
||||
* If the GuildMember cannot be resolved, the User will instead be attempted to be resolved. If that also cannot
|
||||
* be resolved, the user's id will be the result.
|
||||
* @example
|
||||
* // Kick a user by id (or with a user/guild member object)
|
||||
* guild.members.kick('84484653687267328')
|
||||
* .then(kickInfo => console.log(`Kicked ${kickInfo.user?.tag ?? kickInfo.tag ?? kickInfo}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async kick(user, reason) {
|
||||
const id = this.client.users.resolveId(user);
|
||||
if (!id) return Promise.reject(new DiscordjsTypeError(ErrorCodes.InvalidType, 'user', 'UserResolvable'));
|
||||
|
||||
await this.client.rest.delete(Routes.guildMember(this.guild.id, id), { reason });
|
||||
|
||||
return this.resolve(user) ?? this.client.users.resolve(user) ?? id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bans a user from the guild.
|
||||
* @param {UserResolvable} user The user to ban
|
||||
* @param {BanOptions} [options] Options for the ban
|
||||
* @returns {Promise<GuildMember|User|Snowflake>} Result object will be resolved as specifically as possible.
|
||||
* If the GuildMember cannot be resolved, the User will instead be attempted to be resolved. If that also cannot
|
||||
* be resolved, the user id will be the result.
|
||||
* Internally calls the GuildBanManager#create method.
|
||||
* @example
|
||||
* // Ban a user by id (or with a user/guild member object)
|
||||
* guild.members.ban('84484653687267328')
|
||||
* .then(banInfo => console.log(`Banned ${banInfo.user?.tag ?? banInfo.tag ?? banInfo}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
ban(user, options) {
|
||||
return this.guild.bans.create(user, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbans a user from the guild. Internally calls the {@link GuildBanManager#remove} method.
|
||||
* @param {UserResolvable} user The user to unban
|
||||
* @param {string} [reason] Reason for unbanning user
|
||||
* @returns {Promise<?User>} The user that was unbanned
|
||||
* @example
|
||||
* // Unban a user by id (or with a user/guild member object)
|
||||
* guild.members.unban('84484653687267328')
|
||||
* .then(user => console.log(`Unbanned ${user.username} from ${guild.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
unban(user, reason) {
|
||||
return this.guild.bans.remove(user, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk ban users from a guild, and optionally delete previous messages sent by them.
|
||||
* @param {Collection<Snowflake, UserResolvable>|UserResolvable[]} users The users to ban
|
||||
* @param {BulkBanOptions} [options] The options for bulk banning users
|
||||
* @returns {Promise<BulkBanResult>} Returns an object with `bannedUsers` key containing the IDs of the banned users
|
||||
* and the key `failedUsers` with the IDs that could not be banned or were already banned.
|
||||
* Internally calls the GuildBanManager#bulkCreate method.
|
||||
* @example
|
||||
* // Bulk ban users by ids (or with user/guild member objects) and delete all their messages from the past 7 days
|
||||
* guild.members.bulkBan(['84484653687267328'], { deleteMessageSeconds: 7 * 24 * 60 * 60 })
|
||||
* .then(result => {
|
||||
* console.log(`Banned ${result.bannedUsers.length} users, failed to ban ${result.failedUsers.length} users.`)
|
||||
* })
|
||||
* .catch(console.error);
|
||||
*/
|
||||
bulkBan(users, options = {}) {
|
||||
return this.guild.bans.bulkCreate(users, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used for adding or removing a role from a member.
|
||||
* @typedef {Object} AddOrRemoveGuildMemberRoleOptions
|
||||
* @property {GuildMemberResolvable} user The user to add/remove the role from
|
||||
* @property {RoleResolvable} role The role to add/remove
|
||||
* @property {string} [reason] Reason for adding/removing the role
|
||||
*/
|
||||
|
||||
/**
|
||||
* Adds a role to a member.
|
||||
* @param {AddOrRemoveGuildMemberRoleOptions} options Options for adding the role
|
||||
* @returns {Promise<GuildMember|User|Snowflake>}
|
||||
*/
|
||||
async addRole(options) {
|
||||
const { user, role, reason } = options;
|
||||
const userId = this.guild.members.resolveId(user);
|
||||
const roleId = this.guild.roles.resolveId(role);
|
||||
await this.client.rest.put(Routes.guildMemberRole(this.guild.id, userId, roleId), { reason });
|
||||
|
||||
return this.resolve(user) ?? this.client.users.resolve(user) ?? userId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a role from a member.
|
||||
* @param {AddOrRemoveGuildMemberRoleOptions} options Options for removing the role
|
||||
* @returns {Promise<GuildMember|User|Snowflake>}
|
||||
*/
|
||||
async removeRole(options) {
|
||||
const { user, role, reason } = options;
|
||||
const userId = this.guild.members.resolveId(user);
|
||||
const roleId = this.guild.roles.resolveId(role);
|
||||
await this.client.rest.delete(Routes.guildMemberRole(this.guild.id, userId, roleId), { reason });
|
||||
|
||||
return this.resolve(user) ?? this.client.users.resolve(user) ?? userId;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildMemberManager;
|
||||
204
node_modules/discord.js/src/managers/GuildMemberRoleManager.js
generated
vendored
Normal file
204
node_modules/discord.js/src/managers/GuildMemberRoleManager.js
generated
vendored
Normal file
@@ -0,0 +1,204 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const DataManager = require('./DataManager');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
const { Role } = require('../structures/Role');
|
||||
|
||||
/**
|
||||
* Manages API methods for roles of a GuildMember and stores their cache.
|
||||
* @extends {DataManager}
|
||||
*/
|
||||
class GuildMemberRoleManager extends DataManager {
|
||||
constructor(member) {
|
||||
super(member.client, Role);
|
||||
|
||||
/**
|
||||
* The GuildMember this manager belongs to
|
||||
* @type {GuildMember}
|
||||
*/
|
||||
this.member = member;
|
||||
|
||||
/**
|
||||
* The Guild this manager belongs to
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = member.guild;
|
||||
}
|
||||
|
||||
/**
|
||||
* The roles of this member
|
||||
* @type {Collection<Snowflake, Role>}
|
||||
* @readonly
|
||||
*/
|
||||
get cache() {
|
||||
const everyone = this.guild.roles.everyone;
|
||||
return this.guild.roles.cache.filter(role => this.member._roles.includes(role.id)).set(everyone.id, everyone);
|
||||
}
|
||||
|
||||
/**
|
||||
* The role of the member used to hoist them in a separate category in the users list
|
||||
* @type {?Role}
|
||||
* @readonly
|
||||
*/
|
||||
get hoist() {
|
||||
const hoistedRoles = this.cache.filter(role => role.hoist);
|
||||
if (!hoistedRoles.size) return null;
|
||||
return hoistedRoles.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev));
|
||||
}
|
||||
|
||||
/**
|
||||
* The role of the member used to set their role icon
|
||||
* @type {?Role}
|
||||
* @readonly
|
||||
*/
|
||||
get icon() {
|
||||
const iconRoles = this.cache.filter(role => role.icon || role.unicodeEmoji);
|
||||
if (!iconRoles.size) return null;
|
||||
return iconRoles.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev));
|
||||
}
|
||||
|
||||
/**
|
||||
* The role of the member used to set their color
|
||||
* @type {?Role}
|
||||
* @readonly
|
||||
*/
|
||||
get color() {
|
||||
const coloredRoles = this.cache.filter(role => role.color);
|
||||
if (!coloredRoles.size) return null;
|
||||
return coloredRoles.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev));
|
||||
}
|
||||
|
||||
/**
|
||||
* The role of the member with the highest position
|
||||
* @type {Role}
|
||||
* @readonly
|
||||
*/
|
||||
get highest() {
|
||||
return this.cache.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev), this.cache.first());
|
||||
}
|
||||
|
||||
/**
|
||||
* The premium subscriber role of the guild, if present on the member
|
||||
* @type {?Role}
|
||||
* @readonly
|
||||
*/
|
||||
get premiumSubscriberRole() {
|
||||
return this.cache.find(role => role.tags?.premiumSubscriberRole) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The managed role this member created when joining the guild, if any
|
||||
* <info>Only ever available on bots</info>
|
||||
* @type {?Role}
|
||||
* @readonly
|
||||
*/
|
||||
get botRole() {
|
||||
if (!this.member.user.bot) return null;
|
||||
return this.cache.find(role => role.tags?.botId === this.member.user.id) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a role (or multiple roles) to the member.
|
||||
* @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to add
|
||||
* @param {string} [reason] Reason for adding the role(s)
|
||||
* @returns {Promise<GuildMember>}
|
||||
*/
|
||||
async add(roleOrRoles, reason) {
|
||||
if (roleOrRoles instanceof Collection || Array.isArray(roleOrRoles)) {
|
||||
const resolvedRoles = [];
|
||||
for (const role of roleOrRoles.values()) {
|
||||
const resolvedRole = this.guild.roles.resolveId(role);
|
||||
if (!resolvedRole) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidElement, 'Array or Collection', 'roles', role);
|
||||
}
|
||||
resolvedRoles.push(resolvedRole);
|
||||
}
|
||||
|
||||
const newRoles = [...new Set(resolvedRoles.concat(...this.cache.keys()))];
|
||||
return this.set(newRoles, reason);
|
||||
} else {
|
||||
roleOrRoles = this.guild.roles.resolveId(roleOrRoles);
|
||||
if (roleOrRoles === null) {
|
||||
throw new DiscordjsTypeError(
|
||||
ErrorCodes.InvalidType,
|
||||
'roles',
|
||||
'Role, Snowflake or Array or Collection of Roles or Snowflakes',
|
||||
);
|
||||
}
|
||||
|
||||
await this.client.rest.put(Routes.guildMemberRole(this.guild.id, this.member.id, roleOrRoles), { reason });
|
||||
|
||||
const clone = this.member._clone();
|
||||
clone._roles = [...this.cache.keys(), roleOrRoles];
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a role (or multiple roles) from the member.
|
||||
* @param {RoleResolvable|RoleResolvable[]|Collection<Snowflake, Role>} roleOrRoles The role or roles to remove
|
||||
* @param {string} [reason] Reason for removing the role(s)
|
||||
* @returns {Promise<GuildMember>}
|
||||
*/
|
||||
async remove(roleOrRoles, reason) {
|
||||
if (roleOrRoles instanceof Collection || Array.isArray(roleOrRoles)) {
|
||||
const resolvedRoles = [];
|
||||
for (const role of roleOrRoles.values()) {
|
||||
const resolvedRole = this.guild.roles.resolveId(role);
|
||||
if (!resolvedRole) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidElement, 'Array or Collection', 'roles', role);
|
||||
}
|
||||
resolvedRoles.push(resolvedRole);
|
||||
}
|
||||
|
||||
const newRoles = this.cache.filter(role => !resolvedRoles.includes(role.id));
|
||||
return this.set(newRoles, reason);
|
||||
} else {
|
||||
roleOrRoles = this.guild.roles.resolveId(roleOrRoles);
|
||||
if (roleOrRoles === null) {
|
||||
throw new DiscordjsTypeError(
|
||||
ErrorCodes.InvalidType,
|
||||
'roles',
|
||||
'Role, Snowflake or Array or Collection of Roles or Snowflakes',
|
||||
);
|
||||
}
|
||||
|
||||
await this.client.rest.delete(Routes.guildMemberRole(this.guild.id, this.member.id, roleOrRoles), { reason });
|
||||
|
||||
const clone = this.member._clone();
|
||||
const newRoles = this.cache.filter(role => role.id !== roleOrRoles);
|
||||
clone._roles = [...newRoles.keys()];
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the roles applied to the member.
|
||||
* @param {Collection<Snowflake, Role>|RoleResolvable[]} roles The roles or role ids to apply
|
||||
* @param {string} [reason] Reason for applying the roles
|
||||
* @returns {Promise<GuildMember>}
|
||||
* @example
|
||||
* // Set the member's roles to a single role
|
||||
* guildMember.roles.set(['391156570408615936'])
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Remove all the roles from a member
|
||||
* guildMember.roles.set([])
|
||||
* .then(member => console.log(`Member roles is now of ${member.roles.cache.size} size`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
set(roles, reason) {
|
||||
return this.member.edit({ roles, reason });
|
||||
}
|
||||
|
||||
clone() {
|
||||
const clone = new this.constructor(this.member);
|
||||
clone.member._roles = [...this.cache.keys()];
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildMemberRoleManager;
|
||||
17
node_modules/discord.js/src/managers/GuildMessageManager.js
generated
vendored
Normal file
17
node_modules/discord.js/src/managers/GuildMessageManager.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
const MessageManager = require('./MessageManager');
|
||||
|
||||
/**
|
||||
* Manages API methods for messages in a guild and holds their cache.
|
||||
* @extends {MessageManager}
|
||||
*/
|
||||
class GuildMessageManager extends MessageManager {
|
||||
/**
|
||||
* The channel that the messages belong to
|
||||
* @name GuildMessageManager#channel
|
||||
* @type {GuildTextBasedChannel}
|
||||
*/
|
||||
}
|
||||
|
||||
module.exports = GuildMessageManager;
|
||||
297
node_modules/discord.js/src/managers/GuildScheduledEventManager.js
generated
vendored
Normal file
297
node_modules/discord.js/src/managers/GuildScheduledEventManager.js
generated
vendored
Normal file
@@ -0,0 +1,297 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { makeURLSearchParams } = require('@discordjs/rest');
|
||||
const { GuildScheduledEventEntityType, Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsTypeError, DiscordjsError, ErrorCodes } = require('../errors');
|
||||
const { GuildScheduledEvent } = require('../structures/GuildScheduledEvent');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildScheduledEvents and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class GuildScheduledEventManager extends CachedManager {
|
||||
constructor(guild, iterable) {
|
||||
super(guild.client, GuildScheduledEvent, iterable);
|
||||
|
||||
/**
|
||||
* The guild this manager belongs to
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of this manager
|
||||
* @type {Collection<Snowflake, GuildScheduledEvent>}
|
||||
* @name GuildScheduledEventManager#cache
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data that resolves to give a GuildScheduledEvent object. This can be:
|
||||
* * A Snowflake
|
||||
* * A GuildScheduledEvent object
|
||||
* @typedef {Snowflake|GuildScheduledEvent} GuildScheduledEventResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to create a guild scheduled event.
|
||||
* @typedef {Object} GuildScheduledEventCreateOptions
|
||||
* @property {string} name The name of the guild scheduled event
|
||||
* @property {DateResolvable} scheduledStartTime The time to schedule the event at
|
||||
* @property {DateResolvable} [scheduledEndTime] The time to end the event at
|
||||
* <warn>This is required if `entityType` is {@link GuildScheduledEventEntityType.External}</warn>
|
||||
* @property {GuildScheduledEventPrivacyLevel} privacyLevel The privacy level of the guild scheduled event
|
||||
* @property {GuildScheduledEventEntityType} entityType The scheduled entity type of the event
|
||||
* @property {string} [description] The description of the guild scheduled event
|
||||
* @property {GuildVoiceChannelResolvable} [channel] The channel of the guild scheduled event
|
||||
* <warn>This is required if `entityType` is {@link GuildScheduledEventEntityType.StageInstance} or
|
||||
* {@link GuildScheduledEventEntityType.Voice}</warn>
|
||||
* @property {GuildScheduledEventEntityMetadataOptions} [entityMetadata] The entity metadata of the
|
||||
* guild scheduled event
|
||||
* <warn>This is required if `entityType` is {@link GuildScheduledEventEntityType.External}</warn>
|
||||
* @property {?(BufferResolvable|Base64Resolvable)} [image] The cover image of the guild scheduled event
|
||||
* @property {string} [reason] The reason for creating the guild scheduled event
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to set entity metadata of a guild scheduled event.
|
||||
* @typedef {Object} GuildScheduledEventEntityMetadataOptions
|
||||
* @property {string} [location] The location of the guild scheduled event
|
||||
* <warn>This is required if `entityType` is {@link GuildScheduledEventEntityType.External}</warn>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new guild scheduled event.
|
||||
* @param {GuildScheduledEventCreateOptions} options Options for creating the guild scheduled event
|
||||
* @returns {Promise<GuildScheduledEvent>}
|
||||
*/
|
||||
async create(options) {
|
||||
if (typeof options !== 'object') throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'options', 'object', true);
|
||||
let {
|
||||
privacyLevel,
|
||||
entityType,
|
||||
channel,
|
||||
name,
|
||||
scheduledStartTime,
|
||||
description,
|
||||
scheduledEndTime,
|
||||
entityMetadata,
|
||||
reason,
|
||||
image,
|
||||
} = options;
|
||||
|
||||
let entity_metadata, channel_id;
|
||||
if (entityType === GuildScheduledEventEntityType.External) {
|
||||
channel_id = channel === undefined ? channel : null;
|
||||
entity_metadata = { location: entityMetadata?.location };
|
||||
} else {
|
||||
channel_id = this.guild.channels.resolveId(channel);
|
||||
if (!channel_id) throw new DiscordjsError(ErrorCodes.GuildVoiceChannelResolve);
|
||||
entity_metadata = entityMetadata === undefined ? entityMetadata : null;
|
||||
}
|
||||
|
||||
const data = await this.client.rest.post(Routes.guildScheduledEvents(this.guild.id), {
|
||||
body: {
|
||||
channel_id,
|
||||
name,
|
||||
privacy_level: privacyLevel,
|
||||
scheduled_start_time: new Date(scheduledStartTime).toISOString(),
|
||||
scheduled_end_time: scheduledEndTime ? new Date(scheduledEndTime).toISOString() : scheduledEndTime,
|
||||
description,
|
||||
entity_type: entityType,
|
||||
entity_metadata,
|
||||
image: image && (await resolveImage(image)),
|
||||
},
|
||||
reason,
|
||||
});
|
||||
|
||||
return this._add(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to fetch a single guild scheduled event from a guild.
|
||||
* @typedef {BaseFetchOptions} FetchGuildScheduledEventOptions
|
||||
* @property {GuildScheduledEventResolvable} guildScheduledEvent The guild scheduled event to fetch
|
||||
* @property {boolean} [withUserCount=true] Whether to fetch the number of users subscribed to the scheduled event
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch multiple guild scheduled events from a guild.
|
||||
* @typedef {Object} FetchGuildScheduledEventsOptions
|
||||
* @property {boolean} [cache] Whether or not to cache the fetched guild scheduled events
|
||||
* @property {boolean} [withUserCount=true] Whether to fetch the number of users subscribed to each scheduled event
|
||||
* should be returned
|
||||
*/
|
||||
|
||||
/**
|
||||
* Obtains one or more guild scheduled events from Discord, or the guild cache if it's already available.
|
||||
* @param {GuildScheduledEventResolvable|FetchGuildScheduledEventOptions|FetchGuildScheduledEventsOptions} [options]
|
||||
* The id of the guild scheduled event or options
|
||||
* @returns {Promise<GuildScheduledEvent|Collection<Snowflake, GuildScheduledEvent>>}
|
||||
*/
|
||||
async fetch(options = {}) {
|
||||
const id = this.resolveId(options.guildScheduledEvent ?? options);
|
||||
|
||||
if (id) {
|
||||
if (!options.force) {
|
||||
const existing = this.cache.get(id);
|
||||
if (existing) return existing;
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(Routes.guildScheduledEvent(this.guild.id, id), {
|
||||
query: makeURLSearchParams({ with_user_count: options.withUserCount ?? true }),
|
||||
});
|
||||
return this._add(data, options.cache);
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(Routes.guildScheduledEvents(this.guild.id), {
|
||||
query: makeURLSearchParams({ with_user_count: options.withUserCount ?? true }),
|
||||
});
|
||||
|
||||
return data.reduce(
|
||||
(coll, rawGuildScheduledEventData) =>
|
||||
coll.set(
|
||||
rawGuildScheduledEventData.id,
|
||||
this.guild.scheduledEvents._add(rawGuildScheduledEventData, options.cache),
|
||||
),
|
||||
new Collection(),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to edit a guild scheduled event.
|
||||
* @typedef {Object} GuildScheduledEventEditOptions
|
||||
* @property {string} [name] The name of the guild scheduled event
|
||||
* @property {DateResolvable} [scheduledStartTime] The time to schedule the event at
|
||||
* @property {DateResolvable} [scheduledEndTime] The time to end the event at
|
||||
* @property {GuildScheduledEventPrivacyLevel} [privacyLevel] The privacy level of the guild scheduled event
|
||||
* @property {GuildScheduledEventEntityType} [entityType] The scheduled entity type of the event
|
||||
* @property {string} [description] The description of the guild scheduled event
|
||||
* @property {?GuildVoiceChannelResolvable} [channel] The channel of the guild scheduled event
|
||||
* @property {GuildScheduledEventStatus} [status] The status of the guild scheduled event
|
||||
* @property {GuildScheduledEventEntityMetadataOptions} [entityMetadata] The entity metadata of the
|
||||
* guild scheduled event
|
||||
* <warn>This can be modified only if `entityType` of the `GuildScheduledEvent` to be edited is
|
||||
* {@link GuildScheduledEventEntityType.External}</warn>
|
||||
* @property {?(BufferResolvable|Base64Resolvable)} [image] The cover image of the guild scheduled event
|
||||
* @property {string} [reason] The reason for editing the guild scheduled event
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits a guild scheduled event.
|
||||
* @param {GuildScheduledEventResolvable} guildScheduledEvent The guild scheduled event to edit
|
||||
* @param {GuildScheduledEventEditOptions} options Options to edit the guild scheduled event
|
||||
* @returns {Promise<GuildScheduledEvent>}
|
||||
*/
|
||||
async edit(guildScheduledEvent, options) {
|
||||
const guildScheduledEventId = this.resolveId(guildScheduledEvent);
|
||||
if (!guildScheduledEventId) throw new DiscordjsError(ErrorCodes.GuildScheduledEventResolve);
|
||||
|
||||
if (typeof options !== 'object') throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'options', 'object', true);
|
||||
let {
|
||||
privacyLevel,
|
||||
entityType,
|
||||
channel,
|
||||
status,
|
||||
name,
|
||||
scheduledStartTime,
|
||||
description,
|
||||
scheduledEndTime,
|
||||
entityMetadata,
|
||||
reason,
|
||||
image,
|
||||
} = options;
|
||||
|
||||
let entity_metadata;
|
||||
if (entityMetadata) {
|
||||
entity_metadata = {
|
||||
location: entityMetadata.location,
|
||||
};
|
||||
}
|
||||
|
||||
const data = await this.client.rest.patch(Routes.guildScheduledEvent(this.guild.id, guildScheduledEventId), {
|
||||
body: {
|
||||
channel_id: channel === undefined ? channel : this.guild.channels.resolveId(channel),
|
||||
name,
|
||||
privacy_level: privacyLevel,
|
||||
scheduled_start_time: scheduledStartTime ? new Date(scheduledStartTime).toISOString() : undefined,
|
||||
scheduled_end_time: scheduledEndTime ? new Date(scheduledEndTime).toISOString() : scheduledEndTime,
|
||||
description,
|
||||
entity_type: entityType,
|
||||
status,
|
||||
image: image && (await resolveImage(image)),
|
||||
entity_metadata,
|
||||
},
|
||||
reason,
|
||||
});
|
||||
|
||||
return this._add(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a guild scheduled event.
|
||||
* @param {GuildScheduledEventResolvable} guildScheduledEvent The guild scheduled event to delete
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async delete(guildScheduledEvent) {
|
||||
const guildScheduledEventId = this.resolveId(guildScheduledEvent);
|
||||
if (!guildScheduledEventId) throw new DiscordjsError(ErrorCodes.GuildScheduledEventResolve);
|
||||
|
||||
await this.client.rest.delete(Routes.guildScheduledEvent(this.guild.id, guildScheduledEventId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to fetch subscribers of a guild scheduled event
|
||||
* @typedef {Object} FetchGuildScheduledEventSubscribersOptions
|
||||
* @property {number} [limit] The maximum numbers of users to fetch
|
||||
* @property {boolean} [withMember] Whether to fetch guild member data of the users
|
||||
* @property {Snowflake} [before] Consider only users before this user id
|
||||
* @property {Snowflake} [after] Consider only users after this user id
|
||||
* <warn>If both `before` and `after` are provided, only `before` is respected</warn>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a subscriber of a {@link GuildScheduledEvent}
|
||||
* @typedef {Object} GuildScheduledEventUser
|
||||
* @property {Snowflake} guildScheduledEventId The id of the guild scheduled event which the user subscribed to
|
||||
* @property {User} user The user that subscribed to the guild scheduled event
|
||||
* @property {?GuildMember} member The guild member associated with the user, if any
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetches subscribers of a guild scheduled event.
|
||||
* @param {GuildScheduledEventResolvable} guildScheduledEvent The guild scheduled event to fetch subscribers of
|
||||
* @param {FetchGuildScheduledEventSubscribersOptions} [options={}] Options for fetching the subscribers
|
||||
* @returns {Promise<Collection<Snowflake, GuildScheduledEventUser>>}
|
||||
*/
|
||||
async fetchSubscribers(guildScheduledEvent, options = {}) {
|
||||
const guildScheduledEventId = this.resolveId(guildScheduledEvent);
|
||||
if (!guildScheduledEventId) throw new DiscordjsError(ErrorCodes.GuildScheduledEventResolve);
|
||||
|
||||
const query = makeURLSearchParams({
|
||||
limit: options.limit,
|
||||
with_member: options.withMember,
|
||||
before: options.before,
|
||||
after: options.after,
|
||||
});
|
||||
|
||||
const data = await this.client.rest.get(Routes.guildScheduledEventUsers(this.guild.id, guildScheduledEventId), {
|
||||
query,
|
||||
});
|
||||
|
||||
return data.reduce(
|
||||
(coll, rawData) =>
|
||||
coll.set(rawData.user.id, {
|
||||
guildScheduledEventId: rawData.guild_scheduled_event_id,
|
||||
user: this.client.users._add(rawData.user),
|
||||
member: rawData.member ? this.guild.members._add({ ...rawData.member, user: rawData.user }) : null,
|
||||
}),
|
||||
new Collection(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildScheduledEventManager;
|
||||
182
node_modules/discord.js/src/managers/GuildStickerManager.js
generated
vendored
Normal file
182
node_modules/discord.js/src/managers/GuildStickerManager.js
generated
vendored
Normal file
@@ -0,0 +1,182 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
const MessagePayload = require('../structures/MessagePayload');
|
||||
const { Sticker } = require('../structures/Sticker');
|
||||
|
||||
/**
|
||||
* Manages API methods for Guild Stickers and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class GuildStickerManager extends CachedManager {
|
||||
constructor(guild, iterable) {
|
||||
super(guild.client, Sticker, iterable);
|
||||
|
||||
/**
|
||||
* The guild this manager belongs to
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of Guild Stickers
|
||||
* @type {Collection<Snowflake, Sticker>}
|
||||
* @name GuildStickerManager#cache
|
||||
*/
|
||||
|
||||
_add(data, cache) {
|
||||
return super._add(data, cache, { extras: [this.guild] });
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to create a guild sticker.
|
||||
* @typedef {Object} GuildStickerCreateOptions
|
||||
* @property {AttachmentPayload|BufferResolvable|Stream} file The file for the sticker
|
||||
* @property {string} name The name for the sticker
|
||||
* @property {string} tags The Discord name of a unicode emoji representing the sticker's expression
|
||||
* @property {?string} [description] The description for the sticker
|
||||
* @property {string} [reason] Reason for creating the sticker
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new custom sticker in the guild.
|
||||
* @param {GuildStickerCreateOptions} options Options for creating a guild sticker
|
||||
* @returns {Promise<Sticker>} The created sticker
|
||||
* @example
|
||||
* // Create a new sticker from a URL
|
||||
* guild.stickers.create({ file: 'https://i.imgur.com/w3duR07.png', name: 'rip', tags: 'headstone' })
|
||||
* .then(sticker => console.log(`Created new sticker with name ${sticker.name}!`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Create a new sticker from a file on your computer
|
||||
* guild.stickers.create({ file: './memes/banana.png', name: 'banana', tags: 'banana' })
|
||||
* .then(sticker => console.log(`Created new sticker with name ${sticker.name}!`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async create({ file, name, tags, description, reason } = {}) {
|
||||
const resolvedFile = await MessagePayload.resolveFile(file);
|
||||
if (!resolvedFile) throw new DiscordjsTypeError(ErrorCodes.ReqResourceType);
|
||||
file = { ...resolvedFile, key: 'file' };
|
||||
|
||||
const body = { name, tags, description: description ?? '' };
|
||||
|
||||
const sticker = await this.client.rest.post(Routes.guildStickers(this.guild.id), {
|
||||
appendToFormData: true,
|
||||
body,
|
||||
files: [file],
|
||||
reason,
|
||||
});
|
||||
return this.client.actions.GuildStickerCreate.handle(this.guild, sticker).sticker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that resolves to give a Sticker object. This can be:
|
||||
* * A Sticker object
|
||||
* * A Snowflake
|
||||
* @typedef {Sticker|Snowflake} StickerResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a StickerResolvable to a Sticker object.
|
||||
* @method resolve
|
||||
* @memberof GuildStickerManager
|
||||
* @instance
|
||||
* @param {StickerResolvable} sticker The Sticker resolvable to identify
|
||||
* @returns {?Sticker}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a StickerResolvable to a Sticker id string.
|
||||
* @method resolveId
|
||||
* @memberof GuildStickerManager
|
||||
* @instance
|
||||
* @param {StickerResolvable} sticker The Sticker resolvable to identify
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits a sticker.
|
||||
* @param {StickerResolvable} sticker The sticker to edit
|
||||
* @param {GuildStickerEditOptions} [options={}] The new data for the sticker
|
||||
* @returns {Promise<Sticker>}
|
||||
*/
|
||||
async edit(sticker, options = {}) {
|
||||
const stickerId = this.resolveId(sticker);
|
||||
if (!stickerId) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'sticker', 'StickerResolvable');
|
||||
|
||||
const d = await this.client.rest.patch(Routes.guildSticker(this.guild.id, stickerId), {
|
||||
body: options,
|
||||
reason: options.reason,
|
||||
});
|
||||
|
||||
const existing = this.cache.get(stickerId);
|
||||
if (existing) {
|
||||
const clone = existing._clone();
|
||||
clone._patch(d);
|
||||
return clone;
|
||||
}
|
||||
return this._add(d);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a sticker.
|
||||
* @param {StickerResolvable} sticker The sticker to delete
|
||||
* @param {string} [reason] Reason for deleting this sticker
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async delete(sticker, reason) {
|
||||
sticker = this.resolveId(sticker);
|
||||
if (!sticker) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'sticker', 'StickerResolvable');
|
||||
|
||||
await this.client.rest.delete(Routes.guildSticker(this.guild.id, sticker), { reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains one or more stickers from Discord, or the sticker cache if they're already available.
|
||||
* @param {Snowflake} [id] The Sticker's id
|
||||
* @param {BaseFetchOptions} [options] Additional options for this fetch
|
||||
* @returns {Promise<Sticker|Collection<Snowflake, Sticker>>}
|
||||
* @example
|
||||
* // Fetch all stickers from the guild
|
||||
* message.guild.stickers.fetch()
|
||||
* .then(stickers => console.log(`There are ${stickers.size} stickers.`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch a single sticker
|
||||
* message.guild.stickers.fetch('222078108977594368')
|
||||
* .then(sticker => console.log(`The sticker name is: ${sticker.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetch(id, { cache = true, force = false } = {}) {
|
||||
if (id) {
|
||||
if (!force) {
|
||||
const existing = this.cache.get(id);
|
||||
if (existing) return existing;
|
||||
}
|
||||
const sticker = await this.client.rest.get(Routes.guildSticker(this.guild.id, id));
|
||||
return this._add(sticker, cache);
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(Routes.guildStickers(this.guild.id));
|
||||
return new Collection(data.map(sticker => [sticker.id, this._add(sticker, cache)]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the user who uploaded this sticker, if this is a guild sticker.
|
||||
* @param {StickerResolvable} sticker The sticker to fetch the user for
|
||||
* @returns {Promise<?User>}
|
||||
*/
|
||||
async fetchUser(sticker) {
|
||||
sticker = this.resolve(sticker);
|
||||
if (!sticker) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'sticker', 'StickerResolvable');
|
||||
const data = await this.client.rest.get(Routes.guildSticker(this.guild.id, sticker.id));
|
||||
sticker._patch(data);
|
||||
return sticker.user;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildStickerManager;
|
||||
91
node_modules/discord.js/src/managers/GuildTextThreadManager.js
generated
vendored
Normal file
91
node_modules/discord.js/src/managers/GuildTextThreadManager.js
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
'use strict';
|
||||
|
||||
const { ChannelType, Routes } = require('discord-api-types/v10');
|
||||
const ThreadManager = require('./ThreadManager');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
|
||||
/**
|
||||
* Manages API methods for {@link ThreadChannel} objects and stores their cache.
|
||||
* @extends {ThreadManager}
|
||||
*/
|
||||
class GuildTextThreadManager extends ThreadManager {
|
||||
/**
|
||||
* The channel this Manager belongs to
|
||||
* @name GuildTextThreadManager#channel
|
||||
* @type {TextChannel|NewsChannel}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options for creating a thread. <warn>Only one of `startMessage` or `type` can be defined.</warn>
|
||||
* @typedef {StartThreadOptions} GuildTextThreadCreateOptions
|
||||
* @property {MessageResolvable} [startMessage] The message to start a thread from.
|
||||
* <warn>If this is defined, then the `type` of thread gets inferred automatically and cannot be changed.</warn>
|
||||
* @property {ThreadChannelTypes} [type] The type of thread to create.
|
||||
* Defaults to {@link ChannelType.PublicThread} if created in a {@link TextChannel}
|
||||
* <warn>When creating threads in a {@link NewsChannel}, this is ignored and is always
|
||||
* {@link ChannelType.AnnouncementThread}</warn>
|
||||
* @property {boolean} [invitable] Whether non-moderators can add other non-moderators to the thread
|
||||
* <info>Can only be set when type will be {@link ChannelType.PrivateThread}</info>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new thread in the channel.
|
||||
* @param {GuildTextThreadCreateOptions} [options] Options to create a new thread
|
||||
* @returns {Promise<ThreadChannel>}
|
||||
* @example
|
||||
* // Create a new public thread
|
||||
* channel.threads
|
||||
* .create({
|
||||
* name: 'food-talk',
|
||||
* autoArchiveDuration: ThreadAutoArchiveDuration.OneHour,
|
||||
* reason: 'Needed a separate thread for food',
|
||||
* })
|
||||
* .then(threadChannel => console.log(threadChannel))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Create a new private thread
|
||||
* channel.threads
|
||||
* .create({
|
||||
* name: 'mod-talk',
|
||||
* autoArchiveDuration: ThreadAutoArchiveDuration.OneHour,
|
||||
* type: ChannelType.PrivateThread,
|
||||
* reason: 'Needed a separate thread for moderation',
|
||||
* })
|
||||
* .then(threadChannel => console.log(threadChannel))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async create({
|
||||
name,
|
||||
autoArchiveDuration = this.channel.defaultAutoArchiveDuration,
|
||||
startMessage,
|
||||
type,
|
||||
invitable,
|
||||
reason,
|
||||
rateLimitPerUser,
|
||||
} = {}) {
|
||||
let resolvedType =
|
||||
this.channel.type === ChannelType.GuildAnnouncement ? ChannelType.AnnouncementThread : ChannelType.PublicThread;
|
||||
let startMessageId;
|
||||
if (startMessage) {
|
||||
startMessageId = this.channel.messages.resolveId(startMessage);
|
||||
if (!startMessageId) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'startMessage', 'MessageResolvable');
|
||||
} else if (this.channel.type !== ChannelType.GuildAnnouncement) {
|
||||
resolvedType = type ?? resolvedType;
|
||||
}
|
||||
|
||||
const data = await this.client.rest.post(Routes.threads(this.channel.id, startMessageId), {
|
||||
body: {
|
||||
name,
|
||||
auto_archive_duration: autoArchiveDuration,
|
||||
type: resolvedType,
|
||||
invitable: resolvedType === ChannelType.PrivateThread ? invitable : undefined,
|
||||
rate_limit_per_user: rateLimitPerUser,
|
||||
},
|
||||
reason,
|
||||
});
|
||||
|
||||
return this.client.actions.ThreadCreate.handle(data).thread;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildTextThreadManager;
|
||||
301
node_modules/discord.js/src/managers/MessageManager.js
generated
vendored
Normal file
301
node_modules/discord.js/src/managers/MessageManager.js
generated
vendored
Normal file
@@ -0,0 +1,301 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { makeURLSearchParams } = require('@discordjs/rest');
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
const { Message } = require('../structures/Message');
|
||||
const MessagePayload = require('../structures/MessagePayload');
|
||||
const { MakeCacheOverrideSymbol } = require('../util/Symbols');
|
||||
const { resolvePartialEmoji } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Manages API methods for Messages and holds their cache.
|
||||
* @extends {CachedManager}
|
||||
* @abstract
|
||||
*/
|
||||
class MessageManager extends CachedManager {
|
||||
static [MakeCacheOverrideSymbol] = MessageManager;
|
||||
|
||||
constructor(channel, iterable) {
|
||||
super(channel.client, Message, iterable);
|
||||
|
||||
/**
|
||||
* The channel that the messages belong to
|
||||
* @type {TextBasedChannels}
|
||||
*/
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of Messages
|
||||
* @type {Collection<Snowflake, Message>}
|
||||
* @name MessageManager#cache
|
||||
*/
|
||||
|
||||
_add(data, cache) {
|
||||
return super._add(data, cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to a Message object. This can be:
|
||||
* * A Message
|
||||
* * A Snowflake
|
||||
* @typedef {Message|Snowflake} MessageResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch a message.
|
||||
* @typedef {BaseFetchOptions} FetchMessageOptions
|
||||
* @property {MessageResolvable} message The message to fetch
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch multiple messages.
|
||||
* <info>The `before`, `after`, and `around` parameters are mutually exclusive.</info>
|
||||
* @typedef {Object} FetchMessagesOptions
|
||||
* @property {number} [limit] The maximum number of messages to return
|
||||
* @property {Snowflake} [before] Consider only messages before this id
|
||||
* @property {Snowflake} [after] Consider only messages after this id
|
||||
* @property {Snowflake} [around] Consider only messages around this id
|
||||
* @property {boolean} [cache] Whether to cache the fetched messages
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetches message(s) from a channel.
|
||||
* <info>The returned Collection does not contain reaction users of the messages if they were not cached.
|
||||
* Those need to be fetched separately in such a case.</info>
|
||||
* @param {MessageResolvable|FetchMessageOptions|FetchMessagesOptions} [options] Options for fetching message(s)
|
||||
* @returns {Promise<Message|Collection<Snowflake, Message>>}
|
||||
* @example
|
||||
* // Fetch a message
|
||||
* channel.messages.fetch('99539446449315840')
|
||||
* .then(message => console.log(message.content))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch a maximum of 10 messages without caching
|
||||
* channel.messages.fetch({ limit: 10, cache: false })
|
||||
* .then(messages => console.log(`Received ${messages.size} messages`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch a maximum of 10 messages without caching around a message id
|
||||
* channel.messages.fetch({ limit: 10, cache: false, around: '99539446449315840' })
|
||||
* .then(messages => console.log(`Received ${messages.size} messages`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch messages and filter by a user id
|
||||
* channel.messages.fetch()
|
||||
* .then(messages => console.log(`${messages.filter(message =>
|
||||
* message.author.id === '84484653687267328').size} messages`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetch(options) {
|
||||
if (!options) return this._fetchMany();
|
||||
const { message, cache, force } = options;
|
||||
const resolvedMessage = this.resolveId(message ?? options);
|
||||
if (resolvedMessage) return this._fetchSingle({ message: resolvedMessage, cache, force });
|
||||
return this._fetchMany(options);
|
||||
}
|
||||
|
||||
async _fetchSingle({ message, cache, force = false }) {
|
||||
if (!force) {
|
||||
const existing = this.cache.get(message);
|
||||
if (existing && !existing.partial) return existing;
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(Routes.channelMessage(this.channel.id, message));
|
||||
return this._add(data, cache);
|
||||
}
|
||||
|
||||
async _fetchMany(options = {}) {
|
||||
const data = await this.client.rest.get(Routes.channelMessages(this.channel.id), {
|
||||
query: makeURLSearchParams(options),
|
||||
});
|
||||
|
||||
return data.reduce((_data, message) => _data.set(message.id, this._add(message, options.cache)), new Collection());
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the pinned messages of this channel and returns a collection of them.
|
||||
* <info>The returned Collection does not contain any reaction data of the messages.
|
||||
* Those need to be fetched separately.</info>
|
||||
* @param {boolean} [cache=true] Whether to cache the message(s)
|
||||
* @returns {Promise<Collection<Snowflake, Message>>}
|
||||
* @example
|
||||
* // Get pinned messages
|
||||
* channel.messages.fetchPinned()
|
||||
* .then(messages => console.log(`Received ${messages.size} messages`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetchPinned(cache = true) {
|
||||
const data = await this.client.rest.get(Routes.channelPins(this.channel.id));
|
||||
const messages = new Collection();
|
||||
for (const message of data) messages.set(message.id, this._add(message, cache));
|
||||
return messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a {@link MessageResolvable} to a {@link Message} object.
|
||||
* @method resolve
|
||||
* @memberof MessageManager
|
||||
* @instance
|
||||
* @param {MessageResolvable} message The message resolvable to resolve
|
||||
* @returns {?Message}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a {@link MessageResolvable} to a {@link Message} id.
|
||||
* @method resolveId
|
||||
* @memberof MessageManager
|
||||
* @instance
|
||||
* @param {MessageResolvable} message The message resolvable to resolve
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data used to reference an attachment.
|
||||
* @typedef {Object} MessageEditAttachmentData
|
||||
* @property {Snowflake} id The id of the attachment
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options that can be passed to edit a message.
|
||||
* @typedef {BaseMessageOptions} MessageEditOptions
|
||||
* @property {Array<Attachment|MessageEditAttachmentData>} [attachments] An array of attachments to keep.
|
||||
* All attachments will be kept if omitted
|
||||
* @property {MessageFlags} [flags] Which flags to set for the message
|
||||
* <info>Only the {@link MessageFlags.SuppressEmbeds} flag can be modified.</info>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits a message, even if it's not cached.
|
||||
* @param {MessageResolvable} message The message to edit
|
||||
* @param {string|MessageEditOptions|MessagePayload} options The options to edit the message
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
async edit(message, options) {
|
||||
const messageId = this.resolveId(message);
|
||||
if (!messageId) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'message', 'MessageResolvable');
|
||||
|
||||
const { body, files } = await (
|
||||
options instanceof MessagePayload
|
||||
? options
|
||||
: MessagePayload.create(message instanceof Message ? message : this, options)
|
||||
)
|
||||
.resolveBody()
|
||||
.resolveFiles();
|
||||
const d = await this.client.rest.patch(Routes.channelMessage(this.channel.id, messageId), { body, files });
|
||||
|
||||
const existing = this.cache.get(messageId);
|
||||
if (existing) {
|
||||
const clone = existing._clone();
|
||||
clone._patch(d);
|
||||
return clone;
|
||||
}
|
||||
return this._add(d);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publishes a message in an announcement channel to all channels following it, even if it's not cached.
|
||||
* @param {MessageResolvable} message The message to publish
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
async crosspost(message) {
|
||||
message = this.resolveId(message);
|
||||
if (!message) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'message', 'MessageResolvable');
|
||||
|
||||
const data = await this.client.rest.post(Routes.channelMessageCrosspost(this.channel.id, message));
|
||||
return this.cache.get(data.id) ?? this._add(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pins a message to the channel's pinned messages, even if it's not cached.
|
||||
* @param {MessageResolvable} message The message to pin
|
||||
* @param {string} [reason] Reason for pinning
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async pin(message, reason) {
|
||||
message = this.resolveId(message);
|
||||
if (!message) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'message', 'MessageResolvable');
|
||||
|
||||
await this.client.rest.put(Routes.channelPin(this.channel.id, message), { reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpins a message from the channel's pinned messages, even if it's not cached.
|
||||
* @param {MessageResolvable} message The message to unpin
|
||||
* @param {string} [reason] Reason for unpinning
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async unpin(message, reason) {
|
||||
message = this.resolveId(message);
|
||||
if (!message) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'message', 'MessageResolvable');
|
||||
|
||||
await this.client.rest.delete(Routes.channelPin(this.channel.id, message), { reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a reaction to a message, even if it's not cached.
|
||||
* @param {MessageResolvable} message The message to react to
|
||||
* @param {EmojiIdentifierResolvable} emoji The emoji to react with
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async react(message, emoji) {
|
||||
message = this.resolveId(message);
|
||||
if (!message) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'message', 'MessageResolvable');
|
||||
|
||||
emoji = resolvePartialEmoji(emoji);
|
||||
if (!emoji) throw new DiscordjsTypeError(ErrorCodes.EmojiType, 'emoji', 'EmojiIdentifierResolvable');
|
||||
|
||||
const emojiId = emoji.id
|
||||
? `${emoji.animated ? 'a:' : ''}${emoji.name}:${emoji.id}`
|
||||
: encodeURIComponent(emoji.name);
|
||||
|
||||
await this.client.rest.put(Routes.channelMessageOwnReaction(this.channel.id, message, emojiId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a message, even if it's not cached.
|
||||
* @param {MessageResolvable} message The message to delete
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async delete(message) {
|
||||
message = this.resolveId(message);
|
||||
if (!message) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'message', 'MessageResolvable');
|
||||
|
||||
await this.client.rest.delete(Routes.channelMessage(this.channel.id, message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends a poll.
|
||||
* @param {Snowflake} messageId The id of the message
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
async endPoll(messageId) {
|
||||
const message = await this.client.rest.post(Routes.expirePoll(this.channel.id, messageId));
|
||||
return this._add(message, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used for fetching voters of an answer in a poll.
|
||||
* @typedef {BaseFetchPollAnswerVotersOptions} FetchPollAnswerVotersOptions
|
||||
* @param {Snowflake} messageId The id of the message
|
||||
* @param {number} answerId The id of the answer
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetches the users that voted for a poll answer.
|
||||
* @param {FetchPollAnswerVotersOptions} options The options for fetching the poll answer voters
|
||||
* @returns {Promise<Collection<Snowflake, User>>}
|
||||
*/
|
||||
async fetchPollAnswerVoters({ messageId, answerId, after, limit }) {
|
||||
const voters = await this.client.rest.get(Routes.pollAnswerVoters(this.channel.id, messageId, answerId), {
|
||||
query: makeURLSearchParams({ limit, after }),
|
||||
});
|
||||
|
||||
return voters.users.reduce((acc, user) => acc.set(user.id, this.client.users._add(user, false)), new Collection());
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MessageManager;
|
||||
17
node_modules/discord.js/src/managers/PartialGroupDMMessageManager.js
generated
vendored
Normal file
17
node_modules/discord.js/src/managers/PartialGroupDMMessageManager.js
generated
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
'use strict';
|
||||
|
||||
const MessageManager = require('./MessageManager');
|
||||
|
||||
/**
|
||||
* Manages API methods for messages in group direct message channels and holds their cache.
|
||||
* @extends {MessageManager}
|
||||
*/
|
||||
class PartialGroupDMMessageManager extends MessageManager {
|
||||
/**
|
||||
* The channel that the messages belong to
|
||||
* @name PartialGroupDMMessageManager#channel
|
||||
* @type {PartialGroupDMChannel}
|
||||
*/
|
||||
}
|
||||
|
||||
module.exports = PartialGroupDMMessageManager;
|
||||
168
node_modules/discord.js/src/managers/PermissionOverwriteManager.js
generated
vendored
Normal file
168
node_modules/discord.js/src/managers/PermissionOverwriteManager.js
generated
vendored
Normal file
@@ -0,0 +1,168 @@
|
||||
'use strict';
|
||||
|
||||
const process = require('node:process');
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { OverwriteType, Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
const PermissionOverwrites = require('../structures/PermissionOverwrites');
|
||||
const { Role } = require('../structures/Role');
|
||||
|
||||
let cacheWarningEmitted = false;
|
||||
|
||||
/**
|
||||
* Manages API methods for guild channel permission overwrites and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class PermissionOverwriteManager extends CachedManager {
|
||||
constructor(channel, iterable) {
|
||||
super(channel.client, PermissionOverwrites);
|
||||
if (!cacheWarningEmitted && this._cache.constructor.name !== 'Collection') {
|
||||
cacheWarningEmitted = true;
|
||||
process.emitWarning(
|
||||
`Overriding the cache handling for ${this.constructor.name} is unsupported and breaks functionality.`,
|
||||
'UnsupportedCacheOverwriteWarning',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The channel of the permission overwrite this manager belongs to
|
||||
* @type {GuildChannel}
|
||||
*/
|
||||
this.channel = channel;
|
||||
|
||||
if (iterable) {
|
||||
for (const item of iterable) {
|
||||
this._add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of this Manager
|
||||
* @type {Collection<Snowflake, PermissionOverwrites>}
|
||||
* @name PermissionOverwriteManager#cache
|
||||
*/
|
||||
|
||||
_add(data, cache) {
|
||||
return super._add(data, cache, { extras: [this.channel] });
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the permission overwrites in this channel.
|
||||
* @param {OverwriteResolvable[]|Collection<Snowflake, OverwriteResolvable>} overwrites
|
||||
* Permission overwrites the channel gets updated with
|
||||
* @param {string} [reason] Reason for updating the channel overwrites
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* message.channel.permissionOverwrites.set([
|
||||
* {
|
||||
* id: message.author.id,
|
||||
* deny: [PermissionFlagsBits.ViewChannel],
|
||||
* },
|
||||
* ], 'Needed to change permissions');
|
||||
*/
|
||||
set(overwrites, reason) {
|
||||
if (!Array.isArray(overwrites) && !(overwrites instanceof Collection)) {
|
||||
return Promise.reject(
|
||||
new DiscordjsTypeError(
|
||||
ErrorCodes.InvalidType,
|
||||
'overwrites',
|
||||
'Array or Collection of Permission Overwrites',
|
||||
true,
|
||||
),
|
||||
);
|
||||
}
|
||||
return this.channel.edit({ permissionOverwrites: overwrites, reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra information about the overwrite.
|
||||
* @typedef {Object} GuildChannelOverwriteOptions
|
||||
* @property {string} [reason] The reason for creating/editing this overwrite
|
||||
* @property {OverwriteType} [type] The type of overwrite. Use this to bypass automatic resolution of `type`
|
||||
* that results in an error for an uncached structure
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates or edits permission overwrites for a user or role in this channel.
|
||||
* @param {RoleResolvable|UserResolvable} userOrRole The user or role to update
|
||||
* @param {PermissionOverwriteOptions} options The options for the update
|
||||
* @param {GuildChannelOverwriteOptions} [overwriteOptions] The extra information for the update
|
||||
* @param {PermissionOverwrites} [existing] The existing overwrites to merge with this update
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @private
|
||||
*/
|
||||
async upsert(userOrRole, options, overwriteOptions = {}, existing) {
|
||||
let userOrRoleId = this.channel.guild.roles.resolveId(userOrRole) ?? this.client.users.resolveId(userOrRole);
|
||||
let { type, reason } = overwriteOptions;
|
||||
if (typeof type !== 'number') {
|
||||
userOrRole = this.channel.guild.roles.resolve(userOrRole) ?? this.client.users.resolve(userOrRole);
|
||||
if (!userOrRole) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'parameter', 'User nor a Role');
|
||||
type = userOrRole instanceof Role ? OverwriteType.Role : OverwriteType.Member;
|
||||
}
|
||||
|
||||
const { allow, deny } = PermissionOverwrites.resolveOverwriteOptions(options, existing);
|
||||
|
||||
await this.client.rest.put(Routes.channelPermission(this.channel.id, userOrRoleId), {
|
||||
body: { id: userOrRoleId, type, allow, deny },
|
||||
reason,
|
||||
});
|
||||
return this.channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates permission overwrites for a user or role in this channel, or replaces them if already present.
|
||||
* @param {RoleResolvable|UserResolvable} userOrRole The user or role to update
|
||||
* @param {PermissionOverwriteOptions} options The options for the update
|
||||
* @param {GuildChannelOverwriteOptions} [overwriteOptions] The extra information for the update
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Create or Replace permission overwrites for a message author
|
||||
* message.channel.permissionOverwrites.create(message.author, {
|
||||
* SendMessages: false
|
||||
* })
|
||||
* .then(channel => console.log(channel.permissionOverwrites.cache.get(message.author.id)))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
create(userOrRole, options, overwriteOptions) {
|
||||
return this.upsert(userOrRole, options, overwriteOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edits permission overwrites for a user or role in this channel, or creates an entry if not already present.
|
||||
* @param {RoleResolvable|UserResolvable} userOrRole The user or role to update
|
||||
* @param {PermissionOverwriteOptions} options The options for the update
|
||||
* @param {GuildChannelOverwriteOptions} [overwriteOptions] The extra information for the update
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Edit or Create permission overwrites for a message author
|
||||
* message.channel.permissionOverwrites.edit(message.author, {
|
||||
* SendMessages: false
|
||||
* })
|
||||
* .then(channel => console.log(channel.permissionOverwrites.cache.get(message.author.id)))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
edit(userOrRole, options, overwriteOptions) {
|
||||
const existing = this.cache.get(
|
||||
this.channel.guild.roles.resolveId(userOrRole) ?? this.client.users.resolveId(userOrRole),
|
||||
);
|
||||
return this.upsert(userOrRole, options, overwriteOptions, existing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes permission overwrites for a user or role in this channel.
|
||||
* @param {UserResolvable|RoleResolvable} userOrRole The user or role to delete
|
||||
* @param {string} [reason] The reason for deleting the overwrite
|
||||
* @returns {Promise<GuildChannel>}
|
||||
*/
|
||||
async delete(userOrRole, reason) {
|
||||
const userOrRoleId = this.channel.guild.roles.resolveId(userOrRole) ?? this.client.users.resolveId(userOrRole);
|
||||
if (!userOrRoleId) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'parameter', 'User nor a Role');
|
||||
|
||||
await this.client.rest.delete(Routes.channelPermission(this.channel.id, userOrRoleId), { reason });
|
||||
return this.channel;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PermissionOverwriteManager;
|
||||
58
node_modules/discord.js/src/managers/PresenceManager.js
generated
vendored
Normal file
58
node_modules/discord.js/src/managers/PresenceManager.js
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
'use strict';
|
||||
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { Presence } = require('../structures/Presence');
|
||||
|
||||
/**
|
||||
* Manages API methods for Presences and holds their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class PresenceManager extends CachedManager {
|
||||
constructor(client, iterable) {
|
||||
super(client, Presence, iterable);
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of Presences
|
||||
* @type {Collection<Snowflake, Presence>}
|
||||
* @name PresenceManager#cache
|
||||
*/
|
||||
|
||||
_add(data, cache) {
|
||||
return super._add(data, cache, { id: data.user.id });
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to a Presence object. This can be:
|
||||
* * A Presence
|
||||
* * A UserResolvable
|
||||
* * A Snowflake
|
||||
* @typedef {Presence|UserResolvable|Snowflake} PresenceResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a {@link PresenceResolvable} to a {@link Presence} object.
|
||||
* @param {PresenceResolvable} presence The presence resolvable to resolve
|
||||
* @returns {?Presence}
|
||||
*/
|
||||
resolve(presence) {
|
||||
const presenceResolvable = super.resolve(presence);
|
||||
if (presenceResolvable) return presenceResolvable;
|
||||
const UserResolvable = this.client.users.resolveId(presence);
|
||||
return super.resolve(UserResolvable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a {@link PresenceResolvable} to a {@link Presence} id.
|
||||
* @param {PresenceResolvable} presence The presence resolvable to resolve
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
resolveId(presence) {
|
||||
const presenceResolvable = super.resolveId(presence);
|
||||
if (presenceResolvable) return presenceResolvable;
|
||||
const userResolvable = this.client.users.resolveId(presence);
|
||||
return this.cache.has(userResolvable) ? userResolvable : null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PresenceManager;
|
||||
68
node_modules/discord.js/src/managers/ReactionManager.js
generated
vendored
Normal file
68
node_modules/discord.js/src/managers/ReactionManager.js
generated
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
'use strict';
|
||||
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const MessageReaction = require('../structures/MessageReaction');
|
||||
|
||||
/**
|
||||
* Manages API methods for reactions and holds their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class ReactionManager extends CachedManager {
|
||||
constructor(message, iterable) {
|
||||
super(message.client, MessageReaction, iterable);
|
||||
|
||||
/**
|
||||
* The message that this manager belongs to
|
||||
* @type {Message}
|
||||
*/
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
_add(data, cache) {
|
||||
return super._add(data, cache, { id: data.emoji.id ?? data.emoji.name, extras: [this.message] });
|
||||
}
|
||||
|
||||
/**
|
||||
* The reaction cache of this manager
|
||||
* @type {Collection<string|Snowflake, MessageReaction>}
|
||||
* @name ReactionManager#cache
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data that can be resolved to a MessageReaction object. This can be:
|
||||
* * A MessageReaction
|
||||
* * A Snowflake
|
||||
* * The Unicode representation of an emoji
|
||||
* @typedef {MessageReaction|Snowflake} MessageReactionResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a {@link MessageReactionResolvable} to a {@link MessageReaction} object.
|
||||
* @method resolve
|
||||
* @memberof ReactionManager
|
||||
* @instance
|
||||
* @param {MessageReactionResolvable} reaction The MessageReaction to resolve
|
||||
* @returns {?MessageReaction}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a {@link MessageReactionResolvable} to a {@link MessageReaction} id.
|
||||
* @method resolveId
|
||||
* @memberof ReactionManager
|
||||
* @instance
|
||||
* @param {MessageReactionResolvable} reaction The MessageReaction to resolve
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Removes all reactions from a message.
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
async removeAll() {
|
||||
await this.client.rest.delete(Routes.channelMessageAllReactions(this.message.channelId, this.message.id));
|
||||
return this.message;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ReactionManager;
|
||||
78
node_modules/discord.js/src/managers/ReactionUserManager.js
generated
vendored
Normal file
78
node_modules/discord.js/src/managers/ReactionUserManager.js
generated
vendored
Normal file
@@ -0,0 +1,78 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { makeURLSearchParams } = require('@discordjs/rest');
|
||||
const { ReactionType, Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsError, ErrorCodes } = require('../errors');
|
||||
const User = require('../structures/User');
|
||||
|
||||
/**
|
||||
* Manages API methods for users who reacted to a reaction and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class ReactionUserManager extends CachedManager {
|
||||
constructor(reaction, iterable) {
|
||||
super(reaction.client, User, iterable);
|
||||
|
||||
/**
|
||||
* The reaction that this manager belongs to
|
||||
* @type {MessageReaction}
|
||||
*/
|
||||
this.reaction = reaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of this manager
|
||||
* @type {Collection<Snowflake, User>}
|
||||
* @name ReactionUserManager#cache
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch users who gave a reaction.
|
||||
* @typedef {Object} FetchReactionUsersOptions
|
||||
* @property {ReactionType} [type=ReactionType.Normal] The reaction type to fetch
|
||||
* @property {number} [limit=100] The maximum amount of users to fetch, defaults to `100`
|
||||
* @property {Snowflake} [after] Limit fetching users to those with an id greater than the supplied id
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetches all the users that gave this reaction. Resolves with a collection of users, mapped by their ids.
|
||||
* @param {FetchReactionUsersOptions} [options] Options for fetching the users
|
||||
* @returns {Promise<Collection<Snowflake, User>>}
|
||||
*/
|
||||
async fetch({ type = ReactionType.Normal, limit = 100, after } = {}) {
|
||||
const message = this.reaction.message;
|
||||
const query = makeURLSearchParams({ limit, after, type });
|
||||
const data = await this.client.rest.get(
|
||||
Routes.channelMessageReaction(message.channelId, message.id, this.reaction.emoji.identifier),
|
||||
{ query },
|
||||
);
|
||||
const users = new Collection();
|
||||
for (const rawUser of data) {
|
||||
const user = this.client.users._add(rawUser);
|
||||
this.cache.set(user.id, user);
|
||||
users.set(user.id, user);
|
||||
}
|
||||
return users;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a user from this reaction.
|
||||
* @param {UserResolvable} [user=this.client.user] The user to remove the reaction of
|
||||
* @returns {Promise<MessageReaction>}
|
||||
*/
|
||||
async remove(user = this.client.user) {
|
||||
const userId = this.client.users.resolveId(user);
|
||||
if (!userId) throw new DiscordjsError(ErrorCodes.ReactionResolveUser);
|
||||
const message = this.reaction.message;
|
||||
const route =
|
||||
userId === this.client.user.id
|
||||
? Routes.channelMessageOwnReaction(message.channelId, message.id, this.reaction.emoji.identifier)
|
||||
: Routes.channelMessageUserReaction(message.channelId, message.id, this.reaction.emoji.identifier, userId);
|
||||
await this.client.rest.delete(route);
|
||||
return this.reaction;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ReactionUserManager;
|
||||
374
node_modules/discord.js/src/managers/RoleManager.js
generated
vendored
Normal file
374
node_modules/discord.js/src/managers/RoleManager.js
generated
vendored
Normal file
@@ -0,0 +1,374 @@
|
||||
'use strict';
|
||||
|
||||
const process = require('node:process');
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { DiscordAPIError } = require('@discordjs/rest');
|
||||
const { RESTJSONErrorCodes, Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
const { Role } = require('../structures/Role');
|
||||
const { resolveImage } = require('../util/DataResolver');
|
||||
const PermissionsBitField = require('../util/PermissionsBitField');
|
||||
const { setPosition, resolveColor } = require('../util/Util');
|
||||
|
||||
let cacheWarningEmitted = false;
|
||||
|
||||
/**
|
||||
* Manages API methods for roles and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class RoleManager extends CachedManager {
|
||||
constructor(guild, iterable) {
|
||||
super(guild.client, Role, iterable);
|
||||
if (!cacheWarningEmitted && this._cache.constructor.name !== 'Collection') {
|
||||
cacheWarningEmitted = true;
|
||||
process.emitWarning(
|
||||
`Overriding the cache handling for ${this.constructor.name} is unsupported and breaks functionality.`,
|
||||
'UnsupportedCacheOverwriteWarning',
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The guild belonging to this manager
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
}
|
||||
|
||||
/**
|
||||
* The role cache of this manager
|
||||
* @type {Collection<Snowflake, Role>}
|
||||
* @name RoleManager#cache
|
||||
*/
|
||||
|
||||
_add(data, cache) {
|
||||
return super._add(data, cache, { extras: [this.guild] });
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a role from Discord, or the role cache if they're already available.
|
||||
* @param {Snowflake} [id] The role's id
|
||||
* @param {BaseFetchOptions} [options] Additional options for this fetch
|
||||
* @returns {Promise<?Role|Collection<Snowflake, Role>>}
|
||||
* @example
|
||||
* // Fetch all roles from the guild
|
||||
* message.guild.roles.fetch()
|
||||
* .then(roles => console.log(`There are ${roles.size} roles.`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch a single role
|
||||
* message.guild.roles.fetch('222078108977594368')
|
||||
* .then(role => console.log(`The role color is: ${role.color}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetch(id, { cache = true, force = false } = {}) {
|
||||
if (!id) {
|
||||
const data = await this.client.rest.get(Routes.guildRoles(this.guild.id));
|
||||
const roles = new Collection();
|
||||
for (const role of data) roles.set(role.id, this._add(role, cache));
|
||||
return roles;
|
||||
}
|
||||
|
||||
if (!force) {
|
||||
const existing = this.cache.get(id);
|
||||
if (existing) return existing;
|
||||
}
|
||||
|
||||
try {
|
||||
const data = await this.client.rest.get(Routes.guildRole(this.guild.id, id));
|
||||
return this._add(data, cache);
|
||||
} catch (error) {
|
||||
// TODO: Remove this catch in the next major version
|
||||
if (error instanceof DiscordAPIError && error.code === RESTJSONErrorCodes.UnknownRole) {
|
||||
return null;
|
||||
}
|
||||
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to a Role object. This can be:
|
||||
* * A Role
|
||||
* * A Snowflake
|
||||
* @typedef {Role|Snowflake} RoleResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a {@link RoleResolvable} to a {@link Role} object.
|
||||
* @method resolve
|
||||
* @memberof RoleManager
|
||||
* @instance
|
||||
* @param {RoleResolvable} role The role resolvable to resolve
|
||||
* @returns {?Role}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a {@link RoleResolvable} to a {@link Role} id.
|
||||
* @method resolveId
|
||||
* @memberof RoleManager
|
||||
* @instance
|
||||
* @param {RoleResolvable} role The role resolvable to resolve
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to create a new role.
|
||||
* @typedef {Object} RoleCreateOptions
|
||||
* @property {string} [name] The name of the new role
|
||||
* @property {ColorResolvable} [color] The data to create the role with
|
||||
* @property {boolean} [hoist] Whether or not the new role should be hoisted
|
||||
* @property {PermissionResolvable} [permissions] The permissions for the new role
|
||||
* @property {number} [position] The position of the new role
|
||||
* @property {boolean} [mentionable] Whether or not the new 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
|
||||
* @property {string} [reason] The reason for creating this role
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new role in the guild with given information.
|
||||
* <warn>The position will silently reset to 1 if an invalid one is provided, or none.</warn>
|
||||
* @param {RoleCreateOptions} [options] Options for creating the new role
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Create a new role
|
||||
* guild.roles.create()
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Create a new role with data and a reason
|
||||
* guild.roles.create({
|
||||
* name: 'Super Cool Blue People',
|
||||
* color: Colors.Blue,
|
||||
* reason: 'we needed a role for Super Cool People',
|
||||
* })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async create(options = {}) {
|
||||
let { name, color, hoist, permissions, position, mentionable, reason, icon, unicodeEmoji } = options;
|
||||
color &&= resolveColor(color);
|
||||
if (permissions !== undefined) permissions = new PermissionsBitField(permissions);
|
||||
if (icon) {
|
||||
const guildEmojiURL = this.guild.emojis.resolve(icon)?.imageURL();
|
||||
icon = guildEmojiURL ? await resolveImage(guildEmojiURL) : await resolveImage(icon);
|
||||
if (typeof icon !== 'string') icon = undefined;
|
||||
}
|
||||
|
||||
const data = await this.client.rest.post(Routes.guildRoles(this.guild.id), {
|
||||
body: {
|
||||
name,
|
||||
color,
|
||||
hoist,
|
||||
permissions,
|
||||
mentionable,
|
||||
icon,
|
||||
unicode_emoji: unicodeEmoji,
|
||||
},
|
||||
reason,
|
||||
});
|
||||
const { role } = this.client.actions.GuildRoleCreate.handle({
|
||||
guild_id: this.guild.id,
|
||||
role: data,
|
||||
});
|
||||
if (position) return this.setPosition(role, position, { reason });
|
||||
return role;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options for editing a role
|
||||
* @typedef {RoleData} RoleEditOptions
|
||||
* @property {string} [reason] The reason for editing this role
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits a role of the guild.
|
||||
* @param {RoleResolvable} role The role to edit
|
||||
* @param {RoleEditOptions} options The options to provide
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Edit a role
|
||||
* guild.roles.edit('222079219327434752', { name: 'buddies' })
|
||||
* .then(updated => console.log(`Edited role name to ${updated.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async edit(role, options) {
|
||||
role = this.resolve(role);
|
||||
if (!role) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'role', 'RoleResolvable');
|
||||
|
||||
if (typeof options.position === 'number') {
|
||||
await this.setPosition(role, options.position, { reason: options.reason });
|
||||
}
|
||||
|
||||
let icon = options.icon;
|
||||
if (icon) {
|
||||
const guildEmojiURL = this.guild.emojis.resolve(icon)?.imageURL();
|
||||
icon = guildEmojiURL ? await resolveImage(guildEmojiURL) : await resolveImage(icon);
|
||||
if (typeof icon !== 'string') icon = undefined;
|
||||
}
|
||||
|
||||
const body = {
|
||||
name: options.name,
|
||||
color: options.color === undefined ? undefined : resolveColor(options.color),
|
||||
hoist: options.hoist,
|
||||
permissions: options.permissions === undefined ? undefined : new PermissionsBitField(options.permissions),
|
||||
mentionable: options.mentionable,
|
||||
icon,
|
||||
unicode_emoji: options.unicodeEmoji,
|
||||
};
|
||||
|
||||
const d = await this.client.rest.patch(Routes.guildRole(this.guild.id, role.id), { body, reason: options.reason });
|
||||
|
||||
const clone = role._clone();
|
||||
clone._patch(d);
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a role.
|
||||
* @param {RoleResolvable} role The role to delete
|
||||
* @param {string} [reason] Reason for deleting the role
|
||||
* @returns {Promise<void>}
|
||||
* @example
|
||||
* // Delete a role
|
||||
* guild.roles.delete('222079219327434752', 'The role needed to go')
|
||||
* .then(() => console.log('Deleted the role'))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async delete(role, reason) {
|
||||
const id = this.resolveId(role);
|
||||
await this.client.rest.delete(Routes.guildRole(this.guild.id, id), { reason });
|
||||
this.client.actions.GuildRoleDelete.handle({ guild_id: this.guild.id, role_id: id });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new position of the role.
|
||||
* @param {RoleResolvable} role The role to change the position of
|
||||
* @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
|
||||
* guild.roles.setPosition('222197033908436994', 1)
|
||||
* .then(updated => console.log(`Role position: ${updated.position}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async setPosition(role, position, { relative, reason } = {}) {
|
||||
role = this.resolve(role);
|
||||
if (!role) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'role', 'RoleResolvable');
|
||||
const updatedRoles = await setPosition(
|
||||
role,
|
||||
position,
|
||||
relative,
|
||||
this.guild._sortedRoles(),
|
||||
this.client,
|
||||
Routes.guildRoles(this.guild.id),
|
||||
reason,
|
||||
);
|
||||
|
||||
this.client.actions.GuildRolesPositionUpdate.handle({
|
||||
guild_id: this.guild.id,
|
||||
roles: updatedRoles,
|
||||
});
|
||||
return role;
|
||||
}
|
||||
|
||||
/**
|
||||
* The data needed for updating a guild role's position
|
||||
* @typedef {Object} GuildRolePosition
|
||||
* @property {RoleResolvable} role The role's id
|
||||
* @property {number} position The position to update
|
||||
*/
|
||||
|
||||
/**
|
||||
* Batch-updates the guild's role positions
|
||||
* @param {GuildRolePosition[]} rolePositions Role positions to update
|
||||
* @returns {Promise<Guild>}
|
||||
* @example
|
||||
* guild.roles.setPositions([{ role: roleId, position: updatedRoleIndex }])
|
||||
* .then(guild => console.log(`Role positions updated for ${guild}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async setPositions(rolePositions) {
|
||||
// Make sure rolePositions are prepared for API
|
||||
rolePositions = rolePositions.map(rolePosition => ({
|
||||
id: this.resolveId(rolePosition.role),
|
||||
position: rolePosition.position,
|
||||
}));
|
||||
|
||||
// Call the API to update role positions
|
||||
await this.client.rest.patch(Routes.guildRoles(this.guild.id), { body: rolePositions });
|
||||
return this.client.actions.GuildRolesPositionUpdate.handle({
|
||||
guild_id: this.guild.id,
|
||||
roles: rolePositions,
|
||||
}).guild;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the positions of two roles.
|
||||
* @param {RoleResolvable} role1 First role to compare
|
||||
* @param {RoleResolvable} role2 Second role to compare
|
||||
* @returns {number} Negative number if the first role's position is lower (second role's is higher),
|
||||
* positive number if the first's is higher (second's is lower), 0 if equal
|
||||
*/
|
||||
comparePositions(role1, role2) {
|
||||
const resolvedRole1 = this.resolve(role1);
|
||||
const resolvedRole2 = this.resolve(role2);
|
||||
if (!resolvedRole1 || !resolvedRole2) {
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'role', 'Role nor a Snowflake');
|
||||
}
|
||||
|
||||
const role1Position = resolvedRole1.position;
|
||||
const role2Position = resolvedRole2.position;
|
||||
|
||||
if (role1Position === role2Position) {
|
||||
return Number(BigInt(resolvedRole2.id) - BigInt(resolvedRole1.id));
|
||||
}
|
||||
|
||||
return role1Position - role2Position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the managed role a user created when joining the guild, if any
|
||||
* <info>Only ever available for bots</info>
|
||||
* @param {UserResolvable} user The user to access the bot role for
|
||||
* @returns {?Role}
|
||||
*/
|
||||
botRoleFor(user) {
|
||||
const userId = this.client.users.resolveId(user);
|
||||
if (!userId) return null;
|
||||
return this.cache.find(role => role.tags?.botId === userId) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The `@everyone` role of the guild
|
||||
* @type {Role}
|
||||
* @readonly
|
||||
*/
|
||||
get everyone() {
|
||||
return this.cache.get(this.guild.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The premium subscriber role of the guild, if any
|
||||
* @type {?Role}
|
||||
* @readonly
|
||||
*/
|
||||
get premiumSubscriberRole() {
|
||||
return this.cache.find(role => role.tags?.premiumSubscriberRole) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The role with the highest position in the cache
|
||||
* @type {Role}
|
||||
* @readonly
|
||||
*/
|
||||
get highest() {
|
||||
return this.cache.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev), this.cache.first());
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = RoleManager;
|
||||
159
node_modules/discord.js/src/managers/StageInstanceManager.js
generated
vendored
Normal file
159
node_modules/discord.js/src/managers/StageInstanceManager.js
generated
vendored
Normal file
@@ -0,0 +1,159 @@
|
||||
'use strict';
|
||||
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsTypeError, DiscordjsError, ErrorCodes } = require('../errors');
|
||||
const { StageInstance } = require('../structures/StageInstance');
|
||||
|
||||
/**
|
||||
* Manages API methods for {@link StageInstance} objects and holds their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class StageInstanceManager extends CachedManager {
|
||||
constructor(guild, iterable) {
|
||||
super(guild.client, StageInstance, iterable);
|
||||
|
||||
/**
|
||||
* The guild this manager belongs to
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of this Manager
|
||||
* @type {Collection<Snowflake, StageInstance>}
|
||||
* @name StageInstanceManager#cache
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to create a stage instance.
|
||||
* @typedef {Object} StageInstanceCreateOptions
|
||||
* @property {string} topic The topic of the stage instance
|
||||
* @property {StageInstancePrivacyLevel} [privacyLevel] The privacy level of the stage instance
|
||||
* @property {boolean} [sendStartNotification] Whether to notify `@everyone` that the stage instance has started
|
||||
* @property {GuildScheduledEventResolvable} [guildScheduledEvent]
|
||||
* The guild scheduled event associated with the stage instance
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data that can be resolved to a Stage Channel object. This can be:
|
||||
* * A StageChannel
|
||||
* * A Snowflake
|
||||
* @typedef {StageChannel|Snowflake} StageChannelResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a new stage instance.
|
||||
* @param {StageChannelResolvable} channel The stage channel to associate the created stage instance to
|
||||
* @param {StageInstanceCreateOptions} options The options to create the stage instance
|
||||
* @returns {Promise<StageInstance>}
|
||||
* @example
|
||||
* // Create a stage instance
|
||||
* guild.stageInstances.create('1234567890123456789', {
|
||||
* topic: 'A very creative topic',
|
||||
* privacyLevel: GuildPrivacyLevel.GuildOnly
|
||||
* })
|
||||
* .then(stageInstance => console.log(stageInstance))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async create(channel, options) {
|
||||
const channelId = this.guild.channels.resolveId(channel);
|
||||
if (!channelId) throw new DiscordjsError(ErrorCodes.StageChannelResolve);
|
||||
if (typeof options !== 'object') throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'options', 'object', true);
|
||||
const { guildScheduledEvent, topic, privacyLevel, sendStartNotification } = options;
|
||||
|
||||
const guildScheduledEventId = guildScheduledEvent && this.resolveId(guildScheduledEvent);
|
||||
|
||||
const data = await this.client.rest.post(Routes.stageInstances(), {
|
||||
body: {
|
||||
channel_id: channelId,
|
||||
topic,
|
||||
privacy_level: privacyLevel,
|
||||
send_start_notification: sendStartNotification,
|
||||
guild_scheduled_event_id: guildScheduledEventId,
|
||||
},
|
||||
});
|
||||
|
||||
return this._add(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the stage instance associated with a stage channel, if it exists.
|
||||
* @param {StageChannelResolvable} channel The stage channel whose associated stage instance is to be fetched
|
||||
* @param {BaseFetchOptions} [options] Additional options for this fetch
|
||||
* @returns {Promise<StageInstance>}
|
||||
* @example
|
||||
* // Fetch a stage instance
|
||||
* guild.stageInstances.fetch('1234567890123456789')
|
||||
* .then(stageInstance => console.log(stageInstance))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetch(channel, { cache = true, force = false } = {}) {
|
||||
const channelId = this.guild.channels.resolveId(channel);
|
||||
if (!channelId) throw new DiscordjsError(ErrorCodes.StageChannelResolve);
|
||||
|
||||
if (!force) {
|
||||
const existing = this.cache.find(stageInstance => stageInstance.channelId === channelId);
|
||||
if (existing) return existing;
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(Routes.stageInstance(channelId));
|
||||
return this._add(data, cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to edit an existing stage instance.
|
||||
* @typedef {Object} StageInstanceEditOptions
|
||||
* @property {string} [topic] The new topic of the stage instance
|
||||
* @property {StageInstancePrivacyLevel} [privacyLevel] The new privacy level of the stage instance
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits an existing stage instance.
|
||||
* @param {StageChannelResolvable} channel The stage channel whose associated stage instance is to be edited
|
||||
* @param {StageInstanceEditOptions} options The options to edit the stage instance
|
||||
* @returns {Promise<StageInstance>}
|
||||
* @example
|
||||
* // Edit a stage instance
|
||||
* guild.stageInstances.edit('1234567890123456789', { topic: 'new topic' })
|
||||
* .then(stageInstance => console.log(stageInstance))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async edit(channel, options) {
|
||||
if (typeof options !== 'object') throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'options', 'object', true);
|
||||
const channelId = this.guild.channels.resolveId(channel);
|
||||
if (!channelId) throw new DiscordjsError(ErrorCodes.StageChannelResolve);
|
||||
|
||||
let { topic, privacyLevel } = options;
|
||||
|
||||
const data = await this.client.rest.patch(Routes.stageInstance(channelId), {
|
||||
body: {
|
||||
topic,
|
||||
privacy_level: privacyLevel,
|
||||
},
|
||||
});
|
||||
|
||||
if (this.cache.has(data.id)) {
|
||||
const clone = this.cache.get(data.id)._clone();
|
||||
clone._patch(data);
|
||||
return clone;
|
||||
}
|
||||
|
||||
return this._add(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an existing stage instance.
|
||||
* @param {StageChannelResolvable} channel The stage channel whose associated stage instance is to be deleted
|
||||
* @returns {Promise<void>}
|
||||
*/
|
||||
async delete(channel) {
|
||||
const channelId = this.guild.channels.resolveId(channel);
|
||||
if (!channelId) throw new DiscordjsError(ErrorCodes.StageChannelResolve);
|
||||
|
||||
await this.client.rest.delete(Routes.stageInstance(channelId));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = StageInstanceManager;
|
||||
193
node_modules/discord.js/src/managers/ThreadManager.js
generated
vendored
Normal file
193
node_modules/discord.js/src/managers/ThreadManager.js
generated
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { makeURLSearchParams } = require('@discordjs/rest');
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
const ThreadChannel = require('../structures/ThreadChannel');
|
||||
const { MakeCacheOverrideSymbol } = require('../util/Symbols');
|
||||
|
||||
/**
|
||||
* Manages API methods for thread-based channels and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class ThreadManager extends CachedManager {
|
||||
static [MakeCacheOverrideSymbol] = ThreadManager;
|
||||
|
||||
constructor(channel, iterable) {
|
||||
super(channel.client, ThreadChannel, iterable);
|
||||
|
||||
/**
|
||||
* The channel this Manager belongs to
|
||||
* @type {TextChannel|NewsChannel|ForumChannel|MediaChannel}
|
||||
*/
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to a Thread Channel object. This can be:
|
||||
* * A ThreadChannel object
|
||||
* * A Snowflake
|
||||
* @typedef {ThreadChannel|Snowflake} ThreadChannelResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* The cache of this Manager
|
||||
* @type {Collection<Snowflake, ThreadChannel>}
|
||||
* @name ThreadManager#cache
|
||||
*/
|
||||
|
||||
_add(thread) {
|
||||
const existing = this.cache.get(thread.id);
|
||||
if (existing) return existing;
|
||||
this.cache.set(thread.id, thread);
|
||||
return thread;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a {@link ThreadChannelResolvable} to a {@link ThreadChannel} object.
|
||||
* @method resolve
|
||||
* @memberof ThreadManager
|
||||
* @instance
|
||||
* @param {ThreadChannelResolvable} thread The ThreadChannel resolvable to resolve
|
||||
* @returns {?ThreadChannel}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a {@link ThreadChannelResolvable} to a {@link ThreadChannel} id.
|
||||
* @method resolveId
|
||||
* @memberof ThreadManager
|
||||
* @instance
|
||||
* @param {ThreadChannelResolvable} thread The ThreadChannel resolvable to resolve
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options for fetching multiple threads.
|
||||
* @typedef {Object} FetchThreadsOptions
|
||||
* @property {FetchArchivedThreadOptions} [archived] Options used to fetch archived threads
|
||||
*/
|
||||
|
||||
/**
|
||||
* Obtains a thread from Discord, or the channel cache if it's already available.
|
||||
* @param {ThreadChannelResolvable|FetchThreadsOptions} [options] The options to fetch threads. If it is a
|
||||
* ThreadChannelResolvable then the specified thread will be fetched. Fetches all active threads if `undefined`
|
||||
* @param {BaseFetchOptions} [cacheOptions] Additional options for this fetch. <warn>The `force` field gets ignored
|
||||
* if `options` is not a {@link ThreadChannelResolvable}</warn>
|
||||
* @returns {Promise<?(ThreadChannel|FetchedThreads|FetchedThreadsMore)>}
|
||||
* {@link FetchedThreads} if active & {@link FetchedThreadsMore} if archived.
|
||||
* @example
|
||||
* // Fetch a thread by its id
|
||||
* channel.threads.fetch('831955138126104859')
|
||||
* .then(channel => console.log(channel.name))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetch(options, { cache, force } = {}) {
|
||||
if (!options) return this.fetchActive(cache);
|
||||
const channel = this.client.channels.resolveId(options);
|
||||
if (channel) return this.client.channels.fetch(channel, { cache, force });
|
||||
if (options.archived) {
|
||||
return this.fetchArchived(options.archived, cache);
|
||||
}
|
||||
return this.fetchActive(cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that can be resolved to a Date object. This can be:
|
||||
* * A Date object
|
||||
* * A number representing a timestamp
|
||||
* * An [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) string
|
||||
* @typedef {Date|number|string} DateResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* The options used to fetch archived threads.
|
||||
* @typedef {Object} FetchArchivedThreadOptions
|
||||
* @property {string} [type='public'] The type of threads to fetch (`public` or `private`)
|
||||
* @property {boolean} [fetchAll=false] Whether to fetch **all** archived threads when `type` is `private`
|
||||
* <info>This property requires the {@link PermissionFlagsBits.ManageThreads} permission if `true`.</info>
|
||||
* @property {DateResolvable|ThreadChannelResolvable} [before] Only return threads that were archived before this Date
|
||||
* or Snowflake
|
||||
* <warn>Must be a {@link ThreadChannelResolvable} when `type` is `private` and `fetchAll` is `false`.</warn>
|
||||
* @property {number} [limit] Maximum number of threads to return
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data returned from fetching multiple threads.
|
||||
* @typedef {FetchedThreads} FetchedThreadsMore
|
||||
* @property {?boolean} hasMore Whether there are potentially additional threads that require a subsequent call
|
||||
*/
|
||||
|
||||
/**
|
||||
* Obtains a set of archived threads from Discord.
|
||||
* <info>This method requires the {@link PermissionFlagsBits.ReadMessageHistory} permission
|
||||
* in the parent channel.</info>
|
||||
* @param {FetchArchivedThreadOptions} [options] The options to fetch archived threads
|
||||
* @param {boolean} [cache=true] Whether to cache the new thread objects if they aren't already
|
||||
* @returns {Promise<FetchedThreadsMore>}
|
||||
*/
|
||||
async fetchArchived({ type = 'public', fetchAll = false, before, limit } = {}, cache = true) {
|
||||
let path = Routes.channelThreads(this.channel.id, type);
|
||||
if (type === 'private' && !fetchAll) {
|
||||
path = Routes.channelJoinedArchivedThreads(this.channel.id);
|
||||
}
|
||||
let timestamp;
|
||||
let id;
|
||||
const query = makeURLSearchParams({ limit });
|
||||
if (before !== undefined) {
|
||||
if (before instanceof ThreadChannel || /^\d{17,19}$/.test(String(before))) {
|
||||
id = this.resolveId(before);
|
||||
timestamp = this.resolve(before)?.archivedAt?.toISOString();
|
||||
const toUse = type === 'private' && !fetchAll ? id : timestamp;
|
||||
if (toUse) {
|
||||
query.set('before', toUse);
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
timestamp = new Date(before).toISOString();
|
||||
if (type === 'public' || fetchAll) {
|
||||
query.set('before', timestamp);
|
||||
}
|
||||
} catch {
|
||||
throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'before', 'DateResolvable or ThreadChannelResolvable');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const raw = await this.client.rest.get(path, { query });
|
||||
return this.constructor._mapThreads(raw, this.client, { parent: this.channel, cache });
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains all active threads in the channel.
|
||||
* @param {boolean} [cache=true] Whether to cache the fetched data
|
||||
* @returns {Promise<FetchedThreads>}
|
||||
*/
|
||||
async fetchActive(cache = true) {
|
||||
const data = await this.channel.guild.channels.rawFetchGuildActiveThreads();
|
||||
return this.constructor._mapThreads(data, this.client, { parent: this.channel, cache });
|
||||
}
|
||||
|
||||
static _mapThreads(rawThreads, client, { parent, guild, cache }) {
|
||||
const threads = rawThreads.threads.reduce((coll, raw) => {
|
||||
const thread = client.channels._add(raw, guild ?? parent?.guild, { cache });
|
||||
if (parent && thread.parentId !== parent.id) return coll;
|
||||
return coll.set(thread.id, thread);
|
||||
}, new Collection());
|
||||
|
||||
// Discord sends the thread id as id in this object
|
||||
const threadMembers = rawThreads.members.reduce((coll, raw) => {
|
||||
const thread = threads.get(raw.id);
|
||||
return thread ? coll.set(raw.user_id, thread.members._add(raw)) : coll;
|
||||
}, new Collection());
|
||||
|
||||
const response = { threads, members: threadMembers };
|
||||
|
||||
// The GET `/guilds/{guild.id}/threads/active` route does not return `has_more`.
|
||||
if ('has_more' in rawThreads) response.hasMore = rawThreads.has_more;
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ThreadManager;
|
||||
184
node_modules/discord.js/src/managers/ThreadMemberManager.js
generated
vendored
Normal file
184
node_modules/discord.js/src/managers/ThreadMemberManager.js
generated
vendored
Normal file
@@ -0,0 +1,184 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { makeURLSearchParams } = require('@discordjs/rest');
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsTypeError, ErrorCodes } = require('../errors');
|
||||
const ThreadMember = require('../structures/ThreadMember');
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildMembers and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class ThreadMemberManager extends CachedManager {
|
||||
constructor(thread, iterable) {
|
||||
super(thread.client, ThreadMember, iterable);
|
||||
|
||||
/**
|
||||
* The thread this manager belongs to
|
||||
* @type {ThreadChannel}
|
||||
*/
|
||||
this.thread = thread;
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of this Manager
|
||||
* @type {Collection<Snowflake, ThreadMember>}
|
||||
* @name ThreadMemberManager#cache
|
||||
*/
|
||||
|
||||
_add(data, cache = true) {
|
||||
const existing = this.cache.get(data.user_id);
|
||||
if (cache) existing?._patch(data, { cache });
|
||||
if (existing) return existing;
|
||||
|
||||
const member = new ThreadMember(this.thread, data, { cache });
|
||||
if (cache) this.cache.set(data.user_id, member);
|
||||
return member;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the client user as a ThreadMember of the thread.
|
||||
* @param {BaseFetchOptions} [options] The options for fetching the member
|
||||
* @returns {Promise<ThreadMember>}
|
||||
*/
|
||||
fetchMe(options) {
|
||||
return this.fetch({ ...options, member: this.client.user.id });
|
||||
}
|
||||
|
||||
/**
|
||||
* The client user as a ThreadMember of this ThreadChannel
|
||||
* @type {?ThreadMember}
|
||||
* @readonly
|
||||
*/
|
||||
get me() {
|
||||
return this.resolve(this.client.user.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data that resolves to give a ThreadMember object. This can be:
|
||||
* * A ThreadMember object
|
||||
* * A User resolvable
|
||||
* @typedef {ThreadMember|UserResolvable} ThreadMemberResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a {@link ThreadMemberResolvable} to a {@link ThreadMember} object.
|
||||
* @param {ThreadMemberResolvable} member The user that is part of the thread
|
||||
* @returns {?GuildMember}
|
||||
*/
|
||||
resolve(member) {
|
||||
const memberResolvable = super.resolve(member);
|
||||
if (memberResolvable) return memberResolvable;
|
||||
const userResolvable = this.client.users.resolveId(member);
|
||||
if (userResolvable) return super.resolve(userResolvable);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a {@link ThreadMemberResolvable} to a {@link ThreadMember} id string.
|
||||
* @param {ThreadMemberResolvable} member The user that is part of the guild
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
resolveId(member) {
|
||||
const memberResolvable = super.resolveId(member);
|
||||
if (memberResolvable) return memberResolvable;
|
||||
const userResolvable = this.client.users.resolveId(member);
|
||||
return this.cache.has(userResolvable) ? userResolvable : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a member to the thread.
|
||||
* @param {UserResolvable|'@me'} member The member to add
|
||||
* @param {string} [reason] The reason for adding this member
|
||||
* @returns {Promise<Snowflake>}
|
||||
*/
|
||||
async add(member, reason) {
|
||||
const id = member === '@me' ? member : this.client.users.resolveId(member);
|
||||
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'member', 'UserResolvable');
|
||||
await this.client.rest.put(Routes.threadMembers(this.thread.id, id), { reason });
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a user from the thread.
|
||||
* @param {UserResolvable|'@me'} member The member to remove
|
||||
* @param {string} [reason] The reason for removing this member from the thread
|
||||
* @returns {Promise<Snowflake>}
|
||||
*/
|
||||
async remove(member, reason) {
|
||||
const id = member === '@me' ? member : this.client.users.resolveId(member);
|
||||
if (!id) throw new DiscordjsTypeError(ErrorCodes.InvalidType, 'member', 'UserResolvable');
|
||||
await this.client.rest.delete(Routes.threadMembers(this.thread.id, id), { reason });
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options used to fetch a thread member.
|
||||
* @typedef {BaseFetchOptions} FetchThreadMemberOptions
|
||||
* @property {ThreadMemberResolvable} member The thread member to fetch
|
||||
* @property {boolean} [withMember] Whether to also return the guild member associated with this thread member
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch multiple thread members with guild member data.
|
||||
* <info>With `withMember` set to `true`, pagination is enabled.</info>
|
||||
* @typedef {Object} FetchThreadMembersWithGuildMemberDataOptions
|
||||
* @property {true} withMember Whether to also return the guild member data
|
||||
* @property {Snowflake} [after] Consider only thread members after this id
|
||||
* @property {number} [limit] The maximum number of thread members to return
|
||||
* @property {boolean} [cache] Whether to cache the fetched thread members and guild members
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch multiple thread members without guild member data.
|
||||
* @typedef {Object} FetchThreadMembersWithoutGuildMemberDataOptions
|
||||
* @property {false} [withMember] Whether to also return the guild member data
|
||||
* @property {boolean} [cache] Whether to cache the fetched thread members
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options used to fetch multiple thread members.
|
||||
* @typedef {FetchThreadMembersWithGuildMemberDataOptions|
|
||||
* FetchThreadMembersWithoutGuildMemberDataOptions} FetchThreadMembersOptions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetches thread member(s) from Discord.
|
||||
* <info>This method requires the {@link GatewayIntentBits.GuildMembers} privileged gateway intent.</info>
|
||||
* @param {ThreadMemberResolvable|FetchThreadMemberOptions|FetchThreadMembersOptions} [options]
|
||||
* Options for fetching thread member(s)
|
||||
* @returns {Promise<ThreadMember|Collection<Snowflake, ThreadMember>>}
|
||||
*/
|
||||
fetch(options) {
|
||||
if (!options) return this._fetchMany();
|
||||
const { member, withMember, cache, force } = options;
|
||||
const resolvedMember = this.resolveId(member ?? options);
|
||||
if (resolvedMember) return this._fetchSingle({ member: resolvedMember, withMember, cache, force });
|
||||
return this._fetchMany(options);
|
||||
}
|
||||
|
||||
async _fetchSingle({ member, withMember, cache, force = false }) {
|
||||
if (!force) {
|
||||
const existing = this.cache.get(member);
|
||||
if (existing) return existing;
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(Routes.threadMembers(this.thread.id, member), {
|
||||
query: makeURLSearchParams({ with_member: withMember }),
|
||||
});
|
||||
|
||||
return this._add(data, cache);
|
||||
}
|
||||
|
||||
async _fetchMany({ withMember, after, limit, cache } = {}) {
|
||||
const data = await this.client.rest.get(Routes.threadMembers(this.thread.id), {
|
||||
query: makeURLSearchParams({ with_member: withMember, after, limit }),
|
||||
});
|
||||
|
||||
return data.reduce((col, member) => col.set(member.user_id, this._add(member, cache)), new Collection());
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ThreadMemberManager;
|
||||
142
node_modules/discord.js/src/managers/UserManager.js
generated
vendored
Normal file
142
node_modules/discord.js/src/managers/UserManager.js
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
'use strict';
|
||||
|
||||
const { ChannelType, Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { DiscordjsError, ErrorCodes } = require('../errors');
|
||||
const { GuildMember } = require('../structures/GuildMember');
|
||||
const { Message } = require('../structures/Message');
|
||||
const ThreadMember = require('../structures/ThreadMember');
|
||||
const User = require('../structures/User');
|
||||
|
||||
/**
|
||||
* Manages API methods for users and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class UserManager extends CachedManager {
|
||||
constructor(client, iterable) {
|
||||
super(client, User, iterable);
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of this manager
|
||||
* @type {Collection<Snowflake, User>}
|
||||
* @name UserManager#cache
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data that resolves to give a User object. This can be:
|
||||
* * A User object
|
||||
* * A Snowflake
|
||||
* * A Message object (resolves to the message author)
|
||||
* * A GuildMember object
|
||||
* * A ThreadMember object
|
||||
* @typedef {User|Snowflake|Message|GuildMember|ThreadMember} UserResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
* The DM between the client's user and a user
|
||||
* @param {Snowflake} userId The user id
|
||||
* @returns {?DMChannel}
|
||||
* @private
|
||||
*/
|
||||
dmChannel(userId) {
|
||||
return (
|
||||
this.client.channels.cache.find(channel => channel.type === ChannelType.DM && channel.recipientId === userId) ??
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link DMChannel} between the client and a user.
|
||||
* @param {UserResolvable} user The UserResolvable to identify
|
||||
* @param {BaseFetchOptions} [options] Additional options for this fetch
|
||||
* @returns {Promise<DMChannel>}
|
||||
*/
|
||||
async createDM(user, { cache = true, force = false } = {}) {
|
||||
const id = this.resolveId(user);
|
||||
|
||||
if (!force) {
|
||||
const dmChannel = this.dmChannel(id);
|
||||
if (dmChannel && !dmChannel.partial) return dmChannel;
|
||||
}
|
||||
|
||||
const data = await this.client.rest.post(Routes.userChannels(), { body: { recipient_id: id } });
|
||||
return this.client.channels._add(data, null, { cache });
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a {@link DMChannel} (if one exists) between the client and a user. Resolves with the channel if successful.
|
||||
* @param {UserResolvable} user The UserResolvable to identify
|
||||
* @returns {Promise<DMChannel>}
|
||||
*/
|
||||
async deleteDM(user) {
|
||||
const id = this.resolveId(user);
|
||||
const dmChannel = this.dmChannel(id);
|
||||
if (!dmChannel) throw new DiscordjsError(ErrorCodes.UserNoDMChannel);
|
||||
await this.client.rest.delete(Routes.channel(dmChannel.id));
|
||||
this.client.channels._remove(dmChannel.id);
|
||||
return dmChannel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a user from Discord, or the user cache if it's already available.
|
||||
* @param {UserResolvable} user The user to fetch
|
||||
* @param {BaseFetchOptions} [options] Additional options for this fetch
|
||||
* @returns {Promise<User>}
|
||||
*/
|
||||
async fetch(user, { cache = true, force = false } = {}) {
|
||||
const id = this.resolveId(user);
|
||||
if (!force) {
|
||||
const existing = this.cache.get(id);
|
||||
if (existing && !existing.partial) return existing;
|
||||
}
|
||||
|
||||
const data = await this.client.rest.get(Routes.user(id));
|
||||
return this._add(data, cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a user's flags.
|
||||
* @param {UserResolvable} user The UserResolvable to identify
|
||||
* @param {BaseFetchOptions} [options] Additional options for this fetch
|
||||
* @returns {Promise<UserFlagsBitField>}
|
||||
*/
|
||||
async fetchFlags(user, options) {
|
||||
return (await this.fetch(user, options)).flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a message to a user.
|
||||
* @param {UserResolvable} user The UserResolvable to identify
|
||||
* @param {string|MessagePayload|MessageCreateOptions} options The options to provide
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
async send(user, options) {
|
||||
return (await this.createDM(user)).send(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a {@link UserResolvable} to a {@link User} object.
|
||||
* @param {UserResolvable} user The UserResolvable to identify
|
||||
* @returns {?User}
|
||||
*/
|
||||
resolve(user) {
|
||||
if (user instanceof GuildMember || user instanceof ThreadMember) return user.user;
|
||||
if (user instanceof Message) return user.author;
|
||||
return super.resolve(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a {@link UserResolvable} to a {@link User} id.
|
||||
* @param {UserResolvable} user The UserResolvable to identify
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
resolveId(user) {
|
||||
if (user instanceof ThreadMember) return user.id;
|
||||
if (user instanceof GuildMember) return user.user.id;
|
||||
if (user instanceof Message) return user.author.id;
|
||||
return super.resolveId(user);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = UserManager;
|
||||
59
node_modules/discord.js/src/managers/VoiceStateManager.js
generated
vendored
Normal file
59
node_modules/discord.js/src/managers/VoiceStateManager.js
generated
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
'use strict';
|
||||
|
||||
const { Routes } = require('discord-api-types/v10');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const VoiceState = require('../structures/VoiceState');
|
||||
|
||||
/**
|
||||
* Manages API methods for VoiceStates and stores their cache.
|
||||
* @extends {CachedManager}
|
||||
*/
|
||||
class VoiceStateManager extends CachedManager {
|
||||
constructor(guild, iterable) {
|
||||
super(guild.client, VoiceState, iterable);
|
||||
|
||||
/**
|
||||
* The guild this manager belongs to
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of this manager
|
||||
* @type {Collection<Snowflake, VoiceState>}
|
||||
* @name VoiceStateManager#cache
|
||||
*/
|
||||
|
||||
_add(data, cache = true) {
|
||||
const existing = this.cache.get(data.user_id);
|
||||
if (existing) return existing._patch(data);
|
||||
|
||||
const entry = new this.holds(this.guild, data);
|
||||
if (cache) this.cache.set(data.user_id, entry);
|
||||
return entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains a user's voice state from discord or from the cache if it's already available.
|
||||
* @param {GuildMemberResolvable|'@me'} member The member whose voice state is to be fetched
|
||||
* @param {BaseFetchOptions} [options] Additional options for this fetch
|
||||
* @returns {Promise<VoiceState>}
|
||||
* @example
|
||||
* // Fetch a member's voice state
|
||||
* guild.voiceStates.fetch("66564597481480192")
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
async fetch(member, { cache = true, force = false } = {}) {
|
||||
const id = member === '@me' ? member : this.guild.members.resolveId(member);
|
||||
if (!force) {
|
||||
const existing = this.cache.get(id === '@me' ? this.client.user.id : id);
|
||||
if (existing) return existing;
|
||||
}
|
||||
const data = await this.client.rest.get(Routes.guildVoiceState(this.guild.id, id));
|
||||
return this._add(data, cache);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = VoiceStateManager;
|
||||
Reference in New Issue
Block a user