diff --git a/src/client/Client.js b/src/client/Client.js index 4ac6da82c614..6db0b6ed2579 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] Whether any additional scopes should be requested */ /** @@ -418,6 +419,18 @@ 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 4e9d73cacbd2..331c6a040cf4 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.', diff --git a/src/util/Constants.js b/src/util/Constants.js index 308e45ab94e4..ac2046b3d10c 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -375,6 +375,36 @@ 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 + * * `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 + * * `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 diff --git a/typings/index.d.ts b/typings/index.d.ts index 9cf19cce4c66..f6c8878a58bd 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[]; @@ -2824,6 +2825,7 @@ declare module 'discord.js' { permissions?: PermissionResolvable; guild?: GuildResolvable; disableGuildSelect?: boolean; + additionalScopes?: InviteScope[]; } interface InviteOptions { @@ -2836,6 +2838,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';