blob: 4cffab722e6e56498e609b0b61d436dadef35e2e [file] [log] [blame]
PineaFan0d06edc2023-01-17 22:10:31 +00001import { LoadingEmbed } from "../../../utils/defaults.js";
Skyler Greyda16adf2023-03-05 10:22:12 +00002import Discord, {
3 CommandInteraction,
4 ActionRowBuilder,
5 ChannelSelectMenuBuilder,
6 ChannelType,
7 ButtonBuilder,
8 ButtonStyle,
9 StringSelectMenuBuilder,
10 StringSelectMenuOptionBuilder,
11 ButtonInteraction,
12 StringSelectMenuInteraction,
13 ChannelSelectMenuInteraction,
14 APIMessageComponentEmoji
15} from "discord.js";
TheCodedProf01cba762023-02-18 15:55:05 -050016import type { SlashCommandSubcommandBuilder } from "discord.js";
pineafan63fc5e22022-08-04 22:04:10 +010017import client from "../../../utils/client.js";
TheCodedProf01cba762023-02-18 15:55:05 -050018import compare from "lodash";
pineafan41d93562022-07-30 22:10:15 +010019import { toHexArray, toHexInteger } from "../../../utils/calculate.js";
TheCodedProf01cba762023-02-18 15:55:05 -050020import EmojiEmbed from "../../../utils/generateEmojiEmbed.js";
21import getEmojiByName from "../../../utils/getEmojiByName.js";
pineafan41d93562022-07-30 22:10:15 +010022
PineaFan638eb132023-01-19 10:41:22 +000023const logs: Record<string, string> = {
Skyler Grey75ea9172022-08-06 10:22:23 +010024 channelUpdate: "Channels created, deleted or modified",
25 emojiUpdate: "Server emojis modified",
26 stickerUpdate: "Server stickers modified",
27 guildUpdate: "Server settings updated",
28 guildMemberUpdate: "Member updated (i.e. nickname)",
29 guildMemberPunish: "Members punished (i.e. muted, banned, kicked)",
30 guildRoleUpdate: "Role settings changed",
31 guildInviteUpdate: "Server invite created or deleted",
32 messageUpdate: "Message edited",
33 messageDelete: "Message deleted",
34 messageDeleteBulk: "Messages purged",
35 messageReactionUpdate: "Message reactions cleared",
36 messageMassPing: "Message pings multiple members at once",
37 messageAnnounce: "Message published in announcement channel",
38 threadUpdate: "Thread created or deleted",
39 webhookUpdate: "Webhooks created or deleted",
40 guildMemberVerify: "Member runs verify",
41 autoModeratorDeleted: "Messages auto deleted by Nucleus",
Skyler Greyda16adf2023-03-05 10:22:12 +000042 ticketUpdate: "Tickets created or deleted"
TheCodedProf01cba762023-02-18 15:55:05 -050043 //nucleusSettingsUpdated: "Nucleus' settings updated by a moderator" // TODO
pineafan63fc5e22022-08-04 22:04:10 +010044};
pineafan4f164f32022-02-26 22:07:12 +000045
46const command = (builder: SlashCommandSubcommandBuilder) =>
Skyler Greyda16adf2023-03-05 10:22:12 +000047 builder.setName("events").setDescription("The general log channel for the server, and setting what events to show");
pineafan4f164f32022-02-26 22:07:12 +000048
TheCodedProf1f675042023-02-16 17:01:29 -050049const callback = async (interaction: CommandInteraction): Promise<void> => {
TheCodedProf01cba762023-02-18 15:55:05 -050050 const m = (await interaction.reply({
Skyler Grey75ea9172022-08-06 10:22:23 +010051 embeds: LoadingEmbed,
TheCodedProf01cba762023-02-18 15:55:05 -050052 ephemeral: true,
53 fetchReply: true
54 })) as Discord.Message;
55
56 let config = await client.database.guilds.read(interaction.guild!.id);
57 let data = Object.assign({}, config.logging.logs);
58 let closed = false;
59 let show = false;
Skyler Greyad002172022-08-16 18:48:26 +010060 do {
Skyler Greyda16adf2023-03-05 10:22:12 +000061 const channelMenu = new ActionRowBuilder<ChannelSelectMenuBuilder>().addComponents(
62 new ChannelSelectMenuBuilder()
63 .setCustomId("channel")
64 .setPlaceholder("Select a channel")
65 .setChannelTypes(ChannelType.GuildText)
66 );
67 const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
68 new ButtonBuilder()
69 .setCustomId("switch")
70 .setLabel(data.enabled ? "Enabled" : "Disabled")
71 .setStyle(data.enabled ? ButtonStyle.Success : ButtonStyle.Danger)
72 .setEmoji(
73 getEmojiByName(data.enabled ? "CONTROL.TICK" : "CONTROL.CROSS", "id") as APIMessageComponentEmoji
74 ),
75 new ButtonBuilder()
76 .setCustomId("remove")
77 .setLabel("Remove")
78 .setStyle(ButtonStyle.Danger)
79 .setDisabled(!data.channel),
80 new ButtonBuilder().setCustomId("show").setLabel("Manage Events").setStyle(ButtonStyle.Primary),
81 new ButtonBuilder()
82 .setCustomId("save")
83 .setLabel("Save")
84 .setStyle(ButtonStyle.Success)
85 .setDisabled(compare.isEqual(data, config.logging.logs))
86 );
TheCodedProf01cba762023-02-18 15:55:05 -050087
88 const converted = toHexArray(data.toLog);
Skyler Greyda16adf2023-03-05 10:22:12 +000089 const toLogMenu = new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
90 new StringSelectMenuBuilder()
91 .setPlaceholder("Set events to log")
92 .setMaxValues(Object.keys(logs).length)
93 .setCustomId("logs")
94 .setMinValues(0)
95 );
TheCodedProf01cba762023-02-18 15:55:05 -050096 Object.keys(logs).map((e) => {
97 toLogMenu.components[0]!.addOptions(
Skyler Greyda16adf2023-03-05 10:22:12 +000098 new StringSelectMenuOptionBuilder().setLabel(logs[e]!).setValue(e).setDefault(converted.includes(e))
99 );
PineaFan638eb132023-01-19 10:41:22 +0000100 });
TheCodedProf01cba762023-02-18 15:55:05 -0500101
102 const embed = new EmojiEmbed()
103 .setTitle("General Log Channel")
104 .setStatus("Success")
105 .setEmoji("CHANNEL.TEXT.CREATE")
106 .setDescription(
107 `This is the channel that all events you set to be logged will be stored\n` +
Skyler Greyda16adf2023-03-05 10:22:12 +0000108 `**Channel:** ${data.channel ? `<#${data.channel}>` : "None"}\n`
109 );
TheCodedProf01cba762023-02-18 15:55:05 -0500110
Skyler Greyda16adf2023-03-05 10:22:12 +0000111 const components: ActionRowBuilder<ButtonBuilder | ChannelSelectMenuBuilder | StringSelectMenuBuilder>[] = [
112 channelMenu,
113 buttons
114 ];
115 if (show) components.push(toLogMenu);
TheCodedProf01cba762023-02-18 15:55:05 -0500116
117 await interaction.editReply({
118 embeds: [embed],
119 components: components
120 });
121
122 let i: ButtonInteraction | StringSelectMenuInteraction | ChannelSelectMenuInteraction;
pineafan41d93562022-07-30 22:10:15 +0100123 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000124 i = (await m.awaitMessageComponent({
TheCodedProf01cba762023-02-18 15:55:05 -0500125 filter: (i) => i.user.id === interaction.user.id,
126 time: 300000
Skyler Greyda16adf2023-03-05 10:22:12 +0000127 })) as ButtonInteraction | StringSelectMenuInteraction | ChannelSelectMenuInteraction;
pineafan41d93562022-07-30 22:10:15 +0100128 } catch (e) {
TheCodedProf01cba762023-02-18 15:55:05 -0500129 closed = true;
TheCodedProf1807fb32023-02-20 14:33:48 -0500130 continue;
pineafan41d93562022-07-30 22:10:15 +0100131 }
Skyler Greyad002172022-08-16 18:48:26 +0100132
TheCodedProf01cba762023-02-18 15:55:05 -0500133 await i.deferUpdate();
134
Skyler Greyda16adf2023-03-05 10:22:12 +0000135 if (i.isButton()) {
136 switch (i.customId) {
TheCodedProf01cba762023-02-18 15:55:05 -0500137 case "show": {
138 show = !show;
139 break;
140 }
141 case "switch": {
142 data.enabled = !data.enabled;
143 break;
144 }
145 case "save": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000146 await client.database.guilds.write(interaction.guild!.id, { "logging.logs": data });
TheCodedProf01cba762023-02-18 15:55:05 -0500147 config = await client.database.guilds.read(interaction.guild!.id);
148 data = Object.assign({}, config.logging.logs);
Skyler Greyda16adf2023-03-05 10:22:12 +0000149 await client.memory.forceUpdate(interaction.guild!.id);
TheCodedProf01cba762023-02-18 15:55:05 -0500150 break;
151 }
152 case "remove": {
153 data.channel = null;
154 break;
155 }
156 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000157 } else if (i.isStringSelectMenu()) {
TheCodedProf1807fb32023-02-20 14:33:48 -0500158 const hex = toHexInteger(i.values);
TheCodedProf01cba762023-02-18 15:55:05 -0500159 data.toLog = hex;
Skyler Greyda16adf2023-03-05 10:22:12 +0000160 } else if (i.isChannelSelectMenu()) {
TheCodedProf01cba762023-02-18 15:55:05 -0500161 data.channel = i.values[0]!;
162 }
TheCodedProf01cba762023-02-18 15:55:05 -0500163 } while (!closed);
Skyler Greyda16adf2023-03-05 10:22:12 +0000164 await interaction.deleteReply();
pineafan63fc5e22022-08-04 22:04:10 +0100165};
pineafan4f164f32022-02-26 22:07:12 +0000166
TheCodedProff86ba092023-01-27 17:10:07 -0500167const check = (interaction: CommandInteraction, _partial: boolean = false) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100168 const member = interaction.member as Discord.GuildMember;
PineaFan0d06edc2023-01-17 22:10:31 +0000169 if (!member.permissions.has("ManageGuild"))
170 return "You must have the *Manage Server* permission to use this command";
pineafan4f164f32022-02-26 22:07:12 +0000171 return true;
pineafan63fc5e22022-08-04 22:04:10 +0100172};
pineafan4f164f32022-02-26 22:07:12 +0000173
174export { command };
175export { callback };
Skyler Grey75ea9172022-08-06 10:22:23 +0100176export { check };