From 2156ce1e1592cbde070dda39de51815bfb862880 Mon Sep 17 00:00:00 2001 From: Schuyler Cebulskie Date: Fri, 30 Dec 2016 18:06:08 -0500 Subject: [PATCH 01/16] Remove unnecessary branch specification --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index a26af5637..bae0290b1 100644 --- a/package.json +++ b/package.json @@ -39,13 +39,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", From 2b256412709a807365c95dec9ea50f08e1009175 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Fri, 30 Dec 2016 20:03:23 -0600 Subject: [PATCH 02/16] add option for guilds per shard, and fix type (#1053) --- src/util/FetchRecommendedShards.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/util/FetchRecommendedShards.js b/src/util/FetchRecommendedShards.js index a60f51006..217009077 100644 --- a/src/util/FetchRecommendedShards.js +++ b/src/util/FetchRecommendedShards.js @@ -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} 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)); }); }); }; From 054d4655c1a3142663ea63cf4cc001adb2da7e01 Mon Sep 17 00:00:00 2001 From: Schuyler Cebulskie Date: Fri, 30 Dec 2016 21:05:34 -0500 Subject: [PATCH 03/16] Rearrange identifier --- src/structures/Emoji.js | 22 ++++++++++------------ src/structures/ReactionEmoji.js | 2 +- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/structures/Emoji.js b/src/structures/Emoji.js index d8a62e17e..6cd39f661 100644 --- a/src/structures/Emoji.js +++ b/src/structures/Emoji.js @@ -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; diff --git a/src/structures/ReactionEmoji.js b/src/structures/ReactionEmoji.js index b6d2cdbd6..58d00b9b8 100644 --- a/src/structures/ReactionEmoji.js +++ b/src/structures/ReactionEmoji.js @@ -26,8 +26,8 @@ class ReactionEmoji { /** * The identifier of this emoji, used for message reactions - * @readonly * @type {string} + * @readonly */ get identifier() { if (this.id) return `${this.name}:${this.id}`; From 3b9b06227e3483ebd6a690e72e5b2dd4197fa517 Mon Sep 17 00:00:00 2001 From: Michael Huang Date: Fri, 30 Dec 2016 18:06:05 -0800 Subject: [PATCH 04/16] Fix _removeReaction's reaction lookup (#1045) * Fix _removeReaction's `this.reactions` lookup * Use emoji.identifier for reaction collection keys --- src/structures/Message.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/structures/Message.js b/src/structures/Message.js index 85a17c549..51b2314f1 100644 --- a/src/structures/Message.js +++ b/src/structures/Message.js @@ -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)) { From f485ec22b23d78498a462ce59077df87aa33ca39 Mon Sep 17 00:00:00 2001 From: Schuyler Cebulskie Date: Mon, 2 Jan 2017 01:49:06 -0500 Subject: [PATCH 05/16] Rename deploy key --- deploy/{deploy_key.enc => deploy-key.enc} | Bin deploy/deploy.sh | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) rename deploy/{deploy_key.enc => deploy-key.enc} (100%) diff --git a/deploy/deploy_key.enc b/deploy/deploy-key.enc similarity index 100% rename from deploy/deploy_key.enc rename to deploy/deploy-key.enc diff --git a/deploy/deploy.sh b/deploy/deploy.sh index 13811122b..97b3539bc 100644 --- a/deploy/deploy.sh +++ b/deploy/deploy.sh @@ -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" From 2c26d79f505a5ab0f734b212e06bce566c138da2 Mon Sep 17 00:00:00 2001 From: Schuyler Cebulskie Date: Mon, 2 Jan 2017 01:51:26 -0500 Subject: [PATCH 06/16] Replace custom ArrayBuffer converter with Buffer.from --- src/util/ConvertArrayBuffer.js | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/util/ConvertArrayBuffer.js b/src/util/ConvertArrayBuffer.js index 26b1cc8b7..c6bd36433 100644 --- a/src/util/ConvertArrayBuffer.js +++ b/src/util/ConvertArrayBuffer.js @@ -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); }; From 7cbe81e71a7a242bbc0eddc644e8f8bf8834b530 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Tue, 3 Jan 2017 00:59:34 -0600 Subject: [PATCH 07/16] fix editing with an array (#1059) * fix editing with an array * fix build * put this back because reasons * i'm having one of those nights --- src/structures/Message.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/Message.js b/src/structures/Message.js index 51b2314f1..cf4c481f0 100644 --- a/src/structures/Message.js +++ b/src/structures/Message.js @@ -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) { From d47f9d202b4195a6d26e90e15adc378883adf952 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Tue, 3 Jan 2017 17:49:19 -0600 Subject: [PATCH 08/16] update search to have more useful returns (#1060) --- src/client/rest/RESTMethods.js | 12 +++++++++--- src/structures/Guild.js | 4 ++-- src/structures/interface/TextBasedChannel.js | 4 ++-- src/util/TransformSearchOptions.js | 2 +- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js index b1b51b4aa..5ecae4610 100644 --- a/src/client/rest/RESTMethods.js +++ b/src/client/rest/RESTMethods.js @@ -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) { diff --git a/src/structures/Guild.js b/src/structures/Guild.js index aa0f717ab..e3c50b00e 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -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) { diff --git a/src/structures/interface/TextBasedChannel.js b/src/structures/interface/TextBasedChannel.js index dd763d7f0..0daf8600a 100644 --- a/src/structures/interface/TextBasedChannel.js +++ b/src/structures/interface/TextBasedChannel.js @@ -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) { diff --git a/src/util/TransformSearchOptions.js b/src/util/TransformSearchOptions.js index e61056aed..f3e1a6c76 100644 --- a/src/util/TransformSearchOptions.js +++ b/src/util/TransformSearchOptions.js @@ -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); From 495264761c99655012b071301a58a5dc929a257f Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Thu, 5 Jan 2017 09:41:42 -0600 Subject: [PATCH 09/16] Add snowflake utils (#1064) * snowflakes * use proper binary for snowflake example * fix jsdoc errors * remove dupe --- src/client/ClientDataResolver.js | 10 ++-- src/index.js | 1 + src/structures/Channel.js | 2 +- src/structures/ClientUser.js | 8 +-- src/structures/Emoji.js | 4 +- src/structures/GroupDMChannel.js | 2 +- src/structures/Guild.js | 16 ++--- src/structures/GuildChannel.js | 2 +- src/structures/GuildMember.js | 10 ++-- src/structures/Message.js | 16 ++--- src/structures/MessageAttachment.js | 2 +- src/structures/MessageCollector.js | 2 +- src/structures/MessageReaction.js | 2 +- src/structures/OAuth2Application.js | 2 +- src/structures/PartialGuild.js | 2 +- src/structures/PartialGuildChannel.js | 2 +- src/structures/PermissionOverwrites.js | 2 +- src/structures/ReactionEmoji.js | 2 +- src/structures/Role.js | 4 +- src/structures/TextChannel.js | 2 +- src/structures/User.js | 4 +- src/structures/VoiceChannel.js | 2 +- src/structures/Webhook.js | 6 +- src/structures/interface/TextBasedChannel.js | 4 +- src/util/Snowflake.js | 62 ++++++++++++++++++++ 25 files changed, 117 insertions(+), 54 deletions(-) create mode 100644 src/util/Snowflake.js diff --git a/src/client/ClientDataResolver.js b/src/client/ClientDataResolver.js index c17d4944e..c6bf38717 100644 --- a/src/client/ClientDataResolver.js +++ b/src/client/ClientDataResolver.js @@ -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; diff --git a/src/index.js b/src/index.js index 85326bfc1..07cfbf39b 100644 --- a/src/index.js +++ b/src/index.js @@ -9,6 +9,7 @@ module.exports = { splitMessage: require('./util/SplitMessage'), escapeMarkdown: require('./util/EscapeMarkdown'), fetchRecommendedShards: require('./util/FetchRecommendedShards'), + Snowflake: require('./util/Snowflake'), Channel: require('./structures/Channel'), ClientOAuth2Application: require('./structures/ClientOAuth2Application'), diff --git a/src/structures/Channel.js b/src/structures/Channel.js index b37b14b41..6b42b2cd6 100644 --- a/src/structures/Channel.js +++ b/src/structures/Channel.js @@ -27,7 +27,7 @@ class Channel { setup(data) { /** * The unique ID of the channel - * @type {string} + * @type {Snowflake} */ this.id = data.id; } diff --git a/src/structures/ClientUser.js b/src/structures/ClientUser.js index 67e19f9c2..22140bee8 100644 --- a/src/structures/ClientUser.js +++ b/src/structures/ClientUser.js @@ -26,21 +26,21 @@ class ClientUser extends User { /** * A Collection of friends for the logged in user. * This is only filled when using a user account. - * @type {Collection} + * @type {Collection} */ this.friends = new Collection(); /** * A Collection of blocked users for the logged in user. * This is only filled when using a user account. - * @type {Collection} + * @type {Collection} */ this.blocked = new Collection(); /** * A Collection of notes for the logged in user. * This is only filled when using a user account. - * @type {Collection} + * @type {Collection} */ this.notes = new Collection(); @@ -229,7 +229,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} */ fetchMentions(options = { limit: 25, roles: true, everyone: true, guild: null }) { diff --git a/src/structures/Emoji.js b/src/structures/Emoji.js index 6cd39f661..519092c28 100644 --- a/src/structures/Emoji.js +++ b/src/structures/Emoji.js @@ -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} + * @type {Collection} * @readonly */ get roles() { diff --git a/src/structures/GroupDMChannel.js b/src/structures/GroupDMChannel.js index d6b5338d4..cf6739fd3 100644 --- a/src/structures/GroupDMChannel.js +++ b/src/structures/GroupDMChannel.js @@ -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} + * @type {Collection} */ this.recipients = new Collection(); } diff --git a/src/structures/Guild.js b/src/structures/Guild.js index e3c50b00e..8b5cb2d3c 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -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} + * @type {Collection} */ 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} + * @type {Collection} */ 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} + * @type {Collection} */ this.roles = new Collection(); /** * A collection of presences in this guild - * @type {Collection} + * @type {Collection} */ 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 { @@ -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} + * @type {Collection} */ 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; } diff --git a/src/structures/GuildChannel.js b/src/structures/GuildChannel.js index a93078972..ef5687c43 100644 --- a/src/structures/GuildChannel.js +++ b/src/structures/GuildChannel.js @@ -37,7 +37,7 @@ class GuildChannel extends Channel { /** * A map of permission overwrites in this channel for roles and users. - * @type {Collection} + * @type {Collection} */ this.permissionOverwrites = new Collection(); if (data.permission_overwrites) { diff --git a/src/structures/GuildMember.js b/src/structures/GuildMember.js index 60a498a3e..c3cb86cdb 100644 --- a/src/structures/GuildMember.js +++ b/src/structures/GuildMember.js @@ -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} + * @type {Collection} * @readonly */ get roles() { @@ -175,7 +175,7 @@ class GuildMember { /** * The ID of this user - * @type {string} + * @type {Snowflake} * @readonly */ get id() { diff --git a/src/structures/Message.js b/src/structures/Message.js index cf4c481f0..7d6708f10 100644 --- a/src/structures/Message.js +++ b/src/structures/Message.js @@ -33,7 +33,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 +75,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 +94,7 @@ class Message { /** * A collection of attachments in the message - e.g. Pictures - mapped by their ID. - * @type {Collection} + * @type {Collection} */ this.attachments = new Collection(); for (const attachment of data.attachments) this.attachments.set(attachment.id, new Attachment(this, attachment)); @@ -114,9 +114,9 @@ class Message { /** * An object containing a further users, roles or channels collections * @type {Object} - * @property {Collection} mentions.users Mentioned users, maps their ID to the user object. - * @property {Collection} mentions.roles Mentioned roles, maps their ID to the role object. - * @property {Collection} mentions.channels Mentioned channels, + * @property {Collection} mentions.users Mentioned users, maps their ID to the user object. + * @property {Collection} mentions.roles Mentioned roles, maps their ID to the role object. + * @property {Collection} mentions.channels Mentioned channels, * maps their ID to the channel object. * @property {boolean} mentions.everyone Whether or not @everyone was mentioned. */ @@ -156,7 +156,7 @@ class Message { /** * A collection of reactions to this message, mapped by the reaction "id". - * @type {Collection} + * @type {Collection} */ this.reactions = new Collection(); @@ -169,7 +169,7 @@ class Message { /** * ID of the webhook that sent the message, if applicable - * @type {?string} + * @type {?Snowflake} */ this.webhookID = data.webhook_id || null; diff --git a/src/structures/MessageAttachment.js b/src/structures/MessageAttachment.js index 29dfb524e..6bd1030f9 100644 --- a/src/structures/MessageAttachment.js +++ b/src/structures/MessageAttachment.js @@ -23,7 +23,7 @@ class MessageAttachment { setup(data) { /** * The ID of this attachment - * @type {string} + * @type {Snowflake} */ this.id = data.id; diff --git a/src/structures/MessageCollector.js b/src/structures/MessageCollector.js index f84ecbda3..54e9b1539 100644 --- a/src/structures/MessageCollector.js +++ b/src/structures/MessageCollector.js @@ -61,7 +61,7 @@ class MessageCollector extends EventEmitter { /** * A collection of collected messages, mapped by message ID. - * @type {Collection} + * @type {Collection} */ this.collected = new Collection(); diff --git a/src/structures/MessageReaction.js b/src/structures/MessageReaction.js index 30c555f9d..eada0d7a5 100644 --- a/src/structures/MessageReaction.js +++ b/src/structures/MessageReaction.js @@ -27,7 +27,7 @@ class MessageReaction { /** * The users that have given this reaction, mapped by their ID. - * @type {Collection} + * @type {Collection} */ this.users = new Collection(); diff --git a/src/structures/OAuth2Application.js b/src/structures/OAuth2Application.js index b7c728581..cbe162466 100644 --- a/src/structures/OAuth2Application.js +++ b/src/structures/OAuth2Application.js @@ -17,7 +17,7 @@ class OAuth2Application { setup(data) { /** * The ID of the app - * @type {string} + * @type {Snowflake} */ this.id = data.id; diff --git a/src/structures/PartialGuild.js b/src/structures/PartialGuild.js index 407212e2f..e16f67bee 100644 --- a/src/structures/PartialGuild.js +++ b/src/structures/PartialGuild.js @@ -24,7 +24,7 @@ class PartialGuild { setup(data) { /** * The ID of this guild - * @type {string} + * @type {Snowflake} */ this.id = data.id; diff --git a/src/structures/PartialGuildChannel.js b/src/structures/PartialGuildChannel.js index e58a6bb91..13cf4c2f9 100644 --- a/src/structures/PartialGuildChannel.js +++ b/src/structures/PartialGuildChannel.js @@ -23,7 +23,7 @@ class PartialGuildChannel { setup(data) { /** * The ID of this guild channel - * @type {string} + * @type {Snowflake} */ this.id = data.id; diff --git a/src/structures/PermissionOverwrites.js b/src/structures/PermissionOverwrites.js index 9b2f536f5..8044be45a 100644 --- a/src/structures/PermissionOverwrites.js +++ b/src/structures/PermissionOverwrites.js @@ -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; diff --git a/src/structures/ReactionEmoji.js b/src/structures/ReactionEmoji.js index 58d00b9b8..b504a3635 100644 --- a/src/structures/ReactionEmoji.js +++ b/src/structures/ReactionEmoji.js @@ -19,7 +19,7 @@ class ReactionEmoji { /** * The ID of this reaction emoji. - * @type {string} + * @type {?Snowflake} */ this.id = id; } diff --git a/src/structures/Role.js b/src/structures/Role.js index c15ff4be0..329a2264c 100644 --- a/src/structures/Role.js +++ b/src/structures/Role.js @@ -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} + * @type {Collection} * @readonly */ get members() { diff --git a/src/structures/TextChannel.js b/src/structures/TextChannel.js index 6e98e9e89..38e6a56be 100644 --- a/src/structures/TextChannel.js +++ b/src/structures/TextChannel.js @@ -29,7 +29,7 @@ class TextChannel extends GuildChannel { /** * A collection of members that can see this channel, mapped by their ID. - * @type {Collection} + * @type {Collection} * @readonly */ get members() { diff --git a/src/structures/User.js b/src/structures/User.js index fd0a8d305..6beb3f352 100644 --- a/src/structures/User.js +++ b/src/structures/User.js @@ -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; } diff --git a/src/structures/VoiceChannel.js b/src/structures/VoiceChannel.js index 848a6d513..ad18a94b0 100644 --- a/src/structures/VoiceChannel.js +++ b/src/structures/VoiceChannel.js @@ -11,7 +11,7 @@ class VoiceChannel extends GuildChannel { /** * The members in this voice channel. - * @type {Collection} + * @type {Collection} */ this.members = new Collection(); diff --git a/src/structures/Webhook.js b/src/structures/Webhook.js index 96984ffe0..153d8f3a5 100644 --- a/src/structures/Webhook.js +++ b/src/structures/Webhook.js @@ -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; diff --git a/src/structures/interface/TextBasedChannel.js b/src/structures/interface/TextBasedChannel.js index 0daf8600a..5e06cb543 100644 --- a/src/structures/interface/TextBasedChannel.js +++ b/src/structures/interface/TextBasedChannel.js @@ -11,13 +11,13 @@ class TextBasedChannel { constructor() { /** * A collection containing the messages sent to this channel. - * @type {Collection} + * @type {Collection} */ this.messages = new Collection(); /** * The ID of the last message in the channel, if one was sent. - * @type {?string} + * @type {?Snowflake} */ this.lastMessageID = null; } diff --git a/src/util/Snowflake.js b/src/util/Snowflake.js new file mode 100644 index 000000000..ad8259977 --- /dev/null +++ b/src/util/Snowflake.js @@ -0,0 +1,62 @@ +const Long = require('long'); + +// Discord epoch (2015-01-01T00:00:00.000Z) +const EPOCH = 1420070400000; +let INCREMENT = 0; + +function pad(v, n, c = '0') { + return String(v).length >= n ? String(v) : (String(c).repeat(n) + v).slice(-n); +} + + /** + * 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 + */ + + /** + * 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 + * ``` + * Note: this generator hardcodes the worker id as 1 and the process id as 0 + * @typedef {string} Snowflake + * @class Snowflake + */ +class Snowflake { + /** + * Generate a Discord snowflake + * @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(); + } + + /** + * Deconstruct 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, + }; + } +} + +module.exports = Snowflake; From fdc8050188dce1f113faa9195e34db8db49c9f07 Mon Sep 17 00:00:00 2001 From: HyperCoder Date: Thu, 5 Jan 2017 10:43:57 -0500 Subject: [PATCH 10/16] Fix .large (#1062) * Fix .large Would either be true or undefined. * Update Guild.js * To make hydrabolt happy * Update Guild.js --- src/structures/Guild.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/Guild.js b/src/structures/Guild.js index 8b5cb2d3c..faa5ce55a 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -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. From a66b2b7ec5d4612b393bc849cf200a77864b7a1e Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Thu, 5 Jan 2017 10:38:48 -0600 Subject: [PATCH 11/16] add more things to clientuser (#1066) * add more things to clientuser * add desc --- src/structures/ClientUser.js | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/structures/ClientUser.js b/src/structures/ClientUser.js index 22140bee8..5ff0057df 100644 --- a/src/structures/ClientUser.js +++ b/src/structures/ClientUser.js @@ -50,6 +50,27 @@ class ClientUser extends User { * @type {Object} */ this.settings = {}; + + /** + * If the user has discord premium (nitro) + * This is only filled when using a user account. + * @type {?boolean} + */ + this.premium = typeof data.premium === 'boolean' ? data.premium : null; + + /** + * If the user has MFA enabled on their account + * This is only filled when using a user account. + * @type {?boolean} + */ + this.mfaEnabled = typeof data.mfa_enabled === 'boolean' ? data.mfa_enabled : null; + + /** + * If the user has ever used a mobile device on discord + * This is only filled when using a user account. + * @type {?boolean} + */ + this.mobile = typeof data.mobile === 'boolean' ? data.mobile : null; } edit(data) { From 8cff77726a3740ae487a734f42caf7b8f02b88d6 Mon Sep 17 00:00:00 2001 From: Schuyler Cebulskie Date: Sat, 7 Jan 2017 03:22:55 -0500 Subject: [PATCH 12/16] Detardify snowflake docs/organisation --- src/util/Snowflake.js | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/util/Snowflake.js b/src/util/Snowflake.js index ad8259977..8a6d4be16 100644 --- a/src/util/Snowflake.js +++ b/src/util/Snowflake.js @@ -4,20 +4,10 @@ const Long = require('long'); const EPOCH = 1420070400000; let INCREMENT = 0; -function pad(v, n, c = '0') { - return String(v).length >= n ? String(v) : (String(c).repeat(n) + v).slice(-n); -} - - /** - * 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 - */ - +/** + * A container for useful snowflake-related methods + */ +class Snowflake { /** * A Twitter snowflake, except the epoch is 2015-01-01T00:00:00.000Z * ``` @@ -29,9 +19,8 @@ function pad(v, n, c = '0') { * ``` * Note: this generator hardcodes the worker id as 1 and the process id as 0 * @typedef {string} Snowflake - * @class Snowflake */ -class Snowflake { + /** * Generate a Discord snowflake * @returns {Snowflake} The generated snowflake @@ -42,6 +31,16 @@ class Snowflake { 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 + */ + /** * Deconstruct a Discord snowflake * @param {Snowflake} snowflake Snowflake to deconstruct @@ -59,4 +58,8 @@ class Snowflake { } } +function pad(v, n, c = '0') { + return String(v).length >= n ? String(v) : (String(c).repeat(n) + v).slice(-n); +} + module.exports = Snowflake; From add3c1a8ee979e678b6b4a2656ea4ada610bc724 Mon Sep 17 00:00:00 2001 From: Schuyler Cebulskie Date: Sat, 7 Jan 2017 03:29:52 -0500 Subject: [PATCH 13/16] Clean up docs slightly --- src/util/Snowflake.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/util/Snowflake.js b/src/util/Snowflake.js index 8a6d4be16..8cf9b97d8 100644 --- a/src/util/Snowflake.js +++ b/src/util/Snowflake.js @@ -17,12 +17,12 @@ class Snowflake { * 000000111011000111100001101001000101000000 00001 00000 000000000000 * number of ms since discord epoch worker pid increment * ``` - * Note: this generator hardcodes the worker id as 1 and the process id as 0 * @typedef {string} Snowflake */ /** - * Generate a Discord snowflake + * Generates a Discord snowflake + * This hardcodes the worker ID as 1 and the process ID as 0. * @returns {Snowflake} The generated snowflake */ static generate() { @@ -35,14 +35,14 @@ class Snowflake { * 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} 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 */ /** - * Deconstruct a Discord snowflake + * Deconstructs a Discord snowflake * @param {Snowflake} snowflake Snowflake to deconstruct * @returns {DeconstructedSnowflake} Deconstructed snowflake */ From f76b47184a128ba9526bbc60e3259d13738d20b5 Mon Sep 17 00:00:00 2001 From: Zack Campbell Date: Sat, 7 Jan 2017 02:31:15 -0600 Subject: [PATCH 14/16] Fix typo in MessageSearchOptions typedef (#1068) --- src/util/TransformSearchOptions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/util/TransformSearchOptions.js b/src/util/TransformSearchOptions.js index f3e1a6c76..a71ceb0fd 100644 --- a/src/util/TransformSearchOptions.js +++ b/src/util/TransformSearchOptions.js @@ -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) From e5e36d9111d75240e8aa696bec13c9aca564a8e4 Mon Sep 17 00:00:00 2001 From: Schuyler Cebulskie Date: Sat, 7 Jan 2017 03:37:14 -0500 Subject: [PATCH 15/16] Rename snowflake class to prevent naming conflicts --- src/index.js | 1 + src/util/Snowflake.js | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/index.js b/src/index.js index 07cfbf39b..d6cdffc97 100644 --- a/src/index.js +++ b/src/index.js @@ -10,6 +10,7 @@ module.exports = { escapeMarkdown: require('./util/EscapeMarkdown'), fetchRecommendedShards: require('./util/FetchRecommendedShards'), Snowflake: require('./util/Snowflake'), + SnowflakeUtil: require('./util/Snowflake'), Channel: require('./structures/Channel'), ClientOAuth2Application: require('./structures/ClientOAuth2Application'), diff --git a/src/util/Snowflake.js b/src/util/Snowflake.js index 8cf9b97d8..60d0926ac 100644 --- a/src/util/Snowflake.js +++ b/src/util/Snowflake.js @@ -7,7 +7,7 @@ let INCREMENT = 0; /** * A container for useful snowflake-related methods */ -class Snowflake { +class SnowflakeUtil { /** * A Twitter snowflake, except the epoch is 2015-01-01T00:00:00.000Z * ``` @@ -62,4 +62,4 @@ function pad(v, n, c = '0') { return String(v).length >= n ? String(v) : (String(c).repeat(n) + v).slice(-n); } -module.exports = Snowflake; +module.exports = SnowflakeUtil; From 42527ea969f17cc2c42b99a3c24fe95ad60c6c15 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sat, 7 Jan 2017 02:38:23 -0600 Subject: [PATCH 16/16] fix message#isMemberMentioned (#1061) * fix this * e * Update Message.js --- src/structures/Message.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/structures/Message.js b/src/structures/Message.js index 7d6708f10..138169389 100644 --- a/src/structures/Message.js +++ b/src/structures/Message.js @@ -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 @@ -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; }