blob: f8a57b702f998f580ba5de7ee2ef8005f2a978c5 [file] [log] [blame]
PineaFan0d06edc2023-01-17 22:10:31 +00001import { LoadingEmbed } from "../../utils/defaults.js";
TheCodedProff4facde2023-01-28 13:42:48 -05002import Discord, { CommandInteraction, Message, ActionRowBuilder, StringSelectMenuBuilder, ButtonBuilder, ButtonStyle, StringSelectMenuOptionBuilder, APIMessageComponentEmoji, TextInputBuilder, StringSelectMenuInteraction, ButtonInteraction, MessageComponentInteraction, ChannelSelectMenuBuilder, ChannelSelectMenuInteraction, ModalBuilder } from "discord.js";
pineafan0bc04162022-07-25 17:22:26 +01003import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
TheCodedProff86ba092023-01-27 17:10:07 -05004import type { SlashCommandSubcommandBuilder } from "discord.js";
pineafan0bc04162022-07-25 17:22:26 +01005import client from "../../utils/client.js";
pineafan63fc5e22022-08-04 22:04:10 +01006import convertCurlyBracketString from "../../utils/convertCurlyBracketString.js";
pineafan63fc5e22022-08-04 22:04:10 +01007import singleNotify from "../../utils/singleNotify.js";
TheCodedProf4a6d5712023-01-19 15:54:40 -05008import getEmojiByName from "../../utils/getEmojiByName.js";
9import createPageIndicator from "../../utils/createPageIndicator.js";
10import { modalInteractionCollector } from "../../utils/dualCollector.js";
TheCodedProfc2acbcc2023-01-20 17:23:51 -050011
pineafan708692b2022-07-24 22:16:22 +010012
13const command = (builder: SlashCommandSubcommandBuilder) =>
14 builder
pineafan63fc5e22022-08-04 22:04:10 +010015 .setName("stats")
Skyler Grey11236ba2022-08-08 21:13:33 +010016 .setDescription("Controls channels which update when someone joins or leaves the server")
pineafan708692b2022-07-24 22:16:22 +010017
TheCodedProf4a6d5712023-01-19 15:54:40 -050018
TheCodedProf9bc84752023-01-21 05:19:57 -050019const showModal = async (interaction: MessageComponentInteraction, current: { enabled: boolean; name: string; }) => {
TheCodedProfc2acbcc2023-01-20 17:23:51 -050020 await interaction.showModal(
TheCodedProff4facde2023-01-28 13:42:48 -050021 new ModalBuilder()
TheCodedProfc2acbcc2023-01-20 17:23:51 -050022 .setCustomId("modal")
23 .setTitle(`Stats channel name`)
24 .addComponents(
25 new ActionRowBuilder<TextInputBuilder>().addComponents(
26 new TextInputBuilder()
27 .setCustomId("ex1")
28 .setLabel("Server Info (1/3)")
29 .setPlaceholder(
30 `{serverName} - This server's name\n\n` +
31 `These placeholders will be replaced with the server's name, etc..`
32 )
33 .setMaxLength(1)
34 .setRequired(false)
35 .setStyle(Discord.TextInputStyle.Paragraph)
36 ),
37 new ActionRowBuilder<TextInputBuilder>().addComponents(
38 new TextInputBuilder()
39 .setCustomId("ex2")
40 .setLabel("Member Counts (2/3) - {MemberCount:...}")
41 .setPlaceholder(
42 `{:all} - Total member count\n` +
43 `{:humans} - Total non-bot users\n` +
44 `{:bots} - Number of bots\n`
45 )
46 .setMaxLength(1)
47 .setRequired(false)
48 .setStyle(Discord.TextInputStyle.Paragraph)
49 ),
50 new ActionRowBuilder<TextInputBuilder>().addComponents(
51 new TextInputBuilder()
52 .setCustomId("ex3")
53 .setLabel("Latest Member (3/3) - {member:...}")
54 .setPlaceholder(
55 `{:name} - The members name\n`
56 )
57 .setMaxLength(1)
58 .setRequired(false)
59 .setStyle(Discord.TextInputStyle.Paragraph)
60 ),
61 new ActionRowBuilder<TextInputBuilder>().addComponents(
62 new TextInputBuilder()
63 .setCustomId("text")
64 .setLabel("Channel name input")
65 .setMaxLength(1000)
66 .setRequired(true)
67 .setStyle(Discord.TextInputStyle.Short)
68 .setValue(current.name)
69 )
70 )
71 );
TheCodedProf4a6d5712023-01-19 15:54:40 -050072}
73
TheCodedProf9bc84752023-01-21 05:19:57 -050074type ObjectSchema = Record<string, {name: string, enabled: boolean}>
75
TheCodedProf267563a2023-01-21 17:00:57 -050076
TheCodedProf9bc84752023-01-21 05:19:57 -050077
78const addStatsChannel = async (interaction: CommandInteraction, m: Message, currentObject: ObjectSchema): Promise<ObjectSchema> => {
79 let closed = false;
80 let cancelled = false;
81 const originalObject = Object.fromEntries(Object.entries(currentObject).map(([k, v]) => [k, {...v}]));
82 let newChannel: string | undefined;
83 let newChannelName: string = "{memberCount:all}-members";
84 let newChannelEnabled: boolean = true;
85 do {
TheCodedProf267563a2023-01-21 17:00:57 -050086 m = await interaction.editReply({
TheCodedProf9bc84752023-01-21 05:19:57 -050087 embeds: [new EmojiEmbed()
88 .setTitle("Stats Channel")
89 .setDescription(
90 `New stats channel` + (newChannel ? ` in <#${newChannel}>` : "") + "\n\n" +
91 `**Name:** \`${newChannelName}\`\n` +
92 `**Preview:** ${await convertCurlyBracketString(newChannelName, interaction.user!.id, interaction.user.username, interaction.guild!.name, interaction.guild!.members)}\n` +
93 `**Enabled:** ${newChannelEnabled ? "Yes" : "No"}\n\n`
94 )
95 .setEmoji("SETTINGS.STATS.GREEN")
96 .setStatus("Success")
97 ], components: [
98 new ActionRowBuilder<ChannelSelectMenuBuilder>().addComponents(
99 new ChannelSelectMenuBuilder()
100 .setCustomId("channel")
TheCodedProf267563a2023-01-21 17:00:57 -0500101 .setPlaceholder("Select a channel to use")
TheCodedProf9bc84752023-01-21 05:19:57 -0500102 ),
103 new ActionRowBuilder<ButtonBuilder>().addComponents(
104 new ButtonBuilder()
105 .setLabel("Cancel")
106 .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
107 .setStyle(ButtonStyle.Danger)
108 .setCustomId("back"),
109 new ButtonBuilder()
110 .setLabel("Save")
111 .setEmoji(getEmojiByName("ICONS.SAVE", "id"))
112 .setStyle(ButtonStyle.Success)
113 .setCustomId("save"),
114 new ButtonBuilder()
115 .setLabel("Edit name")
116 .setEmoji(getEmojiByName("ICONS.EDIT", "id"))
117 .setStyle(ButtonStyle.Primary)
118 .setCustomId("editName"),
119 new ButtonBuilder()
120 .setLabel(newChannelEnabled ? "Enabled" : "Disabled")
121 .setEmoji(getEmojiByName(newChannelEnabled ? "CONTROL.TICK" : "CONTROL.CROSS", "id"))
122 .setStyle(ButtonStyle.Secondary)
123 .setCustomId("toggleEnabled")
124 )
125 ]
126 });
127 let i: ButtonInteraction | ChannelSelectMenuInteraction;
128 try {
TheCodedProf267563a2023-01-21 17:00:57 -0500129 i = await m.awaitMessageComponent({ time: 300000, filter: (i) => {
130 return i.user.id === interaction.user.id && i.channel!.id === interaction.channel!.id && i.message.id === m.id;
131 }}) as ButtonInteraction | ChannelSelectMenuInteraction;
TheCodedProf9bc84752023-01-21 05:19:57 -0500132 } catch (e) {
133 closed = true;
134 cancelled = true;
135 break;
136 }
137 if (i.isButton()) {
138 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000139 case "back": {
TheCodedProf267563a2023-01-21 17:00:57 -0500140 await i.deferUpdate();
TheCodedProf9bc84752023-01-21 05:19:57 -0500141 closed = true;
142 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000143 }
144 case "save": {
TheCodedProf267563a2023-01-21 17:00:57 -0500145 await i.deferUpdate();
TheCodedProf9bc84752023-01-21 05:19:57 -0500146 if (newChannel) {
147 currentObject[newChannel] = {
148 name: newChannelName,
149 enabled: newChannelEnabled
150 }
151 }
152 closed = true;
153 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000154 }
155 case "editName": {
TheCodedProf9bc84752023-01-21 05:19:57 -0500156 await interaction.editReply({
157 embeds: [new EmojiEmbed()
158 .setTitle("Stats Channel")
159 .setDescription("Modal opened. If you can't see it, click back and try again.")
160 .setStatus("Success")
161 .setEmoji("SETTINGS.STATS.GREEN")
162 ],
163 components: [
164 new ActionRowBuilder<ButtonBuilder>().addComponents(
165 new ButtonBuilder()
166 .setLabel("Back")
167 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
168 .setStyle(ButtonStyle.Primary)
169 .setCustomId("back")
170 )
171 ]
172 });
173 showModal(i, {name: newChannelName, enabled: newChannelEnabled})
174
PineaFanb0d0c242023-02-05 10:59:45 +0000175 const out: Discord.ModalSubmitInteraction | ButtonInteraction| null = await modalInteractionCollector(
TheCodedProf9bc84752023-01-21 05:19:57 -0500176 m,
TheCodedProf267563a2023-01-21 17:00:57 -0500177 (m) => m.channel!.id === interaction.channel!.id && m.user!.id === interaction.user!.id,
178 (i) => i.channel!.id === interaction.channel!.id && i.user!.id === interaction.user!.id && i.message!.id === m.id
PineaFanb0d0c242023-02-05 10:59:45 +0000179 );
TheCodedProf9bc84752023-01-21 05:19:57 -0500180 if (!out) continue;
TheCodedProf9bc84752023-01-21 05:19:57 -0500181 if (out.isButton()) continue;
182 newChannelName = out.fields.getTextInputValue("text");
183 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000184 }
185 case "toggleEnabled": {
TheCodedProf267563a2023-01-21 17:00:57 -0500186 await i.deferUpdate();
TheCodedProf9bc84752023-01-21 05:19:57 -0500187 newChannelEnabled = !newChannelEnabled;
188 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000189 }
TheCodedProf9bc84752023-01-21 05:19:57 -0500190 }
191 } else {
TheCodedProf267563a2023-01-21 17:00:57 -0500192 await i.deferUpdate();
TheCodedProf9bc84752023-01-21 05:19:57 -0500193 if (i.customId === "channel") {
194 newChannel = i.values[0];
195 }
196 }
197 } while (!closed)
198 if (cancelled) return originalObject;
199 if (!(newChannel && newChannelName && newChannelEnabled)) return originalObject;
TheCodedProf267563a2023-01-21 17:00:57 -0500200 return currentObject;
TheCodedProf9bc84752023-01-21 05:19:57 -0500201}
PineaFan5d98a4b2023-01-19 16:15:47 +0000202const callback = async (interaction: CommandInteraction) => {
203 if (!interaction.guild) return;
TheCodedProf4a6d5712023-01-19 15:54:40 -0500204 const { renderChannel } = client.logger;
TheCodedProf4a6d5712023-01-19 15:54:40 -0500205 const m: Message = await interaction.reply({ embeds: LoadingEmbed, ephemeral: true, fetchReply: true });
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500206 let page = 0;
207 let closed = false;
208 const config = await client.database.guilds.read(interaction.guild.id);
TheCodedProf9bc84752023-01-21 05:19:57 -0500209 let currentObject: ObjectSchema = config.stats;
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500210 let modified = false;
PineaFan5d98a4b2023-01-19 16:15:47 +0000211 do {
PineaFana35b71b2023-01-24 19:33:27 +0000212 const embed = new EmojiEmbed()
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500213 .setTitle("Stats Settings")
214 .setEmoji("SETTINGS.STATS.GREEN")
215 .setStatus("Success");
216 const noStatsChannels = Object.keys(currentObject).length === 0;
217 let current: { enabled: boolean; name: string; };
218
219 const pageSelect = new StringSelectMenuBuilder()
PineaFan5d98a4b2023-01-19 16:15:47 +0000220 .setCustomId("page")
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500221 .setPlaceholder("Select a stats channel to manage");
222 const actionSelect = new StringSelectMenuBuilder()
TheCodedProf4a6d5712023-01-19 15:54:40 -0500223 .setCustomId("action")
224 .setPlaceholder("Perform an action")
TheCodedProf4a6d5712023-01-19 15:54:40 -0500225 .addOptions(
226 new StringSelectMenuOptionBuilder()
227 .setLabel("Edit")
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500228 .setDescription("Edit the stats channel")
TheCodedProf4a6d5712023-01-19 15:54:40 -0500229 .setValue("edit")
TheCodedProf4a6d5712023-01-19 15:54:40 -0500230 .setEmoji(getEmojiByName("ICONS.EDIT", "id") as APIMessageComponentEmoji),
231 new StringSelectMenuOptionBuilder()
232 .setLabel("Delete")
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500233 .setDescription("Delete the stats channel")
TheCodedProf4a6d5712023-01-19 15:54:40 -0500234 .setValue("delete")
TheCodedProf4a6d5712023-01-19 15:54:40 -0500235 .setEmoji(getEmojiByName("TICKETS.ISSUE", "id") as APIMessageComponentEmoji)
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500236 );
237 const buttonRow = new ActionRowBuilder<ButtonBuilder>()
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500238 .addComponents(
239 new ButtonBuilder()
240 .setCustomId("back")
241 .setStyle(ButtonStyle.Primary)
242 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji)
243 .setDisabled(page === 0),
244 new ButtonBuilder()
245 .setCustomId("next")
246 .setEmoji(getEmojiByName("CONTROL.RIGHT", "id") as APIMessageComponentEmoji)
247 .setStyle(ButtonStyle.Primary)
248 .setDisabled(page === Object.keys(currentObject).length - 1),
249 new ButtonBuilder()
250 .setCustomId("add")
251 .setLabel("Create new")
252 .setEmoji(getEmojiByName("TICKETS.SUGGESTION", "id") as APIMessageComponentEmoji)
253 .setStyle(ButtonStyle.Secondary)
254 .setDisabled(Object.keys(currentObject).length >= 24),
255 new ButtonBuilder()
256 .setCustomId("save")
257 .setLabel("Save")
258 .setEmoji(getEmojiByName("ICONS.SAVE", "id") as APIMessageComponentEmoji)
259 .setStyle(ButtonStyle.Success)
260 .setDisabled(modified),
TheCodedProf4a6d5712023-01-19 15:54:40 -0500261 );
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500262 if (noStatsChannels) {
263 embed.setDescription("No stats channels have been set up yet. Use the button below to add one.\n\n" +
264 createPageIndicator(1, 1, undefined, true)
265 );
266 pageSelect.setDisabled(true);
267 actionSelect.setDisabled(true);
268 pageSelect.addOptions(new StringSelectMenuOptionBuilder()
269 .setLabel("No stats channels")
270 .setValue("none")
271 );
TheCodedProf4a6d5712023-01-19 15:54:40 -0500272 } else {
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500273 page = Math.min(page, Object.keys(currentObject).length - 1);
274 current = currentObject[Object.keys(config.stats)[page]!]!
TheCodedProf4a6d5712023-01-19 15:54:40 -0500275 actionSelect.addOptions(new StringSelectMenuOptionBuilder()
276 .setLabel(current.enabled ? "Disable" : "Enable")
277 .setValue("toggleEnabled")
278 .setDescription(`Currently ${current.enabled ? "Enabled" : "Disabled"}, click to ${current.enabled ? "disable" : "enable"} this channel`)
279 .setEmoji(getEmojiByName(current.enabled ? "CONTROL.TICK" : "CONTROL.CROSS", "id") as APIMessageComponentEmoji)
280 );
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500281 embed.setDescription(`**Currently Editing:** ${renderChannel(Object.keys(currentObject)[page]!)}\n\n` +
TheCodedProf4a6d5712023-01-19 15:54:40 -0500282 `${getEmojiByName(current.enabled ? "CONTROL.TICK" : "CONTROL.CROSS")} Currently ${current.enabled ? "Enabled" : "Disabled"}\n` +
283 `**Name:** \`${current.name}\`\n` +
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500284 `**Preview:** ${await convertCurlyBracketString(current.name, interaction.user.id, interaction.user.username, interaction.guild.name, interaction.guild.members)}` + '\n\n' +
285 createPageIndicator(Object.keys(config.stats).length, page)
TheCodedProf4a6d5712023-01-19 15:54:40 -0500286 );
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500287 for (const [id, { name, enabled }] of Object.entries(currentObject)) {
288 pageSelect.addOptions(new StringSelectMenuOptionBuilder()
289 .setLabel(`${name} (${renderChannel(id)})`)
290 .setEmoji(getEmojiByName(enabled ? "CONTROL.TICK" : "CONTROL.CROSS", "id") as APIMessageComponentEmoji)
291 .setDescription(`${enabled ? "Enabled" : "Disabled"}`)
292 .setValue(id)
293 );
294 }
295 }
TheCodedProf4a6d5712023-01-19 15:54:40 -0500296
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500297 interaction.editReply({embeds: [embed], components: [
298 new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(pageSelect),
299 new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(actionSelect),
300 buttonRow
301 ]});
TheCodedProf4a6d5712023-01-19 15:54:40 -0500302
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500303 let i: StringSelectMenuInteraction | ButtonInteraction;
TheCodedProf4a6d5712023-01-19 15:54:40 -0500304 try {
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500305 i = await m.awaitMessageComponent({ filter: (interaction) => interaction.user.id === interaction.user.id, time: 60000 }) as StringSelectMenuInteraction | ButtonInteraction;
TheCodedProf4a6d5712023-01-19 15:54:40 -0500306 } catch (e) {
307 closed = true;
308 continue;
309 }
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500310
311 if(i.isStringSelectMenu()) {
TheCodedProf4a6d5712023-01-19 15:54:40 -0500312 switch(i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000313 case "page": {
TheCodedProf267563a2023-01-21 17:00:57 -0500314 await i.deferUpdate();
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500315 page = Object.keys(currentObject).indexOf(i.values[0]!);
TheCodedProf4a6d5712023-01-19 15:54:40 -0500316 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000317 }
318 case "action": {
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500319 modified = true;
TheCodedProf4a6d5712023-01-19 15:54:40 -0500320 switch(i.values[0]!) {
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500321 case "edit": {
322 showModal(i, current!)
TheCodedProf4a6d5712023-01-19 15:54:40 -0500323 await interaction.editReply({
324 embeds: [
325 new EmojiEmbed()
326 .setTitle("Stats Channel")
327 .setDescription("Modal opened. If you can't see it, click back and try again.")
328 .setStatus("Success")
329 .setEmoji("SETTINGS.STATS.GREEN")
330 ],
331 components: [
332 new ActionRowBuilder<ButtonBuilder>().addComponents(
333 new ButtonBuilder()
334 .setLabel("Back")
335 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
336 .setStyle(ButtonStyle.Primary)
337 .setCustomId("back")
338 )
339 ]
340 });
TheCodedProf9bc84752023-01-21 05:19:57 -0500341 let out: Discord.ModalSubmitInteraction | null;
342 try {
343 out = await modalInteractionCollector(
344 m,
345 (m) => m.channel!.id === interaction.channel!.id,
346 (_) => true
347 ) as Discord.ModalSubmitInteraction | null;
348 } catch (e) {
349 continue;
350 }
351 if (!out) continue
TheCodedProf9bc84752023-01-21 05:19:57 -0500352 if (out.isButton()) continue;
353 currentObject[Object.keys(currentObject)[page]!]!.name = out.fields.getTextInputValue("text");
TheCodedProf4a6d5712023-01-19 15:54:40 -0500354 break;
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500355 }
356 case "toggleEnabled": {
TheCodedProf267563a2023-01-21 17:00:57 -0500357 await i.deferUpdate();
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500358 currentObject[Object.keys(currentObject)[page]!]!.enabled = !currentObject[Object.keys(currentObject)[page]!]!.enabled;
359 modified = true;
TheCodedProf4a6d5712023-01-19 15:54:40 -0500360 break;
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500361 }
362 case "delete": {
TheCodedProf267563a2023-01-21 17:00:57 -0500363 await i.deferUpdate();
PineaFanb0d0c242023-02-05 10:59:45 +0000364 currentObject = Object.fromEntries(Object.entries(currentObject).filter(([k]) => k !== Object.keys(currentObject)[page]!));
TheCodedProf267563a2023-01-21 17:00:57 -0500365 page = Math.min(page, Object.keys(currentObject).length - 1);
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500366 modified = true;
TheCodedProf4a6d5712023-01-19 15:54:40 -0500367 break;
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500368 }
TheCodedProf4a6d5712023-01-19 15:54:40 -0500369 }
370 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000371 }
TheCodedProf4a6d5712023-01-19 15:54:40 -0500372 }
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500373 } else {
TheCodedProf267563a2023-01-21 17:00:57 -0500374 await i.deferUpdate();
TheCodedProf4a6d5712023-01-19 15:54:40 -0500375 switch(i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000376 case "back": {
TheCodedProf4a6d5712023-01-19 15:54:40 -0500377 page--;
378 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000379 }
380 case "next": {
TheCodedProf4a6d5712023-01-19 15:54:40 -0500381 page++;
382 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000383 }
384 case "add": {
TheCodedProf9bc84752023-01-21 05:19:57 -0500385 currentObject = await addStatsChannel(interaction, m, currentObject);
TheCodedProf267563a2023-01-21 17:00:57 -0500386 page = Object.keys(currentObject).length - 1;
TheCodedProf4a6d5712023-01-19 15:54:40 -0500387 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000388 }
389 case "save": {
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500390 client.database.guilds.write(interaction.guild.id, {stats: currentObject});
391 singleNotify("statsChannelDeleted", interaction.guild.id, true);
392 modified = false;
393 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000394 }
TheCodedProf4a6d5712023-01-19 15:54:40 -0500395 }
396 }
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500397
PineaFan5d98a4b2023-01-19 16:15:47 +0000398 } while (!closed);
pineafan63fc5e22022-08-04 22:04:10 +0100399};
pineafan708692b2022-07-24 22:16:22 +0100400
TheCodedProff86ba092023-01-27 17:10:07 -0500401const check = (interaction: CommandInteraction, _partial: boolean = false) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100402 const member = interaction.member as Discord.GuildMember;
TheCodedProfafca98b2023-01-17 22:25:43 -0500403 if (!member.permissions.has("ManageChannels"))
PineaFan0d06edc2023-01-17 22:10:31 +0000404 return "You must have the *Manage Channels* permission to use this command";
pineafan708692b2022-07-24 22:16:22 +0100405 return true;
pineafan63fc5e22022-08-04 22:04:10 +0100406};
pineafan708692b2022-07-24 22:16:22 +0100407
PineaFan538d3752023-01-12 21:48:23 +0000408
pineafan708692b2022-07-24 22:16:22 +0100409export { command };
410export { callback };
PineaFan5d98a4b2023-01-19 16:15:47 +0000411export { check };