diff --git a/src/client/Client.js b/src/client/Client.js index 6db0b6ed2..f38a0c0fb 100644 --- a/src/client/Client.js +++ b/src/client/Client.js @@ -29,9 +29,9 @@ const Structures = require('../util/Structures'); */ class Client extends BaseClient { /** - * @param {ClientOptions} [options] Options for the client + * @param {ClientOptions} options Options for the client */ - constructor(options = {}) { + constructor(options) { super(Object.assign({ _tokenType: 'Bot' }, options)); // Obtain shard details from environment or if present, worker threads @@ -457,8 +457,10 @@ 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.intents === 'undefined') { + throw new TypeError('CLIENT_MISSING_INTENTS'); + } else { + options.intents = Intents.resolve(options.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'); diff --git a/src/client/actions/ChannelCreate.js b/src/client/actions/ChannelCreate.js index fa60a0b39..d1660aa76 100644 --- a/src/client/actions/ChannelCreate.js +++ b/src/client/actions/ChannelCreate.js @@ -10,9 +10,9 @@ class ChannelCreateAction extends Action { const channel = client.channels.add(data); if (!existing && channel) { /** - * Emitted whenever a channel is created. + * Emitted whenever a guild channel is created. * @event Client#channelCreate - * @param {DMChannel|GuildChannel} channel The channel that was created + * @param {GuildChannel} channel The channel that was created */ client.emit(Events.CHANNEL_CREATE, channel); } diff --git a/src/client/actions/MessageCreate.js b/src/client/actions/MessageCreate.js index 713870750..ae1741598 100644 --- a/src/client/actions/MessageCreate.js +++ b/src/client/actions/MessageCreate.js @@ -6,7 +6,7 @@ const { Events } = require('../../util/Constants'); class MessageCreateAction extends Action { handle(data) { const client = this.client; - const channel = client.channels.cache.get(data.channel_id); + const channel = this.getChannel(data); if (channel) { const existing = channel.messages.cache.get(data.id); if (existing) return { message: existing }; diff --git a/src/client/actions/PresenceUpdate.js b/src/client/actions/PresenceUpdate.js index f74fbeb5d..69b79eb78 100644 --- a/src/client/actions/PresenceUpdate.js +++ b/src/client/actions/PresenceUpdate.js @@ -22,7 +22,6 @@ class PresenceUpdateAction extends Action { if (!member && data.status !== 'offline') { member = guild.members.add({ user, - roles: data.roles, deaf: false, mute: false, }); diff --git a/src/client/websocket/WebSocketShard.js b/src/client/websocket/WebSocketShard.js index aff151bcf..4fe904e1a 100644 --- a/src/client/websocket/WebSocketShard.js +++ b/src/client/websocket/WebSocketShard.js @@ -3,6 +3,7 @@ const EventEmitter = require('events'); const WebSocket = require('../../WebSocket'); const { Status, Events, ShardEvents, OPCodes, WSEvents } = require('../../util/Constants'); +const Intents = require('../../util/Intents'); const STATUS_KEYS = Object.keys(Status); const CONNECTION_STATE = Object.keys(WebSocket.WebSocket); @@ -594,6 +595,7 @@ class WebSocketShard extends EventEmitter { // Clone the identify payload and assign the token and shard info const d = { ...client.options.ws, + intents: Intents.resolve(client.options.intents), token: client.token, shard: [this.id, Number(client.options.shardCount)], }; diff --git a/src/errors/Messages.js b/src/errors/Messages.js index 331c6a040..e1b53de33 100644 --- a/src/errors/Messages.js +++ b/src/errors/Messages.js @@ -5,6 +5,7 @@ const { register } = require('./DJSError'); const Messages = { CLIENT_INVALID_OPTION: (prop, must) => `The ${prop} option must be ${must}`, CLIENT_INVALID_PROVIDED_SHARDS: 'None of the provided shards were valid.', + CLIENT_MISSING_INTENTS: 'Valid intents must be provided for the Client.', TOKEN_INVALID: 'An invalid token was provided.', TOKEN_MISSING: 'Request to use token, but token was unavailable to the client.', diff --git a/src/managers/GuildManager.js b/src/managers/GuildManager.js index b04a52c12..d5a92b4bf 100644 --- a/src/managers/GuildManager.js +++ b/src/managers/GuildManager.js @@ -53,7 +53,7 @@ class GuildManager extends BaseManager { * @property {ColorResolvable} [color] The color of the role, either a hex string or a base 10 number * @property {boolean} [hoist] Whether or not the role should be hoisted * @property {number} [position] The position of the role - * @property {PermissionResolvable|number} [permissions] The permissions of the role + * @property {PermissionResolvable} [permissions] The permissions of the role * @property {boolean} [mentionable] Whether or not the role should be mentionable */ diff --git a/src/managers/RoleManager.js b/src/managers/RoleManager.js index 667085b6b..04aa47d00 100644 --- a/src/managers/RoleManager.js +++ b/src/managers/RoleManager.js @@ -115,7 +115,7 @@ class RoleManager extends BaseManager { create(options = {}) { let { name, color, hoist, permissions, position, mentionable, reason } = options; if (color) color = resolveColor(color); - if (permissions) permissions = Permissions.resolve(permissions); + if (permissions) permissions = Permissions.resolve(permissions).toString(); return this.client.api .guilds(this.guild.id) diff --git a/src/rest/RequestHandler.js b/src/rest/RequestHandler.js index 100035a4b..245a285cd 100644 --- a/src/rest/RequestHandler.js +++ b/src/rest/RequestHandler.js @@ -105,7 +105,7 @@ class RequestHandler { this.limit = limit ? Number(limit) : Infinity; this.remaining = remaining ? Number(remaining) : 1; this.reset = reset ? calculateReset(reset, serverDate) : Date.now(); - this.retryAfter = retryAfter ? Number(retryAfter) : -1; + this.retryAfter = retryAfter ? Number(retryAfter) * 1000 : -1; // https://github.com/discordapp/discord-api-docs/issues/182 if (request.route.includes('reactions')) { diff --git a/src/structures/ClientPresence.js b/src/structures/ClientPresence.js index 6c0955627..f32577b47 100644 --- a/src/structures/ClientPresence.js +++ b/src/structures/ClientPresence.js @@ -2,7 +2,6 @@ const { Presence } = require('./Presence'); const { TypeError } = require('../errors'); -const Collection = require('../util/Collection'); const { ActivityTypes, OPCodes } = require('../util/Constants'); class ClientPresence extends Presence { @@ -14,8 +13,8 @@ class ClientPresence extends Presence { super(client, Object.assign(data, { status: data.status || 'online', user: { id: null } })); } - async set(presence) { - const packet = await this._parse(presence); + set(presence) { + const packet = this._parse(presence); this.patch(packet); if (typeof presence.shardID === 'undefined') { this.client.ws.broadcast({ op: OPCodes.STATUS_UPDATE, d: packet }); @@ -29,58 +28,33 @@ class ClientPresence extends Presence { return this; } - async _parse({ status, since, afk, activity }) { - const applicationID = activity && (activity.application ? activity.application.id || activity.application : null); - let assets = new Collection(); - if (activity) { - if (typeof activity.name !== 'string') throw new TypeError('INVALID_TYPE', 'name', 'string'); - if (!activity.type) activity.type = 0; - if (activity.assets && applicationID) { - try { - const a = await this.client.api.oauth2.applications(applicationID).assets.get(); - for (const asset of a) assets.set(asset.name, asset.id); - } catch {} // eslint-disable-line no-empty - } - } - - const packet = { - afk: afk != null ? afk : false, // eslint-disable-line eqeqeq - since: since != null ? since : null, // eslint-disable-line eqeqeq + _parse({ status, since, afk, activities }) { + const data = { + activities: [], + afk: typeof afk === 'boolean' ? afk : false, + since: typeof since === 'number' && !Number.isNaN(since) ? since : null, status: status || this.status, - game: activity - ? { - type: activity.type, - name: activity.name, - url: activity.url, - details: activity.details || undefined, - state: activity.state || undefined, - assets: activity.assets - ? { - large_text: activity.assets.largeText || undefined, - small_text: activity.assets.smallText || undefined, - large_image: assets.get(activity.assets.largeImage) || activity.assets.largeImage, - small_image: assets.get(activity.assets.smallImage) || activity.assets.smallImage, - } - : undefined, - timestamps: activity.timestamps || undefined, - party: activity.party || undefined, - application_id: applicationID || undefined, - secrets: activity.secrets || undefined, - instance: activity.instance || undefined, - } - : null, }; + if (activities === null) { + data.activities = null; + return data; + } + if (activities && activities.length) { + for (const [i, activity] of activities.entries()) { + if (typeof activity.name !== 'string') throw new TypeError('INVALID_TYPE', `activities[${i}].name`, 'string'); + if (!activity.type) activity.type = 0; - if ((status || afk || since) && !activity) { - packet.game = this.activities[0] || null; + data.activities.push({ + type: typeof activity.type === 'number' ? activity.type : ActivityTypes.indexOf(activity.type), + name: activity.name, + url: activity.url, + }); + } + } else if ((status || afk || since) && this.activities.length) { + data.activities.push(...this.activities); } - if (packet.game) { - packet.game.type = - typeof packet.game.type === 'number' ? packet.game.type : ActivityTypes.indexOf(packet.game.type); - } - - return packet; + return data; } } diff --git a/src/structures/ClientUser.js b/src/structures/ClientUser.js index 65112b8cc..33b4be56d 100644 --- a/src/structures/ClientUser.js +++ b/src/structures/ClientUser.js @@ -46,16 +46,18 @@ class ClientUser extends Structures.get('User') { return this.client.presence; } - edit(data) { - return this.client.api - .users('@me') - .patch({ data }) - .then(newData => { - this.client.token = newData.token; - const { updated } = this.client.actions.UserUpdate.handle(newData); - if (updated) return updated; - return this; - }); + /** + * Edits the logged in client. + * @param {Object} data The new data + * @param {string} [data.username] The new username + * @param {BufferResolvable|Base64Resolvable} [data.avatar] The new avatar + */ + async edit(data) { + const newData = await this.client.api.users('@me').patch({ data }); + this.client.token = newData.token; + const { updated } = this.client.actions.UserUpdate.handle(newData); + if (updated) return updated; + return this; } /** @@ -103,7 +105,7 @@ class ClientUser extends Structures.get('User') { /** * Sets the full presence of the client user. * @param {PresenceData} data Data for the presence - * @returns {Promise} + * @returns {Presence} * @example * // Set the client user's presence * client.user.setPresence({ activity: { name: 'with discord.js' }, status: 'idle' }) @@ -127,7 +129,7 @@ class ClientUser extends Structures.get('User') { * Sets the status of the client user. * @param {PresenceStatusData} status Status to change to * @param {?number|number[]} [shardID] Shard ID(s) to have the activity set on - * @returns {Promise} + * @returns {Presence} * @example * // Set the client user's status * client.user.setStatus('idle') @@ -144,14 +146,14 @@ class ClientUser extends Structures.get('User') { * @type {Object} * @property {string} [url] Twitch / YouTube stream URL * @property {ActivityType|number} [type] Type of the activity - * @property {?number|number[]} [shardID] Shard Id(s) to have the activity set on + * @property {number|number[]} [shardID] Shard Id(s) to have the activity set on */ /** * Sets the activity the client user is playing. * @param {string|ActivityOptions} [name] Activity being played, or options for setting the activity * @param {ActivityOptions} [options] Options for setting the activity - * @returns {Promise} + * @returns {Presence} * @example * // Set the client user's activity * client.user.setActivity('discord.js', { type: 'WATCHING' }) @@ -159,19 +161,20 @@ class ClientUser extends Structures.get('User') { * .catch(console.error); */ setActivity(name, options = {}) { - if (!name) return this.setPresence({ activity: null, shardID: options.shardID }); + if (!name) return this.setPresence({ activities: null, shardID: options.shardID }); const activity = Object.assign({}, options, typeof name === 'object' ? name : { name }); - return this.setPresence({ activity, shardID: activity.shardID }); + return this.setPresence({ activities: [activity], shardID: activity.shardID }); } /** * Sets/removes the AFK flag for the client user. * @param {boolean} afk Whether or not the user is AFK - * @returns {Promise} + * @param {number|number[]} [shardID] Shard Id(s) to have the AFK flag set on + * @returns {Presence} */ - setAFK(afk) { - return this.setPresence({ afk }); + setAFK(afk, shardID) { + return this.setPresence({ afk, shardID }); } } diff --git a/src/structures/Guild.js b/src/structures/Guild.js index ee0d70c1f..44709efee 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -210,13 +210,6 @@ class Guild extends Base { */ this.systemChannelID = data.system_channel_id; - /** - * Whether embedded images are enabled on this guild - * @type {boolean} - * @deprecated - */ - this.embedEnabled = data.embed_enabled; - /** * The type of premium tier: * * 0: NONE @@ -256,15 +249,6 @@ class Guild extends Base { this.widgetChannelID = data.widget_channel_id; } - if (typeof data.embed_channel_id !== 'undefined') { - /** - * The embed channel ID, if enabled - * @type {?string} - * @deprecated - */ - this.embedChannelID = data.embed_channel_id; - } - /** * The verification level of the guild * @type {VerificationLevel} @@ -585,16 +569,6 @@ class Guild extends Base { return this.client.channels.cache.get(this.widgetChannelID) || null; } - /** - * Embed channel for this guild - * @type {?TextChannel} - * @readonly - * @deprecated - */ - get embedChannel() { - return this.client.channels.cache.get(this.embedChannelID) || null; - } - /** * Rules channel for this guild * @type {?TextChannel} @@ -688,8 +662,6 @@ class Guild extends Base { /** * Fetches a collection of integrations to this guild. * Resolves with a collection mapping integrations by their ids. - * @param {Object} [options] Options for fetching integrations - * @param {boolean} [options.includeApplications] Whether to include bot and Oauth2 webhook integrations * @returns {Promise>} * @example * // Fetch integrations @@ -697,20 +669,12 @@ class Guild extends Base { * .then(integrations => console.log(`Fetched ${integrations.size} integrations`)) * .catch(console.error); */ - fetchIntegrations({ includeApplications = false } = {}) { - return this.client.api - .guilds(this.id) - .integrations.get({ - query: { - include_applications: includeApplications, - }, - }) - .then(data => - data.reduce( - (collection, integration) => collection.set(integration.id, new Integration(this.client, integration, this)), - new Collection(), - ), - ); + async fetchIntegrations() { + const data = await this.client.api.guilds(this.id).integrations.get(); + return data.reduce( + (collection, integration) => collection.set(integration.id, new Integration(this.client, integration, this)), + new Collection(), + ); } /** @@ -895,20 +859,6 @@ class Guild extends Base { * @property {?GuildChannelResolvable} channel The widget channel */ - /** - * Fetches the guild embed. - * @returns {Promise} - * @deprecated - * @example - * // Fetches the guild embed - * guild.fetchEmbed() - * .then(embed => console.log(`The embed is ${embed.enabled ? 'enabled' : 'disabled'}`)) - * .catch(console.error); - */ - fetchEmbed() { - return this.fetchWidget(); - } - /** * Fetches the guild widget. * @returns {Promise} @@ -920,8 +870,8 @@ class Guild extends Base { */ async fetchWidget() { const data = await this.client.api.guilds(this.id).widget.get(); - this.widgetEnabled = this.embedEnabled = data.enabled; - this.widgetChannelID = this.embedChannelID = data.channel_id; + this.widgetEnabled = data.enabled; + this.widgetChannelID = data.channel_id; return { enabled: data.enabled, channel: data.channel_id ? this.channels.cache.get(data.channel_id) : null, @@ -1367,7 +1317,7 @@ class Guild extends Base { * @returns {Promise} * @example * guild.setRolePositions([{ role: roleID, position: updatedRoleIndex }]) - * .then(guild => console.log(`Role permissions updated for ${guild}`)) + * .then(guild => console.log(`Role positions updated for ${guild}`)) * .catch(console.error); */ setRolePositions(rolePositions) { @@ -1392,17 +1342,6 @@ class Guild extends Base { ); } - /** - * Edits the guild's embed. - * @param {GuildWidgetData} embed The embed for the guild - * @param {string} [reason] Reason for changing the guild's embed - * @returns {Promise} - * @deprecated - */ - setEmbed(embed, reason) { - return this.setWidget(embed, reason); - } - /** * Edits the guild's widget. * @param {GuildWidgetData} widget The widget for the guild @@ -1464,7 +1403,7 @@ class Guild extends Base { * @returns {boolean} */ equals(guild) { - let equal = + return ( guild && guild instanceof this.constructor && this.id === guild.id && @@ -1478,20 +1417,10 @@ class Guild extends Base { this.icon === guild.icon && this.ownerID === guild.ownerID && this.verificationLevel === guild.verificationLevel && - this.embedEnabled === guild.embedEnabled && (this.features === guild.features || (this.features.length === guild.features.length && - this.features.every((feat, i) => feat === guild.features[i]))); - - if (equal) { - if (this.embedChannel) { - if (!guild.embedChannel || this.embedChannel.id !== guild.embedChannel.id) equal = false; - } else if (guild.embedChannel) { - equal = false; - } - } - - return equal; + this.features.every((feat, i) => feat === guild.features[i]))) + ); } /** @@ -1522,7 +1451,7 @@ class Guild extends Base { /** * Creates a collection of this guild's roles, sorted by their position and IDs. - * @returns {Collection} + * @returns {Collection} * @private */ _sortedRoles() { @@ -1532,7 +1461,7 @@ class Guild extends Base { /** * Creates a collection of this guild's or a specific category's channels, sorted by their position and IDs. * @param {GuildChannel} [channel] Category to get the channels of - * @returns {Collection} + * @returns {Collection} * @private */ _sortedChannels(channel) { @@ -1549,10 +1478,6 @@ class Guild extends Base { } } -Guild.prototype.setEmbed = deprecate(Guild.prototype.setEmbed, 'Guild#setEmbed: Use setWidget instead'); - -Guild.prototype.fetchEmbed = deprecate(Guild.prototype.fetchEmbed, 'Guild#fetchEmbed: Use fetchWidget instead'); - Guild.prototype.fetchVanityCode = deprecate( Guild.prototype.fetchVanityCode, 'Guild#fetchVanityCode: Use fetchVanityData() instead', diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 394fdebfc..aab133d4c 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -3,7 +3,7 @@ const Integration = require('./Integration'); const Webhook = require('./Webhook'); const Collection = require('../util/Collection'); -const { PartialTypes } = require('../util/Constants'); +const { OverwriteTypes, PartialTypes } = require('../util/Constants'); const Permissions = require('../util/Permissions'); const Snowflake = require('../util/Snowflake'); const Util = require('../util/Util'); @@ -384,16 +384,19 @@ class GuildAuditLogsEntry { case Actions.CHANNEL_OVERWRITE_CREATE: case Actions.CHANNEL_OVERWRITE_UPDATE: case Actions.CHANNEL_OVERWRITE_DELETE: - switch (data.options.type) { - case 'member': - this.extra = guild.members.cache.get(data.options.id) || { id: data.options.id, type: 'member' }; - break; - - case 'role': + switch (Number(data.options.type)) { + case OverwriteTypes.role: this.extra = guild.roles.cache.get(data.options.id) || { id: data.options.id, name: data.options.role_name, - type: 'role', + type: OverwriteTypes[OverwriteTypes.role], + }; + break; + + case OverwriteTypes.member: + this.extra = guild.members.cache.get(data.options.id) || { + id: data.options.id, + type: OverwriteTypes[OverwriteTypes.member], }; break; diff --git a/src/structures/GuildChannel.js b/src/structures/GuildChannel.js index 6832b6ff6..1a53fc7f4 100644 --- a/src/structures/GuildChannel.js +++ b/src/structures/GuildChannel.js @@ -7,6 +7,7 @@ const Role = require('./Role'); const { Error, TypeError } = require('../errors'); const Collection = require('../util/Collection'); const { ChannelTypes } = require('../util/Constants'); +const { OverwriteTypes } = require('../util/Constants'); const Permissions = require('../util/Permissions'); const Util = require('../util/Util'); @@ -161,12 +162,12 @@ class GuildChannel extends Channel { const overwrites = this.overwritesFor(member, true, roles); return permissions - .remove(overwrites.everyone ? overwrites.everyone.deny : 0) - .add(overwrites.everyone ? overwrites.everyone.allow : 0) - .remove(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.deny) : 0) - .add(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.allow) : 0) - .remove(overwrites.member ? overwrites.member.deny : 0) - .add(overwrites.member ? overwrites.member.allow : 0) + .remove(overwrites.everyone ? overwrites.everyone.deny : 0n) + .add(overwrites.everyone ? overwrites.everyone.allow : 0n) + .remove(overwrites.roles.length > 0n ? overwrites.roles.map(role => role.deny) : 0n) + .add(overwrites.roles.length > 0n ? overwrites.roles.map(role => role.allow) : 0n) + .remove(overwrites.member ? overwrites.member.deny : 0n) + .add(overwrites.member ? overwrites.member.allow : 0n) .freeze(); } @@ -183,10 +184,10 @@ class GuildChannel extends Channel { const roleOverwrites = this.permissionOverwrites.get(role.id); return role.permissions - .remove(everyoneOverwrites ? everyoneOverwrites.deny : 0) - .add(everyoneOverwrites ? everyoneOverwrites.allow : 0) - .remove(roleOverwrites ? roleOverwrites.deny : 0) - .add(roleOverwrites ? roleOverwrites.allow : 0) + .remove(everyoneOverwrites ? everyoneOverwrites.deny : 0n) + .add(everyoneOverwrites ? everyoneOverwrites.allow : 0n) + .remove(roleOverwrites ? roleOverwrites.deny : 0n) + .add(roleOverwrites ? roleOverwrites.allow : 0n) .freeze(); } @@ -204,13 +205,12 @@ class GuildChannel extends Channel { * }, * ], 'Needed to change permissions'); */ - overwritePermissions(overwrites, reason) { + async overwritePermissions(overwrites, reason) { if (!Array.isArray(overwrites) && !(overwrites instanceof Collection)) { - return Promise.reject( - new TypeError('INVALID_TYPE', 'overwrites', 'Array or Collection of Permission Overwrites', true), - ); + throw new TypeError('INVALID_TYPE', 'overwrites', 'Array or Collection of Permission Overwrites', true); } - return this.edit({ permissionOverwrites: overwrites, reason }).then(() => this); + await this.edit({ permissionOverwrites: overwrites, reason }); + return this; } /** @@ -227,13 +227,17 @@ class GuildChannel extends Channel { * .then(channel => console.log(channel.permissionOverwrites.get(message.author.id))) * .catch(console.error); */ - updateOverwrite(userOrRole, options, reason) { + async updateOverwrite(userOrRole, options, reason) { userOrRole = this.guild.roles.resolve(userOrRole) || this.client.users.resolve(userOrRole); if (!userOrRole) return Promise.reject(new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role')); const existing = this.permissionOverwrites.get(userOrRole.id); - if (existing) return existing.update(options, reason).then(() => this); - return this.createOverwrite(userOrRole, options, reason); + if (existing) { + await existing.update(options, reason); + } else { + await this.createOverwrite(userOrRole, options, reason); + } + return this; } /** @@ -254,13 +258,19 @@ class GuildChannel extends Channel { userOrRole = this.guild.roles.resolve(userOrRole) || this.client.users.resolve(userOrRole); if (!userOrRole) return Promise.reject(new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role')); - const type = userOrRole instanceof Role ? 'role' : 'member'; + const type = userOrRole instanceof Role ? OverwriteTypes.role : OverwriteTypes.member; const { allow, deny } = PermissionOverwrites.resolveOverwriteOptions(options); return this.client.api .channels(this.id) - .permissions[userOrRole.id].put({ - data: { id: userOrRole.id, type, allow: allow.bitfield, deny: deny.bitfield }, + .permissions(userOrRole.id) + .put({ + data: { + id: userOrRole.id, + type, + allow, + deny, + }, reason, }) .then(() => this); diff --git a/src/structures/PermissionOverwrites.js b/src/structures/PermissionOverwrites.js index bbc7cd136..b8990136c 100644 --- a/src/structures/PermissionOverwrites.js +++ b/src/structures/PermissionOverwrites.js @@ -2,8 +2,8 @@ const Role = require('./Role'); const { TypeError } = require('../errors'); +const { OverwriteTypes } = require('../util/Constants'); const Permissions = require('../util/Permissions'); -const Util = require('../util/Util'); /** * Represents a permission overwrite for a role or member in a guild channel. @@ -28,30 +28,23 @@ class PermissionOverwrites { */ this.id = data.id; - /** - * The type of a permission overwrite. It can be one of: - * * member - * * role - * @typedef {string} OverwriteType - */ - /** * The type of this overwrite * @type {OverwriteType} */ - this.type = data.type; + this.type = OverwriteTypes[data.type]; /** * The permissions that are denied for the user or role. * @type {Readonly} */ - this.deny = new Permissions(data.deny).freeze(); + this.deny = new Permissions(BigInt(data.deny)).freeze(); /** * The permissions that are allowed for the user or role. * @type {Readonly} */ - this.allow = new Permissions(data.allow).freeze(); + this.allow = new Permissions(BigInt(data.allow)).freeze(); } /** @@ -67,16 +60,22 @@ class PermissionOverwrites { * .then(channel => console.log(channel.permissionOverwrites.get(message.author.id))) * .catch(console.error); */ - update(options, reason) { + async update(options, reason) { const { allow, deny } = this.constructor.resolveOverwriteOptions(options, this); - return this.channel.client.api + await this.channel.client.api .channels(this.channel.id) - .permissions[this.id].put({ - data: { id: this.id, type: this.type, allow: allow.bitfield, deny: deny.bitfield }, + .permissions(this.id) + .put({ + data: { + id: this.id, + type: OverwriteTypes[this.type], + allow, + deny, + }, reason, - }) - .then(() => this); + }); + return this; } /** @@ -84,12 +83,18 @@ class PermissionOverwrites { * @param {string} [reason] Reason for deleting this overwrite * @returns {Promise} */ - delete(reason) { - return this.channel.client.api.channels[this.channel.id].permissions[this.id].delete({ reason }).then(() => this); + async delete(reason) { + await this.channel.client.api.channels(this.channel.id).permissions(this.id).delete({ reason }); + return this; } toJSON() { - return Util.flatten(this); + return { + id: this.id, + type: OverwriteTypes[this.type], + allow: this.allow, + deny: this.deny, + }; } /** @@ -142,9 +147,9 @@ class PermissionOverwrites { * The raw data for a permission overwrite * @typedef {Object} RawOverwriteData * @property {Snowflake} id The id of the overwrite - * @property {number} allow The permissions to allow - * @property {number} deny The permissions to deny - * @property {OverwriteType} type The type of this OverwriteData + * @property {string} allow The permissions to allow + * @property {string} deny The permissions to deny + * @property {number} type The type of this OverwriteData */ /** @@ -164,24 +169,29 @@ class PermissionOverwrites { /** * Resolves an overwrite into {@link RawOverwriteData}. * @param {OverwriteResolvable} overwrite The overwrite-like data to resolve - * @param {Guild} guild The guild to resolve from + * @param {Guild} [guild] The guild to resolve from * @returns {RawOverwriteData} */ static resolve(overwrite, guild) { if (overwrite instanceof this) return overwrite.toJSON(); - if (typeof overwrite.id === 'string' && ['role', 'member'].includes(overwrite.type)) { - return { ...overwrite, allow: Permissions.resolve(overwrite.allow), deny: Permissions.resolve(overwrite.deny) }; + if (typeof overwrite.id === 'string' && overwrite.type in OverwriteTypes) { + return { + id: overwrite.id, + type: OverwriteTypes[overwrite.type], + allow: Permissions.resolve(overwrite.allow).toString(), + deny: Permissions.resolve(overwrite.deny).toString(), + }; } const userOrRole = guild.roles.resolve(overwrite.id) || guild.client.users.resolve(overwrite.id); if (!userOrRole) throw new TypeError('INVALID_TYPE', 'parameter', 'User nor a Role'); - const type = userOrRole instanceof Role ? 'role' : 'member'; + const type = userOrRole instanceof Role ? OverwriteTypes.role : OverwriteTypes.member; return { id: userOrRole.id, type, - allow: Permissions.resolve(overwrite.allow), - deny: Permissions.resolve(overwrite.deny), + allow: Permissions.resolve(overwrite.allow).toString(), + deny: Permissions.resolve(overwrite.deny).toString(), }; } } diff --git a/src/structures/Role.js b/src/structures/Role.js index 04db107ee..90fb2383f 100644 --- a/src/structures/Role.js +++ b/src/structures/Role.js @@ -63,7 +63,7 @@ class Role extends Base { * The permissions of the role * @type {Readonly} */ - this.permissions = new Permissions(data.permissions).freeze(); + this.permissions = new Permissions(BigInt(data.permissions)).freeze(); /** * Whether or not the role is managed by an external service @@ -301,7 +301,7 @@ class Role extends Base { * .catch(console.error); * @example * // Remove all permissions from a role - * role.setPermissions(0) + * role.setPermissions(0n) * .then(updated => console.log(`Updated permissions to ${updated.permissions.bitfield}`)) * .catch(console.error); */ diff --git a/src/structures/User.js b/src/structures/User.js index 2811e8622..bddb94825 100644 --- a/src/structures/User.js +++ b/src/structures/User.js @@ -245,7 +245,7 @@ class User extends Base { recipient_id: this.id, }, }); - return this.client.actions.ChannelCreate.handle(data).channel; + return this.client.channels.add(data); } /** @@ -255,8 +255,9 @@ class User extends Base { async deleteDM() { const { dmChannel } = this; if (!dmChannel) throw new Error('USER_NO_DMCHANNEL'); - const data = await this.client.api.channels(dmChannel.id).delete(); - return this.client.actions.ChannelDelete.handle(data).channel; + await this.client.api.channels(dmChannel.id).delete(); + this.client.channels.remove(dmChannel.id); + return dmChannel; } /** diff --git a/src/util/BitField.js b/src/util/BitField.js index 070f28db0..fe32332f4 100644 --- a/src/util/BitField.js +++ b/src/util/BitField.js @@ -7,12 +7,12 @@ const { RangeError } = require('../errors'); */ class BitField { /** - * @param {BitFieldResolvable} [bits=0] Bit(s) to read from + * @param {BitFieldResolvable} [bits=this.constructor.defaultBit] Bit(s) to read from */ - constructor(bits) { + constructor(bits = this.constructor.defaultBit) { /** * Bitfield of the packed bits - * @type {number} + * @type {number|bigint} */ this.bitfield = this.constructor.resolve(bits); } @@ -23,7 +23,7 @@ class BitField { * @returns {boolean} */ any(bit) { - return (this.bitfield & this.constructor.resolve(bit)) !== 0; + return (this.bitfield & this.constructor.resolve(bit)) !== this.constructor.defaultBit; } /** @@ -71,7 +71,7 @@ class BitField { * @returns {BitField} These bits or new BitField if the instance is frozen. */ add(...bits) { - let total = 0; + let total = this.constructor.defaultBit; for (const bit of bits) { total |= this.constructor.resolve(bit); } @@ -86,7 +86,7 @@ class BitField { * @returns {BitField} These bits or new BitField if the instance is frozen. */ remove(...bits) { - let total = 0; + let total = this.constructor.defaultBit; for (const bit of bits) { total |= this.constructor.resolve(bit); } @@ -117,7 +117,7 @@ class BitField { } toJSON() { - return this.bitfield; + return typeof this.bitfield === 'number' ? this.bitfield : this.bitfield.toString(); } valueOf() { @@ -133,18 +133,20 @@ class BitField { * * A bit number (this can be a number literal or a value taken from {@link BitField.FLAGS}) * * An instance of BitField * * An Array of BitFieldResolvable - * @typedef {number|BitField|BitFieldResolvable[]} BitFieldResolvable + * @typedef {number|bigint|BitField|BitFieldResolvable[]} BitFieldResolvable */ /** * Resolves bitfields to their numeric form. - * @param {BitFieldResolvable} [bit=0] - bit(s) to resolve - * @returns {number} + * @param {BitFieldResolvable} [bit] - bit(s) to resolve + * @returns {number|bigint} */ - static resolve(bit = 0) { - if (typeof bit === 'number' && bit >= 0) return bit; + static resolve(bit) { + const { defaultBit } = this; + if (typeof bit === 'undefined') return defaultBit; + if (typeof defaultBit === typeof bit && bit >= defaultBit) return bit; if (bit instanceof BitField) return bit.bitfield; - if (Array.isArray(bit)) return bit.map(p => this.resolve(p)).reduce((prev, p) => prev | p, 0); + if (Array.isArray(bit)) return bit.map(p => this.resolve(p)).reduce((prev, p) => prev | p, defaultBit); if (typeof bit === 'string' && typeof this.FLAGS[bit] !== 'undefined') return this.FLAGS[bit]; throw new RangeError('BITFIELD_INVALID', bit); } @@ -158,4 +160,10 @@ class BitField { */ BitField.FLAGS = {}; +/** + * @type {number|bigint} + * @private + */ +BitField.defaultBit = 0; + module.exports = BitField; diff --git a/src/util/Constants.js b/src/util/Constants.js index ac2046b3d..3f4d7dcbe 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -30,7 +30,8 @@ const { Error, RangeError } = require('../errors'); * @property {number} [restSweepInterval=60] How frequently to delete inactive request buckets, in seconds * (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 {PresenceData} [presence={}] Presence data to use upon login + * @property {IntentsResolvable} intents Intents to enable for this connection * @property {WebsocketOptions} [ws] Options for the WebSocket * @property {HTTPOptions} [http] HTTP options */ @@ -52,7 +53,6 @@ exports.DefaultOptions = { * @typedef {Object} WebsocketOptions * @property {number} [large_threshold=50] Number of members in a guild after which offline users will no longer be * sent in the initial guild member list, must be between 50 and 250 - * @property {IntentsResolvable} [intents] Intents to enable for this connection */ ws: { large_threshold: 50, @@ -62,7 +62,7 @@ exports.DefaultOptions = { $browser: 'discord.js', $device: 'discord.js', }, - version: 6, + version: 8, }, /** @@ -75,7 +75,7 @@ exports.DefaultOptions = { * @property {string} [template='https://discord.new'] Base url of templates */ http: { - version: 7, + version: 8, api: 'https://discord.com/api', cdn: 'https://cdn.discordapp.com', invite: 'https://discord.gg', @@ -557,6 +557,7 @@ exports.VerificationLevels = ['NONE', 'LOW', 'MEDIUM', 'HIGH', 'VERY_HIGH']; * * UNKNOWN_GUILD_TEMPLATE * * BOT_PROHIBITED_ENDPOINT * * BOT_ONLY_ENDPOINT + * * ANNOUNCEMENT_EDIT_LIMIT_EXCEEDED * * CHANNEL_HIT_WRITE_RATELIMIT * * MAXIMUM_GUILDS * * MAXIMUM_FRIENDS @@ -593,7 +594,9 @@ exports.VerificationLevels = ['NONE', 'LOW', 'MEDIUM', 'HIGH', 'VERY_HIGH']; * * CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL * * INVALID_OR_TAKEN_INVITE_CODE * * CANNOT_EXECUTE_ON_SYSTEM_MESSAGE + * * CANNOT_EXECUTE_ON_CHANNEL_TYPE * * INVALID_OAUTH_TOKEN + * * INVALID_RECIPIENTS * * BULK_DELETE_MESSAGE_TOO_OLD * * INVALID_FORM_BODY * * INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT @@ -623,6 +626,7 @@ exports.APIErrors = { UNKNOWN_GUILD_TEMPLATE: 10057, BOT_PROHIBITED_ENDPOINT: 20001, BOT_ONLY_ENDPOINT: 20002, + ANNOUNCEMENT_EDIT_LIMIT_EXCEEDED: 20022, CHANNEL_HIT_WRITE_RATELIMIT: 20028, MAXIMUM_GUILDS: 30001, MAXIMUM_FRIENDS: 30002, @@ -659,7 +663,9 @@ exports.APIErrors = { CANNOT_PIN_MESSAGE_IN_OTHER_CHANNEL: 50019, INVALID_OR_TAKEN_INVITE_CODE: 50020, CANNOT_EXECUTE_ON_SYSTEM_MESSAGE: 50021, + CANNOT_EXECUTE_ON_CHANNEL_TYPE: 50024, INVALID_OAUTH_TOKEN: 50025, + INVALID_RECIPIENTS: 50033, BULK_DELETE_MESSAGE_TOO_OLD: 50034, INVALID_FORM_BODY: 50035, INVITE_ACCEPTED_TO_GUILD_NOT_CONTAINING_BOT: 50036, @@ -703,8 +709,26 @@ exports.WebhookTypes = [ 'Channel Follower', ]; +/** + * An overwrite type: + * * role + * * member + * @typedef {string} OverwriteType + */ +exports.OverwriteTypes = createEnum(['role', 'member']); + function keyMirror(arr) { let tmp = Object.create(null); for (const value of arr) tmp[value] = value; return tmp; } + +function createEnum(keys) { + const obj = {}; + for (const [index, key] of keys.entries()) { + if (key === null) continue; + obj[key] = index; + obj[index] = key; + } + return obj; +} diff --git a/src/util/MessageFlags.js b/src/util/MessageFlags.js index 536cbd881..fb8d2abb6 100644 --- a/src/util/MessageFlags.js +++ b/src/util/MessageFlags.js @@ -15,6 +15,12 @@ class MessageFlags extends BitField {} * @param {BitFieldResolvable} [bits=0] Bit(s) to read from */ +/** + * Bitfield of the packed bits + * @type {number} + * @name MessageFlags#bitfield + */ + /** * Numeric message flags. All available properties: * * `CROSSPOSTED` diff --git a/src/util/Permissions.js b/src/util/Permissions.js index 98a283892..efaf1e72d 100644 --- a/src/util/Permissions.js +++ b/src/util/Permissions.js @@ -10,10 +10,9 @@ const BitField = require('./BitField'); */ class Permissions extends BitField { /** - * @name Permissions - * @kind constructor - * @memberof Permissions - * @param {PermissionResolvable} [bits=0] Bit(s) to read from + * Bitfield of the packed bits + * @type {bigint} + * @name Permissions#bitfield */ /** @@ -22,7 +21,7 @@ class Permissions extends BitField { * * A permission number * * An instance of Permissions * * An Array of PermissionResolvable - * @typedef {string|number|Permissions|PermissionResolvable[]} PermissionResolvable + * @typedef {string|bigint|Permissions|PermissionResolvable[]} PermissionResolvable */ /** @@ -79,53 +78,55 @@ class Permissions extends BitField { * * `MANAGE_ROLES` * * `MANAGE_WEBHOOKS` * * `MANAGE_EMOJIS` - * @type {Object} + * @type {Object} * @see {@link https://discord.com/developers/docs/topics/permissions} */ Permissions.FLAGS = { - CREATE_INSTANT_INVITE: 1 << 0, - KICK_MEMBERS: 1 << 1, - BAN_MEMBERS: 1 << 2, - ADMINISTRATOR: 1 << 3, - MANAGE_CHANNELS: 1 << 4, - MANAGE_GUILD: 1 << 5, - ADD_REACTIONS: 1 << 6, - VIEW_AUDIT_LOG: 1 << 7, - PRIORITY_SPEAKER: 1 << 8, - STREAM: 1 << 9, - VIEW_CHANNEL: 1 << 10, - SEND_MESSAGES: 1 << 11, - SEND_TTS_MESSAGES: 1 << 12, - MANAGE_MESSAGES: 1 << 13, - EMBED_LINKS: 1 << 14, - ATTACH_FILES: 1 << 15, - READ_MESSAGE_HISTORY: 1 << 16, - MENTION_EVERYONE: 1 << 17, - USE_EXTERNAL_EMOJIS: 1 << 18, - VIEW_GUILD_INSIGHTS: 1 << 19, - CONNECT: 1 << 20, - SPEAK: 1 << 21, - MUTE_MEMBERS: 1 << 22, - DEAFEN_MEMBERS: 1 << 23, - MOVE_MEMBERS: 1 << 24, - USE_VAD: 1 << 25, - CHANGE_NICKNAME: 1 << 26, - MANAGE_NICKNAMES: 1 << 27, - MANAGE_ROLES: 1 << 28, - MANAGE_WEBHOOKS: 1 << 29, - MANAGE_EMOJIS: 1 << 30, + CREATE_INSTANT_INVITE: 1n << 0n, + KICK_MEMBERS: 1n << 1n, + BAN_MEMBERS: 1n << 2n, + ADMINISTRATOR: 1n << 3n, + MANAGE_CHANNELS: 1n << 4n, + MANAGE_GUILD: 1n << 5n, + ADD_REACTIONS: 1n << 6n, + VIEW_AUDIT_LOG: 1n << 7n, + PRIORITY_SPEAKER: 1n << 8n, + STREAM: 1n << 9n, + VIEW_CHANNEL: 1n << 10n, + SEND_MESSAGES: 1n << 11n, + SEND_TTS_MESSAGES: 1n << 12n, + MANAGE_MESSAGES: 1n << 13n, + EMBED_LINKS: 1n << 14n, + ATTACH_FILES: 1n << 15n, + READ_MESSAGE_HISTORY: 1n << 16n, + MENTION_EVERYONE: 1n << 17n, + USE_EXTERNAL_EMOJIS: 1n << 18n, + VIEW_GUILD_INSIGHTS: 1n << 19n, + CONNECT: 1n << 20n, + SPEAK: 1n << 21n, + MUTE_MEMBERS: 1n << 22n, + DEAFEN_MEMBERS: 1n << 23n, + MOVE_MEMBERS: 1n << 24n, + USE_VAD: 1n << 25n, + CHANGE_NICKNAME: 1n << 26n, + MANAGE_NICKNAMES: 1n << 27n, + MANAGE_ROLES: 1n << 28n, + MANAGE_WEBHOOKS: 1n << 29n, + MANAGE_EMOJIS: 1n << 30n, }; /** * Bitfield representing every permission combined - * @type {number} + * @type {bigint} */ -Permissions.ALL = Object.values(Permissions.FLAGS).reduce((all, p) => all | p, 0); +Permissions.ALL = Object.values(Permissions.FLAGS).reduce((all, p) => all | p, 0n); /** * Bitfield representing the default permissions for users - * @type {number} + * @type {bigint} */ -Permissions.DEFAULT = 104324673; +Permissions.DEFAULT = BigInt(104324673); + +Permissions.defaultBit = BigInt(0); module.exports = Permissions; diff --git a/src/util/Speaking.js b/src/util/Speaking.js index 5fda560e0..e8914250c 100644 --- a/src/util/Speaking.js +++ b/src/util/Speaking.js @@ -16,6 +16,12 @@ class Speaking extends BitField {} * @param {BitFieldResolvable} [bits=0] Bit(s) to read from */ +/** + * Bitfield of the packed bits + * @type {number} + * @name Speaking#bitfield + */ + /** * Numeric speaking flags. All available properties: * * `SPEAKING` diff --git a/src/util/SystemChannelFlags.js b/src/util/SystemChannelFlags.js index 4d08b7609..b7a3f172f 100644 --- a/src/util/SystemChannelFlags.js +++ b/src/util/SystemChannelFlags.js @@ -17,6 +17,12 @@ class SystemChannelFlags extends BitField {} * @param {SystemChannelFlagsResolvable} [bits=0] Bit(s) to read from */ +/** + * Bitfield of the packed bits + * @type {number} + * @name SystemChannelFlags#bitfield + */ + /** * Data that can be resolved to give a sytem channel flag bitfield. This can be: * * A string (see {@link SystemChannelFlags.FLAGS}) diff --git a/src/util/UserFlags.js b/src/util/UserFlags.js index 871fbb730..ec801b0d0 100644 --- a/src/util/UserFlags.js +++ b/src/util/UserFlags.js @@ -14,6 +14,12 @@ class UserFlags extends BitField {} * @param {BitFieldResolvable} [bits=0] Bit(s) to read from */ +/** + * Bitfield of the packed bits + * @type {number} + * @name UserFlags#bitfield + */ + /** * Numeric user flags. All available properties: * * `DISCORD_EMPLOYEE` diff --git a/test/createGuild.js b/test/createGuild.js index ccd10e027..750987a0c 100644 --- a/test/createGuild.js +++ b/test/createGuild.js @@ -2,9 +2,11 @@ const assert = require('assert'); const { token } = require('./auth'); -const { Client } = require('../src'); +const { Client, Intents } = require('../src'); -const client = new Client(); +const client = new Client({ + intents: Intents.NON_PRIVILEGED, +}); client.on('ready', async () => { try { diff --git a/test/random.js b/test/random.js index 4b719f56e..d8d51e139 100644 --- a/test/random.js +++ b/test/random.js @@ -9,7 +9,9 @@ const Discord = require('../src'); console.time('magic'); -const client = new Discord.Client(); +const client = new Discord.Client({ + intents: Discord.Intents.NON_PRIVILEGED +}); client .login(token) diff --git a/test/sendtest.js b/test/sendtest.js index 691c4e24c..d5456d9c5 100644 --- a/test/sendtest.js +++ b/test/sendtest.js @@ -7,7 +7,9 @@ const fetch = require('node-fetch'); const { owner, token } = require('./auth.js'); const Discord = require('../src'); -const client = new Discord.Client(); +const client = new Discord.Client({ + intents: Discord.Intents.NON_PRIVILEGED, +}); const fill = c => Array(4).fill(c.repeat(1000)); const buffer = l => fetch(l).then(res => res.buffer()); diff --git a/test/shard.js b/test/shard.js index 52225370c..1dd1e89f8 100644 --- a/test/shard.js +++ b/test/shard.js @@ -6,17 +6,13 @@ const Discord = require('../src'); const client = new Discord.Client({ shards: process.argv[2], shardCount: process.argv[3], + intents: Discord.Intents.NON_PRIVILEGED, }); client.on('message', msg => { if (msg.content.startsWith('?eval') && msg.author.id === '66564597481480192') { try { - const com = eval( - msg.content - .split(' ') - .slice(1) - .join(' '), - ); + const com = eval(msg.content.split(' ').slice(1).join(' ')); msg.channel.send(com, { code: true }); } catch (e) { msg.channel.send(e, { code: true }); diff --git a/test/tester1000.js b/test/tester1000.js index 077b996bb..2705a4054 100644 --- a/test/tester1000.js +++ b/test/tester1000.js @@ -8,6 +8,7 @@ const log = (...args) => console.log(process.uptime().toFixed(3), ...args); const client = new Discord.Client({ shardCount: 2, + intents: Discord.Intents.NON_PRIVILEGED, }); client.on('debug', log); diff --git a/test/voice.js b/test/voice.js index 0ab2fe4f0..cd7bc67ea 100644 --- a/test/voice.js +++ b/test/voice.js @@ -5,7 +5,10 @@ const ytdl = require('ytdl-core'); const auth = require('./auth.js'); const Discord = require('../src'); -const client = new Discord.Client({ partials: [] }); +const client = new Discord.Client({ + partials: [], + intents: Discord.Intents.NON_PRIVILEGED, +}); client .login(auth.token) diff --git a/test/webhooktest.js b/test/webhooktest.js index 3691dd8dd..74cb34a5d 100644 --- a/test/webhooktest.js +++ b/test/webhooktest.js @@ -7,7 +7,9 @@ const fetch = require('node-fetch'); const { owner, token, webhookChannel, webhookToken } = require('./auth.js'); const Discord = require('../src'); -const client = new Discord.Client(); +const client = new Discord.Client({ + intents: Discord.Intents.NON_PRIVILEGED, +}); const fill = c => Array(4).fill(c.repeat(1000)); const buffer = l => fetch(l).then(res => res.buffer()); diff --git a/typings/index.d.ts b/typings/index.d.ts index f6c8878a5..5f6874f37 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -9,6 +9,11 @@ declare enum ChannelType { unknown = 7, } +declare enum OverwriteTypes { + role = 0, + member = 1, +} + declare module 'discord.js' { import BaseCollection from '@discordjs/collection'; import { ChildProcess } from 'child_process'; @@ -47,7 +52,7 @@ declare module 'discord.js' { export class ActivityFlags extends BitField { public static FLAGS: Record; - public static resolve(bit?: BitFieldResolvable): number; + public static resolve(bit?: BitFieldResolvable): number; } export class APIMessage { @@ -118,7 +123,7 @@ declare module 'discord.js' { } export class BaseClient extends EventEmitter { - constructor(options?: ClientOptions); + constructor(options?: ClientOptions | WebhookClientOptions); private _timeouts: Set; private _intervals: Set; private _immediates: Set; @@ -127,7 +132,7 @@ declare module 'discord.js' { private decrementMaxListeners(): void; private incrementMaxListeners(): void; - public options: ClientOptions; + public options: ClientOptions | WebhookClientOptions; public clearInterval(interval: NodeJS.Timeout): void; public clearTimeout(timeout: NodeJS.Timeout): void; public clearImmediate(timeout: NodeJS.Immediate): void; @@ -155,23 +160,23 @@ declare module 'discord.js' { public broadcast: VoiceBroadcast; } - export class BitField { - constructor(bits?: BitFieldResolvable); - public bitfield: number; - public add(...bits: BitFieldResolvable[]): BitField; - public any(bit: BitFieldResolvable): boolean; - public equals(bit: BitFieldResolvable): boolean; - public freeze(): Readonly>; - public has(bit: BitFieldResolvable): boolean; - public missing(bits: BitFieldResolvable, ...hasParam: readonly unknown[]): S[]; - public remove(...bits: BitFieldResolvable[]): BitField; + export class BitField { + constructor(bits?: BitFieldResolvable); + public bitfield: N; + public add(...bits: BitFieldResolvable[]): BitField; + public any(bit: BitFieldResolvable): boolean; + public equals(bit: BitFieldResolvable): boolean; + public freeze(): Readonly>; + public has(bit: BitFieldResolvable): boolean; + public missing(bits: BitFieldResolvable, ...hasParam: readonly unknown[]): S[]; + public remove(...bits: BitFieldResolvable[]): BitField; public serialize(...hasParam: readonly unknown[]): Record; public toArray(...hasParam: readonly unknown[]): S[]; public toJSON(): number; public valueOf(): number; public [Symbol.iterator](): IterableIterator; public static FLAGS: object; - public static resolve(bit?: BitFieldResolvable): number; + public static resolve(bit?: BitFieldResolvable): number | bigint; } export class CategoryChannel extends GuildChannel { @@ -193,14 +198,15 @@ declare module 'discord.js' { } export class Client extends BaseClient { - constructor(options?: ClientOptions); + constructor(options: ClientOptions); private actions: object; private _eval(script: string): any; - private _validateOptions(options?: ClientOptions): void; + private _validateOptions(options: ClientOptions): void; public channels: ChannelManager; public readonly emojis: BaseGuildEmojiManager; public guilds: GuildManager; + public options: ClientOptions; public readyAt: Date | null; public readonly readyTimestamp: number | null; public shard: ShardClientUtil | null; @@ -258,13 +264,14 @@ declare module 'discord.js' { export class ClientUser extends User { public mfaEnabled: boolean; public verified: boolean; - public setActivity(options?: ActivityOptions): Promise; - public setActivity(name: string, options?: ActivityOptions): Promise; + public edit(data: ClientUserEditData): Promise; + public setActivity(options?: ActivityOptions): Presence; + public setActivity(name: string, options?: ActivityOptions): Presence; public setAFK(afk: boolean): Promise; - public setAvatar(avatar: BufferResolvable | Base64Resolvable): Promise; - public setPresence(data: PresenceData): Promise; - public setStatus(status: PresenceStatusData, shardID?: number | number[]): Promise; - public setUsername(username: string): Promise; + public setAvatar(avatar: BufferResolvable | Base64Resolvable): Promise; + public setPresence(data: PresenceData): Presence; + public setStatus(status: PresenceStatusData, shardID?: number | number[]): Presence; + public setUsername(username: string): Promise; } export class ClientVoiceManager { @@ -517,6 +524,7 @@ declare module 'discord.js' { MessageTypes: MessageType[]; SystemMessageTypes: SystemMessageType[]; ActivityTypes: ActivityType[]; + OverwriteTypes: OverwriteTypes; ExplicitContentFilterLevels: ExplicitContentFilterLevel[]; DefaultMessageNotifications: DefaultMessageNotifications[]; VerificationLevels: VerificationLevel[]; @@ -587,9 +595,6 @@ declare module 'discord.js' { public deleted: boolean; public description: string | null; public discoverySplash: string | null; - public embedChannel: GuildChannel | null; - public embedChannelID: Snowflake | null; - public embedEnabled: boolean; public emojis: GuildEmojiManager; public explicitContentFilter: ExplicitContentFilterLevel; public features: GuildFeatures[]; @@ -645,8 +650,7 @@ declare module 'discord.js' { public fetchAuditLogs(options?: GuildAuditLogsFetchOptions): Promise; public fetchBan(user: UserResolvable): Promise<{ user: User; reason: string }>; public fetchBans(): Promise>; - public fetchEmbed(): Promise; - public fetchIntegrations(options?: FetchIntegrationsOptions): Promise>; + public fetchIntegrations(): Promise>; public fetchInvites(): Promise>; public fetchPreview(): Promise; public fetchTemplates(): Promise>; @@ -666,7 +670,6 @@ declare module 'discord.js' { reason?: string, ): Promise; public setDiscoverySplash(discoverySplash: Base64Resolvable | null, reason?: string): Promise; - public setEmbed(embed: GuildWidgetData, reason?: string): Promise; public setExplicitContentFilter( explicitContentFilter: ExplicitContentFilterLevel | number, reason?: string, @@ -920,7 +923,7 @@ declare module 'discord.js' { public static PRIVILEGED: number; public static ALL: number; public static NON_PRIVILEGED: number; - public static resolve(bit?: BitFieldResolvable): number; + public static resolve(bit?: BitFieldResolvable): number; } export class Invite extends Base { @@ -1095,7 +1098,7 @@ declare module 'discord.js' { export class MessageFlags extends BitField { public static FLAGS: Record; - public static resolve(bit?: BitFieldResolvable): number; + public static resolve(bit?: BitFieldResolvable): number; } export class MessageMentions { @@ -1189,17 +1192,17 @@ declare module 'discord.js' { public static resolve(overwrite: OverwriteResolvable, guild: Guild): RawOverwriteData; } - export class Permissions extends BitField { + export class Permissions extends BitField { public any(permission: PermissionResolvable, checkAdmin?: boolean): boolean; public has(permission: PermissionResolvable, checkAdmin?: boolean): boolean; - public missing(bits: BitFieldResolvable, checkAdmin?: boolean): PermissionString[]; + public missing(bits: BitFieldResolvable, checkAdmin?: boolean): PermissionString[]; public serialize(checkAdmin?: boolean): Record; public toArray(checkAdmin?: boolean): PermissionString[]; - public static ALL: number; - public static DEFAULT: number; + public static ALL: bigint; + public static DEFAULT: bigint; public static FLAGS: PermissionFlags; - public static resolve(permission?: PermissionResolvable): number; + public static resolve(permission?: PermissionResolvable): bigint; } export class Presence { @@ -1410,7 +1413,7 @@ declare module 'discord.js' { export class Speaking extends BitField { public static FLAGS: Record; - public static resolve(bit?: BitFieldResolvable): number; + public static resolve(bit?: BitFieldResolvable): number; } export class StoreChannel extends GuildChannel { @@ -1468,7 +1471,7 @@ declare module 'discord.js' { export class SystemChannelFlags extends BitField { public static FLAGS: Record; - public static resolve(bit?: BitFieldResolvable): number; + public static resolve(bit?: BitFieldResolvable): number; } export class Team extends Base { @@ -1548,7 +1551,7 @@ declare module 'discord.js' { export class UserFlags extends BitField { public static FLAGS: Record; - public static resolve(bit?: BitFieldResolvable): number; + public static resolve(bit?: BitFieldResolvable): number; } export class Util { @@ -1655,7 +1658,7 @@ declare module 'discord.js' { public voiceManager: ClientVoiceManager; public disconnect(): void; public play(input: VoiceBroadcast | Readable | string, options?: StreamOptions): StreamDispatcher; - public setSpeaking(value: BitFieldResolvable): void; + public setSpeaking(value: BitFieldResolvable): void; public on(event: 'authenticated' | 'closing' | 'newSession' | 'ready' | 'reconnecting', listener: () => void): this; public on(event: 'debug', listener: (message: string) => void): this; @@ -1756,8 +1759,9 @@ declare module 'discord.js' { } export class WebhookClient extends WebhookMixin(BaseClient) { - constructor(id: string, token: string, options?: ClientOptions); + constructor(id: string, token: string, options?: WebhookClientOptions); public client: this; + public options: WebhookClientOptions; public token: string; } @@ -2157,6 +2161,7 @@ declare module 'discord.js' { UNKNOWN_GUILD_TEMPLATE: 10057; BOT_PROHIBITED_ENDPOINT: 20001; BOT_ONLY_ENDPOINT: 20002; + ANNOUNCEMENT_EDIT_LIMIT_EXCEEDED: 20022; CHANNEL_HIT_WRITE_RATELIMIT: 20028; MAXIMUM_GUILDS: 30001; MAXIMUM_FRIENDS: 30002; @@ -2323,17 +2328,17 @@ declare module 'discord.js' { type Base64String = string; - type BitFieldResolvable = - | RecursiveReadonlyArray>> + type BitFieldResolvable = + | RecursiveReadonlyArray>> | T - | number - | Readonly>; + | N + | Readonly>; type BufferResolvable = Buffer | string; interface ChannelCreationOverwrites { - allow?: PermissionResolvable | number; - deny?: PermissionResolvable | number; + allow?: PermissionResolvable; + deny?: PermissionResolvable; id: RoleResolvable | UserResolvable; } @@ -2366,8 +2371,8 @@ declare module 'discord.js' { type ChannelResolvable = Channel | Snowflake; interface ClientEvents { - channelCreate: [channel: Channel]; - channelDelete: [channel: Channel | PartialDMChannel]; + channelCreate: [channel: GuildChannel]; + channelDelete: [channel: DMChannel | GuildChannel]; channelPinsUpdate: [channel: Channel | PartialDMChannel, date: Date]; channelUpdate: [oldChannel: Channel, newChannel: Channel]; debug: [message: string]; @@ -2436,6 +2441,7 @@ declare module 'discord.js' { restSweepInterval?: number; retryLimit?: number; presence?: PresenceData; + intents: BitFieldResolvable; ws?: WebSocketOptions; http?: HTTPOptions; } @@ -2448,6 +2454,11 @@ declare module 'discord.js' { desktop?: ClientPresenceStatus; } + interface ClientUserEditData { + username?: string; + avatar?: BufferResolvable | Base64Resolvable; + } + interface CloseEvent { wasClean: boolean; code: number; @@ -2571,10 +2582,6 @@ declare module 'discord.js' { User: typeof User; } - interface FetchIntegrationsOptions { - includeApplications?: boolean; - } - interface FetchMemberOptions { user: UserResolvable; cache?: boolean; @@ -2871,7 +2878,7 @@ declare module 'discord.js' { content?: StringResolvable; embed?: MessageEmbed | MessageEmbedOptions | null; code?: string | boolean; - flags?: BitFieldResolvable; + flags?: BitFieldResolvable; allowedMentions?: MessageMentionOptions; } @@ -2999,13 +3006,13 @@ declare module 'discord.js' { type OverwriteType = 'member' | 'role'; - interface PermissionFlags extends Record {} + interface PermissionFlags extends Record {} interface PermissionObject extends Record {} interface PermissionOverwriteOption extends Partial> {} - type PermissionResolvable = BitFieldResolvable; + type PermissionResolvable = BitFieldResolvable; type PermissionString = | 'CREATE_INSTANT_INVITE' @@ -3193,9 +3200,9 @@ declare module 'discord.js' { interface RawOverwriteData { id: Snowflake; - allow: number; - deny: number; - type: OverwriteType; + allow: string; + deny: string; + type: number; } interface ReactionCollectorOptions extends CollectorOptions { @@ -3262,7 +3269,7 @@ declare module 'discord.js' { type SystemChannelFlagsString = 'WELCOME_MESSAGE_DISABLED' | 'BOOST_MESSAGE_DISABLED'; - type SystemChannelFlagsResolvable = BitFieldResolvable; + type SystemChannelFlagsResolvable = BitFieldResolvable; type SystemMessageType = Exclude; @@ -3297,6 +3304,11 @@ declare module 'discord.js' { type VoiceStatus = number; + type WebhookClientOptions = Pick< + ClientOptions, + 'allowedMentions' | 'restTimeOffset' | 'restRequestTimeout' | 'retryLimit' | 'http' + >; + interface WebhookEditData { name?: string; avatar?: BufferResolvable; @@ -3331,7 +3343,6 @@ declare module 'discord.js' { interface WebSocketOptions { large_threshold?: number; compress?: boolean; - intents?: BitFieldResolvable | number; properties?: WebSocketProperties; } diff --git a/typings/index.ts b/typings/index.ts index db7abe7c6..75dbc9beb 100644 --- a/typings/index.ts +++ b/typings/index.ts @@ -1,8 +1,10 @@ /// -import { Client, Message, MessageAttachment, MessageEmbed } from 'discord.js'; +import { Client, Intents, Message, MessageAttachment, MessageEmbed } from 'discord.js'; -const client: Client = new Client(); +const client: Client = new Client({ + intents: Intents.NON_PRIVILEGED, +}); client.on('ready', () => { console.log(`Client is logged in as ${client.user!.tag} and ready!`);