mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
Merge branch 'master' into indev-prism
This commit is contained in:
@@ -47,10 +47,10 @@ ENCRYPTED_KEY_VAR="encrypted_${ENCRYPTION_LABEL}_key"
|
||||
ENCRYPTED_IV_VAR="encrypted_${ENCRYPTION_LABEL}_iv"
|
||||
ENCRYPTED_KEY=${!ENCRYPTED_KEY_VAR}
|
||||
ENCRYPTED_IV=${!ENCRYPTED_IV_VAR}
|
||||
openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in deploy/deploy_key.enc -out deploy_key -d
|
||||
chmod 600 deploy_key
|
||||
openssl aes-256-cbc -K $ENCRYPTED_KEY -iv $ENCRYPTED_IV -in deploy/deploy-key.enc -out deploy-key -d
|
||||
chmod 600 deploy-key
|
||||
eval `ssh-agent -s`
|
||||
ssh-add deploy_key
|
||||
ssh-add deploy-key
|
||||
|
||||
# Checkout the repo in the target branch so we can build docs and push to it
|
||||
TARGET_BRANCH="docs"
|
||||
|
||||
@@ -40,13 +40,13 @@
|
||||
"ws": "^1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"erlpack": "hammerandchisel/erlpack#master",
|
||||
"erlpack": "hammerandchisel/erlpack",
|
||||
"node-opus": "^0.2.0",
|
||||
"opusscript": "^0.0.1",
|
||||
"uws": "^0.12.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"discord.js-docgen": "hydrabolt/discord.js-docgen#master",
|
||||
"discord.js-docgen": "hydrabolt/discord.js-docgen",
|
||||
"eslint": "^3.12.0",
|
||||
"parallel-webpack": "^1.6.0",
|
||||
"uglify-js": "mishoo/UglifyJS2#harmony",
|
||||
|
||||
@@ -32,7 +32,7 @@ class ClientDataResolver {
|
||||
* * A Message object (resolves to the message author)
|
||||
* * A Guild object (owner of the guild)
|
||||
* * A GuildMember object
|
||||
* @typedef {User|string|Message|Guild|GuildMember} UserResolvable
|
||||
* @typedef {User|Snowflake|Message|Guild|GuildMember} UserResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -52,7 +52,7 @@ class ClientDataResolver {
|
||||
/**
|
||||
* Resolves a UserResolvable to a user ID string
|
||||
* @param {UserResolvable} user The UserResolvable to identify
|
||||
* @returns {?string}
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
resolveUserID(user) {
|
||||
if (user instanceof User || user instanceof GuildMember) return user.id;
|
||||
@@ -66,7 +66,7 @@ class ClientDataResolver {
|
||||
* Data that resolves to give a Guild object. This can be:
|
||||
* * A Guild object
|
||||
* * A Guild ID
|
||||
* @typedef {Guild|string} GuildResolvable
|
||||
* @typedef {Guild|Snowflake} GuildResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -107,7 +107,7 @@ class ClientDataResolver {
|
||||
* * A Message object (the channel the message was sent in)
|
||||
* * A Guild object (the #general channel)
|
||||
* * A channel ID
|
||||
* @typedef {Channel|Guild|Message|string} ChannelResolvable
|
||||
* @typedef {Channel|Guild|Message|Snowflake} ChannelResolvable
|
||||
*/
|
||||
|
||||
/**
|
||||
@@ -126,7 +126,7 @@ class ClientDataResolver {
|
||||
/**
|
||||
* Resolves a ChannelResolvable to a Channel object
|
||||
* @param {ChannelResolvable} channel The channel resolvable to resolve
|
||||
* @returns {?string}
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
resolveChannelID(channel) {
|
||||
if (channel instanceof Channel) return channel.id;
|
||||
|
||||
@@ -139,9 +139,15 @@ class RESTMethods {
|
||||
}
|
||||
|
||||
const url = `${Constants.Endpoints[`${type}Search`](target.id)}?${queryString}`;
|
||||
return this.rest.makeRequest('get', url, true).then(body =>
|
||||
body.messages.map(x => x.map(m => new Message(this.client.channels.get(m.channel_id), m, this.client)))
|
||||
);
|
||||
return this.rest.makeRequest('get', url, true).then(body => {
|
||||
const messages = body.messages.map(x =>
|
||||
x.map(m => new Message(this.client.channels.get(m.channel_id), m, this.client))
|
||||
);
|
||||
return {
|
||||
totalResults: body.total_results,
|
||||
messages,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
createChannel(guild, channelName, channelType, overwrites) {
|
||||
|
||||
@@ -9,6 +9,8 @@ module.exports = {
|
||||
splitMessage: require('./util/SplitMessage'),
|
||||
escapeMarkdown: require('./util/EscapeMarkdown'),
|
||||
fetchRecommendedShards: require('./util/FetchRecommendedShards'),
|
||||
Snowflake: require('./util/Snowflake'),
|
||||
SnowflakeUtil: require('./util/Snowflake'),
|
||||
|
||||
Channel: require('./structures/Channel'),
|
||||
ClientOAuth2Application: require('./structures/ClientOAuth2Application'),
|
||||
|
||||
@@ -27,7 +27,7 @@ class Channel {
|
||||
setup(data) {
|
||||
/**
|
||||
* The unique ID of the channel
|
||||
* @type {string}
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
}
|
||||
|
||||
@@ -26,21 +26,21 @@ class ClientUser extends User {
|
||||
/**
|
||||
* A Collection of friends for the logged in user.
|
||||
* <warn>This is only filled when using a user account.</warn>
|
||||
* @type {Collection<string, User>}
|
||||
* @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<string, User>}
|
||||
* @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<string, string>}
|
||||
* @type {Collection<Snowflake, string>}
|
||||
*/
|
||||
this.notes = new Collection();
|
||||
|
||||
@@ -50,6 +50,27 @@ class ClientUser extends User {
|
||||
* @type {Object}
|
||||
*/
|
||||
this.settings = {};
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
edit(data) {
|
||||
@@ -229,7 +250,7 @@ class ClientUser extends User {
|
||||
* @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 {Guild|string} [options.guild] Limit the search to a specific guild
|
||||
* @param {Guild|Snowflake} [options.guild] Limit the search to a specific guild
|
||||
* @returns {Promise<Message[]>}
|
||||
*/
|
||||
fetchMentions(options = { limit: 25, roles: true, everyone: true, guild: null }) {
|
||||
|
||||
@@ -26,7 +26,7 @@ class Emoji {
|
||||
setup(data) {
|
||||
/**
|
||||
* The ID of the emoji
|
||||
* @type {string}
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
@@ -71,7 +71,7 @@ class Emoji {
|
||||
|
||||
/**
|
||||
* A collection of roles this emoji is active for (empty if all), mapped by role ID.
|
||||
* @type {Collection<string, Role>}
|
||||
* @type {Collection<Snowflake, Role>}
|
||||
* @readonly
|
||||
*/
|
||||
get roles() {
|
||||
@@ -91,6 +91,16 @@ class Emoji {
|
||||
return Constants.Endpoints.emoji(this.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);
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically returns the emoji mention rather than the object.
|
||||
* @returns {string}
|
||||
@@ -123,18 +133,6 @@ class Emoji {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The identifier of this emoji, used for message reactions
|
||||
* @readonly
|
||||
* @type {string}
|
||||
*/
|
||||
get identifier() {
|
||||
if (this.id) {
|
||||
return `${this.name}:${this.id}`;
|
||||
}
|
||||
return encodeURIComponent(this.name);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Emoji;
|
||||
|
||||
@@ -61,7 +61,7 @@ class GroupDMChannel extends Channel {
|
||||
if (!this.recipients) {
|
||||
/**
|
||||
* A collection of the recipients of this DM, mapped by their ID.
|
||||
* @type {Collection<string, User>}
|
||||
* @type {Collection<Snowflake, User>}
|
||||
*/
|
||||
this.recipients = new Collection();
|
||||
}
|
||||
|
||||
@@ -25,25 +25,25 @@ class Guild {
|
||||
|
||||
/**
|
||||
* A collection of members that are in this guild. The key is the member's ID, the value is the member.
|
||||
* @type {Collection<string, GuildMember>}
|
||||
* @type {Collection<Snowflake, GuildMember>}
|
||||
*/
|
||||
this.members = new Collection();
|
||||
|
||||
/**
|
||||
* A collection of channels that are in this guild. The key is the channel's ID, the value is the channel.
|
||||
* @type {Collection<string, GuildChannel>}
|
||||
* @type {Collection<Snowflake, GuildChannel>}
|
||||
*/
|
||||
this.channels = new Collection();
|
||||
|
||||
/**
|
||||
* A collection of roles that are in this guild. The key is the role's ID, the value is the role.
|
||||
* @type {Collection<string, Role>}
|
||||
* @type {Collection<Snowflake, Role>}
|
||||
*/
|
||||
this.roles = new Collection();
|
||||
|
||||
/**
|
||||
* A collection of presences in this guild
|
||||
* @type {Collection<string, Presence>}
|
||||
* @type {Collection<Snowflake, Presence>}
|
||||
*/
|
||||
this.presences = new Collection();
|
||||
|
||||
@@ -57,7 +57,7 @@ class Guild {
|
||||
|
||||
/**
|
||||
* The Unique ID of the Guild, useful for comparisons.
|
||||
* @type {string}
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
} else {
|
||||
@@ -106,7 +106,7 @@ class Guild {
|
||||
* Whether the guild is "large" (has more than 250 members)
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.large = data.large || this.large;
|
||||
this.large = Boolean('large' in data ? data.large : this.large);
|
||||
|
||||
/**
|
||||
* An array of guild features.
|
||||
@@ -116,13 +116,13 @@ class Guild {
|
||||
|
||||
/**
|
||||
* The ID of the application that created this guild (if applicable)
|
||||
* @type {?string}
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.applicationID = data.application_id;
|
||||
|
||||
/**
|
||||
* A collection of emojis that are in this guild. The key is the emoji's ID, the value is the emoji.
|
||||
* @type {Collection<string, Emoji>}
|
||||
* @type {Collection<Snowflake, Emoji>}
|
||||
*/
|
||||
this.emojis = new Collection();
|
||||
for (const emoji of data.emojis) this.emojis.set(emoji.id, new Emoji(this, emoji));
|
||||
@@ -169,7 +169,7 @@ class Guild {
|
||||
if (data.owner_id) {
|
||||
/**
|
||||
* The user ID of this guild's owner.
|
||||
* @type {string}
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.ownerID = data.owner_id;
|
||||
}
|
||||
@@ -373,8 +373,8 @@ class Guild {
|
||||
* content: 'discord.js',
|
||||
* before: '2016-11-17'
|
||||
* }).then(res => {
|
||||
* const hit = res[0].find(m => m.hit).content;
|
||||
* console.log(`I found: **${hit}**`);
|
||||
* const hit = res.messages[0].find(m => m.hit).content;
|
||||
* console.log(`I found: **${hit}**, total results: ${res.totalResults}`);
|
||||
* }).catch(console.error);
|
||||
*/
|
||||
search(options) {
|
||||
|
||||
@@ -37,7 +37,7 @@ class GuildChannel extends Channel {
|
||||
|
||||
/**
|
||||
* A map of permission overwrites in this channel for roles and users.
|
||||
* @type {Collection<string, PermissionOverwrites>}
|
||||
* @type {Collection<Snowflake, PermissionOverwrites>}
|
||||
*/
|
||||
this.permissionOverwrites = new Collection();
|
||||
if (data.permission_overwrites) {
|
||||
|
||||
@@ -36,7 +36,7 @@ class GuildMember {
|
||||
|
||||
/**
|
||||
* The ID of the last message sent by the member in their guild, if one was sent.
|
||||
* @type {?string}
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.lastMessageID = null;
|
||||
}
|
||||
@@ -68,13 +68,13 @@ class GuildMember {
|
||||
|
||||
/**
|
||||
* The voice session ID of this member, if any
|
||||
* @type {?string}
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.voiceSessionID = data.session_id;
|
||||
|
||||
/**
|
||||
* The voice channel ID of this member, if any
|
||||
* @type {?string}
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.voiceChannelID = data.channel_id;
|
||||
|
||||
@@ -120,7 +120,7 @@ class GuildMember {
|
||||
|
||||
/**
|
||||
* A list of roles that are applied to this GuildMember, mapped by the role ID.
|
||||
* @type {Collection<string, Role>}
|
||||
* @type {Collection<Snowflake, Role>}
|
||||
* @readonly
|
||||
*/
|
||||
get roles() {
|
||||
@@ -175,7 +175,7 @@ class GuildMember {
|
||||
|
||||
/**
|
||||
* The ID of this user
|
||||
* @type {string}
|
||||
* @type {Snowflake}
|
||||
* @readonly
|
||||
*/
|
||||
get id() {
|
||||
|
||||
@@ -4,9 +4,7 @@ const MessageReaction = require('./MessageReaction');
|
||||
const Collection = require('../util/Collection');
|
||||
const Constants = require('../util/Constants');
|
||||
const escapeMarkdown = require('../util/EscapeMarkdown');
|
||||
|
||||
// Done purely for GuildMember, which would cause a bad circular dependency
|
||||
const Discord = require('..');
|
||||
let GuildMember;
|
||||
|
||||
/**
|
||||
* Represents a message on Discord
|
||||
@@ -33,7 +31,7 @@ class Message {
|
||||
setup(data) { // eslint-disable-line complexity
|
||||
/**
|
||||
* The ID of the message (unique in the channel it was sent)
|
||||
* @type {string}
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
@@ -75,7 +73,7 @@ class Message {
|
||||
this.tts = data.tts;
|
||||
|
||||
/**
|
||||
* A random number used for checking message delivery
|
||||
* A random number or string used for checking message delivery
|
||||
* @type {string}
|
||||
*/
|
||||
this.nonce = data.nonce;
|
||||
@@ -94,7 +92,7 @@ class Message {
|
||||
|
||||
/**
|
||||
* A collection of attachments in the message - e.g. Pictures - mapped by their ID.
|
||||
* @type {Collection<string, MessageAttachment>}
|
||||
* @type {Collection<Snowflake, MessageAttachment>}
|
||||
*/
|
||||
this.attachments = new Collection();
|
||||
for (const attachment of data.attachments) this.attachments.set(attachment.id, new Attachment(this, attachment));
|
||||
@@ -114,9 +112,9 @@ class Message {
|
||||
/**
|
||||
* An object containing a further users, roles or channels collections
|
||||
* @type {Object}
|
||||
* @property {Collection<string, User>} mentions.users Mentioned users, maps their ID to the user object.
|
||||
* @property {Collection<string, Role>} mentions.roles Mentioned roles, maps their ID to the role object.
|
||||
* @property {Collection<string, GuildChannel>} mentions.channels Mentioned channels,
|
||||
* @property {Collection<Snowflake, User>} mentions.users Mentioned users, maps their ID to the user object.
|
||||
* @property {Collection<Snowflake, Role>} mentions.roles Mentioned roles, maps their ID to the role object.
|
||||
* @property {Collection<Snowflake, GuildChannel>} mentions.channels Mentioned channels,
|
||||
* maps their ID to the channel object.
|
||||
* @property {boolean} mentions.everyone Whether or not @everyone was mentioned.
|
||||
*/
|
||||
@@ -156,7 +154,7 @@ class Message {
|
||||
|
||||
/**
|
||||
* A collection of reactions to this message, mapped by the reaction "id".
|
||||
* @type {Collection<string, MessageReaction>}
|
||||
* @type {Collection<Snowflake|string, MessageReaction>}
|
||||
*/
|
||||
this.reactions = new Collection();
|
||||
|
||||
@@ -169,7 +167,7 @@ class Message {
|
||||
|
||||
/**
|
||||
* ID of the webhook that sent the message, if applicable
|
||||
* @type {?string}
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.webhookID = data.webhook_id || null;
|
||||
|
||||
@@ -365,9 +363,11 @@ class Message {
|
||||
* @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 Discord.GuildMember && member.roles.some(r => this.mentions.roles.has(r.id))) return true;
|
||||
if (member instanceof GuildMember && member.roles.some(r => this.mentions.roles.has(r.id))) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -390,7 +390,7 @@ class Message {
|
||||
* .catch(console.error);
|
||||
*/
|
||||
edit(content, options) {
|
||||
if (!options && typeof content === 'object') {
|
||||
if (!options && typeof content === 'object' && !(content instanceof Array)) {
|
||||
options = content;
|
||||
content = '';
|
||||
} else if (!options) {
|
||||
@@ -535,7 +535,7 @@ class Message {
|
||||
}
|
||||
|
||||
_addReaction(emoji, user) {
|
||||
const emojiID = emoji.id ? `${emoji.name}:${emoji.id}` : emoji.name;
|
||||
const emojiID = emoji.identifier;
|
||||
let reaction;
|
||||
if (this.reactions.has(emojiID)) {
|
||||
reaction = this.reactions.get(emojiID);
|
||||
@@ -553,7 +553,7 @@ class Message {
|
||||
}
|
||||
|
||||
_removeReaction(emoji, user) {
|
||||
const emojiID = emoji.id || emoji;
|
||||
const emojiID = emoji.identifier;
|
||||
if (this.reactions.has(emojiID)) {
|
||||
const reaction = this.reactions.get(emojiID);
|
||||
if (reaction.users.has(user.id)) {
|
||||
|
||||
@@ -23,7 +23,7 @@ class MessageAttachment {
|
||||
setup(data) {
|
||||
/**
|
||||
* The ID of this attachment
|
||||
* @type {string}
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
|
||||
@@ -61,7 +61,7 @@ class MessageCollector extends EventEmitter {
|
||||
|
||||
/**
|
||||
* A collection of collected messages, mapped by message ID.
|
||||
* @type {Collection<string, Message>}
|
||||
* @type {Collection<Snowflake, Message>}
|
||||
*/
|
||||
this.collected = new Collection();
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class MessageReaction {
|
||||
|
||||
/**
|
||||
* The users that have given this reaction, mapped by their ID.
|
||||
* @type {Collection<string, User>}
|
||||
* @type {Collection<Snowflake, User>}
|
||||
*/
|
||||
this.users = new Collection();
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class OAuth2Application {
|
||||
setup(data) {
|
||||
/**
|
||||
* The ID of the app
|
||||
* @type {string}
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ class PartialGuild {
|
||||
setup(data) {
|
||||
/**
|
||||
* The ID of this guild
|
||||
* @type {string}
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ class PartialGuildChannel {
|
||||
setup(data) {
|
||||
/**
|
||||
* The ID of this guild channel
|
||||
* @type {string}
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class PermissionOverwrites {
|
||||
setup(data) {
|
||||
/**
|
||||
* The ID of this overwrite, either a user ID or a role ID
|
||||
* @type {string}
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
|
||||
@@ -19,15 +19,15 @@ class ReactionEmoji {
|
||||
|
||||
/**
|
||||
* The ID of this reaction emoji.
|
||||
* @type {string}
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* The identifier of this emoji, used for message reactions
|
||||
* @readonly
|
||||
* @type {string}
|
||||
* @readonly
|
||||
*/
|
||||
get identifier() {
|
||||
if (this.id) return `${this.name}:${this.id}`;
|
||||
|
||||
@@ -25,7 +25,7 @@ class Role {
|
||||
setup(data) {
|
||||
/**
|
||||
* The ID of the role (unique to the guild it is part of)
|
||||
* @type {string}
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
@@ -103,7 +103,7 @@ class Role {
|
||||
|
||||
/**
|
||||
* The cached guild members that have this role.
|
||||
* @type {Collection<string, GuildMember>}
|
||||
* @type {Collection<Snowflake, GuildMember>}
|
||||
* @readonly
|
||||
*/
|
||||
get members() {
|
||||
|
||||
@@ -29,7 +29,7 @@ class TextChannel extends GuildChannel {
|
||||
|
||||
/**
|
||||
* A collection of members that can see this channel, mapped by their ID.
|
||||
* @type {Collection<string, GuildMember>}
|
||||
* @type {Collection<Snowflake, GuildMember>}
|
||||
* @readonly
|
||||
*/
|
||||
get members() {
|
||||
|
||||
@@ -22,7 +22,7 @@ class User {
|
||||
setup(data) {
|
||||
/**
|
||||
* The ID of the user
|
||||
* @type {string}
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
@@ -52,7 +52,7 @@ class User {
|
||||
|
||||
/**
|
||||
* The ID of the last message sent by the user, if one was sent.
|
||||
* @type {?string}
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.lastMessageID = null;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ class VoiceChannel extends GuildChannel {
|
||||
|
||||
/**
|
||||
* The members in this voice channel.
|
||||
* @type {Collection<string, GuildMember>}
|
||||
* @type {Collection<Snowflake, GuildMember>}
|
||||
*/
|
||||
this.members = new Collection();
|
||||
|
||||
|
||||
@@ -43,19 +43,19 @@ class Webhook {
|
||||
|
||||
/**
|
||||
* The ID of the webhook
|
||||
* @type {string}
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.id = data.id;
|
||||
|
||||
/**
|
||||
* The guild the webhook belongs to
|
||||
* @type {string}
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.guildID = data.guild_id;
|
||||
|
||||
/**
|
||||
* The channel the webhook belongs to
|
||||
* @type {string}
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.channelID = data.channel_id;
|
||||
|
||||
|
||||
@@ -11,13 +11,13 @@ class TextBasedChannel {
|
||||
constructor() {
|
||||
/**
|
||||
* A collection containing the messages sent to this channel.
|
||||
* @type {Collection<string, Message>}
|
||||
* @type {Collection<Snowflake, Message>}
|
||||
*/
|
||||
this.messages = new Collection();
|
||||
|
||||
/**
|
||||
* The ID of the last message in the channel, if one was sent.
|
||||
* @type {?string}
|
||||
* @type {?Snowflake}
|
||||
*/
|
||||
this.lastMessageID = null;
|
||||
}
|
||||
@@ -224,8 +224,8 @@ class TextBasedChannel {
|
||||
* content: 'discord.js',
|
||||
* before: '2016-11-17'
|
||||
* }).then(res => {
|
||||
* const hit = res[0].find(m => m.hit).content;
|
||||
* console.log(`I found: **${hit}**`);
|
||||
* const hit = res.messages[0].find(m => m.hit).content;
|
||||
* console.log(`I found: **${hit}**, total results: ${res.totalResults}`);
|
||||
* }).catch(console.error);
|
||||
*/
|
||||
search(options) {
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
function arrayBufferToBuffer(ab) {
|
||||
const buffer = new Buffer(ab.byteLength);
|
||||
const view = new Uint8Array(ab);
|
||||
for (var i = 0; i < buffer.length; ++i) buffer[i] = view[i];
|
||||
return buffer;
|
||||
}
|
||||
|
||||
function str2ab(str) {
|
||||
const buffer = new ArrayBuffer(str.length * 2);
|
||||
const view = new Uint16Array(buffer);
|
||||
@@ -14,5 +7,5 @@ function str2ab(str) {
|
||||
|
||||
module.exports = function convertArrayBuffer(x) {
|
||||
if (typeof x === 'string') x = str2ab(x);
|
||||
return arrayBufferToBuffer(x);
|
||||
return Buffer.from(x);
|
||||
};
|
||||
|
||||
@@ -3,17 +3,18 @@ const botGateway = require('./Constants').Endpoints.botGateway;
|
||||
|
||||
/**
|
||||
* Gets the recommended shard count from Discord
|
||||
* @param {number} token Discord auth token
|
||||
* @param {string} token Discord auth token
|
||||
* @param {number} [guildsPerShard=1000] Number of guilds per shard
|
||||
* @returns {Promise<number>} the recommended number of shards
|
||||
*/
|
||||
module.exports = function fetchRecommendedShards(token) {
|
||||
module.exports = function fetchRecommendedShards(token, guildsPerShard = 1000) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!token) throw new Error('A token must be provided.');
|
||||
superagent.get(botGateway)
|
||||
.set('Authorization', `Bot ${token.replace(/^Bot\s*/i, '')}`)
|
||||
.end((err, res) => {
|
||||
if (err) reject(err);
|
||||
resolve(res.body.shards);
|
||||
resolve(res.body.shards * (1000 / guildsPerShard));
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
65
src/util/Snowflake.js
Normal file
65
src/util/Snowflake.js
Normal file
@@ -0,0 +1,65 @@
|
||||
const Long = require('long');
|
||||
|
||||
// Discord epoch (2015-01-01T00:00:00.000Z)
|
||||
const EPOCH = 1420070400000;
|
||||
let INCREMENT = 0;
|
||||
|
||||
/**
|
||||
* A container for useful snowflake-related methods
|
||||
*/
|
||||
class SnowflakeUtil {
|
||||
/**
|
||||
* 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>
|
||||
* @returns {Snowflake} The generated snowflake
|
||||
*/
|
||||
static generate() {
|
||||
if (INCREMENT >= 4095) INCREMENT = 0;
|
||||
const BINARY = `${pad((Date.now() - EPOCH).toString(2), 42)}0000100000${pad((INCREMENT++).toString(2), 12)}`;
|
||||
return Long.fromString(BINARY, 2).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* A deconstructed snowflake
|
||||
* @typedef {Object} DeconstructedSnowflake
|
||||
* @property {Date} date Date in the snowflake
|
||||
* @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 = pad(Long.fromString(snowflake).toString(2), 64);
|
||||
return {
|
||||
date: new Date(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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function pad(v, n, c = '0') {
|
||||
return String(v).length >= n ? String(v) : (String(c).repeat(n) + v).slice(-n);
|
||||
}
|
||||
|
||||
module.exports = SnowflakeUtil;
|
||||
@@ -21,7 +21,7 @@ const long = require('long');
|
||||
* @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} [attachmentExtention] The extension 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)
|
||||
@@ -42,7 +42,7 @@ module.exports = function TransformSearchOptions(options, client) {
|
||||
if (!(options.during instanceof Date)) options.during = new Date(options.during);
|
||||
const t = options.during.getTime() - 14200704e5;
|
||||
options.minID = long.fromNumber(t).shiftLeft(22).toString();
|
||||
options.maxID = long.fromNumber(t + 86400000).shift(222).toString();
|
||||
options.maxID = long.fromNumber(t + 86400000).shiftLeft(22).toString();
|
||||
}
|
||||
|
||||
if (options.channel) options.channel = client.resolver.resolveChannelID(options.channel);
|
||||
|
||||
Reference in New Issue
Block a user