feat(Client): guildAuditLogEntryCreate event (#9058)

* feat(Client): `guildAuditLogEntryCreate` event

* feat: add `targetId` and `executorId`

* types: `ApplicationCommand` fix

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
Almeida
2023-02-17 20:11:52 +00:00
committed by GitHub
parent 1ba1f238f0
commit 9439107a1d
11 changed files with 71 additions and 12 deletions

View File

@@ -120,7 +120,7 @@ body:
- No Intents - No Intents
- Guilds - Guilds
- GuildMembers - GuildMembers
- GuildBans - GuildModeration
- GuildEmojisAndStickers - GuildEmojisAndStickers
- GuildIntegrations - GuildIntegrations
- GuildWebhooks - GuildWebhooks

View File

@@ -12,6 +12,7 @@ class ActionsManager {
this.register(require('./ChannelCreate')); this.register(require('./ChannelCreate'));
this.register(require('./ChannelDelete')); this.register(require('./ChannelDelete'));
this.register(require('./ChannelUpdate')); this.register(require('./ChannelUpdate'));
this.register(require('./GuildAuditLogEntryCreate'));
this.register(require('./GuildBanAdd')); this.register(require('./GuildBanAdd'));
this.register(require('./GuildBanRemove')); this.register(require('./GuildBanRemove'));
this.register(require('./GuildChannelsPositionUpdate')); this.register(require('./GuildChannelsPositionUpdate'));

View File

@@ -0,0 +1,29 @@
'use strict';
const Action = require('./Action');
const GuildAuditLogsEntry = require('../../structures/GuildAuditLogsEntry');
const Events = require('../../util/Events');
class GuildAuditLogEntryCreateAction extends Action {
handle(data) {
const client = this.client;
const guild = client.guilds.cache.get(data.guild_id);
let auditLogEntry;
if (guild) {
auditLogEntry = new GuildAuditLogsEntry(guild, data);
/**
* Emitted whenever a guild audit log entry is created.
* @event Client#guildAuditLogEntryCreate
* @param {GuildAuditLogsEntry} auditLogEntry The entry that was created
* @param {Guild} guild The guild where the entry was created
*/
client.emit(Events.GuildAuditLogEntryCreate, auditLogEntry, guild);
}
return { auditLogEntry };
}
}
module.exports = GuildAuditLogEntryCreateAction;

View File

@@ -0,0 +1,5 @@
'use strict';
module.exports = (client, packet) => {
client.actions.GuildAuditLogEntryCreate.handle(packet.d);
};

View File

@@ -10,6 +10,7 @@ const handlers = Object.fromEntries([
['CHANNEL_DELETE', require('./CHANNEL_DELETE')], ['CHANNEL_DELETE', require('./CHANNEL_DELETE')],
['CHANNEL_PINS_UPDATE', require('./CHANNEL_PINS_UPDATE')], ['CHANNEL_PINS_UPDATE', require('./CHANNEL_PINS_UPDATE')],
['CHANNEL_UPDATE', require('./CHANNEL_UPDATE')], ['CHANNEL_UPDATE', require('./CHANNEL_UPDATE')],
['GUILD_AUDIT_LOG_ENTRY_CREATE', require('./GUILD_AUDIT_LOG_ENTRY_CREATE')],
['GUILD_BAN_ADD', require('./GUILD_BAN_ADD')], ['GUILD_BAN_ADD', require('./GUILD_BAN_ADD')],
['GUILD_BAN_REMOVE', require('./GUILD_BAN_REMOVE')], ['GUILD_BAN_REMOVE', require('./GUILD_BAN_REMOVE')],
['GUILD_CREATE', require('./GUILD_CREATE')], ['GUILD_CREATE', require('./GUILD_CREATE')],

View File

@@ -12,7 +12,7 @@ const { GuildMember } = require('../structures/GuildMember');
let deprecationEmittedForDeleteMessageDays = false; let deprecationEmittedForDeleteMessageDays = false;
/** /**
* Manages API methods for GuildBans and stores their cache. * Manages API methods for guild bans and stores their cache.
* @extends {CachedManager} * @extends {CachedManager}
*/ */
class GuildBanManager extends CachedManager { class GuildBanManager extends CachedManager {

View File

@@ -78,7 +78,7 @@ class GuildAuditLogs {
*/ */
this.entries = new Collection(); this.entries = new Collection();
for (const item of data.audit_log_entries) { for (const item of data.audit_log_entries) {
const entry = new GuildAuditLogsEntry(this, guild, item); const entry = new GuildAuditLogsEntry(guild, item, this);
this.entries.set(entry.id, entry); this.entries.set(entry.id, entry);
} }
} }

View File

@@ -94,7 +94,7 @@ class GuildAuditLogsEntry {
*/ */
static Targets = Targets; static Targets = Targets;
constructor(logs, guild, data) { constructor(guild, data, logs) {
/** /**
* The target type of this entry * The target type of this entry
* @type {AuditLogTargetType} * @type {AuditLogTargetType}
@@ -120,6 +120,12 @@ class GuildAuditLogsEntry {
*/ */
this.reason = data.reason ?? null; this.reason = data.reason ?? null;
/**
* The id of the user that executed this entry
* @type {?Snowflake}
*/
this.executorId = data.user_id;
/** /**
* The user that executed this entry * The user that executed this entry
* @type {?User} * @type {?User}
@@ -127,7 +133,7 @@ class GuildAuditLogsEntry {
this.executor = data.user_id this.executor = data.user_id
? guild.client.options.partials.includes(Partials.User) ? guild.client.options.partials.includes(Partials.User)
? guild.client.users._add({ id: data.user_id }) ? guild.client.users._add({ id: data.user_id })
: guild.client.users.cache.get(data.user_id) : guild.client.users.cache.get(data.user_id) ?? null
: null; : null;
/** /**
@@ -239,6 +245,12 @@ class GuildAuditLogsEntry {
break; break;
} }
/**
* The id of the target of this entry
* @type {?Snowflake}
*/
this.targetId = data.target_id;
/** /**
* The target of this entry * The target of this entry
* @type {?AuditLogEntryTarget} * @type {?AuditLogEntryTarget}
@@ -254,12 +266,12 @@ class GuildAuditLogsEntry {
} else if (targetType === Targets.User && data.target_id) { } else if (targetType === Targets.User && data.target_id) {
this.target = guild.client.options.partials.includes(Partials.User) this.target = guild.client.options.partials.includes(Partials.User)
? guild.client.users._add({ id: data.target_id }) ? guild.client.users._add({ id: data.target_id })
: guild.client.users.cache.get(data.target_id); : guild.client.users.cache.get(data.target_id) ?? null;
} else if (targetType === Targets.Guild) { } else if (targetType === Targets.Guild) {
this.target = guild.client.guilds.cache.get(data.target_id); this.target = guild.client.guilds.cache.get(data.target_id);
} else if (targetType === Targets.Webhook) { } else if (targetType === Targets.Webhook) {
this.target = this.target =
logs.webhooks.get(data.target_id) ?? logs?.webhooks.get(data.target_id) ??
new Webhook( new Webhook(
guild.client, guild.client,
this.changes.reduce( this.changes.reduce(
@@ -294,10 +306,10 @@ class GuildAuditLogsEntry {
this.target = this.target =
data.action_type === AuditLogEvent.MessageBulkDelete data.action_type === AuditLogEvent.MessageBulkDelete
? guild.channels.cache.get(data.target_id) ?? { id: data.target_id } ? guild.channels.cache.get(data.target_id) ?? { id: data.target_id }
: guild.client.users.cache.get(data.target_id); : guild.client.users.cache.get(data.target_id) ?? null;
} else if (targetType === Targets.Integration) { } else if (targetType === Targets.Integration) {
this.target = this.target =
logs.integrations.get(data.target_id) ?? logs?.integrations.get(data.target_id) ??
new Integration( new Integration(
guild.client, guild.client,
this.changes.reduce( this.changes.reduce(
@@ -363,7 +375,7 @@ class GuildAuditLogsEntry {
), ),
); );
} else if (targetType === Targets.ApplicationCommand) { } else if (targetType === Targets.ApplicationCommand) {
this.target = logs.applicationCommands.get(data.target_id) ?? { id: data.target_id }; this.target = logs?.applicationCommands.get(data.target_id) ?? { id: data.target_id };
} else if (targetType === Targets.AutoModeration) { } else if (targetType === Targets.AutoModeration) {
this.target = this.target =
guild.autoModerationRules.cache.get(data.target_id) ?? guild.autoModerationRules.cache.get(data.target_id) ??

View File

@@ -11,6 +11,7 @@
* @property {string} ClientReady ready * @property {string} ClientReady ready
* @property {string} Debug debug * @property {string} Debug debug
* @property {string} Error error * @property {string} Error error
* @property {string} GuildAuditLogEntryCreate guildAuditLogEntryCreate
* @property {string} GuildBanAdd guildBanAdd * @property {string} GuildBanAdd guildBanAdd
* @property {string} GuildBanRemove guildBanRemove * @property {string} GuildBanRemove guildBanRemove
* @property {string} GuildCreate guildCreate * @property {string} GuildCreate guildCreate
@@ -91,6 +92,7 @@ module.exports = {
ClientReady: 'ready', ClientReady: 'ready',
Debug: 'debug', Debug: 'debug',
Error: 'error', Error: 'error',
GuildAuditLogEntryCreate: 'guildAuditLogEntryCreate',
GuildBanAdd: 'guildBanAdd', GuildBanAdd: 'guildBanAdd',
GuildBanRemove: 'guildBanRemove', GuildBanRemove: 'guildBanRemove',
GuildCreate: 'guildCreate', GuildCreate: 'guildCreate',

View File

@@ -1387,19 +1387,21 @@ export class GuildAuditLogsEntry<
: GuildAuditLogsTargetType, : GuildAuditLogsTargetType,
TResolvedType = TAction extends null ? AuditLogEvent : TAction, TResolvedType = TAction extends null ? AuditLogEvent : TAction,
> { > {
private constructor(logs: GuildAuditLogs, guild: Guild, data: RawGuildAuditLogEntryData); private constructor(guild: Guild, data: RawGuildAuditLogEntryData, logs?: GuildAuditLogs);
public static Targets: GuildAuditLogsTargets; public static Targets: GuildAuditLogsTargets;
public action: TResolvedType; public action: TResolvedType;
public actionType: TActionType; public actionType: TActionType;
public changes: AuditLogChange[]; public changes: AuditLogChange[];
public get createdAt(): Date; public get createdAt(): Date;
public get createdTimestamp(): number; public get createdTimestamp(): number;
public executorId: Snowflake | null;
public executor: User | null; public executor: User | null;
public extra: TResolvedType extends keyof GuildAuditLogsEntryExtraField public extra: TResolvedType extends keyof GuildAuditLogsEntryExtraField
? GuildAuditLogsEntryExtraField[TResolvedType] ? GuildAuditLogsEntryExtraField[TResolvedType]
: null; : null;
public id: Snowflake; public id: Snowflake;
public reason: string | null; public reason: string | null;
public targetId: Snowflake | null;
public target: TTargetType extends keyof GuildAuditLogsEntryTargetField<TActionType> public target: TTargetType extends keyof GuildAuditLogsEntryTargetField<TActionType>
? GuildAuditLogsEntryTargetField<TActionType>[TTargetType] ? GuildAuditLogsEntryTargetField<TActionType>[TTargetType]
: Role | GuildEmoji | { id: Snowflake } | null; : Role | GuildEmoji | { id: Snowflake } | null;
@@ -4691,6 +4693,7 @@ export interface ClientEvents {
emojiDelete: [emoji: GuildEmoji]; emojiDelete: [emoji: GuildEmoji];
emojiUpdate: [oldEmoji: GuildEmoji, newEmoji: GuildEmoji]; emojiUpdate: [oldEmoji: GuildEmoji, newEmoji: GuildEmoji];
error: [error: Error]; error: [error: Error];
guildAuditLogEntryCreate: [auditLogEntry: GuildAuditLogsEntry, guild: Guild];
guildBanAdd: [ban: GuildBan]; guildBanAdd: [ban: GuildBan];
guildBanRemove: [ban: GuildBan]; guildBanRemove: [ban: GuildBan];
guildCreate: [guild: Guild]; guildCreate: [guild: Guild];
@@ -4897,6 +4900,7 @@ export enum Events {
AutoModerationRuleDelete = 'autoModerationRuleDelete', AutoModerationRuleDelete = 'autoModerationRuleDelete',
AutoModerationRuleUpdate = 'autoModerationRuleUpdate', AutoModerationRuleUpdate = 'autoModerationRuleUpdate',
ClientReady = 'ready', ClientReady = 'ready',
GuildAuditLogEntryCreate = 'guildAuditLogEntryCreate',
GuildCreate = 'guildCreate', GuildCreate = 'guildCreate',
GuildDelete = 'guildDelete', GuildDelete = 'guildDelete',
GuildUpdate = 'guildUpdate', GuildUpdate = 'guildUpdate',
@@ -5307,7 +5311,7 @@ export interface GuildAuditLogsEntryTargetField<TActionType extends GuildAuditLo
StageInstance: StageInstance; StageInstance: StageInstance;
Sticker: Sticker; Sticker: Sticker;
GuildScheduledEvent: GuildScheduledEvent; GuildScheduledEvent: GuildScheduledEvent;
ApplicationCommand: ApplicationCommand; ApplicationCommand: ApplicationCommand | { id: Snowflake };
AutoModerationRule: AutoModerationRule; AutoModerationRule: AutoModerationRule;
} }

View File

@@ -2138,3 +2138,8 @@ if (anySelectMenu.isStringSelectMenu()) {
} else if (anySelectMenu.isMentionableSelectMenu()) { } else if (anySelectMenu.isMentionableSelectMenu()) {
expectType<MentionableSelectMenuInteraction>(anySelectMenu); expectType<MentionableSelectMenuInteraction>(anySelectMenu);
} }
client.on('guildAuditLogEntryCreate', (auditLogEntry, guild) => {
expectType<GuildAuditLogsEntry>(auditLogEntry);
expectType<Guild>(guild);
});