diff --git a/src/client/Client.js b/src/client/Client.js index f6848ab2b..3da2f439f 100644 --- a/src/client/Client.js +++ b/src/client/Client.js @@ -34,14 +34,7 @@ class Client extends BaseClient { constructor(options) { super(Object.assign({ _tokenType: 'Bot' }, options)); - // Obtain shard details from environment or if present, worker threads - let data = process.env; - try { - // Test if worker threads module is present and used - data = require('worker_threads').workerData || data; - } catch { - // Do nothing - } + const data = require('worker_threads').workerData ?? process.env; if (this.options.shards === DefaultOptions.shards) { if ('SHARDS' in data) { @@ -188,7 +181,7 @@ class Client extends BaseClient { * @readonly */ get readyTimestamp() { - return this.readyAt ? this.readyAt.getTime() : null; + return this.readyAt?.getTime() ?? null; } /** @@ -341,7 +334,7 @@ class Client extends BaseClient { channels++; messages += channel.messages.cache.sweep( - message => now - (message.editedTimestamp || message.createdTimestamp) > lifetimeMs, + message => now - (message.editedTimestamp ?? message.createdTimestamp) > lifetimeMs, ); } diff --git a/src/client/actions/Action.js b/src/client/actions/Action.js index 69e3b63a9..743faad0f 100644 --- a/src/client/actions/Action.js +++ b/src/client/actions/Action.js @@ -32,14 +32,14 @@ class GenericAction { } getChannel(data) { - const id = data.channel_id || data.id; + const id = data.channel_id ?? data.id; return ( - data.channel || + data.channel ?? this.getPayload( { id, guild_id: data.guild_id, - recipients: [data.author || { id: data.user_id }], + recipients: [data.author ?? { id: data.user_id }], }, this.client.channels, id, @@ -49,14 +49,14 @@ class GenericAction { } getMessage(data, channel, cache) { - const id = data.message_id || data.id; + const id = data.message_id ?? data.id; return ( - data.message || + data.message ?? this.getPayload( { id, channel_id: channel.id, - guild_id: data.guild_id || (channel.guild ? channel.guild.id : null), + guild_id: data.guild_id ?? channel.guild?.id, }, channel.messages, id, @@ -67,12 +67,12 @@ class GenericAction { } getReaction(data, message, user) { - const id = data.emoji.id || decodeURIComponent(data.emoji.name); + const id = data.emoji.id ?? decodeURIComponent(data.emoji.name); return this.getPayload( { emoji: data.emoji, count: message.partial ? null : 0, - me: user ? user.id === this.client.user.id : false, + me: user?.id === this.client.user.id, }, message.reactions, id, @@ -86,11 +86,11 @@ class GenericAction { getUser(data) { const id = data.user_id; - return data.user || this.getPayload({ id }, this.client.users, id, PartialTypes.USER); + return data.user ?? this.getPayload({ id }, this.client.users, id, PartialTypes.USER); } getUserFromMember(data) { - if (data.guild_id && data.member && data.member.user) { + if (data.guild_id && data.member?.user) { const guild = this.client.guilds.cache.get(data.guild_id); if (guild) { return guild.members.add(data.member).user; diff --git a/src/client/actions/ChannelDelete.js b/src/client/actions/ChannelDelete.js index 2956d72fa..9b3bd4cb0 100644 --- a/src/client/actions/ChannelDelete.js +++ b/src/client/actions/ChannelDelete.js @@ -12,7 +12,7 @@ class ChannelDeleteAction extends Action { handle(data) { const client = this.client; - let channel = client.channels.cache.get(data.id); + const channel = client.channels.cache.get(data.id); if (channel) { client.channels.remove(channel.id); diff --git a/src/client/actions/GuildDelete.js b/src/client/actions/GuildDelete.js index c30caedba..89877fe89 100644 --- a/src/client/actions/GuildDelete.js +++ b/src/client/actions/GuildDelete.js @@ -53,7 +53,7 @@ class GuildDeleteAction extends Action { this.deleted.set(guild.id, guild); this.scheduleForDeletion(guild.id); } else { - guild = this.deleted.get(data.id) || null; + guild = this.deleted.get(data.id) ?? null; } return { guild }; diff --git a/src/client/actions/GuildEmojisUpdate.js b/src/client/actions/GuildEmojisUpdate.js index 77119333d..7829db1f5 100644 --- a/src/client/actions/GuildEmojisUpdate.js +++ b/src/client/actions/GuildEmojisUpdate.js @@ -5,7 +5,7 @@ const Action = require('./Action'); class GuildEmojisUpdateAction extends Action { handle(data) { const guild = this.client.guilds.cache.get(data.guild_id); - if (!guild || !guild.emojis) return; + if (!guild?.emojis) return; const deletions = new Map(guild.emojis.cache); diff --git a/src/client/actions/MessageCreate.js b/src/client/actions/MessageCreate.js index ae1741598..17a7189de 100644 --- a/src/client/actions/MessageCreate.js +++ b/src/client/actions/MessageCreate.js @@ -12,7 +12,7 @@ class MessageCreateAction extends Action { if (existing) return { message: existing }; const message = channel.messages.add(data); const user = message.author; - let member = message.member; + const member = message.member; channel.lastMessageID = data.id; if (user) { user.lastMessageID = data.id; diff --git a/src/client/actions/MessageReactionAdd.js b/src/client/actions/MessageReactionAdd.js index c7b015190..6107d5dd3 100644 --- a/src/client/actions/MessageReactionAdd.js +++ b/src/client/actions/MessageReactionAdd.js @@ -31,8 +31,8 @@ class MessageReactionAdd extends Action { // Verify reaction if (message.partial && !this.client.options.partials.includes(PartialTypes.REACTION)) return false; - const existing = message.reactions.cache.get(data.emoji.id || data.emoji.name); - if (existing && existing.users.cache.has(user.id)) return { message, reaction: existing, user }; + const existing = message.reactions.cache.get(data.emoji.id ?? data.emoji.name); + if (existing?.users.cache.has(user.id)) return { message, reaction: existing, user }; const reaction = message.reactions.add({ emoji: data.emoji, count: message.partial ? null : 0, diff --git a/src/client/actions/MessageReactionRemoveEmoji.js b/src/client/actions/MessageReactionRemoveEmoji.js index 143702c00..6b2076ef0 100644 --- a/src/client/actions/MessageReactionRemoveEmoji.js +++ b/src/client/actions/MessageReactionRemoveEmoji.js @@ -13,7 +13,7 @@ class MessageReactionRemoveEmoji extends Action { const reaction = this.getReaction(data, message); if (!reaction) return false; - if (!message.partial) message.reactions.cache.delete(reaction.emoji.id || reaction.emoji.name); + if (!message.partial) message.reactions.cache.delete(reaction.emoji.id ?? reaction.emoji.name); /** * Emitted when a bot removes an emoji reaction from a cached message. diff --git a/src/client/actions/PresenceUpdate.js b/src/client/actions/PresenceUpdate.js index fd38c3cda..989c08f78 100644 --- a/src/client/actions/PresenceUpdate.js +++ b/src/client/actions/PresenceUpdate.js @@ -6,18 +6,17 @@ const { Events } = require('../../util/Constants'); class PresenceUpdateAction extends Action { handle(data) { let user = this.client.users.cache.get(data.user.id); - if (!user && data.user.username) user = this.client.users.add(data.user); + if (!user && data.user?.username) user = this.client.users.add(data.user); if (!user) return; - if (data.user && data.user.username) { + if (data.user?.username) { if (!user.equals(data.user)) this.client.actions.UserUpdate.handle(data.user); } const guild = this.client.guilds.cache.get(data.guild_id); if (!guild) return; - let oldPresence = guild.presences.cache.get(user.id); - if (oldPresence) oldPresence = oldPresence._clone(); + const oldPresence = guild.presences.cache.get(user.id)?._clone(); let member = guild.members.cache.get(user.id); if (!member && data.status !== 'offline') { member = guild.members.add({ @@ -28,7 +27,7 @@ class PresenceUpdateAction extends Action { this.client.emit(Events.GUILD_MEMBER_AVAILABLE, member); } guild.presences.add(Object.assign(data, { guild })); - if (member && this.client.listenerCount(Events.PRESENCE_UPDATE) && !member.presence.equals(oldPresence)) { + if (this.client.listenerCount(Events.PRESENCE_UPDATE) && member && !member.presence.equals(oldPresence)) { /** * Emitted whenever a guild member's presence (e.g. status, activity) is changed. * @event Client#presenceUpdate diff --git a/src/client/actions/VoiceStateUpdate.js b/src/client/actions/VoiceStateUpdate.js index 406bd2fb3..e135bbd89 100644 --- a/src/client/actions/VoiceStateUpdate.js +++ b/src/client/actions/VoiceStateUpdate.js @@ -11,9 +11,8 @@ class VoiceStateUpdate extends Action { if (guild) { const VoiceState = Structures.get('VoiceState'); // Update the state - const oldState = guild.voiceStates.cache.has(data.user_id) - ? guild.voiceStates.cache.get(data.user_id)._clone() - : new VoiceState(guild, { user_id: data.user_id }); + const oldState = + guild.voiceStates.cache.get(data.user_id)?._clone() ?? new VoiceState(guild, { user_id: data.user_id }); const newState = guild.voiceStates.add(data); @@ -21,12 +20,12 @@ class VoiceStateUpdate extends Action { let member = guild.members.cache.get(data.user_id); if (member && data.member) { member._patch(data.member); - } else if (data.member && data.member.user && data.member.joined_at) { + } else if (data.member?.user && data.member.joined_at) { member = guild.members.add(data.member); } // Emit event - if (member && member.user.id === client.user.id) { + if (member?.user.id === client.user.id) { client.emit('debug', `[VOICE] received voice state update: ${JSON.stringify(data)}`); client.voice.onVoiceStateUpdate(data); } diff --git a/src/client/websocket/WebSocketManager.js b/src/client/websocket/WebSocketManager.js index 2e54a3947..1840e453d 100644 --- a/src/client/websocket/WebSocketManager.js +++ b/src/client/websocket/WebSocketManager.js @@ -240,7 +240,7 @@ class WebSocketManager extends EventEmitter { try { await shard.connect(); } catch (error) { - if (error && error.code && UNRECOVERABLE_CLOSE_CODES.includes(error.code)) { + if (error?.code && UNRECOVERABLE_CLOSE_CODES.includes(error.code)) { throw new Error(WSCodes[error.code]); // Undefined if session is invalid, error event for regular closes } else if (!error || error.code) { diff --git a/src/client/websocket/WebSocketShard.js b/src/client/websocket/WebSocketShard.js index 2db3bd056..88a9d97c2 100644 --- a/src/client/websocket/WebSocketShard.js +++ b/src/client/websocket/WebSocketShard.js @@ -176,7 +176,7 @@ class WebSocketShard extends EventEmitter { connect() { const { gateway, client } = this.manager; - if (this.connection && this.connection.readyState === WebSocket.OPEN && this.status === Status.READY) { + if (this.connection?.readyState === WebSocket.OPEN && this.status === Status.READY) { return Promise.resolve(); } @@ -216,7 +216,7 @@ class WebSocketShard extends EventEmitter { this.once(ShardEvents.INVALID_SESSION, onInvalidOrDestroyed); this.once(ShardEvents.DESTROYED, onInvalidOrDestroyed); - if (this.connection && this.connection.readyState === WebSocket.OPEN) { + if (this.connection?.readyState === WebSocket.OPEN) { this.debug('An open connection was found, attempting an immediate identify.'); this.identify(); return; @@ -306,7 +306,7 @@ class WebSocketShard extends EventEmitter { * @private */ onError(event) { - const error = event && event.error ? event.error : event; + const error = event?.error ?? event; if (!error) return; /** @@ -345,7 +345,7 @@ class WebSocketShard extends EventEmitter { this.debug(`[CLOSE] Event Code: ${event.code} Clean : ${event.wasClean} - Reason : ${event.reason || 'No reason received'}`); + Reason : ${event.reason ?? 'No reason received'}`); this.setHeartbeatTimer(-1); this.setHelloTimeout(-1); @@ -648,7 +648,7 @@ class WebSocketShard extends EventEmitter { * @private */ _send(data) { - if (!this.connection || this.connection.readyState !== WebSocket.OPEN) { + if (this.connection?.readyState !== WebSocket.OPEN) { this.debug(`Tried to send packet '${JSON.stringify(data)}' but no WebSocket is available!`); this.destroy({ closeCode: 4000 }); return; diff --git a/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js b/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js index 4f460d6a1..35dd3ec0a 100644 --- a/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js +++ b/src/client/websocket/handlers/CHANNEL_PINS_UPDATE.js @@ -8,7 +8,7 @@ module.exports = (client, { d: data }) => { if (channel && !Number.isNaN(time.getTime())) { // Discord sends null for last_pin_timestamp if the last pinned message was removed - channel.lastPinTimestamp = time.getTime() || null; + channel.lastPinTimestamp = time.getTime() ?? null; /** * Emitted whenever the pins of a channel are updated. Due to the nature of the WebSocket event, diff --git a/src/errors/DJSError.js b/src/errors/DJSError.js index 157ca6600..af2ff0975 100644 --- a/src/errors/DJSError.js +++ b/src/errors/DJSError.js @@ -39,7 +39,7 @@ function message(key, args) { const msg = messages.get(key); if (!msg) throw new Error(`An invalid error message key was used: ${key}.`); if (typeof msg === 'function') return msg(...args); - if (args === undefined || args.length === 0) return msg; + if (!args?.length) return msg; args.unshift(msg); return String(...args); } diff --git a/src/managers/ApplicationCommandManager.js b/src/managers/ApplicationCommandManager.js index 63b4715c7..864db7f09 100644 --- a/src/managers/ApplicationCommandManager.js +++ b/src/managers/ApplicationCommandManager.js @@ -41,7 +41,7 @@ class ApplicationCommandManager extends BaseManager { */ commandPath({ id, guildID } = {}) { let path = this.client.api.applications(this.client.application.id); - if (this.guild || guildID) path = path.guilds(this.guild?.id ?? guildID); + if (this.guild ?? guildID) path = path.guilds(this.guild?.id ?? guildID); return id ? path.commands(id) : path.commands; } @@ -84,9 +84,7 @@ class ApplicationCommandManager extends BaseManager { async fetch(id, { guildID, cache = true, force = false } = {}) { if (typeof id === 'object') { ({ guildID, cache = true, force = false } = id); - id = undefined; - } - if (id) { + } else if (id) { if (!force) { const existing = this.cache.get(id); if (existing) return existing; diff --git a/src/managers/BaseGuildEmojiManager.js b/src/managers/BaseGuildEmojiManager.js index 5a188d72c..dad3e7368 100644 --- a/src/managers/BaseGuildEmojiManager.js +++ b/src/managers/BaseGuildEmojiManager.js @@ -67,7 +67,7 @@ class BaseGuildEmojiManager extends BaseManager { if (emoji instanceof ReactionEmoji) return emoji.identifier; if (typeof emoji === 'string') { const res = parseEmoji(emoji); - if (res && res.name.length) { + if (res?.name.length) { emoji = `${res.animated ? 'a:' : ''}${res.name}${res.id ? `:${res.id}` : ''}`; } if (!emoji.includes('%')) return encodeURIComponent(emoji); diff --git a/src/managers/BaseManager.js b/src/managers/BaseManager.js index 57b4018e9..ee3263869 100644 --- a/src/managers/BaseManager.js +++ b/src/managers/BaseManager.js @@ -17,7 +17,7 @@ class BaseManager { * @private * @readonly */ - Object.defineProperty(this, 'holds', { value: Structures.get(holds.name) || holds }); + Object.defineProperty(this, 'holds', { value: Structures.get(holds.name) ?? holds }); /** * The client that instantiated this Manager @@ -42,12 +42,12 @@ class BaseManager { } add(data, cache = true, { id, extras = [] } = {}) { - const existing = this.cache.get(id || data.id); - if (existing && existing._patch && cache) existing._patch(data); + const existing = this.cache.get(id ?? data.id); + if (cache) existing?._patch(data); if (existing) return existing; const entry = this.holds ? new this.holds(this.client, data, ...extras) : data; - if (cache) this.cache.set(id || entry.id, entry); + if (cache) this.cache.set(id ?? entry.id, entry); return entry; } @@ -58,7 +58,7 @@ class BaseManager { */ resolve(idOrInstance) { if (idOrInstance instanceof this.holds) return idOrInstance; - if (typeof idOrInstance === 'string') return this.cache.get(idOrInstance) || null; + if (typeof idOrInstance === 'string') return this.cache.get(idOrInstance) ?? null; return null; } diff --git a/src/managers/ChannelManager.js b/src/managers/ChannelManager.js index 84475a995..953cea454 100644 --- a/src/managers/ChannelManager.js +++ b/src/managers/ChannelManager.js @@ -22,10 +22,10 @@ class ChannelManager extends BaseManager { add(data, guild, cache = true) { const existing = this.cache.get(data.id); if (existing) { - if (existing._patch && cache) existing._patch(data); - if (guild) guild.channels?.add(existing); - if (ThreadChannelTypes.includes(existing.type) && typeof existing.parent?.threads !== 'undefined') { - existing.parent.threads.add(existing); + if (cache) existing._patch(data); + guild?.channels?.add(existing); + if (ThreadChannelTypes.includes(existing.type)) { + existing.parent?.threads?.add(existing); } return existing; } diff --git a/src/managers/GuildChannelManager.js b/src/managers/GuildChannelManager.js index 0d3eedff4..d7c060123 100644 --- a/src/managers/GuildChannelManager.js +++ b/src/managers/GuildChannelManager.js @@ -115,9 +115,10 @@ class GuildChannelManager extends BaseManager { * ], * }) */ - async create(name, options = {}) { - let { type, topic, nsfw, bitrate, userLimit, parent, permissionOverwrites, position, rateLimitPerUser, reason } = - options; + async create( + name, + { type, topic, nsfw, bitrate, userLimit, parent, permissionOverwrites, position, rateLimitPerUser, reason } = {}, + ) { if (parent) parent = this.client.channels.resolveID(parent); if (permissionOverwrites) { permissionOverwrites = permissionOverwrites.map(o => PermissionOverwrites.resolve(o, this.guild)); diff --git a/src/managers/GuildMemberManager.js b/src/managers/GuildMemberManager.js index 302cec88c..629891a65 100644 --- a/src/managers/GuildMemberManager.js +++ b/src/managers/GuildMemberManager.js @@ -269,7 +269,7 @@ class GuildMemberManager extends BaseManager { * @example * // Kick a user by ID (or with a user/guild member object) * guild.members.kick('84484653687267328') - * .then(user => console.log(`Kicked ${user.username || user.id || user} from ${guild.name}`)) + * .then(user => console.log(`Kicked ${user.username ?? user.id ?? user} from ${guild.name}`)) * .catch(console.error); */ async kick(user, reason) { @@ -356,7 +356,7 @@ class GuildMemberManager extends BaseManager { }, }); const fetchedMembers = new Collection(); - const option = query || limit || presences || user_ids; + const option = Boolean(query || limit || presences || user_ids); let i = 0; const handler = (members, _, chunk) => { timeout.refresh(); diff --git a/src/managers/GuildMemberRoleManager.js b/src/managers/GuildMemberRoleManager.js index c3f0b7bdc..1faa59e00 100644 --- a/src/managers/GuildMemberRoleManager.js +++ b/src/managers/GuildMemberRoleManager.js @@ -68,7 +68,7 @@ class GuildMemberRoleManager { * @readonly */ get premiumSubscriberRole() { - return this.cache.find(role => role.tags && role.tags.premiumSubscriberRole) || null; + return this.cache.find(role => role.tags?.premiumSubscriberRole) ?? null; } /** @@ -79,7 +79,7 @@ class GuildMemberRoleManager { */ get botRole() { if (!this.member.user.bot) return null; - return this.cache.find(role => role.tags && role.tags.botID === this.member.user.id) || null; + return this.cache.find(role => role.tags?.botID === this.member.user.id) ?? null; } /** diff --git a/src/managers/MessageManager.js b/src/managers/MessageManager.js index 9ec70ef01..78395bbf4 100644 --- a/src/managers/MessageManager.js +++ b/src/managers/MessageManager.js @@ -150,7 +150,7 @@ class MessageManager extends BaseManager { if (!message) throw new TypeError('INVALID_TYPE', 'message', 'MessageResolvable'); const data = await this.client.api.channels(this.channel.id).messages(message).crosspost.post(); - return this.cache.get(data.id) || this.add(data); + return this.cache.get(data.id) ?? this.add(data); } /** diff --git a/src/managers/PresenceManager.js b/src/managers/PresenceManager.js index c02fe0447..1835e84b2 100644 --- a/src/managers/PresenceManager.js +++ b/src/managers/PresenceManager.js @@ -40,7 +40,7 @@ class PresenceManager extends BaseManager { const presenceResolvable = super.resolve(presence); if (presenceResolvable) return presenceResolvable; const UserResolvable = this.client.users.resolveID(presence); - return super.resolve(UserResolvable) || null; + return super.resolve(UserResolvable); } /** diff --git a/src/managers/ReactionManager.js b/src/managers/ReactionManager.js index e194d8477..afafc6e84 100644 --- a/src/managers/ReactionManager.js +++ b/src/managers/ReactionManager.js @@ -19,7 +19,7 @@ class ReactionManager extends BaseManager { } add(data, cache) { - return super.add(data, cache, { id: data.emoji.id || data.emoji.name, extras: [this.message] }); + return super.add(data, cache, { id: data.emoji.id ?? data.emoji.name, extras: [this.message] }); } /** diff --git a/src/rest/DiscordAPIError.js b/src/rest/DiscordAPIError.js index cc62512a4..3137b7b30 100644 --- a/src/rest/DiscordAPIError.js +++ b/src/rest/DiscordAPIError.js @@ -7,9 +7,9 @@ class DiscordAPIError extends Error { constructor(error, status, request) { super(); - const flattened = this.constructor.flattenErrors(error.errors || error).join('\n'); + const flattened = this.constructor.flattenErrors(error.errors ?? error).join('\n'); this.name = 'DiscordAPIError'; - this.message = error.message && flattened ? `${error.message}\n${flattened}` : error.message || flattened; + this.message = error.message && flattened ? `${error.message}\n${flattened}` : error.message ?? flattened; /** * The HTTP method used for the request @@ -61,7 +61,7 @@ class DiscordAPIError extends Error { if (v._errors) { messages.push(`${newKey}: ${v._errors.map(e => e.message).join(' ')}`); - } else if (v.code || v.message) { + } else if (v.code ?? v.message) { messages.push(`${v.code ? `${v.code}: ` : ''}${v.message}`.trim()); } else if (typeof v === 'string') { messages.push(v); diff --git a/src/rest/HTTPError.js b/src/rest/HTTPError.js index cb96a2beb..f09ce5b15 100644 --- a/src/rest/HTTPError.js +++ b/src/rest/HTTPError.js @@ -18,7 +18,7 @@ class HTTPError extends Error { * HTTP error code returned from the request * @type {number} */ - this.code = code || 500; + this.code = code ?? 500; /** * The HTTP method used for the request diff --git a/src/rest/RESTManager.js b/src/rest/RESTManager.js index bd54587e1..56bf20990 100644 --- a/src/rest/RESTManager.js +++ b/src/rest/RESTManager.js @@ -30,7 +30,7 @@ class RESTManager { } getAuth() { - const token = this.client.token || this.client.accessToken; + const token = this.client.token ?? this.client.accessToken; if (token) return `${this.tokenPrefix} ${token}`; throw new Error('TOKEN_MISSING'); } diff --git a/src/sharding/Shard.js b/src/sharding/Shard.js index 59479a5ed..22bac6111 100644 --- a/src/sharding/Shard.js +++ b/src/sharding/Shard.js @@ -40,7 +40,7 @@ class Shard extends EventEmitter { * Arguments for the shard's process (only when {@link ShardingManager#mode} is `process`) * @type {string[]} */ - this.args = manager.shardArgs || []; + this.args = manager.shardArgs ?? []; /** * Arguments for the shard's process executable (only when {@link ShardingManager#mode} is `process`) @@ -127,14 +127,16 @@ class Shard extends EventEmitter { this._evals.clear(); this._fetches.clear(); + const child = this.process ?? this.worker; + /** * Emitted upon the creation of the shard's child process/worker. * @event Shard#spawn * @param {ChildProcess|Worker} process Child process/worker that was created */ - this.emit('spawn', this.process || this.worker); + this.emit('spawn', child); - if (timeout === -1 || timeout === Infinity) return this.process || this.worker; + if (timeout === -1 || timeout === Infinity) return child; await new Promise((resolve, reject) => { const cleanup = () => { clearTimeout(spawnTimeoutTimer); @@ -168,7 +170,7 @@ class Shard extends EventEmitter { this.once('disconnect', onDisconnect); this.once('death', onDeath); }); - return this.process || this.worker; + return child; } /** @@ -242,10 +244,10 @@ class Shard extends EventEmitter { if (this._fetches.has(prop)) return this._fetches.get(prop); const promise = new Promise((resolve, reject) => { - const child = this.process || this.worker; + const child = this.process ?? this.worker; const listener = message => { - if (!message || message._fetchProp !== prop) return; + if (message?._fetchProp !== prop) return; child.removeListener('message', listener); this._fetches.delete(prop); resolve(message._result); @@ -276,10 +278,10 @@ class Shard extends EventEmitter { if (this._evals.has(script)) return this._evals.get(script); const promise = new Promise((resolve, reject) => { - const child = this.process || this.worker; + const child = this.process ?? this.worker; const listener = message => { - if (!message || message._eval !== script) return; + if (message?._eval !== script) return; child.removeListener('message', listener); this._evals.delete(script); if (!message._error) resolve(message._result); @@ -388,7 +390,7 @@ class Shard extends EventEmitter { * @event Shard#death * @param {ChildProcess|Worker} process Child process/worker that exited */ - this.emit('death', this.process || this.worker); + this.emit('death', this.process ?? this.worker); this.ready = false; this.process = null; diff --git a/src/sharding/ShardClientUtil.js b/src/sharding/ShardClientUtil.js index 74baa3daf..9eb444481 100644 --- a/src/sharding/ShardClientUtil.js +++ b/src/sharding/ShardClientUtil.js @@ -109,10 +109,10 @@ class ShardClientUtil { */ fetchClientValues(prop, shard) { return new Promise((resolve, reject) => { - const parent = this.parentPort || process; + const parent = this.parentPort ?? process; const listener = message => { - if (!message || message._sFetchProp !== prop || message._sFetchPropShard !== shard) return; + if (message?._sFetchProp !== prop || message._sFetchPropShard !== shard) return; parent.removeListener('message', listener); if (!message._error) resolve(message._result); else reject(Util.makeError(message._error)); @@ -139,7 +139,7 @@ class ShardClientUtil { */ broadcastEval(script, options = {}) { return new Promise((resolve, reject) => { - const parent = this.parentPort || process; + const parent = this.parentPort ?? process; if (typeof script !== 'function') { reject(new TypeError('SHARDING_INVALID_EVAL_BROADCAST')); return; @@ -147,7 +147,7 @@ class ShardClientUtil { script = `(${script})(this, ${JSON.stringify(options.context)})`; const listener = message => { - if (!message || message._sEval !== script || message._sEvalShard !== options.shard) return; + if (message?._sEval !== script || message._sEvalShard !== options.shard) return; parent.removeListener('message', listener); if (!message._error) resolve(message._result); else reject(Util.makeError(message._error)); diff --git a/src/sharding/ShardingManager.js b/src/sharding/ShardingManager.js index 5e942c049..ee2177bea 100644 --- a/src/sharding/ShardingManager.js +++ b/src/sharding/ShardingManager.js @@ -70,7 +70,7 @@ class ShardingManager extends EventEmitter { * List of shards this sharding manager spawns * @type {string|number[]} */ - this.shardList = options.shardList || 'auto'; + this.shardList = options.shardList ?? 'auto'; if (this.shardList !== 'auto') { if (!Array.isArray(this.shardList)) { throw new TypeError('CLIENT_INVALID_OPTION', 'shardList', 'an array.'); @@ -132,7 +132,7 @@ class ShardingManager extends EventEmitter { * Token to use for obtaining the automatic shard count, and passing to shards * @type {?string} */ - this.token = options.token ? options.token.replace(/^Bot\s*/i, '') : null; + this.token = options.token?.replace(/^Bot\s*/i, '') ?? null; /** * A collection of shards that this manager has spawned diff --git a/src/structures/Channel.js b/src/structures/Channel.js index cdae8152a..083a30ee4 100644 --- a/src/structures/Channel.js +++ b/src/structures/Channel.js @@ -29,7 +29,7 @@ class Channel extends Base { * * `unknown` - a generic channel of unknown type, could be Channel or GuildChannel * @type {string} */ - this.type = type ? type.toLowerCase() : 'unknown'; + this.type = type?.toLowerCase() ?? 'unknown'; /** * Whether the channel has been deleted @@ -130,7 +130,8 @@ class Channel extends Base { channel = new PartialGroupDMChannel(client, data); } } else { - guild = guild || client.guilds.cache.get(data.guild_id); + if (!guild) guild = client.guilds.cache.get(data.guild_id); + if (guild) { switch (data.type) { case ChannelTypes.TEXT: { diff --git a/src/structures/ClientPresence.js b/src/structures/ClientPresence.js index 7feba5a16..0746f92e9 100644 --- a/src/structures/ClientPresence.js +++ b/src/structures/ClientPresence.js @@ -10,7 +10,7 @@ class ClientPresence extends Presence { * @param {APIPresence} [data={}] The data for the client presence */ constructor(client, data = {}) { - super(client, Object.assign(data, { status: data.status || 'online', user: { id: null } })); + super(client, Object.assign(data, { status: data.status ?? 'online', user: { id: null } })); } set(presence) { @@ -33,7 +33,7 @@ class ClientPresence extends Presence { activities: [], afk: typeof afk === 'boolean' ? afk : false, since: typeof since === 'number' && !Number.isNaN(since) ? since : null, - status: status || this.status, + status: status ?? this.status, }; if (activities?.length) { for (const [i, activity] of activities.entries()) { diff --git a/src/structures/ClientUser.js b/src/structures/ClientUser.js index 8a36e2435..c1b3d97ef 100644 --- a/src/structures/ClientUser.js +++ b/src/structures/ClientUser.js @@ -56,8 +56,7 @@ class ClientUser extends Structures.get('User') { 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; + return updated ?? this; } /** diff --git a/src/structures/CommandInteraction.js b/src/structures/CommandInteraction.js index 2ceafc6ae..deec0d9a2 100644 --- a/src/structures/CommandInteraction.js +++ b/src/structures/CommandInteraction.js @@ -110,17 +110,19 @@ class CommandInteraction extends Interaction { if ('value' in option) result.value = option.value; if ('options' in option) result.options = this._createOptionsCollection(option.options, resolved); - const user = resolved?.users?.[option.value]; - if (user) result.user = this.client.users.add(user); + if (resolved) { + const user = resolved.users?.[option.value]; + if (user) result.user = this.client.users.add(user); - const member = resolved?.members?.[option.value]; - if (member) result.member = this.guild?.members.add({ user, ...member }) ?? member; + const member = resolved.members?.[option.value]; + if (member) result.member = this.guild?.members.add({ user, ...member }) ?? member; - const channel = resolved?.channels?.[option.value]; - if (channel) result.channel = this.client.channels.add(channel, this.guild) ?? channel; + const channel = resolved.channels?.[option.value]; + if (channel) result.channel = this.client.channels.add(channel, this.guild) ?? channel; - const role = resolved?.roles?.[option.value]; - if (role) result.role = this.guild?.roles.add(role) ?? role; + const role = resolved.roles?.[option.value]; + if (role) result.role = this.guild?.roles.add(role) ?? role; + } return result; } diff --git a/src/structures/Emoji.js b/src/structures/Emoji.js index 48b2a8cdf..6a35ec141 100644 --- a/src/structures/Emoji.js +++ b/src/structures/Emoji.js @@ -59,8 +59,7 @@ class Emoji extends Base { * @readonly */ get url() { - if (!this.id) return null; - return this.client.rest.cdn.Emoji(this.id, this.animated ? 'gif' : 'png'); + return this.id && this.client.rest.cdn.Emoji(this.id, this.animated ? 'gif' : 'png'); } /** @@ -69,8 +68,7 @@ class Emoji extends Base { * @readonly */ get createdTimestamp() { - if (!this.id) return null; - return SnowflakeUtil.deconstruct(this.id).timestamp; + return this.id && SnowflakeUtil.deconstruct(this.id).timestamp; } /** @@ -79,8 +77,7 @@ class Emoji extends Base { * @readonly */ get createdAt() { - if (!this.id) return null; - return new Date(this.createdTimestamp); + return this.id && new Date(this.createdTimestamp); } /** diff --git a/src/structures/Guild.js b/src/structures/Guild.js index 685d422e8..0f6b60d65 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -147,13 +147,13 @@ class Guild extends AnonymousGuild { * The full amount of members in this guild * @type {number} */ - this.memberCount = data.member_count || this.memberCount; + this.memberCount = data.member_count ?? this.memberCount; /** * Whether the guild is "large" (has more than large_threshold members, 50 by default) * @type {boolean} */ - this.large = Boolean('large' in data ? data.large : this.large); + this.large = Boolean(data.large ?? this.large); /** * An array of enabled guild features, here are the possible values: @@ -282,7 +282,7 @@ class Guild extends AnonymousGuild { * You will need to fetch the guild using {@link Guild#fetch} if you want to receive this parameter * @type {?number} */ - this.maximumPresences = data.max_presences || 25000; + this.maximumPresences = data.max_presences ?? 25000; } else if (typeof this.maximumPresences === 'undefined') { this.maximumPresences = null; } @@ -406,8 +406,7 @@ class Guild extends AnonymousGuild { * @returns {?string} */ bannerURL({ format, size } = {}) { - if (!this.banner) return null; - return this.client.rest.cdn.Banner(this.id, this.banner, format, size); + return this.banner && this.client.rest.cdn.Banner(this.id, this.banner, format, size); } /** @@ -425,8 +424,7 @@ class Guild extends AnonymousGuild { * @returns {?string} */ splashURL({ format, size } = {}) { - if (!this.splash) return null; - return this.client.rest.cdn.Splash(this.id, this.splash, format, size); + return this.splash && this.client.rest.cdn.Splash(this.id, this.splash, format, size); } /** @@ -435,8 +433,7 @@ class Guild extends AnonymousGuild { * @returns {?string} */ discoverySplashURL({ format, size } = {}) { - if (!this.discoverySplash) return null; - return this.client.rest.cdn.DiscoverySplash(this.id, this.discoverySplash, format, size); + return this.discoverySplash && this.client.rest.cdn.DiscoverySplash(this.id, this.discoverySplash, format, size); } /** @@ -462,7 +459,7 @@ class Guild extends AnonymousGuild { * @readonly */ get afkChannel() { - return this.client.channels.cache.get(this.afkChannelID) || null; + return this.client.channels.resolve(this.afkChannelID); } /** @@ -471,7 +468,7 @@ class Guild extends AnonymousGuild { * @readonly */ get systemChannel() { - return this.client.channels.cache.get(this.systemChannelID) || null; + return this.client.channels.resolve(this.systemChannelID); } /** @@ -480,7 +477,7 @@ class Guild extends AnonymousGuild { * @readonly */ get widgetChannel() { - return this.client.channels.cache.get(this.widgetChannelID) || null; + return this.client.channels.resolve(this.widgetChannelID); } /** @@ -489,7 +486,7 @@ class Guild extends AnonymousGuild { * @readonly */ get rulesChannel() { - return this.client.channels.cache.get(this.rulesChannelID) || null; + return this.client.channels.resolve(this.rulesChannelID); } /** @@ -498,7 +495,7 @@ class Guild extends AnonymousGuild { * @readonly */ get publicUpdatesChannel() { - return this.client.channels.cache.get(this.publicUpdatesChannelID) || null; + return this.client.channels.resolve(this.publicUpdatesChannelID); } /** @@ -508,7 +505,7 @@ class Guild extends AnonymousGuild { */ get me() { return ( - this.members.cache.get(this.client.user.id) || + this.members.resolve(this.client.user.id) ?? (this.client.options.partials.includes(PartialTypes.GUILD_MEMBER) ? this.members.add({ user: { id: this.client.user.id } }, true) : null) @@ -917,7 +914,7 @@ class Guild extends AnonymousGuild { const welcome_channels = welcomeChannels?.map(welcomeChannelData => { const emoji = this.emojis.resolve(welcomeChannelData.emoji); return { - emoji_id: emoji?.id ?? null, + emoji_id: emoji && emoji.id, emoji_name: emoji?.name ?? welcomeChannelData.emoji, channel_id: this.channels.resolveID(welcomeChannelData.channel), description: welcomeChannelData.description, diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index afcb68316..6a8055b7d 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -332,7 +332,7 @@ class GuildAuditLogsEntry { * The reason of this entry * @type {?string} */ - this.reason = data.reason || null; + this.reason = data.reason ?? null; /** * The user that executed this entry @@ -354,9 +354,9 @@ class GuildAuditLogsEntry { /** * Specific property changes - * @type {AuditLogChange[]} + * @type {?(AuditLogChange[])} */ - this.changes = data.changes ? data.changes.map(c => ({ key: c.key, old: c.old_value, new: c.new_value })) : null; + this.changes = data.changes?.map(c => ({ key: c.key, old: c.old_value, new: c.new_value })) ?? null; /** * The ID of this entry @@ -443,7 +443,7 @@ class GuildAuditLogsEntry { this.target = null; if (targetType === Targets.UNKNOWN) { this.target = this.changes.reduce((o, c) => { - o[c.key] = c.new || c.old; + o[c.key] = c.new ?? c.old; return o; }, {}); this.target.id = data.target_id; @@ -456,12 +456,12 @@ class GuildAuditLogsEntry { this.target = guild.client.guilds.cache.get(data.target_id); } else if (targetType === Targets.WEBHOOK) { this.target = - logs.webhooks.get(data.target_id) || + logs.webhooks.get(data.target_id) ?? new Webhook( guild.client, this.changes.reduce( (o, c) => { - o[c.key] = c.new || c.old; + o[c.key] = c.new ?? c.old; return o; }, { @@ -473,13 +473,14 @@ class GuildAuditLogsEntry { } else if (targetType === Targets.INVITE) { this.target = guild.members.fetch(guild.client.user.id).then(me => { if (me.permissions.has(Permissions.FLAGS.MANAGE_GUILD)) { - const change = this.changes.find(c => c.key === 'code'); + let change = this.changes.find(c => c.key === 'code'); + change = change.new ?? change.old; return guild.fetchInvites().then(invites => { - this.target = invites.find(i => i.code === (change.new || change.old)); + this.target = invites.find(i => i.code === change); }); } else { this.target = this.changes.reduce((o, c) => { - o[c.key] = c.new || c.old; + o[c.key] = c.new ?? c.old; return o; }, {}); return this.target; @@ -489,16 +490,16 @@ class GuildAuditLogsEntry { // Discord sends a channel id for the MESSAGE_BULK_DELETE action type. this.target = data.action_type === Actions.MESSAGE_BULK_DELETE - ? guild.channels.cache.get(data.target_id) || { id: data.target_id } + ? guild.channels.cache.get(data.target_id) ?? { id: data.target_id } : guild.client.users.cache.get(data.target_id); } else if (targetType === Targets.INTEGRATION) { this.target = - logs.integrations.get(data.target_id) || + logs.integrations.get(data.target_id) ?? new Integration( guild.client, this.changes.reduce( (o, c) => { - o[c.key] = c.new || c.old; + o[c.key] = c.new ?? c.old; return o; }, { id: data.target_id }, @@ -507,10 +508,10 @@ class GuildAuditLogsEntry { ); } else if (targetType === Targets.CHANNEL) { this.target = - guild.channels.cache.get(data.target_id) || + guild.channels.cache.get(data.target_id) ?? this.changes.reduce( (o, c) => { - o[c.key] = c.new || c.old; + o[c.key] = c.new ?? c.old; return o; }, { id: data.target_id }, @@ -522,7 +523,7 @@ class GuildAuditLogsEntry { guild.client, this.changes.reduce( (o, c) => { - o[c.key] = c.new || c.old; + o[c.key] = c.new ?? c.old; return o; }, { @@ -533,7 +534,7 @@ class GuildAuditLogsEntry { ), ); } else if (data.target_id) { - this.target = guild[`${targetType.toLowerCase()}s`]?.cache.get(data.target_id) || { id: data.target_id }; + this.target = guild[`${targetType.toLowerCase()}s`]?.cache.get(data.target_id) ?? { id: data.target_id }; } } diff --git a/src/structures/GuildChannel.js b/src/structures/GuildChannel.js index 34f129e15..e0ec740ad 100644 --- a/src/structures/GuildChannel.js +++ b/src/structures/GuildChannel.js @@ -85,7 +85,7 @@ class GuildChannel extends Channel { * @readonly */ get parent() { - return this.guild.channels.cache.get(this.parentID) || null; + return this.guild.channels.resolve(this.parentID); } /** @@ -106,10 +106,10 @@ class GuildChannel extends Channel { // Handle empty overwrite if ( - (channelVal === undefined && + (!channelVal && parentVal.deny.bitfield === Permissions.defaultBit && parentVal.allow.bitfield === Permissions.defaultBit) || - (parentVal === undefined && + (!parentVal && channelVal.deny.bitfield === Permissions.defaultBit && channelVal.allow.bitfield === Permissions.defaultBit) ) { @@ -118,8 +118,8 @@ class GuildChannel extends Channel { // Compare overwrites return ( - channelVal !== undefined && - parentVal !== undefined && + typeof channelVal !== 'undefined' && + typeof parentVal !== 'undefined' && channelVal.deny.bitfield === parentVal.deny.bitfield && channelVal.allow.bitfield === parentVal.allow.bitfield ); @@ -145,15 +145,14 @@ class GuildChannel extends Channel { const member = this.guild.members.resolve(memberOrRole); if (member) return this.memberPermissions(member); const role = this.guild.roles.resolve(memberOrRole); - if (role) return this.rolePermissions(role); - return null; + return role && this.rolePermissions(role); } overwritesFor(member, verified = false, roles = null) { if (!verified) member = this.guild.members.resolve(member); if (!member) return []; - roles = roles || member.roles.cache; + if (!roles) roles = member.roles.cache; const roleOverwrites = []; let memberOverwrites; let everyoneOverwrites; @@ -192,20 +191,12 @@ class GuildChannel extends Channel { const overwrites = this.overwritesFor(member, true, roles); return permissions - .remove(overwrites.everyone ? overwrites.everyone.deny : Permissions.defaultBit) - .add(overwrites.everyone ? overwrites.everyone.allow : Permissions.defaultBit) - .remove( - overwrites.roles.length > Permissions.defaultBit - ? overwrites.roles.map(role => role.deny) - : Permissions.defaultBit, - ) - .add( - overwrites.roles.length > Permissions.defaultBit - ? overwrites.roles.map(role => role.allow) - : Permissions.defaultBit, - ) - .remove(overwrites.member ? overwrites.member.deny : Permissions.defaultBit) - .add(overwrites.member ? overwrites.member.allow : Permissions.defaultBit) + .remove(overwrites.everyone?.deny ?? Permissions.defaultBit) + .add(overwrites.everyone?.allow ?? Permissions.defaultBit) + .remove(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.deny) : Permissions.defaultBit) + .add(overwrites.roles.length > 0 ? overwrites.roles.map(role => role.allow) : Permissions.defaultBit) + .remove(overwrites.member?.deny ?? Permissions.defaultBit) + .add(overwrites.member?.allow ?? Permissions.defaultBit) .freeze(); } @@ -222,10 +213,10 @@ class GuildChannel extends Channel { const roleOverwrites = this.permissionOverwrites.get(role.id); return role.permissions - .remove(everyoneOverwrites ? everyoneOverwrites.deny : Permissions.defaultBit) - .add(everyoneOverwrites ? everyoneOverwrites.allow : Permissions.defaultBit) - .remove(roleOverwrites ? roleOverwrites.deny : Permissions.defaultBit) - .add(roleOverwrites ? roleOverwrites.allow : Permissions.defaultBit) + .remove(everyoneOverwrites?.deny ?? Permissions.defaultBit) + .add(everyoneOverwrites?.allow ?? Permissions.defaultBit) + .remove(roleOverwrites?.deny ?? Permissions.defaultBit) + .add(roleOverwrites?.allow ?? Permissions.defaultBit) .freeze(); } @@ -274,7 +265,7 @@ class GuildChannel extends Channel { * .catch(console.error); */ async updateOverwrite(userOrRole, options, overwriteOptions = {}) { - const userOrRoleID = this.guild.roles.resolveID(userOrRole) || this.client.users.resolveID(userOrRole); + const userOrRoleID = this.guild.roles.resolveID(userOrRole) ?? this.client.users.resolveID(userOrRole); const { reason } = overwriteOptions; const existing = this.permissionOverwrites.get(userOrRoleID); if (existing) { @@ -300,10 +291,10 @@ class GuildChannel extends Channel { * .catch(console.error); */ createOverwrite(userOrRole, options, overwriteOptions = {}) { - let userOrRoleID = this.guild.roles.resolveID(userOrRole) || this.client.users.resolveID(userOrRole); + let userOrRoleID = this.guild.roles.resolveID(userOrRole) ?? this.client.users.resolveID(userOrRole); let { type, reason } = overwriteOptions; if (typeof type !== 'number') { - userOrRole = this.guild.roles.resolve(userOrRole) || this.client.users.resolve(userOrRole); + 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')); userOrRoleID = userOrRole.id; type = userOrRole instanceof Role ? OverwriteTypes.role : OverwriteTypes.member; @@ -410,7 +401,7 @@ class GuildChannel extends Channel { if (data.lockPermissions) { if (data.parentID) { const newParent = this.guild.channels.resolve(data.parentID); - if (newParent && newParent.type === 'category') { + if (newParent?.type === 'category') { permission_overwrites = newParent.permissionOverwrites.map(o => PermissionOverwrites.resolve(o, this.guild)); } } else if (this.parent) { @@ -420,13 +411,13 @@ class GuildChannel extends Channel { const newData = await this.client.api.channels(this.id).patch({ data: { - name: (data.name || this.name).trim(), + name: (data.name ?? this.name).trim(), type: ChannelTypes[data.type?.toUpperCase()], topic: data.topic, nsfw: data.nsfw, - bitrate: data.bitrate || this.bitrate, - user_limit: typeof data.userLimit !== 'undefined' ? data.userLimit : this.userLimit, - rtc_region: typeof data.rtcRegion !== 'undefined' ? data.rtcRegion : this.rtcRegion, + bitrate: data.bitrate ?? this.bitrate, + user_limit: data.userLimit ?? this.userLimit, + rtc_region: data.rtcRegion ?? this.rtcRegion, parent_id: data.parentID, lock_permissions: data.lockPermissions, rate_limit_per_user: data.rateLimitPerUser, @@ -476,7 +467,7 @@ class GuildChannel extends Channel { return this.edit( { // eslint-disable-next-line no-prototype-builtins - parentID: channel !== null ? (channel.hasOwnProperty('id') ? channel.id : channel) : null, + parentID: channel?.id ?? channel ?? null, lockPermissions, }, reason, diff --git a/src/structures/GuildEmoji.js b/src/structures/GuildEmoji.js index f26367049..dc586a1e9 100644 --- a/src/structures/GuildEmoji.js +++ b/src/structures/GuildEmoji.js @@ -108,7 +108,7 @@ class GuildEmoji extends BaseGuildEmoji { * .catch(console.error); */ edit(data, reason) { - const roles = data.roles ? data.roles.map(r => r.id || r) : undefined; + const roles = data.roles?.map(r => r.id ?? r); return this.client.api .guilds(this.guild.id) .emojis(this.id) diff --git a/src/structures/GuildMember.js b/src/structures/GuildMember.js index 0f5082621..7bbaf4c89 100644 --- a/src/structures/GuildMember.js +++ b/src/structures/GuildMember.js @@ -85,7 +85,7 @@ class GuildMember extends Base { if ('nick' in data) this.nickname = data.nick; if ('joined_at' in data) this.joinedTimestamp = new Date(data.joined_at).getTime(); if ('premium_since' in data) { - this.premiumSinceTimestamp = data.premium_since === null ? null : new Date(data.premium_since).getTime(); + this.premiumSinceTimestamp = data.premium_since ? new Date(data.premium_since).getTime() : null; } if ('roles' in data) this._roles = data.roles; this.pending = data.pending ?? false; @@ -121,8 +121,7 @@ class GuildMember extends Base { * @readonly */ get lastMessage() { - const channel = this.guild.channels.cache.get(this.lastMessageChannelID); - return (channel && channel.messages.cache.get(this.lastMessageID)) || null; + return this.guild.channels.resolve(this.lastMessageChannelID)?.messages.resolve(this.lastMessageID) ?? null; } /** @@ -133,7 +132,7 @@ class GuildMember extends Base { get voice() { if (!Structures) Structures = require('../util/Structures'); const VoiceState = Structures.get('VoiceState'); - return this.guild.voiceStates.cache.get(this.id) || new VoiceState(this.guild, { user_id: this.id }); + return this.guild.voiceStates.cache.get(this.id) ?? new VoiceState(this.guild, { user_id: this.id }); } /** @@ -163,7 +162,7 @@ class GuildMember extends Base { if (!Structures) Structures = require('../util/Structures'); const Presence = Structures.get('Presence'); return ( - this.guild.presences.cache.get(this.id) || + this.guild.presences.cache.get(this.id) ?? new Presence(this.client, { user: { id: this.id, @@ -179,8 +178,7 @@ class GuildMember extends Base { * @readonly */ get displayColor() { - const role = this.roles.color; - return (role && role.color) || 0; + return this.roles.color?.color ?? 0; } /** @@ -189,8 +187,7 @@ class GuildMember extends Base { * @readonly */ get displayHexColor() { - const role = this.roles.color; - return (role && role.hexColor) || '#000000'; + return this.roles.color?.hexColor ?? '#000000'; } /** @@ -208,7 +205,7 @@ class GuildMember extends Base { * @readonly */ get displayName() { - return this.nickname || this.user.username; + return this.nickname ?? this.user.username; } /** diff --git a/src/structures/GuildPreview.js b/src/structures/GuildPreview.js index adaa07e78..57bacd27a 100644 --- a/src/structures/GuildPreview.js +++ b/src/structures/GuildPreview.js @@ -75,7 +75,7 @@ class GuildPreview extends Base { * The description for this guild * @type {?string} */ - this.description = data.description || null; + this.description = data.description ?? null; if (!this.emojis) { /** @@ -97,8 +97,7 @@ class GuildPreview extends Base { * @returns {?string} */ splashURL({ format, size } = {}) { - if (!this.splash) return null; - return this.client.rest.cdn.Splash(this.id, this.splash, format, size); + return this.splash && this.client.rest.cdn.Splash(this.id, this.splash, format, size); } /** @@ -107,8 +106,7 @@ class GuildPreview extends Base { * @returns {?string} */ discoverySplashURL({ format, size } = {}) { - if (!this.discoverySplash) return null; - return this.client.rest.cdn.DiscoverySplash(this.id, this.discoverySplash, format, size); + return this.discoverySplash && this.client.rest.cdn.DiscoverySplash(this.id, this.discoverySplash, format, size); } /** @@ -117,8 +115,7 @@ class GuildPreview extends Base { * @returns {?string} */ iconURL({ format, size, dynamic } = {}) { - if (!this.icon) return null; - return this.client.rest.cdn.Icon(this.id, this.icon, format, size, dynamic); + return this.icon && this.client.rest.cdn.Icon(this.id, this.icon, format, size, dynamic); } /** diff --git a/src/structures/GuildTemplate.js b/src/structures/GuildTemplate.js index ed4034130..064018981 100644 --- a/src/structures/GuildTemplate.js +++ b/src/structures/GuildTemplate.js @@ -202,7 +202,7 @@ class GuildTemplate extends Base { * @readonly */ get guild() { - return this.client.guilds.cache.get(this.guildID) || null; + return this.client.guilds.resolve(this.guildID); } /** diff --git a/src/structures/Integration.js b/src/structures/Integration.js index 2fc005cf4..237d1c2a2 100644 --- a/src/structures/Integration.js +++ b/src/structures/Integration.js @@ -90,7 +90,7 @@ class Integration extends Base { */ get roles() { const roles = this.guild.roles.cache; - return roles.filter(role => role.tags && role.tags.integrationID === this.id); + return roles.filter(role => role.tags?.integrationID === this.id); } _patch(data) { diff --git a/src/structures/Invite.js b/src/structures/Invite.js index e72082aaa..dcfecb02a 100644 --- a/src/structures/Invite.js +++ b/src/structures/Invite.js @@ -40,37 +40,37 @@ class Invite extends Base { * The approximate number of online members of the guild this invite is for * @type {?number} */ - this.presenceCount = 'approximate_presence_count' in data ? data.approximate_presence_count : null; + this.presenceCount = data.approximate_presence_count ?? null; /** * The approximate total number of members of the guild this invite is for * @type {?number} */ - this.memberCount = 'approximate_member_count' in data ? data.approximate_member_count : null; + this.memberCount = data.approximate_member_count ?? null; /** * Whether or not this invite is temporary * @type {?boolean} */ - this.temporary = 'temporary' in data ? data.temporary : null; + this.temporary = data.temporary ?? null; /** * The maximum age of the invite, in seconds, 0 if never expires * @type {?number} */ - this.maxAge = 'max_age' in data ? data.max_age : null; + this.maxAge = data.max_age ?? null; /** * How many times this invite has been used * @type {?number} */ - this.uses = 'uses' in data ? data.uses : null; + this.uses = data.uses ?? null; /** * The maximum uses of this invite * @type {?number} */ - this.maxUses = 'max_uses' in data ? data.max_uses : null; + this.maxUses = data.max_uses ?? null; /** * The user who created this invite @@ -103,7 +103,7 @@ class Invite extends Base { * The target type * @type {?TargetType} */ - this.targetType = typeof data.target_type === 'number' ? data.target_type : null; + this.targetType = data.target_type ?? null; /** * The channel the invite is for diff --git a/src/structures/Message.js b/src/structures/Message.js index 683caaf92..9cbb86915 100644 --- a/src/structures/Message.js +++ b/src/structures/Message.js @@ -133,13 +133,13 @@ class Message extends Base { * A list of embeds in the message - e.g. YouTube Player * @type {MessageEmbed[]} */ - this.embeds = (data.embeds || []).map(e => new Embed(e, true)); + this.embeds = data.embeds?.map(e => new Embed(e, true)) ?? []; /** * A list of MessageActionRows in the message * @type {MessageActionRow[]} */ - this.components = (data.components ?? []).map(c => BaseMessageComponent.create(c, this.client)); + this.components = data.components?.map(c => BaseMessageComponent.create(c, this.client)) ?? []; /** * A collection of attachments in the message - e.g. Pictures - mapped by their ID @@ -180,7 +180,7 @@ class Message extends Base { * @type {ReactionManager} */ this.reactions = new ReactionManager(this); - if (data.reactions && data.reactions.length > 0) { + if (data.reactions?.length > 0) { for (const reaction of data.reactions) { this.reactions.add(reaction); } @@ -203,7 +203,7 @@ class Message extends Base { * ID of the webhook that sent the message, if applicable * @type {?Snowflake} */ - this.webhookID = data.webhook_id || null; + this.webhookID = data.webhook_id ?? null; /** * Supplemental application information for group activities @@ -312,10 +312,6 @@ class Message extends Base { if ('pinned' in data) this.pinned = data.pinned; if ('tts' in data) this.tts = data.tts; if ('thread' in data) this.thread = this.client.channels.add(data.thread); - if ('embeds' in data) this.embeds = data.embeds.map(e => new Embed(e, true)); - else this.embeds = this.embeds.slice(); - if ('components' in data) this.components = data.components.map(c => BaseMessageComponent.create(c, this.client)); - else this.components = this.components.slice(); if ('attachments' in data) { this.attachments = new Collection(); @@ -326,16 +322,19 @@ class Message extends Base { this.attachments = new Collection(this.attachments); } + this.embeds = data.embeds?.map(e => new Embed(e, true)) ?? this.embeds.slice(); + this.components = data.components?.map(c => BaseMessageComponent.create(c, this.client)) ?? this.components.slice(); + this.mentions = new Mentions( this, - 'mentions' in data ? data.mentions : this.mentions.users, - 'mention_roles' in data ? data.mention_roles : this.mentions.roles, - 'mention_everyone' in data ? data.mention_everyone : this.mentions.everyone, - 'mention_channels' in data ? data.mention_channels : this.mentions.crosspostedChannels, + data.mentions ?? this.mentions.users, + data.mention_roles ?? this.mentions.roles, + data.mention_everyone ?? this.mentions.everyone, + data.mention_channels ?? this.mentions.crosspostedChannels, data.referenced_message?.author ?? this.mentions.repliedUser, ); - this.flags = new MessageFlags('flags' in data ? data.flags : 0).freeze(); + this.flags = new MessageFlags(data.flags ?? 0).freeze(); return clone; } @@ -347,7 +346,7 @@ class Message extends Base { * @readonly */ get member() { - return this.guild ? this.guild.members.resolve(this.author) || null : null; + return this.guild?.members.resolve(this.author) ?? null; } /** @@ -374,7 +373,7 @@ class Message extends Base { * @readonly */ get guild() { - return this.channel.guild || null; + return this.channel.guild ?? null; } /** @@ -434,7 +433,7 @@ class Message extends Base { return new Promise((resolve, reject) => { const collector = this.createReactionCollector(options); collector.once('end', (reactions, reason) => { - if (options.errors && options.errors.includes(reason)) reject(reactions); + if (options.errors?.includes(reason)) reject(reactions); else resolve(reactions); }); }); diff --git a/src/structures/MessageActionRow.js b/src/structures/MessageActionRow.js index 219e27e08..fffbb73a8 100644 --- a/src/structures/MessageActionRow.js +++ b/src/structures/MessageActionRow.js @@ -45,7 +45,7 @@ class MessageActionRow extends BaseMessageComponent { * The components in this action row * @type {MessageActionRowComponent[]} */ - this.components = (data.components ?? []).map(c => BaseMessageComponent.create(c, null, true)); + this.components = data.components?.map(c => BaseMessageComponent.create(c, null, true)) ?? []; } /** diff --git a/src/structures/MessageAttachment.js b/src/structures/MessageAttachment.js index 7120c79f0..829c1f751 100644 --- a/src/structures/MessageAttachment.js +++ b/src/structures/MessageAttachment.js @@ -72,13 +72,13 @@ class MessageAttachment { * The height of this attachment (if an image or video) * @type {?number} */ - this.height = typeof data.height !== 'undefined' ? data.height : null; + this.height = data.height ?? null; /** * The width of this attachment (if an image or video) * @type {?number} */ - this.width = typeof data.width !== 'undefined' ? data.width : null; + this.width = data.width ?? null; /** * This media type of this attachment diff --git a/src/structures/MessageCollector.js b/src/structures/MessageCollector.js index 68dc3737a..09f4ffb7a 100644 --- a/src/structures/MessageCollector.js +++ b/src/structures/MessageCollector.js @@ -114,7 +114,7 @@ class MessageCollector extends Collector { * @returns {void} */ _handleGuildDeletion(guild) { - if (this.channel.guild && guild.id === this.channel.guild.id) { + if (guild.id === this.channel.guild?.id) { this.stop('guildDelete'); } } diff --git a/src/structures/MessageComponentInteractionCollector.js b/src/structures/MessageComponentInteractionCollector.js index d59a52d72..2ca3561ac 100644 --- a/src/structures/MessageComponentInteractionCollector.js +++ b/src/structures/MessageComponentInteractionCollector.js @@ -36,7 +36,7 @@ class MessageComponentInteractionCollector extends Collector { * The source channel from which to collect message component interactions * @type {TextChannel|DMChannel|NewsChannel} */ - this.channel = this.message ? this.message.channel : source; + this.channel = this.message?.channel ?? source; /** * The users which have interacted to components on this collector diff --git a/src/structures/MessageEmbed.js b/src/structures/MessageEmbed.js index 0a223b883..d05a20d05 100644 --- a/src/structures/MessageEmbed.js +++ b/src/structures/MessageEmbed.js @@ -46,25 +46,25 @@ class MessageEmbed { * @type {string} * @deprecated */ - this.type = data.type || 'rich'; + this.type = data.type ?? 'rich'; /** * The title of this embed * @type {?string} */ - this.title = 'title' in data ? data.title : null; + this.title = data.title ?? null; /** * The description of this embed * @type {?string} */ - this.description = 'description' in data ? data.description : null; + this.description = data.description ?? null; /** * The URL of this embed * @type {?string} */ - this.url = 'url' in data ? data.url : null; + this.url = data.url ?? null; /** * The color of this embed @@ -111,7 +111,7 @@ class MessageEmbed { this.thumbnail = data.thumbnail ? { url: data.thumbnail.url, - proxyURL: data.thumbnail.proxyURL || data.thumbnail.proxy_url, + proxyURL: data.thumbnail.proxyURL ?? data.thumbnail.proxy_url, height: data.thumbnail.height, width: data.thumbnail.width, } @@ -133,7 +133,7 @@ class MessageEmbed { this.image = data.image ? { url: data.image.url, - proxyURL: data.image.proxyURL || data.image.proxy_url, + proxyURL: data.image.proxyURL ?? data.image.proxy_url, height: data.image.height, width: data.image.width, } @@ -156,7 +156,7 @@ class MessageEmbed { this.video = data.video ? { url: data.video.url, - proxyURL: data.video.proxyURL || data.video.proxy_url, + proxyURL: data.video.proxyURL ?? data.video.proxy_url, height: data.video.height, width: data.video.width, } @@ -179,8 +179,8 @@ class MessageEmbed { ? { name: data.author.name, url: data.author.url, - iconURL: data.author.iconURL || data.author.icon_url, - proxyIconURL: data.author.proxyIconURL || data.author.proxy_icon_url, + iconURL: data.author.iconURL ?? data.author.icon_url, + proxyIconURL: data.author.proxyIconURL ?? data.author.proxy_icon_url, } : null; @@ -217,8 +217,8 @@ class MessageEmbed { this.footer = data.footer ? { text: data.footer.text, - iconURL: data.footer.iconURL || data.footer.icon_url, - proxyIconURL: data.footer.proxyIconURL || data.footer.proxy_icon_url, + iconURL: data.footer.iconURL ?? data.footer.icon_url, + proxyIconURL: data.footer.proxyIconURL ?? data.footer.proxy_icon_url, } : null; } @@ -395,24 +395,20 @@ class MessageEmbed { type: 'rich', description: this.description, url: this.url, - timestamp: this.timestamp ? new Date(this.timestamp) : null, + timestamp: this.timestamp && new Date(this.timestamp), color: this.color, fields: this.fields, thumbnail: this.thumbnail, image: this.image, - author: this.author - ? { - name: this.author.name, - url: this.author.url, - icon_url: this.author.iconURL, - } - : null, - footer: this.footer - ? { - text: this.footer.text, - icon_url: this.footer.iconURL, - } - : null, + author: this.author && { + name: this.author.name, + url: this.author.url, + icon_url: this.author.iconURL, + }, + footer: this.footer && { + text: this.footer.text, + icon_url: this.footer.iconURL, + }, }; } @@ -447,11 +443,7 @@ class MessageEmbed { return fields .flat(2) .map(field => - this.normalizeField( - field && field.name, - field && field.value, - field && typeof field.inline === 'boolean' ? field.inline : false, - ), + this.normalizeField(field.name, field.value, typeof field.inline === 'boolean' ? field.inline : false), ); } } diff --git a/src/structures/MessageMentions.js b/src/structures/MessageMentions.js index af16eabb4..65e9fdfae 100644 --- a/src/structures/MessageMentions.js +++ b/src/structures/MessageMentions.js @@ -117,7 +117,7 @@ class MessageMentions { this.crosspostedChannels.set(d.id, { channelID: d.id, guildID: d.guild_id, - type: type ? type.toLowerCase() : 'unknown', + type: type?.toLowerCase() ?? 'unknown', name: d.name, }); } @@ -191,11 +191,9 @@ class MessageMentions { if (!ignoreDirect) { const id = - this.client.users.resolveID(data) || - (this.guild && this.guild.roles.resolveID(data)) || - this.client.channels.resolveID(data); + this.guild?.roles.resolveID(data) ?? this.client.channels.resolveID(data) ?? this.client.users.resolveID(data); - return this.users.has(id) || this.channels.has(id) || this.roles.has(id); + return typeof id === 'string' && (this.users.has(id) || this.channels.has(id) || this.roles.has(id)); } return false; diff --git a/src/structures/MessagePayload.js b/src/structures/MessagePayload.js index ae2229548..d53fb4f46 100644 --- a/src/structures/MessagePayload.js +++ b/src/structures/MessagePayload.js @@ -147,7 +147,7 @@ class MessagePayload { let username; let avatarURL; if (isWebhook) { - username = this.options.username || this.target.name; + username = this.options.username ?? this.target.name; if (this.options.avatarURL) avatarURL = this.options.avatarURL; } @@ -239,7 +239,7 @@ class MessagePayload { name = findName(attachment); } else { attachment = fileLike.attachment; - name = fileLike.name || findName(attachment); + name = fileLike.name ?? findName(attachment); } const resource = await DataResolver.resolveFile(attachment); diff --git a/src/structures/MessageReaction.js b/src/structures/MessageReaction.js index e59a7345d..4744cbef6 100644 --- a/src/structures/MessageReaction.js +++ b/src/structures/MessageReaction.js @@ -105,9 +105,9 @@ class MessageReaction { */ async fetch() { const message = await this.message.fetch(); - const existing = message.reactions.cache.get(this.emoji.id || this.emoji.name); + const existing = message.reactions.cache.get(this.emoji.id ?? this.emoji.name); // The reaction won't get set when it has been completely removed - this._patch(existing || { count: 0 }); + this._patch(existing ?? { count: 0 }); return this; } @@ -128,7 +128,7 @@ class MessageReaction { if (!this.me || user.id !== this.message.client.user.id) this.count--; if (user.id === this.message.client.user.id) this.me = false; if (this.count <= 0 && this.users.cache.size === 0) { - this.message.reactions.cache.delete(this.emoji.id || this.emoji.name); + this.message.reactions.cache.delete(this.emoji.id ?? this.emoji.name); } } } diff --git a/src/structures/PartialGroupDMChannel.js b/src/structures/PartialGroupDMChannel.js index be677c517..4950fcb3b 100644 --- a/src/structures/PartialGroupDMChannel.js +++ b/src/structures/PartialGroupDMChannel.js @@ -30,8 +30,7 @@ class PartialGroupDMChannel extends Channel { * @returns {?string} */ iconURL({ format, size } = {}) { - if (!this.icon) return null; - return this.client.rest.cdn.GDMIcon(this.id, this.icon, format, size); + return this.icon && this.client.rest.cdn.GDMIcon(this.id, this.icon, format, size); } delete() { diff --git a/src/structures/PermissionOverwrites.js b/src/structures/PermissionOverwrites.js index 2be0ef71f..224d20a0f 100644 --- a/src/structures/PermissionOverwrites.js +++ b/src/structures/PermissionOverwrites.js @@ -181,7 +181,7 @@ class PermissionOverwrites { }; } - const userOrRole = guild.roles.resolve(overwrite.id) || guild.client.users.resolve(overwrite.id); + 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 ? OverwriteTypes.role : OverwriteTypes.member; diff --git a/src/structures/Presence.js b/src/structures/Presence.js index 30d874a33..d700e9ed5 100644 --- a/src/structures/Presence.js +++ b/src/structures/Presence.js @@ -55,7 +55,7 @@ class Presence { * The guild of this presence * @type {?Guild} */ - this.guild = data.guild || null; + this.guild = data.guild ?? null; this.patch(data); } @@ -66,7 +66,7 @@ class Presence { * @readonly */ get user() { - return this.client.users.cache.get(this.userID) || null; + return this.client.users.resolve(this.userID); } /** @@ -75,7 +75,7 @@ class Presence { * @readonly */ get member() { - return this.guild.members.cache.get(this.userID) || null; + return this.guild.members.resolve(this.userID); } patch(data) { @@ -83,19 +83,13 @@ class Presence { * The status of this presence * @type {PresenceStatus} */ - this.status = data.status || this.status || 'offline'; + this.status = data.status ?? this.status ?? 'offline'; - if (data.activities) { - /** - * The activities of this presence - * @type {Activity[]} - */ - this.activities = data.activities.map(activity => new Activity(this, activity)); - } else if (data.activity || data.game) { - this.activities = [new Activity(this, data.game || data.activity)]; - } else { - this.activities = []; - } + /** + * The activities of this presence + * @type {Activity[]} + */ + this.activities = data.activities?.map(activity => new Activity(this, activity)) ?? []; /** * The devices this presence is on @@ -104,14 +98,14 @@ class Presence { * @property {?ClientPresenceStatus} mobile The current presence in the mobile application * @property {?ClientPresenceStatus} desktop The current presence in the desktop application */ - this.clientStatus = data.client_status || null; + this.clientStatus = data.client_status ?? null; return this; } _clone() { const clone = Object.assign(Object.create(this), this); - if (this.activities) clone.activities = this.activities.map(activity => activity._clone()); + clone.activities = this.activities.map(activity => activity._clone()); return clone; } @@ -127,9 +121,9 @@ class Presence { this.status === presence.status && this.activities.length === presence.activities.length && this.activities.every((activity, index) => activity.equals(presence.activities[index])) && - this.clientStatus.web === presence.clientStatus.web && - this.clientStatus.mobile === presence.clientStatus.mobile && - this.clientStatus.desktop === presence.clientStatus.desktop) + this.clientStatus?.web === presence.clientStatus?.web && + this.clientStatus?.mobile === presence.clientStatus?.mobile && + this.clientStatus?.desktop === presence.clientStatus?.desktop) ); } @@ -175,25 +169,25 @@ class Activity { * If the activity is being streamed, a link to the stream * @type {?string} */ - this.url = data.url || null; + this.url = data.url ?? null; /** * Details about the activity * @type {?string} */ - this.details = data.details || null; + this.details = data.details ?? null; /** * State of the activity * @type {?string} */ - this.state = data.state || null; + this.state = data.state ?? null; /** * Application ID associated with this activity * @type {?Snowflake} */ - this.applicationID = data.application_id || null; + this.applicationID = data.application_id ?? null; /** * Timestamps for the activity @@ -226,7 +220,7 @@ class Activity { * @property {?string} id ID of the party * @property {number[]} size Size of the party as `[current, max]` */ - this.party = data.party || null; + this.party = data.party ?? null; /** * Assets for rich presence @@ -315,25 +309,25 @@ class RichPresenceAssets { * Hover text for the large image * @type {?string} */ - this.largeText = assets.large_text || null; + this.largeText = assets.large_text ?? null; /** * Hover text for the small image * @type {?string} */ - this.smallText = assets.small_text || null; + this.smallText = assets.small_text ?? null; /** * ID of the large image asset * @type {?Snowflake} */ - this.largeImage = assets.large_image || null; + this.largeImage = assets.large_image ?? null; /** * ID of the small image asset * @type {?Snowflake} */ - this.smallImage = assets.small_image || null; + this.smallImage = assets.small_image ?? null; } /** @@ -342,11 +336,13 @@ class RichPresenceAssets { * @returns {?string} The small image URL */ smallImageURL({ format, size } = {}) { - if (!this.smallImage) return null; - return this.activity.presence.client.rest.cdn.AppAsset(this.activity.applicationID, this.smallImage, { - format, - size, - }); + return ( + this.smallImage && + this.activity.presence.client.rest.cdn.AppAsset(this.activity.applicationID, this.smallImage, { + format, + size, + }) + ); } /** diff --git a/src/structures/ReactionCollector.js b/src/structures/ReactionCollector.js index d275dbc35..500eecb06 100644 --- a/src/structures/ReactionCollector.js +++ b/src/structures/ReactionCollector.js @@ -183,7 +183,7 @@ class ReactionCollector extends Collector { * @returns {void} */ _handleGuildDeletion(guild) { - if (this.message.guild && guild.id === this.message.guild.id) { + if (guild.id === this.message.guild?.id) { this.stop('guildDelete'); } } @@ -194,7 +194,7 @@ class ReactionCollector extends Collector { * @returns {Snowflake|string} */ static key(reaction) { - return reaction.emoji.id || reaction.emoji.name; + return reaction.emoji.id ?? reaction.emoji.name; } } diff --git a/src/structures/Role.js b/src/structures/Role.js index 65dbdd760..d932246cf 100644 --- a/src/structures/Role.js +++ b/src/structures/Role.js @@ -215,11 +215,11 @@ class Role extends Base { return this.client.api.guilds[this.guild.id].roles[this.id] .patch({ data: { - name: data.name || this.name, - color: data.color !== null ? Util.resolveColor(data.color || this.color) : null, - hoist: typeof data.hoist !== 'undefined' ? data.hoist : this.hoist, + name: data.name ?? this.name, + color: data.color !== null ? Util.resolveColor(data.color ?? this.color) : null, + hoist: data.hoist ?? this.hoist, permissions: typeof data.permissions !== 'undefined' ? new Permissions(data.permissions) : this.permissions, - mentionable: typeof data.mentionable !== 'undefined' ? data.mentionable : this.mentionable, + mentionable: data.mentionable ?? this.mentionable, }, reason, }) diff --git a/src/structures/Team.js b/src/structures/Team.js index 1f04ba757..df16654db 100644 --- a/src/structures/Team.js +++ b/src/structures/Team.js @@ -32,13 +32,13 @@ class Team extends Base { * The Team's icon hash * @type {?string} */ - this.icon = data.icon || null; + this.icon = data.icon ?? null; /** * The Team's owner id * @type {?string} */ - this.ownerID = data.owner_user_id || null; + this.ownerID = data.owner_user_id ?? null; /** * The Team's members @@ -58,7 +58,7 @@ class Team extends Base { * @readonly */ get owner() { - return this.members.get(this.ownerID) || null; + return this.members.get(this.ownerID) ?? null; } /** diff --git a/src/structures/ThreadChannel.js b/src/structures/ThreadChannel.js index 5b893c09c..352de6a4c 100644 --- a/src/structures/ThreadChannel.js +++ b/src/structures/ThreadChannel.js @@ -197,7 +197,7 @@ class ThreadChannel extends Channel { async edit(data, reason) { const newData = await this.client.api.channels(this.id).patch({ data: { - name: (data.name || this.name).trim(), + name: (data.name ?? this.name).trim(), archived: data.archived, auto_archive_duration: data.autoArchiveDuration, rate_limit_per_user: data.rateLimitPerUser, diff --git a/src/structures/User.js b/src/structures/User.js index 351c31918..d336a1c62 100644 --- a/src/structures/User.js +++ b/src/structures/User.js @@ -141,8 +141,7 @@ class User extends Base { * @readonly */ get lastMessage() { - const channel = this.client.channels.cache.get(this.lastMessageChannelID); - return (channel && channel.messages.cache.get(this.lastMessageID)) || null; + return this.client.channels.resolve(this.lastMessageChannelID)?.messages.resolve(this.lastMessageID) ?? null; } /** @@ -185,7 +184,7 @@ class User extends Base { * @returns {string} */ displayAvatarURL(options) { - return this.avatarURL(options) || this.defaultAvatarURL; + return this.avatarURL(options) ?? this.defaultAvatarURL; } /** @@ -203,8 +202,7 @@ class User extends Base { * @returns {boolean} */ typingIn(channel) { - channel = this.client.channels.resolve(channel); - return channel._typing.has(this.id); + return this.client.channels.resolve(channel)._typing.has(this.id); } /** @@ -223,8 +221,7 @@ class User extends Base { * @returns {number} */ typingDurationIn(channel) { - channel = this.client.channels.resolve(channel); - return channel._typing.has(this.id) ? channel._typing.get(this.id).elapsedTime : -1; + return this.client.channels.resolve(channel)._typing.get(this.id)?.elapsedTime ?? -1; } /** @@ -233,7 +230,7 @@ class User extends Base { * @readonly */ get dmChannel() { - return this.client.channels.cache.find(c => c.type === 'dm' && c.recipient.id === this.id) || null; + return this.client.channels.cache.find(c => c.type === 'dm' && c.recipient.id === this.id) ?? null; } /** diff --git a/src/structures/VoiceState.js b/src/structures/VoiceState.js index 96583a9ed..9fcb2f3e0 100644 --- a/src/structures/VoiceState.js +++ b/src/structures/VoiceState.js @@ -31,42 +31,42 @@ class VoiceState extends Base { * Whether this member is deafened server-wide * @type {?boolean} */ - this.serverDeaf = 'deaf' in data ? data.deaf : null; + this.serverDeaf = data.deaf ?? null; /** * Whether this member is muted server-wide * @type {?boolean} */ - this.serverMute = 'mute' in data ? data.mute : null; + this.serverMute = data.mute ?? null; /** * Whether this member is self-deafened * @type {?boolean} */ - this.selfDeaf = 'self_deaf' in data ? data.self_deaf : null; + this.selfDeaf = data.self_deaf ?? null; /** * Whether this member is self-muted * @type {?boolean} */ - this.selfMute = 'self_mute' in data ? data.self_mute : null; + this.selfMute = data.self_mute ?? null; /** * Whether this member's camera is enabled * @type {?boolean} */ - this.selfVideo = 'self_video' in data ? data.self_video : null; + this.selfVideo = data.self_video ?? null; /** * The session ID of this member's connection * @type {?string} */ - this.sessionID = 'session_id' in data ? data.session_id : null; + this.sessionID = data.session_id ?? null; /** * Whether this member is streaming using "Go Live" * @type {boolean} */ - this.streaming = data.self_stream || false; + this.streaming = data.self_stream ?? false; /** * The ID of the voice or stage channel that this member is in * @type {?Snowflake} */ - this.channelID = data.channel_id || null; + this.channelID = data.channel_id ?? null; /** * Whether this member is suppressed from speaking. This property is specific to stage channels only. * @type {boolean} @@ -88,7 +88,7 @@ class VoiceState extends Base { * @readonly */ get member() { - return this.guild.members.cache.get(this.id) || null; + return this.guild.members.cache.get(this.id) ?? null; } /** @@ -97,7 +97,7 @@ class VoiceState extends Base { * @readonly */ get channel() { - return this.guild.channels.cache.get(this.channelID) || null; + return this.guild.channels.cache.get(this.channelID) ?? null; } /** @@ -125,7 +125,7 @@ class VoiceState extends Base { * @returns {Promise} */ setMute(mute, reason) { - return this.member ? this.member.edit({ mute }, reason) : Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER')); + return this.member?.edit({ mute }, reason) ?? Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER')); } /** @@ -135,7 +135,7 @@ class VoiceState extends Base { * @returns {Promise} */ setDeaf(deaf, reason) { - return this.member ? this.member.edit({ deaf }, reason) : Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER')); + return this.member?.edit({ deaf }, reason) ?? Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER')); } /** @@ -155,9 +155,7 @@ class VoiceState extends Base { * @returns {Promise} */ setChannel(channel, reason) { - return this.member - ? this.member.edit({ channel }, reason) - : Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER')); + return this.member?.edit({ channel }, reason) ?? Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER')); } /** @@ -173,8 +171,7 @@ class VoiceState extends Base { * @returns {Promise} */ async setRequestToSpeak(request) { - const channel = this.channel; - if (channel?.type !== 'stage') throw new Error('VOICE_NOT_STAGE_CHANNEL'); + if (this.channel?.type !== 'stage') throw new Error('VOICE_NOT_STAGE_CHANNEL'); if (this.client.user.id !== this.id) throw new Error('VOICE_STATE_NOT_OWN'); @@ -206,8 +203,7 @@ class VoiceState extends Base { async setSuppressed(suppressed) { if (typeof suppressed !== 'boolean') throw new TypeError('VOICE_STATE_INVALID_TYPE', 'suppressed'); - const channel = this.channel; - if (channel?.type !== 'stage') throw new Error('VOICE_NOT_STAGE_CHANNEL'); + if (this.channel?.type !== 'stage') throw new Error('VOICE_NOT_STAGE_CHANNEL'); const target = this.client.user.id === this.id ? '@me' : this.id; diff --git a/src/structures/Webhook.js b/src/structures/Webhook.js index ccf1514a1..0ed8a5522 100644 --- a/src/structures/Webhook.js +++ b/src/structures/Webhook.js @@ -34,7 +34,7 @@ class Webhook { * @name Webhook#token * @type {?string} */ - Object.defineProperty(this, 'token', { value: data.token || null, writable: true, configurable: true }); + Object.defineProperty(this, 'token', { value: data.token ?? null, writable: true, configurable: true }); /** * The avatar for the webhook @@ -175,11 +175,7 @@ class Webhook { query: { thread_id: messagePayload.options.threadID, wait: true }, auth: false, }) - .then(d => { - const channel = this.client.channels ? this.client.channels.cache.get(d.channel_id) : undefined; - if (!channel) return d; - return channel.messages.add(d, false); - }); + .then(d => this.client.channels?.cache.get(d.channel_id)?.messages.add(d, false) ?? d); } /** diff --git a/src/structures/interfaces/Collector.js b/src/structures/interfaces/Collector.js index ddd3e52ea..31ad91902 100644 --- a/src/structures/interfaces/Collector.js +++ b/src/structures/interfaces/Collector.js @@ -212,11 +212,11 @@ class Collector extends EventEmitter { resetTimer({ time, idle } = {}) { if (this._timeout) { this.client.clearTimeout(this._timeout); - this._timeout = this.client.setTimeout(() => this.stop('time'), time || this.options.time); + this._timeout = this.client.setTimeout(() => this.stop('time'), time ?? this.options.time); } if (this._idletimeout) { this.client.clearTimeout(this._idletimeout); - this._idletimeout = this.client.setTimeout(() => this.stop('idle'), idle || this.options.idle); + this._idletimeout = this.client.setTimeout(() => this.stop('idle'), idle ?? this.options.idle); } } diff --git a/src/structures/interfaces/TextBasedChannel.js b/src/structures/interfaces/TextBasedChannel.js index cc471068d..581400a5c 100644 --- a/src/structures/interfaces/TextBasedChannel.js +++ b/src/structures/interfaces/TextBasedChannel.js @@ -39,7 +39,7 @@ class TextBasedChannel { * @readonly */ get lastMessage() { - return this.messages.cache.get(this.lastMessageID) || null; + return this.messages.resolve(this.lastMessageID); } /** @@ -185,7 +185,7 @@ class TextBasedChannel { if (typeof count !== 'undefined' && count < 1) throw new RangeError('TYPING_COUNT'); if (this.client.user._typing.has(this.id)) { const entry = this.client.user._typing.get(this.id); - entry.count = count || entry.count + 1; + entry.count = count ?? entry.count + 1; return entry.promise; } @@ -193,7 +193,7 @@ class TextBasedChannel { entry.promise = new Promise((resolve, reject) => { const endpoint = this.client.api.channels[this.id].typing; Object.assign(entry, { - count: count || 1, + count: count ?? 1, interval: this.client.setInterval(() => { endpoint.post().catch(error => { this.client.clearInterval(entry.interval); @@ -252,8 +252,7 @@ class TextBasedChannel { * @readonly */ get typingCount() { - if (this.client.user._typing.has(this.id)) return this.client.user._typing.get(this.id).count; - return 0; + return this.client.user._typing.get(this.id)?.count ?? 0; } /** @@ -294,7 +293,7 @@ class TextBasedChannel { return new Promise((resolve, reject) => { const collector = this.createMessageCollector(options); collector.once('end', (collection, reason) => { - if (options.errors && options.errors.includes(reason)) { + if (options.errors?.includes(reason)) { reject(collection); } else { resolve(collection); @@ -355,7 +354,7 @@ class TextBasedChannel { */ async bulkDelete(messages, filterOld = false) { if (Array.isArray(messages) || messages instanceof Collection) { - let messageIDs = messages instanceof Collection ? messages.keyArray() : messages.map(m => m.id || m); + let messageIDs = messages instanceof Collection ? messages.keyArray() : messages.map(m => m.id ?? m); if (filterOld) { messageIDs = messageIDs.filter(id => Date.now() - SnowflakeUtil.deconstruct(id).timestamp < 1209600000); } diff --git a/src/util/Structures.js b/src/util/Structures.js index 325b9e4e6..edfe79e2d 100644 --- a/src/util/Structures.js +++ b/src/util/Structures.js @@ -85,7 +85,7 @@ class Structures { if (!(extended.prototype instanceof structures[structure])) { const prototype = Object.getPrototypeOf(extended); - const received = `${extended.name || 'unnamed'}${prototype.name ? ` extends ${prototype.name}` : ''}`; + const received = `${extended.name ?? 'unnamed'}${prototype.name ? ` extends ${prototype.name}` : ''}`; throw new Error( 'The class/prototype returned from the extender function must extend the existing structure class/prototype' + ` (received function ${received}; expected extension of ${structures[structure].name}).`, diff --git a/src/util/Util.js b/src/util/Util.js index 92e24fb98..7a56595b7 100644 --- a/src/util/Util.js +++ b/src/util/Util.js @@ -289,9 +289,8 @@ class Util { static parseEmoji(text) { if (text.includes('%')) text = decodeURIComponent(text); if (!text.includes(':')) return { animated: false, name: text, id: null }; - const m = text.match(/?/); - if (!m) return null; - return { animated: Boolean(m[1]), name: m[2], id: m[3] || null }; + const match = text.match(/?/); + return match && { animated: Boolean(match[1]), name: match[2], id: match[3] ?? null }; } /** @@ -460,7 +459,7 @@ class Util { if (typeof color === 'string') { if (color === 'RANDOM') return Math.floor(Math.random() * (0xffffff + 1)); if (color === 'DEFAULT') return 0; - color = Colors[color] || parseInt(color.replace('#', ''), 16); + color = Colors[color] ?? parseInt(color.replace('#', ''), 16); } else if (Array.isArray(color)) { color = (color[0] << 16) + (color[1] << 8) + color[2]; } @@ -511,7 +510,7 @@ class Util { * @private */ static basename(path, ext) { - let res = parse(path); + const res = parse(path); return ext && res.ext.startsWith(ext) ? res.name : res.base.split('?')[0]; } diff --git a/test/voice.js b/test/voice.js index 847bcb525..565456cc5 100644 --- a/test/voice.js +++ b/test/voice.js @@ -40,7 +40,7 @@ client.on('message', m => { if (!m.guild) return; if (m.author.id !== '66564597481480192') return; if (m.content.startsWith('/join')) { - const channel = m.guild.channels.cache.get(m.content.split(' ')[1]) || m.member.voice.channel; + const channel = m.guild.channels.cache.get(m.content.split(' ')[1]) ?? m.member.voice.channel; if (channel && channel.type === 'voice') { channel.join().then(conn => { conn.receiver.createStream(m.author, true).on('data', b => console.log(b.toString()));