mirror of
https://github.com/discordjs/discord.js.git
synced 2026-06-16 03:18:20 +00:00
feat: Internal sharding (#2902)
* internal sharding * ready event * the square deal * the new deal * the second new deal * add actual documentation * the new freedom * the great society * federal intervention * some of requested changes * i ran out of things to call these * destroy this * fix: Client#uptime went missing * fix(Client): destroy the client on login failure This may happen duo invalid sharding config / invalid token / user requested destroy * fix(Client): reject login promise when the client is destroyed before ready * fix(WebSocketManager): remove redundancy in destroy method (#2491) * typo(ErrorMessages): duo -> duo to * typo(ErrorMessages): duo -> due * fix: docs and options * docs(WebSocketManager): WebSockethard -> WebSocketShard (#2502) * fix(ClientUser): lazily load to account for extended user structure (#2501) * docs(WebSocketShard): document class to make it visible in documentation (#2504) * fix: WebSocketShard#reconnect * fix: presenceUpdate & userUpdate * presenceUpdate wasn't really being handled at all * userUpdate handled incorrectly because as of v7 in the Discord API, it comes inside presenceUpdate * re-add raw event * member is now part of message create payload * feat: Add functionality to support multiple servers with different shards (#2395) * Added functionallity to spawn multiple sharding managers due to adding start and end shards * Small fixes and limiting shard amount to max recommended * Forgot a check in spawn() * Fixed indentation * Removed optiosn object documentation for totalShards * More fixes and a check that the startShard + amount doesnt go over the recommended shard amount * fix getting max recommended * Removed async from constructor (my fault) * Changed start and end shard to a shardList or "auto" + fixed some brainfarts with isNaN * Changed the loop and totalShard count calculation * shards are actually 0 based * Fixed a problem with the gateway and handled some range errors and type errors * Changed Number.isNan to isNaN and changed a few Integer checks to use Number.isInteger * Added check if shardList contains smth greater than totalShards; made spawn use totalShards again; shardList will be ignored and rebuild if totalShards is 'auto'; fixed docs * ShardingManager#spawn now uses a for..of loop; fixed the if statement inside the new for..of loop to still work as intended; made the totalShards be set to a new amount if smth manual is put into ShardingManager#spawn just like before; Fixed some spelling * internal sharding * ready event * the square deal * the new deal * the second new deal * add actual documentation * the new freedom * the great society * federal intervention * some of requested changes * i ran out of things to call these * destroy this * fix: Client#uptime went missing * fix(Client): destroy the client on login failure This may happen duo invalid sharding config / invalid token / user requested destroy * fix(Client): reject login promise when the client is destroyed before ready * fix(WebSocketManager): remove redundancy in destroy method (#2491) * typo(ErrorMessages): duo -> duo to * typo(ErrorMessages): duo -> due * fix: docs and options * docs(WebSocketManager): WebSockethard -> WebSocketShard (#2502) * fix(ClientUser): lazily load to account for extended user structure (#2501) * docs(WebSocketShard): document class to make it visible in documentation (#2504) * fix: WebSocketShard#reconnect * fix: presenceUpdate & userUpdate * presenceUpdate wasn't really being handled at all * userUpdate handled incorrectly because as of v7 in the Discord API, it comes inside presenceUpdate * Internal Sharding adaptation Adapted to internal sharding Fixed a bug where non ready invalidated sessions wouldnt respawn * Fixed shardCount not retrieving * Fixing style removed unnecessary parenthesis * Fixing and rebasing lets hope i didnt dun hecklered it * Fixing my own retardation * Thanks git rebase * fix: assigning member in message create payload * fix: resumes * fix: IS wont give up reconnecting now * docs: add missing docs mostly * fix: found lost methods * fix: WebSocketManager#broadcast check if shard exists * fix: ShardClientUtil#id returning undefined * feat: handle new session rate limits (#2796) * feat: handle new session rate limits * i have no idea what i was doing last night * fix if statement weirdness * fix: re-add presence parsing from ClientOptions (#2893) * resolve conflicts * typings: missing typings * re-add missing linter rule * fix: replacing ClientUser wrongly * address unecessary performance waste * docs: missing disconnect event * fix(typings): Fix 2 issues with typings (#2909) * (Typings) Update typings to reflect current ClientOptions * fix(Typings) fixes a bug with Websockets and DOM Types * fix travis * feat: allow setting presence per shard * add WebSocketManager#shardX events * adjust typings, docs and performance issues * readjust shard events, now provide shardId parameter instead * fix: ready event should check shardCount, not actualShardCount * fix: re-add replayed parameter of Client#resume * fix(Sharding): fixes several things in Internal Sharding (#2914) * fix(Sharding) fixes several things in Internal Sharding * add default value for shards property * better implement checking for shards array * fix travis & some casing * split shard count into 2 words * update to latest Internal Sharding, fix requested changes * make sure totalShardCount is a number * fix comment * fix small typo * dynamically set totalShardCount if either shards or shardCount is provided * consistency: rename shardID to shardId * remove Client#shardIds * fix: typo in GuildIntegrationsUpdate handler * fix: incorrect packet data being passed in some events (#2919) * fix: edgecase of ShardingManager and totalShardCount (#2918) * fix: Client#userUpdate being passed wrong parameter and fix a potential edgecase of returning null in ClientUser#edit from this event * fix consistency and typings issues * consistency: shardId instances renamed to shardID * typings: fix typings regarding WebSocket * style(.eslintrc): remove additional whitespace * fix(Client): remove ondisconnect handler on timeout * docs(BaseClient): fix typo of Immediate * nitpick: typings, private fields and methods * typo: improve grammar a bit * fix: error assigning client in WebSocketManager * typo: actually spell milliseconds properly
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.ChannelCreate.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.ChannelDelete.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
const { Events } = require('../../../util/Constants');
|
||||
|
||||
module.exports = (client, { d: data }) => {
|
||||
const channel = client.channels.get(data.channel_id);
|
||||
const time = new Date(data.last_pin_timestamp);
|
||||
|
||||
if (channel && time) {
|
||||
// Discord sends null for last_pin_timestamp if the last pinned message was removed
|
||||
channel.lastPinTimestamp = time.getTime() || null;
|
||||
|
||||
/**
|
||||
* Emitted whenever the pins of a channel are updated. Due to the nature of the WebSocket event,
|
||||
* not much information can be provided easily here - you need to manually check the pins yourself.
|
||||
* @event Client#channelPinsUpdate
|
||||
* @param {DMChannel|GroupDMChannel|TextChannel} channel The channel that the pins update occured in
|
||||
* @param {Date} time The time of the pins update
|
||||
*/
|
||||
client.emit(Events.CHANNEL_PINS_UPDATE, channel, time);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
const { Events } = require('../../../util/Constants');
|
||||
|
||||
module.exports = (client, packet) => {
|
||||
const { old, updated } = client.actions.ChannelUpdate.handle(packet.d);
|
||||
if (old && updated) {
|
||||
/**
|
||||
* Emitted whenever a channel is updated - e.g. name change, topic change.
|
||||
* @event Client#channelUpdate
|
||||
* @param {DMChannel|GroupDMChannel|GuildChannel} oldChannel The channel before the update
|
||||
* @param {DMChannel|GroupDMChannel|GuildChannel} newChannel The channel after the update
|
||||
*/
|
||||
client.emit(Events.CHANNEL_UPDATE, old, updated);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
const { Events } = require('../../../util/Constants');
|
||||
|
||||
module.exports = (client, { d: data }) => {
|
||||
const guild = client.guilds.get(data.guild_id);
|
||||
const user = client.users.get(data.user.id);
|
||||
|
||||
/**
|
||||
* Emitted whenever a member is banned from a guild.
|
||||
* @event Client#guildBanAdd
|
||||
* @param {Guild} guild The guild that the ban occurred in
|
||||
* @param {User} user The user that was banned
|
||||
*/
|
||||
if (guild && user) client.emit(Events.GUILD_BAN_ADD, guild, user);
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.GuildBanRemove.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,26 @@
|
||||
const { Events, Status } = require('../../../util/Constants');
|
||||
|
||||
module.exports = async (client, { d: data }, shard) => {
|
||||
let guild = client.guilds.get(data.id);
|
||||
if (guild) {
|
||||
if (!guild.available && !data.unavailable) {
|
||||
// A newly available guild
|
||||
guild._patch(data);
|
||||
client.ws.checkReady();
|
||||
}
|
||||
} else {
|
||||
// A new guild
|
||||
data.shardID = shard.id;
|
||||
guild = client.guilds.add(data);
|
||||
const emitEvent = client.ws.status === Status.READY;
|
||||
if (emitEvent) {
|
||||
/**
|
||||
* Emitted whenever the client joins a guild.
|
||||
* @event Client#guildCreate
|
||||
* @param {Guild} guild The created guild
|
||||
*/
|
||||
if (client.options.fetchAllMembers) await guild.members.fetch();
|
||||
client.emit(Events.GUILD_CREATE, guild);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.GuildDelete.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.GuildEmojisUpdate.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.GuildIntegrationsUpdate.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
const { Events } = require('../../../util/Constants');
|
||||
const Collection = require('../../../util/Collection');
|
||||
|
||||
module.exports = (client, { d: data }) => {
|
||||
const guild = client.guilds.get(data.guild_id);
|
||||
if (!guild) return;
|
||||
const members = new Collection();
|
||||
|
||||
for (const member of data.members) members.set(member.user.id, guild.members.add(member));
|
||||
/**
|
||||
* Emitted whenever a chunk of guild members is received (all members come from the same guild).
|
||||
* @event Client#guildMembersChunk
|
||||
* @param {Collection<Snowflake, GuildMember>} members The members in the chunk
|
||||
* @param {Guild} guild The guild related to the member chunk
|
||||
*/
|
||||
client.emit(Events.GUILD_MEMBERS_CHUNK, members, guild);
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
const { Events, Status } = require('../../../util/Constants');
|
||||
|
||||
module.exports = (client, { d: data }, shard) => {
|
||||
const guild = client.guilds.get(data.guild_id);
|
||||
if (guild) {
|
||||
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
|
||||
*/
|
||||
client.emit(Events.GUILD_MEMBER_ADD, member);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet, shard) => {
|
||||
client.actions.GuildMemberRemove.handle(packet.d, shard);
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
const { Status, Events } = require('../../../util/Constants');
|
||||
|
||||
module.exports = (client, { d: data }, shard) => {
|
||||
const guild = client.guilds.get(data.guild_id);
|
||||
if (guild) {
|
||||
const member = guild.members.get(data.user.id);
|
||||
if (member) {
|
||||
const old = member._update(data);
|
||||
if (shard.status === Status.READY) {
|
||||
/**
|
||||
* Emitted whenever a guild member changes - i.e. new role, removed role, nickname.
|
||||
* @event Client#guildMemberUpdate
|
||||
* @param {GuildMember} oldMember The member before the update
|
||||
* @param {GuildMember} newMember The member after the update
|
||||
*/
|
||||
client.emit(Events.GUILD_MEMBER_UPDATE, old, member);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.GuildRoleCreate.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.GuildRoleDelete.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.GuildRoleUpdate.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.GuildSync.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.GuildUpdate.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.MessageCreate.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.MessageDelete.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.MessageDeleteBulk.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
const { Events } = require('../../../util/Constants');
|
||||
|
||||
module.exports = (client, packet) => {
|
||||
const { user, reaction } = client.actions.MessageReactionAdd.handle(packet.d);
|
||||
if (reaction) client.emit(Events.MESSAGE_REACTION_ADD, reaction, user);
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.MessageReactionRemove.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.MessageReactionRemoveAll.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,14 @@
|
||||
const { Events } = require('../../../util/Constants');
|
||||
|
||||
module.exports = (client, packet) => {
|
||||
const { old, updated } = client.actions.MessageUpdate.handle(packet.d);
|
||||
if (old && updated) {
|
||||
/**
|
||||
* Emitted whenever a message is updated - e.g. embed or content change.
|
||||
* @event Client#messageUpdate
|
||||
* @param {Message} oldMessage The message before the update
|
||||
* @param {Message} newMessage The message after the update
|
||||
*/
|
||||
client.emit(Events.MESSAGE_UPDATE, old, updated);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.PresenceUpdate.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
let ClientUser;
|
||||
|
||||
module.exports = (client, { d: data }, shard) => {
|
||||
if (!ClientUser) ClientUser = require('../../../structures/ClientUser');
|
||||
const clientUser = new ClientUser(client, data.user);
|
||||
client.user = clientUser;
|
||||
client.readyAt = new Date();
|
||||
client.users.set(clientUser.id, clientUser);
|
||||
|
||||
for (const guild of data.guilds) {
|
||||
guild.shardID = shard.id;
|
||||
client.guilds.add(guild);
|
||||
}
|
||||
|
||||
client.ws.checkReady();
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
const { Events } = require('../../../util/Constants');
|
||||
|
||||
module.exports = (client, packet, shard) => {
|
||||
const replayed = shard.sequence - shard.closeSequence;
|
||||
/**
|
||||
* Emitted when the client gateway resumes.
|
||||
* @event Client#resume
|
||||
* @param {number} replayed The number of events that were replayed
|
||||
* @param {number} shardID The ID of the shard that resumed
|
||||
*/
|
||||
client.emit(Events.RESUMED, replayed, shard.id);
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
const { Events } = require('../../../util/Constants');
|
||||
|
||||
module.exports = (client, { d: data }) => {
|
||||
const channel = client.channels.get(data.channel_id);
|
||||
const user = client.users.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
|
||||
*/
|
||||
client.emit(Events.TYPING_START, channel, user);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.UserUpdate.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.emit('self.voiceServer', packet.d);
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.VoiceStateUpdate.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,3 @@
|
||||
module.exports = (client, packet) => {
|
||||
client.actions.WebhooksUpdate.handle(packet.d);
|
||||
};
|
||||
@@ -0,0 +1,11 @@
|
||||
const { WSEvents } = require('../../../util/Constants');
|
||||
|
||||
const handlers = {};
|
||||
|
||||
for (const name of Object.keys(WSEvents)) {
|
||||
try {
|
||||
handlers[name] = require(`./${name}.js`);
|
||||
} catch (err) {} // eslint-disable-line no-empty
|
||||
}
|
||||
|
||||
module.exports = handlers;
|
||||
Reference in New Issue
Block a user