blob: 05d69289cdfd21eeb6e1817644f990730306fb9e [file] [log] [blame]
PineaFan0d06edc2023-01-17 22:10:31 +00001import { LoadingEmbed } from "../../../utils/defaults.js";
TheCodedProf01cba762023-02-18 15:55:05 -05002import Discord, { CommandInteraction, ActionRowBuilder, ChannelSelectMenuBuilder, ChannelType, ButtonBuilder, ButtonStyle, StringSelectMenuBuilder, StringSelectMenuOptionBuilder, ButtonInteraction, StringSelectMenuInteraction, ChannelSelectMenuInteraction, APIMessageComponentEmoji } from "discord.js";
3import type { SlashCommandSubcommandBuilder } from "discord.js";
pineafan63fc5e22022-08-04 22:04:10 +01004import client from "../../../utils/client.js";
TheCodedProf01cba762023-02-18 15:55:05 -05005import compare from "lodash";
pineafan41d93562022-07-30 22:10:15 +01006import { toHexArray, toHexInteger } from "../../../utils/calculate.js";
TheCodedProf01cba762023-02-18 15:55:05 -05007import EmojiEmbed from "../../../utils/generateEmojiEmbed.js";
8import getEmojiByName from "../../../utils/getEmojiByName.js";
pineafan41d93562022-07-30 22:10:15 +01009
PineaFan638eb132023-01-19 10:41:22 +000010const logs: Record<string, string> = {
Skyler Grey75ea9172022-08-06 10:22:23 +010011 channelUpdate: "Channels created, deleted or modified",
12 emojiUpdate: "Server emojis modified",
13 stickerUpdate: "Server stickers modified",
14 guildUpdate: "Server settings updated",
15 guildMemberUpdate: "Member updated (i.e. nickname)",
16 guildMemberPunish: "Members punished (i.e. muted, banned, kicked)",
17 guildRoleUpdate: "Role settings changed",
18 guildInviteUpdate: "Server invite created or deleted",
19 messageUpdate: "Message edited",
20 messageDelete: "Message deleted",
21 messageDeleteBulk: "Messages purged",
22 messageReactionUpdate: "Message reactions cleared",
23 messageMassPing: "Message pings multiple members at once",
24 messageAnnounce: "Message published in announcement channel",
25 threadUpdate: "Thread created or deleted",
26 webhookUpdate: "Webhooks created or deleted",
27 guildMemberVerify: "Member runs verify",
28 autoModeratorDeleted: "Messages auto deleted by Nucleus",
TheCodedProf01cba762023-02-18 15:55:05 -050029 ticketUpdate: "Tickets created or deleted",
30 //nucleusSettingsUpdated: "Nucleus' settings updated by a moderator" // TODO
pineafan63fc5e22022-08-04 22:04:10 +010031};
pineafan4f164f32022-02-26 22:07:12 +000032
33const command = (builder: SlashCommandSubcommandBuilder) =>
TheCodedProf01cba762023-02-18 15:55:05 -050034 builder
35 .setName("events")
36 .setDescription("The general log channel for the server, and setting what events to show")
pineafan4f164f32022-02-26 22:07:12 +000037
TheCodedProf1f675042023-02-16 17:01:29 -050038const callback = async (interaction: CommandInteraction): Promise<void> => {
TheCodedProf01cba762023-02-18 15:55:05 -050039 const m = (await interaction.reply({
Skyler Grey75ea9172022-08-06 10:22:23 +010040 embeds: LoadingEmbed,
TheCodedProf01cba762023-02-18 15:55:05 -050041 ephemeral: true,
42 fetchReply: true
43 })) as Discord.Message;
44
45 let config = await client.database.guilds.read(interaction.guild!.id);
46 let data = Object.assign({}, config.logging.logs);
47 let closed = false;
48 let show = false;
Skyler Greyad002172022-08-16 18:48:26 +010049 do {
TheCodedProf01cba762023-02-18 15:55:05 -050050 const channelMenu = new ActionRowBuilder<ChannelSelectMenuBuilder>()
51 .addComponents(
52 new ChannelSelectMenuBuilder()
53 .setCustomId("channel")
54 .setPlaceholder("Select a channel")
55 .setChannelTypes(ChannelType.GuildText)
56 )
57 const buttons = new ActionRowBuilder<ButtonBuilder>()
58 .addComponents(
59 new ButtonBuilder()
60 .setCustomId("switch")
61 .setLabel(data.enabled ? "Enabled" : "Disabled")
62 .setStyle(data.enabled ? ButtonStyle.Success : ButtonStyle.Danger)
63 .setEmoji(getEmojiByName((data.enabled ? "CONTROL.TICK" : "CONTROL.CROSS"), "id") as APIMessageComponentEmoji),
64 new ButtonBuilder()
65 .setCustomId("remove")
66 .setLabel("Remove")
67 .setStyle(ButtonStyle.Danger)
68 .setDisabled(!data.channel),
69 new ButtonBuilder()
70 .setCustomId("show")
71 .setLabel("Manage Events")
72 .setStyle(ButtonStyle.Primary),
73 new ButtonBuilder()
74 .setCustomId("save")
75 .setLabel("Save")
76 .setStyle(ButtonStyle.Success)
77 .setDisabled(compare.isEqual(data, config.logging.logs))
78 )
79
80 const converted = toHexArray(data.toLog);
81 const toLogMenu = new ActionRowBuilder<StringSelectMenuBuilder>()
82 .addComponents(
83 new StringSelectMenuBuilder()
84 .setPlaceholder("Set events to log")
85 .setMaxValues(Object.keys(logs).length)
86 .setCustomId("logs")
87 .setMinValues(0)
88 )
89 Object.keys(logs).map((e) => {
90 toLogMenu.components[0]!.addOptions(
91 new StringSelectMenuOptionBuilder()
92 .setLabel(logs[e]!)
93 .setValue(e)
94 .setDefault(converted.includes(e))
PineaFan638eb132023-01-19 10:41:22 +000095 )
96 });
TheCodedProf01cba762023-02-18 15:55:05 -050097
98 const embed = new EmojiEmbed()
99 .setTitle("General Log Channel")
100 .setStatus("Success")
101 .setEmoji("CHANNEL.TEXT.CREATE")
102 .setDescription(
103 `This is the channel that all events you set to be logged will be stored\n` +
104 `**Channel:** ${data.channel ? `<#${data.channel}>` : "None"}\n`
105 )
106
TheCodedProf1807fb32023-02-20 14:33:48 -0500107 const components: ActionRowBuilder<ButtonBuilder | ChannelSelectMenuBuilder | StringSelectMenuBuilder>[] = [channelMenu, buttons];
TheCodedProf01cba762023-02-18 15:55:05 -0500108 if(show) components.push(toLogMenu);
109
110 await interaction.editReply({
111 embeds: [embed],
112 components: components
113 });
114
115 let i: ButtonInteraction | StringSelectMenuInteraction | ChannelSelectMenuInteraction;
pineafan41d93562022-07-30 22:10:15 +0100116 try {
PineaFan0d06edc2023-01-17 22:10:31 +0000117 i = await m.awaitMessageComponent({
TheCodedProf01cba762023-02-18 15:55:05 -0500118 filter: (i) => i.user.id === interaction.user.id,
119 time: 300000
120 }) as ButtonInteraction | StringSelectMenuInteraction | ChannelSelectMenuInteraction;
pineafan41d93562022-07-30 22:10:15 +0100121 } catch (e) {
TheCodedProf01cba762023-02-18 15:55:05 -0500122 closed = true;
TheCodedProf1807fb32023-02-20 14:33:48 -0500123 continue;
pineafan41d93562022-07-30 22:10:15 +0100124 }
Skyler Greyad002172022-08-16 18:48:26 +0100125
TheCodedProf01cba762023-02-18 15:55:05 -0500126 await i.deferUpdate();
127
128 if(i.isButton()) {
129 switch(i.customId) {
130 case "show": {
131 show = !show;
132 break;
133 }
134 case "switch": {
135 data.enabled = !data.enabled;
136 break;
137 }
138 case "save": {
139 await client.database.guilds.write(interaction.guild!.id, {"logging.logs": data});
140 config = await client.database.guilds.read(interaction.guild!.id);
141 data = Object.assign({}, config.logging.logs);
Skyler Grey16ecb172023-03-05 07:30:32 +0000142 await client.memory.forceUpdate(interaction.guild!.id)
TheCodedProf01cba762023-02-18 15:55:05 -0500143 break;
144 }
145 case "remove": {
146 data.channel = null;
147 break;
148 }
149 }
150 } else if(i.isStringSelectMenu()) {
TheCodedProf1807fb32023-02-20 14:33:48 -0500151 const hex = toHexInteger(i.values);
TheCodedProf01cba762023-02-18 15:55:05 -0500152 data.toLog = hex;
153 } else if(i.isChannelSelectMenu()) {
154 data.channel = i.values[0]!;
155 }
156
157 } while (!closed);
158 await interaction.deleteReply()
pineafan63fc5e22022-08-04 22:04:10 +0100159};
pineafan4f164f32022-02-26 22:07:12 +0000160
TheCodedProff86ba092023-01-27 17:10:07 -0500161const check = (interaction: CommandInteraction, _partial: boolean = false) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100162 const member = interaction.member as Discord.GuildMember;
PineaFan0d06edc2023-01-17 22:10:31 +0000163 if (!member.permissions.has("ManageGuild"))
164 return "You must have the *Manage Server* permission to use this command";
pineafan4f164f32022-02-26 22:07:12 +0000165 return true;
pineafan63fc5e22022-08-04 22:04:10 +0100166};
pineafan4f164f32022-02-26 22:07:12 +0000167
168export { command };
169export { callback };
Skyler Grey75ea9172022-08-06 10:22:23 +0100170export { check };