diff --git a/src/client/actions/ActionsManager.js b/src/client/actions/ActionsManager.js index 0f3f531..35c0e5a 100644 --- a/src/client/actions/ActionsManager.js +++ b/src/client/actions/ActionsManager.js @@ -11,6 +11,7 @@ class ActionsManager { this.register(require('./ChannelCreate')); this.register(require('./ChannelDelete')); this.register(require('./ChannelUpdate')); + this.register(require('./GuildAuditLogEntryCreate')); this.register(require('./GuildBanAdd')); this.register(require('./GuildBanRemove')); this.register(require('./GuildChannelsPositionUpdate')); diff --git a/src/client/actions/GuildAuditLogEntryCreate.js b/src/client/actions/GuildAuditLogEntryCreate.js new file mode 100644 index 00000000..199e134 --- /dev/null +++ b/src/client/actions/GuildAuditLogEntryCreate.js @@ -0,0 +1,29 @@ +'use strict'; + +const Action = require('./Action'); +const GuildAuditLogsEntry = require('../../structures/GuildAuditLogs').Entry; +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; diff --git a/src/client/websocket/handlers/GUILD_AUDIT_LOG_ENTRY_CREATE.js b/src/client/websocket/handlers/GUILD_AUDIT_LOG_ENTRY_CREATE.js new file mode 100644 index 00000000..8623141 --- /dev/null +++ b/src/client/websocket/handlers/GUILD_AUDIT_LOG_ENTRY_CREATE.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = (client, packet) => { + client.actions.GuildAuditLogEntryCreate.handle(packet.d); +}; diff --git a/src/client/websocket/handlers/index.js b/src/client/websocket/handlers/index.js index 035ecbb..ebacf81 100644 --- a/src/client/websocket/handlers/index.js +++ b/src/client/websocket/handlers/index.js @@ -14,6 +14,7 @@ const handlers = Object.fromEntries([ ['AUTO_MODERATION_RULE_CREATE', require('./AUTO_MODERATION_RULE_CREATE')], ['AUTO_MODERATION_RULE_DELETE', require('./AUTO_MODERATION_RULE_DELETE')], ['AUTO_MODERATION_RULE_UPDATE', require('./AUTO_MODERATION_RULE_UPDATE')], + ['GUILD_AUDIT_LOG_ENTRY_CREATE', require('./GUILD_AUDIT_LOG_ENTRY_CREATE')], ['CALL_CREATE', require('./CALL_CREATE')], ['CALL_UPDATE', require('./CALL_UPDATE')], ['CALL_DELETE', require('./CALL_DELETE')], diff --git a/src/structures/GuildAuditLogs.js b/src/structures/GuildAuditLogs.js index 6626764..dd52bab 100644 --- a/src/structures/GuildAuditLogs.js +++ b/src/structures/GuildAuditLogs.js @@ -225,7 +225,7 @@ class GuildAuditLogs { */ this.entries = new Collection(); 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); } } @@ -384,7 +384,7 @@ class GuildAuditLogs { * Audit logs entry. */ class GuildAuditLogsEntry { - constructor(logs, guild, data) { + constructor(guild, data, logs) { const targetType = GuildAuditLogs.targetType(data.action_type); /** * The target type of this entry @@ -410,6 +410,12 @@ class GuildAuditLogsEntry { */ 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 * @type {?User} @@ -417,7 +423,7 @@ class GuildAuditLogsEntry { this.executor = data.user_id ? guild.client.options.partials.includes(PartialTypes.USER) ? 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; /** @@ -521,6 +527,12 @@ class GuildAuditLogsEntry { break; } + /** + * The id of the target of this entry + * @type {?Snowflake} + */ + this.targetId = data.target_id; + /** * The target of this entry * @type {?AuditLogEntryTarget} @@ -536,12 +548,12 @@ class GuildAuditLogsEntry { } else if (targetType === Targets.USER && data.target_id) { this.target = guild.client.options.partials.includes(PartialTypes.USER) ? 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) { this.target = guild.client.guilds.cache.get(data.target_id); } else if (targetType === Targets.WEBHOOK) { this.target = - logs.webhooks.get(data.target_id) ?? + logs?.webhooks.get(data.target_id) ?? new Webhook( guild.client, this.changes.reduce( @@ -576,10 +588,10 @@ class GuildAuditLogsEntry { this.target = data.action_type === Actions.MESSAGE_BULK_DELETE ? 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) { this.target = - logs.integrations.get(data.target_id) ?? + logs?.integrations.get(data.target_id) ?? new Integration( guild.client, this.changes.reduce( diff --git a/src/util/Constants.js b/src/util/Constants.js index e87a7db..bfb55d8 100644 --- a/src/util/Constants.js +++ b/src/util/Constants.js @@ -401,6 +401,7 @@ exports.Opcodes = { * * GUILD_SCHEDULED_EVENT_DELETE: guildScheduledEventDelete * * GUILD_SCHEDULED_EVENT_USER_ADD: guildScheduledEventUserAdd * * GUILD_SCHEDULED_EVENT_USER_REMOVE: guildScheduledEventUserRemove + * * GUILD_AUDIT_LOG_ENTRY_CREATE: guildAuditLogEntryCreate * @typedef {Object} Events */ exports.Events = { @@ -497,6 +498,7 @@ exports.Events = { GUILD_SCHEDULED_EVENT_DELETE: 'guildScheduledEventDelete', GUILD_SCHEDULED_EVENT_USER_ADD: 'guildScheduledEventUserAdd', GUILD_SCHEDULED_EVENT_USER_REMOVE: 'guildScheduledEventUserRemove', + GUILD_AUDIT_LOG_ENTRY_CREATE: 'guildAuditLogEntryCreate', RELATIONSHIP_ADD: 'relationshipAdd', RELATIONSHIP_REMOVE: 'relationshipRemove', RELATIONSHIP_UPDATE: 'relationshipUpdate', @@ -594,6 +596,7 @@ exports.PartialTypes = keyMirror(['USER', 'CHANNEL', 'GUILD_MEMBER', 'MESSAGE', * * GUILD_SCHEDULED_EVENT_DELETE * * GUILD_SCHEDULED_EVENT_USER_ADD * * GUILD_SCHEDULED_EVENT_USER_REMOVE + * * GUILD_AUDIT_LOG_ENTRY_CREATE * @typedef {string} WSEventType * @see {@link https://discord.com/developers/docs/topics/gateway#commands-and-events-gateway-events} */ @@ -654,6 +657,7 @@ exports.WSEvents = keyMirror([ 'GUILD_SCHEDULED_EVENT_DELETE', 'GUILD_SCHEDULED_EVENT_USER_ADD', 'GUILD_SCHEDULED_EVENT_USER_REMOVE', + 'GUILD_AUDIT_LOG_ENTRY_CREATE', ]); /** diff --git a/typings/index.d.ts b/typings/index.d.ts index 8eb4d18..bbfbe17 100644 --- a/typings/index.d.ts +++ b/typings/index.d.ts @@ -1475,16 +1475,18 @@ export class GuildAuditLogsEntry< ? GuildAuditLogsTypes[TAction][0] : 'UNKNOWN', > { - private constructor(logs: GuildAuditLogs, guild: Guild, data: RawGuildAuditLogEntryData); + private constructor(guild: Guild, data: RawGuildAuditLogEntryData, logs?: GuildAuditLogs); public action: TAction; public actionType: TActionType; public changes: AuditLogChange[]; public readonly createdAt: Date; public readonly createdTimestamp: number; + public executorId: Snowflake | null; public executor: User | null; public extra: TAction extends keyof GuildAuditLogsEntryExtraField ? GuildAuditLogsEntryExtraField[TAction] : null; public id: Snowflake; public reason: string | null; + public targetId: Snowflake | null; public target: TTargetType extends keyof GuildAuditLogsEntryTargetField ? GuildAuditLogsEntryTargetField[TTargetType] : Role | GuildEmoji | { id: Snowflake } | null; @@ -4671,6 +4673,7 @@ export interface ClientEvents extends BaseClientEvents { guildScheduledEventDelete: [guildScheduledEvent: GuildScheduledEvent]; guildScheduledEventUserAdd: [guildScheduledEvent: GuildScheduledEvent, user: User]; guildScheduledEventUserRemove: [guildScheduledEvent: GuildScheduledEvent, user: User]; + guildAuditLogEntryCreate: [auditLogEntry: GuildAuditLogsEntry, guild: Guild]; relationshipAdd: [id: Snowflake, type: RelationshipTypes]; relationshipRemove: [id: Snowflake]; relationshipUpdate: [id: Snowflake, type: RelationshipTypes, data: object]; @@ -4770,6 +4773,7 @@ export interface ConstantsEvents { GUILD_SCHEDULED_EVENT_DELETE: 'guildScheduledEventDelete'; GUILD_SCHEDULED_EVENT_USER_ADD: 'guildScheduledEventUserAdd'; GUILD_SCHEDULED_EVENT_USER_REMOVE: 'guildScheduledEventUserRemove'; + GUILD_AUDIT_LOG_ENTRY_CREATE: 'guildAuditLogEntryCreate'; RELATIONSHIP_ADD: 'relationshipAdd'; RELATIONSHIP_REMOVE: 'relationshipRemove'; RELATIONSHIP_UPDATE: 'relationshipUpdate';