From f0a9f894575871d498447c5de2b5f0f826b117b7 Mon Sep 17 00:00:00 2001 From: IRONM00N <64110067+IRONM00N@users.noreply.github.com> Date: Wed, 29 Dec 2021 22:14:04 -0500 Subject: events --- .../extensions/discord.js/BushClientEvents.d.ts | 34 +++++++++++ src/lib/extensions/discord.js/BushGuild.ts | 68 ++++++++++++---------- src/listeners/custom/bushBan.ts | 32 ---------- src/listeners/custom/bushKick.ts | 31 ---------- src/listeners/custom/bushLevelUpdate.ts | 28 --------- src/listeners/custom/bushMute.ts | 32 ---------- src/listeners/custom/bushPunishRole.ts | 31 ---------- src/listeners/custom/bushPunishRoleRemove.ts | 32 ---------- src/listeners/custom/bushPurge.ts | 40 ------------- src/listeners/custom/bushUnban.ts | 31 ---------- src/listeners/custom/bushUnmute.ts | 31 ---------- src/listeners/custom/bushUpdateModlog.ts | 33 ----------- src/listeners/custom/bushUpdateSettings.ts | 33 ----------- src/listeners/custom/bushWarn.ts | 31 ---------- src/listeners/guild-custom/bushLockdown.ts | 27 +++++++++ src/listeners/guild-custom/bushUnlockdown.ts | 27 +++++++++ src/listeners/guild/syncUnban.ts | 24 -------- src/listeners/guild/syncUnbanPunishmentModel.ts | 24 ++++++++ src/listeners/member-custom/bushBan.ts | 32 ++++++++++ src/listeners/member-custom/bushBlock.ts | 36 ++++++++++++ src/listeners/member-custom/bushKick.ts | 31 ++++++++++ src/listeners/member-custom/bushLevelUpdate.ts | 28 +++++++++ src/listeners/member-custom/bushMute.ts | 32 ++++++++++ src/listeners/member-custom/bushPunishRole.ts | 31 ++++++++++ .../member-custom/bushPunishRoleRemove.ts | 32 ++++++++++ src/listeners/member-custom/bushPurge.ts | 40 +++++++++++++ src/listeners/member-custom/bushUnban.ts | 31 ++++++++++ src/listeners/member-custom/bushUnblock.ts | 32 ++++++++++ src/listeners/member-custom/bushUnmute.ts | 31 ++++++++++ src/listeners/member-custom/bushUpdateModlog.ts | 33 +++++++++++ src/listeners/member-custom/bushUpdateSettings.ts | 33 +++++++++++ src/listeners/member-custom/bushWarn.ts | 31 ++++++++++ src/tasks/removeExpiredPunishements.ts | 12 +++- 33 files changed, 612 insertions(+), 442 deletions(-) delete mode 100644 src/listeners/custom/bushBan.ts delete mode 100644 src/listeners/custom/bushKick.ts delete mode 100644 src/listeners/custom/bushLevelUpdate.ts delete mode 100644 src/listeners/custom/bushMute.ts delete mode 100644 src/listeners/custom/bushPunishRole.ts delete mode 100644 src/listeners/custom/bushPunishRoleRemove.ts delete mode 100644 src/listeners/custom/bushPurge.ts delete mode 100644 src/listeners/custom/bushUnban.ts delete mode 100644 src/listeners/custom/bushUnmute.ts delete mode 100644 src/listeners/custom/bushUpdateModlog.ts delete mode 100644 src/listeners/custom/bushUpdateSettings.ts delete mode 100644 src/listeners/custom/bushWarn.ts create mode 100644 src/listeners/guild-custom/bushLockdown.ts create mode 100644 src/listeners/guild-custom/bushUnlockdown.ts delete mode 100644 src/listeners/guild/syncUnban.ts create mode 100644 src/listeners/guild/syncUnbanPunishmentModel.ts create mode 100644 src/listeners/member-custom/bushBan.ts create mode 100644 src/listeners/member-custom/bushBlock.ts create mode 100644 src/listeners/member-custom/bushKick.ts create mode 100644 src/listeners/member-custom/bushLevelUpdate.ts create mode 100644 src/listeners/member-custom/bushMute.ts create mode 100644 src/listeners/member-custom/bushPunishRole.ts create mode 100644 src/listeners/member-custom/bushPunishRoleRemove.ts create mode 100644 src/listeners/member-custom/bushPurge.ts create mode 100644 src/listeners/member-custom/bushUnban.ts create mode 100644 src/listeners/member-custom/bushUnblock.ts create mode 100644 src/listeners/member-custom/bushUnmute.ts create mode 100644 src/listeners/member-custom/bushUpdateModlog.ts create mode 100644 src/listeners/member-custom/bushUpdateSettings.ts create mode 100644 src/listeners/member-custom/bushWarn.ts (limited to 'src') diff --git a/src/lib/extensions/discord.js/BushClientEvents.d.ts b/src/lib/extensions/discord.js/BushClientEvents.d.ts index 10d70f9..b779991 100644 --- a/src/lib/extensions/discord.js/BushClientEvents.d.ts +++ b/src/lib/extensions/discord.js/BushClientEvents.d.ts @@ -6,6 +6,7 @@ import type { BushGuildBan, BushGuildEmoji, BushGuildMember, + BushGuildTextBasedChannel, BushMessage, BushMessageReaction, BushNewsChannel, @@ -171,6 +172,17 @@ export interface BushClientEvents extends AkairoClientEvents { dmSuccess?: boolean, evidence?: string ]; + bushBlock: [ + victim: BushGuildMember | BushUser, + moderator: BushUser, + guild: BushGuild, + reason: string | undefined, + caseID: string, + duration: number, + dmSuccess: boolean, + channel: BushGuildTextBasedChannel, + evidence?: string + ]; bushKick: [ victim: BushGuildMember, moderator: BushUser, @@ -224,6 +236,16 @@ export interface BushClientEvents extends AkairoClientEvents { dmSuccess: boolean, evidence?: string ]; + bushUnblock: [ + victim: BushGuildMember | BushUser, + moderator: BushUser, + guild: BushGuild, + reason: string | undefined, + caseID: string, + dmSuccess: boolean, + channel: BushGuildTextBasedChannel, + evidence?: string + ]; bushUnmute: [ victim: BushGuildMember, moderator: BushUser, @@ -263,6 +285,18 @@ export interface BushClientEvents extends AkairoClientEvents { currentXp: number, message: BushMessage & { guild: BushGuild } ]; + bushLockdown: [ + moderator: BushGuildMember, + reason?: string | undefined, + channel?: BushGuildTextBasedChannel, + all?: boolean + ]; + bushUnlockdown: [ + moderator: BushGuildMember, + reason?: string | undefined, + channel?: BushGuildTextBasedChannel, + all?: boolean + ]; } type Setting = diff --git a/src/lib/extensions/discord.js/BushGuild.ts b/src/lib/extensions/discord.js/BushGuild.ts index 299fdbc..b67c71b 100644 --- a/src/lib/extensions/discord.js/BushGuild.ts +++ b/src/lib/extensions/discord.js/BushGuild.ts @@ -290,40 +290,46 @@ export class BushGuild extends Guild { const moderator = this.members.resolve(options.moderator); if (!moderator) return 'moderator not found'; - const errors = new Collection(); - let successCount = 0; - - for (const _channel of mappedChannels) { - const channel = _channel!; - if (!channel.permissionsFor(this.me!.id)?.has(['MANAGE_CHANNELS'])) { - errors.set(channel.id, new Error('client no permission')); - continue; - } else if (!channel.permissionsFor(options.moderator)?.has(['MANAGE_CHANNELS'])) { - errors.set(channel.id, new Error('moderator no permission')); - continue; - } - const reason = `${options.unlock ? 'Unlocking' : 'Locking Down'} Channel | ${moderator.user.tag} | ${ - options.reason ?? 'No reason provided' - }`; - - if (channel.isThread()) { - const lockdownSuccess = await channel.parent?.permissionOverwrites - .edit(this.id, { SEND_MESSAGES_IN_THREADS: options.unlock ? null : false }, { reason }) - .catch((e) => e); - if (lockdownSuccess instanceof Error) errors.set(channel.id, lockdownSuccess); - else successCount++; - } else { - const lockdownSuccess = await channel.permissionOverwrites - .edit(this.id, { SEND_MESSAGES: options.unlock ? null : false }, { reason }) - .catch((e) => e); - if (lockdownSuccess instanceof Error) errors.set(channel.id, lockdownSuccess); - else successCount++; + const ret = await (async (): Promise => { + const errors = new Collection(); + let successCount = 0; + + for (const _channel of mappedChannels) { + const channel = _channel!; + if (!channel.permissionsFor(this.me!.id)?.has(['MANAGE_CHANNELS'])) { + errors.set(channel.id, new Error('client no permission')); + continue; + } else if (!channel.permissionsFor(options.moderator)?.has(['MANAGE_CHANNELS'])) { + errors.set(channel.id, new Error('moderator no permission')); + continue; + } + + const reason = `[${options.unlock ? 'Unlockdown' : 'Lockdown'}] ${moderator.user.tag} | ${ + options.reason ?? 'No reason provided' + }`; + + if (channel.isThread()) { + const lockdownSuccess = await channel.parent?.permissionOverwrites + .edit(this.id, { SEND_MESSAGES_IN_THREADS: options.unlock ? null : false }, { reason }) + .catch((e) => e); + if (lockdownSuccess instanceof Error) errors.set(channel.id, lockdownSuccess); + else successCount++; + } else { + const lockdownSuccess = await channel.permissionOverwrites + .edit(this.id, { SEND_MESSAGES: options.unlock ? null : false }, { reason }) + .catch((e) => e); + if (lockdownSuccess instanceof Error) errors.set(channel.id, lockdownSuccess); + else successCount++; + } } - } - if (errors.size) return errors; - else return `success: ${successCount}`; + if (errors.size) return errors; + else return `success: ${successCount}`; + })(); + + client.emit(options.unlock ? 'bushUnlockdown' : 'bushLockdown', moderator, options.reason, options.channel); + return ret; } } diff --git a/src/listeners/custom/bushBan.ts b/src/listeners/custom/bushBan.ts deleted file mode 100644 index 59e010e..0000000 --- a/src/listeners/custom/bushBan.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { BushListener, type BushClientEvents } from '#lib'; -import { GuildMember, MessageEmbed } from 'discord.js'; - -export default class BushBanListener extends BushListener { - public constructor() { - super('bushBan', { - emitter: 'client', - event: 'bushBan', - category: 'custom' - }); - } - - public override async exec(...[victim, moderator, guild, reason, caseID, duration, dmSuccess]: BushClientEvents['bushBan']) { - const logChannel = await guild.getLogChannel('moderation'); - if (!logChannel) return; - const user = victim instanceof GuildMember ? victim.user : victim; - - const logEmbed = new MessageEmbed() - .setColor(util.colors.discord.RED) - .setTimestamp() - .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) - .addField('**Action**', `${duration ? 'Temp Ban' : 'Perm Ban'}`) - .addField('**User**', `${user} (${user.tag})`) - .addField('**Moderator**', `${moderator} (${moderator.tag})`) - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - .addField('**Reason**', `${reason || '[No Reason Provided]'}`); - if (duration) logEmbed.addField('**Duration**', util.humanizeDuration(duration)); - if (dmSuccess === false) logEmbed.addField('**Additional Info**', 'Could not dm user.'); - return await logChannel.send({ embeds: [logEmbed] }); - } -} diff --git a/src/listeners/custom/bushKick.ts b/src/listeners/custom/bushKick.ts deleted file mode 100644 index 866aba4..0000000 --- a/src/listeners/custom/bushKick.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { BushListener, type BushClientEvents } from '#lib'; -import { GuildMember, MessageEmbed } from 'discord.js'; - -export default class BushKickListener extends BushListener { - public constructor() { - super('bushKick', { - emitter: 'client', - event: 'bushKick', - category: 'custom' - }); - } - - public override async exec(...[victim, moderator, guild, reason, caseID, dmSuccess]: BushClientEvents['bushKick']) { - const logChannel = await guild.getLogChannel('moderation'); - if (!logChannel) return; - const user = victim instanceof GuildMember ? victim.user : victim; - - const logEmbed = new MessageEmbed() - .setColor(util.colors.discord.RED) - .setTimestamp() - .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) - .addField('**Action**', `${'Kick'}`) - .addField('**User**', `${user} (${user.tag})`) - .addField('**Moderator**', `${moderator} (${moderator.tag})`) - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - .addField('**Reason**', `${reason || '[No Reason Provided]'}`); - if (dmSuccess === false) logEmbed.addField('**Additional Info**', 'Could not dm user.'); - return await logChannel.send({ embeds: [logEmbed] }); - } -} diff --git a/src/listeners/custom/bushLevelUpdate.ts b/src/listeners/custom/bushLevelUpdate.ts deleted file mode 100644 index 4504c45..0000000 --- a/src/listeners/custom/bushLevelUpdate.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { BushListener, type BushClientEvents } from '#lib'; -import { type TextChannel } from 'discord.js'; - -export default class BushLevelUpdateListener extends BushListener { - public constructor() { - super('bushLevelUpdate', { - emitter: 'client', - event: 'bushLevelUpdate', - category: 'custom' - }); - } - - public override async exec(...[member, _oldLevel, newLevel, _currentXp, message]: BushClientEvents['bushLevelUpdate']) { - if (await message.guild.hasFeature('sendLevelUpMessages')) { - void (async () => { - const channel = ((await message.guild.channels - .fetch((await message.guild.getSetting('levelUpChannel')) ?? message.channelId) - .catch(() => null)) ?? message.channel) as TextChannel; - - const success = await channel - .send(`${util.format.input(member.user.tag)} leveled up to level ${util.format.input(`${newLevel}`)}.`) - .catch(() => null); - - if (!success) await client.console.warn('bushLevelUpdate', `Could not send level up message in ${message.guild}`); - })(); - } - } -} diff --git a/src/listeners/custom/bushMute.ts b/src/listeners/custom/bushMute.ts deleted file mode 100644 index c25bd69..0000000 --- a/src/listeners/custom/bushMute.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { BushListener, type BushClientEvents } from '#lib'; -import { GuildMember, MessageEmbed } from 'discord.js'; - -export default class BushMuteListener extends BushListener { - public constructor() { - super('bushMute', { - emitter: 'client', - event: 'bushMute', - category: 'custom' - }); - } - - public override async exec(...[victim, moderator, guild, reason, caseID, duration, dmSuccess]: BushClientEvents['bushMute']) { - const logChannel = await guild.getLogChannel('moderation'); - if (!logChannel) return; - const user = victim instanceof GuildMember ? victim.user : victim; - - const logEmbed = new MessageEmbed() - .setColor(util.colors.discord.ORANGE) - .setTimestamp() - .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) - .addField('**Action**', `${duration ? 'Temp Mute' : 'Perm Mute'}`) - .addField('**User**', `${user} (${user.tag})`) - .addField('**Moderator**', `${moderator} (${moderator.tag})`) - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - .addField('**Reason**', `${reason || '[No Reason Provided]'}`); - if (duration) logEmbed.addField('**Duration**', `${util.humanizeDuration(duration) || duration}`); - if (dmSuccess === false) logEmbed.addField('**Additional Info**', 'Could not dm user.'); - return await logChannel.send({ embeds: [logEmbed] }); - } -} diff --git a/src/listeners/custom/bushPunishRole.ts b/src/listeners/custom/bushPunishRole.ts deleted file mode 100644 index 3491166..0000000 --- a/src/listeners/custom/bushPunishRole.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { BushListener, type BushClientEvents } from '#lib'; -import { GuildMember, MessageEmbed } from 'discord.js'; - -export default class BushPunishRoleListener extends BushListener { - public constructor() { - super('bushPunishRole', { - emitter: 'client', - event: 'bushPunishRole', - category: 'custom' - }); - } - - public override async exec(...[victim, moderator, guild, reason, caseID, duration]: BushClientEvents['bushPunishRole']) { - const logChannel = await guild.getLogChannel('moderation'); - if (!logChannel) return; - const user = victim instanceof GuildMember ? victim.user : victim; - - const logEmbed = new MessageEmbed() - .setColor(util.colors.discord.YELLOW) - .setTimestamp() - .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) - .addField('**Action**', `${duration ? 'Temp Punishment Role' : 'Perm Punishment Role'}`) - .addField('**User**', `${user} (${user.tag})`) - .addField('**Moderator**', `${moderator} (${moderator.tag})`) - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - .addField('**Reason**', `${reason || '[No Reason Provided]'}`); - if (duration) logEmbed.addField('**Duration**', util.humanizeDuration(duration)); - return await logChannel.send({ embeds: [logEmbed] }); - } -} diff --git a/src/listeners/custom/bushPunishRoleRemove.ts b/src/listeners/custom/bushPunishRoleRemove.ts deleted file mode 100644 index eb1ae71..0000000 --- a/src/listeners/custom/bushPunishRoleRemove.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { BushListener, type BushClientEvents } from '#lib'; -import { GuildMember, MessageEmbed } from 'discord.js'; - -export default class BushPunishRoleRemoveListener extends BushListener { - public constructor() { - super('bushPunishRoleRemove', { - emitter: 'client', - event: 'bushPunishRoleRemove', - category: 'custom' - }); - } - - public override async exec(...[victim, moderator, guild, reason, caseID, role]: BushClientEvents['bushPunishRoleRemove']) { - const logChannel = await guild.getLogChannel('moderation'); - if (!logChannel) return; - const user = victim instanceof GuildMember ? victim.user : victim; - - const logEmbed = new MessageEmbed() - .setColor(util.colors.discord.GREEN) - .setTimestamp() - .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) - .addField('**Action**', `${'Remove Punishment Role'}`) - .addField('**Role**', `${role}`) - .addField('**User**', `${user} (${user.tag})`) - .addField('**Moderator**', `${moderator} (${moderator.tag})`) - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - .addField('**Reason**', `${reason || '[No Reason Provided]'}`); - - return await logChannel.send({ embeds: [logEmbed] }); - } -} diff --git a/src/listeners/custom/bushPurge.ts b/src/listeners/custom/bushPurge.ts deleted file mode 100644 index 97824a4..0000000 --- a/src/listeners/custom/bushPurge.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { BushListener, type BushClientEvents } from '#lib'; -import { MessageEmbed } from 'discord.js'; - -export default class BushPurgeListener extends BushListener { - public constructor() { - super('bushPurge', { - emitter: 'client', - event: 'bushPurge', - category: 'custom' - }); - } - - public override async exec(...[moderator, guild, channel, messages]: BushClientEvents['bushPurge']) { - const logChannel = await guild.getLogChannel('moderation'); - if (!logChannel) return; - - const mappedMessages = messages.map((m) => ({ - id: m.id, - author: `${m.author.tag} (${m.id})`, - content: m.content, - embeds: m.embeds, - attachments: [...m.attachments.values()] - })); - const haste = await util.inspectCleanRedactHaste(mappedMessages); - - const logEmbed = new MessageEmbed() - .setColor(util.colors.discord.DARK_PURPLE) - .setTimestamp() - .setFooter({ text: `${messages.size.toLocaleString()} Messages` }) - .setAuthor({ name: moderator.tag, iconURL: moderator.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) - .addField('**Action**', `${'Purge'}`) - .addField('**Moderator**', `${moderator} (${moderator.tag})`) - .addField('**Channel**', `<#${channel.id}> (${channel.name})`) - .addField( - '**Messages**', - `${haste.url ? `[haste](${haste.url})${haste.error ? `- ${haste.error}` : ''}` : `${util.emojis.error} ${haste.error}`}` - ); - return await logChannel.send({ embeds: [logEmbed] }); - } -} diff --git a/src/listeners/custom/bushUnban.ts b/src/listeners/custom/bushUnban.ts deleted file mode 100644 index a59bcf0..0000000 --- a/src/listeners/custom/bushUnban.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { BushListener, type BushClientEvents } from '#lib'; -import { GuildMember, MessageEmbed } from 'discord.js'; - -export default class BushUnbanListener extends BushListener { - public constructor() { - super('bushUnban', { - emitter: 'client', - event: 'bushUnban', - category: 'custom' - }); - } - - public override async exec(...[victim, moderator, guild, reason, caseID, dmSuccess]: BushClientEvents['bushUnban']) { - const logChannel = await guild.getLogChannel('moderation'); - if (!logChannel) return; - const user = victim instanceof GuildMember ? victim.user : victim; - - const logEmbed = new MessageEmbed() - .setColor(util.colors.discord.GREEN) - .setTimestamp() - .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) - .addField('**Action**', `${'Unban'}`) - .addField('**User**', `${user} (${user.tag})`) - .addField('**Moderator**', `${moderator} (${moderator.tag})`) - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - .addField('**Reason**', `${reason || '[No Reason Provided]'}`); - if (dmSuccess === false) logEmbed.addField('**Additional Info**', 'Could not dm user.'); - return await logChannel.send({ embeds: [logEmbed] }); - } -} diff --git a/src/listeners/custom/bushUnmute.ts b/src/listeners/custom/bushUnmute.ts deleted file mode 100644 index bd14fcd..0000000 --- a/src/listeners/custom/bushUnmute.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { BushListener, type BushClientEvents } from '#lib'; -import { GuildMember, MessageEmbed } from 'discord.js'; - -export default class BushUnmuteListener extends BushListener { - public constructor() { - super('bushUnmute', { - emitter: 'client', - event: 'bushUnmute', - category: 'custom' - }); - } - - public override async exec(...[victim, moderator, guild, reason, caseID, dmSuccess]: BushClientEvents['bushUnmute']) { - const logChannel = await guild.getLogChannel('moderation'); - if (!logChannel) return; - const user = victim instanceof GuildMember ? victim.user : victim; - - const logEmbed = new MessageEmbed() - .setColor(util.colors.discord.GREEN) - .setTimestamp() - .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) - .addField('**Action**', `${'Unmute'}`) - .addField('**User**', `${user} (${user.tag})`) - .addField('**Moderator**', `${moderator} (${moderator.tag})`) - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - .addField('**Reason**', `${reason || '[No Reason Provided]'}`); - if (dmSuccess === false) logEmbed.addField('**Additional Info**', 'Could not dm user.'); - return await logChannel.send({ embeds: [logEmbed] }); - } -} diff --git a/src/listeners/custom/bushUpdateModlog.ts b/src/listeners/custom/bushUpdateModlog.ts deleted file mode 100644 index fa82dba..0000000 --- a/src/listeners/custom/bushUpdateModlog.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { BushListener, type BushClientEvents } from '#lib'; -import { MessageEmbed } from 'discord.js'; - -export default class BushUpdateModlogListener extends BushListener { - public constructor() { - super('bushUpdateModlog', { - emitter: 'client', - event: 'bushUpdateModlog', - category: 'custom' - }); - } - - public override async exec(...[moderator, modlogID, key, oldModlog, newModlog]: BushClientEvents['bushUpdateModlog']) { - const logChannel = await moderator.guild.getLogChannel('moderation'); - if (!logChannel) return; - - const logEmbed = new MessageEmbed() - .setColor(util.colors.discord.BLURPLE) - .setTimestamp() - .setAuthor({ - name: moderator.user.tag, - iconURL: moderator.user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined - }) - .addField('**Action**', `${'Update Modlog'}`) - .addField('**Moderator**', `${moderator} (${moderator.user.tag})`) - .addField('**ModLog Changed**', modlogID) - .addField('**Value Changed**', key) - .addField('**Old Value**', await util.inspectCleanRedactCodeblock(oldModlog, undefined, undefined, 1024)) - .addField('**New Value**', await util.inspectCleanRedactCodeblock(newModlog, undefined, undefined, 1024)); - - return await logChannel.send({ embeds: [logEmbed] }); - } -} diff --git a/src/listeners/custom/bushUpdateSettings.ts b/src/listeners/custom/bushUpdateSettings.ts deleted file mode 100644 index c350bde..0000000 --- a/src/listeners/custom/bushUpdateSettings.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { BushListener, type BushClientEvents } from '#lib'; -import { MessageEmbed } from 'discord.js'; - -export default class BushUpdateSettingsListener extends BushListener { - public constructor() { - super('bushUpdateSettings', { - emitter: 'client', - event: 'bushUpdateSettings', - category: 'custom' - }); - } - - public override async exec(...[setting, guild, oldSettings, newSettings, moderator]: BushClientEvents['bushUpdateSettings']) { - const logChannel = await guild.getLogChannel('moderation'); - if (!logChannel) return; - - const logEmbed = new MessageEmbed().setColor(util.colors.discord.BLURPLE).setTimestamp(); - - if (moderator) - logEmbed.setAuthor({ - name: moderator.user.tag, - iconURL: moderator.user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined - }); - logEmbed.addField('**Action**', `${'Update Settings'}`); - if (moderator) logEmbed.addField('**Moderator**', `${moderator} (${moderator.user.tag})`); - logEmbed - .addField('**Setting Changed**', setting) - .addField('**Old Value**', await util.inspectCleanRedactCodeblock(oldSettings, 'js', undefined, 1024)) - .addField('**New Value**', await util.inspectCleanRedactCodeblock(newSettings, 'js', undefined, 1024)); - - return await logChannel.send({ embeds: [logEmbed] }); - } -} diff --git a/src/listeners/custom/bushWarn.ts b/src/listeners/custom/bushWarn.ts deleted file mode 100644 index 1554aa4..0000000 --- a/src/listeners/custom/bushWarn.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { BushListener, type BushClientEvents } from '#lib'; -import { GuildMember, MessageEmbed } from 'discord.js'; - -export default class BushWarnListener extends BushListener { - public constructor() { - super('bushWarn', { - emitter: 'client', - event: 'bushWarn', - category: 'custom' - }); - } - - public override async exec(...[victim, moderator, guild, reason, caseID, dmSuccess]: BushClientEvents['bushWarn']) { - const logChannel = await guild.getLogChannel('moderation'); - if (!logChannel) return; - const user = victim instanceof GuildMember ? victim.user : victim; - - const logEmbed = new MessageEmbed() - .setColor(util.colors.discord.YELLOW) - .setTimestamp() - .setFooter({ text: `CaseID: ${caseID}` }) - .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) - .addField('**Action**', `${'Warn'}`) - .addField('**User**', `${user} (${user.tag})`) - .addField('**Moderator**', `${moderator} (${moderator.tag})`) - // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing - .addField('**Reason**', `${reason || '[No Reason Provided]'}`); - if (dmSuccess === false) logEmbed.addField('**Additional Info**', 'Could not dm user.'); - return await logChannel.send({ embeds: [logEmbed] }); - } -} diff --git a/src/listeners/guild-custom/bushLockdown.ts b/src/listeners/guild-custom/bushLockdown.ts new file mode 100644 index 0000000..be55a07 --- /dev/null +++ b/src/listeners/guild-custom/bushLockdown.ts @@ -0,0 +1,27 @@ +import { BushListener, type BushClientEvents } from '#lib'; +import { MessageEmbed } from 'discord.js'; + +export default class BushLockdownListener extends BushListener { + public constructor() { + super('bushLockdown', { + emitter: 'client', + event: 'bushLockdown', + category: 'guild-custom' + }); + } + + public override async exec(...[moderator, reason, channel, _all]: BushClientEvents['bushLockdown']) { + const logChannel = await moderator.guild.getLogChannel('moderation'); + if (!logChannel) return; + + const logEmbed = new MessageEmbed() + .setColor(util.colors.discord.BLURPLE) + .setTimestamp() + .addField('**Action**', `${'Lockdown'}`) + .addField('**Moderator**', `${moderator} (${moderator.user.tag})`) + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + .addField('**Reason**', `${reason || '[No Reason Provided]'}`) + .addField('**Channel**', `${channel?.id ? `<#${channel.id}>` : '[All Configured Channels]'}`); + return await logChannel.send({ embeds: [logEmbed] }); + } +} diff --git a/src/listeners/guild-custom/bushUnlockdown.ts b/src/listeners/guild-custom/bushUnlockdown.ts new file mode 100644 index 0000000..d5831c6 --- /dev/null +++ b/src/listeners/guild-custom/bushUnlockdown.ts @@ -0,0 +1,27 @@ +import { BushListener, type BushClientEvents } from '#lib'; +import { MessageEmbed } from 'discord.js'; + +export default class BushUnlockdownListener extends BushListener { + public constructor() { + super('bushUnlockdown', { + emitter: 'client', + event: 'bushUnlockdown', + category: 'guild-custom' + }); + } + + public override async exec(...[moderator, reason, channel, _all]: BushClientEvents['bushUnlockdown']) { + const logChannel = await moderator.guild.getLogChannel('moderation'); + if (!logChannel) return; + + const logEmbed = new MessageEmbed() + .setColor(util.colors.discord.BLURPLE) + .setTimestamp() + .addField('**Action**', `${'Unlockdown'}`) + .addField('**Moderator**', `${moderator} (${moderator.user.tag})`) + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + .addField('**Reason**', `${reason || '[No Reason Provided]'}`) + .addField('**Channel**', `${channel?.id ? `<#${channel.id}>` : '[All Configured Channels]'}`); + return await logChannel.send({ embeds: [logEmbed] }); + } +} diff --git a/src/listeners/guild/syncUnban.ts b/src/listeners/guild/syncUnban.ts deleted file mode 100644 index 01b2679..0000000 --- a/src/listeners/guild/syncUnban.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { ActivePunishment, ActivePunishmentType, BushListener, type BushClientEvents } from '#lib'; - -export default class SyncUnbanListener extends BushListener { - public constructor() { - super('guildBanRemove', { - emitter: 'client', - event: 'guildBanRemove', - category: 'guild' - }); - } - - public override async exec(...[ban]: BushClientEvents['guildBanRemove']) { - const bans = await ActivePunishment.findAll({ - where: { - user: ban.user.id, - guild: ban.guild.id, - type: ActivePunishmentType.BAN - } - }); - for (const dbBan of bans) { - await dbBan.destroy(); - } - } -} diff --git a/src/listeners/guild/syncUnbanPunishmentModel.ts b/src/listeners/guild/syncUnbanPunishmentModel.ts new file mode 100644 index 0000000..44f5bb4 --- /dev/null +++ b/src/listeners/guild/syncUnbanPunishmentModel.ts @@ -0,0 +1,24 @@ +import { ActivePunishment, ActivePunishmentType, BushListener, type BushClientEvents } from '#lib'; + +export default class SyncUnbanListener extends BushListener { + public constructor() { + super('syncUnbanPunishmentModel', { + emitter: 'client', + event: 'guildBanRemove', + category: 'guild' + }); + } + + public override async exec(...[ban]: BushClientEvents['guildBanRemove']) { + const bans = await ActivePunishment.findAll({ + where: { + user: ban.user.id, + guild: ban.guild.id, + type: ActivePunishmentType.BAN + } + }); + for (const dbBan of bans) { + await dbBan.destroy(); + } + } +} diff --git a/src/listeners/member-custom/bushBan.ts b/src/listeners/member-custom/bushBan.ts new file mode 100644 index 0000000..1243071 --- /dev/null +++ b/src/listeners/member-custom/bushBan.ts @@ -0,0 +1,32 @@ +import { BushListener, type BushClientEvents } from '#lib'; +import { GuildMember, MessageEmbed } from 'discord.js'; + +export default class BushBanListener extends BushListener { + public constructor() { + super('bushBan', { + emitter: 'client', + event: 'bushBan', + category: 'member-custom' + }); + } + + public override async exec(...[victim, moderator, guild, reason, caseID, duration, dmSuccess]: BushClientEvents['bushBan']) { + const logChannel = await guild.getLogChannel('moderation'); + if (!logChannel) return; + const user = victim instanceof GuildMember ? victim.user : victim; + + const logEmbed = new MessageEmbed() + .setColor(util.colors.discord.RED) + .setTimestamp() + .setFooter({ text: `CaseID: ${caseID}` }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .addField('**Action**', `${duration ? 'Temp Ban' : 'Perm Ban'}`) + .addField('**User**', `${user} (${user.tag})`) + .addField('**Moderator**', `${moderator} (${moderator.tag})`) + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + .addField('**Reason**', `${reason || '[No Reason Provided]'}`); + if (duration) logEmbed.addField('**Duration**', util.humanizeDuration(duration)); + if (dmSuccess === false) logEmbed.addField('**Additional Info**', 'Could not dm user.'); + return await logChannel.send({ embeds: [logEmbed] }); + } +} diff --git a/src/listeners/member-custom/bushBlock.ts b/src/listeners/member-custom/bushBlock.ts new file mode 100644 index 0000000..8e8adb6 --- /dev/null +++ b/src/listeners/member-custom/bushBlock.ts @@ -0,0 +1,36 @@ +import { BushListener, type BushClientEvents } from '#lib'; +import { GuildMember, MessageEmbed } from 'discord.js'; + +export default class BushBlockListener extends BushListener { + public constructor() { + super('bushBlock', { + emitter: 'client', + event: 'bushBlock', + category: 'member-custom' + }); + } + + public override async exec( + ...[victim, moderator, guild, reason, caseID, duration, dmSuccess, channel]: BushClientEvents['bushBlock'] + ) { + const logChannel = await guild.getLogChannel('moderation'); + if (!logChannel) return; + const user = victim instanceof GuildMember ? victim.user : victim; + + const logEmbed = new MessageEmbed() + .setColor(util.colors.discord.PURPLE) + .setTimestamp() + .setFooter({ text: `CaseID: ${caseID}` }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .addField('**Action**', `${duration ? 'Temp Block' : 'Perm Block'}`) + .addField('**Channel**', `<#${channel.id}>`) + .addField('**User**', `${user} (${user.tag})`) + .addField('**Moderator**', `${moderator} (${moderator.tag})`) + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + .addField('**Reason**', `${reason || '[No Reason Provided]'}`); + + if (duration) logEmbed.addField('**Duration**', `${util.humanizeDuration(duration) || duration}`); + if (dmSuccess === false) logEmbed.addField('**Additional Info**', 'Could not dm user.'); + return await logChannel.send({ embeds: [logEmbed] }); + } +} diff --git a/src/listeners/member-custom/bushKick.ts b/src/listeners/member-custom/bushKick.ts new file mode 100644 index 0000000..26e9617 --- /dev/null +++ b/src/listeners/member-custom/bushKick.ts @@ -0,0 +1,31 @@ +import { BushListener, type BushClientEvents } from '#lib'; +import { GuildMember, MessageEmbed } from 'discord.js'; + +export default class BushKickListener extends BushListener { + public constructor() { + super('bushKick', { + emitter: 'client', + event: 'bushKick', + category: 'member-custom' + }); + } + + public override async exec(...[victim, moderator, guild, reason, caseID, dmSuccess]: BushClientEvents['bushKick']) { + const logChannel = await guild.getLogChannel('moderation'); + if (!logChannel) return; + const user = victim instanceof GuildMember ? victim.user : victim; + + const logEmbed = new MessageEmbed() + .setColor(util.colors.discord.RED) + .setTimestamp() + .setFooter({ text: `CaseID: ${caseID}` }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .addField('**Action**', `${'Kick'}`) + .addField('**User**', `${user} (${user.tag})`) + .addField('**Moderator**', `${moderator} (${moderator.tag})`) + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + .addField('**Reason**', `${reason || '[No Reason Provided]'}`); + if (dmSuccess === false) logEmbed.addField('**Additional Info**', 'Could not dm user.'); + return await logChannel.send({ embeds: [logEmbed] }); + } +} diff --git a/src/listeners/member-custom/bushLevelUpdate.ts b/src/listeners/member-custom/bushLevelUpdate.ts new file mode 100644 index 0000000..18b0fc2 --- /dev/null +++ b/src/listeners/member-custom/bushLevelUpdate.ts @@ -0,0 +1,28 @@ +import { BushListener, type BushClientEvents } from '#lib'; +import { type TextChannel } from 'discord.js'; + +export default class BushLevelUpdateListener extends BushListener { + public constructor() { + super('bushLevelUpdate', { + emitter: 'client', + event: 'bushLevelUpdate', + category: 'member-custom' + }); + } + + public override async exec(...[member, _oldLevel, newLevel, _currentXp, message]: BushClientEvents['bushLevelUpdate']) { + if (await message.guild.hasFeature('sendLevelUpMessages')) { + void (async () => { + const channel = ((await message.guild.channels + .fetch((await message.guild.getSetting('levelUpChannel')) ?? message.channelId) + .catch(() => null)) ?? message.channel) as TextChannel; + + const success = await channel + .send(`${util.format.input(member.user.tag)} leveled up to level ${util.format.input(`${newLevel}`)}.`) + .catch(() => null); + + if (!success) await client.console.warn('bushLevelUpdate', `Could not send level up message in ${message.guild}`); + })(); + } + } +} diff --git a/src/listeners/member-custom/bushMute.ts b/src/listeners/member-custom/bushMute.ts new file mode 100644 index 0000000..a8637fd --- /dev/null +++ b/src/listeners/member-custom/bushMute.ts @@ -0,0 +1,32 @@ +import { BushListener, type BushClientEvents } from '#lib'; +import { GuildMember, MessageEmbed } from 'discord.js'; + +export default class BushMuteListener extends BushListener { + public constructor() { + super('bushMute', { + emitter: 'client', + event: 'bushMute', + category: 'member-custom' + }); + } + + public override async exec(...[victim, moderator, guild, reason, caseID, duration, dmSuccess]: BushClientEvents['bushMute']) { + const logChannel = await guild.getLogChannel('moderation'); + if (!logChannel) return; + const user = victim instanceof GuildMember ? victim.user : victim; + + const logEmbed = new MessageEmbed() + .setColor(util.colors.discord.ORANGE) + .setTimestamp() + .setFooter({ text: `CaseID: ${caseID}` }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .addField('**Action**', `${duration ? 'Temp Mute' : 'Perm Mute'}`) + .addField('**User**', `${user} (${user.tag})`) + .addField('**Moderator**', `${moderator} (${moderator.tag})`) + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + .addField('**Reason**', `${reason || '[No Reason Provided]'}`); + if (duration) logEmbed.addField('**Duration**', `${util.humanizeDuration(duration) || duration}`); + if (dmSuccess === false) logEmbed.addField('**Additional Info**', 'Could not dm user.'); + return await logChannel.send({ embeds: [logEmbed] }); + } +} diff --git a/src/listeners/member-custom/bushPunishRole.ts b/src/listeners/member-custom/bushPunishRole.ts new file mode 100644 index 0000000..731403b --- /dev/null +++ b/src/listeners/member-custom/bushPunishRole.ts @@ -0,0 +1,31 @@ +import { BushListener, type BushClientEvents } from '#lib'; +import { GuildMember, MessageEmbed } from 'discord.js'; + +export default class BushPunishRoleListener extends BushListener { + public constructor() { + super('bushPunishRole', { + emitter: 'client', + event: 'bushPunishRole', + category: 'member-custom' + }); + } + + public override async exec(...[victim, moderator, guild, reason, caseID, duration]: BushClientEvents['bushPunishRole']) { + const logChannel = await guild.getLogChannel('moderation'); + if (!logChannel) return; + const user = victim instanceof GuildMember ? victim.user : victim; + + const logEmbed = new MessageEmbed() + .setColor(util.colors.discord.YELLOW) + .setTimestamp() + .setFooter({ text: `CaseID: ${caseID}` }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .addField('**Action**', `${duration ? 'Temp Punishment Role' : 'Perm Punishment Role'}`) + .addField('**User**', `${user} (${user.tag})`) + .addField('**Moderator**', `${moderator} (${moderator.tag})`) + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + .addField('**Reason**', `${reason || '[No Reason Provided]'}`); + if (duration) logEmbed.addField('**Duration**', util.humanizeDuration(duration)); + return await logChannel.send({ embeds: [logEmbed] }); + } +} diff --git a/src/listeners/member-custom/bushPunishRoleRemove.ts b/src/listeners/member-custom/bushPunishRoleRemove.ts new file mode 100644 index 0000000..7d88ec8 --- /dev/null +++ b/src/listeners/member-custom/bushPunishRoleRemove.ts @@ -0,0 +1,32 @@ +import { BushListener, type BushClientEvents } from '#lib'; +import { GuildMember, MessageEmbed } from 'discord.js'; + +export default class BushPunishRoleRemoveListener extends BushListener { + public constructor() { + super('bushPunishRoleRemove', { + emitter: 'client', + event: 'bushPunishRoleRemove', + category: 'member-custom' + }); + } + + public override async exec(...[victim, moderator, guild, reason, caseID, role]: BushClientEvents['bushPunishRoleRemove']) { + const logChannel = await guild.getLogChannel('moderation'); + if (!logChannel) return; + const user = victim instanceof GuildMember ? victim.user : victim; + + const logEmbed = new MessageEmbed() + .setColor(util.colors.discord.GREEN) + .setTimestamp() + .setFooter({ text: `CaseID: ${caseID}` }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .addField('**Action**', `${'Remove Punishment Role'}`) + .addField('**Role**', `${role}`) + .addField('**User**', `${user} (${user.tag})`) + .addField('**Moderator**', `${moderator} (${moderator.tag})`) + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + .addField('**Reason**', `${reason || '[No Reason Provided]'}`); + + return await logChannel.send({ embeds: [logEmbed] }); + } +} diff --git a/src/listeners/member-custom/bushPurge.ts b/src/listeners/member-custom/bushPurge.ts new file mode 100644 index 0000000..8a1e0c5 --- /dev/null +++ b/src/listeners/member-custom/bushPurge.ts @@ -0,0 +1,40 @@ +import { BushListener, type BushClientEvents } from '#lib'; +import { MessageEmbed } from 'discord.js'; + +export default class BushPurgeListener extends BushListener { + public constructor() { + super('bushPurge', { + emitter: 'client', + event: 'bushPurge', + category: 'member-custom' + }); + } + + public override async exec(...[moderator, guild, channel, messages]: BushClientEvents['bushPurge']) { + const logChannel = await guild.getLogChannel('moderation'); + if (!logChannel) return; + + const mappedMessages = messages.map((m) => ({ + id: m.id, + author: `${m.author.tag} (${m.id})`, + content: m.content, + embeds: m.embeds, + attachments: [...m.attachments.values()] + })); + const haste = await util.inspectCleanRedactHaste(mappedMessages); + + const logEmbed = new MessageEmbed() + .setColor(util.colors.discord.DARK_PURPLE) + .setTimestamp() + .setFooter({ text: `${messages.size.toLocaleString()} Messages` }) + .setAuthor({ name: moderator.tag, iconURL: moderator.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .addField('**Action**', `${'Purge'}`) + .addField('**Moderator**', `${moderator} (${moderator.tag})`) + .addField('**Channel**', `<#${channel.id}> (${channel.name})`) + .addField( + '**Messages**', + `${haste.url ? `[haste](${haste.url})${haste.error ? `- ${haste.error}` : ''}` : `${util.emojis.error} ${haste.error}`}` + ); + return await logChannel.send({ embeds: [logEmbed] }); + } +} diff --git a/src/listeners/member-custom/bushUnban.ts b/src/listeners/member-custom/bushUnban.ts new file mode 100644 index 0000000..e7024ef --- /dev/null +++ b/src/listeners/member-custom/bushUnban.ts @@ -0,0 +1,31 @@ +import { BushListener, type BushClientEvents } from '#lib'; +import { GuildMember, MessageEmbed } from 'discord.js'; + +export default class BushUnbanListener extends BushListener { + public constructor() { + super('bushUnban', { + emitter: 'client', + event: 'bushUnban', + category: 'member-custom' + }); + } + + public override async exec(...[victim, moderator, guild, reason, caseID, dmSuccess]: BushClientEvents['bushUnban']) { + const logChannel = await guild.getLogChannel('moderation'); + if (!logChannel) return; + const user = victim instanceof GuildMember ? victim.user : victim; + + const logEmbed = new MessageEmbed() + .setColor(util.colors.discord.GREEN) + .setTimestamp() + .setFooter({ text: `CaseID: ${caseID}` }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .addField('**Action**', `${'Unban'}`) + .addField('**User**', `${user} (${user.tag})`) + .addField('**Moderator**', `${moderator} (${moderator.tag})`) + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + .addField('**Reason**', `${reason || '[No Reason Provided]'}`); + if (dmSuccess === false) logEmbed.addField('**Additional Info**', 'Could not dm user.'); + return await logChannel.send({ embeds: [logEmbed] }); + } +} diff --git a/src/listeners/member-custom/bushUnblock.ts b/src/listeners/member-custom/bushUnblock.ts new file mode 100644 index 0000000..e313025 --- /dev/null +++ b/src/listeners/member-custom/bushUnblock.ts @@ -0,0 +1,32 @@ +import { BushListener, type BushClientEvents } from '#lib'; +import { GuildMember, MessageEmbed } from 'discord.js'; + +export default class BushUnblockListener extends BushListener { + public constructor() { + super('bushUnblock', { + emitter: 'client', + event: 'bushUnblock', + category: 'member-custom' + }); + } + + public override async exec(...[victim, moderator, guild, reason, caseID, dmSuccess, channel]: BushClientEvents['bushUnblock']) { + const logChannel = await guild.getLogChannel('moderation'); + if (!logChannel) return; + const user = victim instanceof GuildMember ? victim.user : victim; + + const logEmbed = new MessageEmbed() + .setColor(util.colors.discord.GREEN) + .setTimestamp() + .setFooter({ text: `CaseID: ${caseID}` }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .addField('**Action**', `${'Unblock'}`) + .addField('**Channel**', `<#${channel.id}>`) + .addField('**User**', `${user} (${user.tag})`) + .addField('**Moderator**', `${moderator} (${moderator.tag})`) + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + .addField('**Reason**', `${reason || '[No Reason Provided]'}`); + if (dmSuccess === false) logEmbed.addField('**Additional Info**', 'Could not dm user.'); + return await logChannel.send({ embeds: [logEmbed] }); + } +} diff --git a/src/listeners/member-custom/bushUnmute.ts b/src/listeners/member-custom/bushUnmute.ts new file mode 100644 index 0000000..4fa808f --- /dev/null +++ b/src/listeners/member-custom/bushUnmute.ts @@ -0,0 +1,31 @@ +import { BushListener, type BushClientEvents } from '#lib'; +import { GuildMember, MessageEmbed } from 'discord.js'; + +export default class BushUnmuteListener extends BushListener { + public constructor() { + super('bushUnmute', { + emitter: 'client', + event: 'bushUnmute', + category: 'member-custom' + }); + } + + public override async exec(...[victim, moderator, guild, reason, caseID, dmSuccess]: BushClientEvents['bushUnmute']) { + const logChannel = await guild.getLogChannel('moderation'); + if (!logChannel) return; + const user = victim instanceof GuildMember ? victim.user : victim; + + const logEmbed = new MessageEmbed() + .setColor(util.colors.discord.GREEN) + .setTimestamp() + .setFooter({ text: `CaseID: ${caseID}` }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .addField('**Action**', `${'Unmute'}`) + .addField('**User**', `${user} (${user.tag})`) + .addField('**Moderator**', `${moderator} (${moderator.tag})`) + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + .addField('**Reason**', `${reason || '[No Reason Provided]'}`); + if (dmSuccess === false) logEmbed.addField('**Additional Info**', 'Could not dm user.'); + return await logChannel.send({ embeds: [logEmbed] }); + } +} diff --git a/src/listeners/member-custom/bushUpdateModlog.ts b/src/listeners/member-custom/bushUpdateModlog.ts new file mode 100644 index 0000000..46910b9 --- /dev/null +++ b/src/listeners/member-custom/bushUpdateModlog.ts @@ -0,0 +1,33 @@ +import { BushListener, type BushClientEvents } from '#lib'; +import { MessageEmbed } from 'discord.js'; + +export default class BushUpdateModlogListener extends BushListener { + public constructor() { + super('bushUpdateModlog', { + emitter: 'client', + event: 'bushUpdateModlog', + category: 'member-custom' + }); + } + + public override async exec(...[moderator, modlogID, key, oldModlog, newModlog]: BushClientEvents['bushUpdateModlog']) { + const logChannel = await moderator.guild.getLogChannel('moderation'); + if (!logChannel) return; + + const logEmbed = new MessageEmbed() + .setColor(util.colors.discord.BLURPLE) + .setTimestamp() + .setAuthor({ + name: moderator.user.tag, + iconURL: moderator.user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined + }) + .addField('**Action**', `${'Update Modlog'}`) + .addField('**Moderator**', `${moderator} (${moderator.user.tag})`) + .addField('**ModLog Changed**', modlogID) + .addField('**Value Changed**', key) + .addField('**Old Value**', await util.inspectCleanRedactCodeblock(oldModlog, undefined, undefined, 1024)) + .addField('**New Value**', await util.inspectCleanRedactCodeblock(newModlog, undefined, undefined, 1024)); + + return await logChannel.send({ embeds: [logEmbed] }); + } +} diff --git a/src/listeners/member-custom/bushUpdateSettings.ts b/src/listeners/member-custom/bushUpdateSettings.ts new file mode 100644 index 0000000..6a9c3d8 --- /dev/null +++ b/src/listeners/member-custom/bushUpdateSettings.ts @@ -0,0 +1,33 @@ +import { BushListener, type BushClientEvents } from '#lib'; +import { MessageEmbed } from 'discord.js'; + +export default class BushUpdateSettingsListener extends BushListener { + public constructor() { + super('bushUpdateSettings', { + emitter: 'client', + event: 'bushUpdateSettings', + category: 'member-custom' + }); + } + + public override async exec(...[setting, guild, oldSettings, newSettings, moderator]: BushClientEvents['bushUpdateSettings']) { + const logChannel = await guild.getLogChannel('moderation'); + if (!logChannel) return; + + const logEmbed = new MessageEmbed().setColor(util.colors.discord.BLURPLE).setTimestamp(); + + if (moderator) + logEmbed.setAuthor({ + name: moderator.user.tag, + iconURL: moderator.user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined + }); + logEmbed.addField('**Action**', `${'Update Settings'}`); + if (moderator) logEmbed.addField('**Moderator**', `${moderator} (${moderator.user.tag})`); + logEmbed + .addField('**Setting Changed**', setting) + .addField('**Old Value**', await util.inspectCleanRedactCodeblock(oldSettings, 'js', undefined, 1024)) + .addField('**New Value**', await util.inspectCleanRedactCodeblock(newSettings, 'js', undefined, 1024)); + + return await logChannel.send({ embeds: [logEmbed] }); + } +} diff --git a/src/listeners/member-custom/bushWarn.ts b/src/listeners/member-custom/bushWarn.ts new file mode 100644 index 0000000..dba9fd8 --- /dev/null +++ b/src/listeners/member-custom/bushWarn.ts @@ -0,0 +1,31 @@ +import { BushListener, type BushClientEvents } from '#lib'; +import { GuildMember, MessageEmbed } from 'discord.js'; + +export default class BushWarnListener extends BushListener { + public constructor() { + super('bushWarn', { + emitter: 'client', + event: 'bushWarn', + category: 'member-custom' + }); + } + + public override async exec(...[victim, moderator, guild, reason, caseID, dmSuccess]: BushClientEvents['bushWarn']) { + const logChannel = await guild.getLogChannel('moderation'); + if (!logChannel) return; + const user = victim instanceof GuildMember ? victim.user : victim; + + const logEmbed = new MessageEmbed() + .setColor(util.colors.discord.YELLOW) + .setTimestamp() + .setFooter({ text: `CaseID: ${caseID}` }) + .setAuthor({ name: user.tag, iconURL: user.avatarURL({ dynamic: true, format: 'png', size: 4096 }) ?? undefined }) + .addField('**Action**', `${'Warn'}`) + .addField('**User**', `${user} (${user.tag})`) + .addField('**Moderator**', `${moderator} (${moderator.tag})`) + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + .addField('**Reason**', `${reason || '[No Reason Provided]'}`); + if (dmSuccess === false) logEmbed.addField('**Additional Info**', 'Could not dm user.'); + return await logChannel.send({ embeds: [logEmbed] }); + } +} diff --git a/src/tasks/removeExpiredPunishements.ts b/src/tasks/removeExpiredPunishements.ts index 2b89f3d..3c18ebc 100644 --- a/src/tasks/removeExpiredPunishements.ts +++ b/src/tasks/removeExpiredPunishements.ts @@ -1,4 +1,5 @@ import { ActivePunishment, ActivePunishmentType, BushTask, type BushGuild, type BushUser } from '#lib'; +import assert from 'assert'; const { Op } = (await import('sequelize')).default; export default class RemoveExpiredPunishmentsTask extends BushTask { @@ -32,7 +33,7 @@ export default class RemoveExpiredPunishmentsTask extends BushTask { switch (entry.type) { case ActivePunishmentType.BAN: { - if (!user) throw new Error(`user is undefined`); + assert(user); const result = await guild.bushUnban({ user: user, reason: 'Punishment expired.' }); if (['success', 'user not banned'].includes(result)) await entry.destroy(); else throw new Error(result); @@ -40,7 +41,14 @@ export default class RemoveExpiredPunishmentsTask extends BushTask { break; } case ActivePunishmentType.BLOCK: { - //todo once blocks are added + if (!member) { + await entry.destroy(); // channel overrides are removed when the member leaves the guild + continue; + } + const result = await member.unblock({ reason: 'Punishment expired.', channel: entry.extraInfo }); + if (['success', 'user not blocked'].includes(result)) await entry.destroy(); + else throw new Error(result); + void client.logger.verbose(`removeExpiredPunishments`, `Unblocked ${entry.user}.`); break; } case ActivePunishmentType.MUTE: { -- cgit