From ab1737524821d2ad4a2176a7184ffbe1d68ae404 Mon Sep 17 00:00:00 2001 From: hydrabolt Date: Tue, 3 May 2016 16:42:38 +0100 Subject: [PATCH] Added GuildUpdate handling, and setting guilds details --- src/client/ClientDataResolver.js | 24 ++++++ src/client/actions/ActionsManager.js | 1 + src/client/actions/GuildUpdate.js | 42 ++++++++++ src/client/rest/RESTMethods.js | 47 +++++++++++ .../websocket/packets/handlers/GuildUpdate.js | 6 +- src/structures/Guild.js | 82 ++++++++++++++++++- src/structures/ServerChannel.js | 3 +- test/random.js | 21 ++++- 8 files changed, 215 insertions(+), 11 deletions(-) create mode 100644 src/client/actions/GuildUpdate.js diff --git a/src/client/ClientDataResolver.js b/src/client/ClientDataResolver.js index 8f8cd6d22..fc65010cf 100644 --- a/src/client/ClientDataResolver.js +++ b/src/client/ClientDataResolver.js @@ -5,6 +5,7 @@ const Structure = name => require(`../structures/${name}`); const User = Structure('User'); const Message = Structure('Message'); const Guild = Structure('Guild'); +const Channel = Structure('Channel'); const ServerChannel = Structure('ServerChannel'); const TextChannel = Structure('TextChannel'); const VoiceChannel = Structure('VoiceChannel'); @@ -59,8 +60,31 @@ class ClientDataResolver { if (data instanceof Buffer) { return 'data:image/jpg;base64,' + data.toString('base64'); } + return data; } + + ResolveChannel(channel) { + if (channel instanceof Channel) { + return channel; + } + + if ($string(channel)) { + return this.client.store.get('channels', channel); + } + } + + ResolveString(data) { + if (data instanceof String) { + return data; + } + + if (data instanceof Array) { + return data.join('\n'); + } + + return String(data); + } } module.exports = ClientDataResolver; diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js index 9b1ed9256..41d5be9de 100644 --- a/src/client/actions/ActionsManager.js +++ b/src/client/actions/ActionsManager.js @@ -13,6 +13,7 @@ class ActionsManager { this.register('ChannelDelete'); this.register('ChannelUpdate'); this.register('GuildDelete'); + this.register('GuildUpdate'); this.register('UserUpdate'); } diff --git a/src/client/actions/GuildUpdate.js b/src/client/actions/GuildUpdate.js new file mode 100644 index 000000000..96ab7565e --- /dev/null +++ b/src/client/actions/GuildUpdate.js @@ -0,0 +1,42 @@ +'use strict'; + +const Action = require('./Action'); +const Constants = require('../../util/Constants'); +const CloneObject = require('../../util/CloneObject'); +const Message = require('../../structures/Message'); + +class GuildUpdateAction 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) { + let oldGuild = CloneObject(guild); + guild.setup(data); + + if (!oldGuild.equals(data)) { + client.emit(Constants.Events.GUILD_UPDATE, oldGuild, guild); + } + + return { + old: oldGuild, + updated: guild, + }; + } + + return { + old: null, + updated: null, + }; + } +}; + +module.exports = GuildUpdateAction; diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js index 2a3a54176..810b3df58 100644 --- a/src/client/rest/RESTMethods.js +++ b/src/client/rest/RESTMethods.js @@ -152,6 +152,53 @@ class RESTMethods{ .catch(reject); }); } + + UpdateGuild(guild, _data) { + return new Promise((resolve, reject) => { + /* + can contain: + name, region, verificationLevel, afkChannel, afkTimeout, icon, owner, splash + */ + + let data = {}; + + if (_data.name) { + data.name = _data.name; + } + + if (_data.region) { + data.region = _data.region; + } + + if (_data.verificationLevel) { + data.verification_level = Number(_data.verificationLevel); + } + + if (_data.afkChannel) { + data.afk_channel_id = this.rest.client.resolver.ResolveChannel(_data.afkChannel).id; + } + + if (_data.afkTimeout) { + data.afk_timeout = Number(_data.afkTimeout); + } + + if (_data.icon) { + data.icon = this.rest.client.resolver.ResolveBase64(_data.icon); + } + + if (_data.owner) { + data.owner_id = this.rest.client.resolver.ResolveUser(_data.owner).id; + } + + if (_data.splash) { + data.splash = this.rest.client.resolver.ResolveBase64(_data.splash); + } + + this.rest.makeRequest('patch', Constants.Endpoints.GUILD(guild.id), true, data) + .then(data => resolve(this.rest.client.actions.GuildUpdate.handle(data).updated)) + .catch(reject); + }); + } } module.exports = RESTMethods; diff --git a/src/client/websocket/packets/handlers/GuildUpdate.js b/src/client/websocket/packets/handlers/GuildUpdate.js index e74effbfc..7a44eaabc 100644 --- a/src/client/websocket/packets/handlers/GuildUpdate.js +++ b/src/client/websocket/packets/handlers/GuildUpdate.js @@ -19,11 +19,7 @@ class GuildUpdateHandler extends AbstractHandler { let data = packet.d; let client = this.packetManager.client; - let guild = client.store.get('guilds', data.id); - - if (guild) { - client.store.UpdateGuild(guild, data); - } + let response = client.actions.GuildUpdate.handle(data); } diff --git a/src/structures/Guild.js b/src/structures/Guild.js index add9d37ed..1d5e71a6d 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -8,6 +8,21 @@ const VoiceChannel = require('./VoiceChannel'); const Constants = require('../Util/Constants'); const Role = require('./Role'); +function arraysEqual(a, b) { + if (a === b) return true; + if (a.length !== b.length) return false; + + for (let itemInd in a) { + let item = a[itemInd]; + let ind = b.indexOf(item); + if (ind) { + b.splice(ind, 1); + } + } + + return b.length === 0; +} + class Guild { constructor(client, data) { this.client = client; @@ -64,6 +79,34 @@ class Guild { return this.client.resolver.ResolveGuildMember(this, user); } + equals(data) { + let base = + this.id === data.id && + this.available === !data.unavailable && + this.splash === data.splash && + this.region === data.region && + this.name === data.name && + this.memberCount === data.member_count && + this.large === data.large && + this.icon === data.icon && + arraysEqual(this.features, data.features) && + this.owner.id === data.owner_id && + this.verificationLevel === data.verification_level && + this.embedEnabled === data.embed_enabled; + + if (base) { + if (this.embedChannel) { + if (this.embedChannel.id !== data.embed_channel_id) { + base = false; + } + } else if (data.embed_channel_id) { + base = false; + } + } + + return base; + } + setup(data) { this.id = data.id; this.available = !data.unavailable; @@ -79,7 +122,6 @@ class Guild { this.afkTimeout = data.afk_timeout; this.afkChannelID = data.afk_channel_id; this.embedEnabled = data.embed_enabled; - this.embedChannelID = data.embed_channel_id; this.verificationLevel = data.verification_level; this.features = data.features || []; @@ -99,6 +141,8 @@ class Guild { } } + this.embedChannel = this.store.get('channels', data.embed_channel_id); + if (data.roles) { this.store.clear('roles'); for (let role of data.roles) { @@ -143,6 +187,42 @@ class Guild { return this.client.rest.methods.DeleteGuild(this); } + edit(data) { + return this.client.rest.methods.UpdateGuild(this, data); + } + + setName(name) { + return this.edit({ name, }); + } + + setRegion(region) { + return this.edit({ region, }); + } + + setVerificationLevel(verificationLevel) { + return this.edit({ verificationLevel, }); + } + + setAFKChannel(afkchannel) { + return this.edit({ afkChannel, }); + } + + setAFKTimeout(afkTimeout) { + return this.edit({ afkTimeout, }); + } + + setIcon(icon) { + return this.edit({ icon, }); + } + + setOwner(owner) { + return this.edit({ owner, }); + } + + setSplash(splash) { + return this.edit({ splash, }); + } + 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 f15f1b613..3ff271477 100644 --- a/src/structures/ServerChannel.js +++ b/src/structures/ServerChannel.js @@ -7,6 +7,7 @@ const Constants = require('../util/Constants'); function arraysEqual(a, b) { if (a === b) return true; + if (a.length !== b.length) return false; for (let itemInd in a) { let item = a[itemInd]; @@ -50,7 +51,7 @@ class ServerChannel extends Channel{ ); if (base) { - if (other.permission_overwrites && other.permission_overwrites.length === this.permissionOverwrites.length) { + if (other.permission_overwrites) { let thisIDSet = this.permissionOverwrites.map(overwrite => overwrite.id); let otherIDSet = other.permission_overwrites.map(overwrite => overwrite.id); if (arraysEqual(thisIDSet, otherIDSet)) { diff --git a/test/random.js b/test/random.js index 194fe13da..656986c42 100644 --- a/test/random.js +++ b/test/random.js @@ -18,7 +18,7 @@ client.on('guildDelete', (guild) => { console.log('guilddel', guild.name); }); client.on('guildUpdate', (old, guild) => { - console.log(old.name, guild.name); + console.log('guildupdate', old.name, guild.name); }); client.on('channelCreate', channel => { // console.log(channel); @@ -82,11 +82,11 @@ client.on('message', message => { } if (message.content.startsWith('setname')) { - message.channel.setName(message.content.substr(8)).then(chanLoop).catch(console.log); + message.channel.setName(message.content.substr(8)); } if (message.content.startsWith('botname')) { - client.user.setUsername(message.content.substr(8)).then(nameLoop).catch(console.log); + client.user.setUsername(message.content.substr(8)); } if (message.content.startsWith('botavatar')) { @@ -98,14 +98,27 @@ client.on('message', message => { }); } + if (message.content.startsWith('gn')) { + message.guild.setName(message.content.substr(3)) + .then(guild => console.log('guild updated to', guild.name)) + .catch(console.log); + } + if (message.content === 'leave') { message.guild.leave().then(guild => console.log('left guild', guild.name)).catch(console.log); } + + if (message.content === 'stats') { + let m = ''; + m += `I am aware of ${message.guild.channels.length} channels\n`; + m += `I am aware of ${message.guild.members.length} members`; + message.channel.sendMessage(m); + } } }); function nameLoop(user) { - user.setUsername(user.username + 'a').then(nameLoop).catch(console.log); + // user.setUsername(user.username + 'a').then(nameLoop).catch(console.log); } function chanLoop(channel) {