| import { LoadingEmbed } from "../../../utils/defaults.js"; |
| import Discord, { CommandInteraction, ActionRowBuilder, ChannelSelectMenuBuilder, ChannelType, ButtonBuilder, ButtonStyle, StringSelectMenuBuilder, StringSelectMenuOptionBuilder, ButtonInteraction, StringSelectMenuInteraction, ChannelSelectMenuInteraction, APIMessageComponentEmoji } from "discord.js"; |
| import type { SlashCommandSubcommandBuilder } from "discord.js"; |
| import client from "../../../utils/client.js"; |
| import compare from "lodash"; |
| import { toHexArray, toHexInteger } from "../../../utils/calculate.js"; |
| import EmojiEmbed from "../../../utils/generateEmojiEmbed.js"; |
| import getEmojiByName from "../../../utils/getEmojiByName.js"; |
| |
| const logs: Record<string, string> = { |
| channelUpdate: "Channels created, deleted or modified", |
| emojiUpdate: "Server emojis modified", |
| stickerUpdate: "Server stickers modified", |
| guildUpdate: "Server settings updated", |
| guildMemberUpdate: "Member updated (i.e. nickname)", |
| guildMemberPunish: "Members punished (i.e. muted, banned, kicked)", |
| guildRoleUpdate: "Role settings changed", |
| guildInviteUpdate: "Server invite created or deleted", |
| messageUpdate: "Message edited", |
| messageDelete: "Message deleted", |
| messageDeleteBulk: "Messages purged", |
| messageReactionUpdate: "Message reactions cleared", |
| messageMassPing: "Message pings multiple members at once", |
| messageAnnounce: "Message published in announcement channel", |
| threadUpdate: "Thread created or deleted", |
| webhookUpdate: "Webhooks created or deleted", |
| guildMemberVerify: "Member runs verify", |
| autoModeratorDeleted: "Messages auto deleted by Nucleus", |
| ticketUpdate: "Tickets created or deleted", |
| //nucleusSettingsUpdated: "Nucleus' settings updated by a moderator" // TODO |
| }; |
| |
| const command = (builder: SlashCommandSubcommandBuilder) => |
| builder |
| .setName("events") |
| .setDescription("The general log channel for the server, and setting what events to show") |
| |
| const callback = async (interaction: CommandInteraction): Promise<void> => { |
| const m = (await interaction.reply({ |
| embeds: LoadingEmbed, |
| ephemeral: true, |
| fetchReply: true |
| })) as Discord.Message; |
| |
| let config = await client.database.guilds.read(interaction.guild!.id); |
| let data = Object.assign({}, config.logging.logs); |
| let closed = false; |
| let show = false; |
| do { |
| const channelMenu = new ActionRowBuilder<ChannelSelectMenuBuilder>() |
| .addComponents( |
| new ChannelSelectMenuBuilder() |
| .setCustomId("channel") |
| .setPlaceholder("Select a channel") |
| .setChannelTypes(ChannelType.GuildText) |
| ) |
| const buttons = new ActionRowBuilder<ButtonBuilder>() |
| .addComponents( |
| new ButtonBuilder() |
| .setCustomId("switch") |
| .setLabel(data.enabled ? "Enabled" : "Disabled") |
| .setStyle(data.enabled ? ButtonStyle.Success : ButtonStyle.Danger) |
| .setEmoji(getEmojiByName((data.enabled ? "CONTROL.TICK" : "CONTROL.CROSS"), "id") as APIMessageComponentEmoji), |
| new ButtonBuilder() |
| .setCustomId("remove") |
| .setLabel("Remove") |
| .setStyle(ButtonStyle.Danger) |
| .setDisabled(!data.channel), |
| new ButtonBuilder() |
| .setCustomId("show") |
| .setLabel("Manage Events") |
| .setStyle(ButtonStyle.Primary), |
| new ButtonBuilder() |
| .setCustomId("save") |
| .setLabel("Save") |
| .setStyle(ButtonStyle.Success) |
| .setDisabled(compare.isEqual(data, config.logging.logs)) |
| ) |
| |
| const converted = toHexArray(data.toLog); |
| const toLogMenu = new ActionRowBuilder<StringSelectMenuBuilder>() |
| .addComponents( |
| new StringSelectMenuBuilder() |
| .setPlaceholder("Set events to log") |
| .setMaxValues(Object.keys(logs).length) |
| .setCustomId("logs") |
| .setMinValues(0) |
| ) |
| Object.keys(logs).map((e) => { |
| toLogMenu.components[0]!.addOptions( |
| new StringSelectMenuOptionBuilder() |
| .setLabel(logs[e]!) |
| .setValue(e) |
| .setDefault(converted.includes(e)) |
| ) |
| }); |
| |
| const embed = new EmojiEmbed() |
| .setTitle("General Log Channel") |
| .setStatus("Success") |
| .setEmoji("CHANNEL.TEXT.CREATE") |
| .setDescription( |
| `This is the channel that all events you set to be logged will be stored\n` + |
| `**Channel:** ${data.channel ? `<#${data.channel}>` : "None"}\n` |
| ) |
| |
| let components: ActionRowBuilder<ButtonBuilder | ChannelSelectMenuBuilder | StringSelectMenuBuilder>[] = [channelMenu, buttons]; |
| if(show) components.push(toLogMenu); |
| |
| await interaction.editReply({ |
| embeds: [embed], |
| components: components |
| }); |
| |
| let i: ButtonInteraction | StringSelectMenuInteraction | ChannelSelectMenuInteraction; |
| try { |
| i = await m.awaitMessageComponent({ |
| filter: (i) => i.user.id === interaction.user.id, |
| time: 300000 |
| }) as ButtonInteraction | StringSelectMenuInteraction | ChannelSelectMenuInteraction; |
| } catch (e) { |
| closed = true; |
| break; |
| } |
| |
| await i.deferUpdate(); |
| |
| if(i.isButton()) { |
| switch(i.customId) { |
| case "show": { |
| show = !show; |
| break; |
| } |
| case "switch": { |
| data.enabled = !data.enabled; |
| break; |
| } |
| case "save": { |
| await client.database.guilds.write(interaction.guild!.id, {"logging.logs": data}); |
| config = await client.database.guilds.read(interaction.guild!.id); |
| data = Object.assign({}, config.logging.logs); |
| break; |
| } |
| case "remove": { |
| data.channel = null; |
| break; |
| } |
| } |
| } else if(i.isStringSelectMenu()) { |
| let hex = toHexInteger(i.values); |
| data.toLog = hex; |
| } else if(i.isChannelSelectMenu()) { |
| data.channel = i.values[0]!; |
| } |
| |
| } while (!closed); |
| await interaction.deleteReply() |
| }; |
| |
| const check = (interaction: CommandInteraction, _partial: boolean = false) => { |
| const member = interaction.member as Discord.GuildMember; |
| if (!member.permissions.has("ManageGuild")) |
| return "You must have the *Manage Server* permission to use this command"; |
| return true; |
| }; |
| |
| export { command }; |
| export { callback }; |
| export { check }; |