mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-12 09:33:32 +01:00
chore: consistency/prettier (#3852)
* chore: consistency/prettier * chore: rebase * chore: rebase * chore: include typings * fix: include typings file in prettier lint-staged
This commit is contained in:
@@ -3,8 +3,8 @@
|
||||
require('setimmediate');
|
||||
const EventEmitter = require('events');
|
||||
const RESTManager = require('../rest/RESTManager');
|
||||
const Util = require('../util/Util');
|
||||
const { DefaultOptions } = require('../util/Constants');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* The base class for all clients.
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
'use strict';
|
||||
|
||||
const BaseClient = require('./BaseClient');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const ActionsManager = require('./actions/ActionsManager');
|
||||
const ClientVoiceManager = require('./voice/ClientVoiceManager');
|
||||
const WebSocketManager = require('./websocket/WebSocketManager');
|
||||
const ActionsManager = require('./actions/ActionsManager');
|
||||
const Collection = require('../util/Collection');
|
||||
const { Error, TypeError, RangeError } = require('../errors');
|
||||
const ChannelManager = require('../managers/ChannelManager');
|
||||
const GuildEmojiManager = require('../managers/GuildEmojiManager');
|
||||
const GuildManager = require('../managers/GuildManager');
|
||||
const UserManager = require('../managers/UserManager');
|
||||
const ShardClientUtil = require('../sharding/ShardClientUtil');
|
||||
const ClientApplication = require('../structures/ClientApplication');
|
||||
const Invite = require('../structures/Invite');
|
||||
const VoiceRegion = require('../structures/VoiceRegion');
|
||||
const Webhook = require('../structures/Webhook');
|
||||
const Invite = require('../structures/Invite');
|
||||
const ClientApplication = require('../structures/ClientApplication');
|
||||
const ShardClientUtil = require('../sharding/ShardClientUtil');
|
||||
const UserManager = require('../managers/UserManager');
|
||||
const ChannelManager = require('../managers/ChannelManager');
|
||||
const GuildManager = require('../managers/GuildManager');
|
||||
const GuildEmojiManager = require('../managers/GuildEmojiManager');
|
||||
const Collection = require('../util/Collection');
|
||||
const { Events, browser, DefaultOptions } = require('../util/Constants');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const Structures = require('../util/Structures');
|
||||
const { Error, TypeError, RangeError } = require('../errors');
|
||||
|
||||
/**
|
||||
* The main hub for interacting with the Discord API, and the starting point for any bot.
|
||||
@@ -63,9 +63,11 @@ class Client extends BaseClient {
|
||||
if (typeofShards === 'number') this.options.shards = [this.options.shards];
|
||||
|
||||
if (Array.isArray(this.options.shards)) {
|
||||
this.options.shards = [...new Set(
|
||||
this.options.shards.filter(item => !isNaN(item) && item >= 0 && item < Infinity && item === (item | 0)),
|
||||
)];
|
||||
this.options.shards = [
|
||||
...new Set(
|
||||
this.options.shards.filter(item => !isNaN(item) && item >= 0 && item < Infinity && item === (item | 0)),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
this._validateOptions();
|
||||
@@ -93,9 +95,10 @@ class Client extends BaseClient {
|
||||
* Shard helpers for the client (only if the process was spawned from a {@link ShardingManager})
|
||||
* @type {?ShardClientUtil}
|
||||
*/
|
||||
this.shard = !browser && process.env.SHARDING_MANAGER ?
|
||||
ShardClientUtil.singleton(this, process.env.SHARDING_MANAGER_MODE) :
|
||||
null;
|
||||
this.shard =
|
||||
!browser && process.env.SHARDING_MANAGER
|
||||
? ShardClientUtil.singleton(this, process.env.SHARDING_MANAGER_MODE)
|
||||
: null;
|
||||
|
||||
/**
|
||||
* All of the {@link User} objects that have been cached at any point, mapped by their IDs
|
||||
@@ -198,8 +201,12 @@ class Client extends BaseClient {
|
||||
async login(token = this.token) {
|
||||
if (!token || typeof token !== 'string') throw new Error('TOKEN_INVALID');
|
||||
this.token = token = token.replace(/^(Bot|Bearer)\s*/i, '');
|
||||
this.emit(Events.DEBUG,
|
||||
`Provided token: ${token.split('.').map((val, i) => i > 1 ? val.replace(/./g, '*') : val).join('.')}`,
|
||||
this.emit(
|
||||
Events.DEBUG,
|
||||
`Provided token: ${token
|
||||
.split('.')
|
||||
.map((val, i) => (i > 1 ? val.replace(/./g, '*') : val))
|
||||
.join('.')}`,
|
||||
);
|
||||
|
||||
if (this.options.presence) {
|
||||
@@ -238,7 +245,9 @@ class Client extends BaseClient {
|
||||
*/
|
||||
fetchInvite(invite) {
|
||||
const code = DataResolver.resolveInviteCode(invite);
|
||||
return this.api.invites(code).get({ query: { with_counts: true } })
|
||||
return this.api
|
||||
.invites(code)
|
||||
.get({ query: { with_counts: true } })
|
||||
.then(data => new Invite(this, data));
|
||||
}
|
||||
|
||||
@@ -253,7 +262,10 @@ class Client extends BaseClient {
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetchWebhook(id, token) {
|
||||
return this.api.webhooks(id, token).get().then(data => new Webhook(this, data));
|
||||
return this.api
|
||||
.webhooks(id, token)
|
||||
.get()
|
||||
.then(data => new Webhook(this, data));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -289,7 +301,7 @@ class Client extends BaseClient {
|
||||
throw new TypeError('INVALID_TYPE', 'lifetime', 'number');
|
||||
}
|
||||
if (lifetime <= 0) {
|
||||
this.emit(Events.DEBUG, 'Didn\'t sweep messages - lifetime is unlimited');
|
||||
this.emit(Events.DEBUG, "Didn't sweep messages - lifetime is unlimited");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -307,8 +319,10 @@ class Client extends BaseClient {
|
||||
);
|
||||
}
|
||||
|
||||
this.emit(Events.DEBUG,
|
||||
`Swept ${messages} messages older than ${lifetime} seconds in ${channels} text-based channels`);
|
||||
this.emit(
|
||||
Events.DEBUG,
|
||||
`Swept ${messages} messages older than ${lifetime} seconds in ${channels} text-based channels`,
|
||||
);
|
||||
return messages;
|
||||
}
|
||||
|
||||
@@ -317,7 +331,9 @@ class Client extends BaseClient {
|
||||
* @returns {Promise<ClientApplication>}
|
||||
*/
|
||||
fetchApplication() {
|
||||
return this.api.oauth2.applications('@me').get()
|
||||
return this.api.oauth2
|
||||
.applications('@me')
|
||||
.get()
|
||||
.then(app => new ClientApplication(this, app));
|
||||
}
|
||||
|
||||
@@ -364,14 +380,12 @@ class Client extends BaseClient {
|
||||
* @param {ClientOptions} [options=this.options] Options to validate
|
||||
* @private
|
||||
*/
|
||||
_validateOptions(options = this.options) { // eslint-disable-line complexity
|
||||
_validateOptions(options = this.options) {
|
||||
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');
|
||||
}
|
||||
if (options.shards &&
|
||||
!(options.shards === 'auto' || Array.isArray(options.shards))
|
||||
) {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'shards', '\'auto\', a number or array of numbers');
|
||||
if (options.shards && !(options.shards === 'auto' || Array.isArray(options.shards))) {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'shards', "'auto', a number or array of numbers");
|
||||
}
|
||||
if (options.shards && !options.shards.length) throw new RangeError('CLIENT_INVALID_PROVIDED_SHARDS');
|
||||
if (typeof options.messageCacheMaxSize !== 'number' || isNaN(options.messageCacheMaxSize)) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const Webhook = require('../structures/Webhook');
|
||||
const BaseClient = require('./BaseClient');
|
||||
const Webhook = require('../structures/Webhook');
|
||||
|
||||
/**
|
||||
* The webhook client.
|
||||
|
||||
@@ -33,38 +33,65 @@ class GenericAction {
|
||||
|
||||
getChannel(data) {
|
||||
const id = data.channel_id || data.id;
|
||||
return data.channel || this.getPayload({
|
||||
id,
|
||||
guild_id: data.guild_id,
|
||||
recipients: [data.author || { id: data.user_id }],
|
||||
}, this.client.channels, id, PartialTypes.CHANNEL);
|
||||
return (
|
||||
data.channel ||
|
||||
this.getPayload(
|
||||
{
|
||||
id,
|
||||
guild_id: data.guild_id,
|
||||
recipients: [data.author || { id: data.user_id }],
|
||||
},
|
||||
this.client.channels,
|
||||
id,
|
||||
PartialTypes.CHANNEL,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
getMessage(data, channel, cache) {
|
||||
const id = data.message_id || data.id;
|
||||
return data.message || this.getPayload({
|
||||
id,
|
||||
channel_id: channel.id,
|
||||
guild_id: data.guild_id || (channel.guild ? channel.guild.id : null),
|
||||
}, channel.messages, id, PartialTypes.MESSAGE, cache);
|
||||
return (
|
||||
data.message ||
|
||||
this.getPayload(
|
||||
{
|
||||
id,
|
||||
channel_id: channel.id,
|
||||
guild_id: data.guild_id || (channel.guild ? channel.guild.id : null),
|
||||
},
|
||||
channel.messages,
|
||||
id,
|
||||
PartialTypes.MESSAGE,
|
||||
cache,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
getReaction(data, message, user) {
|
||||
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,
|
||||
}, message.reactions, id, PartialTypes.REACTION);
|
||||
return this.getPayload(
|
||||
{
|
||||
emoji: data.emoji,
|
||||
count: message.partial ? null : 0,
|
||||
me: user ? user.id === this.client.user.id : false,
|
||||
},
|
||||
message.reactions,
|
||||
id,
|
||||
PartialTypes.REACTION,
|
||||
);
|
||||
}
|
||||
|
||||
getMember(data, guild) {
|
||||
const id = data.user.id;
|
||||
return this.getPayload({
|
||||
user: {
|
||||
id,
|
||||
return this.getPayload(
|
||||
{
|
||||
user: {
|
||||
id,
|
||||
},
|
||||
},
|
||||
}, guild.members, id, PartialTypes.GUILD_MEMBER);
|
||||
guild.members,
|
||||
id,
|
||||
PartialTypes.GUILD_MEMBER,
|
||||
);
|
||||
}
|
||||
|
||||
getUser(data) {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const Action = require('./Action');
|
||||
const { Events } = require('../../util/Constants');
|
||||
const DMChannel = require('../../structures/DMChannel');
|
||||
const { Events } = require('../../util/Constants');
|
||||
|
||||
class ChannelDeleteAction extends Action {
|
||||
constructor(client) {
|
||||
|
||||
@@ -17,4 +17,3 @@ class GuildIntegrationsUpdate extends Action {
|
||||
}
|
||||
|
||||
module.exports = GuildIntegrationsUpdate;
|
||||
|
||||
|
||||
@@ -27,5 +27,4 @@ class GuildMemberRemoveAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = GuildMemberRemoveAction;
|
||||
|
||||
@@ -22,5 +22,4 @@ class GuildRoleCreate extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = GuildRoleCreate;
|
||||
|
||||
@@ -27,5 +27,4 @@ class GuildRoleDeleteAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = GuildRoleDeleteAction;
|
||||
|
||||
@@ -36,5 +36,4 @@ class GuildRoleUpdateAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = GuildRoleUpdateAction;
|
||||
|
||||
@@ -30,5 +30,4 @@ class GuildUpdateAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = GuildUpdateAction;
|
||||
|
||||
@@ -36,5 +36,4 @@ class MessageCreateAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = MessageCreateAction;
|
||||
|
||||
@@ -26,5 +26,4 @@ class MessageDeleteAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = MessageDeleteAction;
|
||||
|
||||
@@ -13,10 +13,14 @@ class MessageDeleteBulkAction extends Action {
|
||||
const ids = data.ids;
|
||||
const messages = new Collection();
|
||||
for (const id of ids) {
|
||||
const message = this.getMessage({
|
||||
id,
|
||||
guild_id: data.guild_id,
|
||||
}, channel, false);
|
||||
const message = this.getMessage(
|
||||
{
|
||||
id,
|
||||
guild_id: data.guild_id,
|
||||
},
|
||||
channel,
|
||||
false,
|
||||
);
|
||||
if (message) {
|
||||
message.deleted = true;
|
||||
messages.set(message.id, message);
|
||||
@@ -36,5 +40,4 @@ class MessageDeleteBulkAction extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = MessageDeleteBulkAction;
|
||||
|
||||
@@ -41,5 +41,4 @@ class MessageReactionRemove extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = MessageReactionRemove;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const Action = require('./Action');
|
||||
const { Events } = require('../../util/Constants');
|
||||
const VoiceState = require('../../structures/VoiceState');
|
||||
const { Events } = require('../../util/Constants');
|
||||
|
||||
class VoiceStateUpdate extends Action {
|
||||
handle(data) {
|
||||
@@ -10,9 +10,9 @@ class VoiceStateUpdate extends Action {
|
||||
const guild = client.guilds.cache.get(data.guild_id);
|
||||
if (guild) {
|
||||
// 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.has(data.user_id)
|
||||
? guild.voiceStates.cache.get(data.user_id)._clone()
|
||||
: new VoiceState(guild, { user_id: data.user_id });
|
||||
|
||||
const newState = guild.voiceStates.add(data);
|
||||
|
||||
@@ -41,5 +41,4 @@ class VoiceStateUpdate extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = VoiceStateUpdate;
|
||||
|
||||
@@ -16,5 +16,4 @@ class WebhooksUpdate extends Action {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = WebhooksUpdate;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const Collection = require('../../util/Collection');
|
||||
const VoiceConnection = require('./VoiceConnection');
|
||||
const VoiceBroadcast = require('./VoiceBroadcast');
|
||||
const VoiceConnection = require('./VoiceConnection');
|
||||
const { Error } = require('../../errors');
|
||||
const Collection = require('../../util/Collection');
|
||||
|
||||
/**
|
||||
* Manages voice connections for the client
|
||||
@@ -83,7 +83,8 @@ class ClientVoiceManager {
|
||||
} else {
|
||||
connection = new VoiceConnection(this, channel);
|
||||
connection.on('debug', msg =>
|
||||
this.client.emit('debug', `[VOICE (${channel.guild.id}:${connection.status})]: ${msg}`));
|
||||
this.client.emit('debug', `[VOICE (${channel.guild.id}:${connection.status})]: ${msg}`),
|
||||
);
|
||||
connection.authenticate();
|
||||
this.connections.set(channel.guild.id, connection);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
const EventEmitter = require('events');
|
||||
const BroadcastAudioPlayer = require('./player/BroadcastAudioPlayer');
|
||||
const { Events } = require('../../util/Constants');
|
||||
const PlayInterface = require('./util/PlayInterface');
|
||||
const { Events } = require('../../util/Constants');
|
||||
|
||||
/**
|
||||
* A voice broadcast can be played across multiple voice connections for improved shared-stream efficiency.
|
||||
@@ -59,8 +59,9 @@ class VoiceBroadcast extends EventEmitter {
|
||||
* broadcast.play('http://www.sample-videos.com/audio/mp3/wave.mp3');
|
||||
* @returns {BroadcastDispatcher}
|
||||
*/
|
||||
play() { return null; }
|
||||
|
||||
play() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ends the broadcast, unsubscribing all subscribed channels and deleting the broadcast
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
'use strict';
|
||||
|
||||
const VoiceWebSocket = require('./networking/VoiceWebSocket');
|
||||
const EventEmitter = require('events');
|
||||
const VoiceUDP = require('./networking/VoiceUDPClient');
|
||||
const Util = require('../../util/Util');
|
||||
const { OPCodes, VoiceOPCodes, VoiceStatus, Events } = require('../../util/Constants');
|
||||
const VoiceWebSocket = require('./networking/VoiceWebSocket');
|
||||
const AudioPlayer = require('./player/AudioPlayer');
|
||||
const VoiceReceiver = require('./receiver/Receiver');
|
||||
const EventEmitter = require('events');
|
||||
const { Error } = require('../../errors');
|
||||
const PlayInterface = require('./util/PlayInterface');
|
||||
const Speaking = require('../../util/Speaking');
|
||||
const Silence = require('./util/Silence');
|
||||
const { Error } = require('../../errors');
|
||||
const { OPCodes, VoiceOPCodes, VoiceStatus, Events } = require('../../util/Constants');
|
||||
const Speaking = require('../../util/Speaking');
|
||||
const Util = require('../../util/Util');
|
||||
|
||||
// Workaround for Discord now requiring silence to be sent before being able to receive audio
|
||||
class SingleSilence extends Silence {
|
||||
@@ -20,11 +20,7 @@ class SingleSilence extends Silence {
|
||||
}
|
||||
}
|
||||
|
||||
const SUPPORTED_MODES = [
|
||||
'xsalsa20_poly1305_lite',
|
||||
'xsalsa20_poly1305_suffix',
|
||||
'xsalsa20_poly1305',
|
||||
];
|
||||
const SUPPORTED_MODES = ['xsalsa20_poly1305_lite', 'xsalsa20_poly1305_suffix', 'xsalsa20_poly1305'];
|
||||
|
||||
/**
|
||||
* Represents a connection to a guild's voice server.
|
||||
@@ -154,16 +150,18 @@ class VoiceConnection extends EventEmitter {
|
||||
if (this.speaking.equals(value)) return;
|
||||
if (this.status !== VoiceStatus.CONNECTED) return;
|
||||
this.speaking = new Speaking(value).freeze();
|
||||
this.sockets.ws.sendPacket({
|
||||
op: VoiceOPCodes.SPEAKING,
|
||||
d: {
|
||||
speaking: this.speaking.bitfield,
|
||||
delay: 0,
|
||||
ssrc: this.authentication.ssrc,
|
||||
},
|
||||
}).catch(e => {
|
||||
this.emit('debug', e);
|
||||
});
|
||||
this.sockets.ws
|
||||
.sendPacket({
|
||||
op: VoiceOPCodes.SPEAKING,
|
||||
d: {
|
||||
speaking: this.speaking.bitfield,
|
||||
delay: 0,
|
||||
ssrc: this.authentication.ssrc,
|
||||
},
|
||||
})
|
||||
.catch(e => {
|
||||
this.emit('debug', e);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -181,19 +179,25 @@ class VoiceConnection extends EventEmitter {
|
||||
* @private
|
||||
*/
|
||||
sendVoiceStateUpdate(options = {}) {
|
||||
options = Util.mergeDefault({
|
||||
guild_id: this.channel.guild.id,
|
||||
channel_id: this.channel.id,
|
||||
self_mute: this.voice ? this.voice.selfMute : false,
|
||||
self_deaf: this.voice ? this.voice.selfDeaf : false,
|
||||
}, options);
|
||||
options = Util.mergeDefault(
|
||||
{
|
||||
guild_id: this.channel.guild.id,
|
||||
channel_id: this.channel.id,
|
||||
self_mute: this.voice ? this.voice.selfMute : false,
|
||||
self_deaf: this.voice ? this.voice.selfDeaf : false,
|
||||
},
|
||||
options,
|
||||
);
|
||||
|
||||
this.emit('debug', `Sending voice state update: ${JSON.stringify(options)}`);
|
||||
|
||||
return this.channel.guild.shard.send({
|
||||
op: OPCodes.VOICE_STATE_UPDATE,
|
||||
d: options,
|
||||
}, true);
|
||||
return this.channel.guild.shard.send(
|
||||
{
|
||||
op: OPCodes.VOICE_STATE_UPDATE,
|
||||
d: options,
|
||||
},
|
||||
true,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -318,8 +322,7 @@ class VoiceConnection extends EventEmitter {
|
||||
*/
|
||||
authenticate() {
|
||||
this.sendVoiceStateUpdate();
|
||||
this.connectTimeout = this.client.setTimeout(
|
||||
() => this.authenticateFailed('VOICE_CONNECTION_TIMEOUT'), 15000);
|
||||
this.connectTimeout = this.client.setTimeout(() => this.authenticateFailed('VOICE_CONNECTION_TIMEOUT'), 15000);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -371,7 +374,6 @@ class VoiceConnection extends EventEmitter {
|
||||
this.emit('disconnect');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cleans up after disconnect.
|
||||
* @private
|
||||
@@ -513,7 +515,7 @@ class VoiceConnection extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
play() { } // eslint-disable-line no-empty-function
|
||||
play() {} // eslint-disable-line no-empty-function
|
||||
}
|
||||
|
||||
PlayInterface.applyToClass(VoiceConnection);
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
const VolumeInterface = require('../util/VolumeInterface');
|
||||
const { Writable } = require('stream');
|
||||
|
||||
const secretbox = require('../util/Secretbox');
|
||||
const Silence = require('../util/Silence');
|
||||
const VolumeInterface = require('../util/VolumeInterface');
|
||||
|
||||
const FRAME_LENGTH = 20;
|
||||
const CHANNELS = 2;
|
||||
const TIMESTAMP_INC = (48000 / 100) * CHANNELS;
|
||||
|
||||
const MAX_NONCE_SIZE = (2 ** 32) - 1;
|
||||
const MAX_NONCE_SIZE = 2 ** 32 - 1;
|
||||
const nonce = Buffer.alloc(24);
|
||||
|
||||
/**
|
||||
@@ -31,10 +30,7 @@ const nonce = Buffer.alloc(24);
|
||||
* @extends {WritableStream}
|
||||
*/
|
||||
class StreamDispatcher extends Writable {
|
||||
constructor(
|
||||
player,
|
||||
{ seek = 0, volume = 1, fec, plp, bitrate = 96, highWaterMark = 12 } = {},
|
||||
streams) {
|
||||
constructor(player, { seek = 0, volume = 1, fec, plp, bitrate = 96, highWaterMark = 12 } = {}, streams) {
|
||||
const streamOptions = { seek, volume, fec, plp, bitrate, highWaterMark };
|
||||
super(streamOptions);
|
||||
/**
|
||||
@@ -146,7 +142,9 @@ class StreamDispatcher extends Writable {
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get paused() { return Boolean(this.pausedSince); }
|
||||
get paused() {
|
||||
return Boolean(this.pausedSince);
|
||||
}
|
||||
|
||||
/**
|
||||
* Total time that this dispatcher has been paused in milliseconds
|
||||
@@ -233,7 +231,7 @@ class StreamDispatcher extends Writable {
|
||||
done();
|
||||
};
|
||||
if (!this.streams.broadcast) {
|
||||
const next = FRAME_LENGTH + (this.count * FRAME_LENGTH) - (Date.now() - this.startTime - this._pausedTime);
|
||||
const next = FRAME_LENGTH + this.count * FRAME_LENGTH - (Date.now() - this.startTime - this._pausedTime);
|
||||
setTimeout(() => {
|
||||
if ((!this.pausedSince || this._silence) && this._writeCallback) this._writeCallback();
|
||||
}, next);
|
||||
@@ -261,10 +259,7 @@ class StreamDispatcher extends Writable {
|
||||
this._nonce++;
|
||||
if (this._nonce > MAX_NONCE_SIZE) this._nonce = 0;
|
||||
this._nonceBuffer.writeUInt32BE(this._nonce, 0);
|
||||
return [
|
||||
secretbox.methods.close(buffer, this._nonceBuffer, secret_key),
|
||||
this._nonceBuffer.slice(0, 4),
|
||||
];
|
||||
return [secretbox.methods.close(buffer, this._nonceBuffer, secret_key), this._nonceBuffer.slice(0, 4)];
|
||||
} else if (mode === 'xsalsa20_poly1305_suffix') {
|
||||
const random = secretbox.methods.random(24);
|
||||
return [secretbox.methods.close(buffer, random, secret_key), random];
|
||||
@@ -297,11 +292,10 @@ class StreamDispatcher extends Writable {
|
||||
this.emit('debug', 'Failed to send a packet - no UDP socket');
|
||||
return;
|
||||
}
|
||||
this.player.voiceConnection.sockets.udp.send(packet)
|
||||
.catch(e => {
|
||||
this._setSpeaking(0);
|
||||
this.emit('debug', `Failed to send a packet - ${e}`);
|
||||
});
|
||||
this.player.voiceConnection.sockets.udp.send(packet).catch(e => {
|
||||
this._setSpeaking(0);
|
||||
this.emit('debug', `Failed to send a packet - ${e}`);
|
||||
});
|
||||
}
|
||||
|
||||
_setSpeaking(value) {
|
||||
@@ -316,14 +310,18 @@ class StreamDispatcher extends Writable {
|
||||
this.emit('speaking', value);
|
||||
}
|
||||
|
||||
get volumeEditable() { return Boolean(this.streams.volume); }
|
||||
get volumeEditable() {
|
||||
return Boolean(this.streams.volume);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the Opus bitrate of this stream is editable
|
||||
* @type {boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get bitrateEditable() { return this.streams.opus && this.streams.opus.setBitrate; }
|
||||
get bitrateEditable() {
|
||||
return this.streams.opus && this.streams.opus.setBitrate;
|
||||
}
|
||||
|
||||
// Volume
|
||||
get volume() {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const udp = require('dgram');
|
||||
const { VoiceOPCodes } = require('../../../util/Constants');
|
||||
const EventEmitter = require('events');
|
||||
const { Error } = require('../../../errors');
|
||||
const { VoiceOPCodes } = require('../../../util/Constants');
|
||||
|
||||
/**
|
||||
* Represents a UDP client for a Voice Connection.
|
||||
@@ -90,7 +90,7 @@ class VoiceConnectionUDPClient extends EventEmitter {
|
||||
|
||||
async createUDPSocket(address) {
|
||||
this.discordAddress = address;
|
||||
const socket = this.socket = udp.createSocket('udp4');
|
||||
const socket = (this.socket = udp.createSocket('udp4'));
|
||||
socket.on('error', e => {
|
||||
this.emit('debug', `[UDP] Error: ${e}`);
|
||||
this.emit('error', e);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const { OPCodes, VoiceOPCodes } = require('../../../util/Constants');
|
||||
const EventEmitter = require('events');
|
||||
const { Error } = require('../../../errors');
|
||||
const WebSocket = require('../../../WebSocket');
|
||||
const { Error } = require('../../../errors');
|
||||
const { OPCodes, VoiceOPCodes } = require('../../../util/Constants');
|
||||
|
||||
/**
|
||||
* Represents a Voice Connection's WebSocket.
|
||||
@@ -92,7 +92,8 @@ class VoiceWebSocket extends EventEmitter {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) throw new Error('WS_NOT_OPEN', data);
|
||||
this.ws.send(data, null, error => {
|
||||
if (error) reject(error); else resolve(data);
|
||||
if (error) reject(error);
|
||||
else resolve(data);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,17 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const EventEmitter = require('events').EventEmitter;
|
||||
const EventEmitter = require('events');
|
||||
const { Readable: ReadableStream } = require('stream');
|
||||
const prism = require('prism-media');
|
||||
const StreamDispatcher = require('../dispatcher/StreamDispatcher');
|
||||
|
||||
const FFMPEG_ARGUMENTS = [
|
||||
'-analyzeduration', '0',
|
||||
'-loglevel', '0',
|
||||
'-f', 's16le',
|
||||
'-ar', '48000',
|
||||
'-ac', '2',
|
||||
];
|
||||
const FFMPEG_ARGUMENTS = ['-analyzeduration', '0', '-loglevel', '0', '-f', 's16le', '-ar', '48000', '-ac', '2'];
|
||||
|
||||
/**
|
||||
* An Audio Player for a Voice Connection.
|
||||
@@ -61,7 +55,7 @@ class BasePlayer extends EventEmitter {
|
||||
|
||||
playPCMStream(stream, options, streams = {}) {
|
||||
this.destroyDispatcher();
|
||||
const opus = streams.opus = new prism.opus.Encoder({ channels: 2, rate: 48000, frameSize: 960 });
|
||||
const opus = (streams.opus = new prism.opus.Encoder({ channels: 2, rate: 48000, frameSize: 960 }));
|
||||
if (options && options.volume === false) {
|
||||
stream.pipe(opus);
|
||||
return this.playOpusStream(opus, options, streams);
|
||||
@@ -90,7 +84,7 @@ class BasePlayer extends EventEmitter {
|
||||
|
||||
createDispatcher(options, streams, broadcast) {
|
||||
this.destroyDispatcher();
|
||||
const dispatcher = this.dispatcher = new StreamDispatcher(this, options, streams, broadcast);
|
||||
const dispatcher = (this.dispatcher = new StreamDispatcher(this, options, streams, broadcast));
|
||||
return dispatcher;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const BroadcastDispatcher = require('../dispatcher/BroadcastDispatcher');
|
||||
const BasePlayer = require('./BasePlayer');
|
||||
const BroadcastDispatcher = require('../dispatcher/BroadcastDispatcher');
|
||||
|
||||
/**
|
||||
* An Audio Player for a Voice Connection.
|
||||
@@ -20,7 +20,7 @@ class AudioPlayer extends BasePlayer {
|
||||
|
||||
createDispatcher(options, streams) {
|
||||
this.destroyDispatcher();
|
||||
const dispatcher = this.dispatcher = new BroadcastDispatcher(this, options, streams);
|
||||
const dispatcher = (this.dispatcher = new BroadcastDispatcher(this, options, streams));
|
||||
return dispatcher;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
'use strict';
|
||||
|
||||
const secretbox = require('../util/Secretbox');
|
||||
const EventEmitter = require('events');
|
||||
const secretbox = require('../util/Secretbox');
|
||||
|
||||
// The delay between packets when a user is considered to have stopped speaking
|
||||
// https://github.com/discordjs/discord.js/issues/3524#issuecomment-540373200
|
||||
const DISCORD_SPEAKING_DELAY = 250;
|
||||
|
||||
class Readable extends require('stream').Readable { _read() {} } // eslint-disable-line no-empty-function
|
||||
class Readable extends require('stream').Readable {
|
||||
_read() {} // eslint-disable-line no-empty-function
|
||||
}
|
||||
|
||||
class PacketHandler extends EventEmitter {
|
||||
constructor(receiver) {
|
||||
@@ -59,7 +61,7 @@ class PacketHandler extends EventEmitter {
|
||||
packet = Buffer.from(packet);
|
||||
|
||||
// Strip RTP Header Extensions (one-byte only)
|
||||
if (packet[0] === 0xBE && packet[1] === 0xDE && packet.length > 4) {
|
||||
if (packet[0] === 0xbe && packet[1] === 0xde && packet.length > 4) {
|
||||
const headerExtensionLength = packet.readUInt16BE(2);
|
||||
let offset = 4;
|
||||
for (let i = 0; i < headerExtensionLength; i++) {
|
||||
|
||||
@@ -85,12 +85,12 @@ class PlayInterface {
|
||||
|
||||
static applyToClass(structure) {
|
||||
for (const prop of ['play']) {
|
||||
Object.defineProperty(structure.prototype, prop,
|
||||
Object.getOwnPropertyDescriptor(PlayInterface.prototype, prop));
|
||||
Object.defineProperty(structure.prototype, prop, Object.getOwnPropertyDescriptor(PlayInterface.prototype, prop));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PlayInterface;
|
||||
|
||||
// eslint-disable-next-line import/order
|
||||
const Broadcast = require('../VoiceBroadcast');
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
const { Readable } = require('stream');
|
||||
|
||||
const SILENCE_FRAME = Buffer.from([0xF8, 0xFF, 0xFE]);
|
||||
const SILENCE_FRAME = Buffer.from([0xf8, 0xff, 0xfe]);
|
||||
|
||||
class Silence extends Readable {
|
||||
_read() {
|
||||
|
||||
@@ -94,19 +94,10 @@ class VolumeInterface extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
const props = [
|
||||
'volumeDecibels',
|
||||
'volumeLogarithmic',
|
||||
'setVolumeDecibels',
|
||||
'setVolumeLogarithmic',
|
||||
];
|
||||
const props = ['volumeDecibels', 'volumeLogarithmic', 'setVolumeDecibels', 'setVolumeLogarithmic'];
|
||||
|
||||
exports.applyToClass = function applyToClass(structure) {
|
||||
for (const prop of props) {
|
||||
Object.defineProperty(
|
||||
structure.prototype,
|
||||
prop,
|
||||
Object.getOwnPropertyDescriptor(VolumeInterface.prototype, prop),
|
||||
);
|
||||
Object.defineProperty(structure.prototype, prop, Object.getOwnPropertyDescriptor(VolumeInterface.prototype, prop));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
const EventEmitter = require('events');
|
||||
const WebSocketShard = require('./WebSocketShard');
|
||||
const PacketHandlers = require('./handlers');
|
||||
const { Error: DJSError } = require('../../errors');
|
||||
const Collection = require('../../util/Collection');
|
||||
const Util = require('../../util/Util');
|
||||
const WebSocketShard = require('./WebSocketShard');
|
||||
const { Events, ShardEvents, Status, WSCodes, WSEvents } = require('../../util/Constants');
|
||||
const PacketHandlers = require('./handlers');
|
||||
const Util = require('../../util/Util');
|
||||
|
||||
const BeforeReadyWhitelist = [
|
||||
WSEvents.READY,
|
||||
@@ -18,7 +18,9 @@ const BeforeReadyWhitelist = [
|
||||
WSEvents.GUILD_MEMBER_REMOVE,
|
||||
];
|
||||
|
||||
const UNRECOVERABLE_CLOSE_CODES = Object.keys(WSCodes).slice(1).map(Number);
|
||||
const UNRECOVERABLE_CLOSE_CODES = Object.keys(WSCodes)
|
||||
.slice(1)
|
||||
.map(Number);
|
||||
const UNRESUMABLE_CLOSE_CODES = [1000, 4006, 4007];
|
||||
|
||||
/**
|
||||
|
||||
@@ -237,14 +237,15 @@ class WebSocketShard extends EventEmitter {
|
||||
Gateway : ${gateway}
|
||||
Version : ${client.options.ws.version}
|
||||
Encoding : ${WebSocket.encoding}
|
||||
Compression: ${zlib ? 'zlib-stream' : 'none'}`);
|
||||
Compression: ${zlib ? 'zlib-stream' : 'none'}`,
|
||||
);
|
||||
|
||||
this.status = this.status === Status.DISCONNECTED ? Status.RECONNECTING : Status.CONNECTING;
|
||||
this.setHelloTimeout();
|
||||
|
||||
this.connectedAt = Date.now();
|
||||
|
||||
const ws = this.connection = WebSocket.create(gateway, wsQuery);
|
||||
const ws = (this.connection = WebSocket.create(gateway, wsQuery));
|
||||
ws.onopen = this.onOpen.bind(this);
|
||||
ws.onmessage = this.onMessage.bind(this);
|
||||
ws.onerror = this.onError.bind(this);
|
||||
@@ -271,11 +272,8 @@ class WebSocketShard extends EventEmitter {
|
||||
if (data instanceof ArrayBuffer) data = new Uint8Array(data);
|
||||
if (zlib) {
|
||||
const l = data.length;
|
||||
const flush = l >= 4 &&
|
||||
data[l - 4] === 0x00 &&
|
||||
data[l - 3] === 0x00 &&
|
||||
data[l - 2] === 0xFF &&
|
||||
data[l - 1] === 0xFF;
|
||||
const flush =
|
||||
l >= 4 && data[l - 4] === 0x00 && data[l - 3] === 0x00 && data[l - 2] === 0xff && data[l - 1] === 0xff;
|
||||
|
||||
this.inflate.push(data, flush && zlib.Z_SYNC_FLUSH);
|
||||
if (!flush) return;
|
||||
@@ -529,8 +527,10 @@ class WebSocketShard extends EventEmitter {
|
||||
* @param {boolean} [ignoreHeartbeatAck] If we should send the heartbeat forcefully.
|
||||
* @private
|
||||
*/
|
||||
sendHeartbeat(tag = 'HeartbeatTimer',
|
||||
ignoreHeartbeatAck = [Status.WAITING_FOR_GUILDS, Status.IDENTIFYING, Status.RESUMING].includes(this.status)) {
|
||||
sendHeartbeat(
|
||||
tag = 'HeartbeatTimer',
|
||||
ignoreHeartbeatAck = [Status.WAITING_FOR_GUILDS, Status.IDENTIFYING, Status.RESUMING].includes(this.status),
|
||||
) {
|
||||
if (ignoreHeartbeatAck && !this.lastHeartbeatAcked) {
|
||||
this.debug(`[${tag}] Didn't process heartbeat ack yet but we are still connected. Sending one now.`);
|
||||
} else if (!this.lastHeartbeatAcked) {
|
||||
@@ -538,7 +538,8 @@ class WebSocketShard extends EventEmitter {
|
||||
`[${tag}] Didn't receive a heartbeat ack last time, assuming zombie connection. Destroying and reconnecting.
|
||||
Status : ${STATUS_KEYS[this.status]}
|
||||
Sequence : ${this.sequence}
|
||||
Connection State: ${this.connection ? CONNECTION_STATE[this.connection.readyState] : 'No Connection??'}`);
|
||||
Connection State: ${this.connection ? CONNECTION_STATE[this.connection.readyState] : 'No Connection??'}`,
|
||||
);
|
||||
|
||||
this.destroy({ closeCode: 4009, reset: true });
|
||||
return;
|
||||
@@ -741,10 +742,7 @@ class WebSocketShard extends EventEmitter {
|
||||
* @private
|
||||
*/
|
||||
_cleanupConnection() {
|
||||
this.connection.onopen =
|
||||
this.connection.onclose =
|
||||
this.connection.onerror =
|
||||
this.connection.onmessage = null;
|
||||
this.connection.onopen = this.connection.onclose = this.connection.onerror = this.connection.onmessage = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,4 +14,3 @@ module.exports = (client, packet) => {
|
||||
client.emit(Events.CHANNEL_UPDATE, old, updated);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -10,9 +10,9 @@ module.exports = async (client, { d: data }, shard) => {
|
||||
guild._patch(data);
|
||||
// If the client was ready before and we had unavailable guilds, fetch them
|
||||
if (client.ws.status === Status.READY && client.options.fetchAllMembers) {
|
||||
await guild.members.fetch().catch(err =>
|
||||
client.emit(Events.DEBUG, `Failed to fetch all members: ${err}\n${err.stack}`),
|
||||
);
|
||||
await guild.members
|
||||
.fetch()
|
||||
.catch(err => client.emit(Events.DEBUG, `Failed to fetch all members: ${err}\n${err.stack}`));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -26,9 +26,9 @@ module.exports = async (client, { d: data }, shard) => {
|
||||
* @param {Guild} guild The created guild
|
||||
*/
|
||||
if (client.options.fetchAllMembers) {
|
||||
await guild.members.fetch().catch(err =>
|
||||
client.emit(Events.DEBUG, `Failed to fetch all members: ${err}\n${err.stack}`),
|
||||
);
|
||||
await guild.members
|
||||
.fetch()
|
||||
.catch(err => client.emit(Events.DEBUG, `Failed to fetch all members: ${err}\n${err.stack}`));
|
||||
}
|
||||
client.emit(Events.GUILD_CREATE, guild);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const { Events } = require('../../../util/Constants');
|
||||
const Collection = require('../../../util/Collection');
|
||||
const { Events } = require('../../../util/Constants');
|
||||
|
||||
module.exports = (client, { d: data }) => {
|
||||
const guild = client.guilds.cache.get(data.guild_id);
|
||||
|
||||
@@ -8,11 +8,11 @@ module.exports = (client, { d: data }, shard) => {
|
||||
guild.memberCount++;
|
||||
const member = guild.members.add(data);
|
||||
if (shard.status === Status.READY) {
|
||||
/**
|
||||
* Emitted whenever a user joins a guild.
|
||||
* @event Client#guildMemberAdd
|
||||
* @param {GuildMember} member The member that has joined a guild
|
||||
*/
|
||||
/**
|
||||
* Emitted whenever a user joins a guild.
|
||||
* @event Client#guildMemberAdd
|
||||
* @param {GuildMember} member The member that has joined a guild
|
||||
*/
|
||||
client.emit(Events.GUILD_MEMBER_ADD, member);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@ module.exports = (client, { d: data }) => {
|
||||
const user = client.users.cache.get(data.user_id);
|
||||
|
||||
if (channel && user) {
|
||||
/**
|
||||
* Emitted whenever a user starts typing in a channel.
|
||||
* @event Client#typingStart
|
||||
* @param {Channel} channel The channel the user started typing in
|
||||
* @param {User} user The user that started typing
|
||||
*/
|
||||
/**
|
||||
* Emitted whenever a user starts typing in a channel.
|
||||
* @event Client#typingStart
|
||||
* @param {Channel} channel The channel the user started typing in
|
||||
* @param {User} user The user that started typing
|
||||
*/
|
||||
client.emit(Events.TYPING_START, channel, user);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -36,7 +36,7 @@ const Messages = {
|
||||
USER_NO_DMCHANNEL: 'No DM Channel exists!',
|
||||
|
||||
VOICE_INVALID_HEARTBEAT: 'Tried to set voice heartbeat but no valid interval was specified.',
|
||||
VOICE_USER_MISSING: 'Couldn\'t resolve the user to create stream.',
|
||||
VOICE_USER_MISSING: "Couldn't resolve the user to create stream.",
|
||||
VOICE_JOIN_CHANNEL: (full = false) =>
|
||||
`You do not have permission to join this voice channel${full ? '; it is full.' : '.'}`,
|
||||
VOICE_CONNECTION_TIMEOUT: 'Connection not established within 15 seconds.',
|
||||
@@ -71,7 +71,7 @@ const Messages = {
|
||||
SPLIT_MAX_LEN: 'Chunk exceeds the max length and contains no split characters.',
|
||||
|
||||
BAN_RESOLVE_ID: (ban = false) => `Couldn't resolve the user ID to ${ban ? 'ban' : 'unban'}.`,
|
||||
FETCH_BAN_RESOLVE_ID: 'Couldn\'t resolve the user ID to fetch the ban.',
|
||||
FETCH_BAN_RESOLVE_ID: "Couldn't resolve the user ID to fetch the ban.",
|
||||
|
||||
PRUNE_DAYS_TYPE: 'Days must be a number',
|
||||
|
||||
@@ -79,7 +79,7 @@ const Messages = {
|
||||
GUILD_VOICE_CHANNEL_RESOLVE: 'Could not resolve channel to a guild voice channel.',
|
||||
GUILD_CHANNEL_ORPHAN: 'Could not find a parent to this guild channel.',
|
||||
GUILD_OWNED: 'Guild is owned by the client.',
|
||||
GUILD_MEMBERS_TIMEOUT: 'Members didn\'t arrive in time.',
|
||||
GUILD_MEMBERS_TIMEOUT: "Members didn't arrive in time.",
|
||||
GUILD_UNCACHED_ME: 'The client user as a member of this guild is uncached.',
|
||||
|
||||
INVALID_TYPE: (name, expected, an = false) => `Supplied ${name} is not a${an ? 'n' : ''} ${expected}.`,
|
||||
@@ -88,15 +88,15 @@ const Messages = {
|
||||
|
||||
EMOJI_TYPE: 'Emoji must be a string or GuildEmoji/ReactionEmoji',
|
||||
EMOJI_MANAGED: 'Emoji is managed and has no Author.',
|
||||
MISSING_MANAGE_EMOJIS_PERMISSION:
|
||||
guild => `Client must have Manage Emoji permission in guild ${guild} to see emoji authors.`,
|
||||
MISSING_MANAGE_EMOJIS_PERMISSION: guild =>
|
||||
`Client must have Manage Emoji permission in guild ${guild} to see emoji authors.`,
|
||||
|
||||
REACTION_RESOLVE_USER: 'Couldn\'t resolve the user ID to remove from the reaction.',
|
||||
REACTION_RESOLVE_USER: "Couldn't resolve the user ID to remove from the reaction.",
|
||||
|
||||
VANITY_URL: 'This guild does not have the VANITY_URL feature enabled.',
|
||||
|
||||
DELETE_GROUP_DM_CHANNEL: 'Bots don\'t have access to Group DM Channels and cannot delete them',
|
||||
FETCH_GROUP_DM_CHANNEL: 'Bots don\'t have access to Group DM Channels and cannot fetch them',
|
||||
DELETE_GROUP_DM_CHANNEL: "Bots don't have access to Group DM Channels and cannot delete them",
|
||||
FETCH_GROUP_DM_CHANNEL: "Bots don't have access to Group DM Channels and cannot fetch them",
|
||||
};
|
||||
|
||||
for (const [name, message] of Object.entries(Messages)) register(name, message);
|
||||
|
||||
@@ -34,9 +34,9 @@ class BaseManager {
|
||||
this.cacheType = cacheType;
|
||||
|
||||
/**
|
||||
* Holds the cache for the data model
|
||||
* @type {Collection}
|
||||
*/
|
||||
* Holds the cache for the data model
|
||||
* @type {Collection}
|
||||
*/
|
||||
this.cache = new cacheType(...cacheOptions);
|
||||
if (iterable) for (const i of iterable) this.add(i);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const Channel = require('../structures/Channel');
|
||||
const BaseManager = require('./BaseManager');
|
||||
const Channel = require('../structures/Channel');
|
||||
const { Events } = require('../util/Constants');
|
||||
|
||||
/**
|
||||
@@ -14,10 +14,10 @@ class ChannelManager extends BaseManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of Channels
|
||||
* @type {Collection<Snowflake, Channel>}
|
||||
* @name ChannelManager#cache
|
||||
*/
|
||||
* The cache of Channels
|
||||
* @type {Collection<Snowflake, Channel>}
|
||||
* @name ChannelManager#cache
|
||||
*/
|
||||
|
||||
add(data, guild, cache = true) {
|
||||
const existing = this.cache.get(data.id);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const { ChannelTypes } = require('../util/Constants');
|
||||
const BaseManager = require('./BaseManager');
|
||||
const GuildChannel = require('../structures/GuildChannel');
|
||||
const PermissionOverwrites = require('../structures/PermissionOverwrites');
|
||||
const { ChannelTypes } = require('../util/Constants');
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildChannels and stores their cache.
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const Collection = require('../util/Collection');
|
||||
const BaseManager = require('./BaseManager');
|
||||
const { TypeError } = require('../errors');
|
||||
const GuildEmoji = require('../structures/GuildEmoji');
|
||||
const ReactionEmoji = require('../structures/ReactionEmoji');
|
||||
const Collection = require('../util/Collection');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const { TypeError } = require('../errors');
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildEmojis and stores their cache.
|
||||
@@ -22,10 +22,10 @@ class GuildEmojiManager extends BaseManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of GuildEmojis
|
||||
* @type {Collection<Snowflake, GuildEmoji>}
|
||||
* @name GuildEmojiManager#cache
|
||||
*/
|
||||
* The cache of GuildEmojis
|
||||
* @type {Collection<Snowflake, GuildEmoji>}
|
||||
* @name GuildEmojiManager#cache
|
||||
*/
|
||||
|
||||
add(data, cache) {
|
||||
return super.add(data, cache, { extras: [this.guild] });
|
||||
@@ -58,14 +58,17 @@ class GuildEmojiManager extends BaseManager {
|
||||
for (let role of roles instanceof Collection ? roles.values() : roles) {
|
||||
role = this.guild.roles.resolve(role);
|
||||
if (!role) {
|
||||
return Promise.reject(new TypeError('INVALID_TYPE', 'options.roles',
|
||||
'Array or Collection of Roles or Snowflakes', true));
|
||||
return Promise.reject(
|
||||
new TypeError('INVALID_TYPE', 'options.roles', 'Array or Collection of Roles or Snowflakes', true),
|
||||
);
|
||||
}
|
||||
data.roles.push(role.id);
|
||||
}
|
||||
}
|
||||
|
||||
return this.client.api.guilds(this.guild.id).emojis.post({ data, reason })
|
||||
return this.client.api
|
||||
.guilds(this.guild.id)
|
||||
.emojis.post({ data, reason })
|
||||
.then(emoji => this.client.actions.GuildEmojiCreate.handle(this.guild, emoji).emoji);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const Collection = require('../util/Collection');
|
||||
const { TypeError } = require('../errors');
|
||||
const Collection = require('../util/Collection');
|
||||
|
||||
/**
|
||||
* Manages API methods for roles belonging to emojis and stores their cache.
|
||||
@@ -56,8 +56,7 @@ class GuildEmojiRoleManager {
|
||||
roleOrRoles = roleOrRoles.map(r => this.guild.roles.resolve(r));
|
||||
|
||||
if (roleOrRoles.includes(null)) {
|
||||
return Promise.reject(new TypeError('INVALID_TYPE', 'roles',
|
||||
'Array or Collection of Roles or Snowflakes', true));
|
||||
return Promise.reject(new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true));
|
||||
}
|
||||
|
||||
const newRoles = [...new Set(roleOrRoles.concat(...this._roles.values()))];
|
||||
@@ -75,8 +74,7 @@ class GuildEmojiRoleManager {
|
||||
roleOrRoles = roleOrRoles.map(r => this.guild.roles.resolveID(r));
|
||||
|
||||
if (roleOrRoles.includes(null)) {
|
||||
return Promise.reject(new TypeError('INVALID_TYPE', 'roles',
|
||||
'Array or Collection of Roles or Snowflakes', true));
|
||||
return Promise.reject(new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true));
|
||||
}
|
||||
|
||||
const newRoles = this._roles.keyArray().filter(role => !roleOrRoles.includes(role));
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const Guild = require('../structures/Guild');
|
||||
const GuildChannel = require('../structures/GuildChannel');
|
||||
const GuildEmoji = require('../structures/GuildEmoji');
|
||||
const GuildMember = require('../structures/GuildMember');
|
||||
const Invite = require('../structures/Invite');
|
||||
const Role = require('../structures/Role');
|
||||
const {
|
||||
Events,
|
||||
VerificationLevels,
|
||||
DefaultMessageNotifications,
|
||||
ExplicitContentFilterLevels,
|
||||
} = require('../util/Constants');
|
||||
const Guild = require('../structures/Guild');
|
||||
const GuildChannel = require('../structures/GuildChannel');
|
||||
const GuildMember = require('../structures/GuildMember');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const { resolveColor } = require('../util/Util');
|
||||
const GuildEmoji = require('../structures/GuildEmoji');
|
||||
const Invite = require('../structures/Invite');
|
||||
const Role = require('../structures/Role');
|
||||
|
||||
/**
|
||||
* Manages API methods for Guilds and stores their cache.
|
||||
@@ -91,11 +91,15 @@ class GuildManager extends BaseManager {
|
||||
* @returns {?Guild}
|
||||
*/
|
||||
resolve(guild) {
|
||||
if (guild instanceof GuildChannel ||
|
||||
if (
|
||||
guild instanceof GuildChannel ||
|
||||
guild instanceof GuildMember ||
|
||||
guild instanceof GuildEmoji ||
|
||||
guild instanceof Role ||
|
||||
(guild instanceof Invite && guild.guild)) return super.resolve(guild.guild);
|
||||
(guild instanceof Invite && guild.guild)
|
||||
) {
|
||||
return super.resolve(guild.guild);
|
||||
}
|
||||
return super.resolve(guild);
|
||||
}
|
||||
|
||||
@@ -108,11 +112,15 @@ class GuildManager extends BaseManager {
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
resolveID(guild) {
|
||||
if (guild instanceof GuildChannel ||
|
||||
if (
|
||||
guild instanceof GuildChannel ||
|
||||
guild instanceof GuildMember ||
|
||||
guild instanceof GuildEmoji ||
|
||||
guild instanceof Role ||
|
||||
(guild instanceof Invite && guild.guild)) return super.resolveID(guild.guild.id);
|
||||
(guild instanceof Invite && guild.guild)
|
||||
) {
|
||||
return super.resolveID(guild.guild.id);
|
||||
}
|
||||
return super.resolveID(guild);
|
||||
}
|
||||
|
||||
@@ -132,15 +140,18 @@ class GuildManager extends BaseManager {
|
||||
* @param {VerificationLevel} [options.verificationLevel] The verification level for the guild
|
||||
* @returns {Promise<Guild>} The guild that was created
|
||||
*/
|
||||
async create(name, {
|
||||
channels = [],
|
||||
defaultMessageNotifications,
|
||||
explicitContentFilter,
|
||||
icon = null,
|
||||
region,
|
||||
roles = [],
|
||||
verificationLevel,
|
||||
} = {}) {
|
||||
async create(
|
||||
name,
|
||||
{
|
||||
channels = [],
|
||||
defaultMessageNotifications,
|
||||
explicitContentFilter,
|
||||
icon = null,
|
||||
region,
|
||||
roles = [],
|
||||
verificationLevel,
|
||||
} = {},
|
||||
) {
|
||||
icon = await DataResolver.resolveImage(icon);
|
||||
if (typeof verificationLevel !== 'undefined' && typeof verificationLevel !== 'number') {
|
||||
verificationLevel = VerificationLevels.indexOf(verificationLevel);
|
||||
@@ -167,16 +178,19 @@ class GuildManager extends BaseManager {
|
||||
if (role.permissions) role.permissions = Permissions.resolve(role.permissions);
|
||||
}
|
||||
return new Promise((resolve, reject) =>
|
||||
this.client.api.guilds.post({ data: {
|
||||
name,
|
||||
region,
|
||||
icon,
|
||||
verification_level: verificationLevel,
|
||||
default_message_notifications: defaultMessageNotifications,
|
||||
explicit_content_filter: explicitContentFilter,
|
||||
channels,
|
||||
roles,
|
||||
} })
|
||||
this.client.api.guilds
|
||||
.post({
|
||||
data: {
|
||||
name,
|
||||
region,
|
||||
icon,
|
||||
verification_level: verificationLevel,
|
||||
default_message_notifications: defaultMessageNotifications,
|
||||
explicit_content_filter: explicitContentFilter,
|
||||
channels,
|
||||
roles,
|
||||
},
|
||||
})
|
||||
.then(data => {
|
||||
if (this.client.guilds.cache.has(data.id)) return resolve(this.client.guilds.cache.get(data.id));
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const GuildMember = require('../structures/GuildMember');
|
||||
const { Events, OPCodes } = require('../util/Constants');
|
||||
const Collection = require('../util/Collection');
|
||||
const { Error, TypeError } = require('../errors');
|
||||
const GuildMember = require('../structures/GuildMember');
|
||||
const Collection = require('../util/Collection');
|
||||
const { Events, OPCodes } = require('../util/Constants');
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildMembers and stores their cache.
|
||||
@@ -148,10 +148,15 @@ class GuildMemberManager extends BaseManager {
|
||||
*/
|
||||
prune({ days = 7, dry = false, count = true, reason } = {}) {
|
||||
if (typeof days !== 'number') throw new TypeError('PRUNE_DAYS_TYPE');
|
||||
return this.client.api.guilds(this.guild.id).prune[dry ? 'get' : 'post']({ query: {
|
||||
days,
|
||||
compute_prune_count: count,
|
||||
}, reason })
|
||||
return this.client.api
|
||||
.guilds(this.guild.id)
|
||||
.prune[dry ? 'get' : 'post']({
|
||||
query: {
|
||||
days,
|
||||
compute_prune_count: count,
|
||||
},
|
||||
reason,
|
||||
})
|
||||
.then(data => data.pruned);
|
||||
}
|
||||
|
||||
@@ -174,7 +179,9 @@ class GuildMemberManager extends BaseManager {
|
||||
if (options.days) options['delete-message-days'] = options.days;
|
||||
const id = this.client.users.resolveID(user);
|
||||
if (!id) return Promise.reject(new Error('BAN_RESOLVE_ID', true));
|
||||
return this.client.api.guilds(this.guild.id).bans[id].put({ query: options })
|
||||
return this.client.api
|
||||
.guilds(this.guild.id)
|
||||
.bans[id].put({ query: options })
|
||||
.then(() => {
|
||||
if (user instanceof GuildMember) return user;
|
||||
const _user = this.client.users.resolve(id);
|
||||
@@ -200,21 +207,25 @@ class GuildMemberManager extends BaseManager {
|
||||
unban(user, reason) {
|
||||
const id = this.client.users.resolveID(user);
|
||||
if (!id) return Promise.reject(new Error('BAN_RESOLVE_ID'));
|
||||
return this.client.api.guilds(this.guild.id).bans[id].delete({ reason })
|
||||
return this.client.api
|
||||
.guilds(this.guild.id)
|
||||
.bans[id].delete({ reason })
|
||||
.then(() => this.client.users.resolve(user));
|
||||
}
|
||||
|
||||
|
||||
_fetchSingle({ user, cache }) {
|
||||
const existing = this.cache.get(user);
|
||||
if (existing && !existing.partial) return Promise.resolve(existing);
|
||||
return this.client.api.guilds(this.guild.id).members(user).get()
|
||||
return this.client.api
|
||||
.guilds(this.guild.id)
|
||||
.members(user)
|
||||
.get()
|
||||
.then(data => this.add(data, cache));
|
||||
}
|
||||
|
||||
_fetchMany({ limit = 0, withPresences: presences = false, user: user_ids, query } = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.guild.memberCount === this.cache.size && (!query && !limit && !presences && !user_ids)) {
|
||||
if (this.guild.memberCount === this.cache.size && !query && !limit && !presences && !user_ids) {
|
||||
resolve(this.cache);
|
||||
return;
|
||||
}
|
||||
@@ -237,9 +248,11 @@ class GuildMemberManager extends BaseManager {
|
||||
for (const member of members.values()) {
|
||||
if (option) fetchedMembers.set(member.id, member);
|
||||
}
|
||||
if (this.guild.memberCount <= this.cache.size ||
|
||||
if (
|
||||
this.guild.memberCount <= this.cache.size ||
|
||||
(option && members.size < 1000) ||
|
||||
(limit && fetchedMembers.size >= limit)) {
|
||||
(limit && fetchedMembers.size >= limit)
|
||||
) {
|
||||
this.guild.client.removeListener(Events.GUILD_MEMBERS_CHUNK, handler);
|
||||
let fetched = option ? fetchedMembers : this.cache;
|
||||
if (user_ids && !Array.isArray(user_ids) && fetched.size) fetched = fetched.first();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const Collection = require('../util/Collection');
|
||||
const { TypeError } = require('../errors');
|
||||
const Collection = require('../util/Collection');
|
||||
|
||||
/**
|
||||
* Manages API methods for roles of a GuildMember and stores their cache.
|
||||
@@ -49,7 +49,7 @@ class GuildMemberRoleManager {
|
||||
get hoist() {
|
||||
const hoistedRoles = this._roles.filter(role => role.hoist);
|
||||
if (!hoistedRoles.size) return null;
|
||||
return hoistedRoles.reduce((prev, role) => !prev || role.comparePositionTo(prev) > 0 ? role : prev);
|
||||
return hoistedRoles.reduce((prev, role) => (!prev || role.comparePositionTo(prev) > 0 ? role : prev));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,7 +60,7 @@ class GuildMemberRoleManager {
|
||||
get color() {
|
||||
const coloredRoles = this._roles.filter(role => role.color);
|
||||
if (!coloredRoles.size) return null;
|
||||
return coloredRoles.reduce((prev, role) => !prev || role.comparePositionTo(prev) > 0 ? role : prev);
|
||||
return coloredRoles.reduce((prev, role) => (!prev || role.comparePositionTo(prev) > 0 ? role : prev));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -69,7 +69,7 @@ class GuildMemberRoleManager {
|
||||
* @readonly
|
||||
*/
|
||||
get highest() {
|
||||
return this._roles.reduce((prev, role) => role.comparePositionTo(prev) > 0 ? role : prev, this._roles.first());
|
||||
return this._roles.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev), this._roles.first());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,8 +82,7 @@ class GuildMemberRoleManager {
|
||||
if (roleOrRoles instanceof Collection || Array.isArray(roleOrRoles)) {
|
||||
roleOrRoles = roleOrRoles.map(r => this.guild.roles.resolve(r));
|
||||
if (roleOrRoles.includes(null)) {
|
||||
throw new TypeError('INVALID_TYPE', 'roles',
|
||||
'Array or Collection of Roles or Snowflakes', true);
|
||||
throw new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true);
|
||||
}
|
||||
|
||||
const newRoles = [...new Set(roleOrRoles.concat(...this._roles.values()))];
|
||||
@@ -91,8 +90,7 @@ class GuildMemberRoleManager {
|
||||
} else {
|
||||
roleOrRoles = this.guild.roles.resolve(roleOrRoles);
|
||||
if (roleOrRoles === null) {
|
||||
throw new TypeError('INVALID_TYPE', 'roles',
|
||||
'Array or Collection of Roles or Snowflakes', true);
|
||||
throw new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true);
|
||||
}
|
||||
|
||||
await this.client.api.guilds[this.guild.id].members[this.member.id].roles[roleOrRoles.id].put({ reason });
|
||||
@@ -113,8 +111,7 @@ class GuildMemberRoleManager {
|
||||
if (roleOrRoles instanceof Collection || Array.isArray(roleOrRoles)) {
|
||||
roleOrRoles = roleOrRoles.map(r => this.guild.roles.resolve(r));
|
||||
if (roleOrRoles.includes(null)) {
|
||||
throw new TypeError('INVALID_TYPE', 'roles',
|
||||
'Array or Collection of Roles or Snowflakes', true);
|
||||
throw new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true);
|
||||
}
|
||||
|
||||
const newRoles = this._roles.filter(role => !roleOrRoles.includes(role));
|
||||
@@ -122,8 +119,7 @@ class GuildMemberRoleManager {
|
||||
} else {
|
||||
roleOrRoles = this.guild.roles.resolve(roleOrRoles);
|
||||
if (roleOrRoles === null) {
|
||||
throw new TypeError('INVALID_TYPE', 'roles',
|
||||
'Array or Collection of Roles or Snowflakes', true);
|
||||
throw new TypeError('INVALID_TYPE', 'roles', 'Array or Collection of Roles or Snowflakes', true);
|
||||
}
|
||||
|
||||
await this.client.api.guilds[this.guild.id].members[this.member.id].roles[roleOrRoles.id].delete({ reason });
|
||||
|
||||
@@ -2,82 +2,82 @@
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const Message = require('../structures/Message');
|
||||
const LimitedCollection = require('../util/LimitedCollection');
|
||||
const Collection = require('../util/Collection');
|
||||
const LimitedCollection = require('../util/LimitedCollection');
|
||||
|
||||
/**
|
||||
* Manages API methods for Messages and holds their cache.
|
||||
* @extends {BaseManager}
|
||||
*/
|
||||
* Manages API methods for Messages and holds their cache.
|
||||
* @extends {BaseManager}
|
||||
*/
|
||||
class MessageManager extends BaseManager {
|
||||
constructor(channel, iterable) {
|
||||
super(channel.client, iterable, Message, LimitedCollection, channel.client.options.messageCacheMaxSize);
|
||||
/**
|
||||
* The channel that the messages belong to
|
||||
* @type {TextBasedChannel}
|
||||
*/
|
||||
* The channel that the messages belong to
|
||||
* @type {TextBasedChannel}
|
||||
*/
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of Messages
|
||||
* @type {LimitedCollection<Snowflake, Message>}
|
||||
* @name MessageManager#cache
|
||||
*/
|
||||
* The cache of Messages
|
||||
* @type {LimitedCollection<Snowflake, Message>}
|
||||
* @name MessageManager#cache
|
||||
*/
|
||||
|
||||
add(data, cache) {
|
||||
return super.add(data, cache, { extras: [this.channel] });
|
||||
}
|
||||
|
||||
/**
|
||||
* The parameters to pass in when requesting previous messages from a channel. `around`, `before` and
|
||||
* `after` are mutually exclusive. All the parameters are optional.
|
||||
* @typedef {Object} ChannelLogsQueryOptions
|
||||
* @property {number} [limit=50] Number of messages to acquire
|
||||
* @property {Snowflake} [before] ID of a message to get the messages that were posted before it
|
||||
* @property {Snowflake} [after] ID of a message to get the messages that were posted after it
|
||||
* @property {Snowflake} [around] ID of a message to get the messages that were posted around it
|
||||
*/
|
||||
* The parameters to pass in when requesting previous messages from a channel. `around`, `before` and
|
||||
* `after` are mutually exclusive. All the parameters are optional.
|
||||
* @typedef {Object} ChannelLogsQueryOptions
|
||||
* @property {number} [limit=50] Number of messages to acquire
|
||||
* @property {Snowflake} [before] ID of a message to get the messages that were posted before it
|
||||
* @property {Snowflake} [after] ID of a message to get the messages that were posted after it
|
||||
* @property {Snowflake} [around] ID of a message to get the messages that were posted around it
|
||||
*/
|
||||
|
||||
/**
|
||||
* Gets a message, or messages, from this channel.
|
||||
* <info>The returned Collection does not contain reaction users of the messages if they were not cached.
|
||||
* Those need to be fetched separately in such a case.</info>
|
||||
* @param {Snowflake|ChannelLogsQueryOptions} [message] The ID of the message to fetch, or query parameters.
|
||||
* @param {boolean} [cache=true] Whether to cache the message(s)
|
||||
* @returns {Promise<Message>|Promise<Collection<Snowflake, Message>>}
|
||||
* @example
|
||||
* // Get message
|
||||
* channel.messages.fetch('99539446449315840')
|
||||
* .then(message => console.log(message.content))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Get messages
|
||||
* channel.messages.fetch({ limit: 10 })
|
||||
* .then(messages => console.log(`Received ${messages.size} messages`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Get messages and filter by user ID
|
||||
* channel.messages.fetch()
|
||||
* .then(messages => console.log(`${messages.filter(m => m.author.id === '84484653687267328').size} messages`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
* Gets a message, or messages, from this channel.
|
||||
* <info>The returned Collection does not contain reaction users of the messages if they were not cached.
|
||||
* Those need to be fetched separately in such a case.</info>
|
||||
* @param {Snowflake|ChannelLogsQueryOptions} [message] The ID of the message to fetch, or query parameters.
|
||||
* @param {boolean} [cache=true] Whether to cache the message(s)
|
||||
* @returns {Promise<Message>|Promise<Collection<Snowflake, Message>>}
|
||||
* @example
|
||||
* // Get message
|
||||
* channel.messages.fetch('99539446449315840')
|
||||
* .then(message => console.log(message.content))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Get messages
|
||||
* channel.messages.fetch({ limit: 10 })
|
||||
* .then(messages => console.log(`Received ${messages.size} messages`))
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Get messages and filter by user ID
|
||||
* channel.messages.fetch()
|
||||
* .then(messages => console.log(`${messages.filter(m => m.author.id === '84484653687267328').size} messages`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetch(message, cache = true) {
|
||||
return typeof message === 'string' ? this._fetchId(message, cache) : this._fetchMany(message, cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the pinned messages of this channel and returns a collection of them.
|
||||
* <info>The returned Collection does not contain any reaction data of the messages.
|
||||
* Those need to be fetched separately.</info>
|
||||
* @param {boolean} [cache=true] Whether to cache the message(s)
|
||||
* @returns {Promise<Collection<Snowflake, Message>>}
|
||||
* @example
|
||||
* // Get pinned messages
|
||||
* channel.fetchPinned()
|
||||
* .then(messages => console.log(`Received ${messages.size} messages`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
* Fetches the pinned messages of this channel and returns a collection of them.
|
||||
* <info>The returned Collection does not contain any reaction data of the messages.
|
||||
* Those need to be fetched separately.</info>
|
||||
* @param {boolean} [cache=true] Whether to cache the message(s)
|
||||
* @returns {Promise<Collection<Snowflake, Message>>}
|
||||
* @example
|
||||
* // Get pinned messages
|
||||
* channel.fetchPinned()
|
||||
* .then(messages => console.log(`Received ${messages.size} messages`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetchPinned(cache = true) {
|
||||
return this.client.api.channels[this.channel.id].pins.get().then(data => {
|
||||
const messages = new Collection();
|
||||
@@ -94,23 +94,22 @@ class MessageManager extends BaseManager {
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a MessageResolvable to a Message object.
|
||||
* @method resolve
|
||||
* @memberof MessageManager
|
||||
* @instance
|
||||
* @param {MessageResolvable} message The message resolvable to resolve
|
||||
* @returns {?Message}
|
||||
*/
|
||||
* Resolves a MessageResolvable to a Message object.
|
||||
* @method resolve
|
||||
* @memberof MessageManager
|
||||
* @instance
|
||||
* @param {MessageResolvable} message The message resolvable to resolve
|
||||
* @returns {?Message}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a MessageResolvable to a Message ID string.
|
||||
* @method resolveID
|
||||
* @memberof MessageManager
|
||||
* @instance
|
||||
* @param {MessageResolvable} message The message resolvable to resolve
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
|
||||
* Resolves a MessageResolvable to a Message ID string.
|
||||
* @method resolveID
|
||||
* @memberof MessageManager
|
||||
* @instance
|
||||
* @param {MessageResolvable} message The message resolvable to resolve
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Deletes a message, even if it's not cached.
|
||||
@@ -119,7 +118,12 @@ class MessageManager extends BaseManager {
|
||||
*/
|
||||
async delete(message, reason) {
|
||||
message = this.resolveID(message);
|
||||
if (message) await this.client.api.channels(this.channel.id).messages(message).delete({ reason });
|
||||
if (message) {
|
||||
await this.client.api
|
||||
.channels(this.channel.id)
|
||||
.messages(message)
|
||||
.delete({ reason });
|
||||
}
|
||||
}
|
||||
|
||||
async _fetchId(messageID, cache) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const { Presence } = require('../structures/Presence');
|
||||
const BaseManager = require('./BaseManager');
|
||||
const { Presence } = require('../structures/Presence');
|
||||
|
||||
/**
|
||||
* Manages API methods for Presences and holds their cache.
|
||||
@@ -13,10 +13,10 @@ class PresenceManager extends BaseManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* The cache of Presences
|
||||
* @type {Collection<Snowflake, Presence>}
|
||||
* @name PresenceManager#cache
|
||||
*/
|
||||
* The cache of Presences
|
||||
* @type {Collection<Snowflake, Presence>}
|
||||
* @name PresenceManager#cache
|
||||
*/
|
||||
|
||||
add(data, cache) {
|
||||
const existing = this.cache.get(data.user.id);
|
||||
@@ -32,10 +32,10 @@ class PresenceManager extends BaseManager {
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a PresenceResolvable to a Presence object.
|
||||
* @param {PresenceResolvable} presence The presence resolvable to resolve
|
||||
* @returns {?Presence}
|
||||
*/
|
||||
* Resolves a PresenceResolvable to a Presence object.
|
||||
* @param {PresenceResolvable} presence The presence resolvable to resolve
|
||||
* @returns {?Presence}
|
||||
*/
|
||||
resolve(presence) {
|
||||
const presenceResolvable = super.resolve(presence);
|
||||
if (presenceResolvable) return presenceResolvable;
|
||||
@@ -44,10 +44,10 @@ class PresenceManager extends BaseManager {
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a PresenceResolvable to a Presence ID string.
|
||||
* @param {PresenceResolvable} presence The presence resolvable to resolve
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
* Resolves a PresenceResolvable to a Presence ID string.
|
||||
* @param {PresenceResolvable} presence The presence resolvable to resolve
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
resolveID(presence) {
|
||||
const presenceResolvable = super.resolveID(presence);
|
||||
if (presenceResolvable) return presenceResolvable;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const MessageReaction = require('../structures/MessageReaction');
|
||||
const BaseManager = require('./BaseManager');
|
||||
const MessageReaction = require('../structures/MessageReaction');
|
||||
|
||||
/**
|
||||
* Manages API methods for reactions and holds their cache.
|
||||
@@ -36,29 +36,32 @@ class ReactionManager extends BaseManager {
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a MessageReactionResolvable to a MessageReaction object.
|
||||
* @method resolve
|
||||
* @memberof ReactionManager
|
||||
* @instance
|
||||
* @param {MessageReactionResolvable} reaction The MessageReaction to resolve
|
||||
* @returns {?MessageReaction}
|
||||
*/
|
||||
* Resolves a MessageReactionResolvable to a MessageReaction object.
|
||||
* @method resolve
|
||||
* @memberof ReactionManager
|
||||
* @instance
|
||||
* @param {MessageReactionResolvable} reaction The MessageReaction to resolve
|
||||
* @returns {?MessageReaction}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Resolves a MessageReactionResolvable to a MessageReaction ID string.
|
||||
* @method resolveID
|
||||
* @memberof ReactionManager
|
||||
* @instance
|
||||
* @param {MessageReactionResolvable} reaction The MessageReaction to resolve
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
* Resolves a MessageReactionResolvable to a MessageReaction ID string.
|
||||
* @method resolveID
|
||||
* @memberof ReactionManager
|
||||
* @instance
|
||||
* @param {MessageReactionResolvable} reaction The MessageReaction to resolve
|
||||
* @returns {?Snowflake}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Removes all reactions from a message.
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
removeAll() {
|
||||
return this.client.api.channels(this.message.channel.id).messages(this.message.id).reactions.delete()
|
||||
return this.client.api
|
||||
.channels(this.message.channel.id)
|
||||
.messages(this.message.id)
|
||||
.reactions.delete()
|
||||
.then(() => this.message);
|
||||
}
|
||||
|
||||
@@ -72,7 +75,10 @@ class ReactionManager extends BaseManager {
|
||||
const id = reactionEmoji.id || reactionEmoji.name;
|
||||
const existing = this.cache.get(id);
|
||||
if (!this._partial(reactionEmoji)) return existing;
|
||||
const data = await this.client.api.channels(this.message.channel.id).messages(this.message.id).get();
|
||||
const data = await this.client.api
|
||||
.channels(this.message.channel.id)
|
||||
.messages(this.message.id)
|
||||
.get();
|
||||
if (this.message.partial) this.message._patch(data);
|
||||
if (!data.reactions || !data.reactions.some(r => (r.emoji.id || r.emoji.name) === id)) {
|
||||
reactionEmoji.reaction._patch({ count: 0 });
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const Collection = require('../util/Collection');
|
||||
const BaseManager = require('./BaseManager');
|
||||
const { Error } = require('../errors');
|
||||
const Collection = require('../util/Collection');
|
||||
|
||||
/**
|
||||
* Manages API methods for users who reacted to a reaction and stores their cache.
|
||||
@@ -34,9 +34,9 @@ class ReactionUserManager extends BaseManager {
|
||||
*/
|
||||
async fetch({ limit = 100, after, before } = {}) {
|
||||
const message = this.reaction.message;
|
||||
const data = await this.client.api.channels[message.channel.id].messages[message.id]
|
||||
.reactions[this.reaction.emoji.identifier]
|
||||
.get({ query: { limit, before, after } });
|
||||
const data = await this.client.api.channels[message.channel.id].messages[message.id].reactions[
|
||||
this.reaction.emoji.identifier
|
||||
].get({ query: { limit, before, after } });
|
||||
const users = new Collection();
|
||||
for (const rawUser of data) {
|
||||
const user = this.client.users.add(rawUser);
|
||||
@@ -55,8 +55,9 @@ class ReactionUserManager extends BaseManager {
|
||||
const message = this.reaction.message;
|
||||
const userID = message.client.users.resolveID(user);
|
||||
if (!userID) return Promise.reject(new Error('REACTION_RESOLVE_USER'));
|
||||
return message.client.api.channels[message.channel.id].messages[message.id]
|
||||
.reactions[this.reaction.emoji.identifier][userID === message.client.user.id ? '@me' : userID]
|
||||
return message.client.api.channels[message.channel.id].messages[message.id].reactions[
|
||||
this.reaction.emoji.identifier
|
||||
][userID === message.client.user.id ? '@me' : userID]
|
||||
.delete()
|
||||
.then(() => this.reaction);
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const Role = require('../structures/Role');
|
||||
const { resolveColor } = require('../util/Util');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const { resolveColor } = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Manages API methods for roles and stores their cache.
|
||||
@@ -110,14 +110,17 @@ class RoleManager extends BaseManager {
|
||||
if (data.color) data.color = resolveColor(data.color);
|
||||
if (data.permissions) data.permissions = Permissions.resolve(data.permissions);
|
||||
|
||||
return this.guild.client.api.guilds(this.guild.id).roles.post({ data, reason }).then(r => {
|
||||
const { role } = this.client.actions.GuildRoleCreate.handle({
|
||||
guild_id: this.guild.id,
|
||||
role: r,
|
||||
return this.guild.client.api
|
||||
.guilds(this.guild.id)
|
||||
.roles.post({ data, reason })
|
||||
.then(r => {
|
||||
const { role } = this.client.actions.GuildRoleCreate.handle({
|
||||
guild_id: this.guild.id,
|
||||
role: r,
|
||||
});
|
||||
if (data.position) return role.setPosition(data.position, reason);
|
||||
return role;
|
||||
});
|
||||
if (data.position) return role.setPosition(data.position, reason);
|
||||
return role;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -135,7 +138,7 @@ class RoleManager extends BaseManager {
|
||||
* @readonly
|
||||
*/
|
||||
get highest() {
|
||||
return this.cache.reduce((prev, role) => role.comparePositionTo(prev) > 0 ? role : prev, this.cache.first());
|
||||
return this.cache.reduce((prev, role) => (role.comparePositionTo(prev) > 0 ? role : prev), this.cache.first());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const BaseManager = require('./BaseManager');
|
||||
const User = require('../structures/User');
|
||||
const GuildMember = require('../structures/GuildMember');
|
||||
const Message = require('../structures/Message');
|
||||
const User = require('../structures/User');
|
||||
|
||||
/**
|
||||
* Manages API methods for users and stores their cache.
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
const FormData = require('form-data');
|
||||
const https = require('https');
|
||||
const { browser, UserAgent } = require('../util/Constants');
|
||||
const fetch = require('node-fetch');
|
||||
const AbortController = require('abort-controller');
|
||||
const FormData = require('form-data');
|
||||
const fetch = require('node-fetch');
|
||||
const { browser, UserAgent } = require('../util/Constants');
|
||||
|
||||
if (https.Agent) var agent = new https.Agent({ keepAlive: true });
|
||||
|
||||
@@ -26,8 +26,10 @@ class APIRequest {
|
||||
}
|
||||
|
||||
make() {
|
||||
const API = this.options.versioned === false ? this.client.options.http.api :
|
||||
`${this.client.options.http.api}/v${this.client.options.http.version}`;
|
||||
const API =
|
||||
this.options.versioned === false
|
||||
? this.client.options.http.api
|
||||
: `${this.client.options.http.api}/v${this.client.options.http.version}`;
|
||||
const url = API + this.path;
|
||||
let headers = {};
|
||||
|
||||
@@ -42,7 +44,8 @@ class APIRequest {
|
||||
for (const file of this.options.files) if (file && file.file) body.append(file.name, file.file, file.name);
|
||||
if (typeof this.options.data !== 'undefined') body.append('payload_json', JSON.stringify(this.options.data));
|
||||
if (!browser) headers = Object.assign(headers, body.getHeaders());
|
||||
} else if (this.options.data != null) { // eslint-disable-line eqeqeq
|
||||
// eslint-disable-next-line eqeqeq
|
||||
} else if (this.options.data != null) {
|
||||
body = JSON.stringify(this.options.data);
|
||||
headers['Content-Type'] = 'application/json';
|
||||
}
|
||||
|
||||
@@ -3,8 +3,12 @@
|
||||
const noop = () => {}; // eslint-disable-line no-empty-function
|
||||
const methods = ['get', 'post', 'delete', 'patch', 'put'];
|
||||
const reflectors = [
|
||||
'toString', 'valueOf', 'inspect', 'constructor',
|
||||
Symbol.toPrimitive, Symbol.for('nodejs.util.inspect.custom'),
|
||||
'toString',
|
||||
'valueOf',
|
||||
'inspect',
|
||||
'constructor',
|
||||
Symbol.toPrimitive,
|
||||
Symbol.for('nodejs.util.inspect.custom'),
|
||||
];
|
||||
|
||||
function buildRoute(manager) {
|
||||
@@ -22,10 +26,18 @@ function buildRoute(manager) {
|
||||
// All other parts of the route should be considered as part of the bucket identifier
|
||||
else routeBucket.push(route[i]);
|
||||
}
|
||||
return options => manager.request(name, route.join('/'), Object.assign({
|
||||
versioned: manager.versioned,
|
||||
route: routeBucket.join('/'),
|
||||
}, options));
|
||||
return options =>
|
||||
manager.request(
|
||||
name,
|
||||
route.join('/'),
|
||||
Object.assign(
|
||||
{
|
||||
versioned: manager.versioned,
|
||||
route: routeBucket.join('/'),
|
||||
},
|
||||
options,
|
||||
),
|
||||
);
|
||||
}
|
||||
route.push(name);
|
||||
return new Proxy(noop, handler);
|
||||
|
||||
@@ -48,7 +48,7 @@ class DiscordAPIError extends Error {
|
||||
|
||||
for (const [k, v] of Object.entries(obj)) {
|
||||
if (k === 'message') continue;
|
||||
const newKey = key ? isNaN(k) ? `${key}.${k}` : `${key}[${k}]` : k;
|
||||
const newKey = key ? (isNaN(k) ? `${key}.${k}` : `${key}[${k}]`) : k;
|
||||
|
||||
if (v._errors) {
|
||||
messages.push(`${newKey}: ${v._errors.map(e => e.message).join(' ')}`);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const RequestHandler = require('./RequestHandler');
|
||||
const APIRequest = require('./APIRequest');
|
||||
const routeBuilder = require('./APIRouter');
|
||||
const RequestHandler = require('./RequestHandler');
|
||||
const { Error } = require('../errors');
|
||||
const { Endpoints } = require('../util/Constants');
|
||||
const Collection = require('../util/Collection');
|
||||
const { Endpoints } = require('../util/Constants');
|
||||
|
||||
class RESTManager {
|
||||
constructor(client, tokenPrefix = 'Bot') {
|
||||
@@ -37,12 +37,14 @@ class RESTManager {
|
||||
|
||||
push(handler, apiRequest) {
|
||||
return new Promise((resolve, reject) => {
|
||||
handler.push({
|
||||
request: apiRequest,
|
||||
resolve,
|
||||
reject,
|
||||
retries: 0,
|
||||
}).catch(reject);
|
||||
handler
|
||||
.push({
|
||||
request: apiRequest,
|
||||
resolve,
|
||||
reject,
|
||||
retries: 0,
|
||||
})
|
||||
.catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,11 @@
|
||||
|
||||
const DiscordAPIError = require('./DiscordAPIError');
|
||||
const HTTPError = require('./HTTPError');
|
||||
const {
|
||||
Events: { RATE_LIMIT },
|
||||
browser,
|
||||
} = require('../util/Constants');
|
||||
const Util = require('../util/Util');
|
||||
const { Events: { RATE_LIMIT }, browser } = require('../util/Constants');
|
||||
|
||||
function parseResponse(res) {
|
||||
if (res.headers.get('content-type').startsWith('application/json')) return res.json();
|
||||
@@ -52,7 +55,6 @@ class RequestHandler {
|
||||
return this.queue.length === 0 && !this.limited && this.busy !== true;
|
||||
}
|
||||
|
||||
/* eslint-disable-next-line complexity */
|
||||
async execute(item) {
|
||||
// Insert item back to the beginning if currently busy
|
||||
if (this.busy) {
|
||||
@@ -102,9 +104,7 @@ class RequestHandler {
|
||||
} catch (error) {
|
||||
// NodeFetch error expected for all "operational" errors, such as 500 status code
|
||||
this.busy = false;
|
||||
return reject(
|
||||
new HTTPError(error.message, error.constructor.name, error.status, request.method, request.path),
|
||||
);
|
||||
return reject(new HTTPError(error.message, error.constructor.name, error.status, request.method, request.path));
|
||||
}
|
||||
|
||||
if (res && res.headers) {
|
||||
@@ -171,9 +171,7 @@ class RequestHandler {
|
||||
}
|
||||
return null;
|
||||
} catch (err) {
|
||||
return reject(
|
||||
new HTTPError(err.message, err.constructor.name, err.status, request.method, request.path),
|
||||
);
|
||||
return reject(new HTTPError(err.message, err.constructor.name, err.status, request.method, request.path));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
const EventEmitter = require('events');
|
||||
const path = require('path');
|
||||
const Util = require('../util/Util');
|
||||
const { Error } = require('../errors');
|
||||
const Util = require('../util/Util');
|
||||
let childProcess = null;
|
||||
let Worker = null;
|
||||
|
||||
@@ -111,9 +111,11 @@ class Shard extends EventEmitter {
|
||||
if (this.worker) throw new Error('SHARDING_WORKER_EXISTS', this.id);
|
||||
|
||||
if (this.manager.mode === 'process') {
|
||||
this.process = childProcess.fork(path.resolve(this.manager.file), this.args, {
|
||||
env: this.env, execArgv: this.execArgv,
|
||||
})
|
||||
this.process = childProcess
|
||||
.fork(path.resolve(this.manager.file), this.args, {
|
||||
env: this.env,
|
||||
execArgv: this.execArgv,
|
||||
})
|
||||
.on('message', this._handleMessage.bind(this))
|
||||
.on('exit', this._exitListener);
|
||||
} else if (this.manager.mode === 'worker') {
|
||||
@@ -203,7 +205,8 @@ class Shard extends EventEmitter {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.process) {
|
||||
this.process.send(message, err => {
|
||||
if (err) reject(err); else resolve(this);
|
||||
if (err) reject(err);
|
||||
else resolve(this);
|
||||
});
|
||||
} else {
|
||||
this.worker.postMessage(message);
|
||||
@@ -261,7 +264,8 @@ class Shard extends EventEmitter {
|
||||
if (!message || message._eval !== script) return;
|
||||
child.removeListener('message', listener);
|
||||
this._evals.delete(script);
|
||||
if (!message._error) resolve(message._result); else reject(Util.makeError(message._error));
|
||||
if (!message._error) resolve(message._result);
|
||||
else reject(Util.makeError(message._error));
|
||||
};
|
||||
child.on('message', listener);
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const Util = require('../util/Util');
|
||||
const { Events } = require('../util/Constants');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Helper class for sharded clients spawned as a child process/worker, such as from a {@link ShardingManager}.
|
||||
@@ -33,15 +33,27 @@ class ShardClientUtil {
|
||||
|
||||
if (mode === 'process') {
|
||||
process.on('message', this._handleMessage.bind(this));
|
||||
client.on('ready', () => { process.send({ _ready: true }); });
|
||||
client.on('disconnect', () => { process.send({ _disconnect: true }); });
|
||||
client.on('reconnecting', () => { process.send({ _reconnecting: true }); });
|
||||
client.on('ready', () => {
|
||||
process.send({ _ready: true });
|
||||
});
|
||||
client.on('disconnect', () => {
|
||||
process.send({ _disconnect: true });
|
||||
});
|
||||
client.on('reconnecting', () => {
|
||||
process.send({ _reconnecting: true });
|
||||
});
|
||||
} else if (mode === 'worker') {
|
||||
this.parentPort = require('worker_threads').parentPort;
|
||||
this.parentPort.on('message', this._handleMessage.bind(this));
|
||||
client.on('ready', () => { this.parentPort.postMessage({ _ready: true }); });
|
||||
client.on('disconnect', () => { this.parentPort.postMessage({ _disconnect: true }); });
|
||||
client.on('reconnecting', () => { this.parentPort.postMessage({ _reconnecting: true }); });
|
||||
client.on('ready', () => {
|
||||
this.parentPort.postMessage({ _ready: true });
|
||||
});
|
||||
client.on('disconnect', () => {
|
||||
this.parentPort.postMessage({ _disconnect: true });
|
||||
});
|
||||
client.on('reconnecting', () => {
|
||||
this.parentPort.postMessage({ _reconnecting: true });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,7 +84,8 @@ class ShardClientUtil {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (this.mode === 'process') {
|
||||
process.send(message, err => {
|
||||
if (err) reject(err); else resolve();
|
||||
if (err) reject(err);
|
||||
else resolve();
|
||||
});
|
||||
} else if (this.mode === 'worker') {
|
||||
this.parentPort.postMessage(message);
|
||||
@@ -98,7 +111,8 @@ class ShardClientUtil {
|
||||
const listener = message => {
|
||||
if (!message || message._sFetchProp !== prop) return;
|
||||
parent.removeListener('message', listener);
|
||||
if (!message._error) resolve(message._result); else reject(Util.makeError(message._error));
|
||||
if (!message._error) resolve(message._result);
|
||||
else reject(Util.makeError(message._error));
|
||||
};
|
||||
parent.on('message', listener);
|
||||
|
||||
@@ -127,7 +141,8 @@ class ShardClientUtil {
|
||||
const listener = message => {
|
||||
if (!message || message._sEval !== script) return;
|
||||
parent.removeListener('message', listener);
|
||||
if (!message._error) resolve(message._result); else reject(Util.makeError(message._error));
|
||||
if (!message._error) resolve(message._result);
|
||||
else reject(Util.makeError(message._error));
|
||||
};
|
||||
parent.on('message', listener);
|
||||
|
||||
@@ -201,8 +216,10 @@ class ShardClientUtil {
|
||||
if (!this._singleton) {
|
||||
this._singleton = new this(client, mode);
|
||||
} else {
|
||||
client.emit(Events.WARN,
|
||||
'Multiple clients created in child process/worker; only the first will handle sharding helpers.');
|
||||
client.emit(
|
||||
Events.WARN,
|
||||
'Multiple clients created in child process/worker; only the first will handle sharding helpers.',
|
||||
);
|
||||
}
|
||||
return this._singleton;
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const EventEmitter = require('events');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const Shard = require('./Shard');
|
||||
const { Error, TypeError, RangeError } = require('../errors');
|
||||
const Collection = require('../util/Collection');
|
||||
const Util = require('../util/Util');
|
||||
const { Error, TypeError, RangeError } = require('../errors');
|
||||
|
||||
/**
|
||||
* This is a utility class that makes multi-process sharding of a bot an easy and painless experience.
|
||||
@@ -41,14 +41,17 @@ class ShardingManager extends EventEmitter {
|
||||
*/
|
||||
constructor(file, options = {}) {
|
||||
super();
|
||||
options = Util.mergeDefault({
|
||||
totalShards: 'auto',
|
||||
mode: 'process',
|
||||
respawn: true,
|
||||
shardArgs: [],
|
||||
execArgv: [],
|
||||
token: process.env.DISCORD_TOKEN,
|
||||
}, options);
|
||||
options = Util.mergeDefault(
|
||||
{
|
||||
totalShards: 'auto',
|
||||
mode: 'process',
|
||||
respawn: true,
|
||||
shardArgs: [],
|
||||
execArgv: [],
|
||||
token: process.env.DISCORD_TOKEN,
|
||||
},
|
||||
options,
|
||||
);
|
||||
|
||||
/**
|
||||
* Path to the shard script file
|
||||
@@ -71,8 +74,11 @@ class ShardingManager extends EventEmitter {
|
||||
}
|
||||
this.shardList = [...new Set(this.shardList)];
|
||||
if (this.shardList.length < 1) throw new RangeError('CLIENT_INVALID_OPTION', 'shardList', 'at least 1 ID.');
|
||||
if (this.shardList.some(shardID => typeof shardID !== 'number' || isNaN(shardID) ||
|
||||
!Number.isInteger(shardID) || shardID < 0)) {
|
||||
if (
|
||||
this.shardList.some(
|
||||
shardID => typeof shardID !== 'number' || isNaN(shardID) || !Number.isInteger(shardID) || shardID < 0,
|
||||
)
|
||||
) {
|
||||
throw new TypeError('CLIENT_INVALID_OPTION', 'shardList', 'an array of positive integers.');
|
||||
}
|
||||
}
|
||||
@@ -186,8 +192,11 @@ class ShardingManager extends EventEmitter {
|
||||
}
|
||||
|
||||
if (this.shardList.some(shardID => shardID >= amount)) {
|
||||
throw new RangeError('CLIENT_INVALID_OPTION', 'Amount of shards',
|
||||
'bigger than the highest shardID in the shardList option.');
|
||||
throw new RangeError(
|
||||
'CLIENT_INVALID_OPTION',
|
||||
'Amount of shards',
|
||||
'bigger than the highest shardID in the shardList option.',
|
||||
);
|
||||
}
|
||||
|
||||
// Spawn the shards
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const MessageEmbed = require('./MessageEmbed');
|
||||
const MessageAttachment = require('./MessageAttachment');
|
||||
const { browser } = require('../util/Constants');
|
||||
const Util = require('../util/Util');
|
||||
const MessageEmbed = require('./MessageEmbed');
|
||||
const { RangeError } = require('../errors');
|
||||
const { browser } = require('../util/Constants');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const MessageFlags = require('../util/MessageFlags');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents a message to be sent to the API.
|
||||
@@ -78,7 +78,7 @@ class APIMessage {
|
||||
* Makes the content of this message.
|
||||
* @returns {?(string|string[])}
|
||||
*/
|
||||
makeContent() { // eslint-disable-line complexity
|
||||
makeContent() {
|
||||
const GuildMember = require('./GuildMember');
|
||||
|
||||
let content;
|
||||
@@ -88,13 +88,14 @@ class APIMessage {
|
||||
content = Util.resolveString(this.options.content);
|
||||
}
|
||||
|
||||
const disableMentions = typeof this.options.disableMentions === 'undefined' ?
|
||||
this.target.client.options.disableMentions :
|
||||
this.options.disableMentions;
|
||||
const disableMentions =
|
||||
typeof this.options.disableMentions === 'undefined'
|
||||
? this.target.client.options.disableMentions
|
||||
: this.options.disableMentions;
|
||||
if (disableMentions === 'all') {
|
||||
content = Util.removeMentions(content || '');
|
||||
} else if (disableMentions === 'everyone') {
|
||||
content = (content || '').replace(/@([^<>@ ]*)/gsmu, (match, target) => {
|
||||
content = (content || '').replace(/@([^<>@ ]*)/gmsu, (match, target) => {
|
||||
if (target.match(/^[&!]?\d+$/)) {
|
||||
return `@${target}`;
|
||||
} else {
|
||||
@@ -270,7 +271,8 @@ class APIMessage {
|
||||
return 'file.jpg';
|
||||
};
|
||||
|
||||
const ownAttachment = typeof fileLike === 'string' ||
|
||||
const ownAttachment =
|
||||
typeof fileLike === 'string' ||
|
||||
fileLike instanceof (browser ? ArrayBuffer : Buffer) ||
|
||||
typeof fileLike.pipe === 'function';
|
||||
if (ownAttachment) {
|
||||
|
||||
@@ -20,7 +20,9 @@ class Base {
|
||||
return Object.assign(Object.create(this), this);
|
||||
}
|
||||
|
||||
_patch(data) { return data; }
|
||||
_patch(data) {
|
||||
return data;
|
||||
}
|
||||
|
||||
_update(data) {
|
||||
const clone = this._clone();
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
const Base = require('./Base');
|
||||
const { ChannelTypes } = require('../util/Constants');
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
|
||||
/**
|
||||
* Represents any channel on Discord.
|
||||
@@ -82,7 +82,10 @@ class Channel extends Base {
|
||||
* .catch(console.error);
|
||||
*/
|
||||
delete() {
|
||||
return this.client.api.channels(this.id).delete().then(() => this);
|
||||
return this.client.api
|
||||
.channels(this.id)
|
||||
.delete()
|
||||
.then(() => this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
const { ClientApplicationAssetTypes, Endpoints } = require('../util/Constants');
|
||||
const Base = require('./Base');
|
||||
const Team = require('./Team');
|
||||
const { ClientApplicationAssetTypes, Endpoints } = require('../util/Constants');
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
|
||||
const AssetTypes = Object.keys(ClientApplicationAssetTypes);
|
||||
|
||||
@@ -70,11 +70,7 @@ class ClientApplication extends Base {
|
||||
* The owner of this OAuth application
|
||||
* @type {?User|Team}
|
||||
*/
|
||||
this.owner = data.team ?
|
||||
new Team(this.client, data.team) :
|
||||
data.owner ?
|
||||
this.client.users.add(data.owner) :
|
||||
null;
|
||||
this.owner = data.team ? new Team(this.client, data.team) : data.owner ? this.client.users.add(data.owner) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,9 +108,7 @@ class ClientApplication extends Base {
|
||||
*/
|
||||
coverImage({ format, size } = {}) {
|
||||
if (!this.cover) return null;
|
||||
return Endpoints
|
||||
.CDN(this.client.options.http.cdn)
|
||||
.AppIcon(this.id, this.cover, { format, size });
|
||||
return Endpoints.CDN(this.client.options.http.cdn).AppIcon(this.id, this.cover, { format, size });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,12 +124,16 @@ class ClientApplication extends Base {
|
||||
* @returns {Promise<Array<ClientAsset>>}
|
||||
*/
|
||||
fetchAssets() {
|
||||
return this.client.api.oauth2.applications(this.id).assets.get()
|
||||
.then(assets => assets.map(a => ({
|
||||
id: a.id,
|
||||
name: a.name,
|
||||
type: AssetTypes[a.type - 1],
|
||||
})));
|
||||
return this.client.api.oauth2
|
||||
.applications(this.id)
|
||||
.assets.get()
|
||||
.then(assets =>
|
||||
assets.map(a => ({
|
||||
id: a.id,
|
||||
name: a.name,
|
||||
type: AssetTypes[a.type - 1],
|
||||
})),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const { Presence } = require('./Presence');
|
||||
const { TypeError } = require('../errors');
|
||||
const Collection = require('../util/Collection');
|
||||
const { ActivityTypes, OPCodes } = require('../util/Constants');
|
||||
const { TypeError } = require('../errors');
|
||||
|
||||
class ClientPresence extends Presence {
|
||||
/**
|
||||
@@ -29,7 +29,7 @@ class ClientPresence extends Presence {
|
||||
return this;
|
||||
}
|
||||
|
||||
async _parse({ status, since, afk, activity }) { // eslint-disable-line complexity
|
||||
async _parse({ status, since, afk, activity }) {
|
||||
const applicationID = activity && (activity.application ? activity.application.id || activity.application : null);
|
||||
let assets = new Collection();
|
||||
if (activity) {
|
||||
@@ -47,24 +47,28 @@ class ClientPresence extends Presence {
|
||||
afk: afk != null ? afk : false, // eslint-disable-line eqeqeq
|
||||
since: since != null ? since : null, // eslint-disable-line eqeqeq
|
||||
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,
|
||||
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 ((status || afk || since) && !activity) {
|
||||
@@ -72,8 +76,8 @@ class ClientPresence extends Presence {
|
||||
}
|
||||
|
||||
if (packet.game) {
|
||||
packet.game.type = typeof packet.game.type === 'number' ?
|
||||
packet.game.type : ActivityTypes.indexOf(packet.game.type);
|
||||
packet.game.type =
|
||||
typeof packet.game.type === 'number' ? packet.game.type : ActivityTypes.indexOf(packet.game.type);
|
||||
}
|
||||
|
||||
return packet;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const Structures = require('../util/Structures');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const Structures = require('../util/Structures');
|
||||
|
||||
/**
|
||||
* Represents the logged in client's Discord user.
|
||||
@@ -47,7 +47,9 @@ class ClientUser extends Structures.get('User') {
|
||||
}
|
||||
|
||||
edit(data) {
|
||||
return this.client.api.users('@me').patch({ data })
|
||||
return this.client.api
|
||||
.users('@me')
|
||||
.patch({ data })
|
||||
.then(newData => {
|
||||
this.client.token = newData.token;
|
||||
const { updated } = this.client.actions.UserUpdate.handle(newData);
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
const Base = require('./Base');
|
||||
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
|
||||
/**
|
||||
* Represents an emoji, see {@link GuildEmoji} and {@link ReactionEmoji}.
|
||||
|
||||
@@ -1,10 +1,18 @@
|
||||
'use strict';
|
||||
|
||||
const Invite = require('./Invite');
|
||||
const Integration = require('./Integration');
|
||||
const Base = require('./Base');
|
||||
const GuildAuditLogs = require('./GuildAuditLogs');
|
||||
const Webhook = require('./Webhook');
|
||||
const Integration = require('./Integration');
|
||||
const Invite = require('./Invite');
|
||||
const VoiceRegion = require('./VoiceRegion');
|
||||
const Webhook = require('./Webhook');
|
||||
const GuildChannelManager = require('../src/managers/GuildChannelManager');
|
||||
const GuildEmojiManager = require('../src/managers/GuildEmojiManager');
|
||||
const GuildMemberManager = require('../src/managers/GuildMemberManager');
|
||||
const PresenceManager = require('../src/managers/PresenceManager');
|
||||
const RoleManager = require('../src/managers/RoleManager');
|
||||
const VoiceStateManager = require('../src/managers/VoiceStateManager');
|
||||
const Collection = require('../util/Collection');
|
||||
const {
|
||||
ChannelTypes,
|
||||
DefaultMessageNotifications,
|
||||
@@ -12,19 +20,10 @@ const {
|
||||
VerificationLevels,
|
||||
ExplicitContentFilterLevels,
|
||||
} = require('../util/Constants');
|
||||
const Collection = require('../util/Collection');
|
||||
const Util = require('../util/Util');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
const SystemChannelFlags = require('../util/SystemChannelFlags');
|
||||
const GuildMemberManager = require('../managers/GuildMemberManager');
|
||||
const RoleManager = require('../managers/RoleManager');
|
||||
const GuildEmojiManager = require('../managers/GuildEmojiManager');
|
||||
const GuildChannelManager = require('../managers/GuildChannelManager');
|
||||
const PresenceManager = require('../managers/PresenceManager');
|
||||
const VoiceStateManager = require('../managers/VoiceStateManager');
|
||||
const Base = require('./Base');
|
||||
const { Error, TypeError } = require('../errors');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents a guild (or a server) on Discord.
|
||||
@@ -110,7 +109,6 @@ class Guild extends Base {
|
||||
return this.client.ws.shards.get(this.shardID);
|
||||
}
|
||||
|
||||
/* eslint-disable complexity */
|
||||
/**
|
||||
* Sets up the guild.
|
||||
* @param {*} data The raw data of the guild
|
||||
@@ -279,8 +277,8 @@ class Guild extends Base {
|
||||
* The value set for the guild's default message notifications
|
||||
* @type {DefaultMessageNotifications|number}
|
||||
*/
|
||||
this.defaultMessageNotifications = DefaultMessageNotifications[data.default_message_notifications] ||
|
||||
data.default_message_notifications;
|
||||
this.defaultMessageNotifications =
|
||||
DefaultMessageNotifications[data.default_message_notifications] || data.default_message_notifications;
|
||||
|
||||
/**
|
||||
* The value set for the guild's system channel flags
|
||||
@@ -483,9 +481,12 @@ class Guild extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get owner() {
|
||||
return this.members.cache.get(this.ownerID) || (this.client.options.partials.includes(PartialTypes.GUILD_MEMBER) ?
|
||||
this.members.add({ user: { id: this.ownerID } }, true) :
|
||||
null);
|
||||
return (
|
||||
this.members.cache.get(this.ownerID) ||
|
||||
(this.client.options.partials.includes(PartialTypes.GUILD_MEMBER)
|
||||
? this.members.add({ user: { id: this.ownerID } }, true)
|
||||
: null)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -550,10 +551,12 @@ class Guild extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get me() {
|
||||
return this.members.cache.get(this.client.user.id) ||
|
||||
(this.client.options.partials.includes(PartialTypes.GUILD_MEMBER) ?
|
||||
this.members.add({ user: { id: this.client.user.id } }, true) :
|
||||
null);
|
||||
return (
|
||||
this.members.cache.get(this.client.user.id) ||
|
||||
(this.client.options.partials.includes(PartialTypes.GUILD_MEMBER)
|
||||
? this.members.add({ user: { id: this.client.user.id } }, true)
|
||||
: null)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -582,10 +585,13 @@ class Guild extends Base {
|
||||
* @returns {Promise<Guild>}
|
||||
*/
|
||||
fetch() {
|
||||
return this.client.api.guilds(this.id).get().then(data => {
|
||||
this._patch(data);
|
||||
return this;
|
||||
});
|
||||
return this.client.api
|
||||
.guilds(this.id)
|
||||
.get()
|
||||
.then(data => {
|
||||
this._patch(data);
|
||||
return this;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -596,14 +602,17 @@ class Guild extends Base {
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fetches information on a banned user from this guild.
|
||||
* Fetches information on a banned user from this guild.
|
||||
* @param {UserResolvable} user The User to fetch the ban info of
|
||||
* @returns {Promise<BanInfo>}
|
||||
*/
|
||||
fetchBan(user) {
|
||||
const id = this.client.users.resolveID(user);
|
||||
if (!id) throw new Error('FETCH_BAN_RESOLVE_ID');
|
||||
return this.client.api.guilds(this.id).bans(id).get()
|
||||
return this.client.api
|
||||
.guilds(this.id)
|
||||
.bans(id)
|
||||
.get()
|
||||
.then(ban => ({
|
||||
reason: ban.reason,
|
||||
user: this.client.users.add(ban.user),
|
||||
@@ -615,15 +624,18 @@ class Guild extends Base {
|
||||
* @returns {Promise<Collection<Snowflake, BanInfo>>}
|
||||
*/
|
||||
fetchBans() {
|
||||
return this.client.api.guilds(this.id).bans.get().then(bans =>
|
||||
bans.reduce((collection, ban) => {
|
||||
collection.set(ban.user.id, {
|
||||
reason: ban.reason,
|
||||
user: this.client.users.add(ban.user),
|
||||
});
|
||||
return collection;
|
||||
}, new Collection()),
|
||||
);
|
||||
return this.client.api
|
||||
.guilds(this.id)
|
||||
.bans.get()
|
||||
.then(bans =>
|
||||
bans.reduce((collection, ban) => {
|
||||
collection.set(ban.user.id, {
|
||||
reason: ban.reason,
|
||||
user: this.client.users.add(ban.user),
|
||||
});
|
||||
return collection;
|
||||
}, new Collection()),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -637,11 +649,15 @@ class Guild extends Base {
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetchIntegrations() {
|
||||
return this.client.api.guilds(this.id).integrations.get().then(data =>
|
||||
data.reduce((collection, integration) =>
|
||||
collection.set(integration.id, new Integration(this.client, integration, this)),
|
||||
new Collection()),
|
||||
);
|
||||
return this.client.api
|
||||
.guilds(this.id)
|
||||
.integrations.get()
|
||||
.then(data =>
|
||||
data.reduce(
|
||||
(collection, integration) => collection.set(integration.id, new Integration(this.client, integration, this)),
|
||||
new Collection(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -658,7 +674,9 @@ class Guild extends Base {
|
||||
* @returns {Promise<Guild>}
|
||||
*/
|
||||
createIntegration(data, reason) {
|
||||
return this.client.api.guilds(this.id).integrations.post({ data, reason })
|
||||
return this.client.api
|
||||
.guilds(this.id)
|
||||
.integrations.post({ data, reason })
|
||||
.then(() => this);
|
||||
}
|
||||
|
||||
@@ -678,7 +696,9 @@ class Guild extends Base {
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetchInvites() {
|
||||
return this.client.api.guilds(this.id).invites.get()
|
||||
return this.client.api
|
||||
.guilds(this.id)
|
||||
.invites.get()
|
||||
.then(inviteItems => {
|
||||
const invites = new Collection();
|
||||
for (const inviteItem of inviteItems) {
|
||||
@@ -705,7 +725,9 @@ class Guild extends Base {
|
||||
if (!this.features.includes('VANITY_URL')) {
|
||||
return Promise.reject(new Error('VANITY_URL'));
|
||||
}
|
||||
return this.client.api.guilds(this.id, 'vanity-url').get()
|
||||
return this.client.api
|
||||
.guilds(this.id, 'vanity-url')
|
||||
.get()
|
||||
.then(res => res.code);
|
||||
}
|
||||
|
||||
@@ -719,11 +741,14 @@ class Guild extends Base {
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetchWebhooks() {
|
||||
return this.client.api.guilds(this.id).webhooks.get().then(data => {
|
||||
const hooks = new Collection();
|
||||
for (const hook of data) hooks.set(hook.id, new Webhook(this.client, hook));
|
||||
return hooks;
|
||||
});
|
||||
return this.client.api
|
||||
.guilds(this.id)
|
||||
.webhooks.get()
|
||||
.then(data => {
|
||||
const hooks = new Collection();
|
||||
for (const hook of data) hooks.set(hook.id, new Webhook(this.client, hook));
|
||||
return hooks;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -731,11 +756,14 @@ class Guild extends Base {
|
||||
* @returns {Promise<Collection<string, VoiceRegion>>}
|
||||
*/
|
||||
fetchVoiceRegions() {
|
||||
return this.client.api.guilds(this.id).regions.get().then(res => {
|
||||
const regions = new Collection();
|
||||
for (const region of res) regions.set(region.id, new VoiceRegion(region));
|
||||
return regions;
|
||||
});
|
||||
return this.client.api
|
||||
.guilds(this.id)
|
||||
.regions.get()
|
||||
.then(res => {
|
||||
const regions = new Collection();
|
||||
for (const region of res) regions.set(region.id, new VoiceRegion(region));
|
||||
return regions;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -755,10 +783,13 @@ class Guild extends Base {
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetchEmbed() {
|
||||
return this.client.api.guilds(this.id).embed.get().then(data => ({
|
||||
enabled: data.enabled,
|
||||
channel: data.channel_id ? this.channels.cache.get(data.channel_id) : null,
|
||||
}));
|
||||
return this.client.api
|
||||
.guilds(this.id)
|
||||
.embed.get()
|
||||
.then(data => ({
|
||||
enabled: data.enabled,
|
||||
channel: data.channel_id ? this.channels.cache.get(data.channel_id) : null,
|
||||
}));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -779,12 +810,16 @@ class Guild extends Base {
|
||||
if (options.before && options.before instanceof GuildAuditLogs.Entry) options.before = options.before.id;
|
||||
if (typeof options.type === 'string') options.type = GuildAuditLogs.Actions[options.type];
|
||||
|
||||
return this.client.api.guilds(this.id)['audit-logs'].get({ query: {
|
||||
before: options.before,
|
||||
limit: options.limit,
|
||||
user_id: this.client.users.resolveID(options.user),
|
||||
action_type: options.type,
|
||||
} })
|
||||
return this.client.api
|
||||
.guilds(this.id)
|
||||
['audit-logs'].get({
|
||||
query: {
|
||||
before: options.before,
|
||||
limit: options.limit,
|
||||
user_id: this.client.users.resolveID(options.user),
|
||||
action_type: options.type,
|
||||
},
|
||||
})
|
||||
.then(data => GuildAuditLogs.build(this, data));
|
||||
}
|
||||
|
||||
@@ -811,14 +846,18 @@ class Guild extends Base {
|
||||
for (let role of options.roles instanceof Collection ? options.roles.values() : options.roles) {
|
||||
role = this.roles.resolve(role);
|
||||
if (!role) {
|
||||
return Promise.reject(new TypeError('INVALID_TYPE', 'options.roles',
|
||||
'Array or Collection of Roles or Snowflakes', true));
|
||||
return Promise.reject(
|
||||
new TypeError('INVALID_TYPE', 'options.roles', 'Array or Collection of Roles or Snowflakes', true),
|
||||
);
|
||||
}
|
||||
roles.push(role.id);
|
||||
}
|
||||
options.roles = roles;
|
||||
}
|
||||
return this.client.api.guilds(this.id).members(user).put({ data: options })
|
||||
return this.client.api
|
||||
.guilds(this.id)
|
||||
.members(user)
|
||||
.put({ data: options })
|
||||
.then(data => this.members.add(data));
|
||||
}
|
||||
|
||||
@@ -859,9 +898,10 @@ class Guild extends Base {
|
||||
if (data.name) _data.name = data.name;
|
||||
if (data.region) _data.region = data.region;
|
||||
if (typeof data.verificationLevel !== 'undefined') {
|
||||
_data.verification_level = typeof data.verificationLevel === 'number' ?
|
||||
Number(data.verificationLevel) :
|
||||
ExplicitContentFilterLevels.indexOf(data.verificationLevel);
|
||||
_data.verification_level =
|
||||
typeof data.verificationLevel === 'number'
|
||||
? Number(data.verificationLevel)
|
||||
: ExplicitContentFilterLevels.indexOf(data.verificationLevel);
|
||||
}
|
||||
if (typeof data.afkChannel !== 'undefined') {
|
||||
_data.afk_channel_id = this.client.channels.resolveID(data.afkChannel);
|
||||
@@ -875,19 +915,23 @@ class Guild extends Base {
|
||||
if (data.splash) _data.splash = data.splash;
|
||||
if (data.banner) _data.banner = data.banner;
|
||||
if (typeof data.explicitContentFilter !== 'undefined') {
|
||||
_data.explicit_content_filter = typeof data.explicitContentFilter === 'number' ?
|
||||
data.explicitContentFilter :
|
||||
ExplicitContentFilterLevels.indexOf(data.explicitContentFilter);
|
||||
_data.explicit_content_filter =
|
||||
typeof data.explicitContentFilter === 'number'
|
||||
? data.explicitContentFilter
|
||||
: ExplicitContentFilterLevels.indexOf(data.explicitContentFilter);
|
||||
}
|
||||
if (typeof data.defaultMessageNotifications !== 'undefined') {
|
||||
_data.default_message_notifications = typeof data.defaultMessageNotifications === 'string' ?
|
||||
DefaultMessageNotifications.indexOf(data.defaultMessageNotifications) :
|
||||
data.defaultMessageNotifications;
|
||||
_data.default_message_notifications =
|
||||
typeof data.defaultMessageNotifications === 'string'
|
||||
? DefaultMessageNotifications.indexOf(data.defaultMessageNotifications)
|
||||
: data.defaultMessageNotifications;
|
||||
}
|
||||
if (typeof data.systemChannelFlags !== 'undefined') {
|
||||
_data.system_channel_flags = SystemChannelFlags.resolve(data.systemChannelFlags);
|
||||
}
|
||||
return this.client.api.guilds(this.id).patch({ data: _data, reason })
|
||||
return this.client.api
|
||||
.guilds(this.id)
|
||||
.patch({ data: _data, reason })
|
||||
.then(newData => this.client.actions.GuildUpdate.handle(newData).updated);
|
||||
}
|
||||
|
||||
@@ -1094,12 +1138,16 @@ class Guild extends Base {
|
||||
position: r.position,
|
||||
}));
|
||||
|
||||
return this.client.api.guilds(this.id).channels.patch({ data: updatedChannels }).then(() =>
|
||||
this.client.actions.GuildChannelsPositionUpdate.handle({
|
||||
guild_id: this.id,
|
||||
channels: updatedChannels,
|
||||
}).guild,
|
||||
);
|
||||
return this.client.api
|
||||
.guilds(this.id)
|
||||
.channels.patch({ data: updatedChannels })
|
||||
.then(
|
||||
() =>
|
||||
this.client.actions.GuildChannelsPositionUpdate.handle({
|
||||
guild_id: this.id,
|
||||
channels: updatedChannels,
|
||||
}).guild,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1126,14 +1174,18 @@ class Guild extends Base {
|
||||
}));
|
||||
|
||||
// Call the API to update role positions
|
||||
return this.client.api.guilds(this.id).roles.patch({
|
||||
data: rolePositions,
|
||||
}).then(() =>
|
||||
this.client.actions.GuildRolePositionUpdate.handle({
|
||||
guild_id: this.id,
|
||||
roles: rolePositions,
|
||||
}).guild,
|
||||
);
|
||||
return this.client.api
|
||||
.guilds(this.id)
|
||||
.roles.patch({
|
||||
data: rolePositions,
|
||||
})
|
||||
.then(
|
||||
() =>
|
||||
this.client.actions.GuildRolePositionUpdate.handle({
|
||||
guild_id: this.id,
|
||||
roles: rolePositions,
|
||||
}).guild,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1143,13 +1195,16 @@ class Guild extends Base {
|
||||
* @returns {Promise<Guild>}
|
||||
*/
|
||||
setEmbed(embed, reason) {
|
||||
return this.client.api.guilds(this.id).embed.patch({
|
||||
data: {
|
||||
enabled: embed.enabled,
|
||||
channel_id: this.channels.resolveID(embed.channel),
|
||||
},
|
||||
reason,
|
||||
}).then(() => this);
|
||||
return this.client.api
|
||||
.guilds(this.id)
|
||||
.embed.patch({
|
||||
data: {
|
||||
enabled: embed.enabled,
|
||||
channel_id: this.channels.resolveID(embed.channel),
|
||||
},
|
||||
reason,
|
||||
})
|
||||
.then(() => this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1163,7 +1218,10 @@ class Guild extends Base {
|
||||
*/
|
||||
leave() {
|
||||
if (this.ownerID === this.client.user.id) return Promise.reject(new Error('GUILD_OWNED'));
|
||||
return this.client.api.users('@me').guilds(this.id).delete()
|
||||
return this.client.api
|
||||
.users('@me')
|
||||
.guilds(this.id)
|
||||
.delete()
|
||||
.then(() => this.client.actions.GuildDelete.handle({ id: this.id }).guild);
|
||||
}
|
||||
|
||||
@@ -1177,7 +1235,9 @@ class Guild extends Base {
|
||||
* .catch(console.error);
|
||||
*/
|
||||
delete() {
|
||||
return this.client.api.guilds(this.id).delete()
|
||||
return this.client.api
|
||||
.guilds(this.id)
|
||||
.delete()
|
||||
.then(() => this.client.actions.GuildDelete.handle({ id: this.id }).guild);
|
||||
}
|
||||
|
||||
@@ -1203,10 +1263,9 @@ class Guild extends Base {
|
||||
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]))
|
||||
);
|
||||
(this.features === guild.features ||
|
||||
(this.features.length === guild.features.length &&
|
||||
this.features.every((feat, i) => feat === guild.features[i])));
|
||||
|
||||
if (equal) {
|
||||
if (this.embedChannel) {
|
||||
@@ -1261,9 +1320,9 @@ class Guild extends Base {
|
||||
*/
|
||||
_sortedChannels(channel) {
|
||||
const category = channel.type === ChannelTypes.CATEGORY;
|
||||
return Util.discordSort(this.channels.cache.filter(c =>
|
||||
c.type === channel.type && (category || c.parent === channel.parent),
|
||||
));
|
||||
return Util.discordSort(
|
||||
this.channels.cache.filter(c => c.type === channel.type && (category || c.parent === channel.parent)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const Collection = require('../util/Collection');
|
||||
const Integration = require('./Integration');
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
const Webhook = require('./Webhook');
|
||||
const Util = require('../util/Util');
|
||||
const Collection = require('../util/Collection');
|
||||
const { PartialTypes } = require('../util/Constants');
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* The target type of an entry, e.g. `GUILD`. Here are the available types:
|
||||
@@ -125,7 +125,6 @@ const Actions = {
|
||||
INTEGRATION_DELETE: 82,
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Audit logs entries are held in this class.
|
||||
*/
|
||||
@@ -223,49 +222,61 @@ class GuildAuditLogs {
|
||||
* @returns {AuditLogActionType}
|
||||
*/
|
||||
static actionType(action) {
|
||||
if ([
|
||||
Actions.CHANNEL_CREATE,
|
||||
Actions.CHANNEL_OVERWRITE_CREATE,
|
||||
Actions.MEMBER_BAN_REMOVE,
|
||||
Actions.BOT_ADD,
|
||||
Actions.ROLE_CREATE,
|
||||
Actions.INVITE_CREATE,
|
||||
Actions.WEBHOOK_CREATE,
|
||||
Actions.EMOJI_CREATE,
|
||||
Actions.MESSAGE_PIN,
|
||||
Actions.INTEGRATION_CREATE,
|
||||
].includes(action)) return 'CREATE';
|
||||
if (
|
||||
[
|
||||
Actions.CHANNEL_CREATE,
|
||||
Actions.CHANNEL_OVERWRITE_CREATE,
|
||||
Actions.MEMBER_BAN_REMOVE,
|
||||
Actions.BOT_ADD,
|
||||
Actions.ROLE_CREATE,
|
||||
Actions.INVITE_CREATE,
|
||||
Actions.WEBHOOK_CREATE,
|
||||
Actions.EMOJI_CREATE,
|
||||
Actions.MESSAGE_PIN,
|
||||
Actions.INTEGRATION_CREATE,
|
||||
].includes(action)
|
||||
) {
|
||||
return 'CREATE';
|
||||
}
|
||||
|
||||
if ([
|
||||
Actions.CHANNEL_DELETE,
|
||||
Actions.CHANNEL_OVERWRITE_DELETE,
|
||||
Actions.MEMBER_KICK,
|
||||
Actions.MEMBER_PRUNE,
|
||||
Actions.MEMBER_BAN_ADD,
|
||||
Actions.MEMBER_DISCONNECT,
|
||||
Actions.ROLE_DELETE,
|
||||
Actions.INVITE_DELETE,
|
||||
Actions.WEBHOOK_DELETE,
|
||||
Actions.EMOJI_DELETE,
|
||||
Actions.MESSAGE_DELETE,
|
||||
Actions.MESSAGE_BULK_DELETE,
|
||||
Actions.MESSAGE_UNPIN,
|
||||
Actions.INTEGRATION_DELETE,
|
||||
].includes(action)) return 'DELETE';
|
||||
if (
|
||||
[
|
||||
Actions.CHANNEL_DELETE,
|
||||
Actions.CHANNEL_OVERWRITE_DELETE,
|
||||
Actions.MEMBER_KICK,
|
||||
Actions.MEMBER_PRUNE,
|
||||
Actions.MEMBER_BAN_ADD,
|
||||
Actions.MEMBER_DISCONNECT,
|
||||
Actions.ROLE_DELETE,
|
||||
Actions.INVITE_DELETE,
|
||||
Actions.WEBHOOK_DELETE,
|
||||
Actions.EMOJI_DELETE,
|
||||
Actions.MESSAGE_DELETE,
|
||||
Actions.MESSAGE_BULK_DELETE,
|
||||
Actions.MESSAGE_UNPIN,
|
||||
Actions.INTEGRATION_DELETE,
|
||||
].includes(action)
|
||||
) {
|
||||
return 'DELETE';
|
||||
}
|
||||
|
||||
if ([
|
||||
Actions.GUILD_UPDATE,
|
||||
Actions.CHANNEL_UPDATE,
|
||||
Actions.CHANNEL_OVERWRITE_UPDATE,
|
||||
Actions.MEMBER_UPDATE,
|
||||
Actions.MEMBER_ROLE_UPDATE,
|
||||
Actions.MEMBER_MOVE,
|
||||
Actions.ROLE_UPDATE,
|
||||
Actions.INVITE_UPDATE,
|
||||
Actions.WEBHOOK_UPDATE,
|
||||
Actions.EMOJI_UPDATE,
|
||||
Actions.INTEGRATION_UPDATE,
|
||||
].includes(action)) return 'UPDATE';
|
||||
if (
|
||||
[
|
||||
Actions.GUILD_UPDATE,
|
||||
Actions.CHANNEL_UPDATE,
|
||||
Actions.CHANNEL_OVERWRITE_UPDATE,
|
||||
Actions.MEMBER_UPDATE,
|
||||
Actions.MEMBER_ROLE_UPDATE,
|
||||
Actions.MEMBER_MOVE,
|
||||
Actions.ROLE_UPDATE,
|
||||
Actions.INVITE_UPDATE,
|
||||
Actions.WEBHOOK_UPDATE,
|
||||
Actions.EMOJI_UPDATE,
|
||||
Actions.INTEGRATION_UPDATE,
|
||||
].includes(action)
|
||||
) {
|
||||
return 'UPDATE';
|
||||
}
|
||||
|
||||
return 'ALL';
|
||||
}
|
||||
@@ -279,7 +290,7 @@ class GuildAuditLogs {
|
||||
* Audit logs entry.
|
||||
*/
|
||||
class GuildAuditLogsEntry {
|
||||
constructor(logs, guild, data) { // eslint-disable-line complexity
|
||||
constructor(logs, guild, data) {
|
||||
const targetType = GuildAuditLogs.targetType(data.action_type);
|
||||
/**
|
||||
* The target type of this entry
|
||||
@@ -309,9 +320,9 @@ class GuildAuditLogsEntry {
|
||||
* The user that executed this entry
|
||||
* @type {User}
|
||||
*/
|
||||
this.executor = guild.client.options.partials.includes(PartialTypes.USER) ?
|
||||
guild.client.users.add({ id: data.user_id }) :
|
||||
guild.client.users.cache.get(data.user_id);
|
||||
this.executor = guild.client.options.partials.includes(PartialTypes.USER)
|
||||
? guild.client.users.add({ id: data.user_id })
|
||||
: guild.client.users.cache.get(data.user_id);
|
||||
|
||||
/**
|
||||
* An entry in the audit log representing a specific change.
|
||||
@@ -374,13 +385,15 @@ class GuildAuditLogsEntry {
|
||||
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' };
|
||||
this.extra = guild.members.cache.get(data.options.id) || { id: data.options.id, type: 'member' };
|
||||
break;
|
||||
|
||||
case 'role':
|
||||
this.extra = guild.roles.cache.get(data.options.id) ||
|
||||
{ id: data.options.id, name: data.options.role_name, type: 'role' };
|
||||
this.extra = guild.roles.cache.get(data.options.id) || {
|
||||
id: data.options.id,
|
||||
name: data.options.role_name,
|
||||
type: 'role',
|
||||
};
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -405,21 +418,27 @@ class GuildAuditLogsEntry {
|
||||
this.target.id = data.target_id;
|
||||
// MEMBER_DISCONNECT and similar types do not provide a target_id.
|
||||
} else if (targetType === Targets.USER && data.target_id) {
|
||||
this.target = guild.client.options.partials.includes(PartialTypes.USER) ?
|
||||
guild.client.users.add({ id: data.target_id }) :
|
||||
guild.client.users.cache.get(data.target_id);
|
||||
this.target = guild.client.options.partials.includes(PartialTypes.USER)
|
||||
? guild.client.users.add({ id: data.target_id })
|
||||
: guild.client.users.cache.get(data.target_id);
|
||||
} else if (targetType === Targets.GUILD) {
|
||||
this.target = guild.client.guilds.cache.get(data.target_id);
|
||||
} else if (targetType === Targets.WEBHOOK) {
|
||||
this.target = logs.webhooks.get(data.target_id) ||
|
||||
new Webhook(guild.client,
|
||||
this.changes.reduce((o, c) => {
|
||||
o[c.key] = c.new || c.old;
|
||||
return o;
|
||||
}, {
|
||||
id: data.target_id,
|
||||
guild_id: guild.id,
|
||||
}));
|
||||
this.target =
|
||||
logs.webhooks.get(data.target_id) ||
|
||||
new Webhook(
|
||||
guild.client,
|
||||
this.changes.reduce(
|
||||
(o, c) => {
|
||||
o[c.key] = c.new || c.old;
|
||||
return o;
|
||||
},
|
||||
{
|
||||
id: data.target_id,
|
||||
guild_id: guild.id,
|
||||
},
|
||||
),
|
||||
);
|
||||
} else if (targetType === Targets.INVITE) {
|
||||
this.target = guild.members.fetch(guild.client.user.id).then(me => {
|
||||
if (me.permissions.has('MANAGE_GUILD')) {
|
||||
@@ -437,15 +456,24 @@ class GuildAuditLogsEntry {
|
||||
});
|
||||
} else if (targetType === Targets.MESSAGE) {
|
||||
// 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.client.users.cache.get(data.target_id);
|
||||
this.target =
|
||||
data.action_type === Actions.MESSAGE_BULK_DELETE
|
||||
? 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) ||
|
||||
new Integration(guild.client, this.changes.reduce((o, c) => {
|
||||
o[c.key] = c.new || c.old;
|
||||
return o;
|
||||
}, { id: data.target_id }), guild);
|
||||
this.target =
|
||||
logs.integrations.get(data.target_id) ||
|
||||
new Integration(
|
||||
guild.client,
|
||||
this.changes.reduce(
|
||||
(o, c) => {
|
||||
o[c.key] = c.new || c.old;
|
||||
return o;
|
||||
},
|
||||
{ id: data.target_id },
|
||||
),
|
||||
guild,
|
||||
);
|
||||
} else if (data.target_id) {
|
||||
this.target = guild[`${targetType.toLowerCase()}s`].cache.get(data.target_id) || { id: data.target_id };
|
||||
}
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
const Channel = require('./Channel');
|
||||
const Role = require('./Role');
|
||||
const Invite = require('./Invite');
|
||||
const PermissionOverwrites = require('./PermissionOverwrites');
|
||||
const Util = require('../util/Util');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const Collection = require('../util/Collection');
|
||||
const Role = require('./Role');
|
||||
const { Error, TypeError } = require('../errors');
|
||||
const Collection = require('../util/Collection');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents a guild channel from any of the following:
|
||||
@@ -85,9 +85,11 @@ class GuildChannel extends Channel {
|
||||
if (this.permissionOverwrites.size !== this.parent.permissionOverwrites.size) return false;
|
||||
return this.permissionOverwrites.every((value, key) => {
|
||||
const testVal = this.parent.permissionOverwrites.get(key);
|
||||
return testVal !== undefined &&
|
||||
return (
|
||||
testVal !== undefined &&
|
||||
testVal.deny.bitfield === value.deny.bitfield &&
|
||||
testVal.allow.bitfield === value.allow.bitfield;
|
||||
testVal.allow.bitfield === value.allow.bitfield
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -202,12 +204,9 @@ class GuildChannel extends Channel {
|
||||
*/
|
||||
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,
|
||||
));
|
||||
return Promise.reject(
|
||||
new TypeError('INVALID_TYPE', 'overwrites', 'Array or Collection of Permission Overwrites', true),
|
||||
);
|
||||
}
|
||||
return this.edit({ permissionOverwrites: overwrites, reason }).then(() => this);
|
||||
}
|
||||
@@ -256,8 +255,12 @@ class GuildChannel extends Channel {
|
||||
const type = userOrRole instanceof Role ? 'role' : '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 }, reason })
|
||||
return this.client.api
|
||||
.channels(this.id)
|
||||
.permissions[userOrRole.id].put({
|
||||
data: { id: userOrRole.id, type, allow: allow.bitfield, deny: deny.bitfield },
|
||||
reason,
|
||||
})
|
||||
.then(() => this);
|
||||
}
|
||||
|
||||
@@ -316,18 +319,23 @@ class GuildChannel extends Channel {
|
||||
*/
|
||||
async edit(data, reason) {
|
||||
if (typeof data.position !== 'undefined') {
|
||||
await Util.setPosition(this, data.position, false,
|
||||
this.guild._sortedChannels(this), this.client.api.guilds(this.guild.id).channels, reason)
|
||||
.then(updatedChannels => {
|
||||
this.client.actions.GuildChannelsPositionUpdate.handle({
|
||||
guild_id: this.guild.id,
|
||||
channels: updatedChannels,
|
||||
});
|
||||
await Util.setPosition(
|
||||
this,
|
||||
data.position,
|
||||
false,
|
||||
this.guild._sortedChannels(this),
|
||||
this.client.api.guilds(this.guild.id).channels,
|
||||
reason,
|
||||
).then(updatedChannels => {
|
||||
this.client.actions.GuildChannelsPositionUpdate.handle({
|
||||
guild_id: this.guild.id,
|
||||
channels: updatedChannels,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
const permission_overwrites = data.permissionOverwrites &&
|
||||
data.permissionOverwrites.map(o => PermissionOverwrites.resolve(o, this.guild));
|
||||
const permission_overwrites =
|
||||
data.permissionOverwrites && data.permissionOverwrites.map(o => PermissionOverwrites.resolve(o, this.guild));
|
||||
|
||||
const newData = await this.client.api.channels(this.id).patch({
|
||||
data: {
|
||||
@@ -378,11 +386,14 @@ class GuildChannel extends Channel {
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setParent(channel, { lockPermissions = true, reason } = {}) {
|
||||
return this.edit({
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
parentID: channel !== null ? channel.hasOwnProperty('id') ? channel.id : channel : null,
|
||||
lockPermissions,
|
||||
}, reason);
|
||||
return this.edit(
|
||||
{
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
parentID: channel !== null ? (channel.hasOwnProperty('id') ? channel.id : channel) : null,
|
||||
lockPermissions,
|
||||
},
|
||||
reason,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -414,15 +425,20 @@ class GuildChannel extends Channel {
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setPosition(position, { relative, reason } = {}) {
|
||||
return Util.setPosition(this, position, relative,
|
||||
this.guild._sortedChannels(this), this.client.api.guilds(this.guild.id).channels, reason)
|
||||
.then(updatedChannels => {
|
||||
this.client.actions.GuildChannelsPositionUpdate.handle({
|
||||
guild_id: this.guild.id,
|
||||
channels: updatedChannels,
|
||||
});
|
||||
return this;
|
||||
return Util.setPosition(
|
||||
this,
|
||||
position,
|
||||
relative,
|
||||
this.guild._sortedChannels(this),
|
||||
this.client.api.guilds(this.guild.id).channels,
|
||||
reason,
|
||||
).then(updatedChannels => {
|
||||
this.client.actions.GuildChannelsPositionUpdate.handle({
|
||||
guild_id: this.guild.id,
|
||||
channels: updatedChannels,
|
||||
});
|
||||
return this;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -442,9 +458,17 @@ class GuildChannel extends Channel {
|
||||
* .catch(console.error);
|
||||
*/
|
||||
createInvite({ temporary = false, maxAge = 86400, maxUses = 0, unique, reason } = {}) {
|
||||
return this.client.api.channels(this.id).invites.post({ data: {
|
||||
temporary, max_age: maxAge, max_uses: maxUses, unique,
|
||||
}, reason })
|
||||
return this.client.api
|
||||
.channels(this.id)
|
||||
.invites.post({
|
||||
data: {
|
||||
temporary,
|
||||
max_age: maxAge,
|
||||
max_uses: maxUses,
|
||||
unique,
|
||||
},
|
||||
reason,
|
||||
})
|
||||
.then(invite => new Invite(this.client, invite));
|
||||
}
|
||||
|
||||
@@ -481,18 +505,21 @@ class GuildChannel extends Channel {
|
||||
* @returns {Promise<GuildChannel>}
|
||||
*/
|
||||
clone(options = {}) {
|
||||
Util.mergeDefault({
|
||||
name: this.name,
|
||||
permissionOverwrites: this.permissionOverwrites,
|
||||
topic: this.topic,
|
||||
type: this.type,
|
||||
nsfw: this.nsfw,
|
||||
parent: this.parent,
|
||||
bitrate: this.bitrate,
|
||||
userLimit: this.userLimit,
|
||||
rateLimitPerUser: this.rateLimitPerUser,
|
||||
reason: null,
|
||||
}, options);
|
||||
Util.mergeDefault(
|
||||
{
|
||||
name: this.name,
|
||||
permissionOverwrites: this.permissionOverwrites,
|
||||
topic: this.topic,
|
||||
type: this.type,
|
||||
nsfw: this.nsfw,
|
||||
parent: this.parent,
|
||||
bitrate: this.bitrate,
|
||||
userLimit: this.userLimit,
|
||||
rateLimitPerUser: this.rateLimitPerUser,
|
||||
reason: null,
|
||||
},
|
||||
options,
|
||||
);
|
||||
return this.guild.channels.create(options.name, options);
|
||||
}
|
||||
/* eslint-enable max-len */
|
||||
@@ -504,7 +531,8 @@ class GuildChannel extends Channel {
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(channel) {
|
||||
let equal = channel &&
|
||||
let equal =
|
||||
channel &&
|
||||
this.id === channel.id &&
|
||||
this.type === channel.type &&
|
||||
this.topic === channel.topic &&
|
||||
@@ -565,7 +593,10 @@ class GuildChannel extends Channel {
|
||||
* .catch(console.error);
|
||||
*/
|
||||
delete(reason) {
|
||||
return this.client.api.channels(this.id).delete({ reason }).then(() => this);
|
||||
return this.client.api
|
||||
.channels(this.id)
|
||||
.delete({ reason })
|
||||
.then(() => this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const Emoji = require('./Emoji');
|
||||
const { Error } = require('../errors');
|
||||
const GuildEmojiRoleManager = require('../managers/GuildEmojiRoleManager');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const { Error } = require('../errors');
|
||||
const Emoji = require('./Emoji');
|
||||
|
||||
/**
|
||||
* Represents a custom emoji.
|
||||
@@ -74,8 +74,7 @@ class GuildEmoji extends Emoji {
|
||||
*/
|
||||
get deletable() {
|
||||
if (!this.guild.me) throw new Error('GUILD_UNCACHED_ME');
|
||||
return !this.managed &&
|
||||
this.guild.me.hasPermission(Permissions.FLAGS.MANAGE_EMOJIS);
|
||||
return !this.managed && this.guild.me.hasPermission(Permissions.FLAGS.MANAGE_EMOJIS);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,7 +99,10 @@ class GuildEmoji extends Emoji {
|
||||
return Promise.reject(new Error('MISSING_MANAGE_EMOJIS_PERMISSION', this.guild));
|
||||
}
|
||||
}
|
||||
return this.client.api.guilds(this.guild.id).emojis(this.id).get()
|
||||
return this.client.api
|
||||
.guilds(this.guild.id)
|
||||
.emojis(this.id)
|
||||
.get()
|
||||
.then(emoji => this.client.users.add(emoji.user));
|
||||
}
|
||||
|
||||
@@ -124,11 +126,16 @@ class GuildEmoji extends Emoji {
|
||||
*/
|
||||
edit(data, reason) {
|
||||
const roles = data.roles ? data.roles.map(r => r.id || r) : undefined;
|
||||
return this.client.api.guilds(this.guild.id).emojis(this.id)
|
||||
.patch({ data: {
|
||||
name: data.name,
|
||||
roles,
|
||||
}, reason })
|
||||
return this.client.api
|
||||
.guilds(this.guild.id)
|
||||
.emojis(this.id)
|
||||
.patch({
|
||||
data: {
|
||||
name: data.name,
|
||||
roles,
|
||||
},
|
||||
reason,
|
||||
})
|
||||
.then(newData => {
|
||||
const clone = this._clone();
|
||||
clone._patch(newData);
|
||||
@@ -152,7 +159,10 @@ class GuildEmoji extends Emoji {
|
||||
* @returns {Promise<GuildEmoji>}
|
||||
*/
|
||||
delete(reason) {
|
||||
return this.client.api.guilds(this.guild.id).emojis(this.id).delete({ reason })
|
||||
return this.client.api
|
||||
.guilds(this.guild.id)
|
||||
.emojis(this.id)
|
||||
.delete({ reason })
|
||||
.then(() => this);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
'use strict';
|
||||
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const Role = require('./Role');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const GuildMemberRoleManager = require('../managers/GuildMemberRoleManager');
|
||||
const Base = require('./Base');
|
||||
const VoiceState = require('./VoiceState');
|
||||
const { Presence } = require('./Presence');
|
||||
const Role = require('./Role');
|
||||
const VoiceState = require('./VoiceState');
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const { Error } = require('../errors');
|
||||
const GuildMemberRoleManager = require('../managers/GuildMemberRoleManager');
|
||||
const Permissions = require('../util/Permissions');
|
||||
|
||||
/**
|
||||
* Represents a member of a guild on Discord.
|
||||
@@ -152,12 +152,15 @@ class GuildMember extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get presence() {
|
||||
return this.guild.presences.cache.get(this.id) || new Presence(this.client, {
|
||||
user: {
|
||||
id: this.id,
|
||||
},
|
||||
guild: this.guild,
|
||||
});
|
||||
return (
|
||||
this.guild.presences.cache.get(this.id) ||
|
||||
new Presence(this.client, {
|
||||
user: {
|
||||
id: this.id,
|
||||
},
|
||||
guild: this.guild,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -293,7 +296,7 @@ class GuildMember extends Base {
|
||||
data.channel_id = null;
|
||||
data.channel = undefined;
|
||||
}
|
||||
if (data.roles) data.roles = data.roles.map(role => role instanceof Role ? role.id : role);
|
||||
if (data.roles) data.roles = data.roles.map(role => (role instanceof Role ? role.id : role));
|
||||
let endpoint = this.client.api.guilds(this.guild.id);
|
||||
if (this.user.id === this.client.user.id) {
|
||||
const keys = Object.keys(data);
|
||||
@@ -342,7 +345,10 @@ class GuildMember extends Base {
|
||||
* @returns {Promise<GuildMember>}
|
||||
*/
|
||||
kick(reason) {
|
||||
return this.client.api.guilds(this.guild.id).members(this.user.id).delete({ reason })
|
||||
return this.client.api
|
||||
.guilds(this.guild.id)
|
||||
.members(this.user.id)
|
||||
.delete({ reason })
|
||||
.then(() => this);
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,10 @@ class Integration extends Base {
|
||||
*/
|
||||
sync() {
|
||||
this.syncing = true;
|
||||
return this.client.api.guilds(this.guild.id).integrations(this.id).post()
|
||||
return this.client.api
|
||||
.guilds(this.guild.id)
|
||||
.integrations(this.id)
|
||||
.post()
|
||||
.then(() => {
|
||||
this.syncing = false;
|
||||
this.syncedAt = Date.now();
|
||||
@@ -129,7 +132,10 @@ class Integration extends Base {
|
||||
data.expireGracePeriod = null;
|
||||
}
|
||||
// The option enable_emoticons is only available for Twitch at this moment
|
||||
return this.client.api.guilds(this.guild.id).integrations(this.id).patch({ data, reason })
|
||||
return this.client.api
|
||||
.guilds(this.guild.id)
|
||||
.integrations(this.id)
|
||||
.patch({ data, reason })
|
||||
.then(() => {
|
||||
this._patch(data);
|
||||
return this;
|
||||
@@ -142,7 +148,10 @@ class Integration extends Base {
|
||||
* @param {string} [reason] Reason for deleting this integration
|
||||
*/
|
||||
delete(reason) {
|
||||
return this.client.api.guilds(this.guild.id).integrations(this.id).delete({ reason })
|
||||
return this.client.api
|
||||
.guilds(this.guild.id)
|
||||
.integrations(this.id)
|
||||
.delete({ reason })
|
||||
.then(() => this);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const Base = require('./Base');
|
||||
const { Endpoints } = require('../util/Constants');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const Base = require('./Base');
|
||||
|
||||
/**
|
||||
* Represents an invitation to a guild channel.
|
||||
@@ -119,8 +119,10 @@ class Invite extends Base {
|
||||
const guild = this.guild;
|
||||
if (!guild || !this.client.guilds.cache.has(guild.id)) return false;
|
||||
if (!guild.me) throw new Error('GUILD_UNCACHED_ME');
|
||||
return this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_CHANNELS, false) ||
|
||||
guild.me.permissions.has(Permissions.FLAGS.MANAGE_GUILD);
|
||||
return (
|
||||
this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_CHANNELS, false) ||
|
||||
guild.me.permissions.has(Permissions.FLAGS.MANAGE_GUILD)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,7 +131,7 @@ class Invite extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get expiresTimestamp() {
|
||||
return this.createdTimestamp && this.maxAge ? this.createdTimestamp + (this.maxAge * 1000) : null;
|
||||
return this.createdTimestamp && this.maxAge ? this.createdTimestamp + this.maxAge * 1000 : null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
const Mentions = require('./MessageMentions');
|
||||
const APIMessage = require('./APIMessage');
|
||||
const Base = require('./Base');
|
||||
const ClientApplication = require('./ClientApplication');
|
||||
const MessageAttachment = require('./MessageAttachment');
|
||||
const Embed = require('./MessageEmbed');
|
||||
const Mentions = require('./MessageMentions');
|
||||
const ReactionCollector = require('./ReactionCollector');
|
||||
const ClientApplication = require('./ClientApplication');
|
||||
const Util = require('../util/Util');
|
||||
const Collection = require('../util/Collection');
|
||||
const ReactionManager = require('../managers/ReactionManager');
|
||||
const { MessageTypes } = require('../util/Constants');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const Base = require('./Base');
|
||||
const { Error, TypeError } = require('../errors');
|
||||
const APIMessage = require('./APIMessage');
|
||||
const ReactionManager = require('../managers/ReactionManager');
|
||||
const Collection = require('../util/Collection');
|
||||
const { MessageTypes } = require('../util/Constants');
|
||||
const MessageFlags = require('../util/MessageFlags');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents a message on Discord.
|
||||
@@ -43,7 +43,7 @@ class Message extends Base {
|
||||
if (data) this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) { // eslint-disable-line complexity
|
||||
_patch(data) {
|
||||
/**
|
||||
* The ID of the message
|
||||
* @type {Snowflake}
|
||||
@@ -107,9 +107,7 @@ class Message extends Base {
|
||||
this.attachments = new Collection();
|
||||
if (data.attachments) {
|
||||
for (const attachment of data.attachments) {
|
||||
this.attachments.set(attachment.id, new MessageAttachment(
|
||||
attachment.url, attachment.filename, attachment,
|
||||
));
|
||||
this.attachments.set(attachment.id, new MessageAttachment(attachment.url, attachment.filename, attachment));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,10 +156,12 @@ class Message extends Base {
|
||||
* Group activity
|
||||
* @type {?MessageActivity}
|
||||
*/
|
||||
this.activity = data.activity ? {
|
||||
partyID: data.activity.party_id,
|
||||
type: data.activity.type,
|
||||
} : null;
|
||||
this.activity = data.activity
|
||||
? {
|
||||
partyID: data.activity.party_id,
|
||||
type: data.activity.type,
|
||||
}
|
||||
: null;
|
||||
|
||||
/**
|
||||
* The previous versions of the message, sorted with the most recent first
|
||||
@@ -194,11 +194,13 @@ class Message extends Base {
|
||||
* Message reference data
|
||||
* @type {?MessageReference}
|
||||
*/
|
||||
this.reference = data.message_reference ? {
|
||||
channelID: data.message_reference.channel_id,
|
||||
guildID: data.message_reference.guild_id,
|
||||
messageID: data.message_reference.message_id,
|
||||
} : null;
|
||||
this.reference = data.message_reference
|
||||
? {
|
||||
channelID: data.message_reference.channel_id,
|
||||
guildID: data.message_reference.guild_id,
|
||||
messageID: data.message_reference.message_id,
|
||||
}
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,9 +231,7 @@ class Message extends Base {
|
||||
if ('attachments' in data) {
|
||||
this.attachments = new Collection();
|
||||
for (const attachment of data.attachments) {
|
||||
this.attachments.set(attachment.id, new MessageAttachment(
|
||||
attachment.url, attachment.filename, attachment,
|
||||
));
|
||||
this.attachments.set(attachment.id, new MessageAttachment(attachment.url, attachment.filename, attachment));
|
||||
}
|
||||
} else {
|
||||
this.attachments = new Collection(this.attachments);
|
||||
@@ -377,9 +377,11 @@ class Message extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get deletable() {
|
||||
return !this.deleted && (this.author.id === this.client.user.id || (this.guild &&
|
||||
this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_MESSAGES, false)
|
||||
));
|
||||
return (
|
||||
!this.deleted &&
|
||||
(this.author.id === this.client.user.id ||
|
||||
(this.guild && this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_MESSAGES, false)))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -388,8 +390,10 @@ class Message extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get pinnable() {
|
||||
return this.type === 'DEFAULT' && (!this.guild ||
|
||||
this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_MESSAGES, false));
|
||||
return (
|
||||
this.type === 'DEFAULT' &&
|
||||
(!this.guild || this.channel.permissionsFor(this.client.user).has(Permissions.FLAGS.MANAGE_MESSAGES, false))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -412,16 +416,13 @@ class Message extends Base {
|
||||
* .catch(console.error);
|
||||
*/
|
||||
edit(content, options) {
|
||||
const { data } = content instanceof APIMessage ?
|
||||
content.resolveData() :
|
||||
APIMessage.create(this, content, options).resolveData();
|
||||
return this.client.api.channels[this.channel.id].messages[this.id]
|
||||
.patch({ data })
|
||||
.then(d => {
|
||||
const clone = this._clone();
|
||||
clone._patch(d);
|
||||
return clone;
|
||||
});
|
||||
const { data } =
|
||||
content instanceof APIMessage ? content.resolveData() : APIMessage.create(this, content, options).resolveData();
|
||||
return this.client.api.channels[this.channel.id].messages[this.id].patch({ data }).then(d => {
|
||||
const clone = this._clone();
|
||||
clone._patch(d);
|
||||
return clone;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -429,7 +430,10 @@ class Message extends Base {
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
pin() {
|
||||
return this.client.api.channels(this.channel.id).pins(this.id).put()
|
||||
return this.client.api
|
||||
.channels(this.channel.id)
|
||||
.pins(this.id)
|
||||
.put()
|
||||
.then(() => this);
|
||||
}
|
||||
|
||||
@@ -438,7 +442,10 @@ class Message extends Base {
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
unpin() {
|
||||
return this.client.api.channels(this.channel.id).pins(this.id).delete()
|
||||
return this.client.api
|
||||
.channels(this.channel.id)
|
||||
.pins(this.id)
|
||||
.delete()
|
||||
.then(() => this);
|
||||
}
|
||||
|
||||
@@ -461,14 +468,20 @@ class Message extends Base {
|
||||
emoji = this.client.emojis.resolveIdentifier(emoji);
|
||||
if (!emoji) throw new TypeError('EMOJI_TYPE');
|
||||
|
||||
return this.client.api.channels(this.channel.id).messages(this.id).reactions(emoji, '@me')
|
||||
return this.client.api
|
||||
.channels(this.channel.id)
|
||||
.messages(this.id)
|
||||
.reactions(emoji, '@me')
|
||||
.put()
|
||||
.then(() => this.client.actions.MessageReactionAdd.handle({
|
||||
user: this.client.user,
|
||||
channel: this.channel,
|
||||
message: this,
|
||||
emoji: Util.parseEmoji(emoji),
|
||||
}).reaction);
|
||||
.then(
|
||||
() =>
|
||||
this.client.actions.MessageReactionAdd.handle({
|
||||
user: this.client.user,
|
||||
channel: this.channel,
|
||||
message: this,
|
||||
emoji: Util.parseEmoji(emoji),
|
||||
}).reaction,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -509,9 +522,10 @@ class Message extends Base {
|
||||
* .catch(console.error);
|
||||
*/
|
||||
reply(content, options) {
|
||||
return this.channel.send(content instanceof APIMessage ?
|
||||
content :
|
||||
APIMessage.transformOptions(content, options, { reply: this.member || this.author }),
|
||||
return this.channel.send(
|
||||
content instanceof APIMessage
|
||||
? content
|
||||
: APIMessage.transformOptions(content, options, { reply: this.member || this.author }),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -562,16 +576,18 @@ class Message extends Base {
|
||||
const embedUpdate = !message.author && !message.attachments;
|
||||
if (embedUpdate) return this.id === message.id && this.embeds.length === message.embeds.length;
|
||||
|
||||
let equal = this.id === message.id &&
|
||||
this.author.id === message.author.id &&
|
||||
this.content === message.content &&
|
||||
this.tts === message.tts &&
|
||||
this.nonce === message.nonce &&
|
||||
this.embeds.length === message.embeds.length &&
|
||||
this.attachments.length === message.attachments.length;
|
||||
let equal =
|
||||
this.id === message.id &&
|
||||
this.author.id === message.author.id &&
|
||||
this.content === message.content &&
|
||||
this.tts === message.tts &&
|
||||
this.nonce === message.nonce &&
|
||||
this.embeds.length === message.embeds.length &&
|
||||
this.attachments.length === message.attachments.length;
|
||||
|
||||
if (equal && rawData) {
|
||||
equal = this.mentions.everyone === message.mentions.everyone &&
|
||||
equal =
|
||||
this.mentions.everyone === message.mentions.everyone &&
|
||||
this.createdTimestamp === new Date(rawData.timestamp).getTime() &&
|
||||
this.editedTimestamp === new Date(rawData.edited_timestamp).getTime();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const Util = require('../util/Util');
|
||||
const { RangeError } = require('../errors');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents an embed in a message (image/video preview, rich embed, etc.)
|
||||
@@ -11,7 +11,7 @@ class MessageEmbed {
|
||||
this.setup(data);
|
||||
}
|
||||
|
||||
setup(data) { // eslint-disable-line complexity
|
||||
setup(data) {
|
||||
/**
|
||||
* The type of this embed, either:
|
||||
* * `rich` - a rich embed
|
||||
@@ -79,12 +79,14 @@ class MessageEmbed {
|
||||
* The thumbnail of this embed (if there is one)
|
||||
* @type {?MessageEmbedThumbnail}
|
||||
*/
|
||||
this.thumbnail = data.thumbnail ? {
|
||||
url: data.thumbnail.url,
|
||||
proxyURL: data.thumbnail.proxyURL || data.thumbnail.proxy_url,
|
||||
height: data.thumbnail.height,
|
||||
width: data.thumbnail.width,
|
||||
} : null;
|
||||
this.thumbnail = data.thumbnail
|
||||
? {
|
||||
url: data.thumbnail.url,
|
||||
proxyURL: data.thumbnail.proxyURL || data.thumbnail.proxy_url,
|
||||
height: data.thumbnail.height,
|
||||
width: data.thumbnail.width,
|
||||
}
|
||||
: null;
|
||||
|
||||
/**
|
||||
* @typedef {Object} MessageEmbedImage
|
||||
@@ -98,12 +100,14 @@ class MessageEmbed {
|
||||
* The image of this embed, if there is one
|
||||
* @type {?MessageEmbedImage}
|
||||
*/
|
||||
this.image = data.image ? {
|
||||
url: data.image.url,
|
||||
proxyURL: data.image.proxyURL || data.image.proxy_url,
|
||||
height: data.image.height,
|
||||
width: data.image.width,
|
||||
} : null;
|
||||
this.image = data.image
|
||||
? {
|
||||
url: data.image.url,
|
||||
proxyURL: data.image.proxyURL || data.image.proxy_url,
|
||||
height: data.image.height,
|
||||
width: data.image.width,
|
||||
}
|
||||
: null;
|
||||
|
||||
/**
|
||||
* @typedef {Object} MessageEmbedVideo
|
||||
@@ -118,12 +122,14 @@ class MessageEmbed {
|
||||
* @type {?MessageEmbedVideo}
|
||||
* @readonly
|
||||
*/
|
||||
this.video = data.video ? {
|
||||
url: data.video.url,
|
||||
proxyURL: data.video.proxyURL || data.video.proxy_url,
|
||||
height: data.video.height,
|
||||
width: data.video.width,
|
||||
} : null;
|
||||
this.video = data.video
|
||||
? {
|
||||
url: data.video.url,
|
||||
proxyURL: data.video.proxyURL || data.video.proxy_url,
|
||||
height: data.video.height,
|
||||
width: data.video.width,
|
||||
}
|
||||
: null;
|
||||
|
||||
/**
|
||||
* @typedef {Object} MessageEmbedAuthor
|
||||
@@ -137,12 +143,14 @@ class MessageEmbed {
|
||||
* The author of this embed (if there is one)
|
||||
* @type {?MessageEmbedAuthor}
|
||||
*/
|
||||
this.author = data.author ? {
|
||||
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,
|
||||
} : null;
|
||||
this.author = data.author
|
||||
? {
|
||||
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,
|
||||
}
|
||||
: null;
|
||||
|
||||
/**
|
||||
* @typedef {Object} MessageEmbedProvider
|
||||
@@ -154,10 +162,12 @@ class MessageEmbed {
|
||||
* The provider of this embed (if there is one)
|
||||
* @type {?MessageEmbedProvider}
|
||||
*/
|
||||
this.provider = data.provider ? {
|
||||
name: data.provider.name,
|
||||
url: data.provider.name,
|
||||
} : null;
|
||||
this.provider = data.provider
|
||||
? {
|
||||
name: data.provider.name,
|
||||
url: data.provider.name,
|
||||
}
|
||||
: null;
|
||||
|
||||
/**
|
||||
* @typedef {Object} MessageEmbedFooter
|
||||
@@ -170,11 +180,13 @@ class MessageEmbed {
|
||||
* The footer of this embed
|
||||
* @type {?MessageEmbedFooter}
|
||||
*/
|
||||
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,
|
||||
} : null;
|
||||
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,
|
||||
}
|
||||
: null;
|
||||
|
||||
/**
|
||||
* The files of this embed
|
||||
@@ -210,9 +222,11 @@ class MessageEmbed {
|
||||
return (
|
||||
(this.title ? this.title.length : 0) +
|
||||
(this.description ? this.description.length : 0) +
|
||||
(this.fields.length >= 1 ? this.fields.reduce((prev, curr) =>
|
||||
prev + curr.name.length + curr.value.length, 0) : 0) +
|
||||
(this.footer ? this.footer.text.length : 0));
|
||||
(this.fields.length >= 1
|
||||
? this.fields.reduce((prev, curr) => prev + curr.name.length + curr.value.length, 0)
|
||||
: 0) +
|
||||
(this.footer ? this.footer.text.length : 0)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -371,15 +385,19 @@ class MessageEmbed {
|
||||
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,
|
||||
}
|
||||
: null,
|
||||
footer: this.footer
|
||||
? {
|
||||
text: this.footer.text,
|
||||
icon_url: this.footer.iconURL,
|
||||
}
|
||||
: null,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -399,11 +417,11 @@ class MessageEmbed {
|
||||
}
|
||||
|
||||
/**
|
||||
* @typedef {Object} EmbedFieldData
|
||||
* @property {StringResolvable} name The name of this field
|
||||
* @property {StringResolvable} value The value of this field
|
||||
* @property {boolean} [inline=false] If this field will be displayed inline
|
||||
*/
|
||||
* @typedef {Object} EmbedFieldData
|
||||
* @property {StringResolvable} name The name of this field
|
||||
* @property {StringResolvable} value The value of this field
|
||||
* @property {boolean} [inline] If this field will be displayed inline
|
||||
*/
|
||||
|
||||
/**
|
||||
* Normalizes field input and resolves strings.
|
||||
@@ -411,13 +429,15 @@ class MessageEmbed {
|
||||
* @returns {EmbedField[]}
|
||||
*/
|
||||
static normalizeFields(...fields) {
|
||||
return fields.flat(2).map(field =>
|
||||
this.normalizeField(
|
||||
field && field.name,
|
||||
field && field.value,
|
||||
field && typeof field.inline === 'boolean' ? field.inline : false,
|
||||
),
|
||||
);
|
||||
return fields
|
||||
.flat(2)
|
||||
.map(field =>
|
||||
this.normalizeField(
|
||||
field && field.name,
|
||||
field && field.value,
|
||||
field && typeof field.inline === 'boolean' ? field.inline : false,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const Collection = require('../util/Collection');
|
||||
const Util = require('../util/Util');
|
||||
const GuildMember = require('./GuildMember');
|
||||
const Collection = require('../util/Collection');
|
||||
const { ChannelTypes } = require('../util/Constants');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Keeps track of mentions in a {@link Message}.
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const GuildEmoji = require('./GuildEmoji');
|
||||
const Util = require('../util/Util');
|
||||
const ReactionEmoji = require('./ReactionEmoji');
|
||||
const ReactionUserManager = require('../managers/ReactionUserManager');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents a reaction to a message.
|
||||
@@ -59,7 +59,10 @@ class MessageReaction {
|
||||
* @returns {Promise<MessageReaction>}
|
||||
*/
|
||||
async remove() {
|
||||
await this.client.api.channels(this.message.channel.id).messages(this.message.id).reactions(this._emoji.identifier)
|
||||
await this.client.api
|
||||
.channels(this.message.channel.id)
|
||||
.messages(this.message.id)
|
||||
.reactions(this._emoji.identifier)
|
||||
.delete();
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const Role = require('./Role');
|
||||
const { TypeError } = require('../errors');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const Util = require('../util/Util');
|
||||
const { TypeError } = require('../errors');
|
||||
|
||||
/**
|
||||
* Represents a permission overwrite for a role or member in a guild channel.
|
||||
@@ -70,8 +70,12 @@ class PermissionOverwrites {
|
||||
update(options, reason) {
|
||||
const { allow, deny } = this.constructor.resolveOverwriteOptions(options, this);
|
||||
|
||||
return 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 }, reason })
|
||||
return 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 },
|
||||
reason,
|
||||
})
|
||||
.then(() => this);
|
||||
}
|
||||
|
||||
@@ -81,9 +85,7 @@ class PermissionOverwrites {
|
||||
* @returns {Promise<PermissionOverwrites>}
|
||||
*/
|
||||
delete(reason) {
|
||||
return this.channel.client.api.channels[this.channel.id].permissions[this.id]
|
||||
.delete({ reason })
|
||||
.then(() => this);
|
||||
return this.channel.client.api.channels[this.channel.id].permissions[this.id].delete({ reason }).then(() => this);
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
@@ -168,10 +170,7 @@ class PermissionOverwrites {
|
||||
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),
|
||||
};
|
||||
return { ...overwrite, allow: Permissions.resolve(overwrite.allow), deny: Permissions.resolve(overwrite.deny) };
|
||||
}
|
||||
|
||||
const userOrRole = guild.roles.resolve(overwrite.id) || guild.client.users.resolve(overwrite.id);
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const Util = require('../util/Util');
|
||||
const Emoji = require('./Emoji');
|
||||
const ActivityFlags = require('../util/ActivityFlags');
|
||||
const { ActivityTypes } = require('../util/Constants');
|
||||
const Emoji = require('./Emoji');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Activity sent in a message.
|
||||
@@ -121,14 +121,15 @@ class Presence {
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(presence) {
|
||||
return this === presence || (
|
||||
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
|
||||
return (
|
||||
this === presence ||
|
||||
(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)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -186,10 +187,12 @@ class Activity {
|
||||
* @prop {?Date} start When the activity started
|
||||
* @prop {?Date} end When the activity will end
|
||||
*/
|
||||
this.timestamps = data.timestamps ? {
|
||||
start: data.timestamps.start ? new Date(Number(data.timestamps.start)) : null,
|
||||
end: data.timestamps.end ? new Date(Number(data.timestamps.end)) : null,
|
||||
} : null;
|
||||
this.timestamps = data.timestamps
|
||||
? {
|
||||
start: data.timestamps.start ? new Date(Number(data.timestamps.start)) : null,
|
||||
end: data.timestamps.end ? new Date(Number(data.timestamps.end)) : null,
|
||||
}
|
||||
: null;
|
||||
|
||||
/**
|
||||
* Party of the activity
|
||||
@@ -232,11 +235,9 @@ class Activity {
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(activity) {
|
||||
return this === activity || (
|
||||
activity &&
|
||||
this.name === activity.name &&
|
||||
this.type === activity.type &&
|
||||
this.url === activity.url
|
||||
return (
|
||||
this === activity ||
|
||||
(activity && this.name === activity.name && this.type === activity.type && this.url === activity.url)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -303,8 +304,10 @@ class RichPresenceAssets {
|
||||
*/
|
||||
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.activity.presence.client.rest.cdn.AppAsset(this.activity.applicationID, this.smallImage, {
|
||||
format,
|
||||
size,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -321,8 +324,10 @@ class RichPresenceAssets {
|
||||
} else if (/^twitch:/.test(this.largeImage)) {
|
||||
return `https://static-cdn.jtvnw.net/previews-ttv/live_user_${this.largeImage.slice(7)}.png`;
|
||||
}
|
||||
return this.activity.presence.client.rest.cdn
|
||||
.AppAsset(this.activity.applicationID, this.largeImage, { format, size });
|
||||
return this.activity.presence.client.rest.cdn.AppAsset(this.activity.applicationID, this.largeImage, {
|
||||
format,
|
||||
size,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -118,8 +118,7 @@ class ReactionCollector extends Collector {
|
||||
* @param {MessageReaction} reaction The reaction that was removed
|
||||
* @param {User} user The user that removed the reaction
|
||||
*/
|
||||
if (this.collected.has(ReactionCollector.key(reaction)) &&
|
||||
this.users.has(user.id)) {
|
||||
if (this.collected.has(ReactionCollector.key(reaction)) && this.users.has(user.id)) {
|
||||
this.emit('remove', reaction, user);
|
||||
}
|
||||
return reaction.count ? null : ReactionCollector.key(reaction);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const Util = require('../util/Util');
|
||||
const Emoji = require('./Emoji');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents a limited emoji set used for both custom and unicode emojis. Custom emojis
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const Util = require('../util/Util');
|
||||
const Base = require('./Base');
|
||||
const { Error, TypeError } = require('../errors');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* Represents a role on Discord.
|
||||
@@ -180,25 +180,31 @@ class Role extends Base {
|
||||
if (typeof data.permissions !== 'undefined') data.permissions = Permissions.resolve(data.permissions);
|
||||
else data.permissions = this.permissions.bitfield;
|
||||
if (typeof data.position !== 'undefined') {
|
||||
await Util.setPosition(this, data.position, false, this.guild._sortedRoles(),
|
||||
this.client.api.guilds(this.guild.id).roles, reason)
|
||||
.then(updatedRoles => {
|
||||
this.client.actions.GuildRolesPositionUpdate.handle({
|
||||
guild_id: this.guild.id,
|
||||
roles: updatedRoles,
|
||||
});
|
||||
await Util.setPosition(
|
||||
this,
|
||||
data.position,
|
||||
false,
|
||||
this.guild._sortedRoles(),
|
||||
this.client.api.guilds(this.guild.id).roles,
|
||||
reason,
|
||||
).then(updatedRoles => {
|
||||
this.client.actions.GuildRolesPositionUpdate.handle({
|
||||
guild_id: this.guild.id,
|
||||
roles: updatedRoles,
|
||||
});
|
||||
});
|
||||
}
|
||||
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,
|
||||
permissions: data.permissions,
|
||||
mentionable: typeof data.mentionable !== 'undefined' ? data.mentionable : this.mentionable,
|
||||
},
|
||||
reason,
|
||||
})
|
||||
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,
|
||||
permissions: data.permissions,
|
||||
mentionable: typeof data.mentionable !== 'undefined' ? data.mentionable : this.mentionable,
|
||||
},
|
||||
reason,
|
||||
})
|
||||
.then(role => {
|
||||
const clone = this._clone();
|
||||
clone._patch(role);
|
||||
@@ -312,15 +318,20 @@ class Role extends Base {
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setPosition(position, { relative, reason } = {}) {
|
||||
return Util.setPosition(this, position, relative,
|
||||
this.guild._sortedRoles(), this.client.api.guilds(this.guild.id).roles, reason)
|
||||
.then(updatedRoles => {
|
||||
this.client.actions.GuildRolesPositionUpdate.handle({
|
||||
guild_id: this.guild.id,
|
||||
roles: updatedRoles,
|
||||
});
|
||||
return this;
|
||||
return Util.setPosition(
|
||||
this,
|
||||
position,
|
||||
relative,
|
||||
this.guild._sortedRoles(),
|
||||
this.client.api.guilds(this.guild.id).roles,
|
||||
reason,
|
||||
).then(updatedRoles => {
|
||||
this.client.actions.GuildRolesPositionUpdate.handle({
|
||||
guild_id: this.guild.id,
|
||||
roles: updatedRoles,
|
||||
});
|
||||
return this;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -334,11 +345,10 @@ class Role extends Base {
|
||||
* .catch(console.error);
|
||||
*/
|
||||
delete(reason) {
|
||||
return this.client.api.guilds[this.guild.id].roles[this.id].delete({ reason })
|
||||
.then(() => {
|
||||
this.client.actions.GuildRoleDelete.handle({ guild_id: this.guild.id, role_id: this.id });
|
||||
return this;
|
||||
});
|
||||
return this.client.api.guilds[this.guild.id].roles[this.id].delete({ reason }).then(() => {
|
||||
this.client.actions.GuildRoleDelete.handle({ guild_id: this.guild.id, role_id: this.id });
|
||||
return this;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -349,14 +359,16 @@ class Role extends Base {
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(role) {
|
||||
return role &&
|
||||
return (
|
||||
role &&
|
||||
this.id === role.id &&
|
||||
this.name === role.name &&
|
||||
this.color === role.color &&
|
||||
this.hoist === role.hoist &&
|
||||
this.position === role.position &&
|
||||
this.permissions.bitfield === role.permissions.bitfield &&
|
||||
this.managed === role.managed;
|
||||
this.managed === role.managed
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
const Collection = require('../util/Collection');
|
||||
const Base = require('./Base');
|
||||
const TeamMember = require('./TeamMember');
|
||||
const Collection = require('../util/Collection');
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
|
||||
/**
|
||||
* Represents a Client OAuth2 Application Team.
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
const GuildChannel = require('./GuildChannel');
|
||||
const Webhook = require('./Webhook');
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const MessageManager = require('../managers/MessageManager');
|
||||
const Collection = require('../util/Collection');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const MessageManager = require('../managers/MessageManager');
|
||||
|
||||
/**
|
||||
* Represents a guild text channel on Discord.
|
||||
@@ -121,9 +121,15 @@ class TextChannel extends GuildChannel {
|
||||
if (typeof avatar === 'string' && !avatar.startsWith('data:')) {
|
||||
avatar = await DataResolver.resolveImage(avatar);
|
||||
}
|
||||
return this.client.api.channels[this.id].webhooks.post({ data: {
|
||||
name, avatar,
|
||||
}, reason }).then(data => new Webhook(this.client, data));
|
||||
return this.client.api.channels[this.id].webhooks
|
||||
.post({
|
||||
data: {
|
||||
name,
|
||||
avatar,
|
||||
},
|
||||
reason,
|
||||
})
|
||||
.then(data => new Webhook(this.client, data));
|
||||
}
|
||||
|
||||
// These are here only for documentation purposes - they are implemented by TextBasedChannel
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const { Presence } = require('./Presence');
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
const Base = require('./Base');
|
||||
const { Presence } = require('./Presence');
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const { Error } = require('../errors');
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
|
||||
/**
|
||||
* Represents a user on Discord.
|
||||
@@ -219,9 +219,11 @@ class User extends Base {
|
||||
async createDM() {
|
||||
const { dmChannel } = this;
|
||||
if (dmChannel && !dmChannel.partial) return dmChannel;
|
||||
const data = await this.client.api.users(this.client.user.id).channels.post({ data: {
|
||||
recipient_id: this.id,
|
||||
} });
|
||||
const data = await this.client.api.users(this.client.user.id).channels.post({
|
||||
data: {
|
||||
recipient_id: this.id,
|
||||
},
|
||||
});
|
||||
return this.client.actions.ChannelCreate.handle(data).channel;
|
||||
}
|
||||
|
||||
@@ -243,7 +245,8 @@ class User extends Base {
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(user) {
|
||||
let equal = user &&
|
||||
let equal =
|
||||
user &&
|
||||
this.id === user.id &&
|
||||
this.username === user.username &&
|
||||
this.discriminator === user.discriminator &&
|
||||
@@ -272,13 +275,16 @@ class User extends Base {
|
||||
}
|
||||
|
||||
toJSON(...props) {
|
||||
const json = super.toJSON({
|
||||
createdTimestamp: true,
|
||||
defaultAvatarURL: true,
|
||||
tag: true,
|
||||
lastMessage: false,
|
||||
lastMessageID: false,
|
||||
}, ...props);
|
||||
const json = super.toJSON(
|
||||
{
|
||||
createdTimestamp: true,
|
||||
defaultAvatarURL: true,
|
||||
tag: true,
|
||||
lastMessage: false,
|
||||
lastMessageID: false,
|
||||
},
|
||||
...props,
|
||||
);
|
||||
json.avatarURL = this.avatarURL();
|
||||
json.displayAvatarURL = this.displayAvatarURL();
|
||||
return json;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
const GuildChannel = require('./GuildChannel');
|
||||
const { Error } = require('../errors');
|
||||
const Collection = require('../util/Collection');
|
||||
const { browser } = require('../util/Constants');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const Collection = require('../util/Collection');
|
||||
const { Error } = require('../errors');
|
||||
|
||||
/**
|
||||
* Represents a guild voice channel on Discord.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const Base = require('./Base');
|
||||
const { browser } = require('../util/Constants');
|
||||
const { Error, TypeError } = require('../errors');
|
||||
const { browser } = require('../util/Constants');
|
||||
|
||||
/**
|
||||
* Represents the voice state for a Guild Member.
|
||||
@@ -119,9 +119,7 @@ class VoiceState extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get speaking() {
|
||||
return this.channel && this.channel.connection ?
|
||||
Boolean(this.channel.connection._speaking.get(this.id)) :
|
||||
null;
|
||||
return this.channel && this.channel.connection ? Boolean(this.channel.connection._speaking.get(this.id)) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,9 +159,9 @@ class VoiceState extends Base {
|
||||
* @returns {Promise<GuildMember>}
|
||||
*/
|
||||
setChannel(channel, reason) {
|
||||
return this.member ?
|
||||
this.member.edit({ channel }, reason) :
|
||||
Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER'));
|
||||
return this.member
|
||||
? this.member.edit({ channel }, reason)
|
||||
: Promise.reject(new Error('VOICE_STATE_UNCACHED_MEMBER'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
const APIMessage = require('./APIMessage');
|
||||
const Channel = require('./Channel');
|
||||
const { WebhookTypes } = require('../util/Constants');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
const Channel = require('./Channel');
|
||||
const APIMessage = require('./APIMessage');
|
||||
|
||||
/**
|
||||
* Represents a webhook.
|
||||
@@ -149,15 +149,19 @@ class Webhook {
|
||||
}
|
||||
|
||||
const { data, files } = await apiMessage.resolveFiles();
|
||||
return this.client.api.webhooks(this.id, this.token).post({
|
||||
data, files,
|
||||
query: { 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);
|
||||
});
|
||||
return this.client.api
|
||||
.webhooks(this.id, this.token)
|
||||
.post({
|
||||
data,
|
||||
files,
|
||||
query: { 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);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -178,11 +182,14 @@ class Webhook {
|
||||
* }).catch(console.error);
|
||||
*/
|
||||
sendSlackMessage(body) {
|
||||
return this.client.api.webhooks(this.id, this.token).slack.post({
|
||||
query: { wait: true },
|
||||
auth: false,
|
||||
data: body,
|
||||
}).then(data => data.toString() === 'ok');
|
||||
return this.client.api
|
||||
.webhooks(this.id, this.token)
|
||||
.slack.post({
|
||||
query: { wait: true },
|
||||
auth: false,
|
||||
data: body,
|
||||
})
|
||||
.then(data => data.toString() === 'ok');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -195,7 +202,7 @@ class Webhook {
|
||||
* @returns {Promise<Webhook>}
|
||||
*/
|
||||
async edit({ name = this.name, avatar, channel }, reason) {
|
||||
if (avatar && (typeof avatar === 'string' && !avatar.startsWith('data:'))) {
|
||||
if (avatar && typeof avatar === 'string' && !avatar.startsWith('data:')) {
|
||||
avatar = await DataResolver.resolveImage(avatar);
|
||||
}
|
||||
if (channel) channel = channel instanceof Channel ? channel.id : channel;
|
||||
@@ -256,17 +263,8 @@ class Webhook {
|
||||
}
|
||||
|
||||
static applyToClass(structure) {
|
||||
for (const prop of [
|
||||
'send',
|
||||
'sendSlackMessage',
|
||||
'edit',
|
||||
'delete',
|
||||
'createdTimestamp',
|
||||
'createdAt',
|
||||
'url',
|
||||
]) {
|
||||
Object.defineProperty(structure.prototype, prop,
|
||||
Object.getOwnPropertyDescriptor(Webhook.prototype, prop));
|
||||
for (const prop of ['send', 'sendSlackMessage', 'edit', 'delete', 'createdTimestamp', 'createdAt', 'url']) {
|
||||
Object.defineProperty(structure.prototype, prop, Object.getOwnPropertyDescriptor(Webhook.prototype, prop));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const EventEmitter = require('events');
|
||||
const Collection = require('../../util/Collection');
|
||||
const Util = require('../../util/Util');
|
||||
const EventEmitter = require('events');
|
||||
|
||||
/**
|
||||
* Filter to be applied to the collector.
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
/* eslint-disable import/order */
|
||||
const MessageCollector = require('../MessageCollector');
|
||||
const APIMessage = require('../APIMessage');
|
||||
const Snowflake = require('../../util/Snowflake');
|
||||
const Collection = require('../../util/Collection');
|
||||
const { RangeError, TypeError } = require('../../errors');
|
||||
const APIMessage = require('../APIMessage');
|
||||
|
||||
/**
|
||||
* Interface for classes that have text-channel-like features.
|
||||
@@ -144,7 +145,8 @@ class TextBasedChannel {
|
||||
}
|
||||
|
||||
const { data, files } = await apiMessage.resolveFiles();
|
||||
return this.client.api.channels[this.id].messages.post({ data, files })
|
||||
return this.client.api.channels[this.id].messages
|
||||
.post({ data, files })
|
||||
.then(d => this.client.actions.MessageCreate.handle(d).message);
|
||||
}
|
||||
|
||||
@@ -299,23 +301,36 @@ class TextBasedChannel {
|
||||
if (Array.isArray(messages) || messages instanceof Collection) {
|
||||
let messageIDs = messages instanceof Collection ? messages.keyArray() : messages.map(m => m.id || m);
|
||||
if (filterOld) {
|
||||
messageIDs = messageIDs.filter(id =>
|
||||
Date.now() - Snowflake.deconstruct(id).date.getTime() < 1209600000,
|
||||
);
|
||||
messageIDs = messageIDs.filter(id => Date.now() - Snowflake.deconstruct(id).date.getTime() < 1209600000);
|
||||
}
|
||||
if (messageIDs.length === 0) return new Collection();
|
||||
if (messageIDs.length === 1) {
|
||||
await this.client.api.channels(this.id).messages(messageIDs[0]).delete();
|
||||
const message = this.client.actions.MessageDelete.getMessage({
|
||||
message_id: messageIDs[0],
|
||||
}, this);
|
||||
await this.client.api
|
||||
.channels(this.id)
|
||||
.messages(messageIDs[0])
|
||||
.delete();
|
||||
const message = this.client.actions.MessageDelete.getMessage(
|
||||
{
|
||||
message_id: messageIDs[0],
|
||||
},
|
||||
this,
|
||||
);
|
||||
return message ? new Collection([[message.id, message]]) : new Collection();
|
||||
}
|
||||
await this.client.api.channels[this.id].messages['bulk-delete']
|
||||
.post({ data: { messages: messageIDs } });
|
||||
return messageIDs.reduce((col, id) => col.set(id, this.client.actions.MessageDeleteBulk.getMessage({
|
||||
message_id: id,
|
||||
}, this)), new Collection());
|
||||
await this.client.api.channels[this.id].messages['bulk-delete'].post({ data: { messages: messageIDs } });
|
||||
return messageIDs.reduce(
|
||||
(col, id) =>
|
||||
col.set(
|
||||
id,
|
||||
this.client.actions.MessageDeleteBulk.getMessage(
|
||||
{
|
||||
message_id: id,
|
||||
},
|
||||
this,
|
||||
),
|
||||
),
|
||||
new Collection(),
|
||||
);
|
||||
}
|
||||
if (!isNaN(messages)) {
|
||||
const msgs = await this.messages.fetch({ limit: messages });
|
||||
@@ -341,8 +356,11 @@ class TextBasedChannel {
|
||||
}
|
||||
for (const prop of props) {
|
||||
if (ignore.includes(prop)) continue;
|
||||
Object.defineProperty(structure.prototype, prop,
|
||||
Object.getOwnPropertyDescriptor(TextBasedChannel.prototype, prop));
|
||||
Object.defineProperty(
|
||||
structure.prototype,
|
||||
prop,
|
||||
Object.getOwnPropertyDescriptor(TextBasedChannel.prototype, prop),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ const Util = require('./Util');
|
||||
*/
|
||||
class Collection extends BaseCollection {
|
||||
toJSON() {
|
||||
return this.map(e => typeof e.toJSON === 'function' ? e.toJSON() : Util.flatten(e));
|
||||
return this.map(e => (typeof e.toJSON === 'function' ? e.toJSON() : Util.flatten(e)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const Package = exports.Package = require('../../package.json');
|
||||
const Package = (exports.Package = require('../../package.json'));
|
||||
const { Error, RangeError } = require('../errors');
|
||||
const browser = exports.browser = typeof window !== 'undefined';
|
||||
const browser = (exports.browser = typeof window !== 'undefined');
|
||||
|
||||
/**
|
||||
* Options for a client.
|
||||
@@ -90,8 +90,9 @@ exports.DefaultOptions = {
|
||||
},
|
||||
};
|
||||
|
||||
exports.UserAgent = browser ? null :
|
||||
`DiscordBot (${Package.homepage.split('#')[0]}, ${Package.version}) Node.js/${process.version}`;
|
||||
exports.UserAgent = browser
|
||||
? null
|
||||
: `DiscordBot (${Package.homepage.split('#')[0]}, ${Package.version}) Node.js/${process.version}`;
|
||||
|
||||
exports.WSCodes = {
|
||||
1000: 'WS_CLOSE_REQUESTED',
|
||||
@@ -100,12 +101,7 @@ exports.WSCodes = {
|
||||
4011: 'SHARDING_REQUIRED',
|
||||
};
|
||||
|
||||
const AllowedImageFormats = [
|
||||
'webp',
|
||||
'png',
|
||||
'jpg',
|
||||
'gif',
|
||||
];
|
||||
const AllowedImageFormats = ['webp', 'png', 'jpg', 'gif'];
|
||||
|
||||
const AllowedImageSizes = Array.from({ length: 8 }, (e, i) => 2 ** (i + 4));
|
||||
|
||||
@@ -303,13 +299,7 @@ exports.ShardEvents = {
|
||||
* sidebar for more information.</warn>
|
||||
* @typedef {string} PartialType
|
||||
*/
|
||||
exports.PartialTypes = keyMirror([
|
||||
'USER',
|
||||
'CHANNEL',
|
||||
'GUILD_MEMBER',
|
||||
'MESSAGE',
|
||||
'REACTION',
|
||||
]);
|
||||
exports.PartialTypes = keyMirror(['USER', 'CHANNEL', 'GUILD_MEMBER', 'MESSAGE', 'REACTION']);
|
||||
|
||||
/**
|
||||
* The type of a websocket message event, e.g. `MESSAGE_CREATE`. Here are the available events:
|
||||
@@ -439,13 +429,7 @@ exports.MessageTypes = [
|
||||
* * CUSTOM_STATUS
|
||||
* @typedef {string} ActivityType
|
||||
*/
|
||||
exports.ActivityTypes = [
|
||||
'PLAYING',
|
||||
'STREAMING',
|
||||
'LISTENING',
|
||||
'WATCHING',
|
||||
'CUSTOM_STATUS',
|
||||
];
|
||||
exports.ActivityTypes = ['PLAYING', 'STREAMING', 'LISTENING', 'WATCHING', 'CUSTOM_STATUS'];
|
||||
|
||||
exports.ChannelTypes = {
|
||||
TEXT: 0,
|
||||
@@ -464,34 +448,34 @@ exports.ClientApplicationAssetTypes = {
|
||||
|
||||
exports.Colors = {
|
||||
DEFAULT: 0x000000,
|
||||
WHITE: 0xFFFFFF,
|
||||
AQUA: 0x1ABC9C,
|
||||
GREEN: 0x2ECC71,
|
||||
BLUE: 0x3498DB,
|
||||
YELLOW: 0xFFFF00,
|
||||
PURPLE: 0x9B59B6,
|
||||
LUMINOUS_VIVID_PINK: 0xE91E63,
|
||||
GOLD: 0xF1C40F,
|
||||
ORANGE: 0xE67E22,
|
||||
RED: 0xE74C3C,
|
||||
GREY: 0x95A5A6,
|
||||
NAVY: 0x34495E,
|
||||
DARK_AQUA: 0x11806A,
|
||||
DARK_GREEN: 0x1F8B4C,
|
||||
WHITE: 0xffffff,
|
||||
AQUA: 0x1abc9c,
|
||||
GREEN: 0x2ecc71,
|
||||
BLUE: 0x3498db,
|
||||
YELLOW: 0xffff00,
|
||||
PURPLE: 0x9b59b6,
|
||||
LUMINOUS_VIVID_PINK: 0xe91e63,
|
||||
GOLD: 0xf1c40f,
|
||||
ORANGE: 0xe67e22,
|
||||
RED: 0xe74c3c,
|
||||
GREY: 0x95a5a6,
|
||||
NAVY: 0x34495e,
|
||||
DARK_AQUA: 0x11806a,
|
||||
DARK_GREEN: 0x1f8b4c,
|
||||
DARK_BLUE: 0x206694,
|
||||
DARK_PURPLE: 0x71368A,
|
||||
DARK_VIVID_PINK: 0xAD1457,
|
||||
DARK_GOLD: 0xC27C0E,
|
||||
DARK_ORANGE: 0xA84300,
|
||||
DARK_RED: 0x992D22,
|
||||
DARK_GREY: 0x979C9F,
|
||||
DARKER_GREY: 0x7F8C8D,
|
||||
LIGHT_GREY: 0xBCC0C0,
|
||||
DARK_NAVY: 0x2C3E50,
|
||||
BLURPLE: 0x7289DA,
|
||||
GREYPLE: 0x99AAB5,
|
||||
DARK_BUT_NOT_BLACK: 0x2C2F33,
|
||||
NOT_QUITE_BLACK: 0x23272A,
|
||||
DARK_PURPLE: 0x71368a,
|
||||
DARK_VIVID_PINK: 0xad1457,
|
||||
DARK_GOLD: 0xc27c0e,
|
||||
DARK_ORANGE: 0xa84300,
|
||||
DARK_RED: 0x992d22,
|
||||
DARK_GREY: 0x979c9f,
|
||||
DARKER_GREY: 0x7f8c8d,
|
||||
LIGHT_GREY: 0xbcc0c0,
|
||||
DARK_NAVY: 0x2c3e50,
|
||||
BLURPLE: 0x7289da,
|
||||
GREYPLE: 0x99aab5,
|
||||
DARK_BUT_NOT_BLACK: 0x2c2f33,
|
||||
NOT_QUITE_BLACK: 0x23272a,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -501,11 +485,7 @@ exports.Colors = {
|
||||
* * ALL_MEMBERS
|
||||
* @typedef {string} ExplicitContentFilterLevel
|
||||
*/
|
||||
exports.ExplicitContentFilterLevels = [
|
||||
'DISABLED',
|
||||
'MEMBERS_WITHOUT_ROLES',
|
||||
'ALL_MEMBERS',
|
||||
];
|
||||
exports.ExplicitContentFilterLevels = ['DISABLED', 'MEMBERS_WITHOUT_ROLES', 'ALL_MEMBERS'];
|
||||
|
||||
/**
|
||||
* The value set for the verification levels for a guild:
|
||||
@@ -516,13 +496,7 @@ exports.ExplicitContentFilterLevels = [
|
||||
* * VERY_HIGH
|
||||
* @typedef {string} VerificationLevel
|
||||
*/
|
||||
exports.VerificationLevels = [
|
||||
'NONE',
|
||||
'LOW',
|
||||
'MEDIUM',
|
||||
'HIGH',
|
||||
'VERY_HIGH',
|
||||
];
|
||||
exports.VerificationLevels = ['NONE', 'LOW', 'MEDIUM', 'HIGH', 'VERY_HIGH'];
|
||||
|
||||
/**
|
||||
* An error encountered while performing an API request. Here are the potential errors:
|
||||
@@ -641,10 +615,7 @@ exports.APIErrors = {
|
||||
* * MENTIONS
|
||||
* @typedef {string} DefaultMessageNotifications
|
||||
*/
|
||||
exports.DefaultMessageNotifications = [
|
||||
'ALL',
|
||||
'MENTIONS',
|
||||
];
|
||||
exports.DefaultMessageNotifications = ['ALL', 'MENTIONS'];
|
||||
|
||||
/**
|
||||
* The value set for a team members's membership state:
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const fetch = require('node-fetch');
|
||||
const Util = require('../util/Util');
|
||||
const { Error: DiscordError, TypeError } = require('../errors');
|
||||
const { browser } = require('../util/Constants');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
* The DataResolver identifies different objects and tries to resolve a specific piece of information from them.
|
||||
@@ -90,7 +90,7 @@ class DataResolver {
|
||||
|
||||
if (typeof resource === 'string') {
|
||||
if (/^https?:\/\//.test(resource)) {
|
||||
return fetch(resource).then(res => browser ? res.blob() : res.buffer());
|
||||
return fetch(resource).then(res => (browser ? res.blob() : res.buffer()));
|
||||
} else if (!browser) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const file = browser ? resource : path.resolve(resource);
|
||||
|
||||
@@ -41,7 +41,9 @@ class SnowflakeUtil {
|
||||
}
|
||||
if (INCREMENT >= 4095) INCREMENT = 0;
|
||||
// eslint-disable-next-line max-len
|
||||
const BINARY = `${(timestamp - EPOCH).toString(2).padStart(42, '0')}0000100000${(INCREMENT++).toString(2).padStart(12, '0')}`;
|
||||
const BINARY = `${(timestamp - EPOCH).toString(2).padStart(42, '0')}0000100000${(INCREMENT++)
|
||||
.toString(2)
|
||||
.padStart(12, '0')}`;
|
||||
return Util.binaryToID(BINARY);
|
||||
}
|
||||
|
||||
@@ -62,7 +64,9 @@ class SnowflakeUtil {
|
||||
* @returns {DeconstructedSnowflake} Deconstructed snowflake
|
||||
*/
|
||||
static deconstruct(snowflake) {
|
||||
const BINARY = Util.idToBinary(snowflake).toString(2).padStart(64, '0');
|
||||
const BINARY = Util.idToBinary(snowflake)
|
||||
.toString(2)
|
||||
.padStart(64, '0');
|
||||
const res = {
|
||||
timestamp: parseInt(BINARY.substring(0, 42), 2) + EPOCH,
|
||||
workerID: parseInt(BINARY.substring(42, 47), 2),
|
||||
@@ -71,7 +75,9 @@ class SnowflakeUtil {
|
||||
binary: BINARY,
|
||||
};
|
||||
Object.defineProperty(res, 'date', {
|
||||
get: function get() { return new Date(this.timestamp); },
|
||||
get: function get() {
|
||||
return new Date(this.timestamp);
|
||||
},
|
||||
enumerable: true,
|
||||
});
|
||||
return res;
|
||||
|
||||
@@ -60,7 +60,7 @@ class Structures {
|
||||
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}).`,
|
||||
` (received function ${received}; expected extension of ${structures[structure].name}).`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
148
src/util/Util.js
148
src/util/Util.js
@@ -1,11 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const { Colors, DefaultOptions, Endpoints } = require('./Constants');
|
||||
const { parse } = require('path');
|
||||
const fetch = require('node-fetch');
|
||||
const { Colors, DefaultOptions, Endpoints } = require('./Constants');
|
||||
const { Error: DiscordError, RangeError, TypeError } = require('../errors');
|
||||
const has = (o, k) => Object.prototype.hasOwnProperty.call(o, k);
|
||||
const isObject = d => typeof d === 'object' && d !== null;
|
||||
const { parse } = require('path');
|
||||
|
||||
/**
|
||||
* Contains various general-purpose utility methods. These functions are also available on the base `Discord` object.
|
||||
@@ -24,7 +24,12 @@ class Util {
|
||||
static flatten(obj, ...props) {
|
||||
if (!isObject(obj)) return obj;
|
||||
|
||||
props = Object.assign(...Object.keys(obj).filter(k => !k.startsWith('_')).map(k => ({ [k]: true })), ...props);
|
||||
props = Object.assign(
|
||||
...Object.keys(obj)
|
||||
.filter(k => !k.startsWith('_'))
|
||||
.map(k => ({ [k]: true })),
|
||||
...props,
|
||||
);
|
||||
|
||||
const out = {};
|
||||
|
||||
@@ -89,43 +94,52 @@ class Util {
|
||||
* @param {boolean} [options.inlineCodeContent=true] Whether to escape text inside inline code or not
|
||||
* @returns {string}
|
||||
*/
|
||||
static escapeMarkdown(text, {
|
||||
codeBlock = true,
|
||||
inlineCode = true,
|
||||
bold = true,
|
||||
italic = true,
|
||||
underline = true,
|
||||
strikethrough = true,
|
||||
spoiler = true,
|
||||
codeBlockContent = true,
|
||||
inlineCodeContent = true,
|
||||
} = {}) {
|
||||
static escapeMarkdown(
|
||||
text,
|
||||
{
|
||||
codeBlock = true,
|
||||
inlineCode = true,
|
||||
bold = true,
|
||||
italic = true,
|
||||
underline = true,
|
||||
strikethrough = true,
|
||||
spoiler = true,
|
||||
codeBlockContent = true,
|
||||
inlineCodeContent = true,
|
||||
} = {},
|
||||
) {
|
||||
if (!codeBlockContent) {
|
||||
return text.split('```').map((subString, index, array) => {
|
||||
if ((index % 2) && index !== array.length - 1) return subString;
|
||||
return Util.escapeMarkdown(subString, {
|
||||
inlineCode,
|
||||
bold,
|
||||
italic,
|
||||
underline,
|
||||
strikethrough,
|
||||
spoiler,
|
||||
inlineCodeContent,
|
||||
});
|
||||
}).join(codeBlock ? '\\`\\`\\`' : '```');
|
||||
return text
|
||||
.split('```')
|
||||
.map((subString, index, array) => {
|
||||
if (index % 2 && index !== array.length - 1) return subString;
|
||||
return Util.escapeMarkdown(subString, {
|
||||
inlineCode,
|
||||
bold,
|
||||
italic,
|
||||
underline,
|
||||
strikethrough,
|
||||
spoiler,
|
||||
inlineCodeContent,
|
||||
});
|
||||
})
|
||||
.join(codeBlock ? '\\`\\`\\`' : '```');
|
||||
}
|
||||
if (!inlineCodeContent) {
|
||||
return text.split(/(?<=^|[^`])`(?=[^`]|$)/g).map((subString, index, array) => {
|
||||
if ((index % 2) && index !== array.length - 1) return subString;
|
||||
return Util.escapeMarkdown(subString, {
|
||||
codeBlock,
|
||||
bold,
|
||||
italic,
|
||||
underline,
|
||||
strikethrough,
|
||||
spoiler,
|
||||
});
|
||||
}).join(inlineCode ? '\\`' : '`');
|
||||
return text
|
||||
.split(/(?<=^|[^`])`(?=[^`]|$)/g)
|
||||
.map((subString, index, array) => {
|
||||
if (index % 2 && index !== array.length - 1) return subString;
|
||||
return Util.escapeMarkdown(subString, {
|
||||
codeBlock,
|
||||
bold,
|
||||
italic,
|
||||
underline,
|
||||
strikethrough,
|
||||
spoiler,
|
||||
});
|
||||
})
|
||||
.join(inlineCode ? '\\`' : '`');
|
||||
}
|
||||
if (inlineCode) text = Util.escapeInlineCode(text);
|
||||
if (codeBlock) text = Util.escapeCodeBlock(text);
|
||||
@@ -228,10 +242,12 @@ class Util {
|
||||
return fetch(`${DefaultOptions.http.api}/v${DefaultOptions.http.version}${Endpoints.botGateway}`, {
|
||||
method: 'GET',
|
||||
headers: { Authorization: `Bot ${token.replace(/^Bot\s*/i, '')}` },
|
||||
}).then(res => {
|
||||
if (res.ok) return res.json();
|
||||
throw res;
|
||||
}).then(data => data.shards * (1000 / guildsPerShard));
|
||||
})
|
||||
.then(res => {
|
||||
if (res.ok) return res.json();
|
||||
throw res;
|
||||
})
|
||||
.then(data => data.shards * (1000 / guildsPerShard));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -415,14 +431,14 @@ class Util {
|
||||
*/
|
||||
static resolveColor(color) {
|
||||
if (typeof color === 'string') {
|
||||
if (color === 'RANDOM') return Math.floor(Math.random() * (0xFFFFFF + 1));
|
||||
if (color === 'RANDOM') return Math.floor(Math.random() * (0xffffff + 1));
|
||||
if (color === 'DEFAULT') return 0;
|
||||
color = Colors[color] || parseInt(color.replace('#', ''), 16);
|
||||
} else if (Array.isArray(color)) {
|
||||
color = (color[0] << 16) + (color[1] << 8) + color[2];
|
||||
}
|
||||
|
||||
if (color < 0 || color > 0xFFFFFF) throw new RangeError('COLOR_RANGE');
|
||||
if (color < 0 || color > 0xffffff) throw new RangeError('COLOR_RANGE');
|
||||
else if (color && isNaN(color)) throw new TypeError('COLOR_CONVERT');
|
||||
|
||||
return color;
|
||||
@@ -434,10 +450,11 @@ class Util {
|
||||
* @returns {Collection}
|
||||
*/
|
||||
static discordSort(collection) {
|
||||
return collection.sorted((a, b) =>
|
||||
a.rawPosition - b.rawPosition ||
|
||||
parseInt(b.id.slice(0, -10)) - parseInt(a.id.slice(0, -10)) ||
|
||||
parseInt(b.id.slice(10)) - parseInt(a.id.slice(10)),
|
||||
return collection.sorted(
|
||||
(a, b) =>
|
||||
a.rawPosition - b.rawPosition ||
|
||||
parseInt(b.id.slice(0, -10)) - parseInt(a.id.slice(0, -10)) ||
|
||||
parseInt(b.id.slice(10)) - parseInt(a.id.slice(10)),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -506,7 +523,11 @@ class Util {
|
||||
const low = parseInt((high % 10).toString(2) + num.slice(-32), 2);
|
||||
|
||||
dec = (low % 10).toString() + dec;
|
||||
num = Math.floor(high / 10).toString(2) + Math.floor(low / 10).toString(2).padStart(32, '0');
|
||||
num =
|
||||
Math.floor(high / 10).toString(2) +
|
||||
Math.floor(low / 10)
|
||||
.toString(2)
|
||||
.padStart(32, '0');
|
||||
}
|
||||
|
||||
num = parseInt(num, 2);
|
||||
@@ -535,7 +556,7 @@ class Util {
|
||||
*/
|
||||
static cleanContent(str, message) {
|
||||
if (message.client.options.disableMentions === 'everyone') {
|
||||
str = str.replace(/@([^<>@ ]*)/gsmu, (match, target) => {
|
||||
str = str.replace(/@([^<>@ ]*)/gmsu, (match, target) => {
|
||||
if (target.match(/^[&!]?\d+$/)) {
|
||||
return `@${target}`;
|
||||
} else {
|
||||
@@ -543,21 +564,22 @@ class Util {
|
||||
}
|
||||
});
|
||||
}
|
||||
str = str.replace(/<@!?[0-9]+>/g, input => {
|
||||
const id = input.replace(/<|!|>|@/g, '');
|
||||
if (message.channel.type === 'dm') {
|
||||
const user = message.client.users.cache.get(id);
|
||||
return user ? `@${user.username}` : input;
|
||||
}
|
||||
str = str
|
||||
.replace(/<@!?[0-9]+>/g, input => {
|
||||
const id = input.replace(/<|!|>|@/g, '');
|
||||
if (message.channel.type === 'dm') {
|
||||
const user = message.client.users.cache.get(id);
|
||||
return user ? `@${user.username}` : input;
|
||||
}
|
||||
|
||||
const member = message.channel.guild.members.cache.get(id);
|
||||
if (member) {
|
||||
return `@${member.displayName}`;
|
||||
} else {
|
||||
const user = message.client.users.cache.get(id);
|
||||
return user ? `@${user.username}` : input;
|
||||
}
|
||||
})
|
||||
const member = message.channel.guild.members.cache.get(id);
|
||||
if (member) {
|
||||
return `@${member.displayName}`;
|
||||
} else {
|
||||
const user = message.client.users.cache.get(id);
|
||||
return user ? `@${user.username}` : input;
|
||||
}
|
||||
})
|
||||
.replace(/<#[0-9]+>/g, input => {
|
||||
const channel = message.client.channels.cache.get(input.replace(/<|#|>/g, ''));
|
||||
return channel ? `#${channel.name}` : input;
|
||||
|
||||
Reference in New Issue
Block a user