From 2ba876310106a73c0b5565c96c972d971a416607 Mon Sep 17 00:00:00 2001 From: ckohen Date: Thu, 14 Jan 2021 15:19:40 -0800 Subject: [PATCH 1/9] feat(Client): add options.additionalScopes for invite generation --- src/client/Client.js | 14 +++++++++++++- src/util/Constants.js | 28 ++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/src/client/Client.js b/src/client/Client.js index 79a1f44cc4f6..d90814876b5e 100644 --- a/src/client/Client.js +++ b/src/client/Client.js @@ -17,7 +17,7 @@ const Invite = require('../structures/Invite'); const VoiceRegion = require('../structures/VoiceRegion'); const Webhook = require('../structures/Webhook'); const Collection = require('../util/Collection'); -const { Events, DefaultOptions } = require('../util/Constants'); +const { Events, DefaultOptions, InviteScopes } = require('../util/Constants'); const DataResolver = require('../util/DataResolver'); const Intents = require('../util/Intents'); const Permissions = require('../util/Permissions'); @@ -377,6 +377,7 @@ class Client extends BaseClient { * @property {PermissionResolvable} [permissions] Permissions to request * @property {GuildResolvable} [guild] Guild to preselect * @property {boolean} [disableGuildSelect] Whether to disable the guild selection + * @property {InviteScope[]} additionalScopes */ /** @@ -414,6 +415,17 @@ class Client extends BaseClient { query.set('guild_id', guildID); } + if (options.additionalScopes) { + const scopes = options.additionalScopes; + scopes.forEach(scope => { + if (!InviteScopes.includes(scope)) { + throw new TypeError('INVALID_TYPE', 'additionalScopes', 'Array of Invite Scopes', true); + } + }); + scopes.unshift('bot'); + query.set('scope', scopes.join('+')); + } + return `${this.options.http.api}${this.api.oauth2.authorize}?${query}`; } diff --git a/src/util/Constants.js b/src/util/Constants.js index 298bbc196ca1..ddc51b039d31 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -378,6 +378,34 @@ exports.WSEvents = keyMirror([ 'WEBHOOKS_UPDATE', ]); +/** + * A valid scope to request when generating an invite link. + * Scopes that require whitelist are not considered valid for this generator + * * `applications.builds.read`: allows reading build data for a users applications + * * `applications.commands`: allows this bot to create commands in the server + * * `connections`: makes the endpoint for getting a users connections available + * * `email`: allows the `/users/@me` endpoint return with an email + * * `identify`: allows the `/users/@me` endpoint without an email + * * `guilds`: makes the `/users/@me/guilds` endpoint available for a user + * * `guilds.join`: allows the bot to join the user to any guild it is in using Guild#addMember + * * `gdm.join`: allows joining the user to a group dm + * * `webhook.incoming`: generates a webhook to a channel + * @typedef {string} InviteScope + */ +exports.InviteScopes = [ + 'applications.builds.read', + 'applications.commands', + 'applications.entitlements', + 'applications.store.update', + 'connections', + 'email', + 'identity', + 'guilds', + 'guilds.join', + 'gdm.join', + 'webhook.incoming', +]; + /** * The type of a message, e.g. `DEFAULT`. Here are the available types: * * DEFAULT From 43bfb1fc75a3471804a99ee0a6d3bb8c3e073eab Mon Sep 17 00:00:00 2001 From: ckohen Date: Thu, 14 Jan 2021 15:23:19 -0800 Subject: [PATCH 2/9] docs(Client): add docstring for additionalScopes property --- src/client/Client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/Client.js b/src/client/Client.js index d90814876b5e..175d6686222f 100644 --- a/src/client/Client.js +++ b/src/client/Client.js @@ -377,7 +377,7 @@ class Client extends BaseClient { * @property {PermissionResolvable} [permissions] Permissions to request * @property {GuildResolvable} [guild] Guild to preselect * @property {boolean} [disableGuildSelect] Whether to disable the guild selection - * @property {InviteScope[]} additionalScopes + * @property {InviteScope[]} [additionalScopes] Whether any additional scopes should be requested */ /** From 9ce30c2b9ff40b24435beaba41700b664fa7c345 Mon Sep 17 00:00:00 2001 From: ckohen Date: Thu, 14 Jan 2021 15:27:37 -0800 Subject: [PATCH 3/9] fix(Client): use space instead of plus for scope joining --- src/client/Client.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/Client.js b/src/client/Client.js index 175d6686222f..e075239f3dd9 100644 --- a/src/client/Client.js +++ b/src/client/Client.js @@ -423,7 +423,7 @@ class Client extends BaseClient { } }); scopes.unshift('bot'); - query.set('scope', scopes.join('+')); + query.set('scope', scopes.join(' ')); } return `${this.options.http.api}${this.api.oauth2.authorize}?${query}`; From 4d424fb73a5fd335802e6dd7afe39d13c39a63dd Mon Sep 17 00:00:00 2001 From: ckohen Date: Thu, 14 Jan 2021 15:40:03 -0800 Subject: [PATCH 4/9] feat(Client): update typings --- typings/index.d.ts | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/typings/index.d.ts b/typings/index.d.ts index e4e2027e4357..88f1770ef23b 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -513,6 +513,7 @@ declare module 'discord.js' { SMALL: 1; BIG: 2; }; + InviteScopes: InviteScope[]; MessageTypes: MessageType[]; SystemMessageTypes: SystemMessageType[]; ActivityTypes: ActivityType[]; @@ -2729,6 +2730,7 @@ declare module 'discord.js' { permissions?: PermissionResolvable; guild?: GuildResolvable; disableGuildSelect?: boolean; + additionalScopes?: InviteScope[]; } interface InviteOptions { @@ -2741,6 +2743,19 @@ declare module 'discord.js' { type InviteResolvable = string; + type InviteScope = + | 'applications.builds.read' + | 'applications.commands' + | 'applications.entitlements' + | 'applications.store.update' + | 'connections' + | 'email' + | 'identity' + | 'guilds' + | 'guilds.join' + | 'gdm.join' + | 'webhook.incoming'; + type GuildTemplateResolvable = string; type MembershipStates = 'INVITED' | 'ACCEPTED'; From 95774d7f814f12b7e5c8bdbcb768a40a777dd8aa Mon Sep 17 00:00:00 2001 From: ckohen Date: Thu, 14 Jan 2021 21:40:09 -0800 Subject: [PATCH 5/9] fix(Client): use array.some() --- src/client/Client.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/client/Client.js b/src/client/Client.js index e075239f3dd9..821e33f6d6bb 100644 --- a/src/client/Client.js +++ b/src/client/Client.js @@ -417,11 +417,9 @@ class Client extends BaseClient { if (options.additionalScopes) { const scopes = options.additionalScopes; - scopes.forEach(scope => { - if (!InviteScopes.includes(scope)) { - throw new TypeError('INVALID_TYPE', 'additionalScopes', 'Array of Invite Scopes', true); - } - }); + if (scopes.some(scope => !InviteScopes.includes(scope))) { + throw new TypeError('INVALID_TYPE', 'additionalScopes', 'Array of Invite Scopes', true); + } scopes.unshift('bot'); query.set('scope', scopes.join(' ')); } From dc110d08e617c9ef8ad16ea7ced048a743a590b9 Mon Sep 17 00:00:00 2001 From: ckohen Date: Fri, 15 Jan 2021 12:34:08 -0800 Subject: [PATCH 6/9] fix(Client): better handling of Array Co-authored-by: izexi <43889168+izexi@users.noreply.github.com> --- src/client/Client.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/client/Client.js b/src/client/Client.js index 821e33f6d6bb..7f9f7055e502 100644 --- a/src/client/Client.js +++ b/src/client/Client.js @@ -417,11 +417,10 @@ class Client extends BaseClient { if (options.additionalScopes) { const scopes = options.additionalScopes; - if (scopes.some(scope => !InviteScopes.includes(scope))) { + if (!Array.isArray(scopes) || scopes.some(scope => !InviteScopes.includes(scope))) { throw new TypeError('INVALID_TYPE', 'additionalScopes', 'Array of Invite Scopes', true); } - scopes.unshift('bot'); - query.set('scope', scopes.join(' ')); + query.set('scope', ['bot', ...scopes].join(' ')); } return `${this.options.http.api}${this.api.oauth2.authorize}?${query}`; From c17c83d13ff3d520f6e1463e4cd637d0b086d79d Mon Sep 17 00:00:00 2001 From: ckohen Date: Sat, 6 Feb 2021 00:16:25 -0800 Subject: [PATCH 7/9] fix: add missing jsdoc strings --- src/util/Constants.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/util/Constants.js b/src/util/Constants.js index ddc51b039d31..8227a823fb30 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -383,6 +383,8 @@ exports.WSEvents = keyMirror([ * Scopes that require whitelist are not considered valid for this generator * * `applications.builds.read`: allows reading build data for a users applications * * `applications.commands`: allows this bot to create commands in the server + * * `applications.entitlements`: allows reading entitlements for a users applications + * * `applications.store.update`: allows reading and updating of store data for a users applications * * `connections`: makes the endpoint for getting a users connections available * * `email`: allows the `/users/@me` endpoint return with an email * * `identify`: allows the `/users/@me` endpoint without an email From 65fe64c671d2c863ffbd0052991c77ba4dcb0bc2 Mon Sep 17 00:00:00 2001 From: ckohen Date: Sat, 6 Feb 2021 00:16:59 -0800 Subject: [PATCH 8/9] feat(Errors): add error type INVALID_ELEMENT --- src/client/Client.js | 5 ++++- src/errors/Messages.js | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/client/Client.js b/src/client/Client.js index 7f9f7055e502..0656a20d764e 100644 --- a/src/client/Client.js +++ b/src/client/Client.js @@ -417,8 +417,11 @@ class Client extends BaseClient { if (options.additionalScopes) { const scopes = options.additionalScopes; - if (!Array.isArray(scopes) || scopes.some(scope => !InviteScopes.includes(scope))) { + if (!Array.isArray(scopes)) { throw new TypeError('INVALID_TYPE', 'additionalScopes', 'Array of Invite Scopes', true); + } else if (scopes.some(scope => !InviteScopes.includes(scope))) { + const invalidScope = scopes.find(scope => !InviteScopes.includes(scope)); + throw new TypeError('INVALID_ELEMENT', 'Array', 'additionalScopes', invalidScope); } query.set('scope', ['bot', ...scopes].join(' ')); } diff --git a/src/errors/Messages.js b/src/errors/Messages.js index 980bf0975f27..96739e4aa191 100644 --- a/src/errors/Messages.js +++ b/src/errors/Messages.js @@ -89,6 +89,7 @@ const Messages = { GUILD_UNCACHED_ME: 'The client user as a member of this guild is uncached.', INVALID_TYPE: (name, expected, an = false) => `Supplied ${name} is not a${an ? 'n' : ''} ${expected}.`, + INVALID_ELEMENT: (type, name, elem) => `Supplied ${type} ${name} includes an invalid element: ${elem}`, WEBHOOK_MESSAGE: 'The message was not sent by a webhook.', From a9a48771b8c9109d1a29bba10f14bb1a7d30b89d Mon Sep 17 00:00:00 2001 From: ckohen Date: Sat, 6 Feb 2021 00:33:03 -0800 Subject: [PATCH 9/9] fix: don't double iterate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Antonio Román --- src/client/Client.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/client/Client.js b/src/client/Client.js index 0656a20d764e..d3ddff2ab60d 100644 --- a/src/client/Client.js +++ b/src/client/Client.js @@ -419,8 +419,9 @@ class Client extends BaseClient { const scopes = options.additionalScopes; if (!Array.isArray(scopes)) { throw new TypeError('INVALID_TYPE', 'additionalScopes', 'Array of Invite Scopes', true); - } else if (scopes.some(scope => !InviteScopes.includes(scope))) { - const invalidScope = scopes.find(scope => !InviteScopes.includes(scope)); + } + const invalidScope = scopes.find(scope => !InviteScopes.includes(scope)); + if (invalidScope) { throw new TypeError('INVALID_ELEMENT', 'Array', 'additionalScopes', invalidScope); } query.set('scope', ['bot', ...scopes].join(' '));