feat(GuildAuditLogs): handle new event types (#3760)

* Define new AuditLogActions

* Backport constructor rewrite

* Typings

* fix(GuildAuditLogEntry): switch on correct property, coerce to numbers, simplify extra for deleted entities

Co-authored-by: SpaceEEC <spaceeec@yahoo.com>
This commit is contained in:
Ryan Munro
2020-02-13 04:42:57 +11:00
committed by GitHub
parent 83bc6e0779
commit dbdb49ee1c
2 changed files with 125 additions and 23 deletions

View File

@@ -1,6 +1,7 @@
const Collection = require('../util/Collection'); const Collection = require('../util/Collection');
const Snowflake = require('../util/Snowflake'); const Snowflake = require('../util/Snowflake');
const Webhook = require('./Webhook'); const Webhook = require('./Webhook');
const Integration = require('./Integration');
const Invite = require('./Invite'); const Invite = require('./Invite');
/** /**
@@ -13,6 +14,7 @@ const Invite = require('./Invite');
* * WEBHOOK * * WEBHOOK
* * EMOJI * * EMOJI
* * MESSAGE * * MESSAGE
* * INTEGRATION
* @typedef {string} AuditLogTargetType * @typedef {string} AuditLogTargetType
*/ */
@@ -31,6 +33,8 @@ const Targets = {
WEBHOOK: 'WEBHOOK', WEBHOOK: 'WEBHOOK',
EMOJI: 'EMOJI', EMOJI: 'EMOJI',
MESSAGE: 'MESSAGE', MESSAGE: 'MESSAGE',
INTEGRATION: 'INTEGRATION',
UNKNOWN: 'UNKNOWN',
}; };
/** /**
@@ -49,6 +53,9 @@ const Targets = {
* * MEMBER_BAN_REMOVE: 23 * * MEMBER_BAN_REMOVE: 23
* * MEMBER_UPDATE: 24 * * MEMBER_UPDATE: 24
* * MEMBER_ROLE_UPDATE: 25 * * MEMBER_ROLE_UPDATE: 25
* * MEMBER_MOVE: 26
* * MEMBER_DISCONNECT: 27
* * BOT_ADD: 28,
* * ROLE_CREATE: 30 * * ROLE_CREATE: 30
* * ROLE_UPDATE: 31 * * ROLE_UPDATE: 31
* * ROLE_DELETE: 32 * * ROLE_DELETE: 32
@@ -62,6 +69,12 @@ const Targets = {
* * EMOJI_UPDATE: 61 * * EMOJI_UPDATE: 61
* * EMOJI_DELETE: 62 * * EMOJI_DELETE: 62
* * MESSAGE_DELETE: 72 * * MESSAGE_DELETE: 72
* * MESSAGE_BULK_DELETE: 73
* * MESSAGE_PIN: 74
* * MESSAGE_UNPIN: 75
* * INTEGRATION_CREATE: 80
* * INTEGRATION_UPDATE: 81
* * INTEGRATION_DELETE: 82
* @typedef {?number|string} AuditLogAction * @typedef {?number|string} AuditLogAction
*/ */
@@ -85,6 +98,9 @@ const Actions = {
MEMBER_BAN_REMOVE: 23, MEMBER_BAN_REMOVE: 23,
MEMBER_UPDATE: 24, MEMBER_UPDATE: 24,
MEMBER_ROLE_UPDATE: 25, MEMBER_ROLE_UPDATE: 25,
MEMBER_MOVE: 26,
MEMBER_DISCONNECT: 27,
BOT_ADD: 28,
ROLE_CREATE: 30, ROLE_CREATE: 30,
ROLE_UPDATE: 31, ROLE_UPDATE: 31,
ROLE_DELETE: 32, ROLE_DELETE: 32,
@@ -98,6 +114,12 @@ const Actions = {
EMOJI_UPDATE: 61, EMOJI_UPDATE: 61,
EMOJI_DELETE: 62, EMOJI_DELETE: 62,
MESSAGE_DELETE: 72, MESSAGE_DELETE: 72,
MESSAGE_BULK_DELETE: 73,
MESSAGE_PIN: 74,
MESSAGE_UNPIN: 75,
INTEGRATION_CREATE: 80,
INTEGRATION_UPDATE: 81,
INTEGRATION_DELETE: 82,
}; };
@@ -120,6 +142,18 @@ class GuildAuditLogs {
} }
} }
/**
* Cached integrations
* @type {Collection<Snowflake, Integration>}
* @private
*/
this.integrations = new Collection();
if (data.integrations) {
for (const integration of data.integrations) {
this.integrations.set(integration.id, new Integration(guild.client, integration, guild));
}
}
/** /**
* The entries for this guild's audit logs * The entries for this guild's audit logs
* @type {Collection<Snowflake, GuildAuditLogsEntry>} * @type {Collection<Snowflake, GuildAuditLogsEntry>}
@@ -148,9 +182,10 @@ class GuildAuditLogs {
* * An emoji * * An emoji
* * An invite * * An invite
* * A webhook * * A webhook
* * An integration
* * An object with an id key if target was deleted * * An object with an id key if target was deleted
* * An object where the keys represent either the new value or the old value * * An object where the keys represent either the new value or the old value
* @typedef {?Object|Guild|User|Role|Emoji|Invite|Webhook} AuditLogEntryTarget * @typedef {?Object|Guild|User|Role|Emoji|Invite|Webhook|Integration} AuditLogEntryTarget
*/ */
/** /**
@@ -167,6 +202,7 @@ class GuildAuditLogs {
if (target < 60) return Targets.WEBHOOK; if (target < 60) return Targets.WEBHOOK;
if (target < 70) return Targets.EMOJI; if (target < 70) return Targets.EMOJI;
if (target < 80) return Targets.MESSAGE; if (target < 80) return Targets.MESSAGE;
if (target < 90) return Targets.INTEGRATION;
return null; return null;
} }
@@ -190,10 +226,13 @@ class GuildAuditLogs {
Actions.CHANNEL_CREATE, Actions.CHANNEL_CREATE,
Actions.CHANNEL_OVERWRITE_CREATE, Actions.CHANNEL_OVERWRITE_CREATE,
Actions.MEMBER_BAN_REMOVE, Actions.MEMBER_BAN_REMOVE,
Actions.BOT_ADD,
Actions.ROLE_CREATE, Actions.ROLE_CREATE,
Actions.INVITE_CREATE, Actions.INVITE_CREATE,
Actions.WEBHOOK_CREATE, Actions.WEBHOOK_CREATE,
Actions.EMOJI_CREATE, Actions.EMOJI_CREATE,
Actions.MESSAGE_PIN,
Actions.INTEGRATION_CREATE,
].includes(action)) return 'CREATE'; ].includes(action)) return 'CREATE';
if ([ if ([
@@ -202,11 +241,15 @@ class GuildAuditLogs {
Actions.MEMBER_KICK, Actions.MEMBER_KICK,
Actions.MEMBER_PRUNE, Actions.MEMBER_PRUNE,
Actions.MEMBER_BAN_ADD, Actions.MEMBER_BAN_ADD,
Actions.MEMBER_DISCONNECT,
Actions.ROLE_DELETE, Actions.ROLE_DELETE,
Actions.INVITE_DELETE, Actions.INVITE_DELETE,
Actions.WEBHOOK_DELETE, Actions.WEBHOOK_DELETE,
Actions.EMOJI_DELETE, Actions.EMOJI_DELETE,
Actions.MESSAGE_DELETE, Actions.MESSAGE_DELETE,
Actions.MESSAGE_BULK_DELETE,
Actions.MESSAGE_UNPIN,
Actions.INTEGRATION_DELETE,
].includes(action)) return 'DELETE'; ].includes(action)) return 'DELETE';
if ([ if ([
@@ -215,10 +258,12 @@ class GuildAuditLogs {
Actions.CHANNEL_OVERWRITE_UPDATE, Actions.CHANNEL_OVERWRITE_UPDATE,
Actions.MEMBER_UPDATE, Actions.MEMBER_UPDATE,
Actions.MEMBER_ROLE_UPDATE, Actions.MEMBER_ROLE_UPDATE,
Actions.MEMBER_MOVE,
Actions.ROLE_UPDATE, Actions.ROLE_UPDATE,
Actions.INVITE_UPDATE, Actions.INVITE_UPDATE,
Actions.WEBHOOK_UPDATE, Actions.WEBHOOK_UPDATE,
Actions.EMOJI_UPDATE, Actions.EMOJI_UPDATE,
Actions.INTEGRATION_UPDATE,
].includes(action)) return 'UPDATE'; ].includes(action)) return 'UPDATE';
return 'ALL'; return 'ALL';
@@ -229,6 +274,7 @@ class GuildAuditLogs {
* Audit logs entry. * Audit logs entry.
*/ */
class GuildAuditLogsEntry { class GuildAuditLogsEntry {
// eslint-disable-next-line complexity
constructor(logs, guild, data) { constructor(logs, guild, data) {
const targetType = GuildAuditLogs.targetType(data.action_type); const targetType = GuildAuditLogs.targetType(data.action_type);
/** /**
@@ -286,39 +332,74 @@ class GuildAuditLogsEntry {
* @type {?Object|Role|GuildMember} * @type {?Object|Role|GuildMember}
*/ */
this.extra = null; this.extra = null;
if (data.options) { switch (data.action_type) {
if (data.action_type === Actions.MEMBER_PRUNE) { case Actions.MEMBER_PRUNE:
this.extra = { this.extra = {
removed: data.options.members_removed, removed: Number(data.options.members_removed),
days: data.options.delete_member_days, days: Number(data.options.delete_member_days),
}; };
} else if (data.action_type === Actions.MESSAGE_DELETE) { break;
case Actions.MEMBER_MOVE:
case Actions.MESSAGE_DELETE:
case Actions.MESSAGE_BULK_DELETE:
this.extra = { this.extra = {
count: data.options.count, channel: guild.channels.get(data.options.channel_id) || { id: data.options.channel_id },
channel: guild.channels.get(data.options.channel_id), count: Number(data.options.count),
}; };
} else { break;
case Actions.MESSAGE_PIN:
case Actions.MESSAGE_UNPIN:
this.extra = {
channel: guild.client.channels.get(data.options.channel_id) || { id: data.options.channel_id },
messageID: data.options.message_id,
};
break;
case Actions.MEMBER_DISCONNECT:
this.extra = {
count: Number(data.options.count),
};
break;
case Actions.CHANNEL_OVERWRITE_CREATE:
case Actions.CHANNEL_OVERWRITE_UPDATE:
case Actions.CHANNEL_OVERWRITE_DELETE:
switch (data.options.type) { switch (data.options.type) {
case 'member': case 'member':
this.extra = guild.members.get(data.options.id); this.extra = guild.members.get(data.options.id) ||
if (!this.extra) this.extra = { id: data.options.id }; { id: data.options.id, type: 'member' };
break; break;
case 'role': case 'role':
this.extra = guild.roles.get(data.options.id); this.extra = guild.roles.get(data.options.id) ||
if (!this.extra) this.extra = { id: data.options.id, name: data.options.role_name }; { id: data.options.id, name: data.options.role_name, type: 'role' };
break; break;
default: default:
break; break;
} }
} break;
default:
break;
} }
if ([Targets.USER, Targets.GUILD].includes(targetType)) { /**
/** * The target of this entry
* The target of this entry * @type {AuditLogEntryTarget}
* @type {AuditLogEntryTarget} */
*/ this.target = null;
this.target = guild.client[`${targetType.toLowerCase()}s`].get(data.target_id); if (targetType === Targets.UNKNOWN) {
this.changes.reduce((o, c) => {
o[c.key] = c.new || c.old;
return o;
}, {});
this.target.id = data.target_id;
// MEMBER_DISCONNECT and similar types do not provide a target_id.
} else if (targetType === Targets.USER && data.target_id) {
this.target = guild.client.users.get(data.target_id);
} else if (targetType === Targets.GUILD) {
this.target = guild.client.guilds.get(data.target_id);
} else if (targetType === Targets.WEBHOOK) { } else if (targetType === Targets.WEBHOOK) {
this.target = logs.webhooks.get(data.target_id) || this.target = logs.webhooks.get(data.target_id) ||
new Webhook(guild.client, new Webhook(guild.client,
@@ -340,8 +421,17 @@ class GuildAuditLogsEntry {
changes.channel = { id: changes.channel_id }; changes.channel = { id: changes.channel_id };
this.target = new Invite(guild.client, changes); this.target = new Invite(guild.client, changes);
} else if (targetType === Targets.MESSAGE) { } else if (targetType === Targets.MESSAGE) {
this.target = guild.client.users.get(data.target_id); // Discord sends a channel id for the MESSAGE_BULK_DELETE action type.
} else { this.target = data.action_type === Actions.MESSAGE_BULK_DELETE ?
guild.channels.get(data.target_id) || { id: data.target_id } :
guild.client.users.get(data.target_id);
} else if (targetType === Targets.INTEGRATION) {
this.target = logs.integrations.get(data.target_id) ||
new Integration(guild.client, this.changes.reduce((o, c) => {
o[c.key] = c.new || c.old;
return o;
}, { id: data.target_id }), guild);
} else if (data.target_id) {
this.target = guild[`${targetType.toLowerCase()}s`].get(data.target_id) || { id: data.target_id }; this.target = guild[`${targetType.toLowerCase()}s`].get(data.target_id) || { id: data.target_id };
} }
} }

14
typings/index.d.ts vendored
View File

@@ -601,6 +601,7 @@ declare module 'discord.js' {
export class GuildAuditLogs { export class GuildAuditLogs {
constructor(guild: Guild, data: object); constructor(guild: Guild, data: object);
private webhooks: Collection<Snowflake, Webhook>; private webhooks: Collection<Snowflake, Webhook>;
private integrations: Collection<Snowflake, Integration>;
public entries: Collection<Snowflake, GuildAuditLogsEntry>; public entries: Collection<Snowflake, GuildAuditLogsEntry>;
@@ -623,7 +624,7 @@ declare module 'discord.js' {
public extra: object | Role | GuildMember; public extra: object | Role | GuildMember;
public id: Snowflake; public id: Snowflake;
public reason: string; public reason: string;
public target: Guild | User | Role | Emoji | Invite | Webhook; public target: Guild | User | Role | Emoji | Invite | Webhook | Integration | null;
public targetType: GuildAuditLogsTarget; public targetType: GuildAuditLogsTarget;
} }
@@ -1868,6 +1869,9 @@ declare module 'discord.js' {
MEMBER_BAN_REMOVE?: number; MEMBER_BAN_REMOVE?: number;
MEMBER_UPDATE?: number; MEMBER_UPDATE?: number;
MEMBER_ROLE_UPDATE?: number; MEMBER_ROLE_UPDATE?: number;
MEMBER_MOVE?: number;
MEMBER_DISCONNECT?: number;
BOT_ADD?: number;
ROLE_CREATE?: number; ROLE_CREATE?: number;
ROLE_UPDATE?: number; ROLE_UPDATE?: number;
ROLE_DELETE?: number; ROLE_DELETE?: number;
@@ -1881,6 +1885,12 @@ declare module 'discord.js' {
EMOJI_UPDATE?: number; EMOJI_UPDATE?: number;
EMOJI_DELETE?: number; EMOJI_DELETE?: number;
MESSAGE_DELETE?: number; MESSAGE_DELETE?: number;
MESSAGE_BULK_DELETE?: number;
MESSAGE_PIN?: number;
MESSAGE_UNPIN?: number;
INTEGRATION_CREATE?: number;
INTEGRATION_UPDATE?: number;
INTEGRATION_DELETE?: number;
}; };
type GuildAuditLogsActionType = 'CREATE' type GuildAuditLogsActionType = 'CREATE'
@@ -1908,6 +1918,8 @@ declare module 'discord.js' {
WEBHOOK?: string; WEBHOOK?: string;
EMOJI?: string; EMOJI?: string;
MESSAGE?: string; MESSAGE?: string;
INTEGRATION?: string;
UNKNOWN?: string;
}; };
type GuildChannelMessageNotifications = MessageNotifications type GuildChannelMessageNotifications = MessageNotifications