From 998a48596d8e7b40c3f135bf690469eccce500be Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sat, 22 Apr 2017 22:26:44 -0500 Subject: [PATCH 01/40] start audit logs --- src/structures/GuildAuditLogs.js | 90 ++++++++++++++++++++++++++++++++ src/util/Permissions.js | 1 + 2 files changed, 91 insertions(+) create mode 100644 src/structures/GuildAuditLogs.js diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js new file mode 100644 index 000000000000..9813ce158510 --- /dev/null +++ b/src/structures/GuildAuditLogs.js @@ -0,0 +1,90 @@ +const Targets = { + GUILD: 'GUILD', + CHANNEL: 'CHANNEL', + USER: 'USER', + ROLE: 'ROLE', + INVITE: 'INVITE', + WEBHOOK: 'WEBHOOK', + EMOJI: 'EMOJI', +}; + +const Actions = { + GUILD_UPDATE: 1, + CHANNEL_CREATE: 10, + CHANNEL_UPDATE: 11, + CHANNEL_DELETE: 12, + CHANNEL_OVERWRITE_CREATE: 13, + CHANNEL_OVERWRITE_UPDATE: 14, + CHANNEL_OVERWRITE_DELETE: 15, + MEMBER_KICK: 20, + MEMBER_PRUNE: 21, + MEMBER_BAN_ADD: 22, + MEMBER_BAN_REMOVE: 23, + MEMBER_UPDATE: 24, + MEMBER_ROLE_UPDATE: 25, + ROLE_CREATE: 30, + ROLE_UPDATE: 31, + ROLE_DELETE: 32, + INVITE_CREATE: 40, + INVITE_UPDATE: 41, + INVITE_DELETE: 42, + WEBHOOK_CREATE: 50, + WEBHOOK_UPDATE: 51, + WEBHOOK_DELETE: 52, + EMOJI_CREATE: 60, + EMOJI_UPDATE: 61, + EMOJI_DELETE: 62 +}; + +class GuildAuditLogs { + static rootType(e) { + if (e < 10) return Targets.GUILD; + if (e < 20) return Targets.CHANNEL; + if (e < 30) return Targets.USER; + if (e < 40) return Targets.ROLE; + if (e < 50) return Targets.INVITE; + if (e < 60) return Targets.WEBHOOK; + if (e < 70) return Targets.EMOJI; + return null; + } + + static rootMethod(e) { + switch (e) { + case Actions.CHANNEL_CREATE: + case Actions.CHANNEL_OVERWRITE_CREATE: + case Actions.MEMBER_BAN_REMOVE: + case Actions.ROLE_CREATE: + case Actions.INVITE_CREATE: + case Actions.WEBHOOK_CREATE: + case Actions.EMOJI_CREATE: + return 'CREATE'; + + case Actions.CHANNEL_DELETE: + case Actions.CHANNEL_OVERWRITE_DELETE: + case Actions.MEMBER_KICK: + case Actions.MEMBER_PRUNE: + case Actions.MEMBER_BAN_ADD: + case Actions.ROLE_DELETE: + case Actions.INVITE_DELETE: + case Actions.WEBHOOK_DELETE: + case Actions.EMOJI_DELETE: + return 'DELETE'; + + case Actions.GUILD_UPDATE: + case Actions.CHANNEL_UPDATE: + case Actions.CHANNEL_OVERWRITE_UPDATE: + case Actions.MEMBER_UPDATE: + case Actions.ROLE_UPDATE: + case Actions.INVITE_UPDATE: + case Actions.WEBHOOK_UPDATE: + case Actions.EMOJI_UPDATE: + default: + return 'UPDATE'; + } + + } +} + +GuildAuditLogs.Actions = Actions; + +module.exports = GuildAuditLogs; diff --git a/src/util/Permissions.js b/src/util/Permissions.js index bbc4e4d77b8b..d58144c258bb 100644 --- a/src/util/Permissions.js +++ b/src/util/Permissions.js @@ -203,6 +203,7 @@ Permissions.FLAGS = { MANAGE_CHANNELS: 1 << 4, MANAGE_GUILD: 1 << 5, ADD_REACTIONS: 1 << 6, + VIEW_AUDIT_LOG: 1 << 7, READ_MESSAGES: 1 << 10, SEND_MESSAGES: 1 << 11, From 22d35406c19b1a40f96658fc0222b3283996eb05 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sat, 22 Apr 2017 22:31:35 -0500 Subject: [PATCH 02/40] make better var types so gawdl3y doesn't shit on this --- src/structures/GuildAuditLogs.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 9813ce158510..9e625f9bd34a 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -37,19 +37,19 @@ const Actions = { }; class GuildAuditLogs { - static rootType(e) { - if (e < 10) return Targets.GUILD; - if (e < 20) return Targets.CHANNEL; - if (e < 30) return Targets.USER; - if (e < 40) return Targets.ROLE; - if (e < 50) return Targets.INVITE; - if (e < 60) return Targets.WEBHOOK; - if (e < 70) return Targets.EMOJI; + static rootType(type) { + if (type < 10) return Targets.GUILD; + if (type < 20) return Targets.CHANNEL; + if (type < 30) return Targets.USER; + if (type < 40) return Targets.ROLE; + if (type < 50) return Targets.INVITE; + if (type < 60) return Targets.WEBHOOK; + if (type < 70) return Targets.EMOJI; return null; } static rootMethod(e) { - switch (e) { + switch (method) { case Actions.CHANNEL_CREATE: case Actions.CHANNEL_OVERWRITE_CREATE: case Actions.MEMBER_BAN_REMOVE: From cdb6241e605e203b1aef6261dbdb9548c084be63 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sat, 22 Apr 2017 22:40:45 -0500 Subject: [PATCH 03/40] add constructor stuff --- src/structures/GuildAuditLogs.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 9e625f9bd34a..0e755ed2f5f5 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -37,6 +37,17 @@ const Actions = { }; class GuildAuditLogs { + constructor(guild, data) { + this.guild = data.guild; + if (data.users) for (const user of data.users) this.guild.client.manager.newUser(user); + if (data.channels) for (const channel of data.channels) this.guild.client.manager.newChannel(channel, guild); + + for (const entry of data.audit_log_entries) { + // i dunno something + // { target_id: Snowflake, user_id: ?Snowflake, channel_id: ?Snowflake, id: Snowflake, action_type: Int } + } + } + static rootType(type) { if (type < 10) return Targets.GUILD; if (type < 20) return Targets.CHANNEL; @@ -48,7 +59,7 @@ class GuildAuditLogs { return null; } - static rootMethod(e) { + static rootMethod(method) { switch (method) { case Actions.CHANNEL_CREATE: case Actions.CHANNEL_OVERWRITE_CREATE: From cd397e16f330b3ed2e15d693ed38e85a7226bdf6 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sat, 22 Apr 2017 22:51:55 -0500 Subject: [PATCH 04/40] make more changes --- src/structures/GuildAuditLogs.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 0e755ed2f5f5..91769f936b12 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -33,7 +33,7 @@ const Actions = { WEBHOOK_DELETE: 52, EMOJI_CREATE: 60, EMOJI_UPDATE: 61, - EMOJI_DELETE: 62 + EMOJI_DELETE: 62, }; class GuildAuditLogs { @@ -42,9 +42,10 @@ class GuildAuditLogs { if (data.users) for (const user of data.users) this.guild.client.manager.newUser(user); if (data.channels) for (const channel of data.channels) this.guild.client.manager.newChannel(channel, guild); + this.entries = []; for (const entry of data.audit_log_entries) { - // i dunno something - // { target_id: Snowflake, user_id: ?Snowflake, channel_id: ?Snowflake, id: Snowflake, action_type: Int } + // AAA { target_id: Snowflake, user_id: ?Snowflake, channel_id: ?Snowflake, id: Snowflake, action_type: Int } + this.createEntry(entry); } } @@ -92,7 +93,6 @@ class GuildAuditLogs { default: return 'UPDATE'; } - } } From 7e47d54ab8fd4d65c5212bdfb089d472a8aa35f1 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sat, 22 Apr 2017 23:19:48 -0500 Subject: [PATCH 05/40] add entry creation --- src/structures/GuildAuditLogs.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 91769f936b12..ef0733b1e9cd 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -43,10 +43,20 @@ class GuildAuditLogs { if (data.channels) for (const channel of data.channels) this.guild.client.manager.newChannel(channel, guild); this.entries = []; - for (const entry of data.audit_log_entries) { - // AAA { target_id: Snowflake, user_id: ?Snowflake, channel_id: ?Snowflake, id: Snowflake, action_type: Int } - this.createEntry(entry); - } + for (const entry of data.audit_log_entries) this.createEntry(entry); + } + + createEntry(entry) { + const type = this.constructor.rootType(entry.action_type); + const newEntry = { + type, + method: this.constructor.rootMethod(entry.action_type), + target: this.guild[`${type.toLowerCase()}s`].get(entry.target_id), + user: client.users.get(entry.user_id), + changes: entry.changes ? entry.changes.map(c => ({ name: c.key, old: c.old_value, ['new']: c.new_value })) : null, + id: entry.id, + }; + this.entries.push(newEntry); } static rootType(type) { From 1fd6514960c90ff36afabf1a4c007f7900783933 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sat, 22 Apr 2017 23:29:30 -0500 Subject: [PATCH 06/40] add methods --- src/structures/Guild.js | 8 ++++++++ src/util/Constants.js | 1 + 2 files changed, 9 insertions(+) diff --git a/src/structures/Guild.js b/src/structures/Guild.js index 517df9e4cd48..12593f3a9508 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -374,6 +374,14 @@ class Guild { return this.client.rest.methods.fetchVoiceRegions(this.id); } + /** + * Fetch audit logs for this guild + * @returns {Promise} + */ + fetchAuditLogs() { + return this.client.rest.methods.fetchAuditLogs(this); + } + /** * Adds a user to the guild using OAuth2. Requires the `CREATE_INSTANT_INVITE` permission. * @param {UserResolvable} user User to add to the guild diff --git a/src/util/Constants.js b/src/util/Constants.js index d418b7ea19ec..62244ad903f5 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -125,6 +125,7 @@ const Endpoints = exports.Endpoints = { webhooks: `${base}/webhooks`, ack: `${base}/ack`, settings: `${base}/settings`, + auditLogs: `${base}/audit-logs`, Emoji: emojiID => `${base}/emojis/${emojiID}`, Icon: (root, hash) => Endpoints.CDN(root).Icon(guildID, hash), Splash: (root, hash) => Endpoints.CDN(root).Splash(guildID, hash), From 75617d8e3ec1d976d56a2382dd448d88fc0e174e Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sat, 22 Apr 2017 23:33:53 -0500 Subject: [PATCH 07/40] make it all work hopefully --- src/client/rest/RESTMethods.js | 7 +++++++ src/structures/Guild.js | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js index 91cbd25a1d12..f0d0b3cfb793 100644 --- a/src/client/rest/RESTMethods.js +++ b/src/client/rest/RESTMethods.js @@ -19,6 +19,7 @@ const Channel = require('../../structures/Channel'); const GroupDMChannel = require('../../structures/GroupDMChannel'); const Guild = require('../../structures/Guild'); const VoiceRegion = require('../../structures/VoiceRegion'); +const GuildAuditLogs = require('../../structures/GuildAuditLogs'); class RESTMethods { constructor(restManager) { @@ -671,6 +672,12 @@ class RESTMethods { .then(() => this.client.actions.GuildEmojiDelete.handle(emoji).data); } + getGuildAuditLogs(guild) { + return this.rest.makeRequest('get', Endpoints.Guild(guild).auditLogs, true).then(data => + new GuildAuditLogs(guild, data) + ); + } + getWebhook(id, token) { return this.rest.makeRequest('get', Endpoints.Webhook(id, token), !token).then(data => new Webhook(this.client, data) diff --git a/src/structures/Guild.js b/src/structures/Guild.js index 12593f3a9508..99d1cd623354 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -379,7 +379,7 @@ class Guild { * @returns {Promise} */ fetchAuditLogs() { - return this.client.rest.methods.fetchAuditLogs(this); + return this.client.rest.methods.getGuildAuditLogs(this); } /** From 536a0296e0c073b89e1c357faefdc801fa48479b Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sat, 22 Apr 2017 23:42:46 -0500 Subject: [PATCH 08/40] aaa --- src/structures/GuildAuditLogs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index ef0733b1e9cd..5a2c89e6b353 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -38,7 +38,7 @@ const Actions = { class GuildAuditLogs { constructor(guild, data) { - this.guild = data.guild; + this.guild = guild; if (data.users) for (const user of data.users) this.guild.client.manager.newUser(user); if (data.channels) for (const channel of data.channels) this.guild.client.manager.newChannel(channel, guild); From c6d52002fc6f86928c9d4737ad093033b271e5aa Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sat, 22 Apr 2017 23:45:20 -0500 Subject: [PATCH 09/40] aaaa --- src/structures/GuildAuditLogs.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 5a2c89e6b353..feb51d315b46 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -39,8 +39,10 @@ const Actions = { class GuildAuditLogs { constructor(guild, data) { this.guild = guild; - if (data.users) for (const user of data.users) this.guild.client.manager.newUser(user); - if (data.channels) for (const channel of data.channels) this.guild.client.manager.newChannel(channel, guild); + if (data.users) for (const user of data.users) this.guild.client.dataManager.newUser(user); + if (data.channels) for (const channel of data.channels) { + this.guild.client.dataManager.newChannel(channel, guild); + } this.entries = []; for (const entry of data.audit_log_entries) this.createEntry(entry); From 4f2db4a8fbe8392c11cc41435c4a214134e3b853 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sat, 22 Apr 2017 23:46:54 -0500 Subject: [PATCH 10/40] i wish i could test this locally --- src/structures/GuildAuditLogs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index feb51d315b46..7e44726a0310 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -54,7 +54,7 @@ class GuildAuditLogs { type, method: this.constructor.rootMethod(entry.action_type), target: this.guild[`${type.toLowerCase()}s`].get(entry.target_id), - user: client.users.get(entry.user_id), + user: this.guild.client.users.get(entry.user_id), changes: entry.changes ? entry.changes.map(c => ({ name: c.key, old: c.old_value, ['new']: c.new_value })) : null, id: entry.id, }; From d53d80e30e722a1c129060b472a3695cf8f6e5e9 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sat, 22 Apr 2017 23:49:59 -0500 Subject: [PATCH 11/40] fix users, guild when i feel like it --- src/structures/GuildAuditLogs.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 7e44726a0310..633164be722f 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -53,7 +53,9 @@ class GuildAuditLogs { const newEntry = { type, method: this.constructor.rootMethod(entry.action_type), - target: this.guild[`${type.toLowerCase()}s`].get(entry.target_id), + target: type === 'USER' ? + this.guild.client.users.get(entry.target_id) : + this.guild[`${type.toLowerCase()}s`].get(entry.target_id), user: this.guild.client.users.get(entry.user_id), changes: entry.changes ? entry.changes.map(c => ({ name: c.key, old: c.old_value, ['new']: c.new_value })) : null, id: entry.id, From 837f0655d93dd840ddb95eece44d1e787376f7c3 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sat, 22 Apr 2017 23:51:58 -0500 Subject: [PATCH 12/40] make guild prop non-enumerable --- src/structures/GuildAuditLogs.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 633164be722f..be0a7383990f 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -38,7 +38,8 @@ const Actions = { class GuildAuditLogs { constructor(guild, data) { - this.guild = guild; + Object.defineProperty(this, 'guild', { value: guild }); + if (data.users) for (const user of data.users) this.guild.client.dataManager.newUser(user); if (data.channels) for (const channel of data.channels) { this.guild.client.dataManager.newChannel(channel, guild); From edfdafdf5124e7cb6f3438e69add916b643b8163 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sat, 22 Apr 2017 23:58:00 -0500 Subject: [PATCH 13/40] make better types --- src/structures/GuildAuditLogs.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index be0a7383990f..68e3dfb04395 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -50,13 +50,14 @@ class GuildAuditLogs { } createEntry(entry) { - const type = this.constructor.rootType(entry.action_type); + const root = this.constructor.rootType(entry.action_type); const newEntry = { - type, + root, + type: Object.keys(Actions).find(k => Actions[k] === entry.action_type), method: this.constructor.rootMethod(entry.action_type), - target: type === 'USER' ? + target: root === 'USER' ? this.guild.client.users.get(entry.target_id) : - this.guild[`${type.toLowerCase()}s`].get(entry.target_id), + this.guild[`${root.toLowerCase()}s`].get(entry.target_id), user: this.guild.client.users.get(entry.user_id), changes: entry.changes ? entry.changes.map(c => ({ name: c.key, old: c.old_value, ['new']: c.new_value })) : null, id: entry.id, From 1af75c2951922b8c52d2e0b3cff18e8450c93e1d Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sun, 23 Apr 2017 00:03:01 -0500 Subject: [PATCH 14/40] change nouns --- src/structures/GuildAuditLogs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 68e3dfb04395..7888c4f40a41 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -58,7 +58,7 @@ class GuildAuditLogs { target: root === 'USER' ? this.guild.client.users.get(entry.target_id) : this.guild[`${root.toLowerCase()}s`].get(entry.target_id), - user: this.guild.client.users.get(entry.user_id), + executor: this.guild.client.users.get(entry.user_id), changes: entry.changes ? entry.changes.map(c => ({ name: c.key, old: c.old_value, ['new']: c.new_value })) : null, id: entry.id, }; From 30c35e14a49311d4ef2176e4fec35e21a5bedb30 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sun, 23 Apr 2017 00:07:09 -0500 Subject: [PATCH 15/40] e --- src/structures/GuildAuditLogs.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 7888c4f40a41..4ebf6d7fb6b5 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -41,8 +41,8 @@ class GuildAuditLogs { Object.defineProperty(this, 'guild', { value: guild }); if (data.users) for (const user of data.users) this.guild.client.dataManager.newUser(user); - if (data.channels) for (const channel of data.channels) { - this.guild.client.dataManager.newChannel(channel, guild); + if (data.channels) { + for (const channel of data.channels) this.guild.client.dataManager.newChannel(channel, guild); } this.entries = []; @@ -59,7 +59,7 @@ class GuildAuditLogs { this.guild.client.users.get(entry.target_id) : this.guild[`${root.toLowerCase()}s`].get(entry.target_id), executor: this.guild.client.users.get(entry.user_id), - changes: entry.changes ? entry.changes.map(c => ({ name: c.key, old: c.old_value, ['new']: c.new_value })) : null, + changes: entry.changes ? entry.changes.map(c => ({ name: c.key, old: c.old_value, new: c.new_value })) : null, id: entry.id, }; this.entries.push(newEntry); From d4d6774871b5687a1238e3582b479df79838d1fa Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sun, 23 Apr 2017 11:53:17 -0500 Subject: [PATCH 16/40] Update GuildAuditLogs.js --- src/structures/GuildAuditLogs.js | 75 +++++++++++++++++++++++--------- 1 file changed, 54 insertions(+), 21 deletions(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 4ebf6d7fb6b5..cd279f5ab9c2 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -38,31 +38,13 @@ const Actions = { class GuildAuditLogs { constructor(guild, data) { - Object.defineProperty(this, 'guild', { value: guild }); - - if (data.users) for (const user of data.users) this.guild.client.dataManager.newUser(user); + if (data.users) for (const user of data.users) guild.client.dataManager.newUser(user); if (data.channels) { - for (const channel of data.channels) this.guild.client.dataManager.newChannel(channel, guild); + for (const channel of data.channels) guild.client.dataManager.newChannel(channel, guild); } this.entries = []; - for (const entry of data.audit_log_entries) this.createEntry(entry); - } - - createEntry(entry) { - const root = this.constructor.rootType(entry.action_type); - const newEntry = { - root, - type: Object.keys(Actions).find(k => Actions[k] === entry.action_type), - method: this.constructor.rootMethod(entry.action_type), - target: root === 'USER' ? - this.guild.client.users.get(entry.target_id) : - this.guild[`${root.toLowerCase()}s`].get(entry.target_id), - executor: this.guild.client.users.get(entry.user_id), - changes: entry.changes ? entry.changes.map(c => ({ name: c.key, old: c.old_value, new: c.new_value })) : null, - id: entry.id, - }; - this.entries.push(newEntry); + for (const entry of data.audit_log_entries) this.entries.push(new GuildAuditLogsEntry(guild, entry)); } static rootType(type) { @@ -114,4 +96,55 @@ class GuildAuditLogs { GuildAuditLogs.Actions = Actions; +class GuildAuditLogsEntry { + constructor(guild, data) { + const root = GuildAuditLogs.rootType(data.action_type); + /** + * Root action type of this entry + * @type {string} + */ + this.root = root; + + /** + * Specific action type of this entry + * @type {string} + */ + this.type = Object.keys(Actions).find(k => Actions[k] === entry.action_type); + + /** + * Method of this entry + * @type {string} + */ + this.method = GuildAuditLogs.rootMethod(data.action_type); + + if (['USER', 'GUILD'].includes(root)) { + /** + * Target of this entry + * @type {Guild|User|Role|Invite|Webhook|Emoji} + */ + this.target = guild.client[`${root.toLowerCase()}s`].get(entry.target_id); + } else { + this.target = guild[`${root.toLowerCase()}s`].get(entry.target_id); + } + + /** + * User that executed this entry + * @type {User} + */ + this.executor = guild.client.users.get(entry.user_id); + + /** + * Specific property changes + * @type {Object[]} + */ + this.changes: entry.changes ? entry.changes.map(c => ({ name: c.key, old: c.old_value, new: c.new_value })) : null; + + /** + * ID of this entry + * @type {Snowflake} + */ + this.id = entry.id; + } +} + module.exports = GuildAuditLogs; From 4f03c414ff72657f683dfe47d67b5451264144ca Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sun, 23 Apr 2017 11:55:15 -0500 Subject: [PATCH 17/40] Update GuildAuditLogs.js --- src/structures/GuildAuditLogs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index cd279f5ab9c2..8dce3f8c9d21 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -137,7 +137,7 @@ class GuildAuditLogsEntry { * Specific property changes * @type {Object[]} */ - this.changes: entry.changes ? entry.changes.map(c => ({ name: c.key, old: c.old_value, new: c.new_value })) : null; + this.changes = entry.changes ? entry.changes.map(c => ({ name: c.key, old: c.old_value, new: c.new_value })) : null; /** * ID of this entry From e9ca17b929aeb61381ba799cc39463d331ca4747 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sun, 23 Apr 2017 11:57:02 -0500 Subject: [PATCH 18/40] Update GuildAuditLogs.js --- src/structures/GuildAuditLogs.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 8dce3f8c9d21..3e5157b682c4 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -95,6 +95,7 @@ class GuildAuditLogs { } GuildAuditLogs.Actions = Actions; +GuildAuditLogs.Targets = Targets; class GuildAuditLogsEntry { constructor(guild, data) { @@ -109,7 +110,7 @@ class GuildAuditLogsEntry { * Specific action type of this entry * @type {string} */ - this.type = Object.keys(Actions).find(k => Actions[k] === entry.action_type); + this.type = Object.keys(Actions).find(k => Actions[k] === data.action_type); /** * Method of this entry @@ -122,28 +123,28 @@ class GuildAuditLogsEntry { * Target of this entry * @type {Guild|User|Role|Invite|Webhook|Emoji} */ - this.target = guild.client[`${root.toLowerCase()}s`].get(entry.target_id); + this.target = guild.client[`${root.toLowerCase()}s`].get(data.target_id); } else { - this.target = guild[`${root.toLowerCase()}s`].get(entry.target_id); + this.target = guild[`${root.toLowerCase()}s`].get(data.target_id); } /** * User that executed this entry * @type {User} */ - this.executor = guild.client.users.get(entry.user_id); + this.executor = guild.client.users.get(data.user_id); /** * Specific property changes * @type {Object[]} */ - this.changes = entry.changes ? entry.changes.map(c => ({ name: c.key, old: c.old_value, new: c.new_value })) : null; + this.changes = data.changes ? data.changes.map(c => ({ name: c.key, old: c.old_value, new: c.new_value })) : null; /** * ID of this entry * @type {Snowflake} */ - this.id = entry.id; + this.id = data.id; } } From 31b344355a83e9c17eb6375cd83c54ce46756cf1 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sun, 23 Apr 2017 20:11:11 -0500 Subject: [PATCH 19/40] eek --- src/structures/GuildAuditLogs.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 3e5157b682c4..0bd37bf32ac3 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -105,13 +105,13 @@ class GuildAuditLogsEntry { * @type {string} */ this.root = root; - + /** * Specific action type of this entry * @type {string} */ this.type = Object.keys(Actions).find(k => Actions[k] === data.action_type); - + /** * Method of this entry * @type {string} @@ -127,19 +127,19 @@ class GuildAuditLogsEntry { } else { this.target = guild[`${root.toLowerCase()}s`].get(data.target_id); } - + /** * User that executed this entry * @type {User} */ this.executor = guild.client.users.get(data.user_id); - + /** * Specific property changes * @type {Object[]} */ this.changes = data.changes ? data.changes.map(c => ({ name: c.key, old: c.old_value, new: c.new_value })) : null; - + /** * ID of this entry * @type {Snowflake} From 574ecb6fddb9803ee89ab451285f9b44e5dde995 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sun, 23 Apr 2017 20:14:10 -0500 Subject: [PATCH 20/40] Update GuildAuditLogs.js --- src/structures/GuildAuditLogs.js | 64 ++++++++++++++++---------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 0bd37bf32ac3..c9e05f2526cb 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -59,38 +59,38 @@ class GuildAuditLogs { } static rootMethod(method) { - switch (method) { - case Actions.CHANNEL_CREATE: - case Actions.CHANNEL_OVERWRITE_CREATE: - case Actions.MEMBER_BAN_REMOVE: - case Actions.ROLE_CREATE: - case Actions.INVITE_CREATE: - case Actions.WEBHOOK_CREATE: - case Actions.EMOJI_CREATE: - return 'CREATE'; - - case Actions.CHANNEL_DELETE: - case Actions.CHANNEL_OVERWRITE_DELETE: - case Actions.MEMBER_KICK: - case Actions.MEMBER_PRUNE: - case Actions.MEMBER_BAN_ADD: - case Actions.ROLE_DELETE: - case Actions.INVITE_DELETE: - case Actions.WEBHOOK_DELETE: - case Actions.EMOJI_DELETE: - return 'DELETE'; - - case Actions.GUILD_UPDATE: - case Actions.CHANNEL_UPDATE: - case Actions.CHANNEL_OVERWRITE_UPDATE: - case Actions.MEMBER_UPDATE: - case Actions.ROLE_UPDATE: - case Actions.INVITE_UPDATE: - case Actions.WEBHOOK_UPDATE: - case Actions.EMOJI_UPDATE: - default: - return 'UPDATE'; - } + if ([ + Actions.CHANNEL_CREATE, + Actions.CHANNEL_OVERWRITE_CREATE, + Actions.MEMBER_BAN_REMOVE, + Actions.ROLE_CREATE, + Actions.INVITE_CREATE, + Actions.WEBHOOK_CREATE, + Actions.EMOJI_CREATE, + ].includes(method)) return 'CREATE'; + + if ([ + Actions.CHANNEL_DELETE, + Actions.CHANNEL_OVERWRITE_DELETE, + Actions.MEMBER_KICK, + Actions.MEMBER_PRUNE, + Actions.MEMBER_BAN_ADD, + Actions.ROLE_DELETE, + Actions.INVITE_DELETE, + Actions.WEBHOOK_DELETE, + Actions.EMOJI_DELETE, + ].includes(method)) return 'DELETE'; + + if ([ + Actions.GUILD_UPDATE, + Actions.CHANNEL_UPDATE, + Actions.CHANNEL_OVERWRITE_UPDATE, + Actions.MEMBER_UPDATE, + Actions.ROLE_UPDATE, + Actions.INVITE_UPDATE, + Actions.WEBHOOK_UPDATE, + Actions.EMOJI_UPDATE, + ].includes(method)) return 'UPDATE'; } } From 7f515c5a83fbea3bd3525f16086d6bed0649d995 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sun, 23 Apr 2017 20:17:11 -0500 Subject: [PATCH 21/40] Update GuildAuditLogs.js --- src/structures/GuildAuditLogs.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index c9e05f2526cb..1d002333a44a 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -91,6 +91,9 @@ class GuildAuditLogs { Actions.WEBHOOK_UPDATE, Actions.EMOJI_UPDATE, ].includes(method)) return 'UPDATE'; + + // Discord client source suggests I should return 'UPDATE' if nothing else matches + return 'UPDATE'; } } From e40246b91cb9d398c89c893b25c8b3ff3610824a Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sun, 23 Apr 2017 20:19:21 -0500 Subject: [PATCH 22/40] friggin trailing spaces --- src/structures/GuildAuditLogs.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 1d002333a44a..dbb14059bab2 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -91,7 +91,7 @@ class GuildAuditLogs { Actions.WEBHOOK_UPDATE, Actions.EMOJI_UPDATE, ].includes(method)) return 'UPDATE'; - + // Discord client source suggests I should return 'UPDATE' if nothing else matches return 'UPDATE'; } From 83e0f3dc0cc99999fe154a031bfa835a40e27bf4 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Mon, 24 Apr 2017 16:34:10 -0500 Subject: [PATCH 23/40] Update GuildAuditLogs.js --- src/structures/GuildAuditLogs.js | 34 ++++++++++++++++---------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index dbb14059bab2..05f13da0acf8 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -47,18 +47,18 @@ class GuildAuditLogs { for (const entry of data.audit_log_entries) this.entries.push(new GuildAuditLogsEntry(guild, entry)); } - static rootType(type) { - if (type < 10) return Targets.GUILD; - if (type < 20) return Targets.CHANNEL; - if (type < 30) return Targets.USER; - if (type < 40) return Targets.ROLE; - if (type < 50) return Targets.INVITE; - if (type < 60) return Targets.WEBHOOK; - if (type < 70) return Targets.EMOJI; + static rootTarget(target) { + if (target < 10) return Targets.GUILD; + if (target < 20) return Targets.CHANNEL; + if (target < 30) return Targets.USER; + if (target < 40) return Targets.ROLE; + if (target < 50) return Targets.INVITE; + if (target < 60) return Targets.WEBHOOK; + if (target < 70) return Targets.EMOJI; return null; } - static rootMethod(method) { + static rootAction(action) { if ([ Actions.CHANNEL_CREATE, Actions.CHANNEL_OVERWRITE_CREATE, @@ -67,7 +67,7 @@ class GuildAuditLogs { Actions.INVITE_CREATE, Actions.WEBHOOK_CREATE, Actions.EMOJI_CREATE, - ].includes(method)) return 'CREATE'; + ].includes(action)) return 'CREATE'; if ([ Actions.CHANNEL_DELETE, @@ -79,7 +79,7 @@ class GuildAuditLogs { Actions.INVITE_DELETE, Actions.WEBHOOK_DELETE, Actions.EMOJI_DELETE, - ].includes(method)) return 'DELETE'; + ].includes(action)) return 'DELETE'; if ([ Actions.GUILD_UPDATE, @@ -90,7 +90,7 @@ class GuildAuditLogs { Actions.INVITE_UPDATE, Actions.WEBHOOK_UPDATE, Actions.EMOJI_UPDATE, - ].includes(method)) return 'UPDATE'; + ].includes(action)) return 'UPDATE'; // Discord client source suggests I should return 'UPDATE' if nothing else matches return 'UPDATE'; @@ -102,7 +102,7 @@ GuildAuditLogs.Targets = Targets; class GuildAuditLogsEntry { constructor(guild, data) { - const root = GuildAuditLogs.rootType(data.action_type); + const root = GuildAuditLogs.rootTarget(data.action_type); /** * Root action type of this entry * @type {string} @@ -110,16 +110,16 @@ class GuildAuditLogsEntry { this.root = root; /** - * Specific action type of this entry + * Action type of this entry * @type {string} */ - this.type = Object.keys(Actions).find(k => Actions[k] === data.action_type); + this.type = GuildAuditLogs.rootAction(data.action_type); /** - * Method of this entry + * Specific action type of this entry * @type {string} */ - this.method = GuildAuditLogs.rootMethod(data.action_type); + this.action = Object.keys(Actions).find(k => Actions[k] === data.action_type); if (['USER', 'GUILD'].includes(root)) { /** From c73bd8f345198581f4d4e6a998ac96e4f3f1fbf7 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Mon, 24 Apr 2017 16:35:40 -0500 Subject: [PATCH 24/40] docs! --- src/structures/GuildAuditLogs.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 05f13da0acf8..cb267ba34226 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -43,6 +43,10 @@ class GuildAuditLogs { for (const channel of data.channels) guild.client.dataManager.newChannel(channel, guild); } + /** + * Entries for this Guild's audit logs + * @type {GuildAuditLogsEntry[]} + */ this.entries = []; for (const entry of data.audit_log_entries) this.entries.push(new GuildAuditLogsEntry(guild, entry)); } From 447390c86d51de501158cdbaa77118366d750ee2 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Wed, 26 Apr 2017 19:16:03 -0500 Subject: [PATCH 25/40] Update GuildAuditLogs.js --- src/structures/GuildAuditLogs.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index cb267ba34226..f5b72ec09840 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -39,9 +39,6 @@ const Actions = { class GuildAuditLogs { constructor(guild, data) { if (data.users) for (const user of data.users) guild.client.dataManager.newUser(user); - if (data.channels) { - for (const channel of data.channels) guild.client.dataManager.newChannel(channel, guild); - } /** * Entries for this Guild's audit logs From a41623297989714462caf266f023a4a0c2c1cbb8 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Wed, 26 Apr 2017 19:52:26 -0500 Subject: [PATCH 26/40] reason stuff --- src/client/rest/RESTMethods.js | 15 +++++++-------- src/structures/Guild.js | 14 ++++++++++---- src/structures/GuildMember.js | 14 ++++++++------ 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js index f0d0b3cfb793..c848b0f827db 100644 --- a/src/client/rest/RESTMethods.js +++ b/src/client/rest/RESTMethods.js @@ -384,8 +384,9 @@ class RESTMethods { ); } - kickGuildMember(guild, member) { - return this.rest.makeRequest('delete', Endpoints.Guild(guild).Member(member), true).then(() => + kickGuildMember(guild, member, reason) { + const url = `${Endpoints.Guild(guild).Member(member)}?reason=${reason}`; + return this.rest.makeRequest('delete', url, true, { reason }).then(() => this.client.actions.GuildMemberRemove.handle({ guild_id: guild.id, user: member.user, @@ -528,14 +529,12 @@ class RESTMethods { return this.rest.makeRequest('post', Endpoints.Channel(channelID).typing, true); } - banGuildMember(guild, member, deleteDays = 0) { + banGuildMember(guild, member, options) { const id = this.client.resolver.resolveUserID(member); if (!id) return Promise.reject(new Error('Couldn\'t resolve the user ID to ban.')); - return this.rest.makeRequest( - 'put', `${Endpoints.Guild(guild).bans}/${id}?delete-message-days=${deleteDays}`, true, { - 'delete-message-days': deleteDays, - } - ).then(() => { + + const url = `${Endpoints.Guild(guild).bans}/${id}?${querystring.stringify(options)}`; + return this.rest.makeRequest('put', url, true).then(() => { if (member instanceof GuildMember) return member; const user = this.client.resolver.resolveUser(id); if (user) { diff --git a/src/structures/Guild.js b/src/structures/Guild.js index 99d1cd623354..4fc589f2c526 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -614,8 +614,9 @@ class Guild { /** * Bans a user from the guild. * @param {UserResolvable} user The user to ban - * @param {number} [deleteDays=0] The amount of days worth of messages from this user that should - * also be deleted. Between `0` and `7`. + * @param {Object} [options] Ban options. + * @param {number} [options.days=0] Number of days of messages to delete + * @param {string} [options.reason] Reason for banning * @returns {Promise} Result object will be resolved as specifically as possible. * If the GuildMember cannot be resolved, the User will instead be attempted to be resolved. If that also cannot * be resolved, the user ID will be the result. @@ -625,8 +626,13 @@ class Guild { * .then(user => console.log(`Banned ${user.username || user.id || user} from ${guild.name}`)) * .catch(console.error); */ - ban(user, deleteDays = 0) { - return this.client.rest.methods.banGuildMember(this, user, deleteDays); + ban(user, options = {}) { + if (typeof options === 'number') { + options = { reason: null, days: options }; + } else if (typeof options === 'string') { + options = { reason: options, days: 0 }; + } + return this.client.rest.methods.banGuildMember(this, user, options); } /** diff --git a/src/structures/GuildMember.js b/src/structures/GuildMember.js index 3785290ebf27..e9c415057880 100644 --- a/src/structures/GuildMember.js +++ b/src/structures/GuildMember.js @@ -472,23 +472,25 @@ class GuildMember { /** * Kick this member from the guild + * @param {string} [reason] Reason for kicking user * @returns {Promise} */ - kick() { - return this.client.rest.methods.kickGuildMember(this.guild, this); + kick(reason) { + return this.client.rest.methods.kickGuildMember(this.guild, this, reason); } /** * Ban this guild member - * @param {number} [deleteDays=0] The amount of days worth of messages from this member that should - * also be deleted. Between `0` and `7`. + * @param {Object} [options] Ban options. + * @param {number} [options.days=0] Number of days of messages to delete + * @param {string} [options.reason] Reason for banning * @returns {Promise} * @example * // ban a guild member * guildMember.ban(7); */ - ban(deleteDays = 0) { - return this.client.rest.methods.banGuildMember(this.guild, this, deleteDays); + ban(options) { + return this.guild.ban(this, options); } /** From 3b3c42d1f62e616fd6fdbdc19c930f1b5b716cf9 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Wed, 26 Apr 2017 20:04:27 -0500 Subject: [PATCH 27/40] Update GuildAuditLogs.js --- src/structures/GuildAuditLogs.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index f5b72ec09840..568b290e51ff 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -122,6 +122,12 @@ class GuildAuditLogsEntry { */ this.action = Object.keys(Actions).find(k => Actions[k] === data.action_type); + /** + * Reason of this entry + * @type {?string} + */ + this.reason = data.reason; + if (['USER', 'GUILD'].includes(root)) { /** * Target of this entry From 7ecd60b552ccee94b2efa1602274432ba79508ad Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Wed, 26 Apr 2017 21:06:47 -0500 Subject: [PATCH 28/40] Update GuildAuditLogs.js --- src/structures/GuildAuditLogs.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 568b290e51ff..8fe024b1f317 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -93,8 +93,7 @@ class GuildAuditLogs { Actions.EMOJI_UPDATE, ].includes(action)) return 'UPDATE'; - // Discord client source suggests I should return 'UPDATE' if nothing else matches - return 'UPDATE'; + return 'ALL'; } } From 5e354cc3492bcf65b5a226c30c7af9662a3dfc28 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Wed, 26 Apr 2017 21:19:51 -0500 Subject: [PATCH 29/40] support before/after for pagination --- src/client/rest/RESTMethods.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js index c848b0f827db..a207d15ee7c8 100644 --- a/src/client/rest/RESTMethods.js +++ b/src/client/rest/RESTMethods.js @@ -5,7 +5,7 @@ const Constants = require('../../util/Constants'); const Endpoints = Constants.Endpoints; const Collection = require('../../util/Collection'); const Snowflake = require('../../util/Snowflake'); -const Util = require('../../util/Util'); +const Util = require('../../util/Util');a const User = require('../../structures/User'); const GuildMember = require('../../structures/GuildMember'); @@ -671,10 +671,11 @@ class RESTMethods { .then(() => this.client.actions.GuildEmojiDelete.handle(emoji).data); } - getGuildAuditLogs(guild) { - return this.rest.makeRequest('get', Endpoints.Guild(guild).auditLogs, true).then(data => - new GuildAuditLogs(guild, data) - ); + getGuildAuditLogs(guild, options = {}) { + if (options.before && options.before instanceof GuildAuditLogs.Entry) options.before = options.before.id; + if (options.after && options.after instanceof GuildAuditLogs.Entry) options.after = options.after.id; + const url = `${Endpoints.Guild(guild).auditLogs}?${querystring.stringify(options)}`; + return this.rest.makeRequest('get', url, true).then(data => new GuildAuditLogs(guild, data)); } getWebhook(id, token) { From 3cf60e65eacb2dcbd62d4e1797a3acf4f0dce647 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Wed, 26 Apr 2017 21:21:08 -0500 Subject: [PATCH 30/40] Update Guild.js --- src/structures/Guild.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/structures/Guild.js b/src/structures/Guild.js index 4fc589f2c526..e55d380b41cf 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -376,10 +376,13 @@ class Guild { /** * Fetch audit logs for this guild + * @param {object} [options={}] Options for fetching audit logs + * @param {Snowflake|GuildAuditLogsEntry} [options.before] Pagination before + * @param {Snowflake|GuildAuditLogsEntry} [options.after] Pagination after * @returns {Promise} */ - fetchAuditLogs() { - return this.client.rest.methods.getGuildAuditLogs(this); + fetchAuditLogs(options) { + return this.client.rest.methods.getGuildAuditLogs(this, options); } /** From e16814c04173a88af2f3dade3e24106466b66b45 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Wed, 26 Apr 2017 21:21:46 -0500 Subject: [PATCH 31/40] Update GuildAuditLogs.js --- src/structures/GuildAuditLogs.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 8fe024b1f317..f6a6f9265f31 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -97,9 +97,6 @@ class GuildAuditLogs { } } -GuildAuditLogs.Actions = Actions; -GuildAuditLogs.Targets = Targets; - class GuildAuditLogsEntry { constructor(guild, data) { const root = GuildAuditLogs.rootTarget(data.action_type); @@ -157,4 +154,8 @@ class GuildAuditLogsEntry { } } +GuildAuditLogs.Actions = Actions; +GuildAuditLogs.Targets = Targets; +GuildAuditLogs.Entry = GuildAuditLogsEntry; + module.exports = GuildAuditLogs; From 22e800c44aa7a2476edcafdfdb4dedd56a0d47c1 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Wed, 26 Apr 2017 21:26:21 -0500 Subject: [PATCH 32/40] mfw using github web editor --- src/client/rest/RESTMethods.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js index a207d15ee7c8..24fdc2d03137 100644 --- a/src/client/rest/RESTMethods.js +++ b/src/client/rest/RESTMethods.js @@ -5,7 +5,7 @@ const Constants = require('../../util/Constants'); const Endpoints = Constants.Endpoints; const Collection = require('../../util/Collection'); const Snowflake = require('../../util/Snowflake'); -const Util = require('../../util/Util');a +const Util = require('../../util/Util'); const User = require('../../structures/User'); const GuildMember = require('../../structures/GuildMember'); From 87980b6b5442eca4412a0eb0bd2b98c8bfba26fe Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Wed, 26 Apr 2017 21:34:40 -0500 Subject: [PATCH 33/40] fix build --- src/structures/Guild.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/structures/Guild.js b/src/structures/Guild.js index e55d380b41cf..46ef25bf9990 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -376,7 +376,7 @@ class Guild { /** * Fetch audit logs for this guild - * @param {object} [options={}] Options for fetching audit logs + * @param {Object} [options={}] Options for fetching audit logs * @param {Snowflake|GuildAuditLogsEntry} [options.before] Pagination before * @param {Snowflake|GuildAuditLogsEntry} [options.after] Pagination after * @returns {Promise} From 095692b399a99354778d98e2c0d82802f6b1ce81 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Wed, 26 Apr 2017 22:32:32 -0500 Subject: [PATCH 34/40] Update Guild.js --- src/structures/Guild.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/structures/Guild.js b/src/structures/Guild.js index 46ef25bf9990..7ecd4533b441 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -377,8 +377,9 @@ class Guild { /** * Fetch audit logs for this guild * @param {Object} [options={}] Options for fetching audit logs - * @param {Snowflake|GuildAuditLogsEntry} [options.before] Pagination before - * @param {Snowflake|GuildAuditLogsEntry} [options.after] Pagination after + * @param {Snowflake|GuildAuditLogsEntry} [options.before] Limit to entries from before specified entry + * @param {Snowflake|GuildAuditLogsEntry} [options.after] Limit to entries from after specified entry + * @param {number} [options.limit] Limit number of entries * @returns {Promise} */ fetchAuditLogs(options) { From c70cae6b911dcd9c3ec84a16601d6d58531a93e7 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Wed, 26 Apr 2017 23:31:38 -0500 Subject: [PATCH 35/40] amazing cache fuckery shit evil --- src/structures/Guild.js | 4 ++- src/structures/GuildAuditLogs.js | 47 ++++++++++++++++++++------------ 2 files changed, 33 insertions(+), 18 deletions(-) diff --git a/src/structures/Guild.js b/src/structures/Guild.js index 46ef25bf9990..1d31266b0a58 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -382,7 +382,9 @@ class Guild { * @returns {Promise} */ fetchAuditLogs(options) { - return this.client.rest.methods.getGuildAuditLogs(this, options); + return this.client.rest.methods.getGuildAuditLogs(this, options).then(logs => + Promise.all(logs.entries.map(e => e.target)).then(() => logs) + ); } /** diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index f6a6f9265f31..7b844a6b9673 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -48,7 +48,7 @@ class GuildAuditLogs { for (const entry of data.audit_log_entries) this.entries.push(new GuildAuditLogsEntry(guild, entry)); } - static rootTarget(target) { + static targetType(target) { if (target < 10) return Targets.GUILD; if (target < 20) return Targets.CHANNEL; if (target < 30) return Targets.USER; @@ -59,7 +59,7 @@ class GuildAuditLogs { return null; } - static rootAction(action) { + static actionType(action) { if ([ Actions.CHANNEL_CREATE, Actions.CHANNEL_OVERWRITE_CREATE, @@ -99,18 +99,18 @@ class GuildAuditLogs { class GuildAuditLogsEntry { constructor(guild, data) { - const root = GuildAuditLogs.rootTarget(data.action_type); + const targetType = GuildAuditLogs.targetType(data.action_type); /** - * Root action type of this entry + * Target type of this entry * @type {string} */ - this.root = root; + this.targetType = targetType; /** * Action type of this entry * @type {string} */ - this.type = GuildAuditLogs.rootAction(data.action_type); + this.actionType = GuildAuditLogs.actionType(data.action_type); /** * Specific action type of this entry @@ -122,17 +122,7 @@ class GuildAuditLogsEntry { * Reason of this entry * @type {?string} */ - this.reason = data.reason; - - if (['USER', 'GUILD'].includes(root)) { - /** - * Target of this entry - * @type {Guild|User|Role|Invite|Webhook|Emoji} - */ - this.target = guild.client[`${root.toLowerCase()}s`].get(data.target_id); - } else { - this.target = guild[`${root.toLowerCase()}s`].get(data.target_id); - } + this.reason = data.reason || null; /** * User that executed this entry @@ -151,6 +141,29 @@ class GuildAuditLogsEntry { * @type {Snowflake} */ this.id = data.id; + + if (['USER', 'GUILD'].includes(targetType)) { + /** + * Target of this entry + * @type {?Guild|User|Role|Emoji|Promise|Promise} + */ + this.target = guild.client[`${targetType.toLowerCase()}s`].get(data.target_id); + } else if (targetType === 'WEBHOOK') { + this.target = guild.fetchWebhooks() + .then(hooks => { + this.target = hooks.find(h => h.id === data.target_id); + return this.target; + }); + } else if (targetType === 'INVITE') { + const change = this.changes.find(c => c.name === 'code'); + this.target = guild.fetchInvites() + .then(invites => { + this.target = invites.find(i => i.code === (change.new || change.old)); + return this.target; + }); + } else { + this.target = guild[`${targetType.toLowerCase()}s`].get(data.target_id); + } } } From 54e6ba7e3191ce0d4a1ec4c2c0b822bdb37b98c1 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Thu, 27 Apr 2017 10:35:21 -0500 Subject: [PATCH 36/40] cool stuff --- src/client/rest/RESTMethods.js | 17 +++++++++++++++-- src/structures/Guild.js | 6 +++--- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js index 24fdc2d03137..672c00abfe6a 100644 --- a/src/client/rest/RESTMethods.js +++ b/src/client/rest/RESTMethods.js @@ -674,8 +674,21 @@ class RESTMethods { getGuildAuditLogs(guild, options = {}) { if (options.before && options.before instanceof GuildAuditLogs.Entry) options.before = options.before.id; if (options.after && options.after instanceof GuildAuditLogs.Entry) options.after = options.after.id; - const url = `${Endpoints.Guild(guild).auditLogs}?${querystring.stringify(options)}`; - return this.rest.makeRequest('get', url, true).then(data => new GuildAuditLogs(guild, data)); + if (typeof options.type === 'string') options.type = GuildAuditLogs.Actions[options.type]; + + const queryString = (querystring.stringify({ + before: options.before, + after: options.after, + limit: options.limit, + user_id: this.client.resolver.resolveUserID(options.user), + action_type: options.type, + }).match(/[^=&?]+=[^=&?]+/g) || []).join('&'); + + return this.rest.makeRequest('get', `${Endpoints.Guild(guild).auditLogs}?${queryString}`, true) + .then(data => { + const logs = new GuildAuditLogs(guild, data); + return Promise.all(logs.entries.map(e => e.target)).then(() => logs); + }); } getWebhook(id, token) { diff --git a/src/structures/Guild.js b/src/structures/Guild.js index 128e64bf9a9e..9990ed6a3121 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -380,12 +380,12 @@ class Guild { * @param {Snowflake|GuildAuditLogsEntry} [options.before] Limit to entries from before specified entry * @param {Snowflake|GuildAuditLogsEntry} [options.after] Limit to entries from after specified entry * @param {number} [options.limit] Limit number of entries + * @param {UserResolvable} [options.user] Only show entries involving this user + * @param {string|number} [options.type] Only show entries involving this action type * @returns {Promise} */ fetchAuditLogs(options) { - return this.client.rest.methods.getGuildAuditLogs(this, options).then(logs => - Promise.all(logs.entries.map(e => e.target)).then(() => logs) - ); + return this.client.rest.methods.getGuildAuditLogs(this, options); } /** From 14904365115968a4a08a9673ffe06dd2d2f7873f Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Thu, 27 Apr 2017 21:28:58 -0500 Subject: [PATCH 37/40] make building audit logs nicer --- src/client/rest/RESTMethods.js | 5 +---- src/structures/GuildAuditLogs.js | 7 +++++++ 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js index 672c00abfe6a..2806524b3444 100644 --- a/src/client/rest/RESTMethods.js +++ b/src/client/rest/RESTMethods.js @@ -685,10 +685,7 @@ class RESTMethods { }).match(/[^=&?]+=[^=&?]+/g) || []).join('&'); return this.rest.makeRequest('get', `${Endpoints.Guild(guild).auditLogs}?${queryString}`, true) - .then(data => { - const logs = new GuildAuditLogs(guild, data); - return Promise.all(logs.entries.map(e => e.target)).then(() => logs); - }); + .then(data => GuildAuditLogs.build(guild, data)); } getWebhook(id, token) { diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 7b844a6b9673..91eb3d0f69b1 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -48,6 +48,13 @@ class GuildAuditLogs { for (const entry of data.audit_log_entries) this.entries.push(new GuildAuditLogsEntry(guild, entry)); } + static build(...args) { + return new Promise(resolve => { + const logs = new GuildAuditLogs(...args); + Promise.all(logs.entries.map(e => e.target)).then(() => resolve(logs)); + }); + } + static targetType(target) { if (target < 10) return Targets.GUILD; if (target < 20) return Targets.CHANNEL; From cdcc0bf76bd91be189a09d2298e0b56b771e8c36 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Fri, 28 Apr 2017 10:26:55 -0500 Subject: [PATCH 38/40] ban endpoint stuff --- src/client/rest/RESTMethods.js | 17 +++++++++-------- src/structures/Guild.js | 8 +++++++- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js index 2806524b3444..d0e6fbc3f3c4 100644 --- a/src/client/rest/RESTMethods.js +++ b/src/client/rest/RESTMethods.js @@ -573,14 +573,15 @@ class RESTMethods { } getGuildBans(guild) { - return this.rest.makeRequest('get', Endpoints.Guild(guild).bans, true).then(banItems => { - const bannedUsers = new Collection(); - for (const banItem of banItems) { - const user = this.client.dataManager.newUser(banItem.user); - bannedUsers.set(user.id, user); - } - return bannedUsers; - }); + return this.rest.makeRequest('get', Endpoints.Guild(guild).bans, true).then(bans => + bans.reduce((collection, ban) => { + collection.set(ban.user.id, { + reason: ban.reason, + user: this.client.dataManager.newUser(ban.user), + }); + return collection; + }, new Collection()) + ); } updateGuildRole(role, _data) { diff --git a/src/structures/Guild.js b/src/structures/Guild.js index 9990ed6a3121..68f44bbdee22 100644 --- a/src/structures/Guild.js +++ b/src/structures/Guild.js @@ -347,7 +347,13 @@ class Guild { * @returns {Promise>} */ fetchBans() { - return this.client.rest.methods.getGuildBans(this); + return this.client.rest.methods.getGuildBans(this) + // This entire re-mapping can be removed in the next major release + .then(bans => { + const users = new Collection(); + for (const ban of bans.values()) users.set(ban.user.id, ban.user); + return users; + }); } /** From 110d4063c3d5a6d074b28721c1711a989f09bae8 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Fri, 28 Apr 2017 10:32:50 -0500 Subject: [PATCH 39/40] dox --- src/structures/GuildAuditLogs.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 91eb3d0f69b1..d83b44fb6618 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -48,6 +48,10 @@ class GuildAuditLogs { for (const entry of data.audit_log_entries) this.entries.push(new GuildAuditLogsEntry(guild, entry)); } + /** + * Handles possible promises for entry targets + * @returns {GuildAuditLogs} + */ static build(...args) { return new Promise(resolve => { const logs = new GuildAuditLogs(...args); @@ -55,6 +59,11 @@ class GuildAuditLogs { }); } + /** + * Find target type from entry action + * @param {number} target Action target + * @returns {?string} + */ static targetType(target) { if (target < 10) return Targets.GUILD; if (target < 20) return Targets.CHANNEL; @@ -66,6 +75,12 @@ class GuildAuditLogs { return null; } + + /** + * Find action type from entry action + * @param {string} action Action target + * @returns {string} + */ static actionType(action) { if ([ Actions.CHANNEL_CREATE, From caf9514e07773950c5be9ab7f10c25fb176358f7 Mon Sep 17 00:00:00 2001 From: Gus Caplan Date: Sat, 29 Apr 2017 12:23:19 -0500 Subject: [PATCH 40/40] <.< --- src/client/rest/RESTMethods.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/client/rest/RESTMethods.js b/src/client/rest/RESTMethods.js index 2379ed224132..69d29ecbad12 100644 --- a/src/client/rest/RESTMethods.js +++ b/src/client/rest/RESTMethods.js @@ -389,7 +389,7 @@ class RESTMethods { kickGuildMember(guild, member, reason) { const url = `${Endpoints.Guild(guild).Member(member)}?reason=${reason}`; - return this.rest.makeRequest('delete', url, true, { reason }).then(() => + return this.rest.makeRequest('delete', url, true).then(() => this.client.actions.GuildMemberRemove.handle({ guild_id: guild.id, user: member.user,