diff --git a/src/client/Client.js b/src/client/Client.js index c25671374..b63f5a515 100644 --- a/src/client/Client.js +++ b/src/client/Client.js @@ -17,6 +17,7 @@ const Webhook = require('../structures/Webhook'); const Collection = require('../util/Collection'); const { Events, browser, DefaultOptions } = require('../util/Constants'); const DataResolver = require('../util/DataResolver'); +const Intents = require('../util/Intents'); const Permissions = require('../util/Permissions'); const Structures = require('../util/Structures'); @@ -381,6 +382,9 @@ class Client extends BaseClient { * @private */ _validateOptions(options = this.options) { + if (typeof options.ws.intents !== 'undefined') { + options.ws.intents = Intents.resolve(options.ws.intents); + } if (typeof options.shardCount !== 'number' || isNaN(options.shardCount) || options.shardCount < 1) { throw new TypeError('CLIENT_INVALID_OPTION', 'shardCount', 'a number greater than or equal to 1'); } @@ -415,9 +419,6 @@ class Client extends BaseClient { if (typeof options.restSweepInterval !== 'number' || isNaN(options.restSweepInterval)) { throw new TypeError('CLIENT_INVALID_OPTION', 'restSweepInterval', 'a number'); } - if (!Array.isArray(options.disabledEvents)) { - throw new TypeError('CLIENT_INVALID_OPTION', 'disabledEvents', 'an Array'); - } if (typeof options.retryLimit !== 'number' || isNaN(options.retryLimit)) { throw new TypeError('CLIENT_INVALID_OPTION', 'retryLimit', 'a number'); } diff --git a/src/client/websocket/WebSocketManager.js b/src/client/websocket/WebSocketManager.js index 905626b65..180110637 100644 --- a/src/client/websocket/WebSocketManager.js +++ b/src/client/websocket/WebSocketManager.js @@ -382,7 +382,7 @@ class WebSocketManager extends EventEmitter { }); } - if (packet && !this.client.options.disabledEvents.includes(packet.t) && PacketHandlers[packet.t]) { + if (packet && PacketHandlers[packet.t]) { PacketHandlers[packet.t](this.client, packet, shard); } diff --git a/src/index.js b/src/index.js index 155d2f539..c448943a5 100644 --- a/src/index.js +++ b/src/index.js @@ -22,6 +22,7 @@ module.exports = { DiscordAPIError: require('./rest/DiscordAPIError'), HTTPError: require('./rest/HTTPError'), MessageFlags: require('./util/MessageFlags'), + Intents: require('./util/Intents'), Permissions: require('./util/Permissions'), Speaking: require('./util/Speaking'), Snowflake: require('./util/Snowflake'), diff --git a/src/util/Constants.js b/src/util/Constants.js index bc0ccc6b7..74365789d 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -35,10 +35,6 @@ const browser = (exports.browser = typeof window !== 'undefined'); * (or 0 for never) * @property {number} [retryLimit=1] How many times to retry on 5XX errors (Infinity for indefinite amount of retries) * @property {PresenceData} [presence] Presence data to use upon login - * @property {WSEventType[]} [disabledEvents] An array of disabled websocket events. Events in this array will not be - * processed, potentially resulting in performance improvements for larger bots. Only disable events you are - * 100% certain you don't need, as many are important, but not obviously so. The safest one to disable with the - * most impact is typically `TYPING_START`. * @property {WebsocketOptions} [ws] Options for the WebSocket * @property {HTTPOptions} [http] HTTP options */ @@ -51,7 +47,6 @@ exports.DefaultOptions = { disableMentions: 'none', partials: [], restWsBridgeTimeout: 5000, - disabledEvents: [], restRequestTimeout: 15000, retryLimit: 1, restTimeOffset: 500, @@ -62,6 +57,7 @@ exports.DefaultOptions = { * WebSocket options (these are left as snake_case to match the API) * @typedef {Object} WebsocketOptions * @property {number} [large_threshold=250] Number of members in a guild to be considered large + * @property {IntentsResolvable} [intents] Intents to enable for this connection */ ws: { large_threshold: 250, diff --git a/src/util/Intents.js b/src/util/Intents.js new file mode 100644 index 000000000..06ef470b9 --- /dev/null +++ b/src/util/Intents.js @@ -0,0 +1,76 @@ +'use strict'; +const BitField = require('./BitField'); + +/** + * Data structure that makes it easy to calculate intents. + * @extends {BitField} + */ +class Intents extends BitField {} + +/** + * Data that can be resolved to give a permission number. This can be: + * * A string (see {@link Intents.FLAGS}) + * * An intents flag + * * An instance of Intents + * * An array of IntentsResolvable + * @typedef {string|number|Intents|IntentsResolvable[]} IntentsResolvable + */ + +/** + * Numeric websocket intents. All available properties: + * * `GUILDS` + * * `GUILD_MEMBERS` + * * `GUILD_BANS` + * * `GUILD_EMOJIS` + * * `GUILD_INTEGRATIONS` + * * `GUILD_WEBHOOKS` + * * `GUILD_INVITES` + * * `GUILD_VOICE_STATES` + * * `GUILD_PRESENCES` + * * `GUILD_MESSAGES` + * * `GUILD_MESSAGE_REACTIONS` + * * `GUILD_MESSAGE_TYPING` + * * `DIRECT_MESSAGES` + * * `DIRECT_MESSAGE_REACTIONS` + * * `DIRECT_MESSAGE_TYPING` + * @type {Object} + * @see {@link https://discordapp.com/developers/docs/topics/gateway#list-of-intents} + */ +Intents.FLAGS = { + GUILDS: 1 << 0, + GUILD_MEMBERS: 1 << 1, + GUILD_BANS: 1 << 2, + GUILD_EMOJIS: 1 << 3, + GUILD_INTEGRATIONS: 1 << 4, + GUILD_WEBHOOKS: 1 << 5, + GUILD_INVITES: 1 << 6, + GUILD_VOICE_STATES: 1 << 7, + GUILD_PRESENCES: 1 << 8, + GUILD_MESSAGES: 1 << 9, + GUILD_MESSAGE_REACTIONS: 1 << 10, + GUILD_MESSAGE_TYPING: 1 << 11, + DIRECT_MESSAGES: 1 << 12, + DIRECT_MESSAGE_REACTIONS: 1 << 13, + DIRECT_MESSAGE_TYPING: 1 << 14, +}; + +/** + * Bitfield representing all privileged intents + * @type {number} + * @see {@link https://discordapp.com/developers/docs/topics/gateway#privileged-intents} + */ +Intents.PRIVILEGED = Intents.FLAGS.GUILD_MEMBERS | Intents.FLAGS.GUILD_PRESENCES; + +/** + * Bitfield representing all intents combined + * @type {number} + */ +Intents.ALL = Object.values(Intents.FLAGS).reduce((acc, p) => acc | p, 0); + +/** + * Bitfield representing all non-privileged intents + * @type {number} + */ +Intents.NON_PRIVILEGED = Intents.ALL & ~Intents.PRIVILEGED; + +module.exports = Intents; diff --git a/typings/index.d.ts b/typings/index.d.ts index 70589cafa..bbbaad8fb 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -2298,7 +2298,6 @@ declare module 'discord.js' { restSweepInterval?: number; retryLimit?: number; presence?: PresenceData; - disabledEvents?: WSEventType[]; ws?: WebSocketOptions; http?: HTTPOptions; } @@ -2631,6 +2630,23 @@ declare module 'discord.js' { name: string; } + type IntentsString = + | 'GUILDS' + | 'GUILD_MEMBERS' + | 'GUILD_BANS' + | 'GUILD_EMOJIS' + | 'GUILD_INTEGRATIONS' + | 'GUILD_WEBHOOKS' + | 'GUILD_INVITES' + | 'GUILD_VOICE_STATES' + | 'GUILD_PRESENCES' + | 'GUILD_MESSAGES' + | 'GUILD_MESSAGE_REACTIONS' + | 'GUILD_MESSAGE_TYPING' + | 'DIRECT_MESSAGES' + | 'DIRECT_MESSAGE_REACTIONS' + | 'DIRECT_MESSAGE_TYPING'; + interface InviteOptions { temporary?: boolean; maxAge?: number; @@ -2986,6 +3002,7 @@ declare module 'discord.js' { interface WebSocketOptions { large_threshold?: number; compress?: boolean; + intents?: Intents | number; } type WSEventType =