This commit is contained in:
2020-12-12 16:58:15 +01:00
parent d024fe6a3e
commit fac6006da9
341 changed files with 60376 additions and 0 deletions

38
node_modules/discord.js/src/util/ActivityFlags.js generated vendored Normal file
View File

@@ -0,0 +1,38 @@
'use strict';
const BitField = require('./BitField');
/**
* Data structure that makes it easy to interact with an {@link Activity#flags} bitfield.
* @extends {BitField}
*/
class ActivityFlags extends BitField {}
/**
* @name ActivityFlags
* @kind constructor
* @memberof ActivityFlags
* @param {BitFieldResolvable} [bits=0] Bit(s) to read from
*/
/**
* Numeric activity flags. All available properties:
* * `INSTANCE`
* * `JOIN`
* * `SPECTATE`
* * `JOIN_REQUEST`
* * `SYNC`
* * `PLAY`
* @type {Object}
* @see {@link https://discord.com/developers/docs/topics/gateway#activity-object-activity-flags}
*/
ActivityFlags.FLAGS = {
INSTANCE: 1 << 0,
JOIN: 1 << 1,
SPECTATE: 1 << 2,
JOIN_REQUEST: 1 << 3,
SYNC: 1 << 4,
PLAY: 1 << 5,
};
module.exports = ActivityFlags;

164
node_modules/discord.js/src/util/BitField.js generated vendored Normal file
View File

@@ -0,0 +1,164 @@
'use strict';
const { RangeError } = require('../errors');
/**
* Data structure that makes it easy to interact with a bitfield.
*/
class BitField {
/**
* @param {BitFieldResolvable} [bits=0] Bit(s) to read from
*/
constructor(bits) {
/**
* Bitfield of the packed bits
* @type {number}
*/
this.bitfield = this.constructor.resolve(bits);
}
/**
* Checks whether the bitfield has a bit, or any of multiple bits.
* @param {BitFieldResolvable} bit Bit(s) to check for
* @returns {boolean}
*/
any(bit) {
return (this.bitfield & this.constructor.resolve(bit)) !== 0;
}
/**
* Checks if this bitfield equals another
* @param {BitFieldResolvable} bit Bit(s) to check for
* @returns {boolean}
*/
equals(bit) {
return this.bitfield === this.constructor.resolve(bit);
}
/**
* Checks whether the bitfield has a bit, or multiple bits.
* @param {BitFieldResolvable} bit Bit(s) to check for
* @returns {boolean}
*/
has(bit) {
if (Array.isArray(bit)) return bit.every(p => this.has(p));
bit = this.constructor.resolve(bit);
return (this.bitfield & bit) === bit;
}
/**
* Gets all given bits that are missing from the bitfield.
* @param {BitFieldResolvable} bits Bit(s) to check for
* @param {...*} hasParams Additional parameters for the has method, if any
* @returns {string[]}
*/
missing(bits, ...hasParams) {
if (!Array.isArray(bits)) bits = new this.constructor(bits).toArray(false);
return bits.filter(p => !this.has(p, ...hasParams));
}
/**
* Freezes these bits, making them immutable.
* @returns {Readonly<BitField>} These bits
*/
freeze() {
return Object.freeze(this);
}
/**
* Adds bits to these ones.
* @param {...BitFieldResolvable} [bits] Bits to add
* @returns {BitField} These bits or new BitField if the instance is frozen.
*/
add(...bits) {
let total = 0;
for (const bit of bits) {
total |= this.constructor.resolve(bit);
}
if (Object.isFrozen(this)) return new this.constructor(this.bitfield | total);
this.bitfield |= total;
return this;
}
/**
* Removes bits from these.
* @param {...BitFieldResolvable} [bits] Bits to remove
* @returns {BitField} These bits or new BitField if the instance is frozen.
*/
remove(...bits) {
let total = 0;
for (const bit of bits) {
total |= this.constructor.resolve(bit);
}
if (Object.isFrozen(this)) return new this.constructor(this.bitfield & ~total);
this.bitfield &= ~total;
return this;
}
/**
* Gets an object mapping field names to a {@link boolean} indicating whether the
* bit is available.
* @param {...*} hasParams Additional parameters for the has method, if any
* @returns {Object}
*/
serialize(...hasParams) {
const serialized = {};
for (const [flag, bit] of Object.entries(this.constructor.FLAGS)) serialized[flag] = this.has(bit, ...hasParams);
return serialized;
}
/**
* Gets an {@link Array} of bitfield names based on the bits available.
* @param {...*} hasParams Additional parameters for the has method, if any
* @returns {string[]}
*/
toArray(...hasParams) {
return Object.keys(this.constructor.FLAGS).filter(bit => this.has(bit, ...hasParams));
}
toJSON() {
return this.bitfield;
}
valueOf() {
return this.bitfield;
}
*[Symbol.iterator]() {
yield* this.toArray();
}
/**
* Data that can be resolved to give a bitfield. This can be:
* * A string (see {@link BitField.FLAGS})
* * A bit number
* * An instance of BitField
* * An Array of BitFieldResolvable
* @typedef {string|number|BitField|BitFieldResolvable[]} BitFieldResolvable
*/
/**
* Resolves bitfields to their numeric form.
* @param {BitFieldResolvable} [bit=0] - bit(s) to resolve
* @returns {number}
*/
static resolve(bit = 0) {
if (typeof bit === 'number' && bit >= 0) return bit;
if (bit instanceof BitField) return bit.bitfield;
if (Array.isArray(bit)) return bit.map(p => this.resolve(p)).reduce((prev, p) => prev | p, 0);
if (typeof bit === 'string' && typeof this.FLAGS[bit] !== 'undefined') return this.FLAGS[bit];
const error = new RangeError('BITFIELD_INVALID');
error.bit = bit;
throw error;
}
}
/**
* Numeric bitfield flags.
* <info>Defined in extension classes</info>
* @type {Object}
* @abstract
*/
BitField.FLAGS = {};
module.exports = BitField;

17
node_modules/discord.js/src/util/Collection.js generated vendored Normal file
View File

@@ -0,0 +1,17 @@
'use strict';
const BaseCollection = require('@discordjs/collection');
const Util = require('./Util');
class Collection extends BaseCollection {
toJSON() {
return this.map(e => (typeof e.toJSON === 'function' ? e.toJSON() : Util.flatten(e)));
}
}
module.exports = Collection;
/**
* @external Collection
* @see {@link https://discord.js.org/#/docs/collection/master/class/Collection}
*/

678
node_modules/discord.js/src/util/Constants.js generated vendored Normal file
View File

@@ -0,0 +1,678 @@
'use strict';
const Package = (exports.Package = require('../../package.json'));
const { Error, RangeError } = require('../errors');
const browser = (exports.browser = typeof window !== 'undefined');
/**
* Options for a client.
* @typedef {Object} ClientOptions
* @property {number|number[]|string} [shards] ID of the shard to run, or an array of shard IDs. If not specified,
* the client will spawn {@link ClientOptions#shardCount} shards. If set to `auto`, it will fetch the
* recommended amount of shards from Discord and spawn that amount
* @property {number} [shardCount=1] The total amount of shards used by all processes of this bot
* (e.g. recommended shard count, shard count of the ShardingManager)
* @property {number} [messageCacheMaxSize=200] Maximum number of messages to cache per channel
* (-1 or Infinity for unlimited - don't do this without message sweeping, otherwise memory usage will climb
* indefinitely)
* @property {number} [messageCacheLifetime=0] How long a message should stay in the cache until it is considered
* sweepable (in seconds, 0 for forever)
* @property {number} [messageSweepInterval=0] How frequently to remove messages from the cache that are older than
* the message cache lifetime (in seconds, 0 for never)
* @property {number} [messageEditHistoryMaxSize=-1] Maximum number of previous versions to hold for an edited message
* (-1 or Infinity for unlimited - don't do this without sweeping, otherwise memory usage may climb indefinitely.)
* @property {boolean} [fetchAllMembers=false] Whether to cache all guild members and users upon startup, as well as
* upon joining a guild (should be avoided whenever possible)
* @property {DisableMentionType} [disableMentions='none'] Default value for {@link MessageOptions#disableMentions}
* @property {MessageMentionOptions} [allowedMentions] Default value for {@link MessageOptions#allowedMentions}
* @property {PartialType[]} [partials] Structures allowed to be partial. This means events can be emitted even when
* they're missing all the data for a particular structure. See the "Partials" topic listed in the sidebar for some
* important usage information, as partials require you to put checks in place when handling data.
* @property {number} [restWsBridgeTimeout=5000] Maximum time permitted between REST responses and their
* corresponding websocket events
* @property {number} [restTimeOffset=500] Extra time in milliseconds to wait before continuing to make REST
* requests (higher values will reduce rate-limiting errors on bad connections)
* @property {number} [restRequestTimeout=15000] Time to wait before cancelling a REST request, in milliseconds
* @property {number} [restSweepInterval=60] How frequently to delete inactive request buckets, in seconds
* (or 0 for never)
* @property {number} [retryLimit=1] How many times to retry on 5XX errors (Infinity for indefinite amount of retries)
* @property {PresenceData} [presence] Presence data to use upon login
* @property {WebsocketOptions} [ws] Options for the WebSocket
* @property {HTTPOptions} [http] HTTP options
*/
exports.DefaultOptions = {
shardCount: 1,
messageCacheMaxSize: 200,
messageCacheLifetime: 0,
messageSweepInterval: 0,
messageEditHistoryMaxSize: -1,
fetchAllMembers: false,
disableMentions: 'none',
partials: [],
restWsBridgeTimeout: 5000,
restRequestTimeout: 15000,
retryLimit: 1,
restTimeOffset: 500,
restSweepInterval: 60,
presence: {},
/**
* WebSocket options (these are left as snake_case to match the API)
* @typedef {Object} WebsocketOptions
* @property {number} [large_threshold=50] Number of members in a guild after which offline users will no longer be
* sent in the initial guild member list, must be between 50 and 250
* @property {IntentsResolvable} [intents] Intents to enable for this connection
*/
ws: {
large_threshold: 50,
compress: false,
properties: {
$os: browser ? 'browser' : process.platform,
$browser: 'discord.js',
$device: 'discord.js',
},
version: 6,
},
/**
* HTTP options
* @typedef {Object} HTTPOptions
* @property {number} [version=7] API version to use
* @property {string} [api='https://discord.com/api'] Base url of the API
* @property {string} [cdn='https://cdn.discordapp.com'] Base url of the CDN
* @property {string} [invite='https://discord.gg'] Base url of invites
* @property {string} [template='https://discord.new'] Base url of templates
*/
http: {
version: 7,
api: 'https://discord.com/api',
cdn: 'https://cdn.discordapp.com',
invite: 'https://discord.gg',
template: 'https://discord.new',
},
};
exports.UserAgent = browser
? null
: `DiscordBot (${Package.homepage.split('#')[0]}, ${Package.version}) Node.js/${process.version}`;
exports.WSCodes = {
1000: 'WS_CLOSE_REQUESTED',
4004: 'TOKEN_INVALID',
4010: 'SHARDING_INVALID',
4011: 'SHARDING_REQUIRED',
4013: 'INVALID_INTENTS',
4014: 'DISALLOWED_INTENTS',
};
const AllowedImageFormats = ['webp', 'png', 'jpg', 'jpeg', 'gif'];
const AllowedImageSizes = Array.from({ length: 9 }, (e, i) => 2 ** (i + 4));
function makeImageUrl(root, { format = 'webp', size } = {}) {
if (format && !AllowedImageFormats.includes(format)) throw new Error('IMAGE_FORMAT', format);
if (size && !AllowedImageSizes.includes(size)) throw new RangeError('IMAGE_SIZE', size);
return `${root}.${format}${size ? `?size=${size}` : ''}`;
}
/**
* Options for Image URLs.
* @typedef {Object} ImageURLOptions
* @property {string} [format] One of `webp`, `png`, `jpg`, `jpeg`, `gif`. If no format is provided,
* defaults to `webp`.
* @property {boolean} [dynamic] If true, the format will dynamically change to `gif` for
* animated avatars; the default is false.
* @property {number} [size] One of `16`, `32`, `64`, `128`, `256`, `512`, `1024`, `2048`, `4096`
*/
exports.Endpoints = {
CDN(root) {
return {
Emoji: (emojiID, format = 'png') => `${root}/emojis/${emojiID}.${format}`,
Asset: name => `${root}/assets/${name}`,
DefaultAvatar: discriminator => `${root}/embed/avatars/${discriminator}.png`,
Avatar: (userID, hash, format = 'webp', size, dynamic = false) => {
if (dynamic) format = hash.startsWith('a_') ? 'gif' : format;
return makeImageUrl(`${root}/avatars/${userID}/${hash}`, { format, size });
},
Banner: (guildID, hash, format = 'webp', size) =>
makeImageUrl(`${root}/banners/${guildID}/${hash}`, { format, size }),
Icon: (guildID, hash, format = 'webp', size, dynamic = false) => {
if (dynamic) format = hash.startsWith('a_') ? 'gif' : format;
return makeImageUrl(`${root}/icons/${guildID}/${hash}`, { format, size });
},
AppIcon: (clientID, hash, { format = 'webp', size } = {}) =>
makeImageUrl(`${root}/app-icons/${clientID}/${hash}`, { size, format }),
AppAsset: (clientID, hash, { format = 'webp', size } = {}) =>
makeImageUrl(`${root}/app-assets/${clientID}/${hash}`, { size, format }),
GDMIcon: (channelID, hash, format = 'webp', size) =>
makeImageUrl(`${root}/channel-icons/${channelID}/${hash}`, { size, format }),
Splash: (guildID, hash, format = 'webp', size) =>
makeImageUrl(`${root}/splashes/${guildID}/${hash}`, { size, format }),
DiscoverySplash: (guildID, hash, format = 'webp', size) =>
makeImageUrl(`${root}/discovery-splashes/${guildID}/${hash}`, { size, format }),
TeamIcon: (teamID, hash, { format = 'webp', size } = {}) =>
makeImageUrl(`${root}/team-icons/${teamID}/${hash}`, { size, format }),
};
},
invite: (root, code) => `${root}/${code}`,
botGateway: '/gateway/bot',
};
/**
* The current status of the client. Here are the available statuses:
* * READY: 0
* * CONNECTING: 1
* * RECONNECTING: 2
* * IDLE: 3
* * NEARLY: 4
* * DISCONNECTED: 5
* * WAITING_FOR_GUILDS: 6
* * IDENTIFYING: 7
* * RESUMING: 8
* @typedef {number} Status
*/
exports.Status = {
READY: 0,
CONNECTING: 1,
RECONNECTING: 2,
IDLE: 3,
NEARLY: 4,
DISCONNECTED: 5,
WAITING_FOR_GUILDS: 6,
IDENTIFYING: 7,
RESUMING: 8,
};
/**
* The current status of a voice connection. Here are the available statuses:
* * CONNECTED: 0
* * CONNECTING: 1
* * AUTHENTICATING: 2
* * RECONNECTING: 3
* * DISCONNECTED: 4
* @typedef {number} VoiceStatus
*/
exports.VoiceStatus = {
CONNECTED: 0,
CONNECTING: 1,
AUTHENTICATING: 2,
RECONNECTING: 3,
DISCONNECTED: 4,
};
exports.OPCodes = {
DISPATCH: 0,
HEARTBEAT: 1,
IDENTIFY: 2,
STATUS_UPDATE: 3,
VOICE_STATE_UPDATE: 4,
VOICE_GUILD_PING: 5,
RESUME: 6,
RECONNECT: 7,
REQUEST_GUILD_MEMBERS: 8,
INVALID_SESSION: 9,
HELLO: 10,
HEARTBEAT_ACK: 11,
};
exports.VoiceOPCodes = {
IDENTIFY: 0,
SELECT_PROTOCOL: 1,
READY: 2,
HEARTBEAT: 3,
SESSION_DESCRIPTION: 4,
SPEAKING: 5,
HELLO: 8,
CLIENT_CONNECT: 12,
CLIENT_DISCONNECT: 13,
};
exports.Events = {
RATE_LIMIT: 'rateLimit',
CLIENT_READY: 'ready',
GUILD_CREATE: 'guildCreate',
GUILD_DELETE: 'guildDelete',
GUILD_UPDATE: 'guildUpdate',
GUILD_UNAVAILABLE: 'guildUnavailable',
GUILD_AVAILABLE: 'guildAvailable',
GUILD_MEMBER_ADD: 'guildMemberAdd',
GUILD_MEMBER_REMOVE: 'guildMemberRemove',
GUILD_MEMBER_UPDATE: 'guildMemberUpdate',
GUILD_MEMBER_AVAILABLE: 'guildMemberAvailable',
GUILD_MEMBER_SPEAKING: 'guildMemberSpeaking',
GUILD_MEMBERS_CHUNK: 'guildMembersChunk',
GUILD_INTEGRATIONS_UPDATE: 'guildIntegrationsUpdate',
GUILD_ROLE_CREATE: 'roleCreate',
GUILD_ROLE_DELETE: 'roleDelete',
INVITE_CREATE: 'inviteCreate',
INVITE_DELETE: 'inviteDelete',
GUILD_ROLE_UPDATE: 'roleUpdate',
GUILD_EMOJI_CREATE: 'emojiCreate',
GUILD_EMOJI_DELETE: 'emojiDelete',
GUILD_EMOJI_UPDATE: 'emojiUpdate',
GUILD_BAN_ADD: 'guildBanAdd',
GUILD_BAN_REMOVE: 'guildBanRemove',
CHANNEL_CREATE: 'channelCreate',
CHANNEL_DELETE: 'channelDelete',
CHANNEL_UPDATE: 'channelUpdate',
CHANNEL_PINS_UPDATE: 'channelPinsUpdate',
MESSAGE_CREATE: 'message',
MESSAGE_DELETE: 'messageDelete',
MESSAGE_UPDATE: 'messageUpdate',
MESSAGE_BULK_DELETE: 'messageDeleteBulk',
MESSAGE_REACTION_ADD: 'messageReactionAdd',
MESSAGE_REACTION_REMOVE: 'messageReactionRemove',
MESSAGE_REACTION_REMOVE_ALL: 'messageReactionRemoveAll',
MESSAGE_REACTION_REMOVE_EMOJI: 'messageReactionRemoveEmoji',
USER_UPDATE: 'userUpdate',
PRESENCE_UPDATE: 'presenceUpdate',
VOICE_SERVER_UPDATE: 'voiceServerUpdate',
VOICE_STATE_UPDATE: 'voiceStateUpdate',
VOICE_BROADCAST_SUBSCRIBE: 'subscribe',
VOICE_BROADCAST_UNSUBSCRIBE: 'unsubscribe',
TYPING_START: 'typingStart',
TYPING_STOP: 'typingStop',
WEBHOOKS_UPDATE: 'webhookUpdate',
ERROR: 'error',
WARN: 'warn',
DEBUG: 'debug',
SHARD_DISCONNECT: 'shardDisconnect',
SHARD_ERROR: 'shardError',
SHARD_RECONNECTING: 'shardReconnecting',
SHARD_READY: 'shardReady',
SHARD_RESUME: 'shardResume',
INVALIDATED: 'invalidated',
RAW: 'raw',
};
exports.ShardEvents = {
CLOSE: 'close',
DESTROYED: 'destroyed',
INVALID_SESSION: 'invalidSession',
READY: 'ready',
RESUMED: 'resumed',
ALL_READY: 'allReady',
};
/**
* The type of Structure allowed to be a partial:
* * USER
* * CHANNEL (only affects DMChannels)
* * GUILD_MEMBER
* * MESSAGE
* * REACTION
* <warn>Partials require you to put checks in place when handling data, read the Partials topic listed in the
* sidebar for more information.</warn>
* @typedef {string} PartialType
*/
exports.PartialTypes = keyMirror(['USER', 'CHANNEL', 'GUILD_MEMBER', 'MESSAGE', 'REACTION']);
/**
* The type of a websocket message event, e.g. `MESSAGE_CREATE`. Here are the available events:
* * READY
* * RESUMED
* * GUILD_CREATE
* * GUILD_DELETE
* * GUILD_UPDATE
* * INVITE_CREATE
* * INVITE_DELETE
* * GUILD_MEMBER_ADD
* * GUILD_MEMBER_REMOVE
* * GUILD_MEMBER_UPDATE
* * GUILD_MEMBERS_CHUNK
* * GUILD_INTEGRATIONS_UPDATE
* * GUILD_ROLE_CREATE
* * GUILD_ROLE_DELETE
* * GUILD_ROLE_UPDATE
* * GUILD_BAN_ADD
* * GUILD_BAN_REMOVE
* * GUILD_EMOJIS_UPDATE
* * CHANNEL_CREATE
* * CHANNEL_DELETE
* * CHANNEL_UPDATE
* * CHANNEL_PINS_UPDATE
* * MESSAGE_CREATE
* * MESSAGE_DELETE
* * MESSAGE_UPDATE
* * MESSAGE_DELETE_BULK
* * MESSAGE_REACTION_ADD
* * MESSAGE_REACTION_REMOVE
* * MESSAGE_REACTION_REMOVE_ALL
* * MESSAGE_REACTION_REMOVE_EMOJI
* * USER_UPDATE
* * PRESENCE_UPDATE
* * TYPING_START
* * VOICE_STATE_UPDATE
* * VOICE_SERVER_UPDATE
* * WEBHOOKS_UPDATE
* @typedef {string} WSEventType
*/
exports.WSEvents = keyMirror([
'READY',
'RESUMED',
'GUILD_CREATE',
'GUILD_DELETE',
'GUILD_UPDATE',
'INVITE_CREATE',
'INVITE_DELETE',
'GUILD_MEMBER_ADD',
'GUILD_MEMBER_REMOVE',
'GUILD_MEMBER_UPDATE',
'GUILD_MEMBERS_CHUNK',
'GUILD_INTEGRATIONS_UPDATE',
'GUILD_ROLE_CREATE',
'GUILD_ROLE_DELETE',
'GUILD_ROLE_UPDATE',
'GUILD_BAN_ADD',
'GUILD_BAN_REMOVE',
'GUILD_EMOJIS_UPDATE',
'CHANNEL_CREATE',
'CHANNEL_DELETE',
'CHANNEL_UPDATE',
'CHANNEL_PINS_UPDATE',
'MESSAGE_CREATE',
'MESSAGE_DELETE',
'MESSAGE_UPDATE',
'MESSAGE_DELETE_BULK',
'MESSAGE_REACTION_ADD',
'MESSAGE_REACTION_REMOVE',
'MESSAGE_REACTION_REMOVE_ALL',
'MESSAGE_REACTION_REMOVE_EMOJI',
'USER_UPDATE',
'PRESENCE_UPDATE',
'TYPING_START',
'VOICE_STATE_UPDATE',
'VOICE_SERVER_UPDATE',
'WEBHOOKS_UPDATE',
]);
/**
* The type of a message, e.g. `DEFAULT`. Here are the available types:
* * DEFAULT
* * RECIPIENT_ADD
* * RECIPIENT_REMOVE
* * CALL
* * CHANNEL_NAME_CHANGE
* * CHANNEL_ICON_CHANGE
* * PINS_ADD
* * GUILD_MEMBER_JOIN
* * USER_PREMIUM_GUILD_SUBSCRIPTION
* * USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1
* * USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2
* * USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3
* * CHANNEL_FOLLOW_ADD
* * GUILD_DISCOVERY_DISQUALIFIED
* * GUILD_DISCOVERY_REQUALIFIED
* @typedef {string} MessageType
*/
exports.MessageTypes = [
'DEFAULT',
'RECIPIENT_ADD',
'RECIPIENT_REMOVE',
'CALL',
'CHANNEL_NAME_CHANGE',
'CHANNEL_ICON_CHANGE',
'PINS_ADD',
'GUILD_MEMBER_JOIN',
'USER_PREMIUM_GUILD_SUBSCRIPTION',
'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_1',
'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_2',
'USER_PREMIUM_GUILD_SUBSCRIPTION_TIER_3',
'CHANNEL_FOLLOW_ADD',
null,
'GUILD_DISCOVERY_DISQUALIFIED',
'GUILD_DISCOVERY_REQUALIFIED',
];
/**
* <info>Bots cannot set a `CUSTOM_STATUS`, it is only for custom statuses received from users</info>
* The type of an activity of a users presence, e.g. `PLAYING`. Here are the available types:
* * PLAYING
* * STREAMING
* * LISTENING
* * WATCHING
* * CUSTOM_STATUS
* * COMPETING
* @typedef {string} ActivityType
*/
exports.ActivityTypes = ['PLAYING', 'STREAMING', 'LISTENING', 'WATCHING', 'CUSTOM_STATUS', 'COMPETING'];
exports.ChannelTypes = {
TEXT: 0,
DM: 1,
VOICE: 2,
GROUP: 3,
CATEGORY: 4,
NEWS: 5,
STORE: 6,
};
exports.ClientApplicationAssetTypes = {
SMALL: 1,
BIG: 2,
};
exports.Colors = {
DEFAULT: 0x000000,
WHITE: 0xffffff,
AQUA: 0x1abc9c,
GREEN: 0x2ecc71,
BLUE: 0x3498db,
YELLOW: 0xffff00,
PURPLE: 0x9b59b6,
LUMINOUS_VIVID_PINK: 0xe91e63,
GOLD: 0xf1c40f,
ORANGE: 0xe67e22,
RED: 0xe74c3c,
GREY: 0x95a5a6,
NAVY: 0x34495e,
DARK_AQUA: 0x11806a,
DARK_GREEN: 0x1f8b4c,
DARK_BLUE: 0x206694,
DARK_PURPLE: 0x71368a,
DARK_VIVID_PINK: 0xad1457,
DARK_GOLD: 0xc27c0e,
DARK_ORANGE: 0xa84300,
DARK_RED: 0x992d22,
DARK_GREY: 0x979c9f,
DARKER_GREY: 0x7f8c8d,
LIGHT_GREY: 0xbcc0c0,
DARK_NAVY: 0x2c3e50,
BLURPLE: 0x7289da,
GREYPLE: 0x99aab5,
DARK_BUT_NOT_BLACK: 0x2c2f33,
NOT_QUITE_BLACK: 0x23272a,
};
/**
* The value set for the explicit content filter levels for a guild:
* * DISABLED
* * MEMBERS_WITHOUT_ROLES
* * ALL_MEMBERS
* @typedef {string} ExplicitContentFilterLevel
*/
exports.ExplicitContentFilterLevels = ['DISABLED', 'MEMBERS_WITHOUT_ROLES', 'ALL_MEMBERS'];
/**
* The value set for the verification levels for a guild:
* * NONE
* * LOW
* * MEDIUM
* * HIGH
* * VERY_HIGH
* @typedef {string} VerificationLevel
*/
exports.VerificationLevels = ['NONE', 'LOW', 'MEDIUM', 'HIGH', 'VERY_HIGH'];
/**
* An error encountered while performing an API request. Here are the potential errors:
* * UNKNOWN_ACCOUNT
* * UNKNOWN_APPLICATION
* * UNKNOWN_CHANNEL
* * UNKNOWN_GUILD
* * UNKNOWN_INTEGRATION
* * UNKNOWN_INVITE
* * UNKNOWN_MEMBER
* * UNKNOWN_MESSAGE
* * UNKNOWN_OVERWRITE
* * UNKNOWN_PROVIDER
* * UNKNOWN_ROLE
* * UNKNOWN_TOKEN
* * UNKNOWN_USER
* * UNKNOWN_EMOJI
* * UNKNOWN_WEBHOOK
* * UNKNOWN_BAN
* * UNKNOWN_GUILD_TEMPLATE
* * BOT_PROHIBITED_ENDPOINT
* * BOT_ONLY_ENDPOINT
* * CHANNEL_HIT_WRITE_RATELIMIT
* * MAXIMUM_GUILDS
* * MAXIMUM_FRIENDS
* * MAXIMUM_PINS
* * MAXIMUM_ROLES
* * MAXIMUM_WEBHOOKS
* * MAXIMUM_REACTIONS
* * MAXIMUM_CHANNELS
* * MAXIMUM_ATTACHMENTS
* * MAXIMUM_INVITES
* * GUILD_ALREADY_HAS_TEMPLATE
* * UNAUTHORIZED
* * ACCOUNT_VERIFICATION_REQUIRED
* * REQUEST_ENTITY_TOO_LARGE
* * FEATURE_TEMPORARILY_DISABLED
* * USER_BANNED
* * ALREADY_CROSSPOSTED
* * MISSING_ACCESS
* * INVALID_ACCOUNT_TYPE
* * CANNOT_EXECUTE_ON_DM
* * EMBED_DISABLED
* * CANNOT_EDIT_MESSAGE_BY_OTHER
* * CANNOT_SEND_EMPTY_MESSAGE
* * CANNOT_MESSAGE_USER
* * CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL
* * CHANNEL_VERIFICATION_LEVEL_TOO_HIGH
* * OAUTH2_APPLICATION_BOT_ABSENT
* * MAXIMUM_OAUTH2_APPLICATIONS
* * INVALID_OAUTH_STATE
* * MISSING_PERMISSIONS
* * INVALID_AUTHENTICATION_TOKEN
* * NOTE_TOO_LONG
* * INVALID_BULK_DELETE_QUANTITY
* * CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL
* * INVALID_OR_TAKEN_INVITE_CODE
* * CANNOT_EXECUTE_ON_SYSTEM_MESSAGE
* * INVALID_OAUTH_TOKEN
* * BULK_DELETE_MESSAGE_TOO_OLD
* * INVALID_FORM_BODY
* * INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT
* * INVALID_API_VERSION
* * CANNOT_DELETE_COMMUNITY_REQUIRED_CHANNEL
* * REACTION_BLOCKED
* * RESOURCE_OVERLOADED
* @typedef {string} APIError
*/
exports.APIErrors = {
UNKNOWN_ACCOUNT: 10001,
UNKNOWN_APPLICATION: 10002,
UNKNOWN_CHANNEL: 10003,
UNKNOWN_GUILD: 10004,
UNKNOWN_INTEGRATION: 10005,
UNKNOWN_INVITE: 10006,
UNKNOWN_MEMBER: 10007,
UNKNOWN_MESSAGE: 10008,
UNKNOWN_OVERWRITE: 10009,
UNKNOWN_PROVIDER: 10010,
UNKNOWN_ROLE: 10011,
UNKNOWN_TOKEN: 10012,
UNKNOWN_USER: 10013,
UNKNOWN_EMOJI: 10014,
UNKNOWN_WEBHOOK: 10015,
UNKNOWN_BAN: 10026,
UNKNOWN_GUILD_TEMPLATE: 10057,
BOT_PROHIBITED_ENDPOINT: 20001,
BOT_ONLY_ENDPOINT: 20002,
CHANNEL_HIT_WRITE_RATELIMIT: 20028,
MAXIMUM_GUILDS: 30001,
MAXIMUM_FRIENDS: 30002,
MAXIMUM_PINS: 30003,
MAXIMUM_ROLES: 30005,
MAXIMUM_WEBHOOKS: 30007,
MAXIMUM_REACTIONS: 30010,
MAXIMUM_CHANNELS: 30013,
MAXIMUM_ATTACHMENTS: 30015,
MAXIMUM_INVITES: 30016,
GUILD_ALREADY_HAS_TEMPLATE: 30031,
UNAUTHORIZED: 40001,
ACCOUNT_VERIFICATION_REQUIRED: 40002,
REQUEST_ENTITY_TOO_LARGE: 40005,
FEATURE_TEMPORARILY_DISABLED: 40006,
USER_BANNED: 40007,
ALREADY_CROSSPOSTED: 40033,
MISSING_ACCESS: 50001,
INVALID_ACCOUNT_TYPE: 50002,
CANNOT_EXECUTE_ON_DM: 50003,
EMBED_DISABLED: 50004,
CANNOT_EDIT_MESSAGE_BY_OTHER: 50005,
CANNOT_SEND_EMPTY_MESSAGE: 50006,
CANNOT_MESSAGE_USER: 50007,
CANNOT_SEND_MESSAGES_IN_VOICE_CHANNEL: 50008,
CHANNEL_VERIFICATION_LEVEL_TOO_HIGH: 50009,
OAUTH2_APPLICATION_BOT_ABSENT: 50010,
MAXIMUM_OAUTH2_APPLICATIONS: 50011,
INVALID_OAUTH_STATE: 50012,
MISSING_PERMISSIONS: 50013,
INVALID_AUTHENTICATION_TOKEN: 50014,
NOTE_TOO_LONG: 50015,
INVALID_BULK_DELETE_QUANTITY: 50016,
CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL: 50019,
INVALID_OR_TAKEN_INVITE_CODE: 50020,
CANNOT_EXECUTE_ON_SYSTEM_MESSAGE: 50021,
INVALID_OAUTH_TOKEN: 50025,
BULK_DELETE_MESSAGE_TOO_OLD: 50034,
INVALID_FORM_BODY: 50035,
INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT: 50036,
INVALID_API_VERSION: 50041,
CANNOT_DELETE_COMMUNITY_REQUIRED_CHANNEL: 50074,
REACTION_BLOCKED: 90001,
RESOURCE_OVERLOADED: 130000,
};
/**
* The value set for a guild's default message notifications, e.g. `ALL`. Here are the available types:
* * ALL
* * MENTIONS
* @typedef {string} DefaultMessageNotifications
*/
exports.DefaultMessageNotifications = ['ALL', 'MENTIONS'];
/**
* The value set for a team members's membership state:
* * INVITED
* * ACCEPTED
* @typedef {string} MembershipStates
*/
exports.MembershipStates = [
// They start at 1
null,
'INVITED',
'ACCEPTED',
];
/**
* The value set for a webhook's type:
* * Incoming
* * Channel Follower
* @typedef {string} WebhookTypes
*/
exports.WebhookTypes = [
// They start at 1
null,
'Incoming',
'Channel Follower',
];
function keyMirror(arr) {
let tmp = Object.create(null);
for (const value of arr) tmp[value] = value;
return tmp;
}

153
node_modules/discord.js/src/util/DataResolver.js generated vendored Normal file
View File

@@ -0,0 +1,153 @@
'use strict';
const fs = require('fs');
const path = require('path');
const stream = require('stream');
const fetch = require('node-fetch');
const { Error: DiscordError, TypeError } = require('../errors');
const { browser } = require('../util/Constants');
const Util = require('../util/Util');
/**
* The DataResolver identifies different objects and tries to resolve a specific piece of information from them.
* @private
*/
class DataResolver {
constructor() {
throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
}
/**
* Data that can be resolved to give an invite code. This can be:
* * An invite code
* * An invite URL
* @typedef {string} InviteResolvable
*/
/**
* Data that can be resolved to give an template code. This can be:
* * A template code
* * A template URL
* @typedef {string} GuildTemplateResolvable
*/
/**
* Resolves the string to a code based on the passed regex.
* @param {string} data The string to resolve
* @param {RegExp} regex The RegExp used to extract the code
* @returns {string}
*/
static resolveCode(data, regex) {
const match = regex.exec(data);
return match ? match[1] || data : data;
}
/**
* Resolves InviteResolvable to an invite code.
* @param {InviteResolvable} data The invite resolvable to resolve
* @returns {string}
*/
static resolveInviteCode(data) {
return this.resolveCode(data, /discord(?:(?:app)?\.com\/invite|\.gg(?:\/invite)?)\/([\w-]{2,255})/i);
}
/**
* Resolves GuildTemplateResolvable to a template code.
* @param {GuildTemplateResolvable} data The template resolvable to resolve
* @returns {string}
*/
static resolveGuildTemplateCode(data) {
return this.resolveCode(data, /discord(?:app)?\.(?:com\/template|new)\/([\w-]{2,255})/i);
}
/**
* Resolves a Base64Resolvable, a string, or a BufferResolvable to a Base 64 image.
* @param {BufferResolvable|Base64Resolvable} image The image to be resolved
* @returns {Promise<?string>}
*/
static async resolveImage(image) {
if (!image) return null;
if (typeof image === 'string' && image.startsWith('data:')) {
return image;
}
const file = await this.resolveFileAsBuffer(image);
return DataResolver.resolveBase64(file);
}
/**
* Data that resolves to give a Base64 string, typically for image uploading. This can be:
* * A Buffer
* * A base64 string
* @typedef {Buffer|string} Base64Resolvable
*/
/**
* Resolves a Base64Resolvable to a Base 64 image.
* @param {Base64Resolvable} data The base 64 resolvable you want to resolve
* @returns {?string}
*/
static resolveBase64(data) {
if (Buffer.isBuffer(data)) return `data:image/jpg;base64,${data.toString('base64')}`;
return data;
}
/**
* Data that can be resolved to give a Buffer. This can be:
* * A Buffer
* * The path to a local file
* * A URL
* @typedef {string|Buffer} BufferResolvable
*/
/**
* @external Stream
* @see {@link https://nodejs.org/api/stream.html}
*/
/**
* Resolves a BufferResolvable to a Buffer or a Stream.
* @param {BufferResolvable|Stream} resource The buffer or stream resolvable to resolve
* @returns {Promise<Buffer|Stream>}
*/
static async resolveFile(resource) {
if (!browser && Buffer.isBuffer(resource)) return resource;
if (browser && resource instanceof ArrayBuffer) return Util.convertToBuffer(resource);
// eslint-disable-next-line no-undef
if (browser && resource instanceof Blob) return resource;
if (resource instanceof stream.Readable) return resource;
if (typeof resource === 'string') {
if (/^https?:\/\//.test(resource)) {
const res = await fetch(resource);
return browser ? res.blob() : res.body;
} else if (!browser) {
return new Promise((resolve, reject) => {
const file = path.resolve(resource);
fs.stat(file, (err, stats) => {
if (err) return reject(err);
if (!stats.isFile()) return reject(new DiscordError('FILE_NOT_FOUND', file));
return resolve(fs.createReadStream(file));
});
});
}
}
throw new TypeError('REQ_RESOURCE_TYPE');
}
/**
* Resolves a BufferResolvable to a Buffer.
* @param {BufferResolvable|Stream} resource The buffer or stream resolvable to resolve
* @returns {Promise<Buffer>}
*/
static async resolveFileAsBuffer(resource) {
const file = await this.resolveFile(resource);
if (Buffer.isBuffer(file)) return file;
const buffers = [];
for await (const data of file) buffers.push(data);
return Buffer.concat(buffers);
}
}
module.exports = DataResolver;

83
node_modules/discord.js/src/util/Intents.js generated vendored Normal file
View File

@@ -0,0 +1,83 @@
'use strict';
const BitField = require('./BitField');
/**
* Data structure that makes it easy to calculate intents.
* @extends {BitField}
*/
class Intents extends BitField {}
/**
* @name Intents
* @kind constructor
* @memberof Intents
* @param {IntentsResolvable} [bits=0] Bit(s) to read from
*/
/**
* Data that can be resolved to give a permission number. This can be:
* * A string (see {@link Intents.FLAGS})
* * An intents flag
* * An instance of Intents
* * An array of IntentsResolvable
* @typedef {string|number|Intents|IntentsResolvable[]} IntentsResolvable
*/
/**
* Numeric websocket intents. All available properties:
* * `GUILDS`
* * `GUILD_MEMBERS`
* * `GUILD_BANS`
* * `GUILD_EMOJIS`
* * `GUILD_INTEGRATIONS`
* * `GUILD_WEBHOOKS`
* * `GUILD_INVITES`
* * `GUILD_VOICE_STATES`
* * `GUILD_PRESENCES`
* * `GUILD_MESSAGES`
* * `GUILD_MESSAGE_REACTIONS`
* * `GUILD_MESSAGE_TYPING`
* * `DIRECT_MESSAGES`
* * `DIRECT_MESSAGE_REACTIONS`
* * `DIRECT_MESSAGE_TYPING`
* @type {Object}
* @see {@link https://discord.com/developers/docs/topics/gateway#list-of-intents}
*/
Intents.FLAGS = {
GUILDS: 1 << 0,
GUILD_MEMBERS: 1 << 1,
GUILD_BANS: 1 << 2,
GUILD_EMOJIS: 1 << 3,
GUILD_INTEGRATIONS: 1 << 4,
GUILD_WEBHOOKS: 1 << 5,
GUILD_INVITES: 1 << 6,
GUILD_VOICE_STATES: 1 << 7,
GUILD_PRESENCES: 1 << 8,
GUILD_MESSAGES: 1 << 9,
GUILD_MESSAGE_REACTIONS: 1 << 10,
GUILD_MESSAGE_TYPING: 1 << 11,
DIRECT_MESSAGES: 1 << 12,
DIRECT_MESSAGE_REACTIONS: 1 << 13,
DIRECT_MESSAGE_TYPING: 1 << 14,
};
/**
* Bitfield representing all privileged intents
* @type {number}
* @see {@link https://discord.com/developers/docs/topics/gateway#privileged-intents}
*/
Intents.PRIVILEGED = Intents.FLAGS.GUILD_MEMBERS | Intents.FLAGS.GUILD_PRESENCES;
/**
* Bitfield representing all intents combined
* @type {number}
*/
Intents.ALL = Object.values(Intents.FLAGS).reduce((acc, p) => acc | p, 0);
/**
* Bitfield representing all non-privileged intents
* @type {number}
*/
Intents.NON_PRIVILEGED = Intents.ALL & ~Intents.PRIVILEGED;
module.exports = Intents;

34
node_modules/discord.js/src/util/LimitedCollection.js generated vendored Normal file
View File

@@ -0,0 +1,34 @@
'use strict';
const Collection = require('./Collection.js');
/**
* A Collection which holds a max amount of entries. The first key is deleted if the Collection has
* reached max size.
* @extends {Collection}
* @param {number} [maxSize=0] The maximum size of the Collection
* @param {Iterable} [iterable=null] Optional entries passed to the Map constructor.
* @private
*/
class LimitedCollection extends Collection {
constructor(maxSize = 0, iterable = null) {
super(iterable);
/**
* The max size of the Collection.
* @type {number}
*/
this.maxSize = maxSize;
}
set(key, value) {
if (this.maxSize === 0) return this;
if (this.size >= this.maxSize && !this.has(key)) this.delete(this.firstKey());
return super.set(key, value);
}
static get [Symbol.species]() {
return Collection;
}
}
module.exports = LimitedCollection;

36
node_modules/discord.js/src/util/MessageFlags.js generated vendored Normal file
View File

@@ -0,0 +1,36 @@
'use strict';
const BitField = require('./BitField');
/**
* Data structure that makes it easy to interact with an {@link Message#flags} bitfield.
* @extends {BitField}
*/
class MessageFlags extends BitField {}
/**
* @name MessageFlags
* @kind constructor
* @memberof MessageFlags
* @param {BitFieldResolvable} [bits=0] Bit(s) to read from
*/
/**
* Numeric message flags. All available properties:
* * `CROSSPOSTED`
* * `IS_CROSSPOST`
* * `SUPPRESS_EMBEDS`
* * `SOURCE_MESSAGE_DELETED`
* * `URGENT`
* @type {Object}
* @see {@link https://discord.com/developers/docs/resources/channel#message-object-message-flags}
*/
MessageFlags.FLAGS = {
CROSSPOSTED: 1 << 0,
IS_CROSSPOST: 1 << 1,
SUPPRESS_EMBEDS: 1 << 2,
SOURCE_MESSAGE_DELETED: 1 << 3,
URGENT: 1 << 4,
};
module.exports = MessageFlags;

131
node_modules/discord.js/src/util/Permissions.js generated vendored Normal file
View File

@@ -0,0 +1,131 @@
'use strict';
const BitField = require('./BitField');
/**
* Data structure that makes it easy to interact with a permission bitfield. All {@link GuildMember}s have a set of
* permissions in their guild, and each channel in the guild may also have {@link PermissionOverwrites} for the member
* that override their default permissions.
* @extends {BitField}
*/
class Permissions extends BitField {
/**
* @name Permissions
* @kind constructor
* @memberof Permissions
* @param {PermissionResolvable} [bits=0] Bit(s) to read from
*/
/**
* Data that can be resolved to give a permission number. This can be:
* * A string (see {@link Permissions.FLAGS})
* * A permission number
* * An instance of Permissions
* * An Array of PermissionResolvable
* @typedef {string|number|Permissions|PermissionResolvable[]} PermissionResolvable
*/
/**
* Checks whether the bitfield has a permission, or any of multiple permissions.
* @param {PermissionResolvable} permission Permission(s) to check for
* @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override
* @returns {boolean}
*/
any(permission, checkAdmin = true) {
return (checkAdmin && super.has(this.constructor.FLAGS.ADMINISTRATOR)) || super.any(permission);
}
/**
* Checks whether the bitfield has a permission, or multiple permissions.
* @param {PermissionResolvable} permission Permission(s) to check for
* @param {boolean} [checkAdmin=true] Whether to allow the administrator permission to override
* @returns {boolean}
*/
has(permission, checkAdmin = true) {
return (checkAdmin && super.has(this.constructor.FLAGS.ADMINISTRATOR)) || super.has(permission);
}
}
/**
* Numeric permission flags. All available properties:
* * `ADMINISTRATOR` (implicitly has *all* permissions, and bypasses all channel overwrites)
* * `CREATE_INSTANT_INVITE` (create invitations to the guild)
* * `KICK_MEMBERS`
* * `BAN_MEMBERS`
* * `MANAGE_CHANNELS` (edit and reorder channels)
* * `MANAGE_GUILD` (edit the guild information, region, etc.)
* * `ADD_REACTIONS` (add new reactions to messages)
* * `VIEW_AUDIT_LOG`
* * `PRIORITY_SPEAKER`
* * `STREAM`
* * `VIEW_CHANNEL`
* * `SEND_MESSAGES`
* * `SEND_TTS_MESSAGES`
* * `MANAGE_MESSAGES` (delete messages and reactions)
* * `EMBED_LINKS` (links posted will have a preview embedded)
* * `ATTACH_FILES`
* * `READ_MESSAGE_HISTORY` (view messages that were posted prior to opening Discord)
* * `MENTION_EVERYONE`
* * `USE_EXTERNAL_EMOJIS` (use emojis from different guilds)
* * `VIEW_GUILD_INSIGHTS`
* * `CONNECT` (connect to a voice channel)
* * `SPEAK` (speak in a voice channel)
* * `MUTE_MEMBERS` (mute members across all voice channels)
* * `DEAFEN_MEMBERS` (deafen members across all voice channels)
* * `MOVE_MEMBERS` (move members between voice channels)
* * `USE_VAD` (use voice activity detection)
* * `CHANGE_NICKNAME`
* * `MANAGE_NICKNAMES` (change other members' nicknames)
* * `MANAGE_ROLES`
* * `MANAGE_WEBHOOKS`
* * `MANAGE_EMOJIS`
* @type {Object}
* @see {@link https://discord.com/developers/docs/topics/permissions}
*/
Permissions.FLAGS = {
CREATE_INSTANT_INVITE: 1 << 0,
KICK_MEMBERS: 1 << 1,
BAN_MEMBERS: 1 << 2,
ADMINISTRATOR: 1 << 3,
MANAGE_CHANNELS: 1 << 4,
MANAGE_GUILD: 1 << 5,
ADD_REACTIONS: 1 << 6,
VIEW_AUDIT_LOG: 1 << 7,
PRIORITY_SPEAKER: 1 << 8,
STREAM: 1 << 9,
VIEW_CHANNEL: 1 << 10,
SEND_MESSAGES: 1 << 11,
SEND_TTS_MESSAGES: 1 << 12,
MANAGE_MESSAGES: 1 << 13,
EMBED_LINKS: 1 << 14,
ATTACH_FILES: 1 << 15,
READ_MESSAGE_HISTORY: 1 << 16,
MENTION_EVERYONE: 1 << 17,
USE_EXTERNAL_EMOJIS: 1 << 18,
VIEW_GUILD_INSIGHTS: 1 << 19,
CONNECT: 1 << 20,
SPEAK: 1 << 21,
MUTE_MEMBERS: 1 << 22,
DEAFEN_MEMBERS: 1 << 23,
MOVE_MEMBERS: 1 << 24,
USE_VAD: 1 << 25,
CHANGE_NICKNAME: 1 << 26,
MANAGE_NICKNAMES: 1 << 27,
MANAGE_ROLES: 1 << 28,
MANAGE_WEBHOOKS: 1 << 29,
MANAGE_EMOJIS: 1 << 30,
};
/**
* Bitfield representing every permission combined
* @type {number}
*/
Permissions.ALL = Object.values(Permissions.FLAGS).reduce((all, p) => all | p, 0);
/**
* Bitfield representing the default permissions for users
* @type {number}
*/
Permissions.DEFAULT = 104324673;
module.exports = Permissions;

93
node_modules/discord.js/src/util/Snowflake.js generated vendored Normal file
View File

@@ -0,0 +1,93 @@
'use strict';
const Util = require('../util/Util');
// Discord epoch (2015-01-01T00:00:00.000Z)
const EPOCH = 1420070400000;
let INCREMENT = 0;
/**
* A container for useful snowflake-related methods.
*/
class SnowflakeUtil {
constructor() {
throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
}
/**
* A Twitter snowflake, except the epoch is 2015-01-01T00:00:00.000Z
* ```
* If we have a snowflake '266241948824764416' we can represent it as binary:
*
* 64 22 17 12 0
* 000000111011000111100001101001000101000000 00001 00000 000000000000
* number of ms since Discord epoch worker pid increment
* ```
* @typedef {string} Snowflake
*/
/**
* Generates a Discord snowflake.
* <info>This hardcodes the worker ID as 1 and the process ID as 0.</info>
* @param {number|Date} [timestamp=Date.now()] Timestamp or date of the snowflake to generate
* @returns {Snowflake} The generated snowflake
*/
static generate(timestamp = Date.now()) {
if (timestamp instanceof Date) timestamp = timestamp.getTime();
if (typeof timestamp !== 'number' || isNaN(timestamp)) {
throw new TypeError(
`"timestamp" argument must be a number (received ${isNaN(timestamp) ? 'NaN' : typeof timestamp})`,
);
}
if (INCREMENT >= 4095) INCREMENT = 0;
const BINARY = `${(timestamp - EPOCH).toString(2).padStart(42, '0')}0000100000${(INCREMENT++)
.toString(2)
.padStart(12, '0')}`;
return Util.binaryToID(BINARY);
}
/**
* A deconstructed snowflake.
* @typedef {Object} DeconstructedSnowflake
* @property {number} timestamp Timestamp the snowflake was created
* @property {Date} date Date the snowflake was created
* @property {number} workerID Worker ID in the snowflake
* @property {number} processID Process ID in the snowflake
* @property {number} increment Increment in the snowflake
* @property {string} binary Binary representation of the snowflake
*/
/**
* Deconstructs a Discord snowflake.
* @param {Snowflake} snowflake Snowflake to deconstruct
* @returns {DeconstructedSnowflake} Deconstructed snowflake
*/
static deconstruct(snowflake) {
const BINARY = Util.idToBinary(snowflake).toString(2).padStart(64, '0');
const res = {
timestamp: parseInt(BINARY.substring(0, 42), 2) + EPOCH,
workerID: parseInt(BINARY.substring(42, 47), 2),
processID: parseInt(BINARY.substring(47, 52), 2),
increment: parseInt(BINARY.substring(52, 64), 2),
binary: BINARY,
};
Object.defineProperty(res, 'date', {
get: function get() {
return new Date(this.timestamp);
},
enumerable: true,
});
return res;
}
/**
* Discord's epoch value (2015-01-01T00:00:00.000Z).
* @type {number}
* @readonly
*/
static get EPOCH() {
return EPOCH;
}
}
module.exports = SnowflakeUtil;

33
node_modules/discord.js/src/util/Speaking.js generated vendored Normal file
View File

@@ -0,0 +1,33 @@
'use strict';
const BitField = require('./BitField');
/**
* Data structure that makes it easy to interact with a {@link VoiceConnection#speaking}
* and {@link guildMemberSpeaking} event bitfields.
* @extends {BitField}
*/
class Speaking extends BitField {}
/**
* @name Speaking
* @kind constructor
* @memberof Speaking
* @param {BitFieldResolvable} [bits=0] Bit(s) to read from
*/
/**
* Numeric speaking flags. All available properties:
* * `SPEAKING`
* * `SOUNDSHARE`
* * `PRIORITY_SPEAKING`
* @type {Object}
* @see {@link https://discord.com/developers/docs/topics/voice-connections#speaking}
*/
Speaking.FLAGS = {
SPEAKING: 1 << 0,
SOUNDSHARE: 1 << 1,
PRIORITY_SPEAKING: 1 << 2,
};
module.exports = Speaking;

112
node_modules/discord.js/src/util/Structures.js generated vendored Normal file
View File

@@ -0,0 +1,112 @@
'use strict';
/**
* An extendable structure:
* * **`GuildEmoji`**
* * **`DMChannel`**
* * **`TextChannel`**
* * **`VoiceChannel`**
* * **`CategoryChannel`**
* * **`NewsChannel`**
* * **`StoreChannel`**
* * **`GuildMember`**
* * **`Guild`**
* * **`Message`**
* * **`MessageReaction`**
* * **`Presence`**
* * **`ClientPresence`**
* * **`VoiceState`**
* * **`Role`**
* * **`User`**
* @typedef {string} ExtendableStructure
*/
/**
* Allows for the extension of built-in Discord.js structures that are instantiated by {@link BaseManager Managers}.
*/
class Structures {
constructor() {
throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
}
/**
* Retrieves a structure class.
* @param {string} structure Name of the structure to retrieve
* @returns {Function}
*/
static get(structure) {
if (typeof structure === 'string') return structures[structure];
throw new TypeError(`"structure" argument must be a string (received ${typeof structure})`);
}
/**
* Extends a structure.
* <warn> Make sure to extend all structures before instantiating your client.
* Extending after doing so may not work as expected. </warn>
* @param {ExtendableStructure} structure Name of the structure class to extend
* @param {Function} extender Function that takes the base class to extend as its only parameter and returns the
* extended class/prototype
* @returns {Function} Extended class/prototype returned from the extender
* @example
* const { Structures } = require('discord.js');
*
* Structures.extend('Guild', Guild => {
* class CoolGuild extends Guild {
* constructor(client, data) {
* super(client, data);
* this.cool = true;
* }
* }
*
* return CoolGuild;
* });
*/
static extend(structure, extender) {
if (!structures[structure]) throw new RangeError(`"${structure}" is not a valid extensible structure.`);
if (typeof extender !== 'function') {
const received = `(received ${typeof extender})`;
throw new TypeError(
`"extender" argument must be a function that returns the extended structure class/prototype ${received}.`,
);
}
const extended = extender(structures[structure]);
if (typeof extended !== 'function') {
const received = `(received ${typeof extended})`;
throw new TypeError(`The extender function must return the extended structure class/prototype ${received}.`);
}
if (!(extended.prototype instanceof structures[structure])) {
const prototype = Object.getPrototypeOf(extended);
const received = `${extended.name || 'unnamed'}${prototype.name ? ` extends ${prototype.name}` : ''}`;
throw new Error(
'The class/prototype returned from the extender function must extend the existing structure class/prototype' +
` (received function ${received}; expected extension of ${structures[structure].name}).`,
);
}
structures[structure] = extended;
return extended;
}
}
const structures = {
GuildEmoji: require('../structures/GuildEmoji'),
DMChannel: require('../structures/DMChannel'),
TextChannel: require('../structures/TextChannel'),
VoiceChannel: require('../structures/VoiceChannel'),
CategoryChannel: require('../structures/CategoryChannel'),
NewsChannel: require('../structures/NewsChannel'),
StoreChannel: require('../structures/StoreChannel'),
GuildMember: require('../structures/GuildMember'),
Guild: require('../structures/Guild'),
Message: require('../structures/Message'),
MessageReaction: require('../structures/MessageReaction'),
Presence: require('../structures/Presence').Presence,
ClientPresence: require('../structures/ClientPresence'),
VoiceState: require('../structures/VoiceState'),
Role: require('../structures/Role'),
User: require('../structures/User'),
};
module.exports = Structures;

40
node_modules/discord.js/src/util/SystemChannelFlags.js generated vendored Normal file
View File

@@ -0,0 +1,40 @@
'use strict';
const BitField = require('./BitField');
/**
* Data structure that makes it easy to interact with a {@link Guild#systemChannelFlags} bitfield.
* <info>Note that all event message types are enabled by default,
* and by setting their corresponding flags you are disabling them</info>
* @extends {BitField}
*/
class SystemChannelFlags extends BitField {}
/**
* @name SystemChannelFlags
* @kind constructor
* @memberof SystemChannelFlags
* @param {SystemChannelFlagsResolvable} [bits=0] Bit(s) to read from
*/
/**
* Data that can be resolved to give a sytem channel flag bitfield. This can be:
* * A string (see {@link SystemChannelFlags.FLAGS})
* * A sytem channel flag
* * An instance of SystemChannelFlags
* * An Array of SystemChannelFlagsResolvable
* @typedef {string|number|SystemChannelFlags|SystemChannelFlagsResolvable[]} SystemChannelFlagsResolvable
*/
/**
* Numeric system channel flags. All available properties:
* * `WELCOME_MESSAGE_DISABLED`
* * `BOOST_MESSAGE_DISABLED`
* @type {Object}
*/
SystemChannelFlags.FLAGS = {
WELCOME_MESSAGE_DISABLED: 1 << 0,
BOOST_MESSAGE_DISABLED: 1 << 1,
};
module.exports = SystemChannelFlags;

55
node_modules/discord.js/src/util/UserFlags.js generated vendored Normal file
View File

@@ -0,0 +1,55 @@
'use strict';
const BitField = require('./BitField');
/**
* Data structure that makes it easy to interact with a {@link User#flags} bitfield.
* @extends {BitField}
*/
class UserFlags extends BitField {}
/**
* @name UserFlags
* @kind constructor
* @memberof UserFlags
* @param {BitFieldResolvable} [bits=0] Bit(s) to read from
*/
/**
* Numeric user flags. All available properties:
* * `DISCORD_EMPLOYEE`
* * `PARTNERED_SERVER_OWNER`
* * `DISCORD_PARTNER` **(deprecated)**
* * `HYPESQUAD_EVENTS`
* * `BUGHUNTER_LEVEL_1`
* * `HOUSE_BRAVERY`
* * `HOUSE_BRILLIANCE`
* * `HOUSE_BALANCE`
* * `EARLY_SUPPORTER`
* * `TEAM_USER`
* * `SYSTEM`
* * `BUGHUNTER_LEVEL_2`
* * `VERIFIED_BOT`
* * `EARLY_VERIFIED_BOT_DEVELOPER`
* * `VERIFIED_DEVELOPER` **(deprecated)**
* @type {Object}
* @see {@link https://discord.com/developers/docs/resources/user#user-object-user-flags}
*/
UserFlags.FLAGS = {
DISCORD_EMPLOYEE: 1 << 0,
PARTNERED_SERVER_OWNER: 1 << 1,
DISCORD_PARTNER: 1 << 1,
HYPESQUAD_EVENTS: 1 << 2,
BUGHUNTER_LEVEL_1: 1 << 3,
HOUSE_BRAVERY: 1 << 6,
HOUSE_BRILLIANCE: 1 << 7,
HOUSE_BALANCE: 1 << 8,
EARLY_SUPPORTER: 1 << 9,
TEAM_USER: 1 << 10,
SYSTEM: 1 << 12,
BUGHUNTER_LEVEL_2: 1 << 14,
VERIFIED_BOT: 1 << 16,
EARLY_VERIFIED_DEVELOPER: 1 << 17,
VERIFIED_DEVELOPER: 1 << 17,
};
module.exports = UserFlags;

625
node_modules/discord.js/src/util/Util.js generated vendored Normal file
View File

@@ -0,0 +1,625 @@
'use strict';
const { parse } = require('path');
const fetch = require('node-fetch');
const { Colors, DefaultOptions, Endpoints } = require('./Constants');
const { Error: DiscordError, RangeError, TypeError } = require('../errors');
const has = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
const isObject = d => typeof d === 'object' && d !== null;
/**
* Contains various general-purpose utility methods. These functions are also available on the base `Discord` object.
*/
class Util {
constructor() {
throw new Error(`The ${this.constructor.name} class may not be instantiated.`);
}
/**
* Flatten an object. Any properties that are collections will get converted to an array of keys.
* @param {Object} obj The object to flatten.
* @param {...Object<string, boolean|string>} [props] Specific properties to include/exclude.
* @returns {Object}
*/
static flatten(obj, ...props) {
if (!isObject(obj)) return obj;
const objProps = Object.keys(obj)
.filter(k => !k.startsWith('_'))
.map(k => ({ [k]: true }));
props = objProps.length ? Object.assign(...objProps, ...props) : Object.assign({}, ...props);
const out = {};
for (let [prop, newProp] of Object.entries(props)) {
if (!newProp) continue;
newProp = newProp === true ? prop : newProp;
const element = obj[prop];
const elemIsObj = isObject(element);
const valueOf = elemIsObj && typeof element.valueOf === 'function' ? element.valueOf() : null;
// If it's a Collection, make the array of keys
if (element instanceof require('./Collection')) out[newProp] = Array.from(element.keys());
// If the valueOf is a Collection, use its array of keys
else if (valueOf instanceof require('./Collection')) out[newProp] = Array.from(valueOf.keys());
// If it's an array, flatten each element
else if (Array.isArray(element)) out[newProp] = element.map(e => Util.flatten(e));
// If it's an object with a primitive `valueOf`, use that value
else if (typeof valueOf !== 'object') out[newProp] = valueOf;
// If it's a primitive
else if (!elemIsObj) out[newProp] = element;
}
return out;
}
/**
* Splits a string into multiple chunks at a designated character that do not exceed a specific length.
* @param {StringResolvable} text Content to split
* @param {SplitOptions} [options] Options controlling the behavior of the split
* @returns {string[]}
*/
static splitMessage(text, { maxLength = 2000, char = '\n', prepend = '', append = '' } = {}) {
text = Util.resolveString(text);
if (text.length <= maxLength) return [text];
const splitText = text.split(char);
if (splitText.some(chunk => chunk.length > maxLength)) throw new RangeError('SPLIT_MAX_LEN');
const messages = [];
let msg = '';
for (const chunk of splitText) {
if (msg && (msg + char + chunk + append).length > maxLength) {
messages.push(msg + append);
msg = prepend;
}
msg += (msg && msg !== prepend ? char : '') + chunk;
}
return messages.concat(msg).filter(m => m);
}
/**
* Escapes any Discord-flavour markdown in a string.
* @param {string} text Content to escape
* @param {Object} [options={}] What types of markdown to escape
* @param {boolean} [options.codeBlock=true] Whether to escape code blocks or not
* @param {boolean} [options.inlineCode=true] Whether to escape inline code or not
* @param {boolean} [options.bold=true] Whether to escape bolds or not
* @param {boolean} [options.italic=true] Whether to escape italics or not
* @param {boolean} [options.underline=true] Whether to escape underlines or not
* @param {boolean} [options.strikethrough=true] Whether to escape strikethroughs or not
* @param {boolean} [options.spoiler=true] Whether to escape spoilers or not
* @param {boolean} [options.codeBlockContent=true] Whether to escape text inside code blocks or not
* @param {boolean} [options.inlineCodeContent=true] Whether to escape text inside inline code or not
* @returns {string}
*/
static escapeMarkdown(
text,
{
codeBlock = true,
inlineCode = true,
bold = true,
italic = true,
underline = true,
strikethrough = true,
spoiler = true,
codeBlockContent = true,
inlineCodeContent = true,
} = {},
) {
if (!codeBlockContent) {
return text
.split('```')
.map((subString, index, array) => {
if (index % 2 && index !== array.length - 1) return subString;
return Util.escapeMarkdown(subString, {
inlineCode,
bold,
italic,
underline,
strikethrough,
spoiler,
inlineCodeContent,
});
})
.join(codeBlock ? '\\`\\`\\`' : '```');
}
if (!inlineCodeContent) {
return text
.split(/(?<=^|[^`])`(?=[^`]|$)/g)
.map((subString, index, array) => {
if (index % 2 && index !== array.length - 1) return subString;
return Util.escapeMarkdown(subString, {
codeBlock,
bold,
italic,
underline,
strikethrough,
spoiler,
});
})
.join(inlineCode ? '\\`' : '`');
}
if (inlineCode) text = Util.escapeInlineCode(text);
if (codeBlock) text = Util.escapeCodeBlock(text);
if (italic) text = Util.escapeItalic(text);
if (bold) text = Util.escapeBold(text);
if (underline) text = Util.escapeUnderline(text);
if (strikethrough) text = Util.escapeStrikethrough(text);
if (spoiler) text = Util.escapeSpoiler(text);
return text;
}
/**
* Escapes code block markdown in a string.
* @param {string} text Content to escape
* @returns {string}
*/
static escapeCodeBlock(text) {
return text.replace(/```/g, '\\`\\`\\`');
}
/**
* Escapes inline code markdown in a string.
* @param {string} text Content to escape
* @returns {string}
*/
static escapeInlineCode(text) {
return text.replace(/(?<=^|[^`])`(?=[^`]|$)/g, '\\`');
}
/**
* Escapes italic markdown in a string.
* @param {string} text Content to escape
* @returns {string}
*/
static escapeItalic(text) {
let i = 0;
text = text.replace(/(?<=^|[^*])\*([^*]|\*\*|$)/g, (_, match) => {
if (match === '**') return ++i % 2 ? `\\*${match}` : `${match}\\*`;
return `\\*${match}`;
});
i = 0;
return text.replace(/(?<=^|[^_])_([^_]|__|$)/g, (_, match) => {
if (match === '__') return ++i % 2 ? `\\_${match}` : `${match}\\_`;
return `\\_${match}`;
});
}
/**
* Escapes bold markdown in a string.
* @param {string} text Content to escape
* @returns {string}
*/
static escapeBold(text) {
let i = 0;
return text.replace(/\*\*(\*)?/g, (_, match) => {
if (match) return ++i % 2 ? `${match}\\*\\*` : `\\*\\*${match}`;
return '\\*\\*';
});
}
/**
* Escapes underline markdown in a string.
* @param {string} text Content to escape
* @returns {string}
*/
static escapeUnderline(text) {
let i = 0;
return text.replace(/__(_)?/g, (_, match) => {
if (match) return ++i % 2 ? `${match}\\_\\_` : `\\_\\_${match}`;
return '\\_\\_';
});
}
/**
* Escapes strikethrough markdown in a string.
* @param {string} text Content to escape
* @returns {string}
*/
static escapeStrikethrough(text) {
return text.replace(/~~/g, '\\~\\~');
}
/**
* Escapes spoiler markdown in a string.
* @param {string} text Content to escape
* @returns {string}
*/
static escapeSpoiler(text) {
return text.replace(/\|\|/g, '\\|\\|');
}
/**
* Gets the recommended shard count from Discord.
* @param {string} token Discord auth token
* @param {number} [guildsPerShard=1000] Number of guilds per shard
* @returns {Promise<number>} The recommended number of shards
*/
static fetchRecommendedShards(token, guildsPerShard = 1000) {
if (!token) throw new DiscordError('TOKEN_MISSING');
return fetch(`${DefaultOptions.http.api}/v${DefaultOptions.http.version}${Endpoints.botGateway}`, {
method: 'GET',
headers: { Authorization: `Bot ${token.replace(/^Bot\s*/i, '')}` },
})
.then(res => {
if (res.ok) return res.json();
if (res.status === 401) throw new DiscordError('TOKEN_INVALID');
throw res;
})
.then(data => data.shards * (1000 / guildsPerShard));
}
/**
* Parses emoji info out of a string. The string must be one of:
* * A UTF-8 emoji (no ID)
* * A URL-encoded UTF-8 emoji (no ID)
* * A Discord custom emoji (`<:name:id>` or `<a:name:id>`)
* @param {string} text Emoji string to parse
* @returns {Object} Object with `animated`, `name`, and `id` properties
* @private
*/
static parseEmoji(text) {
if (text.includes('%')) text = decodeURIComponent(text);
if (!text.includes(':')) return { animated: false, name: text, id: null };
const m = text.match(/<?(?:(a):)?(\w{2,32}):(\d{17,19})?>?/);
if (!m) return null;
return { animated: Boolean(m[1]), name: m[2], id: m[3] || null };
}
/**
* Shallow-copies an object with its class/prototype intact.
* @param {Object} obj Object to clone
* @returns {Object}
* @private
*/
static cloneObject(obj) {
return Object.assign(Object.create(obj), obj);
}
/**
* Sets default properties on an object that aren't already specified.
* @param {Object} def Default properties
* @param {Object} given Object to assign defaults to
* @returns {Object}
* @private
*/
static mergeDefault(def, given) {
if (!given) return def;
for (const key in def) {
if (!has(given, key) || given[key] === undefined) {
given[key] = def[key];
} else if (given[key] === Object(given[key])) {
given[key] = Util.mergeDefault(def[key], given[key]);
}
}
return given;
}
/**
* Converts an ArrayBuffer or string to a Buffer.
* @param {ArrayBuffer|string} ab ArrayBuffer to convert
* @returns {Buffer}
* @private
*/
static convertToBuffer(ab) {
if (typeof ab === 'string') ab = Util.str2ab(ab);
return Buffer.from(ab);
}
/**
* Converts a string to an ArrayBuffer.
* @param {string} str String to convert
* @returns {ArrayBuffer}
* @private
*/
static str2ab(str) {
const buffer = new ArrayBuffer(str.length * 2);
const view = new Uint16Array(buffer);
for (var i = 0, strLen = str.length; i < strLen; i++) view[i] = str.charCodeAt(i);
return buffer;
}
/**
* Makes an Error from a plain info object.
* @param {Object} obj Error info
* @param {string} obj.name Error type
* @param {string} obj.message Message for the error
* @param {string} obj.stack Stack for the error
* @returns {Error}
* @private
*/
static makeError(obj) {
const err = new Error(obj.message);
err.name = obj.name;
err.stack = obj.stack;
return err;
}
/**
* Makes a plain error info object from an Error.
* @param {Error} err Error to get info from
* @returns {Object}
* @private
*/
static makePlainError(err) {
return {
name: err.name,
message: err.message,
stack: err.stack,
};
}
/**
* Moves an element in an array *in place*.
* @param {Array<*>} array Array to modify
* @param {*} element Element to move
* @param {number} newIndex Index or offset to move the element to
* @param {boolean} [offset=false] Move the element by an offset amount rather than to a set index
* @returns {number}
* @private
*/
static moveElementInArray(array, element, newIndex, offset = false) {
const index = array.indexOf(element);
newIndex = (offset ? index : 0) + newIndex;
if (newIndex > -1 && newIndex < array.length) {
const removedElement = array.splice(index, 1)[0];
array.splice(newIndex, 0, removedElement);
}
return array.indexOf(element);
}
/**
* Data that can be resolved to give a string. This can be:
* * A string
* * An array (joined with a new line delimiter to give a string)
* * Any value
* @typedef {string|Array|*} StringResolvable
*/
/**
* Resolves a StringResolvable to a string.
* @param {StringResolvable} data The string resolvable to resolve
* @returns {string}
*/
static resolveString(data) {
if (typeof data === 'string') return data;
if (Array.isArray(data)) return data.join('\n');
return String(data);
}
/**
* Can be a number, hex string, an RGB array like:
* ```js
* [255, 0, 255] // purple
* ```
* or one of the following strings:
* - `DEFAULT`
* - `WHITE`
* - `AQUA`
* - `GREEN`
* - `BLUE`
* - `YELLOW`
* - `PURPLE`
* - `LUMINOUS_VIVID_PINK`
* - `GOLD`
* - `ORANGE`
* - `RED`
* - `GREY`
* - `DARKER_GREY`
* - `NAVY`
* - `DARK_AQUA`
* - `DARK_GREEN`
* - `DARK_BLUE`
* - `DARK_PURPLE`
* - `DARK_VIVID_PINK`
* - `DARK_GOLD`
* - `DARK_ORANGE`
* - `DARK_RED`
* - `DARK_GREY`
* - `LIGHT_GREY`
* - `DARK_NAVY`
* - `BLURPLE`
* - `GREYPLE`
* - `DARK_BUT_NOT_BLACK`
* - `NOT_QUITE_BLACK`
* - `RANDOM`
* @typedef {string|number|number[]} ColorResolvable
*/
/**
* Resolves a ColorResolvable into a color number.
* @param {ColorResolvable} color Color to resolve
* @returns {number} A color
*/
static resolveColor(color) {
if (typeof color === 'string') {
if (color === 'RANDOM') return Math.floor(Math.random() * (0xffffff + 1));
if (color === 'DEFAULT') return 0;
color = Colors[color] || parseInt(color.replace('#', ''), 16);
} else if (Array.isArray(color)) {
color = (color[0] << 16) + (color[1] << 8) + color[2];
}
if (color < 0 || color > 0xffffff) throw new RangeError('COLOR_RANGE');
else if (color && isNaN(color)) throw new TypeError('COLOR_CONVERT');
return color;
}
/**
* Sorts by Discord's position and ID.
* @param {Collection} collection Collection of objects to sort
* @returns {Collection}
*/
static discordSort(collection) {
return collection.sorted(
(a, b) =>
a.rawPosition - b.rawPosition ||
parseInt(b.id.slice(0, -10)) - parseInt(a.id.slice(0, -10)) ||
parseInt(b.id.slice(10)) - parseInt(a.id.slice(10)),
);
}
/**
* Sets the position of a Channel or Role.
* @param {Channel|Role} item Object to set the position of
* @param {number} position New position for the object
* @param {boolean} relative Whether `position` is relative to its current position
* @param {Collection<string, Channel|Role>} sorted A collection of the objects sorted properly
* @param {APIRouter} route Route to call PATCH on
* @param {string} [reason] Reason for the change
* @returns {Promise<Object[]>} Updated item list, with `id` and `position` properties
* @private
*/
static setPosition(item, position, relative, sorted, route, reason) {
let updatedItems = sorted.array();
Util.moveElementInArray(updatedItems, item, position, relative);
updatedItems = updatedItems.map((r, i) => ({ id: r.id, position: i }));
return route.patch({ data: updatedItems, reason }).then(() => updatedItems);
}
/**
* Alternative to Node's `path.basename`, removing query string after the extension if it exists.
* @param {string} path Path to get the basename of
* @param {string} [ext] File extension to remove
* @returns {string} Basename of the path
* @private
*/
static basename(path, ext) {
let res = parse(path);
return ext && res.ext.startsWith(ext) ? res.name : res.base.split('?')[0];
}
/**
* Transforms a snowflake from a decimal string to a bit string.
* @param {Snowflake} num Snowflake to be transformed
* @returns {string}
* @private
*/
static idToBinary(num) {
let bin = '';
let high = parseInt(num.slice(0, -10)) || 0;
let low = parseInt(num.slice(-10));
while (low > 0 || high > 0) {
bin = String(low & 1) + bin;
low = Math.floor(low / 2);
if (high > 0) {
low += 5000000000 * (high % 2);
high = Math.floor(high / 2);
}
}
return bin;
}
/**
* Transforms a snowflake from a bit string to a decimal string.
* @param {string} num Bit string to be transformed
* @returns {Snowflake}
* @private
*/
static binaryToID(num) {
let dec = '';
while (num.length > 50) {
const high = parseInt(num.slice(0, -32), 2);
const low = parseInt((high % 10).toString(2) + num.slice(-32), 2);
dec = (low % 10).toString() + dec;
num =
Math.floor(high / 10).toString(2) +
Math.floor(low / 10)
.toString(2)
.padStart(32, '0');
}
num = parseInt(num, 2);
while (num > 0) {
dec = (num % 10).toString() + dec;
num = Math.floor(num / 10);
}
return dec;
}
/**
* Breaks user, role and everyone/here mentions by adding a zero width space after every @ character
* @param {string} str The string to sanitize
* @returns {string}
*/
static removeMentions(str) {
return str.replace(/@/g, '@\u200b');
}
/**
* The content to have all mentions replaced by the equivalent text.
* @param {string} str The string to be converted
* @param {Message} message The message object to reference
* @returns {string}
*/
static cleanContent(str, message) {
str = str
.replace(/<@!?[0-9]+>/g, input => {
const id = input.replace(/<|!|>|@/g, '');
if (message.channel.type === 'dm') {
const user = message.client.users.cache.get(id);
return user ? Util.removeMentions(`@${user.username}`) : input;
}
const member = message.channel.guild.members.cache.get(id);
if (member) {
return Util.removeMentions(`@${member.displayName}`);
} else {
const user = message.client.users.cache.get(id);
return user ? Util.removeMentions(`@${user.username}`) : input;
}
})
.replace(/<#[0-9]+>/g, input => {
const channel = message.client.channels.cache.get(input.replace(/<|#|>/g, ''));
return channel ? `#${channel.name}` : input;
})
.replace(/<@&[0-9]+>/g, input => {
if (message.channel.type === 'dm') return input;
const role = message.guild.roles.cache.get(input.replace(/<|@|>|&/g, ''));
return role ? `@${role.name}` : input;
});
if (message.client.options.disableMentions === 'everyone') {
str = str.replace(/@([^<>@ ]*)/gmsu, (match, target) => {
if (target.match(/^[&!]?\d+$/)) {
return `@${target}`;
} else {
return `@\u200b${target}`;
}
});
}
if (message.client.options.disableMentions === 'all') {
return Util.removeMentions(str);
} else {
return str;
}
}
/**
* The content to put in a codeblock with all codeblock fences replaced by the equivalent backticks.
* @param {string} text The string to be converted
* @returns {string}
*/
static cleanCodeBlockContent(text) {
return text.replace(/```/g, '`\u200b``');
}
/**
* Creates a Promise that resolves after a specified duration.
* @param {number} ms How long to wait before resolving (in milliseconds)
* @returns {Promise<void>}
* @private
*/
static delayFor(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
}
module.exports = Util;