diff --git a/src/structure/components/observers/AuditLog.js b/src/structure/components/observers/AuditLog.js index 4f42259..293667a 100644 --- a/src/structure/components/observers/AuditLog.js +++ b/src/structure/components/observers/AuditLog.js @@ -68,45 +68,80 @@ class AuditLogObserver extends Observer { } async guildMemberUpdate(oldMember, newMember) { - if (oldMember.roles.cache.size === newMember.roles.cache.size) return undefined; + + const timeout = oldMember.communicationDisabledUntilTimestamp !== newMember.communicationDisabledUntilTimestamp; + const roleBased = oldMember.roles.cache.size !== newMember.roles.cache.size; + if (timeout) return this._logTimeoutMute(oldMember, newMember); + if (roleBased) return this._logRoleMute(oldMember, newMember); + } + + async _logTimeoutMute(oldMember, newMember) { + const { guildWrapper: wrapper } = newMember; + const settings = await wrapper.settings(); + if (!settings.moderation.channel) return undefined; + + const mute = oldMember.communicationDisabledUntilTimestamp === null && newMember.communicationDisabledUntilTimestamp !== null; + const auditLogs = await wrapper.fetchAuditLogs({ limit: 1, type: 'MEMBER_UPDATE' }); + if (!auditLogs.entries.size) return undefined; + + const entry = auditLogs.entries.find((e) => e.changes?.some((e) => e.key === 'communication_disabled_until')); + if(!entry) return undefined; + + let type = null, + duration = null; + if (mute) { + if (!settings.moderation.infractions.includes('MUTE')) return undefined; + type = 'MUTE'; + duration = newMember.communicationDisabledUntilTimestamp - Date.now(); + } else { + if (!settings.moderation.infractions.includes('UNMUTE')) return undefined; + type = 'UNMUTE'; + } + new Infraction(this.client, { + type, + targetType: 'USER', + guild: wrapper, + target: newMember.user, + executor: entry.executor, + duration, + reason: wrapper.format('O_AUDITLOG_AUTOLOG') + entry.reason ? '\n' + entry.reason : '' + }).handle(); + } + + async _logRoleMute(oldMember, newMember) { const { guildWrapper: wrapper } = newMember; const settings = await wrapper.settings(); if (!settings.moderation.channel) return undefined; const mutedRole = settings.mute.role; if (!mutedRole) return undefined; + const audit = await this._fetchFirstEntry(newMember.guild, newMember.user, 'MEMBER_ROLE_UPDATE'); + if (!audit) return undefined; + let type = null; if (!oldMember.roles.cache.has(mutedRole) && newMember.roles.cache.has(mutedRole)) { //Member was assigned muted role. if (!settings.moderation.infractions.includes('MUTE')) return undefined; - const audit = await this._fetchFirstEntry(newMember.guild, newMember.user, 'MEMBER_ROLE_UPDATE'); - if (!audit) return undefined; - new Infraction(this.client, { - type: 'MUTE', - targetType: 'USER', - guild: wrapper, - target: newMember.user, - executor: audit.executor, - reason: "*This action was performed without the bot.*" - }).handle(); + type = 'MUTE'; + } else if (oldMember.roles.cache.has(mutedRole) && !newMember.roles.cache.has(mutedRole)) { //Member was unassigned muted role. if (!settings.moderation.infractions.includes('UNMUTE')) return undefined; - const audit = await this._fetchFirstEntry(newMember.guild, newMember.user, 'MEMBER_ROLE_UPDATE'); - if (!audit) return undefined; - new Infraction(this.client, { - type: 'UNMUTE', - targetType: 'USER', - guild: wrapper, - target: newMember.user, - executor: audit.executor, - reason: "*This action was performed without the bot.*" - }).handle(); + type = 'UNMUTE'; } + if (!type) return; + new Infraction(this.client, { + type, + targetType: 'USER', + guild: wrapper, + target: newMember.user, + executor: audit.executor, + reason: wrapper.format('O_AUDITLOG_AUTOLOG', { reason: audit.reason }) + }).handle(); } async _fetchFirstEntry(guild, user, type) { if (!guild.me.permissions.has('VIEW_AUDIT_LOG')) return null; - const audit = await guild.fetchAuditLogs({ limit: 1 }); + const audit = await guild.fetchAuditLogs({ limit: 1, type }); if (audit.entries.size === 0) return null; const entry = audit.entries.filter((e) => e?.target?.id === user.id).first();