diff --git a/src/client/Client.js b/src/client/Client.js index 579642d58..f07216d81 100644 --- a/src/client/Client.js +++ b/src/client/Client.js @@ -173,6 +173,13 @@ class Client extends EventEmitter { return timeout; } + syncGuilds(guilds = this.guilds.array()) { + return this.ws.send({ + op: 12, + d: guilds.map(g => g.id), + }); + } + /** * Caches a user, or obtains it from the cache if it's already cached. * If the user isn't already cached, it will only be obtainable by OAuth bot accounts. diff --git a/src/client/ClientManager.js b/src/client/ClientManager.js index 2cd6a3932..e214fc9f6 100644 --- a/src/client/ClientManager.js +++ b/src/client/ClientManager.js @@ -48,7 +48,7 @@ class ClientManager { this.client.ws.send({ op: Constants.OPCodes.HEARTBEAT, d: Date.now(), - }); + }, true); }, time); } diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js index 378136598..bb07c00f8 100644 --- a/src/client/actions/ActionsManager.js +++ b/src/client/actions/ActionsManager.js @@ -20,6 +20,7 @@ class ActionsManager { this.register('GuildRoleUpdate'); this.register('UserGet'); this.register('UserUpdate'); + this.register('GuildSync'); } register(name) { diff --git a/src/client/actions/GuildSync.js b/src/client/actions/GuildSync.js new file mode 100644 index 000000000..a232df008 --- /dev/null +++ b/src/client/actions/GuildSync.js @@ -0,0 +1,29 @@ +const Action = require('./Action'); + +class GuildSync extends Action { + + handle(data) { + const client = this.client; + const guild = client.guilds.get(data.id); + + if (guild) { + data.presences = data.presences || []; + data.members = data.members || []; + for (const presence of data.presences) { + const user = client.users.get(presence.user.id); + if (user) { + user.status = presence.status; + user.game = presence.game; + } + } + for (const syncMember of data.members) { + const member = guild.members.get(syncMember.user.id); + if (member) { + guild._updateMember(member, syncMember); + } + } + } + } +} + +module.exports = GuildSync; diff --git a/src/client/websocket/WebSocketManager.js b/src/client/websocket/WebSocketManager.js index da53944d2..3f07901a1 100644 --- a/src/client/websocket/WebSocketManager.js +++ b/src/client/websocket/WebSocketManager.js @@ -71,7 +71,10 @@ class WebSocketManager { * @param {Object} packet An object that can be JSON stringified * @returns {void} */ - send(data) { + send(data, force = false) { + if (force) { + return this.ws.send(JSON.stringify(data)); + } this._queue.push(JSON.stringify(data)); this.doQueue(); } diff --git a/src/client/websocket/packets/WebSocketPacketManager.js b/src/client/websocket/packets/WebSocketPacketManager.js index 88b0f5c0e..284024a77 100644 --- a/src/client/websocket/packets/WebSocketPacketManager.js +++ b/src/client/websocket/packets/WebSocketPacketManager.js @@ -40,6 +40,7 @@ class WebSocketPacketManager { this.register(Constants.WSEvents.VOICE_SERVER_UPDATE, 'VoiceServerUpdate'); this.register(Constants.WSEvents.MESSAGE_DELETE_BULK, 'MessageDeleteBulk'); this.register(Constants.WSEvents.CHANNEL_PINS_UPDATE, 'ChannelPinsUpdate'); + this.register(Constants.WSEvents.GUILD_SYNC, 'GuildSync'); } get client() { diff --git a/src/client/websocket/packets/handlers/GuildSync.js b/src/client/websocket/packets/handlers/GuildSync.js new file mode 100644 index 000000000..941ea9f15 --- /dev/null +++ b/src/client/websocket/packets/handlers/GuildSync.js @@ -0,0 +1,14 @@ +const AbstractHandler = require('./AbstractHandler'); + +class GuildSyncHandler extends AbstractHandler { + + handle(packet) { + const data = packet.d; + const client = this.packetManager.client; + + client.actions.GuildSync.handle(data); + } + +} + +module.exports = GuildSyncHandler; diff --git a/src/client/websocket/packets/handlers/Ready.js b/src/client/websocket/packets/handlers/Ready.js index 217127c77..3f430d71a 100644 --- a/src/client/websocket/packets/handlers/Ready.js +++ b/src/client/websocket/packets/handlers/Ready.js @@ -21,6 +21,12 @@ class ReadyHandler extends AbstractHandler { client.dataManager.newChannel(privateDM); } + if (!client.user.bot) { + client.setInterval(client.syncGuilds.bind(client), 30000); + } + + client.once('ready', client.syncGuilds.bind(client)); + this.packetManager.ws.sessionID = data.session_id; this.packetManager.ws.checkIfReady('abc'); diff --git a/src/structures/Guild.js b/src/structures/Guild.js index 5c2e98117..45cb56cf2 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -625,11 +625,12 @@ class Guild { return this.members.get(this.ownerID); } + /** + * Syncs this guild (already done automatically every 30 seconds) + * @returns {void} + */ sync() { - return this.client.ws.send({ - op: 12, - d: [this.id], - }); + this.client.syncGuilds([this]); } } diff --git a/src/util/Constants.js b/src/util/Constants.js index 88d8d52a2..db3bb220b 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -201,6 +201,7 @@ exports.WSEvents = { VOICE_SERVER_UPDATE: 'VOICE_SERVER_UPDATE', MESSAGE_DELETE_BULK: 'MESSAGE_DELETE_BULK', CHANNEL_PINS_UPDATE: 'CHANNEL_PINS_UPDATE', + GUILD_SYNC: 'GUILD_SYNC', }; const PermissionFlags = exports.PermissionFlags = {