From f95c588d875c4b5fab0ed9831383205941c32aca Mon Sep 17 00:00:00 2001 From: hydrabolt Date: Sun, 1 May 2016 14:51:46 +0100 Subject: [PATCH] Added Guild Deletion --- TODO.md | 4 +- src/client/actions/ActionsManager.js | 1 + src/client/actions/ChannelDelete.js | 17 ++++++ src/client/actions/GuildDelete.js | 54 +++++++++++++++++++ src/client/actions/MessageDelete.js | 19 +++++-- src/client/rest/RESTMethods.js | 21 ++++++++ .../packets/handlers/ChannelDelete.js | 2 +- .../websocket/packets/handlers/GuildDelete.js | 17 ++---- src/structures/Guild.js | 8 +++ src/structures/ServerChannel.js | 1 + src/structures/datastore/ClientDataStore.js | 1 - test/random.js | 10 ++-- 12 files changed, 129 insertions(+), 26 deletions(-) create mode 100644 src/client/actions/GuildDelete.js diff --git a/TODO.md b/TODO.md index 19bac313b..0f2f60e58 100644 --- a/TODO.md +++ b/TODO.md @@ -5,8 +5,8 @@ - [ ] updating user details - [x] deleting messages - [x] updating messages -- [ ] leaving guilds -- [ ] deleting guilds +- [x] leaving guilds +- [x] deleting guilds - [ ] _joining guilds_ - [x] creating channels - [x] updating channels diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js index 8e4032eed..ed711b5fa 100644 --- a/src/client/actions/ActionsManager.js +++ b/src/client/actions/ActionsManager.js @@ -12,6 +12,7 @@ class ActionsManager { this.register('ChannelCreate'); this.register('ChannelDelete'); this.register('ChannelUpdate'); + this.register('GuildDelete'); } register(name) { diff --git a/src/client/actions/ChannelDelete.js b/src/client/actions/ChannelDelete.js index 2c07e0019..4f021d0ed 100644 --- a/src/client/actions/ChannelDelete.js +++ b/src/client/actions/ChannelDelete.js @@ -8,6 +8,8 @@ class ChannelDeleteAction extends Action { constructor(client) { super(client); + this.timeouts = []; + this.deleted = {}; } handle(data) { @@ -15,13 +17,28 @@ class ChannelDeleteAction extends Action { let channel = client.store.get('channels', data.id); if (channel) { + client.store.KillChannel(channel); + this.deleted[channel.id] = channel; + this.scheduleForDeletion(channel.id); + + } else if (this.deleted[data.id]) { + + channel = this.deleted[data.id]; + } return { channel, }; } + + scheduleForDeletion(id) { + this.timeouts.push( + setTimeout(() => delete this.deleted[id], + this.client.options.rest_ws_bridge_timeout) + ); + } }; module.exports = ChannelDeleteAction; diff --git a/src/client/actions/GuildDelete.js b/src/client/actions/GuildDelete.js new file mode 100644 index 000000000..271cb7b52 --- /dev/null +++ b/src/client/actions/GuildDelete.js @@ -0,0 +1,54 @@ +'use strict'; + +const Action = require('./Action'); +const Constants = require('../../util/Constants'); +const Message = require('../../structures/Message'); + +class GuildDeleteAction extends Action { + + constructor(client) { + super(client); + this.deleted = {}; + this.timeouts = []; + } + + handle(data) { + + let client = this.client; + let guild = client.store.get('guilds', data.id); + + if (guild) { + if (guild.available && data.unavailable) { + // guild is unavailable + guild.available = false; + client.emit(Constants.Events.GUILD_UNAVAILABLE, guild); + + // stops the GuildDelete packet thinking a guild was actually deleted, + // handles emitting of event itself + return { + guild: null, + }; + } else { + // delete guild + client.store.remove('guilds', guild); + this.deleted[guild.id] = guild; + this.scheduleForDeletion(guild.id); + } + } else if (this.deleted[data.id]) { + guild = this.deleted[data.id]; + } + + return { + guild, + }; + } + + scheduleForDeletion(id) { + this.timeouts.push( + setTimeout(() => delete this.deleted[id], + this.client.options.rest_ws_bridge_timeout) + ); + } +}; + +module.exports = GuildDeleteAction; diff --git a/src/client/actions/MessageDelete.js b/src/client/actions/MessageDelete.js index 9f82f0a15..a8a2f8e04 100644 --- a/src/client/actions/MessageDelete.js +++ b/src/client/actions/MessageDelete.js @@ -9,6 +9,7 @@ class MessageDeleteAction extends Action { constructor(client) { super(client); this.timeouts = []; + this.deleted = {}; } handle(data) { @@ -16,9 +17,17 @@ class MessageDeleteAction extends Action { let channel = client.store.get('channels', data.channel_id); if (channel) { let message = channel.store.get('messages', data.id); - if (message && !message._deleted) { - message._deleted = true; - this.scheduleForDeletion(channel, message.id); + + if (message) { + + channel.store.remove('messages', message.id); + this.deleted[channel.id + message.id] = message; + this.scheduleForDeletion(channel.id, message.id); + + } else if (this.deleted[channel.id + data.id]) { + + message = this.deleted[channel.id + data.id]; + } return { @@ -31,9 +40,9 @@ class MessageDeleteAction extends Action { }; } - scheduleForDeletion(channel, id) { + scheduleForDeletion(channelID, messageID) { this.timeouts.push( - setTimeout(() => channel.store.remove('messages', id), + setTimeout(() => delete this.deleted[channelID + messageID], this.client.options.rest_ws_bridge_timeout) ); } diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js index 7311aa55a..d175dcf67 100644 --- a/src/client/rest/RESTMethods.js +++ b/src/client/rest/RESTMethods.js @@ -111,6 +111,27 @@ class RESTMethods{ .catch(reject); }); } + + LeaveGuild(guild) { + return new Promise((resolve, reject) => { + this.rest.makeRequest('del', Constants.Endpoints.ME_GUILD(guild.id), true) + .then(() => { + resolve(this.rest.client.actions.GuildDelete.handle({ id:guild.id }).guild); + }) + .catch(reject); + }); + } + + // untested but probably will work + DeleteGuild(guild) { + return new Promise((resolve, reject) => { + this.rest.makeRequest('del', Constants.Endpoints.GUILD(guild.id), true) + .then(() => { + resolve(this.rest.client.actions.GuildDelete.handle({ id:guild.id }).guild); + }) + .catch(reject); + }); + } } module.exports = RESTMethods; diff --git a/src/client/websocket/packets/handlers/ChannelDelete.js b/src/client/websocket/packets/handlers/ChannelDelete.js index 8a171dc43..82a6eed6f 100644 --- a/src/client/websocket/packets/handlers/ChannelDelete.js +++ b/src/client/websocket/packets/handlers/ChannelDelete.js @@ -19,7 +19,7 @@ class ChannelDeleteHandler extends AbstractHandler { let data = packet.d; let client = this.packetManager.client; - let response = client.actions.ChannelCreate.handle(data); + let response = client.actions.ChannelDelete.handle(data); if (response.channel) { client.emit(Constants.Events.CHANNEL_DELETE, response.channel); diff --git a/src/client/websocket/packets/handlers/GuildDelete.js b/src/client/websocket/packets/handlers/GuildDelete.js index 350c27b1c..05319a5cb 100644 --- a/src/client/websocket/packets/handlers/GuildDelete.js +++ b/src/client/websocket/packets/handlers/GuildDelete.js @@ -18,21 +18,10 @@ class GuildDeleteHandler extends AbstractHandler { let data = packet.d; let client = this.packetManager.client; - let guild = client.store.get('guilds', data.id); + let response = client.actions.GuildDelete.handle(data); - if (guild) { - if (guild.available && data.unavailable) { - // guild is unavailable - guild.available = false; - client.emit(Constants.Events.GUILD_UNAVAILABLE, guild); - } else { - // delete guild - client.store.KillGuild(guild); - this.packetManager.ws.checkIfReady(); - } - } else { - // it's not there! :( - client.emit('warn', 'guild deleted but not cached in first place. missed packet?'); + if (response.guild) { + client.emit(Constants.Events.GUILD_DELETE, response.guild); } } diff --git a/src/structures/Guild.js b/src/structures/Guild.js index 566f3be0b..add9d37ed 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -135,6 +135,14 @@ class Guild { return this.client.rest.methods.CreateChannel(this, name, type); } + leave() { + return this.client.rest.methods.LeaveGuild(this); + } + + delete() { + return this.client.rest.methods.DeleteGuild(this); + } + get channels() { return this.store.getAsArray('channels'); } get $channels() { return this.store.data.channels; } diff --git a/src/structures/ServerChannel.js b/src/structures/ServerChannel.js index d5133a4a6..f15f1b613 100644 --- a/src/structures/ServerChannel.js +++ b/src/structures/ServerChannel.js @@ -9,6 +9,7 @@ function arraysEqual(a, b) { if (a === b) return true; for (let itemInd in a) { + let item = a[itemInd]; let ind = b.indexOf(item); if (ind) { b.splice(ind, 1); diff --git a/src/structures/datastore/ClientDataStore.js b/src/structures/datastore/ClientDataStore.js index 15f359d6a..cdcbdc2e3 100644 --- a/src/structures/datastore/ClientDataStore.js +++ b/src/structures/datastore/ClientDataStore.js @@ -82,7 +82,6 @@ class ClientDataStore extends AbstractDataStore{ } KillChannel(channel) { - let already = this.get('channels', channel.id); this.remove('channels', channel); if (channel instanceof ServerChannel) { channel.guild.store.remove('channels', channel); diff --git a/test/random.js b/test/random.js index 03c244535..9f4b6879d 100644 --- a/test/random.js +++ b/test/random.js @@ -14,7 +14,7 @@ client.on('guildCreate', (guild) => { console.log(guild); }); client.on('guildDelete', (guild) => { - console.log(guild); + console.log('guilddel', guild.name); }); client.on('guildUpdate', (old, guild) => { console.log(old.name, guild.name); @@ -23,7 +23,7 @@ client.on('channelCreate', channel => { // console.log(channel); }); client.on('channelDelete', channel => { - console.log('channDel', channel); + console.log('channDel', channel.name); }); client.on('channelUpdate', (old, chan) => { @@ -77,12 +77,16 @@ client.on('message', message => { } if (message.content === 'delchann') { - message.channel.delete(); + message.channel.delete().then(chan => console.log('selfDelChann', chan.name)); } if (message.content.startsWith('setname')) { message.channel.setName(message.content.substr(8)).then(chanLoop).catch(console.log); } + + if (message.content === 'leave') { + message.guild.leave().then(guild => console.log('left guild', guild.name)).catch(console.log); + } } });