mirror of
https://github.com/musix-org/musix-oss
synced 2025-07-04 13:54:29 +00:00
fix
This commit is contained in:
75
node_modules/discord.js/src/structures/Attachment.js
generated
vendored
Normal file
75
node_modules/discord.js/src/structures/Attachment.js
generated
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
/**
|
||||
* Represents an attachment in a message.
|
||||
* @param {BufferResolvable|Stream} file The file
|
||||
* @param {string} [name] The name of the file, if any
|
||||
*/
|
||||
class Attachment {
|
||||
constructor(file, name) {
|
||||
this.file = null;
|
||||
if (name) this.setAttachment(file, name);
|
||||
else this._attach(file);
|
||||
}
|
||||
|
||||
/**
|
||||
* The name of the file
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get name() {
|
||||
return this.file.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* The file
|
||||
* @type {?BufferResolvable|Stream}
|
||||
* @readonly
|
||||
*/
|
||||
get attachment() {
|
||||
return this.file.attachment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the file of this attachment.
|
||||
* @param {BufferResolvable|Stream} file The file
|
||||
* @param {string} name The name of the file
|
||||
* @returns {Attachment} This attachment
|
||||
*/
|
||||
setAttachment(file, name) {
|
||||
this.file = { attachment: file, name };
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the file of this attachment.
|
||||
* @param {BufferResolvable|Stream} attachment The file
|
||||
* @returns {Attachment} This attachment
|
||||
*/
|
||||
setFile(attachment) {
|
||||
this.file = { attachment };
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of this attachment.
|
||||
* @param {string} name The name of the image
|
||||
* @returns {Attachment} This attachment
|
||||
*/
|
||||
setName(name) {
|
||||
this.file.name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the file of this attachment.
|
||||
* @param {BufferResolvable|Stream} file The file
|
||||
* @param {string} name The name of the file
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
_attach(file, name) {
|
||||
if (typeof file === 'string') this.file = file;
|
||||
else this.setAttachment(file, name);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Attachment;
|
22
node_modules/discord.js/src/structures/CategoryChannel.js
generated
vendored
Normal file
22
node_modules/discord.js/src/structures/CategoryChannel.js
generated
vendored
Normal file
@ -0,0 +1,22 @@
|
||||
const GuildChannel = require('./GuildChannel');
|
||||
|
||||
/**
|
||||
* Represents a guild category channel on Discord.
|
||||
* @extends {GuildChannel}
|
||||
*/
|
||||
class CategoryChannel extends GuildChannel {
|
||||
constructor(guild, data) {
|
||||
super(guild, data);
|
||||
this.type = 'category';
|
||||
}
|
||||
/**
|
||||
* The channels that are part of this category
|
||||
* @type {?Collection<Snowflake, GuildChannel>}
|
||||
* @readonly
|
||||
*/
|
||||
get children() {
|
||||
return this.guild.channels.filter(c => c.parentID === this.id);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CategoryChannel;
|
76
node_modules/discord.js/src/structures/Channel.js
generated
vendored
Normal file
76
node_modules/discord.js/src/structures/Channel.js
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
|
||||
/**
|
||||
* Represents any channel on Discord.
|
||||
*/
|
||||
class Channel {
|
||||
constructor(client, data) {
|
||||
/**
|
||||
* The client that instantiated the Channel
|
||||
* @name Channel#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
|
||||
/**
|
||||
* The type of the channel, either:
|
||||
* * `dm` - a DM channel
|
||||
* * `group` - a Group DM channel
|
||||
* * `text` - a guild text channel
|
||||
* * `voice` - a guild voice channel
|
||||
* * `category` - a guild category channel
|
||||
* @type {string}
|
||||
*/
|
||||
this.type = null;
|
||||
|
||||
/**
|
||||
* Whether the channel has been deleted
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.deleted = false;
|
||||
|
||||
if (data) this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The unique ID of the channel
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp the channel was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return Snowflake.deconstruct(this.id).timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the channel was created
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the channel.
|
||||
* @returns {Promise<Channel>}
|
||||
* @example
|
||||
* // Delete the channel
|
||||
* channel.delete()
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
delete() {
|
||||
return this.client.rest.methods.deleteChannel(this);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Channel;
|
431
node_modules/discord.js/src/structures/ClientUser.js
generated
vendored
Normal file
431
node_modules/discord.js/src/structures/ClientUser.js
generated
vendored
Normal file
@ -0,0 +1,431 @@
|
||||
const User = require('./User');
|
||||
const Collection = require('../util/Collection');
|
||||
const ClientUserSettings = require('./ClientUserSettings');
|
||||
const ClientUserGuildSettings = require('./ClientUserGuildSettings');
|
||||
const Constants = require('../util/Constants');
|
||||
const util = require('util');
|
||||
|
||||
/**
|
||||
* Represents the logged in client's Discord user.
|
||||
* @extends {User}
|
||||
*/
|
||||
class ClientUser extends User {
|
||||
setup(data) {
|
||||
super.setup(data);
|
||||
|
||||
/**
|
||||
* Whether or not this account has been verified
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.verified = data.verified;
|
||||
|
||||
/**
|
||||
* The email of this account
|
||||
* <warn>This is only filled when using a user account.</warn>
|
||||
* @type {?string}
|
||||
*/
|
||||
this.email = data.email;
|
||||
this.localPresence = {};
|
||||
this._typing = new Map();
|
||||
|
||||
/**
|
||||
* A Collection of friends for the logged in user
|
||||
* <warn>This is only filled when using a user account.</warn>
|
||||
* @type {Collection<Snowflake, User>}
|
||||
*/
|
||||
this.friends = new Collection();
|
||||
|
||||
/**
|
||||
* A Collection of blocked users for the logged in user
|
||||
* <warn>This is only filled when using a user account.</warn>
|
||||
* @type {Collection<Snowflake, User>}
|
||||
*/
|
||||
this.blocked = new Collection();
|
||||
|
||||
/**
|
||||
* A Collection of notes for the logged in user
|
||||
* <warn>This is only filled when using a user account.</warn>
|
||||
* @type {Collection<Snowflake, string>}
|
||||
*/
|
||||
this.notes = new Collection();
|
||||
|
||||
/**
|
||||
* If the user has Discord premium (nitro)
|
||||
* <warn>This is only filled when using a user account.</warn>
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.premium = typeof data.premium === 'boolean' ? data.premium : null;
|
||||
|
||||
/**
|
||||
* If the user has MFA enabled on their account
|
||||
* <warn>This is only filled when using a user account.</warn>
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.mfaEnabled = typeof data.mfa_enabled === 'boolean' ? data.mfa_enabled : null;
|
||||
|
||||
/**
|
||||
* If the user has ever used a mobile device on Discord
|
||||
* <warn>This is only filled when using a user account.</warn>
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.mobile = typeof data.mobile === 'boolean' ? data.mobile : null;
|
||||
|
||||
/**
|
||||
* Various settings for this user
|
||||
* <warn>This is only filled when using a user account.</warn>
|
||||
* @type {?ClientUserSettings}
|
||||
*/
|
||||
this.settings = data.user_settings ? new ClientUserSettings(this, data.user_settings) : null;
|
||||
|
||||
/**
|
||||
* All of the user's guild settings
|
||||
* <warn>This is only filled when using a user account</warn>
|
||||
* @type {Collection<Snowflake, ClientUserGuildSettings>}
|
||||
*/
|
||||
this.guildSettings = new Collection();
|
||||
if (data.user_guild_settings) {
|
||||
for (const settings of data.user_guild_settings) {
|
||||
this.guildSettings.set(settings.guild_id, new ClientUserGuildSettings(settings, this.client));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
edit(data) {
|
||||
return this.client.rest.methods.updateCurrentUser(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the username of the logged in client.
|
||||
* <info>Changing usernames in Discord is heavily rate limited, with only 2 requests
|
||||
* every hour. Use this sparingly!</info>
|
||||
* @param {string} username The new username
|
||||
* @param {string} [password] Current password (only for user accounts)
|
||||
* @returns {Promise<ClientUser>}
|
||||
* @example
|
||||
* // Set username
|
||||
* client.user.setUsername('discordjs')
|
||||
* .then(user => console.log(`My new username is ${user.username}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setUsername(username, password) {
|
||||
return this.client.rest.methods.updateCurrentUser({ username }, password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the email for the client user's account.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @param {string} email New email to change to
|
||||
* @param {string} password Current password
|
||||
* @returns {Promise<ClientUser>}
|
||||
* @example
|
||||
* // Set email
|
||||
* client.user.setEmail('bob@gmail.com', 'some amazing password 123')
|
||||
* .then(user => console.log(`My new email is ${user.email}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setEmail(email, password) {
|
||||
return this.client.rest.methods.updateCurrentUser({ email }, password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the password for the client user's account.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @param {string} newPassword New password to change to
|
||||
* @param {string} oldPassword Current password
|
||||
* @returns {Promise<ClientUser>}
|
||||
* @example
|
||||
* // Set password
|
||||
* client.user.setPassword('some new amazing password 456', 'some amazing password 123')
|
||||
* .then(user => console.log('New password set!'))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setPassword(newPassword, oldPassword) {
|
||||
return this.client.rest.methods.updateCurrentUser({ password: newPassword }, oldPassword);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the avatar of the logged in client.
|
||||
* @param {BufferResolvable|Base64Resolvable} avatar The new avatar
|
||||
* @returns {Promise<ClientUser>}
|
||||
* @example
|
||||
* // Set avatar
|
||||
* client.user.setAvatar('./avatar.png')
|
||||
* .then(user => console.log(`New avatar set!`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setAvatar(avatar) {
|
||||
return this.client.resolver.resolveImage(avatar).then(data =>
|
||||
this.client.rest.methods.updateCurrentUser({ avatar: data })
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data resembling a raw Discord presence.
|
||||
* @typedef {Object} PresenceData
|
||||
* @property {PresenceStatus} [status] Status of the user
|
||||
* @property {boolean} [afk] Whether the user is AFK
|
||||
* @property {Object} [game] Game the user is playing
|
||||
* @property {string} [game.name] Name of the game
|
||||
* @property {string} [game.url] Twitch stream URL
|
||||
* @property {?ActivityType|number} [game.type] Type of the activity
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sets the full presence of the client user.
|
||||
* @param {PresenceData} data Data for the presence
|
||||
* @returns {Promise<ClientUser>}
|
||||
* @example
|
||||
* // Set the client user's presence
|
||||
* client.user.setPresence({ game: { name: 'with discord.js' }, status: 'idle' })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setPresence(data) {
|
||||
// {"op":3,"d":{"status":"dnd","since":0,"game":null,"afk":false}}
|
||||
return new Promise(resolve => {
|
||||
let status = this.localPresence.status || this.presence.status;
|
||||
let game = this.localPresence.game;
|
||||
let afk = this.localPresence.afk || this.presence.afk;
|
||||
|
||||
if (!game && this.presence.game) {
|
||||
game = {
|
||||
name: this.presence.game.name,
|
||||
type: this.presence.game.type,
|
||||
url: this.presence.game.url,
|
||||
};
|
||||
}
|
||||
|
||||
if (data.status) {
|
||||
if (typeof data.status !== 'string') throw new TypeError('Status must be a string');
|
||||
if (this.bot) {
|
||||
status = data.status;
|
||||
} else {
|
||||
this.settings.update(Constants.UserSettingsMap.status, data.status);
|
||||
status = 'invisible';
|
||||
}
|
||||
}
|
||||
|
||||
if (data.game) {
|
||||
game = data.game;
|
||||
game.type = game.url && typeof game.type === 'undefined' ? 1 : game.type || 0;
|
||||
if (typeof game.type === 'string') {
|
||||
game.type = Constants.ActivityTypes.indexOf(game.type.toUpperCase());
|
||||
}
|
||||
} else if (typeof data.game !== 'undefined') {
|
||||
game = null;
|
||||
}
|
||||
|
||||
if (typeof data.afk !== 'undefined') afk = data.afk;
|
||||
afk = Boolean(afk);
|
||||
|
||||
this.localPresence = { status, game, afk };
|
||||
this.localPresence.since = 0;
|
||||
this.localPresence.game = this.localPresence.game || null;
|
||||
|
||||
this.client.ws.send({
|
||||
op: 3,
|
||||
d: this.localPresence,
|
||||
});
|
||||
|
||||
this.client._setPresence(this.id, this.localPresence);
|
||||
|
||||
resolve(this);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* A user's status. Must be one of:
|
||||
* * `online`
|
||||
* * `idle`
|
||||
* * `invisible`
|
||||
* * `dnd` (do not disturb)
|
||||
* @typedef {string} PresenceStatus
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sets the status of the client user.
|
||||
* @param {PresenceStatus} status Status to change to
|
||||
* @returns {Promise<ClientUser>}
|
||||
* @example
|
||||
* // Set the client user's status
|
||||
* client.user.setStatus('idle')
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setStatus(status) {
|
||||
return this.setPresence({ status });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the game the client user is playing.
|
||||
* @param {?string} game Game being played
|
||||
* @param {?string} [streamingURL] Twitch stream URL
|
||||
* @returns {Promise<ClientUser>}
|
||||
* @deprecated
|
||||
*/
|
||||
setGame(game, streamingURL) {
|
||||
if (!game) return this.setPresence({ game: null });
|
||||
return this.setPresence({
|
||||
game: {
|
||||
name: game,
|
||||
url: streamingURL,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the activity the client user is playing.
|
||||
* @param {?string} name Activity being played
|
||||
* @param {Object} [options] Options for setting the activity
|
||||
* @param {string} [options.url] Twitch stream URL
|
||||
* @param {ActivityType|number} [options.type] Type of the activity
|
||||
* @returns {Promise<Presence>}
|
||||
* @example
|
||||
* client.user.setActivity('YouTube', { type: 'WATCHING' })
|
||||
* .then(presence => console.log(`Activity set to ${presence.game ? presence.game.name : 'none'}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setActivity(name, { url, type } = {}) {
|
||||
if (!name) return this.setPresence({ game: null });
|
||||
return this.setPresence({
|
||||
game: { name, type, url },
|
||||
}).then(clientUser => clientUser.presence);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets/removes the AFK flag for the client user.
|
||||
* @param {boolean} afk Whether or not the user is AFK
|
||||
* @returns {Promise<ClientUser>}
|
||||
*/
|
||||
setAFK(afk) {
|
||||
return this.setPresence({ afk });
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches messages that mentioned the client's user.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @param {Object} [options] Options for the fetch
|
||||
* @param {number} [options.limit=25] Maximum number of mentions to retrieve
|
||||
* @param {boolean} [options.roles=true] Whether to include role mentions
|
||||
* @param {boolean} [options.everyone=true] Whether to include everyone/here mentions
|
||||
* @param {GuildResolvable} [options.guild] Limit the search to a specific guild
|
||||
* @returns {Promise<Message[]>}
|
||||
* @example
|
||||
* // Fetch mentions
|
||||
* client.user.fetchMentions()
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch mentions from a guild
|
||||
* client.user.fetchMentions({ guild: '222078108977594368' })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetchMentions(options = {}) {
|
||||
return this.client.rest.methods.fetchMentions(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a friend request.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @param {UserResolvable} user The user to send the friend request to
|
||||
* @returns {Promise<User>} The user the friend request was sent to
|
||||
*/
|
||||
addFriend(user) {
|
||||
user = this.client.resolver.resolveUser(user);
|
||||
return this.client.rest.methods.addFriend(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a friend.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @param {UserResolvable} user The user to remove from your friends
|
||||
* @returns {Promise<User>} The user that was removed
|
||||
*/
|
||||
removeFriend(user) {
|
||||
user = this.client.resolver.resolveUser(user);
|
||||
return this.client.rest.methods.removeFriend(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a guild.
|
||||
* <warn>This is only available to bots in less than 10 guilds and user accounts.</warn>
|
||||
* @param {string} name The name of the guild
|
||||
* @param {string} [region] The region for the server
|
||||
* @param {BufferResolvable|Base64Resolvable} [icon=null] The icon for the guild
|
||||
* @returns {Promise<Guild>} The guild that was created
|
||||
*/
|
||||
createGuild(name, region, icon = null) {
|
||||
if (typeof icon === 'string' && icon.startsWith('data:')) {
|
||||
return this.client.rest.methods.createGuild({ name, icon, region });
|
||||
} else {
|
||||
return this.client.resolver.resolveImage(icon).then(data =>
|
||||
this.client.rest.methods.createGuild({ name, icon: data, region })
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An object containing either a user or access token, and an optional nickname.
|
||||
* @typedef {Object} GroupDMRecipientOptions
|
||||
* @property {UserResolvable|Snowflake} [user] User to add to the Group DM
|
||||
* (only available if a user is creating the DM)
|
||||
* @property {string} [accessToken] Access token to use to add a user to the Group DM
|
||||
* (only available if a bot is creating the DM)
|
||||
* @property {string} [nick] Permanent nickname (only available if a bot is creating the DM)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a Group DM.
|
||||
* @param {GroupDMRecipientOptions[]} recipients The recipients
|
||||
* @returns {Promise<GroupDMChannel>}
|
||||
* @example
|
||||
* // Create a Group DM with a token provided from OAuth
|
||||
* client.user.createGroupDM([{
|
||||
* user: '66564597481480192',
|
||||
* accessToken: token
|
||||
* }])
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
createGroupDM(recipients) {
|
||||
return this.client.rest.methods.createGroupDM({
|
||||
recipients: recipients.map(u => this.client.resolver.resolveUserID(u.user)),
|
||||
accessTokens: recipients.map(u => u.accessToken),
|
||||
nicks: recipients.reduce((o, r) => {
|
||||
if (r.nick) o[r.user ? r.user.id : r.id] = r.nick;
|
||||
return o;
|
||||
}, {}),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts an invite to join a guild.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @param {Invite|string} invite Invite or code to accept
|
||||
* @returns {Promise<Guild>} Joined guild
|
||||
*/
|
||||
acceptInvite(invite) {
|
||||
return this.client.rest.methods.acceptInvite(invite);
|
||||
}
|
||||
}
|
||||
|
||||
ClientUser.prototype.setGame =
|
||||
util.deprecate(ClientUser.prototype.setGame, 'ClientUser#setGame: use ClientUser#setActivity instead');
|
||||
|
||||
ClientUser.prototype.addFriend =
|
||||
util.deprecate(ClientUser.prototype.addFriend, 'ClientUser#addFriend: userbot methods will be removed');
|
||||
|
||||
ClientUser.prototype.removeFriend =
|
||||
util.deprecate(ClientUser.prototype.removeFriend, 'ClientUser#removeFriend: userbot methods will be removed');
|
||||
|
||||
ClientUser.prototype.setPassword =
|
||||
util.deprecate(ClientUser.prototype.setPassword, 'ClientUser#setPassword: userbot methods will be removed');
|
||||
|
||||
ClientUser.prototype.setEmail =
|
||||
util.deprecate(ClientUser.prototype.setEmail, 'ClientUser#setEmail: userbot methods will be removed');
|
||||
|
||||
ClientUser.prototype.fetchMentions =
|
||||
util.deprecate(ClientUser.prototype.fetchMentions, 'ClientUser#fetchMentions: userbot methods will be removed');
|
||||
|
||||
module.exports = ClientUser;
|
30
node_modules/discord.js/src/structures/ClientUserChannelOverride.js
generated
vendored
Normal file
30
node_modules/discord.js/src/structures/ClientUserChannelOverride.js
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
const Constants = require('../util/Constants');
|
||||
|
||||
/**
|
||||
* A wrapper around the ClientUser's channel overrides.
|
||||
*/
|
||||
class ClientUserChannelOverride {
|
||||
constructor(data) {
|
||||
this.patch(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch the data contained in this class with new partial data.
|
||||
* @param {Object} data Data to patch this with
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
patch(data) {
|
||||
for (const key of Object.keys(Constants.UserChannelOverrideMap)) {
|
||||
const value = Constants.UserChannelOverrideMap[key];
|
||||
if (!data.hasOwnProperty(key)) continue;
|
||||
if (typeof value === 'function') {
|
||||
this[value.name] = value(data[key]);
|
||||
} else {
|
||||
this[value] = data[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ClientUserChannelOverride;
|
60
node_modules/discord.js/src/structures/ClientUserGuildSettings.js
generated
vendored
Normal file
60
node_modules/discord.js/src/structures/ClientUserGuildSettings.js
generated
vendored
Normal file
@ -0,0 +1,60 @@
|
||||
const Constants = require('../util/Constants');
|
||||
const Collection = require('../util/Collection');
|
||||
const ClientUserChannelOverride = require('./ClientUserChannelOverride');
|
||||
|
||||
/**
|
||||
* A wrapper around the ClientUser's guild settings.
|
||||
*/
|
||||
class ClientUserGuildSettings {
|
||||
constructor(data, client) {
|
||||
/**
|
||||
* The client that created the instance of the ClientUserGuildSettings
|
||||
* @name ClientUserGuildSettings#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
/**
|
||||
* The ID of the guild this settings are for
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.guildID = data.guild_id;
|
||||
this.channelOverrides = new Collection();
|
||||
this.patch(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch the data contained in this class with new partial data.
|
||||
* @param {Object} data Data to patch this with
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
patch(data) {
|
||||
for (const key of Object.keys(Constants.UserGuildSettingsMap)) {
|
||||
const value = Constants.UserGuildSettingsMap[key];
|
||||
if (!data.hasOwnProperty(key)) continue;
|
||||
if (key === 'channel_overrides') {
|
||||
for (const channel of data[key]) {
|
||||
this.channelOverrides.set(channel.channel_id,
|
||||
new ClientUserChannelOverride(channel));
|
||||
}
|
||||
} else if (typeof value === 'function') {
|
||||
this[value.name] = value(data[key]);
|
||||
} else {
|
||||
this[value] = data[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a specific property of the guild settings.
|
||||
* @param {string} name Name of property
|
||||
* @param {value} value Value to patch
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
update(name, value) {
|
||||
return this.client.rest.methods.patchClientUserGuildSettings(this.guildID, { [name]: value });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ClientUserGuildSettings;
|
80
node_modules/discord.js/src/structures/ClientUserSettings.js
generated
vendored
Normal file
80
node_modules/discord.js/src/structures/ClientUserSettings.js
generated
vendored
Normal file
@ -0,0 +1,80 @@
|
||||
const Constants = require('../util/Constants');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* A wrapper around the ClientUser's settings.
|
||||
*/
|
||||
class ClientUserSettings {
|
||||
constructor(user, data) {
|
||||
this.user = user;
|
||||
this.patch(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch the data contained in this class with new partial data.
|
||||
* @param {Object} data Data to patch this with
|
||||
* @returns {void}
|
||||
* @private
|
||||
*/
|
||||
patch(data) {
|
||||
for (const key of Object.keys(Constants.UserSettingsMap)) {
|
||||
const value = Constants.UserSettingsMap[key];
|
||||
if (!data.hasOwnProperty(key)) continue;
|
||||
if (typeof value === 'function') {
|
||||
this[value.name] = value(data[key]);
|
||||
} else {
|
||||
this[value] = data[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a specific property of of user settings.
|
||||
* @param {string} name Name of property
|
||||
* @param {*} value Value to patch
|
||||
* @returns {Promise<Object>}
|
||||
*/
|
||||
update(name, value) {
|
||||
return this.user.client.rest.methods.patchUserSettings({ [name]: value });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the position at which this guild will appear in the Discord client.
|
||||
* @param {Guild} guild The guild to move
|
||||
* @param {number} position Absolute or relative position
|
||||
* @param {boolean} [relative=false] Whether to position relatively or absolutely
|
||||
* @returns {Promise<Guild>}
|
||||
*/
|
||||
setGuildPosition(guild, position, relative) {
|
||||
const temp = Object.assign([], this.guildPositions);
|
||||
Util.moveElementInArray(temp, guild.id, position, relative);
|
||||
return this.update('guild_positions', temp).then(() => guild);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a guild to the list of restricted guilds.
|
||||
* @param {Guild} guild The guild to add
|
||||
* @returns {Promise<Guild>}
|
||||
*/
|
||||
addRestrictedGuild(guild) {
|
||||
const temp = Object.assign([], this.restrictedGuilds);
|
||||
if (temp.includes(guild.id)) return Promise.reject(new Error('Guild is already restricted'));
|
||||
temp.push(guild.id);
|
||||
return this.update('restricted_guilds', temp).then(() => guild);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a guild from the list of restricted guilds.
|
||||
* @param {Guild} guild The guild to remove
|
||||
* @returns {Promise<Guild>}
|
||||
*/
|
||||
removeRestrictedGuild(guild) {
|
||||
const temp = Object.assign([], this.restrictedGuilds);
|
||||
const index = temp.indexOf(guild.id);
|
||||
if (index < 0) return Promise.reject(new Error('Guild is not restricted'));
|
||||
temp.splice(index, 1);
|
||||
return this.update('restricted_guilds', temp).then(() => guild);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ClientUserSettings;
|
69
node_modules/discord.js/src/structures/DMChannel.js
generated
vendored
Normal file
69
node_modules/discord.js/src/structures/DMChannel.js
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
const Channel = require('./Channel');
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const Collection = require('../util/Collection');
|
||||
|
||||
/**
|
||||
* Represents a direct message channel between two users.
|
||||
* @extends {Channel}
|
||||
* @implements {TextBasedChannel}
|
||||
*/
|
||||
class DMChannel extends Channel {
|
||||
constructor(client, data) {
|
||||
super(client, data);
|
||||
this.type = 'dm';
|
||||
this.messages = new Collection();
|
||||
this._typing = new Map();
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
super.setup(data);
|
||||
|
||||
/**
|
||||
* The recipient on the other end of the DM
|
||||
* @type {User}
|
||||
*/
|
||||
this.recipient = this.client.dataManager.newUser(data.recipients[0]);
|
||||
|
||||
/**
|
||||
* The ID of the last message in the channel, if one was sent
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.lastMessageID = data.last_message_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically concatenates the recipient's mention instead of the
|
||||
* DM channel object.
|
||||
* @returns {string}
|
||||
*/
|
||||
toString() {
|
||||
return this.recipient.toString();
|
||||
}
|
||||
|
||||
// These are here only for documentation purposes - they are implemented by TextBasedChannel
|
||||
/* eslint-disable no-empty-function */
|
||||
send() {}
|
||||
sendMessage() {}
|
||||
sendEmbed() {}
|
||||
sendFile() {}
|
||||
sendFiles() {}
|
||||
sendCode() {}
|
||||
fetchMessage() {}
|
||||
fetchMessages() {}
|
||||
fetchPinnedMessages() {}
|
||||
search() {}
|
||||
startTyping() {}
|
||||
stopTyping() {}
|
||||
get typing() {}
|
||||
get typingCount() {}
|
||||
createCollector() {}
|
||||
createMessageCollector() {}
|
||||
awaitMessages() {}
|
||||
// Doesn't work on DM channels; bulkDelete() {}
|
||||
acknowledge() {}
|
||||
_cacheMessage() {}
|
||||
}
|
||||
|
||||
TextBasedChannel.applyToClass(DMChannel, true, ['bulkDelete']);
|
||||
|
||||
module.exports = DMChannel;
|
251
node_modules/discord.js/src/structures/Emoji.js
generated
vendored
Normal file
251
node_modules/discord.js/src/structures/Emoji.js
generated
vendored
Normal file
@ -0,0 +1,251 @@
|
||||
const Constants = require('../util/Constants');
|
||||
const Collection = require('../util/Collection');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
|
||||
/**
|
||||
* Represents a custom emoji.
|
||||
*/
|
||||
class Emoji {
|
||||
constructor(guild, data) {
|
||||
/**
|
||||
* The client that instantiated this object
|
||||
* @name Emoji#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: guild.client });
|
||||
|
||||
/**
|
||||
* The guild this emoji is part of
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
|
||||
/**
|
||||
* Whether this emoji has been deleted
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.deleted = false;
|
||||
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The ID of the emoji
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The name of the emoji
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* Whether or not this emoji requires colons surrounding it
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.requiresColons = data.require_colons;
|
||||
|
||||
/**
|
||||
* Whether this emoji is managed by an external service
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.managed = data.managed;
|
||||
|
||||
/**
|
||||
* Whether this emoji is animated
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.animated = data.animated;
|
||||
|
||||
this._roles = data.roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp the emoji was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return Snowflake.deconstruct(this.id).timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the emoji was created
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the moej is deletable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get deletable() {
|
||||
return !this.managed && this.guild.me.hasPermission(Permissions.FLAGS.MANAGE_EMOJIS);
|
||||
}
|
||||
|
||||
/**
|
||||
* A collection of roles this emoji is active for (empty if all), mapped by role ID
|
||||
* @type {Collection<Snowflake, Role>}
|
||||
* @readonly
|
||||
*/
|
||||
get roles() {
|
||||
const roles = new Collection();
|
||||
for (const role of this._roles) {
|
||||
if (this.guild.roles.has(role)) roles.set(role, this.guild.roles.get(role));
|
||||
}
|
||||
return roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL to the emoji file
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get url() {
|
||||
return Constants.Endpoints.CDN(this.client.options.http.cdn).Emoji(this.id, this.animated ? 'gif' : 'png');
|
||||
}
|
||||
|
||||
/**
|
||||
* The identifier of this emoji, used for message reactions
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get identifier() {
|
||||
if (this.id) return `${this.name}:${this.id}`;
|
||||
return encodeURIComponent(this.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Data for editing an emoji.
|
||||
* @typedef {Object} EmojiEditData
|
||||
* @property {string} [name] The name of the emoji
|
||||
* @property {Collection<Snowflake, Role>|Array<Snowflake|Role>} [roles] Roles to restrict emoji to
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits the emoji.
|
||||
* @param {EmojiEditData} data The new data for the emoji
|
||||
* @param {string} [reason] Reason for editing this emoji
|
||||
* @returns {Promise<Emoji>}
|
||||
* @example
|
||||
* // Edit an emoji
|
||||
* emoji.edit({name: 'newemoji'})
|
||||
* .then(e => console.log(`Edited emoji ${e}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
edit(data, reason) {
|
||||
return this.client.rest.methods.updateEmoji(this, data, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the emoji.
|
||||
* @param {string} name The new name for the emoji
|
||||
* @param {string} [reason] The reason for changing the emoji's name
|
||||
* @returns {Promise<Emoji>}
|
||||
*/
|
||||
setName(name, reason) {
|
||||
return this.edit({ name }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the author for this emoji
|
||||
* @returns {Promise<User>}
|
||||
*/
|
||||
fetchAuthor() {
|
||||
if (this.managed) return Promise.reject(new Error('Emoji is managed and has no Author.'));
|
||||
return this.client.rest.makeRequest('get', Constants.Endpoints.Guild(this.guild).Emoji(this.id), true)
|
||||
.then(emoji => this.client.dataManager.newUser(emoji.user));
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a role to the list of roles that can use this emoji.
|
||||
* @param {Role} role The role to add
|
||||
* @returns {Promise<Emoji>}
|
||||
*/
|
||||
addRestrictedRole(role) {
|
||||
return this.addRestrictedRoles([role]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add multiple roles to the list of roles that can use this emoji.
|
||||
* @param {Role[]} roles Roles to add
|
||||
* @returns {Promise<Emoji>}
|
||||
*/
|
||||
addRestrictedRoles(roles) {
|
||||
const newRoles = new Collection(this.roles);
|
||||
for (const role of roles) {
|
||||
if (this.guild.roles.has(role.id)) newRoles.set(role.id, role);
|
||||
}
|
||||
return this.edit({ roles: newRoles });
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a role from the list of roles that can use this emoji.
|
||||
* @param {Role} role The role to remove
|
||||
* @returns {Promise<Emoji>}
|
||||
*/
|
||||
removeRestrictedRole(role) {
|
||||
return this.removeRestrictedRoles([role]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove multiple roles from the list of roles that can use this emoji.
|
||||
* @param {Role[]} roles Roles to remove
|
||||
* @returns {Promise<Emoji>}
|
||||
*/
|
||||
removeRestrictedRoles(roles) {
|
||||
const newRoles = new Collection(this.roles);
|
||||
for (const role of roles) {
|
||||
if (newRoles.has(role.id)) newRoles.delete(role.id);
|
||||
}
|
||||
return this.edit({ roles: newRoles });
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically returns the emoji mention rather than the object.
|
||||
* @returns {string}
|
||||
* @example
|
||||
* // Send an emoji:
|
||||
* const emoji = guild.emojis.first();
|
||||
* msg.reply(`Hello! ${emoji}`);
|
||||
*/
|
||||
toString() {
|
||||
if (!this.id || !this.requiresColons) {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
return `<${this.animated ? 'a' : ''}:${this.name}:${this.id}>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this emoji is the same as another one.
|
||||
* @param {Emoji|Object} other The emoji to compare it to
|
||||
* @returns {boolean} Whether the emoji is equal to the given emoji or not
|
||||
*/
|
||||
equals(other) {
|
||||
if (other instanceof Emoji) {
|
||||
return (
|
||||
other.id === this.id &&
|
||||
other.name === this.name &&
|
||||
other.managed === this.managed &&
|
||||
other.requiresColons === this.requiresColons
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
other.id === this.id &&
|
||||
other.name === this.name
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Emoji;
|
239
node_modules/discord.js/src/structures/GroupDMChannel.js
generated
vendored
Normal file
239
node_modules/discord.js/src/structures/GroupDMChannel.js
generated
vendored
Normal file
@ -0,0 +1,239 @@
|
||||
const Channel = require('./Channel');
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const Collection = require('../util/Collection');
|
||||
const Constants = require('../util/Constants');
|
||||
|
||||
/*
|
||||
{ type: 3,
|
||||
recipients:
|
||||
[ { username: 'Charlie',
|
||||
id: '123',
|
||||
discriminator: '6631',
|
||||
avatar: '123' },
|
||||
{ username: 'Ben',
|
||||
id: '123',
|
||||
discriminator: '2055',
|
||||
avatar: '123' },
|
||||
{ username: 'Adam',
|
||||
id: '123',
|
||||
discriminator: '2406',
|
||||
avatar: '123' } ],
|
||||
owner_id: '123',
|
||||
name: null,
|
||||
last_message_id: '123',
|
||||
id: '123',
|
||||
icon: null }
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a Group DM on Discord.
|
||||
* @extends {Channel}
|
||||
* @implements {TextBasedChannel}
|
||||
*/
|
||||
class GroupDMChannel extends Channel {
|
||||
constructor(client, data) {
|
||||
super(client, data);
|
||||
this.type = 'group';
|
||||
this.messages = new Collection();
|
||||
this._typing = new Map();
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
super.setup(data);
|
||||
|
||||
/**
|
||||
* The name of this Group DM, can be null if one isn't set
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* A hash of this Group DM icon
|
||||
* @type {?string}
|
||||
*/
|
||||
this.icon = data.icon;
|
||||
|
||||
/**
|
||||
* The user ID of this Group DM's owner
|
||||
* @type {string}
|
||||
*/
|
||||
this.ownerID = data.owner_id;
|
||||
|
||||
/**
|
||||
* If the DM is managed by an application
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.managed = data.managed;
|
||||
|
||||
/**
|
||||
* Application ID of the application that made this Group DM, if applicable
|
||||
* @type {?string}
|
||||
*/
|
||||
this.applicationID = data.application_id;
|
||||
|
||||
if (data.nicks) {
|
||||
/**
|
||||
* Nicknames for group members
|
||||
* @type {?Collection<Snowflake, string>}
|
||||
*/
|
||||
this.nicks = new Collection(data.nicks.map(n => [n.id, n.nick]));
|
||||
}
|
||||
|
||||
if (!this.recipients) {
|
||||
/**
|
||||
* A collection of the recipients of this DM, mapped by their ID
|
||||
* @type {Collection<Snowflake, User>}
|
||||
*/
|
||||
this.recipients = new Collection();
|
||||
}
|
||||
|
||||
if (data.recipients) {
|
||||
for (const recipient of data.recipients) {
|
||||
const user = this.client.dataManager.newUser(recipient);
|
||||
this.recipients.set(user.id, user);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The ID of the last message in the channel, if one was sent
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.lastMessageID = data.last_message_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* The owner of this Group DM
|
||||
* @type {User}
|
||||
* @readonly
|
||||
*/
|
||||
get owner() {
|
||||
return this.client.users.get(this.ownerID);
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL to this guild's icon
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get iconURL() {
|
||||
if (!this.icon) return null;
|
||||
return Constants.Endpoints.Channel(this).Icon(this.client.options.http.cdn, this.icon);
|
||||
}
|
||||
|
||||
edit(data) {
|
||||
const _data = {};
|
||||
if (data.name) _data.name = data.name;
|
||||
if (typeof data.icon !== 'undefined') _data.icon = data.icon;
|
||||
return this.client.rest.methods.updateGroupDMChannel(this, _data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this channel equals another channel. It compares all properties, so for most operations
|
||||
* it is advisable to just compare `channel.id === channel2.id` as it is much faster and is often
|
||||
* what most users need.
|
||||
* @param {GroupDMChannel} channel Channel to compare with
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(channel) {
|
||||
const equal = channel &&
|
||||
this.id === channel.id &&
|
||||
this.name === channel.name &&
|
||||
this.icon === channel.icon &&
|
||||
this.ownerID === channel.ownerID;
|
||||
|
||||
if (equal) {
|
||||
return this.recipients.equals(channel.recipients);
|
||||
}
|
||||
|
||||
return equal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a user to the DM
|
||||
* @param {UserResolvable|string} accessTokenOrID Access token or user resolvable
|
||||
* @param {string} [nick] Permanent nickname to give the user (only available if a bot is creating the DM)
|
||||
* @returns {Promise<GroupDMChannel>}
|
||||
*/
|
||||
|
||||
addUser(accessTokenOrID, nick) {
|
||||
return this.client.rest.methods.addUserToGroupDM(this, {
|
||||
nick,
|
||||
id: this.client.resolver.resolveUserID(accessTokenOrID),
|
||||
accessToken: accessTokenOrID,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new GroupDMChannel icon.
|
||||
* @param {Base64Resolvable|BufferResolvable} icon The new icon of the group dm
|
||||
* @returns {Promise<GroupDMChannel>}
|
||||
* @example
|
||||
* // Edit the group dm icon
|
||||
* channel.setIcon('./icon.png')
|
||||
* .then(updated => console.log('Updated the channel icon'))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setIcon(icon) {
|
||||
return this.client.resolver.resolveImage(icon).then(data => this.edit({ icon: data }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new name for this Group DM.
|
||||
* @param {string} name New name for this Group DM
|
||||
* @returns {Promise<GroupDMChannel>}
|
||||
*/
|
||||
setName(name) {
|
||||
return this.edit({ name });
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a user from this Group DM.
|
||||
* @param {UserResolvable} user User to remove
|
||||
* @returns {Promise<GroupDMChannel>}
|
||||
*/
|
||||
removeUser(user) {
|
||||
const id = this.client.resolver.resolveUserID(user);
|
||||
return this.client.rest.methods.removeUserFromGroupDM(this, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically concatenates the channel's name instead of the Channel object.
|
||||
* @returns {string}
|
||||
* @example
|
||||
* // Logs: Hello from My Group DM!
|
||||
* console.log(`Hello from ${channel}!`);
|
||||
* @example
|
||||
* // Logs: Hello from My Group DM!
|
||||
* console.log(`Hello from ' + channel + '!');
|
||||
*/
|
||||
toString() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
// These are here only for documentation purposes - they are implemented by TextBasedChannel
|
||||
/* eslint-disable no-empty-function */
|
||||
send() {}
|
||||
sendMessage() {}
|
||||
sendEmbed() {}
|
||||
sendFile() {}
|
||||
sendFiles() {}
|
||||
sendCode() {}
|
||||
fetchMessage() {}
|
||||
fetchMessages() {}
|
||||
fetchPinnedMessages() {}
|
||||
search() {}
|
||||
startTyping() {}
|
||||
stopTyping() {}
|
||||
get typing() {}
|
||||
get typingCount() {}
|
||||
createCollector() {}
|
||||
createMessageCollector() {}
|
||||
awaitMessages() {}
|
||||
// Doesn't work on Group DMs; bulkDelete() {}
|
||||
acknowledge() {}
|
||||
_cacheMessage() {}
|
||||
}
|
||||
|
||||
TextBasedChannel.applyToClass(GroupDMChannel, true, ['bulkDelete']);
|
||||
|
||||
module.exports = GroupDMChannel;
|
1351
node_modules/discord.js/src/structures/Guild.js
generated
vendored
Normal file
1351
node_modules/discord.js/src/structures/Guild.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
371
node_modules/discord.js/src/structures/GuildAuditLogs.js
generated
vendored
Normal file
371
node_modules/discord.js/src/structures/GuildAuditLogs.js
generated
vendored
Normal file
@ -0,0 +1,371 @@
|
||||
const Collection = require('../util/Collection');
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
const Webhook = require('./Webhook');
|
||||
const Invite = require('./Invite');
|
||||
|
||||
/**
|
||||
* The target type of an entry, e.g. `GUILD`. Here are the available types:
|
||||
* * GUILD
|
||||
* * CHANNEL
|
||||
* * USER
|
||||
* * ROLE
|
||||
* * INVITE
|
||||
* * WEBHOOK
|
||||
* * EMOJI
|
||||
* * MESSAGE
|
||||
* @typedef {string} AuditLogTargetType
|
||||
*/
|
||||
|
||||
/**
|
||||
* Key mirror of all available audit log targets.
|
||||
* @name GuildAuditLogs.Targets
|
||||
* @type {AuditLogTargetType}
|
||||
*/
|
||||
const Targets = {
|
||||
ALL: 'ALL',
|
||||
GUILD: 'GUILD',
|
||||
CHANNEL: 'CHANNEL',
|
||||
USER: 'USER',
|
||||
ROLE: 'ROLE',
|
||||
INVITE: 'INVITE',
|
||||
WEBHOOK: 'WEBHOOK',
|
||||
EMOJI: 'EMOJI',
|
||||
MESSAGE: 'MESSAGE',
|
||||
};
|
||||
|
||||
/**
|
||||
* The action of an entry. Here are the available actions:
|
||||
* * ALL: null
|
||||
* * GUILD_UPDATE: 1
|
||||
* * CHANNEL_CREATE: 10
|
||||
* * CHANNEL_UPDATE: 11
|
||||
* * CHANNEL_DELETE: 12
|
||||
* * CHANNEL_OVERWRITE_CREATE: 13
|
||||
* * CHANNEL_OVERWRITE_UPDATE: 14
|
||||
* * CHANNEL_OVERWRITE_DELETE: 15
|
||||
* * MEMBER_KICK: 20
|
||||
* * MEMBER_PRUNE: 21
|
||||
* * MEMBER_BAN_ADD: 22
|
||||
* * MEMBER_BAN_REMOVE: 23
|
||||
* * MEMBER_UPDATE: 24
|
||||
* * MEMBER_ROLE_UPDATE: 25
|
||||
* * ROLE_CREATE: 30
|
||||
* * ROLE_UPDATE: 31
|
||||
* * ROLE_DELETE: 32
|
||||
* * INVITE_CREATE: 40
|
||||
* * INVITE_UPDATE: 41
|
||||
* * INVITE_DELETE: 42
|
||||
* * WEBHOOK_CREATE: 50
|
||||
* * WEBHOOK_UPDATE: 51
|
||||
* * WEBHOOK_DELETE: 52
|
||||
* * EMOJI_CREATE: 60
|
||||
* * EMOJI_UPDATE: 61
|
||||
* * EMOJI_DELETE: 62
|
||||
* * MESSAGE_DELETE: 72
|
||||
* @typedef {?number|string} AuditLogAction
|
||||
*/
|
||||
|
||||
/**
|
||||
* All available actions keyed under their names to their numeric values.
|
||||
* @name GuildAuditLogs.Actions
|
||||
* @type {AuditLogAction}
|
||||
*/
|
||||
const Actions = {
|
||||
ALL: null,
|
||||
GUILD_UPDATE: 1,
|
||||
CHANNEL_CREATE: 10,
|
||||
CHANNEL_UPDATE: 11,
|
||||
CHANNEL_DELETE: 12,
|
||||
CHANNEL_OVERWRITE_CREATE: 13,
|
||||
CHANNEL_OVERWRITE_UPDATE: 14,
|
||||
CHANNEL_OVERWRITE_DELETE: 15,
|
||||
MEMBER_KICK: 20,
|
||||
MEMBER_PRUNE: 21,
|
||||
MEMBER_BAN_ADD: 22,
|
||||
MEMBER_BAN_REMOVE: 23,
|
||||
MEMBER_UPDATE: 24,
|
||||
MEMBER_ROLE_UPDATE: 25,
|
||||
ROLE_CREATE: 30,
|
||||
ROLE_UPDATE: 31,
|
||||
ROLE_DELETE: 32,
|
||||
INVITE_CREATE: 40,
|
||||
INVITE_UPDATE: 41,
|
||||
INVITE_DELETE: 42,
|
||||
WEBHOOK_CREATE: 50,
|
||||
WEBHOOK_UPDATE: 51,
|
||||
WEBHOOK_DELETE: 52,
|
||||
EMOJI_CREATE: 60,
|
||||
EMOJI_UPDATE: 61,
|
||||
EMOJI_DELETE: 62,
|
||||
MESSAGE_DELETE: 72,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Audit logs entries are held in this class.
|
||||
*/
|
||||
class GuildAuditLogs {
|
||||
constructor(guild, data) {
|
||||
if (data.users) for (const user of data.users) guild.client.dataManager.newUser(user);
|
||||
|
||||
/**
|
||||
* Cached webhooks
|
||||
* @type {Collection<Snowflake, Webhook>}
|
||||
* @private
|
||||
*/
|
||||
this.webhooks = new Collection();
|
||||
if (data.webhooks) {
|
||||
for (const hook of data.webhooks) {
|
||||
this.webhooks.set(hook.id, new Webhook(guild.client, hook));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The entries for this guild's audit logs
|
||||
* @type {Collection<Snowflake, GuildAuditLogsEntry>}
|
||||
*/
|
||||
this.entries = new Collection();
|
||||
for (const item of data.audit_log_entries) {
|
||||
const entry = new GuildAuditLogsEntry(this, guild, item);
|
||||
this.entries.set(entry.id, entry);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles possible promises for entry targets.
|
||||
* @returns {Promise<GuildAuditLogs>}
|
||||
*/
|
||||
static build(...args) {
|
||||
const logs = new GuildAuditLogs(...args);
|
||||
return Promise.all(logs.entries.map(e => e.target)).then(() => logs);
|
||||
}
|
||||
|
||||
/**
|
||||
* The target of an entry. It can be one of:
|
||||
* * A guild
|
||||
* * A user
|
||||
* * A role
|
||||
* * An emoji
|
||||
* * An invite
|
||||
* * A webhook
|
||||
* * An object where the keys represent either the new value or the old value
|
||||
* @typedef {?Object|Guild|User|Role|Emoji|Invite|Webhook} AuditLogEntryTarget
|
||||
*/
|
||||
|
||||
/**
|
||||
* Find target type from entry action.
|
||||
* @param {number} target The action target
|
||||
* @returns {?string}
|
||||
*/
|
||||
static targetType(target) {
|
||||
if (target < 10) return Targets.GUILD;
|
||||
if (target < 20) return Targets.CHANNEL;
|
||||
if (target < 30) return Targets.USER;
|
||||
if (target < 40) return Targets.ROLE;
|
||||
if (target < 50) return Targets.INVITE;
|
||||
if (target < 60) return Targets.WEBHOOK;
|
||||
if (target < 70) return Targets.EMOJI;
|
||||
if (target < 80) return Targets.MESSAGE;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The action type of an entry, e.g. `CREATE`. Here are the available types:
|
||||
* * CREATE
|
||||
* * DELETE
|
||||
* * UPDATE
|
||||
* * ALL
|
||||
* @typedef {string} AuditLogActionType
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Finds the action type from the entry action.
|
||||
* @param {AuditLogAction} action The action target
|
||||
* @returns {AuditLogActionType}
|
||||
*/
|
||||
static actionType(action) {
|
||||
if ([
|
||||
Actions.CHANNEL_CREATE,
|
||||
Actions.CHANNEL_OVERWRITE_CREATE,
|
||||
Actions.MEMBER_BAN_REMOVE,
|
||||
Actions.ROLE_CREATE,
|
||||
Actions.INVITE_CREATE,
|
||||
Actions.WEBHOOK_CREATE,
|
||||
Actions.EMOJI_CREATE,
|
||||
].includes(action)) return 'CREATE';
|
||||
|
||||
if ([
|
||||
Actions.CHANNEL_DELETE,
|
||||
Actions.CHANNEL_OVERWRITE_DELETE,
|
||||
Actions.MEMBER_KICK,
|
||||
Actions.MEMBER_PRUNE,
|
||||
Actions.MEMBER_BAN_ADD,
|
||||
Actions.ROLE_DELETE,
|
||||
Actions.INVITE_DELETE,
|
||||
Actions.WEBHOOK_DELETE,
|
||||
Actions.EMOJI_DELETE,
|
||||
Actions.MESSAGE_DELETE,
|
||||
].includes(action)) return 'DELETE';
|
||||
|
||||
if ([
|
||||
Actions.GUILD_UPDATE,
|
||||
Actions.CHANNEL_UPDATE,
|
||||
Actions.CHANNEL_OVERWRITE_UPDATE,
|
||||
Actions.MEMBER_UPDATE,
|
||||
Actions.MEMBER_ROLE_UPDATE,
|
||||
Actions.ROLE_UPDATE,
|
||||
Actions.INVITE_UPDATE,
|
||||
Actions.WEBHOOK_UPDATE,
|
||||
Actions.EMOJI_UPDATE,
|
||||
].includes(action)) return 'UPDATE';
|
||||
|
||||
return 'ALL';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Audit logs entry.
|
||||
*/
|
||||
class GuildAuditLogsEntry {
|
||||
constructor(logs, guild, data) {
|
||||
const targetType = GuildAuditLogs.targetType(data.action_type);
|
||||
/**
|
||||
* The target type of this entry
|
||||
* @type {AuditLogTargetType}
|
||||
*/
|
||||
this.targetType = targetType;
|
||||
|
||||
/**
|
||||
* The action type of this entry
|
||||
* @type {AuditLogActionType}
|
||||
*/
|
||||
this.actionType = GuildAuditLogs.actionType(data.action_type);
|
||||
|
||||
/**
|
||||
* Specific action type of this entry in its string representation
|
||||
* @type {AuditLogAction}
|
||||
*/
|
||||
this.action = Object.keys(Actions).find(k => Actions[k] === data.action_type);
|
||||
|
||||
/**
|
||||
* The reason of this entry
|
||||
* @type {?string}
|
||||
*/
|
||||
this.reason = data.reason || null;
|
||||
|
||||
/**
|
||||
* The user that executed this entry
|
||||
* @type {User}
|
||||
*/
|
||||
this.executor = guild.client.users.get(data.user_id);
|
||||
|
||||
/**
|
||||
* An entry in the audit log representing a specific change.
|
||||
* @typedef {object} AuditLogChange
|
||||
* @property {string} key The property that was changed, e.g. `nick` for nickname changes
|
||||
* @property {*} [old] The old value of the change, e.g. for nicknames, the old nickname
|
||||
* @property {*} [new] The new value of the change, e.g. for nicknames, the new nickname
|
||||
*/
|
||||
|
||||
/**
|
||||
* Specific property changes
|
||||
* @type {AuditLogChange[]}
|
||||
*/
|
||||
this.changes = data.changes ? data.changes.map(c => ({ key: c.key, old: c.old_value, new: c.new_value })) : null;
|
||||
|
||||
/**
|
||||
* The ID of this entry
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* Any extra data from the entry
|
||||
* @type {?Object|Role|GuildMember}
|
||||
*/
|
||||
this.extra = null;
|
||||
if (data.options) {
|
||||
if (data.action_type === Actions.MEMBER_PRUNE) {
|
||||
this.extra = {
|
||||
removed: data.options.members_removed,
|
||||
days: data.options.delete_member_days,
|
||||
};
|
||||
} else if (data.action_type === Actions.MESSAGE_DELETE) {
|
||||
this.extra = {
|
||||
count: data.options.count,
|
||||
channel: guild.channels.get(data.options.channel_id),
|
||||
};
|
||||
} else {
|
||||
switch (data.options.type) {
|
||||
case 'member':
|
||||
this.extra = guild.members.get(data.options.id);
|
||||
if (!this.extra) this.extra = { id: data.options.id };
|
||||
break;
|
||||
case 'role':
|
||||
this.extra = guild.roles.get(data.options.id);
|
||||
if (!this.extra) this.extra = { id: data.options.id, name: data.options.role_name };
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ([Targets.USER, Targets.GUILD].includes(targetType)) {
|
||||
/**
|
||||
* The target of this entry
|
||||
* @type {AuditLogEntryTarget}
|
||||
*/
|
||||
this.target = guild.client[`${targetType.toLowerCase()}s`].get(data.target_id);
|
||||
} else if (targetType === Targets.WEBHOOK) {
|
||||
this.target = logs.webhooks.get(data.target_id) ||
|
||||
new Webhook(guild.client,
|
||||
this.changes.reduce((o, c) => {
|
||||
o[c.key] = c.new || c.old;
|
||||
return o;
|
||||
}, {
|
||||
id: data.target_id,
|
||||
guild_id: guild.id,
|
||||
}));
|
||||
} else if (targetType === Targets.INVITE) {
|
||||
const changes = this.changes.reduce((o, c) => {
|
||||
o[c.key] = c.new || c.old;
|
||||
return o;
|
||||
}, {
|
||||
id: data.target_id,
|
||||
guild,
|
||||
});
|
||||
changes.channel = { id: changes.channel_id };
|
||||
this.target = new Invite(guild.client, changes);
|
||||
} else if (targetType === Targets.MESSAGE) {
|
||||
this.target = guild.client.users.get(data.target_id);
|
||||
} else {
|
||||
this.target = guild[`${targetType.toLowerCase()}s`].get(data.target_id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp this entry was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return Snowflake.deconstruct(this.id).timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* The time this entry was created
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
}
|
||||
|
||||
GuildAuditLogs.Actions = Actions;
|
||||
GuildAuditLogs.Targets = Targets;
|
||||
GuildAuditLogs.Entry = GuildAuditLogsEntry;
|
||||
|
||||
module.exports = GuildAuditLogs;
|
529
node_modules/discord.js/src/structures/GuildChannel.js
generated
vendored
Normal file
529
node_modules/discord.js/src/structures/GuildChannel.js
generated
vendored
Normal file
@ -0,0 +1,529 @@
|
||||
const Channel = require('./Channel');
|
||||
const Role = require('./Role');
|
||||
const PermissionOverwrites = require('./PermissionOverwrites');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const Collection = require('../util/Collection');
|
||||
const Constants = require('../util/Constants');
|
||||
const Invite = require('./Invite');
|
||||
|
||||
/**
|
||||
* Represents a guild channel (i.e. text channels and voice channels).
|
||||
* @extends {Channel}
|
||||
*/
|
||||
class GuildChannel extends Channel {
|
||||
constructor(guild, data) {
|
||||
super(guild.client, data);
|
||||
|
||||
/**
|
||||
* The guild the channel is in
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
super.setup(data);
|
||||
|
||||
/**
|
||||
* The name of the guild channel
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* The position of the channel in the list
|
||||
* @type {number}
|
||||
*/
|
||||
this.position = data.position;
|
||||
|
||||
/**
|
||||
* The ID of the category parent of this channel
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.parentID = data.parent_id;
|
||||
|
||||
/**
|
||||
* A map of permission overwrites in this channel for roles and users
|
||||
* @type {Collection<Snowflake, PermissionOverwrites>}
|
||||
*/
|
||||
this.permissionOverwrites = new Collection();
|
||||
if (data.permission_overwrites) {
|
||||
for (const overwrite of data.permission_overwrites) {
|
||||
this.permissionOverwrites.set(overwrite.id, new PermissionOverwrites(this, overwrite));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The position of the channel
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get calculatedPosition() {
|
||||
const sorted = this.guild._sortedChannels(this.type);
|
||||
return sorted.array().indexOf(sorted.get(this.id));
|
||||
}
|
||||
|
||||
/**
|
||||
* The category parent of this channel
|
||||
* @type {?CategoryChannel}
|
||||
* @readonly
|
||||
*/
|
||||
get parent() {
|
||||
return this.guild.channels.get(this.parentID) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the overall set of permissions for a user in this channel, taking into account channel overwrites.
|
||||
* @param {GuildMemberResolvable} member The user that you want to obtain the overall permissions for
|
||||
* @returns {?Permissions}
|
||||
*/
|
||||
memberPermissions(member) {
|
||||
member = this.client.resolver.resolveGuildMember(this.guild, member);
|
||||
if (!member) return null;
|
||||
|
||||
if (member.id === this.guild.ownerID) return new Permissions(member, Permissions.ALL);
|
||||
|
||||
const roles = member.roles;
|
||||
const permissions = new Permissions(roles.map(role => role.permissions));
|
||||
|
||||
if (permissions.has(Permissions.FLAGS.ADMINISTRATOR)) return new Permissions(Permissions.ALL).freeze();
|
||||
|
||||
const overwrites = this.overwritesFor(member, true, roles);
|
||||
|
||||
return permissions
|
||||
.remove(overwrites.everyone ? overwrites.everyone.deny : 0)
|
||||
.add(overwrites.everyone ? overwrites.everyone.allow : 0)
|
||||
.remove(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.deny) : 0)
|
||||
.add(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.allow) : 0)
|
||||
.remove(overwrites.member ? overwrites.member.deny : 0)
|
||||
.add(overwrites.member ? overwrites.member.allow : 0)
|
||||
.freeze();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the overall set of permissions for a role in this channel, taking into account channel overwrites.
|
||||
* @param {RoleResolvable} role The role that you want to obtain the overall permissions for
|
||||
* @returns {?Permissions}
|
||||
*/
|
||||
rolePermissions(role) {
|
||||
if (role.permissions & Permissions.FLAGS.ADMINISTRATOR) return new Permissions(Permissions.ALL).freeze();
|
||||
|
||||
const everyoneOverwrites = this.permissionOverwrites.get(this.guild.id);
|
||||
const roleOverwrites = this.permissionOverwrites.get(role.id);
|
||||
|
||||
return new Permissions(role.permissions)
|
||||
.remove(everyoneOverwrites ? everyoneOverwrites.deny : 0)
|
||||
.add(everyoneOverwrites ? everyoneOverwrites.allow : 0)
|
||||
.remove(roleOverwrites ? roleOverwrites.deny : 0)
|
||||
.add(roleOverwrites ? roleOverwrites.allow : 0)
|
||||
.freeze();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the overall set of permissions for a member or role in this channel, taking into account channel overwrites.
|
||||
* @param {GuildMemberResolvable|RoleResolvable} memberOrRole The member or role to obtain the overall permissions for
|
||||
* @returns {?Permissions}
|
||||
*/
|
||||
permissionsFor(memberOrRole) {
|
||||
const member = this.guild.member(memberOrRole);
|
||||
if (member) return this.memberPermissions(member);
|
||||
const role = this.client.resolver.resolveRole(this.guild, memberOrRole);
|
||||
if (role) return this.rolePermissions(role);
|
||||
return null;
|
||||
}
|
||||
|
||||
overwritesFor(member, verified = false, roles = null) {
|
||||
if (!verified) member = this.client.resolver.resolveGuildMember(this.guild, member);
|
||||
if (!member) return [];
|
||||
|
||||
roles = roles || member.roles;
|
||||
const roleOverwrites = [];
|
||||
let memberOverwrites;
|
||||
let everyoneOverwrites;
|
||||
|
||||
for (const overwrite of this.permissionOverwrites.values()) {
|
||||
if (overwrite.id === this.guild.id) {
|
||||
everyoneOverwrites = overwrite;
|
||||
} else if (roles.has(overwrite.id)) {
|
||||
roleOverwrites.push(overwrite);
|
||||
} else if (overwrite.id === member.id) {
|
||||
memberOverwrites = overwrite;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
everyone: everyoneOverwrites,
|
||||
roles: roleOverwrites,
|
||||
member: memberOverwrites,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the permission overwrites for a channel
|
||||
* @param {Object} [options] Options
|
||||
* @param {ChannelCreationOverwrites[]|Collection<Snowflake, PermissionOverwrites>} [options.overwrites]
|
||||
* Permission overwrites
|
||||
* @param {string} [options.reason] Reason for updating the channel overwrites
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* channel.replacePermissionOverwrites({
|
||||
* overwrites: [
|
||||
* {
|
||||
* id: message.author.id,
|
||||
* denied: ['VIEW_CHANNEL'],
|
||||
* },
|
||||
* ],
|
||||
* reason: 'Needed to change permissions'
|
||||
* });
|
||||
*/
|
||||
replacePermissionOverwrites({ overwrites, reason } = {}) {
|
||||
return this.edit({ permissionOverwrites: overwrites, reason })
|
||||
.then(() => this);
|
||||
}
|
||||
|
||||
/**
|
||||
* An object mapping permission flags to `true` (enabled), `null` (unset) or `false` (disabled).
|
||||
* ```js
|
||||
* {
|
||||
* 'SEND_MESSAGES': true,
|
||||
* 'EMBED_LINKS': null,
|
||||
* 'ATTACH_FILES': false,
|
||||
* }
|
||||
* ```
|
||||
* @typedef {Object} PermissionOverwriteOptions
|
||||
*/
|
||||
|
||||
/**
|
||||
* Overwrites the permissions for a user or role in this channel.
|
||||
* @param {Role|Snowflake|UserResolvable} userOrRole The user or role to update
|
||||
* @param {PermissionOverwriteOptions} options The configuration for the update
|
||||
* @param {string} [reason] Reason for creating/editing this overwrite
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Overwrite permissions for a message author
|
||||
* message.channel.overwritePermissions(message.author, {
|
||||
* SEND_MESSAGES: false
|
||||
* })
|
||||
* .then(updated => console.log(updated.permissionOverwrites.get(message.author.id)))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Overwite permissions for a message author and reset some
|
||||
* message.channel.overwritePermissions(message.author, {
|
||||
* VIEW_CHANNEL: false,
|
||||
* SEND_MESSAGES: null
|
||||
* })
|
||||
* .then(updated => console.log(updated.permissionOverwrites.get(message.author.id)))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
overwritePermissions(userOrRole, options, reason) {
|
||||
const payload = {
|
||||
allow: 0,
|
||||
deny: 0,
|
||||
};
|
||||
|
||||
if (userOrRole instanceof Role) {
|
||||
payload.type = 'role';
|
||||
} else if (this.guild.roles.has(userOrRole)) {
|
||||
userOrRole = this.guild.roles.get(userOrRole);
|
||||
payload.type = 'role';
|
||||
} else {
|
||||
userOrRole = this.client.resolver.resolveUser(userOrRole);
|
||||
payload.type = 'member';
|
||||
if (!userOrRole) return Promise.reject(new TypeError('Supplied parameter was neither a User nor a Role.'));
|
||||
}
|
||||
|
||||
payload.id = userOrRole.id;
|
||||
|
||||
const prevOverwrite = this.permissionOverwrites.get(userOrRole.id);
|
||||
|
||||
if (prevOverwrite) {
|
||||
payload.allow = prevOverwrite.allow;
|
||||
payload.deny = prevOverwrite.deny;
|
||||
}
|
||||
|
||||
for (const perm in options) {
|
||||
if (options[perm] === true) {
|
||||
payload.allow |= Permissions.FLAGS[perm] || 0;
|
||||
payload.deny &= ~(Permissions.FLAGS[perm] || 0);
|
||||
} else if (options[perm] === false) {
|
||||
payload.allow &= ~(Permissions.FLAGS[perm] || 0);
|
||||
payload.deny |= Permissions.FLAGS[perm] || 0;
|
||||
} else if (options[perm] === null) {
|
||||
payload.allow &= ~(Permissions.FLAGS[perm] || 0);
|
||||
payload.deny &= ~(Permissions.FLAGS[perm] || 0);
|
||||
}
|
||||
}
|
||||
|
||||
return this.client.rest.methods.setChannelOverwrite(this, payload, reason).then(() => this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Locks in the permission overwrites from the parent channel.
|
||||
* @returns {Promise<GuildChannel>}
|
||||
*/
|
||||
lockPermissions() {
|
||||
if (!this.parent) return Promise.reject(new TypeError('Could not find a parent to this guild channel.'));
|
||||
const permissionOverwrites = this.parent.permissionOverwrites.map(overwrite => ({
|
||||
deny: overwrite.deny.bitfield,
|
||||
allow: overwrite.allow.bitfield,
|
||||
id: overwrite.id,
|
||||
type: overwrite.type,
|
||||
}));
|
||||
return this.edit({ permissionOverwrites });
|
||||
}
|
||||
|
||||
/**
|
||||
* The data for a guild channel.
|
||||
* @typedef {Object} ChannelData
|
||||
* @property {string} [name] The name of the channel
|
||||
* @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 channel
|
||||
* @property {string} [parent] The parent ID of the channel
|
||||
* @property {ChannelCreationOverwrites[]|Collection<Snowflake, PermissionOverwrites>} [overwrites]
|
||||
* Overwrites of the channel
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits the channel.
|
||||
* @param {ChannelData} data The new data for the channel
|
||||
* @param {string} [reason] Reason for editing this channel
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Edit a channel
|
||||
* channel.edit({ name: 'new-channel' })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
edit(data, reason) {
|
||||
return this.client.rest.methods.updateChannel(this, data, reason).then(() => this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new name for the guild channel.
|
||||
* @param {string} name The new name for the guild channel
|
||||
* @param {string} [reason] Reason for changing the guild channel's name
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Set a new channel name
|
||||
* channel.setName('not_general')
|
||||
* .then(newChannel => console.log(`Channel's new name is ${newChannel.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setName(name, reason) {
|
||||
return this.edit({ name }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new position for the guild channel.
|
||||
* @param {number} position The new position for the guild channel
|
||||
* @param {boolean} [relative=false] Move the position relative to its current value
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Set a new channel position
|
||||
* channel.setPosition(2)
|
||||
* .then(newChannel => console.log(`Channel's new position is ${newChannel.position}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setPosition(position, relative) {
|
||||
return this.guild.setChannelPosition(this, position, relative);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new parent for the guild channel.
|
||||
* @param {CategoryChannel|SnowFlake} parent The new parent for the guild channel
|
||||
* @param {string} [reason] Reason for changing the guild channel's parent
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Sets the parent of a channel
|
||||
* channel.setParent('174674066072928256')
|
||||
* .then(updated => console.log(`Set the category of ${updated.name} to ${updated.parent.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setParent(parent, reason) {
|
||||
parent = this.client.resolver.resolveChannelID(parent);
|
||||
return this.edit({ parent }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new topic for the guild channel.
|
||||
* @param {string} topic The new topic for the guild channel
|
||||
* @param {string} [reason] Reason for changing the guild channel's topic
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Set a new channel topic
|
||||
* channel.setTopic('Needs more rate limiting')
|
||||
* .then(updated => console.log(`Channel's new topic is ${updated.topic}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setTopic(topic, reason) {
|
||||
return this.edit({ topic }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an invite to this guild channel.
|
||||
* <warn>This is only available when using a bot account.</warn>
|
||||
* @param {Object} [options={}] Options for the invite
|
||||
* @param {boolean} [options.temporary=false] Whether members that joined via the invite should be automatically
|
||||
* kicked after 24 hours if they have not yet received a role
|
||||
* @param {number} [options.maxAge=86400] How long the invite should last (in seconds, 0 for forever)
|
||||
* @param {number} [options.maxUses=0] Maximum number of uses
|
||||
* @param {boolean} [options.unique=false] Create a unique invite, or use an existing one with similar settings
|
||||
* @param {string} [reason] Reason for creating the invite
|
||||
* @returns {Promise<Invite>}
|
||||
* @example
|
||||
* // Create an invite to a channel
|
||||
* channel.createInvite()
|
||||
* .then(invite => console.log(`Created an invite with a code of ${invite.code}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
createInvite(options = {}, reason) {
|
||||
return this.client.rest.methods.createChannelInvite(this, options, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this channel.
|
||||
* @param {string} [name=this.name] Optional name for the new channel, otherwise it has the name of this channel
|
||||
* @param {boolean} [withPermissions=true] Whether to clone the channel with this channel's permission overwrites
|
||||
* @param {boolean} [withTopic=true] Whether to clone the channel with this channel's topic
|
||||
* @param {string} [reason] Reason for cloning this channel
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Clone a channel
|
||||
* channel.clone(undefined, true, false, 'Needed a clone')
|
||||
* .then(clone => console.log(`Cloned ${channel.name} to make a channel called ${clone.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
clone(name = this.name, withPermissions = true, withTopic = true, reason) {
|
||||
return this.guild.createChannel(name, this.type, withPermissions ? this.permissionOverwrites : [], reason)
|
||||
.then(channel => withTopic ? channel.setTopic(this.topic) : channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a collection of invites to this guild channel.
|
||||
* Resolves with a collection mapping invites by their codes.
|
||||
* @returns {Promise<Collection<string, Invite>>}
|
||||
*/
|
||||
fetchInvites() {
|
||||
return this.client.rest.makeRequest('get', Constants.Endpoints.Channel(this.id).invites, true)
|
||||
.then(data => {
|
||||
const invites = new Collection();
|
||||
for (let invite of data) {
|
||||
invite = new Invite(this.client, invite);
|
||||
invites.set(invite.code, invite);
|
||||
}
|
||||
|
||||
return invites;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this channel.
|
||||
* @param {string} [reason] Reason for deleting this channel
|
||||
* @returns {Promise<GuildChannel>}
|
||||
* @example
|
||||
* // Delete the channel
|
||||
* channel.delete('Making room for new channels')
|
||||
* .then(deleted => console.log(`Deleted ${deleted.name} to make room for new channels`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
delete(reason) {
|
||||
return this.client.rest.methods.deleteChannel(this, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this channel has the same type, topic, position, name, overwrites and ID as another channel.
|
||||
* In most cases, a simple `channel.id === channel2.id` will do, and is much faster too.
|
||||
* @param {GuildChannel} channel Channel to compare with
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(channel) {
|
||||
let equal = channel &&
|
||||
this.id === channel.id &&
|
||||
this.type === channel.type &&
|
||||
this.topic === channel.topic &&
|
||||
this.position === channel.position &&
|
||||
this.name === channel.name;
|
||||
|
||||
if (equal) {
|
||||
if (this.permissionOverwrites && channel.permissionOverwrites) {
|
||||
equal = this.permissionOverwrites.equals(channel.permissionOverwrites);
|
||||
} else {
|
||||
equal = !this.permissionOverwrites && !channel.permissionOverwrites;
|
||||
}
|
||||
}
|
||||
|
||||
return equal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the channel is deletable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get deletable() {
|
||||
return this.id !== this.guild.id &&
|
||||
this.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_CHANNELS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the channel is manageable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get manageable() {
|
||||
if (this.client.user.id === this.guild.ownerID) return true;
|
||||
const permissions = this.permissionsFor(this.client.user);
|
||||
if (!permissions) return false;
|
||||
return permissions.has([Permissions.FLAGS.MANAGE_CHANNELS, Permissions.FLAGS.VIEW_CHANNEL]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the channel is muted
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @type {?boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get muted() {
|
||||
if (this.client.user.bot) return null;
|
||||
try {
|
||||
return this.client.user.guildSettings.get(this.guild.id).channelOverrides.get(this.id).muted;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of message that should notify you
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @type {?MessageNotificationType}
|
||||
* @readonly
|
||||
*/
|
||||
get messageNotifications() {
|
||||
if (this.client.user.bot) return null;
|
||||
try {
|
||||
return this.client.user.guildSettings.get(this.guild.id).channelOverrides.get(this.id).messageNotifications;
|
||||
} catch (err) {
|
||||
return Constants.MessageNotificationTypes[3];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically returns the channel's mention instead of the Channel object.
|
||||
* @returns {string}
|
||||
* @example
|
||||
* // Logs: Hello from <#123456789012345678>
|
||||
* console.log(`Hello from ${channel}`);
|
||||
* @example
|
||||
* // Logs: Hello from <#123456789012345678>
|
||||
* console.log('Hello from ' + channel);
|
||||
*/
|
||||
toString() {
|
||||
return `<#${this.id}>`;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildChannel;
|
609
node_modules/discord.js/src/structures/GuildMember.js
generated
vendored
Normal file
609
node_modules/discord.js/src/structures/GuildMember.js
generated
vendored
Normal file
@ -0,0 +1,609 @@
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const Role = require('./Role');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const Collection = require('../util/Collection');
|
||||
const { Presence } = require('./Presence');
|
||||
const util = require('util');
|
||||
|
||||
/**
|
||||
* Represents a member of a guild on Discord.
|
||||
* @implements {TextBasedChannel}
|
||||
*/
|
||||
class GuildMember {
|
||||
constructor(guild, data) {
|
||||
/**
|
||||
* The client that instantiated this GuildMember
|
||||
* @name GuildMember#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: guild.client });
|
||||
|
||||
/**
|
||||
* The guild that this member is part of
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
|
||||
/**
|
||||
* The user that this member instance Represents
|
||||
* @type {User}
|
||||
*/
|
||||
this.user = {};
|
||||
|
||||
/**
|
||||
* The timestamp this member joined the guild at
|
||||
* @type {number}
|
||||
*/
|
||||
this.joinedTimestamp = null;
|
||||
|
||||
this._roles = [];
|
||||
if (data) this.setup(data);
|
||||
|
||||
/**
|
||||
* The ID of the last message sent by this member in their guild, if one was sent
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.lastMessageID = null;
|
||||
|
||||
/**
|
||||
* The Message object of the last message sent by this member in their guild, if one was sent
|
||||
* @type {?Message}
|
||||
*/
|
||||
this.lastMessage = null;
|
||||
|
||||
/**
|
||||
* Whether the member has been removed from the guild
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.deleted = false;
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* Whether this member is deafened server-wide
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.serverDeaf = data.deaf;
|
||||
|
||||
/**
|
||||
* Whether this member is muted server-wide
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.serverMute = data.mute;
|
||||
|
||||
/**
|
||||
* Whether this member is self-muted
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.selfMute = data.self_mute;
|
||||
|
||||
/**
|
||||
* Whether this member is self-deafened
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.selfDeaf = data.self_deaf;
|
||||
|
||||
/**
|
||||
* The voice session ID of this member, if any
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.voiceSessionID = data.session_id;
|
||||
|
||||
/**
|
||||
* The voice channel ID of this member, if any
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.voiceChannelID = data.channel_id;
|
||||
|
||||
/**
|
||||
* Whether this member is speaking and the client is in the same channel
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.speaking = false;
|
||||
|
||||
/**
|
||||
* The nickname of this member, if they have one
|
||||
* @type {?string}
|
||||
*/
|
||||
this.nickname = data.nick || null;
|
||||
|
||||
if (data.joined_at) this.joinedTimestamp = new Date(data.joined_at).getTime();
|
||||
|
||||
this.user = data.user;
|
||||
this._roles = data.roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* The time this member joined the guild
|
||||
* @type {?Date}
|
||||
* @readonly
|
||||
*/
|
||||
get joinedAt() {
|
||||
return this.joinedTimestamp ? new Date(this.joinedTimestamp) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The presence of this member
|
||||
* @type {Presence}
|
||||
* @readonly
|
||||
*/
|
||||
get presence() {
|
||||
return this.frozenPresence || this.guild.presences.get(this.id) || new Presence(undefined, this.client);
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of roles that are applied to this member, mapped by the role ID
|
||||
* @type {Collection<Snowflake, Role>}
|
||||
* @readonly
|
||||
*/
|
||||
get roles() {
|
||||
const list = new Collection();
|
||||
const everyoneRole = this.guild.roles.get(this.guild.id);
|
||||
|
||||
if (everyoneRole) list.set(everyoneRole.id, everyoneRole);
|
||||
|
||||
for (const roleID of this._roles) {
|
||||
const role = this.guild.roles.get(roleID);
|
||||
if (role) list.set(role.id, role);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* The role of this member with the highest position
|
||||
* @type {Role}
|
||||
* @readonly
|
||||
*/
|
||||
get highestRole() {
|
||||
return this.roles.reduce((prev, role) => !prev || role.comparePositionTo(prev) > 0 ? role : prev);
|
||||
}
|
||||
|
||||
/**
|
||||
* The role of this member used to set their color
|
||||
* @type {?Role}
|
||||
* @readonly
|
||||
*/
|
||||
get colorRole() {
|
||||
const coloredRoles = this.roles.filter(role => role.color);
|
||||
if (!coloredRoles.size) return null;
|
||||
return coloredRoles.reduce((prev, role) => !prev || role.comparePositionTo(prev) > 0 ? role : prev);
|
||||
}
|
||||
|
||||
/**
|
||||
* The displayed color of this member in base 10
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get displayColor() {
|
||||
const role = this.colorRole;
|
||||
return (role && role.color) || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The displayed color of this member in hexadecimal
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get displayHexColor() {
|
||||
const role = this.colorRole;
|
||||
return (role && role.hexColor) || '#000000';
|
||||
}
|
||||
|
||||
/**
|
||||
* The role of this member used to hoist them in a separate category in the users list
|
||||
* @type {?Role}
|
||||
* @readonly
|
||||
*/
|
||||
get hoistRole() {
|
||||
const hoistedRoles = this.roles.filter(role => role.hoist);
|
||||
if (!hoistedRoles.size) return null;
|
||||
return hoistedRoles.reduce((prev, role) => !prev || role.comparePositionTo(prev) > 0 ? role : prev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this member is muted in any way
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get mute() {
|
||||
return this.selfMute || this.serverMute;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this member is deafened in any way
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get deaf() {
|
||||
return this.selfDeaf || this.serverDeaf;
|
||||
}
|
||||
|
||||
/**
|
||||
* The voice channel this member is in, if any
|
||||
* @type {?VoiceChannel}
|
||||
* @readonly
|
||||
*/
|
||||
get voiceChannel() {
|
||||
return this.guild.channels.get(this.voiceChannelID);
|
||||
}
|
||||
|
||||
/**
|
||||
* The ID of this user
|
||||
* @type {Snowflake}
|
||||
* @readonly
|
||||
*/
|
||||
get id() {
|
||||
return this.user.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* The nickname of this member, or their username if they don't have one
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get displayName() {
|
||||
return this.nickname || this.user.username;
|
||||
}
|
||||
|
||||
/**
|
||||
* The overall set of permissions for this member, taking only roles into account
|
||||
* @type {Permissions}
|
||||
* @readonly
|
||||
*/
|
||||
get permissions() {
|
||||
if (this.user.id === this.guild.ownerID) return new Permissions(this, Permissions.ALL);
|
||||
|
||||
let permissions = 0;
|
||||
const roles = this.roles;
|
||||
for (const role of roles.values()) permissions |= role.permissions;
|
||||
|
||||
return new Permissions(this, permissions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this member is manageable in terms of role hierarchy by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get manageable() {
|
||||
if (this.user.id === this.guild.ownerID) return false;
|
||||
if (this.user.id === this.client.user.id) return false;
|
||||
return this.guild.me.highestRole.comparePositionTo(this.highestRole) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this member is kickable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get kickable() {
|
||||
return this.manageable && this.guild.me.permissions.has(Permissions.FLAGS.KICK_MEMBERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this member is bannable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get bannable() {
|
||||
return this.manageable && this.guild.me.permissions.has(Permissions.FLAGS.BAN_MEMBERS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `channel.permissionsFor(guildMember)`. Returns permissions for this member in a guild channel,
|
||||
* taking into account roles and permission overwrites.
|
||||
* @param {ChannelResolvable} channel The guild channel to use as context
|
||||
* @returns {?Permissions}
|
||||
*/
|
||||
permissionsIn(channel) {
|
||||
channel = this.client.resolver.resolveChannel(channel);
|
||||
if (!channel || !channel.guild) throw new Error('Could not resolve channel to a guild channel.');
|
||||
return channel.permissionsFor(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if any of this member's roles have a permission.
|
||||
* @param {PermissionResolvable} permission Permission(s) to check for
|
||||
* @param {boolean} [explicit=false] Whether to require the role to explicitly have the exact permission
|
||||
* **(deprecated)**
|
||||
* @param {boolean} [checkAdmin] Whether to allow the administrator permission to override
|
||||
* (takes priority over `explicit`)
|
||||
* @param {boolean} [checkOwner] Whether to allow being the guild's owner to override
|
||||
* (takes priority over `explicit`)
|
||||
* @returns {boolean}
|
||||
*/
|
||||
hasPermission(permission, explicit = false, checkAdmin, checkOwner) {
|
||||
if (typeof checkAdmin === 'undefined') checkAdmin = !explicit;
|
||||
if (typeof checkOwner === 'undefined') checkOwner = !explicit;
|
||||
if (checkOwner && this.user.id === this.guild.ownerID) return true;
|
||||
return this.roles.some(r => r.hasPermission(permission, undefined, checkAdmin));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the roles of this member allows them to perform specific actions.
|
||||
* @param {PermissionResolvable} permissions The permissions to check for
|
||||
* @param {boolean} [explicit=false] Whether to require the member to explicitly have the exact permissions
|
||||
* @returns {boolean}
|
||||
* @deprecated
|
||||
*/
|
||||
hasPermissions(permissions, explicit = false) {
|
||||
if (!explicit && this.user.id === this.guild.ownerID) return true;
|
||||
return this.hasPermission(permissions, explicit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the roles of this member allows them to perform specific actions, and lists any missing permissions.
|
||||
* @param {PermissionResolvable} permissions The permissions to check for
|
||||
* @param {boolean} [explicit=false] Whether to require the member to explicitly have the exact permissions
|
||||
* @returns {PermissionResolvable}
|
||||
*/
|
||||
missingPermissions(permissions, explicit = false) {
|
||||
if (!(permissions instanceof Array)) permissions = [permissions];
|
||||
return this.permissions.missing(permissions, explicit);
|
||||
}
|
||||
|
||||
/**
|
||||
* The data for editing this member.
|
||||
* @typedef {Object} GuildMemberEditData
|
||||
* @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 {ChannelResolvable} [channel] Channel to move member to (if they are connected to voice)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits this member.
|
||||
* @param {GuildMemberEditData} data The data to edit the member with
|
||||
* @param {string} [reason] Reason for editing this user
|
||||
* @returns {Promise<GuildMember>}
|
||||
* @example
|
||||
* // Set a member's nickname and clear their roles
|
||||
* message.member.edit({
|
||||
* nick: 'Cool Name',
|
||||
* roles: []
|
||||
* })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
edit(data, reason) {
|
||||
return this.client.rest.methods.updateGuildMember(this, data, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mute/unmute this member.
|
||||
* @param {boolean} mute Whether or not the member should be muted
|
||||
* @param {string} [reason] Reason for muting or unmuting
|
||||
* @returns {Promise<GuildMember>}
|
||||
* @example
|
||||
* // Mute a member with a reason
|
||||
* message.member.setMute(true, 'It needed to be done')
|
||||
* .then(() => console.log(`Muted ${message.member.displayName}`)))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setMute(mute, reason) {
|
||||
return this.edit({ mute }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deafen/undeafen this member.
|
||||
* @param {boolean} deaf Whether or not the member should be deafened
|
||||
* @param {string} [reason] Reason for deafening or undeafening
|
||||
* @returns {Promise<GuildMember>}
|
||||
* @example
|
||||
* // Deafen a member
|
||||
* message.member.setDeaf(true)
|
||||
* .then(() => console.log(`Deafened ${message.member.displayName}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setDeaf(deaf, reason) {
|
||||
return this.edit({ deaf }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves this member to the given channel.
|
||||
* @param {ChannelResolvable} channel The channel to move the member to
|
||||
* @returns {Promise<GuildMember>}
|
||||
* @example
|
||||
* // Moves a member to a voice channel
|
||||
* member.setVoiceChannel('174674066072928256')
|
||||
* .then(() => console.log(`Moved ${member.displayName}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setVoiceChannel(channel) {
|
||||
return this.edit({ channel });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the roles applied to this 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.setRoles(['391156570408615936'])
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Remove all of the member's roles
|
||||
* guildMember.setRoles([])
|
||||
* .then(member => console.log(`${member.displayName} now has ${member.roles.size} roles`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setRoles(roles, reason) {
|
||||
return this.edit({ roles }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a single role to this member.
|
||||
* @param {RoleResolvable} role The role or ID of the role to add
|
||||
* @param {string} [reason] Reason for adding the role
|
||||
* @returns {Promise<GuildMember>}
|
||||
* @example
|
||||
* // Give a role to a member
|
||||
* message.member.addRole('193654001089118208')
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
addRole(role, reason) {
|
||||
if (!(role instanceof Role)) role = this.guild.roles.get(role);
|
||||
if (!role) return Promise.reject(new TypeError('Supplied parameter was neither a Role nor a Snowflake.'));
|
||||
return this.client.rest.methods.addMemberRole(this, role, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds multiple roles to this member.
|
||||
* @param {Collection<Snowflake, Role>|RoleResolvable[]} roles The roles or role IDs to add
|
||||
* @param {string} [reason] Reason for adding the roles
|
||||
* @returns {Promise<GuildMember>}
|
||||
* @example
|
||||
* // Gives a member a few roles
|
||||
* message.member.addRoles(['193654001089118208', '369308579892690945'])
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
addRoles(roles, reason) {
|
||||
let allRoles;
|
||||
if (roles instanceof Collection) {
|
||||
allRoles = this._roles.slice();
|
||||
for (const role of roles.values()) allRoles.push(role.id);
|
||||
} else {
|
||||
allRoles = this._roles.concat(roles);
|
||||
}
|
||||
return this.edit({ roles: allRoles }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a single role from this member.
|
||||
* @param {RoleResolvable} role The role or ID of the role to remove
|
||||
* @param {string} [reason] Reason for removing the role
|
||||
* @returns {Promise<GuildMember>}
|
||||
* @example
|
||||
* // Remove a role from a member
|
||||
* message.member.removeRole('193654001089118208')
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
removeRole(role, reason) {
|
||||
if (!(role instanceof Role)) role = this.guild.roles.get(role);
|
||||
if (!role) return Promise.reject(new TypeError('Supplied parameter was neither a Role nor a Snowflake.'));
|
||||
return this.client.rest.methods.removeMemberRole(this, role, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes multiple roles from this member.
|
||||
* @param {Collection<Snowflake, Role>|RoleResolvable[]} roles The roles or role IDs to remove
|
||||
* @param {string} [reason] Reason for removing the roles
|
||||
* @returns {Promise<GuildMember>}
|
||||
* @example
|
||||
* // Removes a few roles from the member
|
||||
* message.member.removeRoles(['193654001089118208', '369308579892690945'])
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
removeRoles(roles, reason) {
|
||||
const allRoles = this._roles.slice();
|
||||
if (roles instanceof Collection) {
|
||||
for (const role of roles.values()) {
|
||||
const index = allRoles.indexOf(role.id);
|
||||
if (index >= 0) allRoles.splice(index, 1);
|
||||
}
|
||||
} else {
|
||||
for (const role of roles) {
|
||||
const index = allRoles.indexOf(role instanceof Role ? role.id : role);
|
||||
if (index >= 0) allRoles.splice(index, 1);
|
||||
}
|
||||
}
|
||||
return this.edit({ roles: allRoles }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the nickname for this member.
|
||||
* @param {string} nick The nickname for the guild member
|
||||
* @param {string} [reason] Reason for setting the nickname
|
||||
* @returns {Promise<GuildMember>}
|
||||
* @example
|
||||
* // Update the member's nickname
|
||||
* message.member.setNickname('Cool Name')
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setNickname(nick, reason) {
|
||||
return this.edit({ nick }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DM channel between the client and this member.
|
||||
* @returns {Promise<DMChannel>}
|
||||
*/
|
||||
createDM() {
|
||||
return this.user.createDM();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes any DMs with this guild member.
|
||||
* @returns {Promise<DMChannel>}
|
||||
*/
|
||||
deleteDM() {
|
||||
return this.user.deleteDM();
|
||||
}
|
||||
|
||||
/**
|
||||
* Kick this member from the guild.
|
||||
* @param {string} [reason] Reason for kicking user
|
||||
* @returns {Promise<GuildMember>}
|
||||
* @example
|
||||
* // Kick a member
|
||||
* member.kick()
|
||||
* .then(() => console.log(`Kicked ${member.displayName}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
kick(reason) {
|
||||
return this.client.rest.methods.kickGuildMember(this.guild, this, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ban this member.
|
||||
* @param {Object|number|string} [options] Ban options. If a number, the number of days to delete messages for, if a
|
||||
* string, the ban reason. Supplying an object allows you to do both.
|
||||
* @param {number} [options.days=0] Number of days of messages to delete
|
||||
* @param {string} [options.reason] Reason for banning
|
||||
* @returns {Promise<GuildMember>}
|
||||
* @example
|
||||
* // Ban a guild member
|
||||
* member.ban(7)
|
||||
* .then(() => console.log(`Banned ${member.displayName}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
ban(options) {
|
||||
return this.guild.ban(this, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically concatenates the user's mention instead of the Member object.
|
||||
* @returns {string}
|
||||
* @example
|
||||
* // Logs: Hello from <@123456789>!
|
||||
* console.log(`Hello from ${member}!`);
|
||||
*/
|
||||
toString() {
|
||||
return `<@${this.nickname ? '!' : ''}${this.user.id}>`;
|
||||
}
|
||||
|
||||
// These are here only for documentation purposes - they are implemented by TextBasedChannel
|
||||
/* eslint-disable no-empty-function */
|
||||
send() {}
|
||||
sendMessage() {}
|
||||
sendEmbed() {}
|
||||
sendFile() {}
|
||||
sendCode() {}
|
||||
}
|
||||
|
||||
TextBasedChannel.applyToClass(GuildMember);
|
||||
|
||||
GuildMember.prototype.hasPermissions = util.deprecate(GuildMember.prototype.hasPermissions,
|
||||
'GuildMember#hasPermissions is deprecated - use GuildMember#hasPermission, it now takes an array');
|
||||
|
||||
module.exports = GuildMember;
|
163
node_modules/discord.js/src/structures/Invite.js
generated
vendored
Normal file
163
node_modules/discord.js/src/structures/Invite.js
generated
vendored
Normal file
@ -0,0 +1,163 @@
|
||||
const PartialGuild = require('./PartialGuild');
|
||||
const PartialGuildChannel = require('./PartialGuildChannel');
|
||||
const Constants = require('../util/Constants');
|
||||
|
||||
/**
|
||||
* Represents an invitation to a guild channel.
|
||||
* <warn>The only guaranteed properties are `code`, `guild` and `channel`. Other properties can be missing.</warn>
|
||||
*/
|
||||
class Invite {
|
||||
constructor(client, data) {
|
||||
/**
|
||||
* The client that instantiated the invite
|
||||
* @name Invite#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The guild the invite is for. If this guild is already known, this will be a guild object. If the guild is
|
||||
* unknown, this will be a PartialGuild object
|
||||
* @type {Guild|PartialGuild}
|
||||
*/
|
||||
this.guild = this.client.guilds.get(data.guild.id) || new PartialGuild(this.client, data.guild);
|
||||
|
||||
/**
|
||||
* The code for this invite
|
||||
* @type {string}
|
||||
*/
|
||||
this.code = data.code;
|
||||
|
||||
/**
|
||||
* The approximate number of online members of the guild this invite is for
|
||||
* @type {number}
|
||||
*/
|
||||
this.presenceCount = data.approximate_presence_count;
|
||||
|
||||
/**
|
||||
* The approximate total number of members of the guild this invite is for
|
||||
* @type {number}
|
||||
*/
|
||||
this.memberCount = data.approximate_member_count;
|
||||
|
||||
/**
|
||||
* The number of text channels the guild this invite goes to has
|
||||
* @type {number}
|
||||
*/
|
||||
this.textChannelCount = data.guild.text_channel_count;
|
||||
|
||||
/**
|
||||
* The number of voice channels the guild this invite goes to has
|
||||
* @type {number}
|
||||
*/
|
||||
this.voiceChannelCount = data.guild.voice_channel_count;
|
||||
|
||||
/**
|
||||
* Whether or not this invite is temporary
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.temporary = data.temporary;
|
||||
|
||||
/**
|
||||
* The maximum age of the invite, in seconds
|
||||
* @type {?number}
|
||||
*/
|
||||
this.maxAge = data.max_age;
|
||||
|
||||
/**
|
||||
* How many times this invite has been used
|
||||
* @type {number}
|
||||
*/
|
||||
this.uses = data.uses;
|
||||
|
||||
/**
|
||||
* The maximum uses of this invite
|
||||
* @type {number}
|
||||
*/
|
||||
this.maxUses = data.max_uses;
|
||||
|
||||
if (data.inviter) {
|
||||
/**
|
||||
* The user who created this invite
|
||||
* @type {?User}
|
||||
*/
|
||||
this.inviter = this.client.dataManager.newUser(data.inviter);
|
||||
}
|
||||
|
||||
/**
|
||||
* The channel the invite is for. If this channel is already known, this will be a GuildChannel object.
|
||||
* If the channel is unknown, this will be a PartialGuildChannel object.
|
||||
* @type {GuildChannel|PartialGuildChannel}
|
||||
*/
|
||||
this.channel = this.client.channels.get(data.channel.id) || new PartialGuildChannel(this.client, data.channel);
|
||||
|
||||
/**
|
||||
* The timestamp the invite was created at
|
||||
* @type {number}
|
||||
*/
|
||||
this.createdTimestamp = new Date(data.created_at).getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the invite was created
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp the invite will expire at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get expiresTimestamp() {
|
||||
return this.createdTimestamp + (this.maxAge * 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the invite will expire
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get expiresAt() {
|
||||
return new Date(this.expiresTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL to the invite
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get url() {
|
||||
return Constants.Endpoints.inviteLink(this.code);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes this invite.
|
||||
* @param {string} [reason] Reason for deleting this invite
|
||||
* @returns {Promise<Invite>}
|
||||
*/
|
||||
delete(reason) {
|
||||
return this.client.rest.methods.deleteInvite(this, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically concatenates the invite's URL instead of the object.
|
||||
* @returns {string}
|
||||
* @example
|
||||
* // Logs: Invite: https://discord.gg/A1b2C3
|
||||
* console.log(`Invite: ${invite}`);
|
||||
*/
|
||||
toString() {
|
||||
return this.url;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Invite;
|
604
node_modules/discord.js/src/structures/Message.js
generated
vendored
Normal file
604
node_modules/discord.js/src/structures/Message.js
generated
vendored
Normal file
@ -0,0 +1,604 @@
|
||||
const Mentions = require('./MessageMentions');
|
||||
const Attachment = require('./MessageAttachment');
|
||||
const Embed = require('./MessageEmbed');
|
||||
const RichEmbed = require('./RichEmbed');
|
||||
const MessageReaction = require('./MessageReaction');
|
||||
const ReactionCollector = require('./ReactionCollector');
|
||||
const Util = require('../util/Util');
|
||||
const Collection = require('../util/Collection');
|
||||
const Constants = require('../util/Constants');
|
||||
const Permissions = require('../util/Permissions');
|
||||
let GuildMember;
|
||||
|
||||
/**
|
||||
* Represents a message on Discord.
|
||||
*/
|
||||
class Message {
|
||||
constructor(channel, data, client) {
|
||||
/**
|
||||
* The client that instantiated the Message
|
||||
* @name Message#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
|
||||
/**
|
||||
* The channel that the message was sent in
|
||||
* @type {TextChannel|DMChannel|GroupDMChannel}
|
||||
*/
|
||||
this.channel = channel;
|
||||
|
||||
/**
|
||||
* Whether this message has been deleted
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.deleted = false;
|
||||
|
||||
if (data) this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) { // eslint-disable-line complexity
|
||||
/**
|
||||
* The ID of the message
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The type of the message
|
||||
* @type {MessageType}
|
||||
*/
|
||||
this.type = Constants.MessageTypes[data.type];
|
||||
|
||||
/**
|
||||
* The content of the message
|
||||
* @type {string}
|
||||
*/
|
||||
this.content = data.content;
|
||||
|
||||
/**
|
||||
* The author of the message
|
||||
* @type {User}
|
||||
*/
|
||||
this.author = this.client.dataManager.newUser(data.author, !data.webhook_id);
|
||||
|
||||
/**
|
||||
* Represents the author of the message as a guild member
|
||||
* Only available if the message comes from a guild where the author is still a member
|
||||
* @type {?GuildMember}
|
||||
*/
|
||||
this.member = this.guild ? this.guild.member(this.author) || null : null;
|
||||
|
||||
/**
|
||||
* Whether or not this message is pinned
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.pinned = data.pinned;
|
||||
|
||||
/**
|
||||
* Whether or not the message was Text-To-Speech
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.tts = data.tts;
|
||||
|
||||
/**
|
||||
* A random number or string used for checking message delivery
|
||||
* @type {string}
|
||||
*/
|
||||
this.nonce = data.nonce;
|
||||
|
||||
/**
|
||||
* Whether or not this message was sent by Discord, not actually a user (e.g. pin notifications)
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.system = data.type === 6;
|
||||
|
||||
/**
|
||||
* A list of embeds in the message - e.g. YouTube Player
|
||||
* @type {MessageEmbed[]}
|
||||
*/
|
||||
this.embeds = data.embeds.map(e => new Embed(this, e));
|
||||
|
||||
/**
|
||||
* A collection of attachments in the message - e.g. Pictures - mapped by their ID
|
||||
* @type {Collection<Snowflake, MessageAttachment>}
|
||||
*/
|
||||
this.attachments = new Collection();
|
||||
for (const attachment of data.attachments) this.attachments.set(attachment.id, new Attachment(this, attachment));
|
||||
|
||||
/**
|
||||
* The timestamp the message was sent at
|
||||
* @type {number}
|
||||
*/
|
||||
this.createdTimestamp = new Date(data.timestamp).getTime();
|
||||
|
||||
/**
|
||||
* The timestamp the message was last edited at (if applicable)
|
||||
* @type {?number}
|
||||
*/
|
||||
this.editedTimestamp = data.edited_timestamp ? new Date(data.edited_timestamp).getTime() : null;
|
||||
|
||||
/**
|
||||
* A collection of reactions to this message, mapped by the reaction ID
|
||||
* @type {Collection<Snowflake, MessageReaction>}
|
||||
*/
|
||||
this.reactions = new Collection();
|
||||
if (data.reactions && data.reactions.length > 0) {
|
||||
for (const reaction of data.reactions) {
|
||||
const id = reaction.emoji.id ? `${reaction.emoji.name}:${reaction.emoji.id}` : reaction.emoji.name;
|
||||
this.reactions.set(id, new MessageReaction(this, reaction.emoji, reaction.count, reaction.me));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* All valid mentions that the message contains
|
||||
* @type {MessageMentions}
|
||||
*/
|
||||
this.mentions = new Mentions(this, data.mentions, data.mention_roles, data.mention_everyone);
|
||||
|
||||
/**
|
||||
* ID of the webhook that sent the message, if applicable
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.webhookID = data.webhook_id || null;
|
||||
|
||||
/**
|
||||
* Whether this message is a hit in a search
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.hit = typeof data.hit === 'boolean' ? data.hit : null;
|
||||
|
||||
/**
|
||||
* The previous versions of the message, sorted with the most recent first
|
||||
* @type {Message[]}
|
||||
* @private
|
||||
*/
|
||||
this._edits = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the message.
|
||||
* @param {Object} data Raw Discord message update data
|
||||
* @private
|
||||
*/
|
||||
patch(data) {
|
||||
const clone = Util.cloneObject(this);
|
||||
this._edits.unshift(clone);
|
||||
|
||||
if ('editedTimestamp' in data) this.editedTimestamp = new Date(data.edited_timestamp).getTime();
|
||||
if ('content' in data) this.content = data.content;
|
||||
if ('pinned' in data) this.pinned = data.pinned;
|
||||
if ('tts' in data) this.tts = data.tts;
|
||||
if ('embeds' in data) this.embeds = data.embeds.map(e => new Embed(this, e));
|
||||
else this.embeds = this.embeds.slice();
|
||||
|
||||
if ('attachments' in data) {
|
||||
this.attachments = new Collection();
|
||||
for (const attachment of data.attachments) this.attachments.set(attachment.id, new Attachment(this, attachment));
|
||||
} else {
|
||||
this.attachments = new Collection(this.attachments);
|
||||
}
|
||||
|
||||
this.mentions = new Mentions(
|
||||
this,
|
||||
'mentions' in data ? data.mentions : this.mentions.users,
|
||||
'mentions_roles' in data ? data.mentions_roles : this.mentions.roles,
|
||||
'mention_everyone' in data ? data.mention_everyone : this.mentions.everyone
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the message was sent
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the message was last edited at (if applicable)
|
||||
* @type {?Date}
|
||||
* @readonly
|
||||
*/
|
||||
get editedAt() {
|
||||
return this.editedTimestamp ? new Date(this.editedTimestamp) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The guild the message was sent in (if in a guild channel)
|
||||
* @type {?Guild}
|
||||
* @readonly
|
||||
*/
|
||||
get guild() {
|
||||
return this.channel.guild || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The url to jump to the message
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get url() {
|
||||
return `https://discordapp.com/channels/${this.guild ? this.guild.id : '@me'}/${this.channel.id}/${this.id}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* The message contents with all mentions replaced by the equivalent text.
|
||||
* If mentions cannot be resolved to a name, the relevant mention in the message content will not be converted.
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get cleanContent() {
|
||||
return this.content
|
||||
.replace(/@(everyone|here)/g, '@\u200b$1')
|
||||
.replace(/<@!?[0-9]+>/g, input => {
|
||||
const id = input.replace(/<|!|>|@/g, '');
|
||||
if (this.channel.type === 'dm' || this.channel.type === 'group') {
|
||||
return this.client.users.has(id) ? `@${this.client.users.get(id).username}` : input;
|
||||
}
|
||||
|
||||
const member = this.channel.guild.members.get(id);
|
||||
if (member) {
|
||||
if (member.nickname) return `@${member.nickname}`;
|
||||
return `@${member.user.username}`;
|
||||
} else {
|
||||
const user = this.client.users.get(id);
|
||||
if (user) return `@${user.username}`;
|
||||
return input;
|
||||
}
|
||||
})
|
||||
.replace(/<#[0-9]+>/g, input => {
|
||||
const channel = this.client.channels.get(input.replace(/<|#|>/g, ''));
|
||||
if (channel) return `#${channel.name}`;
|
||||
return input;
|
||||
})
|
||||
.replace(/<@&[0-9]+>/g, input => {
|
||||
if (this.channel.type === 'dm' || this.channel.type === 'group') return input;
|
||||
const role = this.guild.roles.get(input.replace(/<|@|>|&/g, ''));
|
||||
if (role) return `@${role.name}`;
|
||||
return input;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a reaction collector.
|
||||
* @param {CollectorFilter} filter The filter to apply
|
||||
* @param {ReactionCollectorOptions} [options={}] Options to send to the collector
|
||||
* @returns {ReactionCollector}
|
||||
* @example
|
||||
* // Create a reaction collector
|
||||
* const filter = (reaction, user) => reaction.emoji.name === '👌' && user.id === 'someID'
|
||||
* const collector = message.createReactionCollector(filter, { time: 15000 });
|
||||
* collector.on('collect', r => console.log(`Collected ${r.emoji.name}`));
|
||||
* collector.on('end', collected => console.log(`Collected ${collected.size} items`));
|
||||
*/
|
||||
createReactionCollector(filter, options = {}) {
|
||||
return new ReactionCollector(this, filter, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* An object containing the same properties as CollectorOptions, but a few more:
|
||||
* @typedef {ReactionCollectorOptions} AwaitReactionsOptions
|
||||
* @property {string[]} [errors] Stop/end reasons that cause the promise to reject
|
||||
*/
|
||||
|
||||
/**
|
||||
* Similar to createMessageCollector but in promise form.
|
||||
* Resolves with a collection of reactions that pass the specified filter.
|
||||
* @param {CollectorFilter} filter The filter function to use
|
||||
* @param {AwaitReactionsOptions} [options={}] Optional options to pass to the internal collector
|
||||
* @returns {Promise<Collection<string, MessageReaction>>}
|
||||
* @example
|
||||
* // Create a reaction collector
|
||||
* const filter = (reaction, user) => reaction.emoji.name === '👌' && user.id === 'someID'
|
||||
* message.awaitReactions(filter, { time: 15000 })
|
||||
* .then(collected => console.log(`Collected ${collected.size} reactions`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
awaitReactions(filter, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const collector = this.createReactionCollector(filter, options);
|
||||
collector.once('end', (reactions, reason) => {
|
||||
if (options.errors && options.errors.includes(reason)) reject(reactions);
|
||||
else resolve(reactions);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* An array of cached versions of the message, including the current version
|
||||
* Sorted from latest (first) to oldest (last)
|
||||
* @type {Message[]}
|
||||
* @readonly
|
||||
*/
|
||||
get edits() {
|
||||
const copy = this._edits.slice();
|
||||
copy.unshift(this);
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the message is editable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get editable() {
|
||||
return this.author.id === this.client.user.id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the message is deletable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get deletable() {
|
||||
return !this.deleted && (this.author.id === this.client.user.id || (this.guild &&
|
||||
this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_MESSAGES)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the message is pinnable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get pinnable() {
|
||||
return !this.guild ||
|
||||
this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_MESSAGES);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not a user, channel or role is mentioned in this message.
|
||||
* @param {GuildChannel|User|Role|string} data Either a guild channel, user or a role object, or a string representing
|
||||
* the ID of any of these
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isMentioned(data) {
|
||||
data = data && data.id ? data.id : data;
|
||||
return this.mentions.users.has(data) || this.mentions.channels.has(data) || this.mentions.roles.has(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not a guild member is mentioned in this message. Takes into account
|
||||
* user mentions, role mentions, and @everyone/@here mentions.
|
||||
* @param {GuildMember|User} member The member/user to check for a mention of
|
||||
* @returns {boolean}
|
||||
*/
|
||||
isMemberMentioned(member) {
|
||||
// Lazy-loading is used here to get around a circular dependency that breaks things
|
||||
if (!GuildMember) GuildMember = require('./GuildMember');
|
||||
if (this.mentions.everyone) return true;
|
||||
if (this.mentions.users.has(member.id)) return true;
|
||||
if (member instanceof GuildMember && member.roles.some(r => this.mentions.roles.has(r.id))) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options that can be passed into editMessage.
|
||||
* @typedef {Object} MessageEditOptions
|
||||
* @property {Object} [embed] An embed to be added/edited
|
||||
* @property {string|boolean} [code] Language for optional codeblock formatting to apply
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edit the content of the message.
|
||||
* @param {StringResolvable} [content] The new content for the message
|
||||
* @param {MessageEditOptions|RichEmbed} [options] The options to provide
|
||||
* @returns {Promise<Message>}
|
||||
* @example
|
||||
* // Update the content of a message
|
||||
* message.edit('This is my new content!')
|
||||
* .then(msg => console.log(`New message content: ${msg}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
edit(content, options) {
|
||||
if (!options && typeof content === 'object' && !(content instanceof Array)) {
|
||||
options = content;
|
||||
content = '';
|
||||
} else if (!options) {
|
||||
options = {};
|
||||
}
|
||||
if (options instanceof RichEmbed) options = { embed: options };
|
||||
return this.client.rest.methods.updateMessage(this, content, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit the content of the message, with a code block.
|
||||
* @param {string} lang The language for the code block
|
||||
* @param {StringResolvable} content The new content for the message
|
||||
* @returns {Promise<Message>}
|
||||
* @deprecated
|
||||
*/
|
||||
editCode(lang, content) {
|
||||
content = Util.escapeMarkdown(this.client.resolver.resolveString(content), true);
|
||||
return this.edit(`\`\`\`${lang || ''}\n${content}\n\`\`\``);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pins this message to the channel's pinned messages.
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
pin() {
|
||||
return this.client.rest.methods.pinMessage(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unpins this message from the channel's pinned messages.
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
unpin() {
|
||||
return this.client.rest.methods.unpinMessage(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a reaction to the message.
|
||||
* @param {string|Emoji|ReactionEmoji} emoji The emoji to react with
|
||||
* @returns {Promise<MessageReaction>}
|
||||
* @example
|
||||
* // React to a message with a unicode emoji
|
||||
* message.react('🤔')
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // React to a message with a custom emoji
|
||||
* message.react(message.guild.emojis.get('123456789012345678'))
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
react(emoji) {
|
||||
emoji = this.client.resolver.resolveEmojiIdentifier(emoji);
|
||||
if (!emoji) throw new TypeError('Emoji must be a string or Emoji/ReactionEmoji');
|
||||
|
||||
return this.client.rest.methods.addMessageReaction(this, emoji);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all reactions from a message.
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
clearReactions() {
|
||||
return this.client.rest.methods.removeMessageReactions(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the message.
|
||||
* @param {number} [timeout=0] How long to wait to delete the message in milliseconds
|
||||
* @returns {Promise<Message>}
|
||||
* @example
|
||||
* // Delete a message
|
||||
* message.delete()
|
||||
* .then(msg => console.log(`Deleted message from ${msg.author.username}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
delete(timeout = 0) {
|
||||
if (timeout <= 0) {
|
||||
return this.client.rest.methods.deleteMessage(this);
|
||||
} else {
|
||||
return new Promise(resolve => {
|
||||
this.client.setTimeout(() => {
|
||||
resolve(this.delete());
|
||||
}, timeout);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reply to the message.
|
||||
* @param {StringResolvable} [content] The content for the message
|
||||
* @param {MessageOptions} [options] The options to provide
|
||||
* @returns {Promise<Message|Message[]>}
|
||||
* @example
|
||||
* // Reply to a message
|
||||
* message.reply('Hey, I\'m a reply!')
|
||||
* .then(sent => console.log(`Sent a reply to ${sent.author.username}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
reply(content, options) {
|
||||
if (!options && typeof content === 'object' && !(content instanceof Array)) {
|
||||
options = content;
|
||||
content = '';
|
||||
} else if (!options) {
|
||||
options = {};
|
||||
}
|
||||
return this.channel.send(content, Object.assign(options, { reply: this.member || this.author }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the message as read.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
acknowledge() {
|
||||
return this.client.rest.methods.ackMessage(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the webhook used to create this message.
|
||||
* @returns {Promise<?Webhook>}
|
||||
*/
|
||||
fetchWebhook() {
|
||||
if (!this.webhookID) return Promise.reject(new Error('The message was not sent by a webhook.'));
|
||||
return this.client.fetchWebhook(this.webhookID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Used mainly internally. Whether two messages are identical in properties. If you want to compare messages
|
||||
* without checking all the properties, use `message.id === message2.id`, which is much more efficient. This
|
||||
* method allows you to see if there are differences in content, embeds, attachments, nonce and tts properties.
|
||||
* @param {Message} message The message to compare it to
|
||||
* @param {Object} rawData Raw data passed through the WebSocket about this message
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(message, rawData) {
|
||||
if (!message) return false;
|
||||
const embedUpdate = !message.author && !message.attachments;
|
||||
if (embedUpdate) return this.id === message.id && this.embeds.length === message.embeds.length;
|
||||
|
||||
let equal = this.id === message.id &&
|
||||
this.author.id === message.author.id &&
|
||||
this.content === message.content &&
|
||||
this.tts === message.tts &&
|
||||
this.nonce === message.nonce &&
|
||||
this.embeds.length === message.embeds.length &&
|
||||
this.attachments.length === message.attachments.length;
|
||||
|
||||
if (equal && rawData) {
|
||||
equal = this.mentions.everyone === message.mentions.everyone &&
|
||||
this.createdTimestamp === new Date(rawData.timestamp).getTime() &&
|
||||
this.editedTimestamp === new Date(rawData.edited_timestamp).getTime();
|
||||
}
|
||||
|
||||
return equal;
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically concatenates the message's content instead of the object.
|
||||
* @returns {string}
|
||||
* @example
|
||||
* // Logs: Message: This is a message!
|
||||
* console.log(`Message: ${message}`);
|
||||
*/
|
||||
toString() {
|
||||
return this.content;
|
||||
}
|
||||
|
||||
_addReaction(emoji, user) {
|
||||
const emojiID = emoji.id ? `${emoji.name}:${emoji.id}` : emoji.name;
|
||||
let reaction;
|
||||
if (this.reactions.has(emojiID)) {
|
||||
reaction = this.reactions.get(emojiID);
|
||||
if (!reaction.me) reaction.me = user.id === this.client.user.id;
|
||||
} else {
|
||||
reaction = new MessageReaction(this, emoji, 0, user.id === this.client.user.id);
|
||||
this.reactions.set(emojiID, reaction);
|
||||
}
|
||||
if (!reaction.users.has(user.id)) {
|
||||
reaction.users.set(user.id, user);
|
||||
reaction.count++;
|
||||
}
|
||||
return reaction;
|
||||
}
|
||||
|
||||
_removeReaction(emoji, user) {
|
||||
const emojiID = emoji.id ? `${emoji.name}:${emoji.id}` : emoji.name;
|
||||
if (this.reactions.has(emojiID)) {
|
||||
const reaction = this.reactions.get(emojiID);
|
||||
if (reaction.users.has(user.id)) {
|
||||
reaction.users.delete(user.id);
|
||||
reaction.count--;
|
||||
if (user.id === this.client.user.id) reaction.me = false;
|
||||
if (reaction.count <= 0) this.reactions.delete(emojiID);
|
||||
return reaction;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
_clearReactions() {
|
||||
this.reactions.clear();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Message;
|
68
node_modules/discord.js/src/structures/MessageAttachment.js
generated
vendored
Normal file
68
node_modules/discord.js/src/structures/MessageAttachment.js
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
/**
|
||||
* Represents an attachment in a message.
|
||||
*/
|
||||
class MessageAttachment {
|
||||
constructor(message, data) {
|
||||
/**
|
||||
* The client that instantiated this MessageAttachment
|
||||
* @name MessageAttachment#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: message.client });
|
||||
|
||||
/**
|
||||
* The message this attachment is part of
|
||||
* @type {Message}
|
||||
*/
|
||||
this.message = message;
|
||||
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The ID of this attachment
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The file name of this attachment
|
||||
* @type {string}
|
||||
*/
|
||||
this.filename = data.filename;
|
||||
|
||||
/**
|
||||
* The size of this attachment in bytes
|
||||
* @type {number}
|
||||
*/
|
||||
this.filesize = data.size;
|
||||
|
||||
/**
|
||||
* The URL to this attachment
|
||||
* @type {string}
|
||||
*/
|
||||
this.url = data.url;
|
||||
|
||||
/**
|
||||
* The Proxy URL to this attachment
|
||||
* @type {string}
|
||||
*/
|
||||
this.proxyURL = data.proxy_url;
|
||||
|
||||
/**
|
||||
* The height of this attachment (if an image)
|
||||
* @type {?number}
|
||||
*/
|
||||
this.height = data.height;
|
||||
|
||||
/**
|
||||
* The width of this attachment (if an image)
|
||||
* @type {?number}
|
||||
*/
|
||||
this.width = data.width;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MessageAttachment;
|
100
node_modules/discord.js/src/structures/MessageCollector.js
generated
vendored
Normal file
100
node_modules/discord.js/src/structures/MessageCollector.js
generated
vendored
Normal file
@ -0,0 +1,100 @@
|
||||
const Collector = require('./interfaces/Collector');
|
||||
const util = require('util');
|
||||
|
||||
/**
|
||||
* @typedef {CollectorOptions} MessageCollectorOptions
|
||||
* @property {number} max The maximum amount of messages to process
|
||||
* @property {number} maxMatches The maximum amount of messages to collect
|
||||
*/
|
||||
|
||||
/**
|
||||
* Collects messages on a channel.
|
||||
* @extends {Collector}
|
||||
*/
|
||||
class MessageCollector extends Collector {
|
||||
/**
|
||||
* @param {TextChannel|DMChannel|GroupDMChannel} channel The channel
|
||||
* @param {CollectorFilter} filter The filter to be applied to this collector
|
||||
* @param {MessageCollectorOptions} options The options to be applied to this collector
|
||||
* @emits MessageCollector#message
|
||||
*/
|
||||
constructor(channel, filter, options = {}) {
|
||||
super(channel.client, filter, options);
|
||||
|
||||
/**
|
||||
* The channel
|
||||
* @type {TextBasedChannel}
|
||||
*/
|
||||
this.channel = channel;
|
||||
|
||||
/**
|
||||
* Total number of messages that were received in the channel during message collection
|
||||
* @type {number}
|
||||
*/
|
||||
this.received = 0;
|
||||
|
||||
this.client.setMaxListeners(this.client.getMaxListeners() + 1);
|
||||
this.client.on('message', this.listener);
|
||||
|
||||
// For backwards compatibility (remove in v12)
|
||||
if (this.options.max) this.options.maxProcessed = this.options.max;
|
||||
if (this.options.maxMatches) this.options.max = this.options.maxMatches;
|
||||
this._reEmitter = message => {
|
||||
/**
|
||||
* Emitted when the collector receives a message.
|
||||
* @event MessageCollector#message
|
||||
* @param {Message} message The message
|
||||
* @deprecated
|
||||
*/
|
||||
this.emit('message', message);
|
||||
};
|
||||
this.on('collect', this._reEmitter);
|
||||
}
|
||||
|
||||
// Remove in v12
|
||||
on(eventName, listener) {
|
||||
if (eventName === 'message') {
|
||||
listener = util.deprecate(listener, 'MessageCollector will soon no longer emit "message", use "collect" instead');
|
||||
}
|
||||
super.on(eventName, listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming message for possible collection.
|
||||
* @param {Message} message The message that could be collected
|
||||
* @returns {?{key: Snowflake, value: Message}}
|
||||
* @private
|
||||
*/
|
||||
handle(message) {
|
||||
if (message.channel.id !== this.channel.id) return null;
|
||||
this.received++;
|
||||
return {
|
||||
key: message.id,
|
||||
value: message,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check after collection to see if the collector is done.
|
||||
* @returns {?string} Reason to end the collector, if any
|
||||
* @private
|
||||
*/
|
||||
postCheck() {
|
||||
// Consider changing the end reasons for v12
|
||||
if (this.options.maxMatches && this.collected.size >= this.options.max) return 'matchesLimit';
|
||||
if (this.options.max && this.received >= this.options.maxProcessed) return 'limit';
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes event listeners.
|
||||
* @private
|
||||
*/
|
||||
cleanup() {
|
||||
this.removeListener('collect', this._reEmitter);
|
||||
this.client.removeListener('message', this.listener);
|
||||
this.client.setMaxListeners(this.client.getMaxListeners() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MessageCollector;
|
386
node_modules/discord.js/src/structures/MessageEmbed.js
generated
vendored
Normal file
386
node_modules/discord.js/src/structures/MessageEmbed.js
generated
vendored
Normal file
@ -0,0 +1,386 @@
|
||||
/**
|
||||
* Represents an embed in a message (image/video preview, rich embed, etc.)
|
||||
* <info>This class is only used for *recieved* embeds. If you wish to send one, use the {@link RichEmbed} class.</info>
|
||||
*/
|
||||
class MessageEmbed {
|
||||
constructor(message, data) {
|
||||
/**
|
||||
* The client that instantiated this embed
|
||||
* @name MessageEmbed#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: message.client });
|
||||
|
||||
/**
|
||||
* The message this embed is part of
|
||||
* @type {Message}
|
||||
*/
|
||||
this.message = message;
|
||||
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The type of this embed
|
||||
* @type {string}
|
||||
*/
|
||||
this.type = data.type;
|
||||
|
||||
/**
|
||||
* The title of this embed
|
||||
* @type {?string}
|
||||
*/
|
||||
this.title = data.title;
|
||||
|
||||
/**
|
||||
* The description of this embed
|
||||
* @type {?string}
|
||||
*/
|
||||
this.description = data.description;
|
||||
|
||||
/**
|
||||
* The URL of this embed
|
||||
* @type {string}
|
||||
*/
|
||||
this.url = data.url;
|
||||
|
||||
/**
|
||||
* The color of the embed
|
||||
* @type {number}
|
||||
*/
|
||||
this.color = data.color;
|
||||
|
||||
/**
|
||||
* The fields of this embed
|
||||
* @type {MessageEmbedField[]}
|
||||
*/
|
||||
this.fields = [];
|
||||
if (data.fields) for (const field of data.fields) this.fields.push(new MessageEmbedField(this, field));
|
||||
|
||||
/**
|
||||
* The timestamp of this embed
|
||||
* @type {number}
|
||||
*/
|
||||
this.timestamp = data.timestamp;
|
||||
|
||||
/**
|
||||
* The thumbnail of this embed
|
||||
* @type {?MessageEmbedThumbnail}
|
||||
*/
|
||||
this.thumbnail = data.thumbnail ? new MessageEmbedThumbnail(this, data.thumbnail) : null;
|
||||
|
||||
/**
|
||||
* The image of this embed
|
||||
* @type {?MessageEmbedImage}
|
||||
*/
|
||||
this.image = data.image ? new MessageEmbedImage(this, data.image) : null;
|
||||
|
||||
/**
|
||||
* The video of this embed
|
||||
* @type {?MessageEmbedVideo}
|
||||
*/
|
||||
this.video = data.video ? new MessageEmbedVideo(this, data.video) : null;
|
||||
|
||||
/**
|
||||
* The author of this embed
|
||||
* @type {?MessageEmbedAuthor}
|
||||
*/
|
||||
this.author = data.author ? new MessageEmbedAuthor(this, data.author) : null;
|
||||
|
||||
/**
|
||||
* The provider of this embed
|
||||
* @type {?MessageEmbedProvider}
|
||||
*/
|
||||
this.provider = data.provider ? new MessageEmbedProvider(this, data.provider) : null;
|
||||
|
||||
/**
|
||||
* The footer of this embed
|
||||
* @type {?MessageEmbedFooter}
|
||||
*/
|
||||
this.footer = data.footer ? new MessageEmbedFooter(this, data.footer) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The date this embed was created
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The hexadecimal version of the embed color, with a leading hash
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get hexColor() {
|
||||
if (!this.color) return null;
|
||||
let col = this.color.toString(16);
|
||||
while (col.length < 6) col = `0${col}`;
|
||||
return `#${col}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a thumbnail for a message embed.
|
||||
*/
|
||||
class MessageEmbedThumbnail {
|
||||
constructor(embed, data) {
|
||||
/**
|
||||
* The embed this thumbnail is part of
|
||||
* @type {MessageEmbed}
|
||||
*/
|
||||
this.embed = embed;
|
||||
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The URL for this thumbnail
|
||||
* @type {string}
|
||||
*/
|
||||
this.url = data.url;
|
||||
|
||||
/**
|
||||
* The Proxy URL for this thumbnail
|
||||
* @type {string}
|
||||
*/
|
||||
this.proxyURL = data.proxy_url;
|
||||
|
||||
/**
|
||||
* The height of the thumbnail
|
||||
* @type {number}
|
||||
*/
|
||||
this.height = data.height;
|
||||
|
||||
/**
|
||||
* The width of the thumbnail
|
||||
* @type {number}
|
||||
*/
|
||||
this.width = data.width;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an image for a message embed.
|
||||
*/
|
||||
class MessageEmbedImage {
|
||||
constructor(embed, data) {
|
||||
/**
|
||||
* The embed this image is part of
|
||||
* @type {MessageEmbed}
|
||||
*/
|
||||
this.embed = embed;
|
||||
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The URL for this image
|
||||
* @type {string}
|
||||
*/
|
||||
this.url = data.url;
|
||||
|
||||
/**
|
||||
* The Proxy URL for this image
|
||||
* @type {string}
|
||||
*/
|
||||
this.proxyURL = data.proxy_url;
|
||||
|
||||
/**
|
||||
* The height of the image
|
||||
* @type {number}
|
||||
*/
|
||||
this.height = data.height;
|
||||
|
||||
/**
|
||||
* The width of the image
|
||||
* @type {number}
|
||||
*/
|
||||
this.width = data.width;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a video for a message embed.
|
||||
*/
|
||||
class MessageEmbedVideo {
|
||||
constructor(embed, data) {
|
||||
/**
|
||||
* The embed this video is part of
|
||||
* @type {MessageEmbed}
|
||||
*/
|
||||
this.embed = embed;
|
||||
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The source URL for this video
|
||||
* @type {string}
|
||||
*/
|
||||
this.url = data.url;
|
||||
|
||||
/**
|
||||
* The height of the video
|
||||
* @type {number}
|
||||
*/
|
||||
this.height = data.height;
|
||||
|
||||
/**
|
||||
* The width of the video
|
||||
* @type {number}
|
||||
*/
|
||||
this.width = data.width;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a provider for a message embed.
|
||||
*/
|
||||
class MessageEmbedProvider {
|
||||
constructor(embed, data) {
|
||||
/**
|
||||
* The embed this provider is part of
|
||||
* @type {MessageEmbed}
|
||||
*/
|
||||
this.embed = embed;
|
||||
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The name of this provider
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* The URL of this provider
|
||||
* @type {string}
|
||||
*/
|
||||
this.url = data.url;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents an author for a message embed.
|
||||
*/
|
||||
class MessageEmbedAuthor {
|
||||
constructor(embed, data) {
|
||||
/**
|
||||
* The embed this author is part of
|
||||
* @type {MessageEmbed}
|
||||
*/
|
||||
this.embed = embed;
|
||||
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The name of this author
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* The URL of this author
|
||||
* @type {string}
|
||||
*/
|
||||
this.url = data.url;
|
||||
|
||||
/**
|
||||
* The icon URL of this author
|
||||
* @type {string}
|
||||
*/
|
||||
this.iconURL = data.icon_url;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a field for a message embed.
|
||||
*/
|
||||
class MessageEmbedField {
|
||||
constructor(embed, data) {
|
||||
/**
|
||||
* The embed this footer is part of
|
||||
* @type {MessageEmbed}
|
||||
*/
|
||||
this.embed = embed;
|
||||
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The name of this field
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* The value of this field
|
||||
* @type {string}
|
||||
*/
|
||||
this.value = data.value;
|
||||
|
||||
/**
|
||||
* If this field is displayed inline
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.inline = data.inline;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the footer of a message embed.
|
||||
*/
|
||||
class MessageEmbedFooter {
|
||||
constructor(embed, data) {
|
||||
/**
|
||||
* The embed this footer is part of
|
||||
* @type {MessageEmbed}
|
||||
*/
|
||||
this.embed = embed;
|
||||
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The text in this footer
|
||||
* @type {string}
|
||||
*/
|
||||
this.text = data.text;
|
||||
|
||||
/**
|
||||
* The icon URL of this footer
|
||||
* @type {string}
|
||||
*/
|
||||
this.iconURL = data.icon_url;
|
||||
|
||||
/**
|
||||
* The proxy icon URL of this footer
|
||||
* @type {string}
|
||||
*/
|
||||
this.proxyIconUrl = data.proxy_icon_url;
|
||||
}
|
||||
}
|
||||
|
||||
MessageEmbed.Thumbnail = MessageEmbedThumbnail;
|
||||
MessageEmbed.Image = MessageEmbedImage;
|
||||
MessageEmbed.Video = MessageEmbedVideo;
|
||||
MessageEmbed.Provider = MessageEmbedProvider;
|
||||
MessageEmbed.Author = MessageEmbedAuthor;
|
||||
MessageEmbed.Field = MessageEmbedField;
|
||||
MessageEmbed.Footer = MessageEmbedFooter;
|
||||
|
||||
module.exports = MessageEmbed;
|
144
node_modules/discord.js/src/structures/MessageMentions.js
generated
vendored
Normal file
144
node_modules/discord.js/src/structures/MessageMentions.js
generated
vendored
Normal file
@ -0,0 +1,144 @@
|
||||
const Collection = require('../util/Collection');
|
||||
|
||||
/**
|
||||
* Keeps track of mentions in a {@link Message}.
|
||||
*/
|
||||
class MessageMentions {
|
||||
constructor(message, users, roles, everyone) {
|
||||
/**
|
||||
* Whether `@everyone` or `@here` were mentioned
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.everyone = Boolean(everyone);
|
||||
|
||||
if (users) {
|
||||
if (users instanceof Collection) {
|
||||
/**
|
||||
* Any users that were mentioned
|
||||
* @type {Collection<Snowflake, User>}
|
||||
*/
|
||||
this.users = new Collection(users);
|
||||
} else {
|
||||
this.users = new Collection();
|
||||
for (const mention of users) {
|
||||
let user = message.client.users.get(mention.id);
|
||||
if (!user) user = message.client.dataManager.newUser(mention);
|
||||
this.users.set(user.id, user);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.users = new Collection();
|
||||
}
|
||||
|
||||
if (roles) {
|
||||
if (roles instanceof Collection) {
|
||||
/**
|
||||
* Any roles that were mentioned
|
||||
* @type {Collection<Snowflake, Role>}
|
||||
*/
|
||||
this.roles = new Collection(roles);
|
||||
} else {
|
||||
this.roles = new Collection();
|
||||
for (const mention of roles) {
|
||||
const role = message.channel.guild.roles.get(mention);
|
||||
if (role) this.roles.set(role.id, role);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.roles = new Collection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Content of the message
|
||||
* @type {Message}
|
||||
* @private
|
||||
*/
|
||||
this._content = message.content;
|
||||
|
||||
/**
|
||||
* The client the message is from
|
||||
* @type {Client}
|
||||
* @private
|
||||
*/
|
||||
this._client = message.client;
|
||||
|
||||
/**
|
||||
* The guild the message is in
|
||||
* @type {?Guild}
|
||||
* @private
|
||||
*/
|
||||
this._guild = message.channel.guild;
|
||||
|
||||
/**
|
||||
* Cached members for {@MessageMention#members}
|
||||
* @type {?Collection<Snowflake, GuildMember>}
|
||||
* @private
|
||||
*/
|
||||
this._members = null;
|
||||
|
||||
/**
|
||||
* Cached channels for {@MessageMention#channels}
|
||||
* @type {?Collection<Snowflake, GuildChannel>}
|
||||
* @private
|
||||
*/
|
||||
this._channels = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Any members that were mentioned (only in {@link TextChannel}s)
|
||||
* @type {?Collection<Snowflake, GuildMember>}
|
||||
* @readonly
|
||||
*/
|
||||
get members() {
|
||||
if (this._members) return this._members;
|
||||
if (!this._guild) return null;
|
||||
this._members = new Collection();
|
||||
this.users.forEach(user => {
|
||||
const member = this._guild.member(user);
|
||||
if (member) this._members.set(member.user.id, member);
|
||||
});
|
||||
return this._members;
|
||||
}
|
||||
|
||||
/**
|
||||
* Any channels that were mentioned
|
||||
* @type {Collection<Snowflake, GuildChannel>}
|
||||
* @readonly
|
||||
*/
|
||||
get channels() {
|
||||
if (this._channels) return this._channels;
|
||||
this._channels = new Collection();
|
||||
let matches;
|
||||
while ((matches = this.constructor.CHANNELS_PATTERN.exec(this._content)) !== null) {
|
||||
const chan = this._client.channels.get(matches[1]);
|
||||
if (chan) this._channels.set(chan.id, chan);
|
||||
}
|
||||
return this._channels;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Regular expression that globally matches `@everyone` and `@here`
|
||||
* @type {RegExp}
|
||||
*/
|
||||
MessageMentions.EVERYONE_PATTERN = /@(everyone|here)/g;
|
||||
|
||||
/**
|
||||
* Regular expression that globally matches user mentions like `<@81440962496172032>`
|
||||
* @type {RegExp}
|
||||
*/
|
||||
MessageMentions.USERS_PATTERN = /<@!?[0-9]+>/g;
|
||||
|
||||
/**
|
||||
* Regular expression that globally matches role mentions like `<@&297577916114403338>`
|
||||
* @type {RegExp}
|
||||
*/
|
||||
MessageMentions.ROLES_PATTERN = /<@&[0-9]+>/g;
|
||||
|
||||
/**
|
||||
* Regular expression that globally matches channel mentions like `<#222079895583457280>`
|
||||
* @type {RegExp}
|
||||
*/
|
||||
MessageMentions.CHANNELS_PATTERN = /<#([0-9]+)>/g;
|
||||
|
||||
module.exports = MessageMentions;
|
96
node_modules/discord.js/src/structures/MessageReaction.js
generated
vendored
Normal file
96
node_modules/discord.js/src/structures/MessageReaction.js
generated
vendored
Normal file
@ -0,0 +1,96 @@
|
||||
const Collection = require('../util/Collection');
|
||||
const Emoji = require('./Emoji');
|
||||
const ReactionEmoji = require('./ReactionEmoji');
|
||||
|
||||
/**
|
||||
* Represents a reaction to a message.
|
||||
*/
|
||||
class MessageReaction {
|
||||
constructor(message, emoji, count, me) {
|
||||
/**
|
||||
* The message that this reaction refers to
|
||||
* @type {Message}
|
||||
*/
|
||||
this.message = message;
|
||||
|
||||
/**
|
||||
* Whether the client has given this reaction
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.me = me;
|
||||
|
||||
/**
|
||||
* The number of people that have given the same reaction
|
||||
* @type {number}
|
||||
*/
|
||||
this.count = count || 0;
|
||||
|
||||
/**
|
||||
* The users that have given this reaction, mapped by their ID
|
||||
* @type {Collection<Snowflake, User>}
|
||||
*/
|
||||
this.users = new Collection();
|
||||
|
||||
this._emoji = new ReactionEmoji(this, emoji.name, emoji.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The emoji of this reaction, either an Emoji object for known custom emojis, or a ReactionEmoji
|
||||
* object which has fewer properties. Whatever the prototype of the emoji, it will still have
|
||||
* `name`, `id`, `identifier` and `toString()`
|
||||
* @type {Emoji|ReactionEmoji}
|
||||
* @readonly
|
||||
*/
|
||||
get emoji() {
|
||||
if (this._emoji instanceof Emoji) return this._emoji;
|
||||
// Check to see if the emoji has become known to the client
|
||||
if (this._emoji.id) {
|
||||
const emojis = this.message.client.emojis;
|
||||
if (emojis.has(this._emoji.id)) {
|
||||
const emoji = emojis.get(this._emoji.id);
|
||||
this._emoji = emoji;
|
||||
return emoji;
|
||||
}
|
||||
}
|
||||
return this._emoji;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a user from this reaction.
|
||||
* @param {UserResolvable} [user=this.message.client.user] The user to remove the reaction of
|
||||
* @returns {Promise<MessageReaction>}
|
||||
*/
|
||||
remove(user = this.message.client.user) {
|
||||
const message = this.message;
|
||||
const userID = this.message.client.resolver.resolveUserID(user);
|
||||
if (!userID) return Promise.reject(new Error('Couldn\'t resolve the user ID to remove from the reaction.'));
|
||||
return message.client.rest.methods.removeMessageReaction(
|
||||
message, this.emoji.identifier, userID
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all the users that gave this reaction. Resolves with a collection of users, mapped by their IDs.
|
||||
* @param {number} [limit=100] The maximum amount of users to fetch, defaults to 100
|
||||
* @param {Object} [options] Options to fetch users
|
||||
* @param {Snowflake} [options.before] Limit fetching users to those with an id lower than the supplied id
|
||||
* @param {Snowflake} [options.after] Limit fetching users to those with an id greater than the supplied id
|
||||
* @returns {Promise<Collection<Snowflake, User>>}
|
||||
*/
|
||||
fetchUsers(limit = 100, { after, before } = {}) {
|
||||
const message = this.message;
|
||||
return message.client.rest.methods.getMessageReactionUsers(
|
||||
message, this.emoji.identifier, { after, before, limit }
|
||||
).then(data => {
|
||||
const users = new Collection();
|
||||
for (const rawUser of data) {
|
||||
const user = this.message.client.dataManager.newUser(rawUser);
|
||||
this.users.set(user.id, user);
|
||||
users.set(user.id, user);
|
||||
}
|
||||
return users;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MessageReaction;
|
147
node_modules/discord.js/src/structures/OAuth2Application.js
generated
vendored
Normal file
147
node_modules/discord.js/src/structures/OAuth2Application.js
generated
vendored
Normal file
@ -0,0 +1,147 @@
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
const util = require('util');
|
||||
|
||||
/**
|
||||
* Represents an OAuth2 Application.
|
||||
*/
|
||||
class OAuth2Application {
|
||||
constructor(client, data) {
|
||||
/**
|
||||
* The client that instantiated the application
|
||||
* @name OAuth2Application#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The ID of the app
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The name of the app
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* The app's description
|
||||
* @type {string}
|
||||
*/
|
||||
this.description = data.description;
|
||||
|
||||
/**
|
||||
* The app's icon hash
|
||||
* @type {?string}
|
||||
*/
|
||||
this.icon = data.icon;
|
||||
|
||||
/**
|
||||
* The app's icon URL
|
||||
* @type {string}
|
||||
*/
|
||||
this.iconURL = `https://cdn.discordapp.com/app-icons/${this.id}/${this.icon}.jpg`;
|
||||
|
||||
/**
|
||||
* The app's RPC origins
|
||||
* @type {?string[]}
|
||||
*/
|
||||
this.rpcOrigins = data.rpc_origins;
|
||||
|
||||
/**
|
||||
* The app's redirect URIs
|
||||
* @type {string[]}
|
||||
*/
|
||||
this.redirectURIs = data.redirect_uris;
|
||||
|
||||
/**
|
||||
* If this app's bot requires a code grant when using the OAuth2 flow
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.botRequireCodeGrant = data.bot_require_code_grant;
|
||||
|
||||
/**
|
||||
* If this app's bot is public
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.botPublic = data.bot_public;
|
||||
|
||||
/**
|
||||
* If this app can use rpc
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.rpcApplicationState = data.rpc_application_state;
|
||||
|
||||
/**
|
||||
* Object containing basic info about this app's bot
|
||||
* @type {Object}
|
||||
*/
|
||||
this.bot = data.bot;
|
||||
|
||||
/**
|
||||
* The flags for the app
|
||||
* @type {number}
|
||||
*/
|
||||
this.flags = data.flags;
|
||||
|
||||
/**
|
||||
* OAuth2 secret for the application
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.secret = data.secret;
|
||||
|
||||
if (data.owner) {
|
||||
/**
|
||||
* The owner of this OAuth application
|
||||
* @type {?User}
|
||||
*/
|
||||
this.owner = this.client.dataManager.newUser(data.owner);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp the app was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return Snowflake.deconstruct(this.id).timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the app was created
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the app's secret and bot token.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @returns {OAuth2Application}
|
||||
*/
|
||||
reset() {
|
||||
return this.client.rest.methods.resetApplication(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically concatenates the app name rather than the app object.
|
||||
* @returns {string}
|
||||
*/
|
||||
toString() {
|
||||
return this.name;
|
||||
}
|
||||
}
|
||||
|
||||
OAuth2Application.prototype.reset =
|
||||
util.deprecate(OAuth2Application.prototype.reset, 'OAuth2Application#reset: userbot methods will be removed');
|
||||
|
||||
module.exports = OAuth2Application;
|
51
node_modules/discord.js/src/structures/PartialGuild.js
generated
vendored
Normal file
51
node_modules/discord.js/src/structures/PartialGuild.js
generated
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
{ splash: null,
|
||||
id: '123123123',
|
||||
icon: '123123123',
|
||||
name: 'name' }
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a guild that the client only has limited information for - e.g. from invites.
|
||||
*/
|
||||
class PartialGuild {
|
||||
constructor(client, data) {
|
||||
/**
|
||||
* The client that instantiated this PartialGuild
|
||||
* @name PartialGuild#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The ID of this guild
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The name of this guild
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* The hash of this guild's icon
|
||||
* @type {?string}
|
||||
*/
|
||||
this.icon = data.icon;
|
||||
|
||||
/**
|
||||
* The hash of the guild splash image (VIP only)
|
||||
* @type {?string}
|
||||
*/
|
||||
this.splash = data.splash;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PartialGuild;
|
44
node_modules/discord.js/src/structures/PartialGuildChannel.js
generated
vendored
Normal file
44
node_modules/discord.js/src/structures/PartialGuildChannel.js
generated
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
const Constants = require('../util/Constants');
|
||||
|
||||
/*
|
||||
{ type: 0, id: '123123', name: 'heavy-testing' } }
|
||||
*/
|
||||
|
||||
/**
|
||||
* Represents a guild channel that the client only has limited information for - e.g. from invites.
|
||||
*/
|
||||
class PartialGuildChannel {
|
||||
constructor(client, data) {
|
||||
/**
|
||||
* The client that instantiated this PartialGuildChannel
|
||||
* @name PartialGuildChannel#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The ID of this guild channel
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The name of this guild channel
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* The type of this guild channel - `text` or `voice`
|
||||
* @type {string}
|
||||
*/
|
||||
this.type = Constants.ChannelTypes.TEXT === data.type ? 'text' : 'voice';
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PartialGuildChannel;
|
69
node_modules/discord.js/src/structures/PermissionOverwrites.js
generated
vendored
Normal file
69
node_modules/discord.js/src/structures/PermissionOverwrites.js
generated
vendored
Normal file
@ -0,0 +1,69 @@
|
||||
const Permissions = require('../util/Permissions');
|
||||
|
||||
/**
|
||||
* Represents a permission overwrite for a role or member in a guild channel.
|
||||
*/
|
||||
class PermissionOverwrites {
|
||||
constructor(guildChannel, data) {
|
||||
/**
|
||||
* The GuildChannel this overwrite is for
|
||||
* @name PermissionOverwrites#channel
|
||||
* @type {GuildChannel}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'channel', { value: guildChannel });
|
||||
|
||||
if (data) this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The ID of this overwrite, either a user ID or a role ID
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The type of this overwrite
|
||||
* @type {string}
|
||||
*/
|
||||
this.type = data.type;
|
||||
|
||||
/**
|
||||
* The permissions that are denied for the user or role as a bitfield.
|
||||
* @type {number}
|
||||
* @deprecated
|
||||
*/
|
||||
this.deny = data.deny;
|
||||
|
||||
/**
|
||||
* The permissions that are allowed for the user or role as a bitfield.
|
||||
* @type {number}
|
||||
* @deprecated
|
||||
*/
|
||||
this.allow = data.allow;
|
||||
|
||||
/**
|
||||
* The permissions that are denied for the user or role.
|
||||
* @type {Permissions}
|
||||
*/
|
||||
this.denied = new Permissions(data.deny).freeze();
|
||||
|
||||
/**
|
||||
* The permissions that are allowed for the user or role.
|
||||
* @type {Permissions}
|
||||
*/
|
||||
this.allowed = new Permissions(data.allow).freeze();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete this Permission Overwrite.
|
||||
* @param {string} [reason] Reason for deleting this overwrite
|
||||
* @returns {Promise<PermissionOverwrites>}
|
||||
*/
|
||||
delete(reason) {
|
||||
return this.channel.client.rest.methods.deletePermissionOverwrites(this, reason);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PermissionOverwrites;
|
219
node_modules/discord.js/src/structures/Presence.js
generated
vendored
Normal file
219
node_modules/discord.js/src/structures/Presence.js
generated
vendored
Normal file
@ -0,0 +1,219 @@
|
||||
const { ActivityFlags, Endpoints } = require('../util/Constants');
|
||||
|
||||
/**
|
||||
* Represents a user's presence.
|
||||
*/
|
||||
class Presence {
|
||||
constructor(data = {}, client) {
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
|
||||
/**
|
||||
* The status of the presence:
|
||||
*
|
||||
* * **`online`** - user is online
|
||||
* * **`offline`** - user is offline or invisible
|
||||
* * **`idle`** - user is AFK
|
||||
* * **`dnd`** - user is in Do not Disturb
|
||||
* @type {string}
|
||||
*/
|
||||
this.status = data.status || 'offline';
|
||||
|
||||
/**
|
||||
* The game that the user is playing
|
||||
* @type {?Game}
|
||||
*/
|
||||
this.game = data.game ? new Game(data.game, this) : null;
|
||||
}
|
||||
|
||||
update(data) {
|
||||
this.status = data.status || this.status;
|
||||
this.game = data.game ? new Game(data.game, this) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this presence is equal to another
|
||||
* @param {Presence} presence The presence to compare with
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(presence) {
|
||||
return this === presence || (
|
||||
presence &&
|
||||
this.status === presence.status &&
|
||||
this.game ? this.game.equals(presence.game) : !presence.game
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a game that is part of a user's presence.
|
||||
*/
|
||||
class Game {
|
||||
constructor(data, presence) {
|
||||
Object.defineProperty(this, 'presence', { value: presence });
|
||||
|
||||
/**
|
||||
* The name of the game being played
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* The type of the game status
|
||||
* @type {number}
|
||||
*/
|
||||
this.type = data.type;
|
||||
|
||||
/**
|
||||
* If the game is being streamed, a link to the stream
|
||||
* @type {?string}
|
||||
*/
|
||||
this.url = data.url || null;
|
||||
|
||||
/**
|
||||
* Details about the activity
|
||||
* @type {?string}
|
||||
*/
|
||||
this.details = data.details || null;
|
||||
|
||||
/**
|
||||
* State of the activity
|
||||
* @type {?string}
|
||||
*/
|
||||
this.state = data.state || null;
|
||||
|
||||
/**
|
||||
* Application ID associated with this activity
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.applicationID = data.application_id || null;
|
||||
|
||||
/**
|
||||
* Timestamps for the activity
|
||||
* @type {?Object}
|
||||
* @prop {?Date} start When the activity started
|
||||
* @prop {?Date} end When the activity will end
|
||||
*/
|
||||
this.timestamps = data.timestamps ? {
|
||||
start: data.timestamps.start ? new Date(Number(data.timestamps.start)) : null,
|
||||
end: data.timestamps.end ? new Date(Number(data.timestamps.end)) : null,
|
||||
} : null;
|
||||
|
||||
/**
|
||||
* Party of the activity
|
||||
* @type {?Object}
|
||||
* @prop {?string} id ID of the party
|
||||
* @prop {number[]} size Size of the party as `[current, max]`
|
||||
*/
|
||||
this.party = data.party || null;
|
||||
|
||||
/**
|
||||
* Assets for rich presence
|
||||
* @type {?RichPresenceAssets}
|
||||
*/
|
||||
this.assets = data.assets ? new RichPresenceAssets(this, data.assets) : null;
|
||||
|
||||
this.syncID = data.sync_id;
|
||||
this._flags = data.flags;
|
||||
}
|
||||
|
||||
get flags() {
|
||||
const flags = [];
|
||||
for (const [name, flag] of Object.entries(ActivityFlags)) {
|
||||
if ((this._flags & flag) === flag) flags.push(name);
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the game is being streamed
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get streaming() {
|
||||
return this.type === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically returns the game's name instead of the Game object.
|
||||
* @returns {string}
|
||||
*/
|
||||
toString() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this game is equal to another game
|
||||
* @param {Game} game The game to compare with
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(game) {
|
||||
return this === game || (
|
||||
game &&
|
||||
this.name === game.name &&
|
||||
this.type === game.type &&
|
||||
this.url === game.url
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Assets for a rich presence
|
||||
*/
|
||||
class RichPresenceAssets {
|
||||
constructor(game, assets) {
|
||||
Object.defineProperty(this, 'game', { value: game });
|
||||
|
||||
/**
|
||||
* Hover text for the large image
|
||||
* @type {?string}
|
||||
*/
|
||||
this.largeText = assets.large_text || null;
|
||||
|
||||
/**
|
||||
* Hover text for the small image
|
||||
* @type {?string}
|
||||
*/
|
||||
this.smallText = assets.small_text || null;
|
||||
|
||||
/**
|
||||
* ID of the large image asset
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.largeImage = assets.large_image || null;
|
||||
|
||||
/**
|
||||
* ID of the small image asset
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.smallImage = assets.small_image || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL of the small image asset
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get smallImageURL() {
|
||||
if (!this.smallImage) return null;
|
||||
return Endpoints.CDN(this.game.presence.client.options.http.cdn)
|
||||
.AppAsset(this.game.applicationID, this.smallImage);
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL of the large image asset
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get largeImageURL() {
|
||||
if (!this.largeImage) return null;
|
||||
if (/^spotify:/.test(this.largeImage)) {
|
||||
return `https://i.scdn.co/image/${this.largeImage.slice(8)}`;
|
||||
}
|
||||
return Endpoints.CDN(this.game.presence.client.options.http.cdn)
|
||||
.AppAsset(this.game.applicationID, this.largeImage);
|
||||
}
|
||||
}
|
||||
|
||||
exports.Presence = Presence;
|
||||
exports.Game = Game;
|
||||
exports.RichPresenceAssets = RichPresenceAssets;
|
85
node_modules/discord.js/src/structures/ReactionCollector.js
generated
vendored
Normal file
85
node_modules/discord.js/src/structures/ReactionCollector.js
generated
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
const Collector = require('./interfaces/Collector');
|
||||
const Collection = require('../util/Collection');
|
||||
|
||||
/**
|
||||
* @typedef {CollectorOptions} ReactionCollectorOptions
|
||||
* @property {number} max The maximum total amount of reactions to collect
|
||||
* @property {number} maxEmojis The maximum number of emojis to collect
|
||||
* @property {number} maxUsers The maximum number of users to react
|
||||
*/
|
||||
|
||||
/**
|
||||
* Collects reactions on messages.
|
||||
* @extends {Collector}
|
||||
*/
|
||||
class ReactionCollector extends Collector {
|
||||
/**
|
||||
* @param {Message} message The message upon which to collect reactions
|
||||
* @param {CollectorFilter} filter The filter to apply to this collector
|
||||
* @param {ReactionCollectorOptions} [options={}] The options to apply to this collector
|
||||
*/
|
||||
constructor(message, filter, options = {}) {
|
||||
super(message.client, filter, options);
|
||||
|
||||
/**
|
||||
* The message
|
||||
* @type {Message}
|
||||
*/
|
||||
this.message = message;
|
||||
|
||||
/**
|
||||
* The users which have reacted
|
||||
* @type {Collection}
|
||||
*/
|
||||
this.users = new Collection();
|
||||
|
||||
/**
|
||||
* The total number of reactions collected
|
||||
* @type {number}
|
||||
*/
|
||||
this.total = 0;
|
||||
|
||||
this.client.setMaxListeners(this.client.getMaxListeners() + 1);
|
||||
this.client.on('messageReactionAdd', this.listener);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle an incoming reaction for possible collection.
|
||||
* @param {MessageReaction} reaction The reaction to possibly collect
|
||||
* @returns {?{key: Snowflake, value: MessageReaction}}
|
||||
* @private
|
||||
*/
|
||||
handle(reaction) {
|
||||
if (reaction.message.id !== this.message.id) return null;
|
||||
return {
|
||||
key: reaction.emoji.id || reaction.emoji.name,
|
||||
value: reaction,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check after collection to see if the collector is done.
|
||||
* @param {MessageReaction} reaction The reaction that was collected
|
||||
* @param {User} user The user that reacted
|
||||
* @returns {?string} Reason to end the collector, if any
|
||||
* @private
|
||||
*/
|
||||
postCheck(reaction, user) {
|
||||
this.users.set(user.id, user);
|
||||
if (this.options.max && ++this.total >= this.options.max) return 'limit';
|
||||
if (this.options.maxEmojis && this.collected.size >= this.options.maxEmojis) return 'emojiLimit';
|
||||
if (this.options.maxUsers && this.users.size >= this.options.maxUsers) return 'userLimit';
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove event listeners.
|
||||
* @private
|
||||
*/
|
||||
cleanup() {
|
||||
this.client.removeListener('messageReactionAdd', this.listener);
|
||||
this.client.setMaxListeners(this.client.getMaxListeners() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ReactionCollector;
|
49
node_modules/discord.js/src/structures/ReactionEmoji.js
generated
vendored
Normal file
49
node_modules/discord.js/src/structures/ReactionEmoji.js
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
/**
|
||||
* Represents a limited emoji set used for both custom and unicode emojis. Custom emojis
|
||||
* will use this class opposed to the Emoji class when the client doesn't know enough
|
||||
* information about them.
|
||||
*/
|
||||
class ReactionEmoji {
|
||||
constructor(reaction, name, id) {
|
||||
/**
|
||||
* The message reaction this emoji refers to
|
||||
* @type {MessageReaction}
|
||||
*/
|
||||
this.reaction = reaction;
|
||||
|
||||
/**
|
||||
* The name of this reaction emoji
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = name;
|
||||
|
||||
/**
|
||||
* The ID of this reaction emoji
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* The identifier of this emoji, used for message reactions
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get identifier() {
|
||||
if (this.id) return `${this.name}:${this.id}`;
|
||||
return encodeURIComponent(this.name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the text required to form a graphical emoji on Discord.
|
||||
* @example
|
||||
* // Send the emoji used in a reaction to the channel the reaction is part of
|
||||
* reaction.message.channel.send(`The emoji used is ${reaction.emoji}`);
|
||||
* @returns {string}
|
||||
*/
|
||||
toString() {
|
||||
return this.id ? `<:${this.name}:${this.id}>` : this.name;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ReactionEmoji;
|
279
node_modules/discord.js/src/structures/RichEmbed.js
generated
vendored
Normal file
279
node_modules/discord.js/src/structures/RichEmbed.js
generated
vendored
Normal file
@ -0,0 +1,279 @@
|
||||
const Attachment = require('./Attachment');
|
||||
const MessageEmbed = require('./MessageEmbed');
|
||||
let ClientDataResolver;
|
||||
|
||||
/**
|
||||
* A rich embed to be sent with a message with a fluent interface for creation.
|
||||
* @param {Object} [data] Data to set in the rich embed
|
||||
*/
|
||||
class RichEmbed {
|
||||
constructor(data = {}) {
|
||||
/**
|
||||
* Title for this Embed
|
||||
* @type {string}
|
||||
*/
|
||||
this.title = data.title;
|
||||
|
||||
/**
|
||||
* Description for this Embed
|
||||
* @type {string}
|
||||
*/
|
||||
this.description = data.description;
|
||||
|
||||
/**
|
||||
* URL for this Embed
|
||||
* @type {string}
|
||||
*/
|
||||
this.url = data.url;
|
||||
|
||||
/**
|
||||
* Color for this Embed
|
||||
* @type {number}
|
||||
*/
|
||||
this.color = data.color;
|
||||
|
||||
/**
|
||||
* Author for this Embed
|
||||
* @type {Object}
|
||||
*/
|
||||
this.author = data.author;
|
||||
|
||||
/**
|
||||
* Timestamp for this Embed
|
||||
* @type {Date}
|
||||
*/
|
||||
this.timestamp = data.timestamp;
|
||||
|
||||
/**
|
||||
* Fields for this Embed
|
||||
* @type {Object[]}
|
||||
*/
|
||||
this.fields = data.fields || [];
|
||||
|
||||
/**
|
||||
* Thumbnail for this Embed
|
||||
* @type {Object}
|
||||
*/
|
||||
this.thumbnail = data.thumbnail;
|
||||
|
||||
/**
|
||||
* Image for this Embed
|
||||
* @type {Object}
|
||||
*/
|
||||
this.image = data.image;
|
||||
|
||||
/**
|
||||
* Footer for this Embed
|
||||
* @type {Object}
|
||||
*/
|
||||
this.footer = data.footer;
|
||||
|
||||
/**
|
||||
* File to upload alongside this Embed
|
||||
* @type {FileOptions|string|Attachment}
|
||||
*/
|
||||
this.file = data.file;
|
||||
|
||||
/**
|
||||
* The files to upload alongside this Embed
|
||||
* @type {Array<FileOptions|string|Attachment>}
|
||||
*/
|
||||
this.files = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the title of this embed.
|
||||
* @param {StringResolvable} title The title
|
||||
* @returns {RichEmbed} This embed
|
||||
*/
|
||||
setTitle(title) {
|
||||
title = resolveString(title);
|
||||
if (title.length > 256) throw new RangeError('RichEmbed titles may not exceed 256 characters.');
|
||||
this.title = title;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the description of this embed.
|
||||
* @param {StringResolvable} description The description
|
||||
* @returns {RichEmbed} This embed
|
||||
*/
|
||||
setDescription(description) {
|
||||
description = resolveString(description);
|
||||
if (description.length > 2048) throw new RangeError('RichEmbed descriptions may not exceed 2048 characters.');
|
||||
this.description = description;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the URL of this embed.
|
||||
* @param {string} url The URL
|
||||
* @returns {RichEmbed} This embed
|
||||
*/
|
||||
setURL(url) {
|
||||
this.url = url;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the color of this embed.
|
||||
* @param {ColorResolvable} color The color of the embed
|
||||
* @returns {RichEmbed} This embed
|
||||
*/
|
||||
setColor(color) {
|
||||
if (!ClientDataResolver) ClientDataResolver = require('../client/ClientDataResolver');
|
||||
this.color = ClientDataResolver.resolveColor(color);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the author of this embed.
|
||||
* @param {StringResolvable} name The name of the author
|
||||
* @param {string} [icon] The icon URL of the author
|
||||
* @param {string} [url] The URL of the author
|
||||
* @returns {RichEmbed} This embed
|
||||
*/
|
||||
setAuthor(name, icon, url) {
|
||||
this.author = { name: resolveString(name), icon_url: icon, url };
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the timestamp of this embed.
|
||||
* @param {Date} [timestamp=new Date()] The timestamp
|
||||
* @returns {RichEmbed} This embed
|
||||
*/
|
||||
setTimestamp(timestamp = new Date()) {
|
||||
this.timestamp = timestamp;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a field to the embed (max 25).
|
||||
* @param {StringResolvable} name The name of the field
|
||||
* @param {StringResolvable} value The value of the field
|
||||
* @param {boolean} [inline=false] Set the field to display inline
|
||||
* @returns {RichEmbed} This embed
|
||||
*/
|
||||
addField(name, value, inline = false) {
|
||||
if (this.fields.length >= 25) throw new RangeError('RichEmbeds may not exceed 25 fields.');
|
||||
name = resolveString(name);
|
||||
if (name.length > 256) throw new RangeError('RichEmbed field names may not exceed 256 characters.');
|
||||
if (!/\S/.test(name)) throw new RangeError('RichEmbed field names may not be empty.');
|
||||
value = resolveString(value);
|
||||
if (value.length > 1024) throw new RangeError('RichEmbed field values may not exceed 1024 characters.');
|
||||
if (!/\S/.test(value)) throw new RangeError('RichEmbed field values may not be empty.');
|
||||
this.fields.push({ name, value, inline });
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience function for `<RichEmbed>.addField('\u200B', '\u200B', inline)`.
|
||||
* @param {boolean} [inline=false] Set the field to display inline
|
||||
* @returns {RichEmbed} This embed
|
||||
*/
|
||||
addBlankField(inline = false) {
|
||||
return this.addField('\u200B', '\u200B', inline);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the thumbnail of this embed.
|
||||
* @param {string} url The URL of the thumbnail
|
||||
* @returns {RichEmbed} This embed
|
||||
*/
|
||||
setThumbnail(url) {
|
||||
this.thumbnail = { url };
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the image of this embed.
|
||||
* @param {string} url The URL of the image
|
||||
* @returns {RichEmbed} This embed
|
||||
*/
|
||||
setImage(url) {
|
||||
this.image = { url };
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the footer of this embed.
|
||||
* @param {StringResolvable} text The text of the footer
|
||||
* @param {string} [icon] The icon URL of the footer
|
||||
* @returns {RichEmbed} This embed
|
||||
*/
|
||||
setFooter(text, icon) {
|
||||
text = resolveString(text);
|
||||
if (text.length > 2048) throw new RangeError('RichEmbed footer text may not exceed 2048 characters.');
|
||||
this.footer = { text, icon_url: icon };
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the file to upload alongside the embed. This file can be accessed via `attachment://fileName.extension` when
|
||||
* setting an embed image or author/footer icons. Only one file may be attached.
|
||||
* @param {FileOptions|string|Attachment} file Local path or URL to the file to attach,
|
||||
* or valid FileOptions for a file to attach
|
||||
* @returns {RichEmbed} This embed
|
||||
*/
|
||||
attachFile(file) {
|
||||
if (this.file) throw new RangeError('You may not upload more than one file at once.');
|
||||
if (file instanceof Attachment) file = file.file;
|
||||
this.file = file;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the files to upload alongside the embed. A file can be accessed via `attachment://fileName.extension` when
|
||||
* setting an embed image or author/footer icons. Multiple files can be attached.
|
||||
* @param {Array<FileOptions|string|Attachment>} files Files to attach
|
||||
* @returns {RichEmbed}
|
||||
*/
|
||||
attachFiles(files) {
|
||||
files = files.map(file => file instanceof Attachment ? file.file : file);
|
||||
this.files = this.files.concat(files);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the embed object to be processed.
|
||||
* @returns {Object} The raw data of this embed
|
||||
* @private
|
||||
*/
|
||||
_apiTransform() {
|
||||
return {
|
||||
title: this.title,
|
||||
type: 'rich',
|
||||
description: this.description,
|
||||
url: this.url,
|
||||
timestamp: this.timestamp ? new Date(this.timestamp) : null,
|
||||
color: this.color,
|
||||
fields: this.fields ?
|
||||
this.fields.map(field => ({ name: field.name, value: field.value, inline: field.inline })) :
|
||||
null,
|
||||
thumbnail: this.thumbnail ? {
|
||||
url: this.thumbnail.url,
|
||||
} : null,
|
||||
image: this.image ? {
|
||||
url: this.image.url,
|
||||
} : null,
|
||||
author: this.author ? {
|
||||
name: this.author.name,
|
||||
url: this.author.url,
|
||||
icon_url: this.author instanceof MessageEmbed.Author ? this.author.iconURL : this.author.icon_url,
|
||||
} : null,
|
||||
footer: this.footer ? {
|
||||
text: this.footer.text,
|
||||
icon_url: this.footer instanceof MessageEmbed.Footer ? this.footer.iconURL : this.footer.icon_url,
|
||||
} : null,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = RichEmbed;
|
||||
|
||||
function resolveString(data) {
|
||||
if (typeof data === 'string') return data;
|
||||
if (data instanceof Array) return data.join('\n');
|
||||
return String(data);
|
||||
}
|
376
node_modules/discord.js/src/structures/Role.js
generated
vendored
Normal file
376
node_modules/discord.js/src/structures/Role.js
generated
vendored
Normal file
@ -0,0 +1,376 @@
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const util = require('util');
|
||||
|
||||
/**
|
||||
* Represents a role on Discord.
|
||||
*/
|
||||
class Role {
|
||||
constructor(guild, data) {
|
||||
/**
|
||||
* The client that instantiated the role
|
||||
* @name Role#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: guild.client });
|
||||
|
||||
/**
|
||||
* The guild that the role belongs to
|
||||
* @type {Guild}
|
||||
*/
|
||||
this.guild = guild;
|
||||
|
||||
/**
|
||||
* Whether the role has been deleted
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.deleted = false;
|
||||
|
||||
if (data) this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The ID of the role (unique to the guild it is part of)
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The name of the role
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* The base 10 color of the role
|
||||
* @type {number}
|
||||
*/
|
||||
this.color = data.color;
|
||||
|
||||
/**
|
||||
* If true, users that are part of this role will appear in a separate category in the users list
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.hoist = data.hoist;
|
||||
|
||||
/**
|
||||
* The position of the role from the API
|
||||
* @type {number}
|
||||
*/
|
||||
this.position = data.position;
|
||||
|
||||
/**
|
||||
* The permissions bitfield of the role
|
||||
* @type {number}
|
||||
*/
|
||||
this.permissions = data.permissions;
|
||||
|
||||
/**
|
||||
* Whether or not the role is managed by an external service
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.managed = data.managed;
|
||||
|
||||
/**
|
||||
* Whether or not the role can be mentioned by anyone
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.mentionable = data.mentionable;
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp the role was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return Snowflake.deconstruct(this.id).timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the role was created
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The hexadecimal version of the role color, with a leading hashtag
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get hexColor() {
|
||||
let col = this.color.toString(16);
|
||||
while (col.length < 6) col = `0${col}`;
|
||||
return `#${col}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* The cached guild members that have this role
|
||||
* @type {Collection<Snowflake, GuildMember>}
|
||||
* @readonly
|
||||
*/
|
||||
get members() {
|
||||
return this.guild.members.filter(m => m.roles.has(this.id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the role is editable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get editable() {
|
||||
if (this.managed) return false;
|
||||
const clientMember = this.guild.member(this.client.user);
|
||||
if (!clientMember.permissions.has(Permissions.FLAGS.MANAGE_ROLES_OR_PERMISSIONS)) return false;
|
||||
return clientMember.highestRole.comparePositionTo(this) > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The position of the role in the role manager
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get calculatedPosition() {
|
||||
const sorted = this.guild._sortedRoles;
|
||||
return sorted.array().indexOf(sorted.get(this.id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an object mapping permission names to whether or not the role enables that permission.
|
||||
* @returns {Object<string, boolean>}
|
||||
* @example
|
||||
* // Print the serialized role permissions
|
||||
* console.log(role.serialize());
|
||||
*/
|
||||
serialize() {
|
||||
return new Permissions(this.permissions).serialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the role has a permission.
|
||||
* @param {PermissionResolvable} permission Permission(s) to check for
|
||||
* @param {boolean} [explicit=false] Whether to require the role to explicitly have the exact permission
|
||||
* **(deprecated)**
|
||||
* @param {boolean} [checkAdmin] Whether to allow the administrator permission to override
|
||||
* (takes priority over `explicit`)
|
||||
* @returns {boolean}
|
||||
* @example
|
||||
* // See if a role can ban a member
|
||||
* if (role.hasPermission('BAN_MEMBERS')) {
|
||||
* console.log('This role can ban members');
|
||||
* } else {
|
||||
* console.log('This role can\'t ban members');
|
||||
* }
|
||||
*/
|
||||
hasPermission(permission, explicit = false, checkAdmin) {
|
||||
return new Permissions(this.permissions).has(
|
||||
permission, typeof checkAdmin !== 'undefined' ? checkAdmin : !explicit
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the role has all specified permissions.
|
||||
* @param {PermissionResolvable} permissions The permissions to check for
|
||||
* @param {boolean} [explicit=false] Whether to require the role to explicitly have the exact permissions
|
||||
* @returns {boolean}
|
||||
* @deprecated
|
||||
*/
|
||||
hasPermissions(permissions, explicit = false) {
|
||||
return new Permissions(this.permissions).has(permissions, !explicit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares this role's position to another role's.
|
||||
* @param {Role} role Role to compare to this one
|
||||
* @returns {number} Negative number if this role's position is lower (other role's is higher),
|
||||
* positive number if this one is higher (other's is lower), 0 if equal
|
||||
*/
|
||||
comparePositionTo(role) {
|
||||
return this.constructor.comparePositions(this, role);
|
||||
}
|
||||
|
||||
/**
|
||||
* The data for a role.
|
||||
* @typedef {Object} RoleData
|
||||
* @property {string} [name] The name of the role
|
||||
* @property {ColorResolvable} [color] The color of the role, either a hex string or a base 10 number
|
||||
* @property {boolean} [hoist] Whether or not the role should be hoisted
|
||||
* @property {number} [position] The position of the role
|
||||
* @property {PermissionResolvable|number} [permissions] The permissions of the role
|
||||
* @property {boolean} [mentionable] Whether or not the role should be mentionable
|
||||
*/
|
||||
|
||||
/**
|
||||
* Edits the role.
|
||||
* @param {RoleData} data The new data for the role
|
||||
* @param {string} [reason] The reason for editing this role
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Edit name of a role
|
||||
* role.edit({ name: 'New Name' })
|
||||
* .then(updated => console.log(`Edited role name from ${role.name} to ${updated.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
edit(data, reason) {
|
||||
return this.client.rest.methods.updateGuildRole(this, data, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new name for the role.
|
||||
* @param {string} name The new name of the role
|
||||
* @param {string} [reason] Reason for changing the role's name
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Set the name of the role
|
||||
* role.setName('New Name')
|
||||
* .then(updated => console.log(`Edited role name from ${role.name} to ${updated.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setName(name, reason) {
|
||||
return this.edit({ name }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a new color for the role.
|
||||
* @param {ColorResolvable} color The color of the role
|
||||
* @param {string} [reason] Reason for changing the role's color
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Set the color of a role
|
||||
* role.setColor('#FF0000')
|
||||
* .then(updated => console.log(`Set color of role to ${role.color}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setColor(color, reason) {
|
||||
return this.edit({ color }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether or not the role should be hoisted.
|
||||
* @param {boolean} hoist Whether or not to hoist the role
|
||||
* @param {string} [reason] Reason for setting whether or not the role should be hoisted
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Set the hoist of the role
|
||||
* role.setHoist(true)
|
||||
* .then(updated => console.log(`Role hoisted: ${updated.hoist}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setHoist(hoist, reason) {
|
||||
return this.edit({ hoist }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the position of the role.
|
||||
* @param {number} position The position of the role
|
||||
* @param {boolean} [relative=false] Move the position relative to its current value
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Set the position of the role
|
||||
* role.setPosition(1)
|
||||
* .then(updated => console.log(`Role position: ${updated.position}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setPosition(position, relative) {
|
||||
return this.guild.setRolePosition(this, position, relative).then(() => this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the permissions of the role.
|
||||
* @param {PermissionResolvable} permissions The permissions of the role
|
||||
* @param {string} [reason] Reason for changing the role's permissions
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Set the permissions of the role
|
||||
* role.setPermissions(['KICK_MEMBERS', 'BAN_MEMBERS'])
|
||||
* .then(updated => console.log(`Updated permissions to ${updated.permissions.bitfield}`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Remove all permissions from a role
|
||||
* role.setPermissions(0)
|
||||
* .then(updated => console.log(`Updated permissions to ${updated.permissions.bitfield}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setPermissions(permissions, reason) {
|
||||
return this.edit({ permissions }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether this role is mentionable.
|
||||
* @param {boolean} mentionable Whether this role should be mentionable
|
||||
* @param {string} [reason] Reason for setting whether or not this role should be mentionable
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Make the role mentionable
|
||||
* role.setMentionable(true, 'Role needs to be pinged')
|
||||
* .then(updated => console.log(`Role mentionable: ${updated.mentionable}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setMentionable(mentionable, reason) {
|
||||
return this.edit({ mentionable }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the role.
|
||||
* @param {string} [reason] Reason for deleting the role
|
||||
* @returns {Promise<Role>}
|
||||
* @example
|
||||
* // Delete a role
|
||||
* role.delete('The role needed to go')
|
||||
* .then(deleted => console.log(`Deleted role ${deleted.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
delete(reason) {
|
||||
return this.client.rest.methods.deleteGuildRole(this, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this role equals another role. It compares all properties, so for most operations
|
||||
* it is advisable to just compare `role.id === role2.id` as it is much faster and is often
|
||||
* what most users need.
|
||||
* @param {Role} role Role to compare with
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(role) {
|
||||
return role &&
|
||||
this.id === role.id &&
|
||||
this.name === role.name &&
|
||||
this.color === role.color &&
|
||||
this.hoist === role.hoist &&
|
||||
this.position === role.position &&
|
||||
this.permissions === role.permissions &&
|
||||
this.managed === role.managed;
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically concatenates the role mention rather than the Role object.
|
||||
* @returns {string}
|
||||
*/
|
||||
toString() {
|
||||
if (this.id === this.guild.id) return '@everyone';
|
||||
return `<@&${this.id}>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the positions of two roles.
|
||||
* @param {Role} role1 First role to compare
|
||||
* @param {Role} 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
|
||||
*/
|
||||
static comparePositions(role1, role2) {
|
||||
if (role1.position === role2.position) return role2.id - role1.id;
|
||||
return role1.position - role2.position;
|
||||
}
|
||||
}
|
||||
|
||||
Role.prototype.hasPermissions = util
|
||||
.deprecate(Role.prototype.hasPermissions,
|
||||
'Role#hasPermissions is deprecated - use Role#hasPermission instead, it now takes an array');
|
||||
|
||||
module.exports = Role;
|
126
node_modules/discord.js/src/structures/TextChannel.js
generated
vendored
Normal file
126
node_modules/discord.js/src/structures/TextChannel.js
generated
vendored
Normal file
@ -0,0 +1,126 @@
|
||||
const GuildChannel = require('./GuildChannel');
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const Collection = require('../util/Collection');
|
||||
|
||||
/**
|
||||
* Represents a guild text channel on Discord.
|
||||
* @extends {GuildChannel}
|
||||
* @implements {TextBasedChannel}
|
||||
*/
|
||||
class TextChannel extends GuildChannel {
|
||||
constructor(guild, data) {
|
||||
super(guild, data);
|
||||
this.type = 'text';
|
||||
this.messages = new Collection();
|
||||
this._typing = new Map();
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
super.setup(data);
|
||||
|
||||
/**
|
||||
* The topic of the text channel
|
||||
* @type {?string}
|
||||
*/
|
||||
this.topic = data.topic;
|
||||
|
||||
/**
|
||||
* If the Discord considers this channel NSFW
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
this.nsfw = Boolean(data.nsfw);
|
||||
|
||||
/**
|
||||
* The ID of the last message sent in this channel, if one was sent
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.lastMessageID = data.last_message_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* A collection of members that can see this channel, mapped by their ID
|
||||
* @type {Collection<Snowflake, GuildMember>}
|
||||
* @readonly
|
||||
*/
|
||||
get members() {
|
||||
const members = new Collection();
|
||||
for (const member of this.guild.members.values()) {
|
||||
if (this.permissionsFor(member).has('READ_MESSAGES')) {
|
||||
members.set(member.id, member);
|
||||
}
|
||||
}
|
||||
return members;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch all webhooks for the channel.
|
||||
* @returns {Promise<Collection<Snowflake, Webhook>>}
|
||||
* @example
|
||||
* // Fetch webhooks
|
||||
* channel.fetchWebhooks()
|
||||
* .then(hooks => console.log(`This channel has ${hooks.size} hooks`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetchWebhooks() {
|
||||
return this.client.rest.methods.getChannelWebhooks(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this channel is flagged as NSFW.
|
||||
* @param {boolean} nsfw Whether the channel should be considered NSFW
|
||||
* @param {string} [reason] Reason for changing the channel's NSFW flag
|
||||
* @returns {Promise<TextChannel>}
|
||||
*/
|
||||
setNSFW(nsfw, reason) {
|
||||
return this.edit({ nsfw }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a webhook for the channel.
|
||||
* @param {string} name The name of the webhook
|
||||
* @param {BufferResolvable|Base64Resolvable} [avatar] The avatar for the webhook
|
||||
* @param {string} [reason] Reason for creating this webhook
|
||||
* @returns {Promise<Webhook>} webhook The created webhook
|
||||
* @example
|
||||
* channel.createWebhook('Snek', 'https://i.imgur.com/mI8XcpG.jpg')
|
||||
* .then(webhook => console.log(`Created webhook ${webhook}`))
|
||||
* .catch(console.error)
|
||||
*/
|
||||
createWebhook(name, avatar, reason) {
|
||||
if (typeof avatar === 'string' && avatar.startsWith('data:')) {
|
||||
return this.client.rest.methods.createWebhook(this, name, avatar, reason);
|
||||
} else {
|
||||
return this.client.resolver.resolveImage(avatar).then(data =>
|
||||
this.client.rest.methods.createWebhook(this, name, data, reason)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// These are here only for documentation purposes - they are implemented by TextBasedChannel
|
||||
/* eslint-disable no-empty-function */
|
||||
send() { }
|
||||
sendMessage() { }
|
||||
sendEmbed() { }
|
||||
sendFile() { }
|
||||
sendFiles() { }
|
||||
sendCode() { }
|
||||
fetchMessage() { }
|
||||
fetchMessages() { }
|
||||
fetchPinnedMessages() { }
|
||||
search() { }
|
||||
startTyping() { }
|
||||
stopTyping() { }
|
||||
get typing() { }
|
||||
get typingCount() { }
|
||||
createCollector() { }
|
||||
createMessageCollector() { }
|
||||
awaitMessages() { }
|
||||
bulkDelete() { }
|
||||
acknowledge() { }
|
||||
_cacheMessage() { }
|
||||
}
|
||||
|
||||
TextBasedChannel.applyToClass(TextChannel, true);
|
||||
|
||||
module.exports = TextChannel;
|
322
node_modules/discord.js/src/structures/User.js
generated
vendored
Normal file
322
node_modules/discord.js/src/structures/User.js
generated
vendored
Normal file
@ -0,0 +1,322 @@
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const Constants = require('../util/Constants');
|
||||
const Presence = require('./Presence').Presence;
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
const util = require('util');
|
||||
|
||||
/**
|
||||
* Represents a user on Discord.
|
||||
* @implements {TextBasedChannel}
|
||||
*/
|
||||
class User {
|
||||
constructor(client, data) {
|
||||
/**
|
||||
* The client that created the instance of the user
|
||||
* @name User#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
|
||||
if (data) this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The ID of the user
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The username of the user
|
||||
* @type {string}
|
||||
*/
|
||||
this.username = data.username;
|
||||
|
||||
/**
|
||||
* A discriminator based on username for the user
|
||||
* @type {string}
|
||||
*/
|
||||
this.discriminator = data.discriminator;
|
||||
|
||||
/**
|
||||
* The ID of the user's avatar
|
||||
* @type {string}
|
||||
*/
|
||||
this.avatar = data.avatar;
|
||||
|
||||
/**
|
||||
* Whether or not the user is a bot
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.bot = Boolean(data.bot);
|
||||
|
||||
/**
|
||||
* The ID of the last message sent by the user, if one was sent
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.lastMessageID = null;
|
||||
|
||||
/**
|
||||
* The Message object of the last message sent by the user, if one was sent
|
||||
* @type {?Message}
|
||||
*/
|
||||
this.lastMessage = null;
|
||||
}
|
||||
|
||||
patch(data) {
|
||||
for (const prop of ['id', 'username', 'discriminator', 'avatar', 'bot']) {
|
||||
if (typeof data[prop] !== 'undefined') this[prop] = data[prop];
|
||||
}
|
||||
if (data.token) this.client.token = data.token;
|
||||
}
|
||||
|
||||
/**
|
||||
* The timestamp the user was created at
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return Snowflake.deconstruct(this.id).timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* The time the user was created
|
||||
* @type {Date}
|
||||
* @readonly
|
||||
*/
|
||||
get createdAt() {
|
||||
return new Date(this.createdTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The presence of this user
|
||||
* @type {Presence}
|
||||
* @readonly
|
||||
*/
|
||||
get presence() {
|
||||
if (this.client.presences.has(this.id)) return this.client.presences.get(this.id);
|
||||
for (const guild of this.client.guilds.values()) {
|
||||
if (guild.presences.has(this.id)) return guild.presences.get(this.id);
|
||||
}
|
||||
return new Presence(undefined, this.client);
|
||||
}
|
||||
|
||||
/**
|
||||
* A link to the user's avatar
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get avatarURL() {
|
||||
if (!this.avatar) return null;
|
||||
return Constants.Endpoints.User(this).Avatar(this.client.options.http.cdn, this.avatar);
|
||||
}
|
||||
|
||||
/**
|
||||
* A link to the user's default avatar
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get defaultAvatarURL() {
|
||||
const avatars = Object.keys(Constants.DefaultAvatars);
|
||||
const avatar = avatars[this.discriminator % avatars.length];
|
||||
return Constants.Endpoints.CDN(this.client.options.http.host).Asset(`${Constants.DefaultAvatars[avatar]}.png`);
|
||||
}
|
||||
|
||||
/**
|
||||
* A link to the user's avatar if they have one. Otherwise a link to their default avatar will be returned
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get displayAvatarURL() {
|
||||
return this.avatarURL || this.defaultAvatarURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* The Discord "tag" for this user
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get tag() {
|
||||
return `${this.username}#${this.discriminator}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* The note that is set for the user
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get note() {
|
||||
return this.client.user.notes.get(this.id) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the user is typing in a channel.
|
||||
* @param {ChannelResolvable} channel The channel to check in
|
||||
* @returns {boolean}
|
||||
*/
|
||||
typingIn(channel) {
|
||||
channel = this.client.resolver.resolveChannel(channel);
|
||||
return channel._typing.has(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the time that the user started typing.
|
||||
* @param {ChannelResolvable} channel The channel to get the time in
|
||||
* @returns {?Date}
|
||||
*/
|
||||
typingSinceIn(channel) {
|
||||
channel = this.client.resolver.resolveChannel(channel);
|
||||
return channel._typing.has(this.id) ? new Date(channel._typing.get(this.id).since) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the amount of time the user has been typing in a channel for (in milliseconds), or -1 if they're not typing.
|
||||
* @param {ChannelResolvable} channel The channel to get the time in
|
||||
* @returns {number}
|
||||
*/
|
||||
typingDurationIn(channel) {
|
||||
channel = this.client.resolver.resolveChannel(channel);
|
||||
return channel._typing.has(this.id) ? channel._typing.get(this.id).elapsedTime : -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* The DM between the client's user and this user
|
||||
* @type {?DMChannel}
|
||||
* @readonly
|
||||
*/
|
||||
get dmChannel() {
|
||||
return this.client.channels.filter(c => c.type === 'dm').find(c => c.recipient.id === this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a DM channel between the client and the user.
|
||||
* @returns {Promise<DMChannel>}
|
||||
*/
|
||||
createDM() {
|
||||
return this.client.rest.methods.createDM(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a DM channel (if one exists) between the client and the user. Resolves with the channel if successful.
|
||||
* @returns {Promise<DMChannel>}
|
||||
*/
|
||||
deleteDM() {
|
||||
return this.client.rest.methods.deleteChannel(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a friend request to the user.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @returns {Promise<User>}
|
||||
*/
|
||||
addFriend() {
|
||||
return this.client.rest.methods.addFriend(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the user from your friends.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @returns {Promise<User>}
|
||||
*/
|
||||
removeFriend() {
|
||||
return this.client.rest.methods.removeFriend(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Blocks the user.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @returns {Promise<User>}
|
||||
*/
|
||||
block() {
|
||||
return this.client.rest.methods.blockUser(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unblocks the user.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @returns {Promise<User>}
|
||||
*/
|
||||
unblock() {
|
||||
return this.client.rest.methods.unblockUser(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the profile of the user.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @returns {Promise<UserProfile>}
|
||||
*/
|
||||
fetchProfile() {
|
||||
return this.client.rest.methods.fetchUserProfile(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a note for the user.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @param {string} note The note to set for the user
|
||||
* @returns {Promise<User>}
|
||||
*/
|
||||
setNote(note) {
|
||||
return this.client.rest.methods.setNote(this, note);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the user is equal to another. It compares ID, username, discriminator, avatar, and bot flags.
|
||||
* It is recommended to compare equality by using `user.id === user2.id` unless you want to compare all properties.
|
||||
* @param {User} user User to compare with
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(user) {
|
||||
let equal = user &&
|
||||
this.id === user.id &&
|
||||
this.username === user.username &&
|
||||
this.discriminator === user.discriminator &&
|
||||
this.avatar === user.avatar &&
|
||||
this.bot === Boolean(user.bot);
|
||||
|
||||
return equal;
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically concatenates the user's mention instead of the User object.
|
||||
* @returns {string}
|
||||
* @example
|
||||
* // logs: Hello from <@123456789>!
|
||||
* console.log(`Hello from ${user}!`);
|
||||
*/
|
||||
toString() {
|
||||
return `<@${this.id}>`;
|
||||
}
|
||||
|
||||
// These are here only for documentation purposes - they are implemented by TextBasedChannel
|
||||
/* eslint-disable no-empty-function */
|
||||
send() {}
|
||||
sendMessage() {}
|
||||
sendEmbed() {}
|
||||
sendFile() {}
|
||||
sendCode() {}
|
||||
}
|
||||
|
||||
TextBasedChannel.applyToClass(User);
|
||||
|
||||
User.prototype.block =
|
||||
util.deprecate(User.prototype.block, 'User#block: userbot methods will be removed');
|
||||
|
||||
User.prototype.unblock =
|
||||
util.deprecate(User.prototype.unblock, 'User#unblock: userbot methods will be removed');
|
||||
|
||||
User.prototype.addFriend =
|
||||
util.deprecate(User.prototype.addFriend, 'User#addFriend: userbot methods will be removed');
|
||||
|
||||
User.prototype.removeFriend =
|
||||
util.deprecate(User.prototype.removeFriend, 'User#removeFriend: userbot methods will be removed');
|
||||
|
||||
User.prototype.setNote =
|
||||
util.deprecate(User.prototype.setNote, 'User#setNote, userbot methods will be removed');
|
||||
|
||||
User.prototype.fetchProfile =
|
||||
util.deprecate(User.prototype.fetchProfile, 'User#fetchProfile: userbot methods will be removed');
|
||||
|
||||
module.exports = User;
|
48
node_modules/discord.js/src/structures/UserConnection.js
generated
vendored
Normal file
48
node_modules/discord.js/src/structures/UserConnection.js
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
/**
|
||||
* Represents a user connection (or "platform identity").
|
||||
*/
|
||||
class UserConnection {
|
||||
constructor(user, data) {
|
||||
/**
|
||||
* The user that owns the connection
|
||||
* @type {User}
|
||||
*/
|
||||
this.user = user;
|
||||
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The type of the connection
|
||||
* @type {string}
|
||||
*/
|
||||
this.type = data.type;
|
||||
|
||||
/**
|
||||
* The username of the connection account
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* The id of the connection account
|
||||
* @type {string}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* Whether the connection is revoked
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.revoked = data.revoked;
|
||||
|
||||
/**
|
||||
* Partial server integrations (not yet implemented)
|
||||
* @type {Object[]}
|
||||
*/
|
||||
this.integrations = data.integrations;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = UserConnection;
|
62
node_modules/discord.js/src/structures/UserProfile.js
generated
vendored
Normal file
62
node_modules/discord.js/src/structures/UserProfile.js
generated
vendored
Normal file
@ -0,0 +1,62 @@
|
||||
const Collection = require('../util/Collection');
|
||||
const UserConnection = require('./UserConnection');
|
||||
|
||||
/**
|
||||
* Represents a user's profile on Discord.
|
||||
*/
|
||||
class UserProfile {
|
||||
constructor(user, data) {
|
||||
/**
|
||||
* The owner of the profile
|
||||
* @type {User}
|
||||
*/
|
||||
this.user = user;
|
||||
|
||||
/**
|
||||
* The client that created the instance of the UserProfile
|
||||
* @name UserProfile#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: user.client });
|
||||
|
||||
/**
|
||||
* The guilds that the client user and the user share
|
||||
* @type {Collection<Snowflake, Guild>}
|
||||
*/
|
||||
this.mutualGuilds = new Collection();
|
||||
|
||||
/**
|
||||
* The user's connections
|
||||
* @type {Collection<Snowflake, UserConnection>}
|
||||
*/
|
||||
this.connections = new Collection();
|
||||
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* If the user has Discord Premium
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.premium = data.premium;
|
||||
|
||||
/**
|
||||
* The date since which the user has had Discord Premium
|
||||
* @type {?Date}
|
||||
*/
|
||||
this.premiumSince = data.premium_since ? new Date(data.premium_since) : null;
|
||||
|
||||
for (const guild of data.mutual_guilds) {
|
||||
if (this.client.guilds.has(guild.id)) {
|
||||
this.mutualGuilds.set(guild.id, this.client.guilds.get(guild.id));
|
||||
}
|
||||
}
|
||||
for (const connection of data.connected_accounts) {
|
||||
this.connections.set(connection.id, new UserConnection(this.user, connection));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = UserProfile;
|
146
node_modules/discord.js/src/structures/VoiceChannel.js
generated
vendored
Normal file
146
node_modules/discord.js/src/structures/VoiceChannel.js
generated
vendored
Normal file
@ -0,0 +1,146 @@
|
||||
const GuildChannel = require('./GuildChannel');
|
||||
const Collection = require('../util/Collection');
|
||||
const Permissions = require('../util/Permissions');
|
||||
|
||||
/**
|
||||
* Represents a guild voice channel on Discord.
|
||||
* @extends {GuildChannel}
|
||||
*/
|
||||
class VoiceChannel extends GuildChannel {
|
||||
constructor(guild, data) {
|
||||
super(guild, data);
|
||||
|
||||
/**
|
||||
* The members in this voice channel
|
||||
* @type {Collection<Snowflake, GuildMember>}
|
||||
*/
|
||||
this.members = new Collection();
|
||||
|
||||
this.type = 'voice';
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
super.setup(data);
|
||||
|
||||
/**
|
||||
* The bitrate of this voice channel
|
||||
* @type {number}
|
||||
*/
|
||||
this.bitrate = data.bitrate * 0.001;
|
||||
|
||||
/**
|
||||
* The maximum amount of users allowed in this channel - 0 means unlimited.
|
||||
* @type {number}
|
||||
*/
|
||||
this.userLimit = data.user_limit;
|
||||
}
|
||||
|
||||
/**
|
||||
* The voice connection for this voice channel, if the client is connected
|
||||
* @type {?VoiceConnection}
|
||||
* @readonly
|
||||
*/
|
||||
get connection() {
|
||||
const connection = this.guild.voiceConnection;
|
||||
if (connection && connection.channel.id === this.id) return connection;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the voice channel is full
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get full() {
|
||||
return this.userLimit > 0 && this.members.size >= this.userLimit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the channel is deletable by the client user
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get deletable() {
|
||||
return super.deletable && this.permissionsFor(this.client.user).has(Permissions.FLAGS.CONNECT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the client has permission join the voice channel
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get joinable() {
|
||||
if (this.client.browser) return false;
|
||||
if (!this.permissionsFor(this.client.user).has('CONNECT')) return false;
|
||||
if (this.full && !this.permissionsFor(this.client.user).has('MOVE_MEMBERS')) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the client has permission to send audio to the voice channel
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get speakable() {
|
||||
return this.permissionsFor(this.client.user).has('SPEAK');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bitrate of the channel (in kbps).
|
||||
* @param {number} bitrate The new bitrate
|
||||
* @param {string} [reason] Reason for changing the channel's bitrate
|
||||
* @returns {Promise<VoiceChannel>}
|
||||
* @example
|
||||
* // Set the bitrate of a voice channel
|
||||
* voiceChannel.setBitrate(48)
|
||||
* .then(vc => console.log(`Set bitrate to ${vc.bitrate}kbps for ${vc.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setBitrate(bitrate, reason) {
|
||||
bitrate *= 1000;
|
||||
return this.edit({ bitrate }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the user limit of the channel.
|
||||
* @param {number} userLimit The new user limit
|
||||
* @param {string} [reason] Reason for changing the user limit
|
||||
* @returns {Promise<VoiceChannel>}
|
||||
* @example
|
||||
* // Set the user limit of a voice channel
|
||||
* voiceChannel.setUserLimit(42)
|
||||
* .then(vc => console.log(`Set user limit to ${vc.userLimit} for ${vc.name}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setUserLimit(userLimit, reason) {
|
||||
return this.edit({ userLimit }, reason);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to join this voice channel.
|
||||
* @returns {Promise<VoiceConnection>}
|
||||
* @example
|
||||
* // Join a voice channel
|
||||
* voiceChannel.join()
|
||||
* .then(connection => console.log('Connected!'))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
join() {
|
||||
if (this.client.browser) return Promise.reject(new Error('Voice connections are not available in browsers.'));
|
||||
return this.client.voice.joinChannel(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Leaves this voice channel.
|
||||
* @example
|
||||
* // Leave a voice channel
|
||||
* voiceChannel.leave();
|
||||
*/
|
||||
leave() {
|
||||
if (this.client.browser) return;
|
||||
const connection = this.client.voice.connections.get(this.guild.id);
|
||||
if (connection && connection.channel.id === this.id) connection.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = VoiceChannel;
|
50
node_modules/discord.js/src/structures/VoiceRegion.js
generated
vendored
Normal file
50
node_modules/discord.js/src/structures/VoiceRegion.js
generated
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Represents a Discord voice region for guilds.
|
||||
*/
|
||||
class VoiceRegion {
|
||||
constructor(data) {
|
||||
/**
|
||||
* The ID of the region
|
||||
* @type {string}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* Name of the region
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* Whether the region is VIP-only
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.vip = data.vip;
|
||||
|
||||
/**
|
||||
* Whether the region is deprecated
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.deprecated = data.deprecated;
|
||||
|
||||
/**
|
||||
* Whether the region is optimal
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.optimal = data.optimal;
|
||||
|
||||
/**
|
||||
* Whether the region is custom
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.custom = data.custom;
|
||||
|
||||
/**
|
||||
* A sample hostname for what a connection might look like
|
||||
* @type {string}
|
||||
*/
|
||||
this.sampleHostname = data.sample_hostname;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = VoiceRegion;
|
301
node_modules/discord.js/src/structures/Webhook.js
generated
vendored
Normal file
301
node_modules/discord.js/src/structures/Webhook.js
generated
vendored
Normal file
@ -0,0 +1,301 @@
|
||||
const path = require('path');
|
||||
const Util = require('../util/Util');
|
||||
const Attachment = require('./Attachment');
|
||||
const RichEmbed = require('./RichEmbed');
|
||||
|
||||
/**
|
||||
* Represents a webhook.
|
||||
*/
|
||||
class Webhook {
|
||||
constructor(client, dataOrID, token) {
|
||||
if (client) {
|
||||
/**
|
||||
* The client that instantiated the webhook
|
||||
* @name Webhook#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
if (dataOrID) this.setup(dataOrID);
|
||||
} else {
|
||||
this.id = dataOrID;
|
||||
this.token = token;
|
||||
Object.defineProperty(this, 'client', { value: this });
|
||||
}
|
||||
}
|
||||
|
||||
setup(data) {
|
||||
/**
|
||||
* The name of the webhook
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
|
||||
/**
|
||||
* The token for the webhook
|
||||
* @type {string}
|
||||
*/
|
||||
Object.defineProperty(this, 'token', { value: data.token, writable: true, configurable: true });
|
||||
|
||||
/**
|
||||
* The avatar for the webhook
|
||||
* @type {?string}
|
||||
*/
|
||||
this.avatar = data.avatar;
|
||||
|
||||
/**
|
||||
* The ID of the webhook
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The guild the webhook belongs to
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.guildID = data.guild_id;
|
||||
|
||||
/**
|
||||
* The channel the webhook belongs to
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.channelID = data.channel_id;
|
||||
|
||||
if (data.user) {
|
||||
/**
|
||||
* The owner of the webhook
|
||||
* @type {?User|Object}
|
||||
*/
|
||||
this.owner = this.client.users ? this.client.users.get(data.user.id) : data.user;
|
||||
} else {
|
||||
this.owner = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Options that can be passed into send, sendMessage, sendFile, sendEmbed, and sendCode.
|
||||
* @typedef {Object} WebhookMessageOptions
|
||||
* @property {string} [username=this.name] Username override for the message
|
||||
* @property {string} [avatarURL] Avatar URL override for the message
|
||||
* @property {boolean} [tts=false] Whether or not the message should be spoken aloud
|
||||
* @property {string} [nonce=''] The nonce for the message
|
||||
* @property {Array<RichEmbed|Object>} [embeds] An array of embeds for the message
|
||||
* (see [here](https://discordapp.com/developers/docs/resources/channel#embed-object) for more details)
|
||||
* @property {boolean} [disableEveryone=this.client.options.disableEveryone] Whether or not @everyone and @here
|
||||
* should be replaced with plain-text
|
||||
* @property {FileOptions|BufferResolvable|Attachment} [file] A file to send with the message **(deprecated)**
|
||||
* @property {FileOptions[]|BufferResolvable[]|Attachment[]} [files] Files to send with the message
|
||||
* @property {string|boolean} [code] Language for optional codeblock formatting to apply
|
||||
* @property {boolean|SplitOptions} [split=false] Whether or not the message should be split into multiple messages if
|
||||
* it exceeds the character limit. If an object is provided, these are the options for splitting the message.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Send a message with this webhook.
|
||||
* @param {StringResolvable} content The content to send
|
||||
* @param {WebhookMessageOptions|Attachment|RichEmbed} [options] The options to provide,
|
||||
* can also be just a RichEmbed or Attachment
|
||||
* @returns {Promise<Message|Message[]|Object|Object[]>}
|
||||
* @example
|
||||
* // Send a basic message
|
||||
* webhook.send('hello!')
|
||||
* .then(message => console.log(`Sent message: ${message.content}`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Send a remote file
|
||||
* webhook.send({
|
||||
* files: ['https://cdn.discordapp.com/icons/222078108977594368/6e1019b3179d71046e463a75915e7244.png?size=2048']
|
||||
* })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Send a local file
|
||||
* webhook.send({
|
||||
* files: [{
|
||||
* attachment: 'entire/path/to/file.jpg',
|
||||
* name: 'file.jpg'
|
||||
* }]
|
||||
* })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Send an embed with a local image inside
|
||||
* webhook.send('This is an embed', {
|
||||
* embeds: [{
|
||||
* thumbnail: {
|
||||
* url: 'attachment://file.jpg'
|
||||
* }
|
||||
* }],
|
||||
* files: [{
|
||||
* attachment: 'entire/path/to/file.jpg',
|
||||
* name: 'file.jpg'
|
||||
* }]
|
||||
* })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
send(content, options) { // eslint-disable-line complexity
|
||||
if (!options && typeof content === 'object' && !(content instanceof Array)) {
|
||||
options = content;
|
||||
content = '';
|
||||
} else if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
if (options instanceof Attachment) options = { files: [options] };
|
||||
if (options instanceof RichEmbed) options = { embeds: [options] };
|
||||
|
||||
if (content) {
|
||||
content = this.client.resolver.resolveString(content);
|
||||
let { split, code, disableEveryone } = options;
|
||||
if (split && typeof split !== 'object') split = {};
|
||||
if (typeof code !== 'undefined' && (typeof code !== 'boolean' || code === true)) {
|
||||
content = Util.escapeMarkdown(content, true);
|
||||
content = `\`\`\`${typeof code !== 'boolean' ? code || '' : ''}\n${content}\n\`\`\``;
|
||||
if (split) {
|
||||
split.prepend = `\`\`\`${typeof code !== 'boolean' ? code || '' : ''}\n`;
|
||||
split.append = '\n```';
|
||||
}
|
||||
}
|
||||
if (disableEveryone || (typeof disableEveryone === 'undefined' && this.client.options.disableEveryone)) {
|
||||
content = content.replace(/@(everyone|here)/g, '@\u200b$1');
|
||||
}
|
||||
|
||||
if (split) content = Util.splitMessage(content, split);
|
||||
}
|
||||
|
||||
if (options.file) {
|
||||
if (options.files) options.files.push(options.file);
|
||||
else options.files = [options.file];
|
||||
}
|
||||
|
||||
if (options.embeds) {
|
||||
const files = [];
|
||||
for (const embed of options.embeds) {
|
||||
if (embed.file) files.push(embed.file);
|
||||
}
|
||||
if (options.files) options.files.push(...files);
|
||||
else options.files = files;
|
||||
}
|
||||
|
||||
if (options.embeds) options.embeds = options.embeds.map(e => new RichEmbed(e)._apiTransform());
|
||||
|
||||
if (options.files) {
|
||||
for (let i = 0; i < options.files.length; i++) {
|
||||
let file = options.files[i];
|
||||
if (typeof file === 'string' || Buffer.isBuffer(file)) file = { attachment: file };
|
||||
if (!file.name) {
|
||||
if (typeof file.attachment === 'string') {
|
||||
file.name = path.basename(file.attachment);
|
||||
} else if (file.attachment && file.attachment.path) {
|
||||
file.name = path.basename(file.attachment.path);
|
||||
} else if (file instanceof Attachment) {
|
||||
file = { attachment: file.file, name: path.basename(file.file) || 'file.jpg' };
|
||||
} else {
|
||||
file.name = 'file.jpg';
|
||||
}
|
||||
} else if (file instanceof Attachment) {
|
||||
file = file.file;
|
||||
}
|
||||
options.files[i] = file;
|
||||
}
|
||||
|
||||
return Promise.all(options.files.map(file =>
|
||||
this.client.resolver.resolveFile(file.attachment).then(resource => {
|
||||
file.file = resource;
|
||||
return file;
|
||||
})
|
||||
)).then(files => this.client.rest.methods.sendWebhookMessage(this, content, options, files));
|
||||
}
|
||||
|
||||
return this.client.rest.methods.sendWebhookMessage(this, content, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message with this webhook
|
||||
* @param {StringResolvable} content The content to send
|
||||
* @param {WebhookMessageOptions} [options={}] The options to provide
|
||||
* @returns {Promise<Message|Message[]>}
|
||||
* @deprecated
|
||||
* @example
|
||||
* // Send a message
|
||||
* webhook.sendMessage('hello!')
|
||||
* .then(message => console.log(`Sent message: ${message.content}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
sendMessage(content, options = {}) {
|
||||
return this.send(content, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a file with this webhook.
|
||||
* @param {BufferResolvable} attachment The file to send
|
||||
* @param {string} [name='file.jpg'] The name and extension of the file
|
||||
* @param {StringResolvable} [content] Text message to send with the attachment
|
||||
* @param {WebhookMessageOptions} [options] The options to provide
|
||||
* @returns {Promise<Message>}
|
||||
* @deprecated
|
||||
*/
|
||||
sendFile(attachment, name, content, options = {}) {
|
||||
return this.send(content, Object.assign(options, { file: { attachment, name } }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a code block with this webhook.
|
||||
* @param {string} lang Language for the code block
|
||||
* @param {StringResolvable} content Content of the code block
|
||||
* @param {WebhookMessageOptions} options The options to provide
|
||||
* @returns {Promise<Message|Message[]>}
|
||||
* @deprecated
|
||||
*/
|
||||
sendCode(lang, content, options = {}) {
|
||||
return this.send(content, Object.assign(options, { code: lang }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a raw slack message with this webhook.
|
||||
* @param {Object} body The raw body to send
|
||||
* @returns {Promise}
|
||||
* @example
|
||||
* // Send a slack message
|
||||
* webhook.sendSlackMessage({
|
||||
* 'username': 'Wumpus',
|
||||
* 'attachments': [{
|
||||
* 'pretext': 'this looks pretty cool',
|
||||
* 'color': '#F0F',
|
||||
* 'footer_icon': 'http://snek.s3.amazonaws.com/topSnek.png',
|
||||
* 'footer': 'Powered by sneks',
|
||||
* 'ts': Date.now() / 1000
|
||||
* }]
|
||||
* }).catch(console.error);
|
||||
*/
|
||||
sendSlackMessage(body) {
|
||||
return this.client.rest.methods.sendSlackWebhookMessage(this, body);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit the webhook.
|
||||
* @param {string} name The new name for the webhook
|
||||
* @param {BufferResolvable} [avatar] The new avatar for the webhook
|
||||
* @returns {Promise<Webhook>}
|
||||
*/
|
||||
edit(name = this.name, avatar) {
|
||||
if (avatar) {
|
||||
return this.client.resolver.resolveImage(avatar).then(data =>
|
||||
this.client.rest.methods.editWebhook(this, name, data)
|
||||
);
|
||||
}
|
||||
return this.client.rest.methods.editWebhook(this, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the webhook.
|
||||
* @param {string} [reason] Reason for deleting the webhook
|
||||
* @returns {Promise}
|
||||
*/
|
||||
delete(reason) {
|
||||
return this.client.rest.methods.deleteWebhook(this, reason);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Webhook;
|
179
node_modules/discord.js/src/structures/interfaces/Collector.js
generated
vendored
Normal file
179
node_modules/discord.js/src/structures/interfaces/Collector.js
generated
vendored
Normal file
@ -0,0 +1,179 @@
|
||||
const Collection = require('../../util/Collection');
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
|
||||
/**
|
||||
* Filter to be applied to the collector.
|
||||
* @typedef {Function} CollectorFilter
|
||||
* @param {...*} args Any arguments received by the listener
|
||||
* @param {Collection} collection The items collected by this collector
|
||||
* @returns {boolean}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options to be applied to the collector.
|
||||
* @typedef {Object} CollectorOptions
|
||||
* @property {number} [time] How long to run the collector for
|
||||
*/
|
||||
|
||||
/**
|
||||
* Abstract class for defining a new Collector.
|
||||
* @abstract
|
||||
*/
|
||||
class Collector extends EventEmitter {
|
||||
constructor(client, filter, options = {}) {
|
||||
super();
|
||||
|
||||
/**
|
||||
* The client
|
||||
* @name Collector#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
|
||||
/**
|
||||
* The filter applied to this collector
|
||||
* @type {CollectorFilter}
|
||||
*/
|
||||
this.filter = filter;
|
||||
|
||||
/**
|
||||
* The options of this collector
|
||||
* @type {CollectorOptions}
|
||||
*/
|
||||
this.options = options;
|
||||
|
||||
/**
|
||||
* The items collected by this collector
|
||||
* @type {Collection}
|
||||
*/
|
||||
this.collected = new Collection();
|
||||
|
||||
/**
|
||||
* Whether this collector has finished collecting
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.ended = false;
|
||||
|
||||
/**
|
||||
* Timeout for cleanup
|
||||
* @type {?Timeout}
|
||||
* @private
|
||||
*/
|
||||
this._timeout = null;
|
||||
|
||||
/**
|
||||
* Call this to handle an event as a collectable element
|
||||
* Accepts any event data as parameters
|
||||
* @type {Function}
|
||||
* @private
|
||||
*/
|
||||
this.listener = this._handle.bind(this);
|
||||
if (options.time) this._timeout = this.client.setTimeout(() => this.stop('time'), options.time);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {...*} args The arguments emitted by the listener
|
||||
* @emits Collector#collect
|
||||
* @private
|
||||
*/
|
||||
_handle(...args) {
|
||||
const collect = this.handle(...args);
|
||||
if (!collect || !this.filter(...args, this.collected)) return;
|
||||
|
||||
this.collected.set(collect.key, collect.value);
|
||||
|
||||
/**
|
||||
* Emitted whenever an element is collected.
|
||||
* @event Collector#collect
|
||||
* @param {*} element The element that got collected
|
||||
* @param {Collector} collector The collector
|
||||
*/
|
||||
this.emit('collect', collect.value, this);
|
||||
|
||||
const post = this.postCheck(...args);
|
||||
if (post) this.stop(post);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a promise that resolves with the next collected element;
|
||||
* rejects with collected elements if the collector finishes without receiving a next element
|
||||
* @type {Promise}
|
||||
* @readonly
|
||||
*/
|
||||
get next() {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.ended) {
|
||||
reject(this.collected);
|
||||
return;
|
||||
}
|
||||
|
||||
const cleanup = () => {
|
||||
this.removeListener('collect', onCollect);
|
||||
this.removeListener('end', onEnd);
|
||||
};
|
||||
|
||||
const onCollect = item => {
|
||||
cleanup();
|
||||
resolve(item);
|
||||
};
|
||||
|
||||
const onEnd = () => {
|
||||
cleanup();
|
||||
reject(this.collected); // eslint-disable-line prefer-promise-reject-errors
|
||||
};
|
||||
|
||||
this.on('collect', onCollect);
|
||||
this.on('end', onEnd);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop this collector and emit the `end` event.
|
||||
* @param {string} [reason='user'] The reason this collector is ending
|
||||
* @emits Collector#end
|
||||
*/
|
||||
stop(reason = 'user') {
|
||||
if (this.ended) return;
|
||||
|
||||
if (this._timeout) this.client.clearTimeout(this._timeout);
|
||||
this.ended = true;
|
||||
this.cleanup();
|
||||
|
||||
/**
|
||||
* Emitted when the collector is finished collecting.
|
||||
* @event Collector#end
|
||||
* @param {Collection} collected The elements collected by the collector
|
||||
* @param {string} reason The reason the collector ended
|
||||
*/
|
||||
this.emit('end', this.collected, reason);
|
||||
}
|
||||
|
||||
/* eslint-disable no-empty-function, valid-jsdoc */
|
||||
/**
|
||||
* Handles incoming events from the `listener` function. Returns null if the event should not be collected,
|
||||
* or returns an object describing the data that should be stored.
|
||||
* @see Collector#listener
|
||||
* @param {...*} args Any args the event listener emits
|
||||
* @returns {?{key: string, value}} Data to insert into collection, if any
|
||||
* @abstract
|
||||
*/
|
||||
handle() {}
|
||||
|
||||
/**
|
||||
* This method runs after collection to see if the collector should finish.
|
||||
* @param {...*} args Any args the event listener emits
|
||||
* @returns {?string} Reason to end the collector, if any
|
||||
* @abstract
|
||||
*/
|
||||
postCheck() {}
|
||||
|
||||
/**
|
||||
* Called when the collector is ending.
|
||||
* @abstract
|
||||
*/
|
||||
cleanup() {}
|
||||
/* eslint-enable no-empty-function, valid-jsdoc */
|
||||
}
|
||||
|
||||
module.exports = Collector;
|
609
node_modules/discord.js/src/structures/interfaces/TextBasedChannel.js
generated
vendored
Normal file
609
node_modules/discord.js/src/structures/interfaces/TextBasedChannel.js
generated
vendored
Normal file
@ -0,0 +1,609 @@
|
||||
const path = require('path');
|
||||
const Message = require('../Message');
|
||||
const MessageCollector = require('../MessageCollector');
|
||||
const Collection = require('../../util/Collection');
|
||||
const Attachment = require('../../structures/Attachment');
|
||||
const RichEmbed = require('../../structures/RichEmbed');
|
||||
const Snowflake = require('../../util/Snowflake');
|
||||
const util = require('util');
|
||||
|
||||
/**
|
||||
* Interface for classes that have text-channel-like features.
|
||||
* @interface
|
||||
*/
|
||||
class TextBasedChannel {
|
||||
constructor() {
|
||||
/**
|
||||
* A collection containing the messages sent to this channel
|
||||
* @type {Collection<Snowflake, Message>}
|
||||
*/
|
||||
this.messages = new Collection();
|
||||
|
||||
/**
|
||||
* The ID of the last message in the channel, if one was sent
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.lastMessageID = null;
|
||||
|
||||
/**
|
||||
* The Message object of the last message in the channel, if one was sent
|
||||
* @type {?Message}
|
||||
*/
|
||||
this.lastMessage = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Options provided when sending or editing a message.
|
||||
* @typedef {Object} MessageOptions
|
||||
* @property {boolean} [tts=false] Whether or not the message should be spoken aloud
|
||||
* @property {string} [nonce=''] The nonce for the message
|
||||
* @property {RichEmbed|Object} [embed] An embed for the message
|
||||
* (see [here](https://discordapp.com/developers/docs/resources/channel#embed-object) for more details)
|
||||
* @property {boolean} [disableEveryone=this.client.options.disableEveryone] Whether or not @everyone and @here
|
||||
* should be replaced with plain-text
|
||||
* @property {FileOptions|BufferResolvable|Attachment} [file] A file to send with the message **(deprecated)**
|
||||
* @property {FileOptions[]|BufferResolvable[]|Attachment[]} [files] Files to send with the message
|
||||
* @property {string|boolean} [code] Language for optional codeblock formatting to apply
|
||||
* @property {boolean|SplitOptions} [split=false] Whether or not the message should be split into multiple messages if
|
||||
* it exceeds the character limit. If an object is provided, these are the options for splitting the message
|
||||
* @property {UserResolvable} [reply] User to reply to (prefixes the message with a mention, except in DMs)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} FileOptions
|
||||
* @property {BufferResolvable} attachment File to attach
|
||||
* @property {string} [name='file.jpg'] Filename of the attachment
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options for splitting a message.
|
||||
* @typedef {Object} SplitOptions
|
||||
* @property {number} [maxLength=1950] Maximum character length per message piece
|
||||
* @property {string} [char='\n'] Character to split the message with
|
||||
* @property {string} [prepend=''] Text to prepend to every piece except the first
|
||||
* @property {string} [append=''] Text to append to every piece except the last
|
||||
*/
|
||||
|
||||
/**
|
||||
* Send a message to this channel.
|
||||
* @param {StringResolvable} [content] Text for the message
|
||||
* @param {MessageOptions|Attachment|RichEmbed} [options] Options for the message,
|
||||
* can also be just a RichEmbed or Attachment
|
||||
* @returns {Promise<Message|Message[]>}
|
||||
* @example
|
||||
* // Send a basic message
|
||||
* channel.send('hello!')
|
||||
* .then(message => console.log(`Sent message: ${message.content}`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Send a remote file
|
||||
* channel.send({
|
||||
* files: ['https://cdn.discordapp.com/icons/222078108977594368/6e1019b3179d71046e463a75915e7244.png?size=2048']
|
||||
* })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Send a local file
|
||||
* channel.send({
|
||||
* files: [{
|
||||
* attachment: 'entire/path/to/file.jpg',
|
||||
* name: 'file.jpg'
|
||||
* }]
|
||||
* })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Send an embed with a local image inside
|
||||
* channel.send('This is an embed', {
|
||||
* embed: {
|
||||
* thumbnail: {
|
||||
* url: 'attachment://file.jpg'
|
||||
* }
|
||||
* },
|
||||
* files: [{
|
||||
* attachment: 'entire/path/to/file.jpg',
|
||||
* name: 'file.jpg'
|
||||
* }]
|
||||
* })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
// eslint-disable-next-line complexity
|
||||
send(content, options) {
|
||||
if (!options && typeof content === 'object' && !(content instanceof Array)) {
|
||||
options = content;
|
||||
content = '';
|
||||
} else if (!options) {
|
||||
options = {};
|
||||
}
|
||||
|
||||
const { reply } = options;
|
||||
if (options instanceof Attachment) options = { files: [options.file] };
|
||||
if (options instanceof RichEmbed) {
|
||||
if (options.reply) options.reply = undefined;
|
||||
options = { embed: options };
|
||||
}
|
||||
options.reply = reply;
|
||||
|
||||
if (options.embed) {
|
||||
if (options.embed.file) {
|
||||
if (options.files) options.files.push(options.embed.file);
|
||||
else options.files = [options.embed.file];
|
||||
}
|
||||
if (options.embed.files) {
|
||||
if (options.files) options.files = options.files.concat(options.embed.files);
|
||||
else options.files = options.embed.files;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.file) {
|
||||
if (options.files) options.files.push(options.file);
|
||||
else options.files = [options.file];
|
||||
}
|
||||
|
||||
if (options.embed) options.embed = new RichEmbed(options.embed)._apiTransform();
|
||||
|
||||
if (options.files) {
|
||||
for (let i = 0; i < options.files.length; i++) {
|
||||
let file = options.files[i];
|
||||
if (!file || typeof file === 'string' || Buffer.isBuffer(file)) file = { attachment: file };
|
||||
if (!file.name) {
|
||||
if (typeof file.attachment === 'string') {
|
||||
file.name = path.basename(file.attachment);
|
||||
} else if (file.attachment && file.attachment.path) {
|
||||
file.name = path.basename(file.attachment.path);
|
||||
} else if (file instanceof Attachment) {
|
||||
file = { attachment: file.file, name: path.basename(file.file) || 'file.jpg' };
|
||||
} else {
|
||||
file.name = 'file.jpg';
|
||||
}
|
||||
} else if (file instanceof Attachment) {
|
||||
file = file.file;
|
||||
}
|
||||
options.files[i] = file;
|
||||
}
|
||||
|
||||
return Promise.all(options.files.map(file =>
|
||||
this.client.resolver.resolveFile(file.attachment).then(resource => {
|
||||
file.file = resource;
|
||||
return file;
|
||||
})
|
||||
)).then(files => this.client.rest.methods.sendMessage(this, content, options, files));
|
||||
}
|
||||
|
||||
return this.client.rest.methods.sendMessage(this, content, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a single message from this channel, regardless of it being cached or not. Since the single message fetching
|
||||
* endpoint is reserved for bot accounts, this abstracts the `fetchMessages` method to obtain the single message when
|
||||
* using a user account.
|
||||
* @param {Snowflake} messageID ID of the message to get
|
||||
* @returns {Promise<Message>}
|
||||
* @example
|
||||
* // Get message
|
||||
* channel.fetchMessage('99539446449315840')
|
||||
* .then(message => console.log(message.content))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetchMessage(messageID) {
|
||||
if (!this.client.user.bot) {
|
||||
return this.fetchMessages({ limit: 1, around: messageID }).then(messages => {
|
||||
const msg = messages.get(messageID);
|
||||
if (!msg) throw new Error('Message not found.');
|
||||
return msg;
|
||||
});
|
||||
}
|
||||
return this.client.rest.methods.getChannelMessage(this, messageID).then(data => {
|
||||
const msg = data instanceof Message ? data : new Message(this, data, this.client);
|
||||
this._cacheMessage(msg);
|
||||
return msg;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The parameters to pass in when requesting previous messages from a channel. `around`, `before` and
|
||||
* `after` are mutually exclusive. All the parameters are optional.
|
||||
* @typedef {Object} ChannelLogsQueryOptions
|
||||
* @property {number} [limit=50] Number of messages to acquire
|
||||
* @property {Snowflake} [before] ID of a message to get the messages that were posted before it
|
||||
* @property {Snowflake} [after] ID of a message to get the messages that were posted after it
|
||||
* @property {Snowflake} [around] ID of a message to get the messages that were posted around it
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets the past messages sent in this channel. Resolves with a collection mapping message ID's to Message objects.
|
||||
* <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 {ChannelLogsQueryOptions} [options={}] Query parameters to pass in
|
||||
* @returns {Promise<Collection<Snowflake, Message>>}
|
||||
* @example
|
||||
* // Get messages
|
||||
* channel.fetchMessages({ limit: 10 })
|
||||
* .then(messages => console.log(`Received ${messages.size} messages`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Get messages and filter by user ID
|
||||
* channel.fetchMessages()
|
||||
* .then(messages => console.log(`${messages.filter(m => m.author.id === '84484653687267328').size} messages`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetchMessages(options = {}) {
|
||||
return this.client.rest.methods.getChannelMessages(this, options).then(data => {
|
||||
const messages = new Collection();
|
||||
for (const message of data) {
|
||||
const msg = new Message(this, message, this.client);
|
||||
messages.set(message.id, msg);
|
||||
this._cacheMessage(msg);
|
||||
}
|
||||
return messages;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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>
|
||||
* @returns {Promise<Collection<Snowflake, Message>>}
|
||||
* @example
|
||||
* // Get pinned messages
|
||||
* channel.fetchPinnedMessages()
|
||||
* .then(messages => console.log(`Received ${messages.size} messages`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetchPinnedMessages() {
|
||||
return this.client.rest.methods.getChannelPinnedMessages(this).then(data => {
|
||||
const messages = new Collection();
|
||||
for (const message of data) {
|
||||
const msg = new Message(this, message, this.client);
|
||||
messages.set(message.id, msg);
|
||||
this._cacheMessage(msg);
|
||||
}
|
||||
return messages;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} MessageSearchOptions
|
||||
* @property {string} [content] Message content
|
||||
* @property {Snowflake} [maxID] Maximum ID for the filter
|
||||
* @property {Snowflake} [minID] Minimum ID for the filter
|
||||
* @property {string} [has] One of `link`, `embed`, `file`, `video`, `image`, or `sound`,
|
||||
* or add `-` to negate (e.g. `-file`)
|
||||
* @property {ChannelResolvable} [channel] Channel to limit search to (only for guild search endpoint)
|
||||
* @property {UserResolvable} [author] Author to limit search
|
||||
* @property {string} [authorType] One of `user`, `bot`, `webhook`, or add `-` to negate (e.g. `-webhook`)
|
||||
* @property {string} [sortBy='recent'] `recent` or `relevant`
|
||||
* @property {string} [sortOrder='desc'] `asc` or `desc`
|
||||
* @property {number} [contextSize=2] How many messages to get around the matched message (0 to 2)
|
||||
* @property {number} [limit=25] Maximum number of results to get (1 to 25)
|
||||
* @property {number} [offset=0] Offset the "pages" of results (since you can only see 25 at a time)
|
||||
* @property {UserResolvable} [mentions] Mentioned user filter
|
||||
* @property {boolean} [mentionsEveryone] If everyone is mentioned
|
||||
* @property {string} [linkHostname] Filter links by hostname
|
||||
* @property {string} [embedProvider] The name of an embed provider
|
||||
* @property {string} [embedType] one of `image`, `video`, `url`, `rich`
|
||||
* @property {string} [attachmentFilename] The name of an attachment
|
||||
* @property {string} [attachmentExtension] The extension of an attachment
|
||||
* @property {Date} [before] Date to find messages before
|
||||
* @property {Date} [after] Date to find messages before
|
||||
* @property {Date} [during] Date to find messages during (range of date to date + 24 hours)
|
||||
* @property {boolean} [nsfw=false] Include results from NSFW channels
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} MessageSearchResult
|
||||
* @property {number} totalResults Total result count
|
||||
* @property {Message[][]} messages Array of message results
|
||||
* The message which has triggered the result will have the `hit` property set to `true`
|
||||
*/
|
||||
|
||||
/**
|
||||
* Performs a search within the channel.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @param {MessageSearchOptions} [options={}] Options to pass to the search
|
||||
* @returns {Promise<MessageSearchResult>}
|
||||
* @example
|
||||
* channel.search({
|
||||
* content: 'discord.js',
|
||||
* before: '2016-11-17'
|
||||
* }).then(res => {
|
||||
* const hit = res.messages[0].find(m => m.hit).content;
|
||||
* console.log(`I found: **${hit}**, total results: ${res.totalResults}`);
|
||||
* }).catch(console.error);
|
||||
*/
|
||||
search(options = {}) {
|
||||
return this.client.rest.methods.search(this, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a typing indicator in the channel.
|
||||
* @param {number} [count] The number of times startTyping should be considered to have been called
|
||||
* @example
|
||||
* // Start typing in a channel
|
||||
* channel.startTyping();
|
||||
*/
|
||||
startTyping(count) {
|
||||
if (typeof count !== 'undefined' && count < 1) throw new RangeError('Count must be at least 1.');
|
||||
if (this.client.user._typing.has(this.id)) {
|
||||
const entry = this.client.user._typing.get(this.id);
|
||||
entry.count = count || entry.count + 1;
|
||||
return;
|
||||
}
|
||||
|
||||
const entry = {
|
||||
count: count || 1,
|
||||
interval: this.client.setInterval(() => {
|
||||
this.client.rest.methods.sendTyping(this.id).catch(() => {
|
||||
this.client.clearInterval(entry.interval);
|
||||
this.client.user._typing.delete(this.id);
|
||||
});
|
||||
}, 9000),
|
||||
};
|
||||
this.client.rest.methods.sendTyping(this.id).catch(() => {
|
||||
this.client.clearInterval(entry.interval);
|
||||
this.client.user._typing.delete(this.id);
|
||||
});
|
||||
this.client.user._typing.set(this.id, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the typing indicator in the channel.
|
||||
* The indicator will only stop if this is called as many times as startTyping().
|
||||
* <info>It can take a few seconds for the client user to stop typing.</info>
|
||||
* @param {boolean} [force=false] Whether or not to reset the call count and force the indicator to stop
|
||||
* @example
|
||||
* // Reduce the typing count by one and stop typing if it reached 0
|
||||
* channel.stopTyping();
|
||||
* @example
|
||||
* // Force typing to fully stop in a channel
|
||||
* channel.stopTyping(true);
|
||||
*/
|
||||
stopTyping(force = false) {
|
||||
if (this.client.user._typing.has(this.id)) {
|
||||
const entry = this.client.user._typing.get(this.id);
|
||||
entry.count--;
|
||||
if (entry.count <= 0 || force) {
|
||||
this.client.clearInterval(entry.interval);
|
||||
this.client.user._typing.delete(this.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the typing indicator is being shown in the channel
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get typing() {
|
||||
return this.client.user._typing.has(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of times `startTyping` has been called
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
get typingCount() {
|
||||
if (this.client.user._typing.has(this.id)) return this.client.user._typing.get(this.id).count;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Message Collector
|
||||
* @param {CollectorFilter} filter The filter to create the collector with
|
||||
* @param {MessageCollectorOptions} [options={}] The options to pass to the collector
|
||||
* @returns {MessageCollector}
|
||||
* @deprecated
|
||||
*/
|
||||
createCollector(filter, options) {
|
||||
return this.createMessageCollector(filter, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Message Collector.
|
||||
* @param {CollectorFilter} filter The filter to create the collector with
|
||||
* @param {MessageCollectorOptions} [options={}] The options to pass to the collector
|
||||
* @returns {MessageCollector}
|
||||
* @example
|
||||
* // Create a message collector
|
||||
* const filter = m => m.content.includes('discord');
|
||||
* const collector = channel.createMessageCollector(filter, { time: 15000 });
|
||||
* collector.on('collect', m => console.log(`Collected ${m.content}`));
|
||||
* collector.on('end', collected => console.log(`Collected ${collected.size} items`));
|
||||
*/
|
||||
createMessageCollector(filter, options = {}) {
|
||||
return new MessageCollector(this, filter, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* An object containing the same properties as CollectorOptions, but a few more:
|
||||
* @typedef {MessageCollectorOptions} AwaitMessagesOptions
|
||||
* @property {string[]} [errors] Stop/end reasons that cause the promise to reject
|
||||
*/
|
||||
|
||||
/**
|
||||
* Similar to createCollector but in promise form. Resolves with a collection of messages that pass the specified
|
||||
* filter.
|
||||
* @param {CollectorFilter} filter The filter function to use
|
||||
* @param {AwaitMessagesOptions} [options={}] Optional options to pass to the internal collector
|
||||
* @returns {Promise<Collection<Snowflake, Message>>}
|
||||
* @example
|
||||
* // Await !vote messages
|
||||
* const filter = m => m.content.startsWith('!vote');
|
||||
* // Errors: ['time'] treats ending because of the time limit as an error
|
||||
* channel.awaitMessages(filter, { max: 4, time: 60000, errors: ['time'] })
|
||||
* .then(collected => console.log(collected.size))
|
||||
* .catch(collected => console.log(`After a minute, only ${collected.size} out of 4 voted.`));
|
||||
*/
|
||||
awaitMessages(filter, options = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const collector = this.createCollector(filter, options);
|
||||
collector.once('end', (collection, reason) => {
|
||||
if (options.errors && options.errors.includes(reason)) {
|
||||
reject(collection);
|
||||
} else {
|
||||
resolve(collection);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk delete given messages that are newer than two weeks.
|
||||
* <warn>This is only available when using a bot account.</warn>
|
||||
* @param {Collection<Snowflake, Message>|Message[]|Snowflake[]|number} messages
|
||||
* Messages or number of messages to delete
|
||||
* @param {boolean} [filterOld=false] Filter messages to remove those which are older than two weeks automatically
|
||||
* @returns {Promise<Collection<Snowflake, Message>>} Deleted messages
|
||||
* @example
|
||||
* // Bulk delete messages
|
||||
* channel.bulkDelete(5)
|
||||
* .then(messages => console.log(`Bulk deleted ${messages.size} messages`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
bulkDelete(messages, filterOld = false) {
|
||||
if (messages instanceof Array || messages instanceof Collection) {
|
||||
let messageIDs = messages instanceof Collection ? messages.keyArray() : messages.map(m => m.id || m);
|
||||
if (filterOld) {
|
||||
messageIDs = messageIDs.filter(id => Date.now() - Snowflake.deconstruct(id).date.getTime() < 1209600000);
|
||||
}
|
||||
if (messageIDs.length === 0) return Promise.resolve(new Collection());
|
||||
if (messageIDs.length === 1) {
|
||||
return this.fetchMessage(messageIDs[0]).then(m => m.delete()).then(m => new Collection([[m.id, m]]));
|
||||
}
|
||||
return this.client.rest.methods.bulkDeleteMessages(this, messageIDs);
|
||||
}
|
||||
if (!isNaN(messages)) return this.fetchMessages({ limit: messages }).then(msgs => this.bulkDelete(msgs, filterOld));
|
||||
throw new TypeError('The messages must be an Array, Collection, or number.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks all messages in this channel as read.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @returns {Promise<TextChannel|GroupDMChannel|DMChannel>}
|
||||
*/
|
||||
acknowledge() {
|
||||
if (!this.lastMessageID) return Promise.resolve(this);
|
||||
return this.client.rest.methods.ackTextChannel(this);
|
||||
}
|
||||
|
||||
_cacheMessage(message) {
|
||||
const maxSize = this.client.options.messageCacheMaxSize;
|
||||
if (maxSize === 0) return null;
|
||||
if (this.messages.size >= maxSize && maxSize > 0) this.messages.delete(this.messages.firstKey());
|
||||
this.messages.set(message.id, message);
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
/** @lends TextBasedChannel.prototype */
|
||||
const Deprecated = {
|
||||
/**
|
||||
* Send a message to this channel.
|
||||
* @param {StringResolvable} [content] Text for the message
|
||||
* @param {MessageOptions} [options={}] Options for the message
|
||||
* @returns {Promise<Message|Message[]>}
|
||||
* @deprecated
|
||||
* @example
|
||||
* // Send a message
|
||||
* channel.sendMessage('hello!')
|
||||
* .then(message => console.log(`Sent message: ${message.content}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
sendMessage(content, options) {
|
||||
return this.send(content, options);
|
||||
},
|
||||
|
||||
/**
|
||||
* Send an embed to this channel.
|
||||
* @param {RichEmbed|Object} embed Embed for the message
|
||||
* @param {string} [content] Text for the message
|
||||
* @param {MessageOptions} [options] Options for the message
|
||||
* @returns {Promise<Message>}
|
||||
* @deprecated
|
||||
*/
|
||||
sendEmbed(embed, content, options) {
|
||||
if (!options && typeof content === 'object' && !(content instanceof Array)) {
|
||||
options = content;
|
||||
content = '';
|
||||
} else if (!options) {
|
||||
options = {};
|
||||
}
|
||||
return this.send(content, Object.assign(options, { embed }));
|
||||
},
|
||||
|
||||
/**
|
||||
* Send files to this channel.
|
||||
* @param {FileOptions[]|string[]} files Files to send with the message
|
||||
* @param {StringResolvable} [content] Text for the message
|
||||
* @param {MessageOptions} [options] Options for the message
|
||||
* @returns {Promise<Message>}
|
||||
* @deprecated
|
||||
*/
|
||||
sendFiles(files, content, options = {}) {
|
||||
return this.send(content, Object.assign(options, { files }));
|
||||
},
|
||||
|
||||
/**
|
||||
* Send a file to this channel.
|
||||
* @param {BufferResolvable} attachment File to send
|
||||
* @param {string} [name='file.jpg'] Name and extension of the file
|
||||
* @param {StringResolvable} [content] Text for the message
|
||||
* @param {MessageOptions} [options] Options for the message
|
||||
* @returns {Promise<Message>}
|
||||
* @deprecated
|
||||
*/
|
||||
sendFile(attachment, name, content, options = {}) {
|
||||
return this.send({ files: [{ attachment, name }], content, options });
|
||||
},
|
||||
|
||||
/**
|
||||
* Send a code block to this channel.
|
||||
* @param {string} lang Language for the code block
|
||||
* @param {StringResolvable} content Content of the code block
|
||||
* @param {MessageOptions} [options] Options for the message
|
||||
* @returns {Promise<Message|Message[]>}
|
||||
* @deprecated
|
||||
*/
|
||||
sendCode(lang, content, options = {}) {
|
||||
return this.send(content, Object.assign(options, { code: lang }));
|
||||
},
|
||||
};
|
||||
|
||||
for (const key of Object.keys(Deprecated)) {
|
||||
TextBasedChannel.prototype[key] = util.deprecate(Deprecated[key], `TextChannel#${key}: use TextChannel#send instead`);
|
||||
}
|
||||
|
||||
exports.applyToClass = (structure, full = false, ignore = []) => {
|
||||
const props = ['send', 'sendMessage', 'sendEmbed', 'sendFile', 'sendFiles', 'sendCode'];
|
||||
if (full) {
|
||||
props.push(
|
||||
'_cacheMessage',
|
||||
'acknowledge',
|
||||
'fetchMessages',
|
||||
'fetchMessage',
|
||||
'search',
|
||||
'bulkDelete',
|
||||
'startTyping',
|
||||
'stopTyping',
|
||||
'typing',
|
||||
'typingCount',
|
||||
'fetchPinnedMessages',
|
||||
'createCollector',
|
||||
'createMessageCollector',
|
||||
'awaitMessages'
|
||||
);
|
||||
}
|
||||
for (const prop of props) {
|
||||
if (ignore.includes(prop)) continue;
|
||||
Object.defineProperty(structure.prototype, prop, Object.getOwnPropertyDescriptor(TextBasedChannel.prototype, prop));
|
||||
}
|
||||
};
|
||||
|
||||
TextBasedChannel.prototype.acknowledge = util.deprecate(
|
||||
TextBasedChannel.prototype.acknowledge, 'TextBasedChannel#acknowledge: userbot methods will be removed'
|
||||
);
|
||||
|
||||
TextBasedChannel.prototype.search =
|
||||
util.deprecate(TextBasedChannel.prototype.search, 'TextBasedChannel#search: userbot methods will be removed');
|
26
node_modules/discord.js/src/structures/shared/resolvePermissions.js
generated
vendored
Normal file
26
node_modules/discord.js/src/structures/shared/resolvePermissions.js
generated
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
const Permissions = require('../../util/Permissions');
|
||||
const Collection = require('../../util/Collection');
|
||||
|
||||
module.exports = function resolvePermissions(overwrites, guild) {
|
||||
if (overwrites instanceof Collection || overwrites instanceof Array) {
|
||||
overwrites = overwrites.map(overwrite => {
|
||||
const role = this.client.resolver.resolveRole(guild, overwrite.id);
|
||||
if (role) {
|
||||
overwrite.id = role.id;
|
||||
overwrite.type = 'role';
|
||||
} else {
|
||||
overwrite.id = this.client.resolver.resolveUserID(overwrite.id);
|
||||
overwrite.type = 'member';
|
||||
}
|
||||
|
||||
return {
|
||||
allow: Permissions.resolve(overwrite.allow || overwrite.allowed || 0),
|
||||
deny: Permissions.resolve(overwrite.deny || overwrite.denied || 0),
|
||||
type: overwrite.type,
|
||||
id: overwrite.id,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
return overwrites;
|
||||
};
|
Reference in New Issue
Block a user