From c6e55216874f1892727db927f55db3de6a1712d8 Mon Sep 17 00:00:00 2001 From: monbrey Date: Mon, 5 Jul 2021 07:53:57 +1000 Subject: [PATCH] feat(Client): enforce passing scopes to generateInvite (#6024) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Antonio Román Co-authored-by: SpaceEEC --- src/client/Client.js | 37 +++++++++++++++++++++++-------------- src/errors/Messages.js | 2 ++ src/util/Constants.js | 1 + typings/index.d.ts | 2 +- 4 files changed, 27 insertions(+), 15 deletions(-) diff --git a/src/client/Client.js b/src/client/Client.js index b93efd3befd1..8e58c400b967 100644 --- a/src/client/Client.js +++ b/src/client/Client.js @@ -375,10 +375,10 @@ class Client extends BaseClient { /** * Options for {@link Client#generateInvite}. * @typedef {Object} InviteGenerationOptions + * @property {InviteScope[]} scopes Scopes that should be requested * @property {PermissionResolvable} [permissions] Permissions to request * @property {GuildResolvable} [guild] Guild to preselect * @property {boolean} [disableGuildSelect] Whether to disable the guild selection - * @property {InviteScope[]} [additionalScopes] Whether any additional scopes should be requested */ /** @@ -387,11 +387,17 @@ class Client extends BaseClient { * @returns {string} * @example * const link = client.generateInvite({ + * scopes: ['applications.commands'], + * }); + * console.log(`Generated application invite link: ${link}`); + * @example + * const link = client.generateInvite({ * permissions: [ * Permissions.FLAGS.SEND_MESSAGES, * Permissions.FLAGS.MANAGE_GUILD, * Permissions.FLAGS.MENTION_EVERYONE, * ], + * scopes: ['bot'], * }); * console.log(`Generated bot invite link: ${link}`); */ @@ -401,9 +407,24 @@ class Client extends BaseClient { const query = new URLSearchParams({ client_id: this.application.id, - scope: 'bot', }); + const { scopes } = options; + if (typeof scopes === 'undefined') { + throw new TypeError('INVITE_MISSING_SCOPES'); + } + if (!Array.isArray(scopes)) { + throw new TypeError('INVALID_TYPE', 'scopes', 'Array of Invite Scopes', true); + } + if (!scopes.some(scope => ['bot', 'applications.commands'].includes(scope))) { + throw new TypeError('INVITE_MISSING_SCOPES'); + } + const invalidScope = scopes.find(scope => !InviteScopes.includes(scope)); + if (invalidScope) { + throw new TypeError('INVALID_ELEMENT', 'Array', 'scopes', invalidScope); + } + query.set('scope', scopes.join(' ')); + if (options.permissions) { const permissions = Permissions.resolve(options.permissions); if (permissions) query.set('permissions', permissions); @@ -419,18 +440,6 @@ class Client extends BaseClient { query.set('guild_id', guildId); } - if (options.additionalScopes) { - const scopes = options.additionalScopes; - if (!Array.isArray(scopes)) { - throw new TypeError('INVALID_TYPE', 'additionalScopes', 'Array of Invite Scopes', true); - } - const invalidScope = scopes.find(scope => !InviteScopes.includes(scope)); - if (invalidScope) { - throw new TypeError('INVALID_ELEMENT', 'Array', 'additionalScopes', invalidScope); - } - query.set('scope', ['bot', ...scopes].join(' ')); - } - return `${this.options.http.api}${this.api.oauth2.authorize}?${query}`; } diff --git a/src/errors/Messages.js b/src/errors/Messages.js index 8d97ec7aa497..4a10d187758f 100644 --- a/src/errors/Messages.js +++ b/src/errors/Messages.js @@ -132,6 +132,8 @@ const Messages = { INTERACTION_EPHEMERAL_REPLIED: 'Ephemeral responses cannot be fetched or deleted.', INTERACTION_FETCH_EPHEMERAL: 'Ephemeral responses cannot be fetched.', + INVITE_MISSING_SCOPES: 'At least one valid scope must be provided for the invite', + NOT_IMPLEMENTED: (what, name) => `Method ${what} not implemented on ${name}.`, }; diff --git a/src/util/Constants.js b/src/util/Constants.js index 73537a4aceb8..0a8990bd96b2 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -328,6 +328,7 @@ exports.InviteScopes = [ 'applications.commands', 'applications.entitlements', 'applications.store.update', + 'bot', 'connections', 'email', 'identity', diff --git a/typings/index.d.ts b/typings/index.d.ts index 8c4cbc539d89..73ca2a1b7d86 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -3696,7 +3696,7 @@ declare module 'discord.js' { permissions?: PermissionResolvable; guild?: GuildResolvable; disableGuildSelect?: boolean; - additionalScopes?: InviteScope[]; + scopes: InviteScope[]; } interface CreateInviteOptions {