jillo-bot/src/commands/auditlog.ts

123 lines
3.6 KiB
TypeScript

import { ActionRowBuilder, ButtonBuilder, ButtonStyle, CommandInteraction, ComponentType, SlashCommandBuilder, StringSelectMenuBuilder } from 'discord.js';
import { Command } from '../types/index';
import { AuditLog, db } from '../lib/db';
import { EventType } from '../lib/events';
import { chunks } from '../lib/util';
export default {
data: new SlashCommandBuilder()
.setName('auditlog')
.setDescription('[ADMIN] Set up an audit logger, or edit an existing one')
.setDefaultMemberPermissions('0'),
execute: async (interaction: CommandInteraction) => {
if (!interaction.isChatInputCommand()) return;
const channel = interaction.channelId;
if (!channel) return;
const log = await db<AuditLog>('auditLogs')
.select('eventTypes')
.where('channel', channel)
.first();
let types = log ? log.eventTypes.split(',') : [];
const options = Object.values(EventType)
.map(event => ({
label: event,
value: event,
}));
const chunked = [...chunks(options, 25)];
const selectRows =
chunked.map(
(opt, i) => new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
new StringSelectMenuBuilder()
.addOptions(
...opt
)
.setMinValues(0)
.setMaxValues(opt.length)
.setCustomId(`auditlog-select-events-${i}`)
)
);
const components = [
...selectRows,
new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setCustomId('auditlog-select-events-done')
.setLabel('Done')
.setStyle(ButtonStyle.Primary)
.setDisabled(true)
),
];
const formatContent = () =>
`${log ? `Editing audit log in <#${channel}>` : `Creating audit log in <#${channel}>`}\n` +
'Select the types of events to be reported on' + ((types.length > 0) ? `\n**Current events**: ${types.map(s => '`' + s + '`').join(', ')}` : '');
const msg = await interaction.reply({
ephemeral: true,
content: formatContent(),
components,
});
const selectCollector = msg.createMessageComponentCollector({
componentType: ComponentType.StringSelect,
time: 60_000 * 5,
});
selectCollector.on('collect', async selectInteraction => {
const possibleTypes = selectInteraction.component.options.map(opt => opt.value);
const selectedTypes = selectInteraction.values;
types = types.filter(t => !possibleTypes.includes(t));
types = [...types, ...selectedTypes];
components[components.length - 1].components[0].setDisabled(types.length === 0);
await selectInteraction.reply({
content: 'Hit "Done" when finished',
ephemeral: true,
});
await msg.edit({
content: formatContent(),
components,
});
});
selectCollector.on('end', async () => {
await msg.edit({
content: formatContent(),
components: [],
});
});
const buttonInteraction = await msg.awaitMessageComponent({ componentType: ComponentType.Button, time: 60_000 * 5 });
selectCollector.stop();
if (log) {
await db<AuditLog>('auditLogs')
.where('channel', channel)
.update({
eventTypes: types.join(','),
});
} else {
await db<AuditLog>('auditLogs')
.insert({
guild: interaction.guildId!,
channel: channel,
eventTypes: types.join(','),
});
}
await buttonInteraction.reply({
content: 'Audit log successfully created.',
components: [],
ephemeral: true,
});
}
} satisfies Command;