blob: ecab6127ca57c34b5494784c2ac4f56f3d193d90 [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 -050077const addStatsChannel = async (interaction: CommandInteraction, m: Message, currentObject: ObjectSchema): Promise<ObjectSchema> => {
78 let closed = false;
79 let cancelled = false;
80 const originalObject = Object.fromEntries(Object.entries(currentObject).map(([k, v]) => [k, {...v}]));
81 let newChannel: string | undefined;
82 let newChannelName: string = "{memberCount:all}-members";
83 let newChannelEnabled: boolean = true;
84 do {
TheCodedProf267563a2023-01-21 17:00:57 -050085 m = await interaction.editReply({
TheCodedProf9bc84752023-01-21 05:19:57 -050086 embeds: [new EmojiEmbed()
87 .setTitle("Stats Channel")
88 .setDescription(
89 `New stats channel` + (newChannel ? ` in <#${newChannel}>` : "") + "\n\n" +
90 `**Name:** \`${newChannelName}\`\n` +
91 `**Preview:** ${await convertCurlyBracketString(newChannelName, interaction.user!.id, interaction.user.username, interaction.guild!.name, interaction.guild!.members)}\n` +
92 `**Enabled:** ${newChannelEnabled ? "Yes" : "No"}\n\n`
93 )
94 .setEmoji("SETTINGS.STATS.GREEN")
95 .setStatus("Success")
96 ], components: [
97 new ActionRowBuilder<ChannelSelectMenuBuilder>().addComponents(
98 new ChannelSelectMenuBuilder()
99 .setCustomId("channel")
TheCodedProf267563a2023-01-21 17:00:57 -0500100 .setPlaceholder("Select a channel to use")
TheCodedProf9bc84752023-01-21 05:19:57 -0500101 ),
102 new ActionRowBuilder<ButtonBuilder>().addComponents(
103 new ButtonBuilder()
104 .setLabel("Cancel")
105 .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
106 .setStyle(ButtonStyle.Danger)
107 .setCustomId("back"),
108 new ButtonBuilder()
109 .setLabel("Save")
110 .setEmoji(getEmojiByName("ICONS.SAVE", "id"))
111 .setStyle(ButtonStyle.Success)
112 .setCustomId("save"),
113 new ButtonBuilder()
114 .setLabel("Edit name")
115 .setEmoji(getEmojiByName("ICONS.EDIT", "id"))
116 .setStyle(ButtonStyle.Primary)
117 .setCustomId("editName"),
118 new ButtonBuilder()
119 .setLabel(newChannelEnabled ? "Enabled" : "Disabled")
120 .setEmoji(getEmojiByName(newChannelEnabled ? "CONTROL.TICK" : "CONTROL.CROSS", "id"))
121 .setStyle(ButtonStyle.Secondary)
122 .setCustomId("toggleEnabled")
123 )
124 ]
125 });
126 let i: ButtonInteraction | ChannelSelectMenuInteraction;
127 try {
TheCodedProf267563a2023-01-21 17:00:57 -0500128 i = await m.awaitMessageComponent({ time: 300000, filter: (i) => {
129 return i.user.id === interaction.user.id && i.channel!.id === interaction.channel!.id && i.message.id === m.id;
130 }}) as ButtonInteraction | ChannelSelectMenuInteraction;
TheCodedProf9bc84752023-01-21 05:19:57 -0500131 } catch (e) {
132 closed = true;
133 cancelled = true;
134 break;
135 }
136 if (i.isButton()) {
137 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000138 case "back": {
TheCodedProf267563a2023-01-21 17:00:57 -0500139 await i.deferUpdate();
TheCodedProf9bc84752023-01-21 05:19:57 -0500140 closed = true;
141 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000142 }
143 case "save": {
TheCodedProf267563a2023-01-21 17:00:57 -0500144 await i.deferUpdate();
TheCodedProf9bc84752023-01-21 05:19:57 -0500145 if (newChannel) {
146 currentObject[newChannel] = {
147 name: newChannelName,
148 enabled: newChannelEnabled
149 }
150 }
151 closed = true;
152 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000153 }
154 case "editName": {
TheCodedProf9bc84752023-01-21 05:19:57 -0500155 await interaction.editReply({
156 embeds: [new EmojiEmbed()
157 .setTitle("Stats Channel")
158 .setDescription("Modal opened. If you can't see it, click back and try again.")
159 .setStatus("Success")
160 .setEmoji("SETTINGS.STATS.GREEN")
161 ],
162 components: [
163 new ActionRowBuilder<ButtonBuilder>().addComponents(
164 new ButtonBuilder()
165 .setLabel("Back")
166 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
167 .setStyle(ButtonStyle.Primary)
168 .setCustomId("back")
169 )
170 ]
171 });
172 showModal(i, {name: newChannelName, enabled: newChannelEnabled})
173
TheCodedProf01cba762023-02-18 15:55:05 -0500174 const out: Discord.ModalSubmitInteraction | ButtonInteraction| null = await modalInteractionCollector(m, interaction.user);
TheCodedProf9bc84752023-01-21 05:19:57 -0500175 if (!out) continue;
TheCodedProf9bc84752023-01-21 05:19:57 -0500176 if (out.isButton()) continue;
177 newChannelName = out.fields.getTextInputValue("text");
178 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000179 }
180 case "toggleEnabled": {
TheCodedProf267563a2023-01-21 17:00:57 -0500181 await i.deferUpdate();
TheCodedProf9bc84752023-01-21 05:19:57 -0500182 newChannelEnabled = !newChannelEnabled;
183 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000184 }
TheCodedProf9bc84752023-01-21 05:19:57 -0500185 }
186 } else {
TheCodedProf267563a2023-01-21 17:00:57 -0500187 await i.deferUpdate();
TheCodedProf9bc84752023-01-21 05:19:57 -0500188 if (i.customId === "channel") {
189 newChannel = i.values[0];
190 }
191 }
192 } while (!closed)
193 if (cancelled) return originalObject;
194 if (!(newChannel && newChannelName && newChannelEnabled)) return originalObject;
TheCodedProf267563a2023-01-21 17:00:57 -0500195 return currentObject;
TheCodedProf9bc84752023-01-21 05:19:57 -0500196}
PineaFan5d98a4b2023-01-19 16:15:47 +0000197const callback = async (interaction: CommandInteraction) => {
198 if (!interaction.guild) return;
TheCodedProf4a6d5712023-01-19 15:54:40 -0500199 const { renderChannel } = client.logger;
TheCodedProf4a6d5712023-01-19 15:54:40 -0500200 const m: Message = await interaction.reply({ embeds: LoadingEmbed, ephemeral: true, fetchReply: true });
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500201 let page = 0;
202 let closed = false;
203 const config = await client.database.guilds.read(interaction.guild.id);
TheCodedProf9bc84752023-01-21 05:19:57 -0500204 let currentObject: ObjectSchema = config.stats;
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500205 let modified = false;
PineaFan5d98a4b2023-01-19 16:15:47 +0000206 do {
PineaFana35b71b2023-01-24 19:33:27 +0000207 const embed = new EmojiEmbed()
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500208 .setTitle("Stats Settings")
209 .setEmoji("SETTINGS.STATS.GREEN")
210 .setStatus("Success");
211 const noStatsChannels = Object.keys(currentObject).length === 0;
212 let current: { enabled: boolean; name: string; };
213
214 const pageSelect = new StringSelectMenuBuilder()
PineaFan5d98a4b2023-01-19 16:15:47 +0000215 .setCustomId("page")
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500216 .setPlaceholder("Select a stats channel to manage");
217 const actionSelect = new StringSelectMenuBuilder()
TheCodedProf4a6d5712023-01-19 15:54:40 -0500218 .setCustomId("action")
219 .setPlaceholder("Perform an action")
TheCodedProf4a6d5712023-01-19 15:54:40 -0500220 .addOptions(
221 new StringSelectMenuOptionBuilder()
222 .setLabel("Edit")
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500223 .setDescription("Edit the stats channel")
TheCodedProf4a6d5712023-01-19 15:54:40 -0500224 .setValue("edit")
TheCodedProf4a6d5712023-01-19 15:54:40 -0500225 .setEmoji(getEmojiByName("ICONS.EDIT", "id") as APIMessageComponentEmoji),
226 new StringSelectMenuOptionBuilder()
227 .setLabel("Delete")
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500228 .setDescription("Delete the stats channel")
TheCodedProf4a6d5712023-01-19 15:54:40 -0500229 .setValue("delete")
TheCodedProf4a6d5712023-01-19 15:54:40 -0500230 .setEmoji(getEmojiByName("TICKETS.ISSUE", "id") as APIMessageComponentEmoji)
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500231 );
232 const buttonRow = new ActionRowBuilder<ButtonBuilder>()
TheCodedProf1c3ad3c2023-01-25 17:58:36 -0500233 .addComponents(
234 new ButtonBuilder()
235 .setCustomId("back")
236 .setStyle(ButtonStyle.Primary)
237 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji)
238 .setDisabled(page === 0),
239 new ButtonBuilder()
240 .setCustomId("next")
241 .setEmoji(getEmojiByName("CONTROL.RIGHT", "id") as APIMessageComponentEmoji)
242 .setStyle(ButtonStyle.Primary)
243 .setDisabled(page === Object.keys(currentObject).length - 1),
244 new ButtonBuilder()
245 .setCustomId("add")
246 .setLabel("Create new")
247 .setEmoji(getEmojiByName("TICKETS.SUGGESTION", "id") as APIMessageComponentEmoji)
248 .setStyle(ButtonStyle.Secondary)
249 .setDisabled(Object.keys(currentObject).length >= 24),
250 new ButtonBuilder()
251 .setCustomId("save")
252 .setLabel("Save")
253 .setEmoji(getEmojiByName("ICONS.SAVE", "id") as APIMessageComponentEmoji)
254 .setStyle(ButtonStyle.Success)
255 .setDisabled(modified),
TheCodedProf4a6d5712023-01-19 15:54:40 -0500256 );
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500257 if (noStatsChannels) {
258 embed.setDescription("No stats channels have been set up yet. Use the button below to add one.\n\n" +
259 createPageIndicator(1, 1, undefined, true)
260 );
261 pageSelect.setDisabled(true);
262 actionSelect.setDisabled(true);
263 pageSelect.addOptions(new StringSelectMenuOptionBuilder()
264 .setLabel("No stats channels")
265 .setValue("none")
266 );
TheCodedProf4a6d5712023-01-19 15:54:40 -0500267 } else {
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500268 page = Math.min(page, Object.keys(currentObject).length - 1);
269 current = currentObject[Object.keys(config.stats)[page]!]!
TheCodedProf4a6d5712023-01-19 15:54:40 -0500270 actionSelect.addOptions(new StringSelectMenuOptionBuilder()
271 .setLabel(current.enabled ? "Disable" : "Enable")
272 .setValue("toggleEnabled")
273 .setDescription(`Currently ${current.enabled ? "Enabled" : "Disabled"}, click to ${current.enabled ? "disable" : "enable"} this channel`)
274 .setEmoji(getEmojiByName(current.enabled ? "CONTROL.TICK" : "CONTROL.CROSS", "id") as APIMessageComponentEmoji)
275 );
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500276 embed.setDescription(`**Currently Editing:** ${renderChannel(Object.keys(currentObject)[page]!)}\n\n` +
TheCodedProf4a6d5712023-01-19 15:54:40 -0500277 `${getEmojiByName(current.enabled ? "CONTROL.TICK" : "CONTROL.CROSS")} Currently ${current.enabled ? "Enabled" : "Disabled"}\n` +
278 `**Name:** \`${current.name}\`\n` +
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500279 `**Preview:** ${await convertCurlyBracketString(current.name, interaction.user.id, interaction.user.username, interaction.guild.name, interaction.guild.members)}` + '\n\n' +
280 createPageIndicator(Object.keys(config.stats).length, page)
TheCodedProf4a6d5712023-01-19 15:54:40 -0500281 );
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500282 for (const [id, { name, enabled }] of Object.entries(currentObject)) {
283 pageSelect.addOptions(new StringSelectMenuOptionBuilder()
284 .setLabel(`${name} (${renderChannel(id)})`)
285 .setEmoji(getEmojiByName(enabled ? "CONTROL.TICK" : "CONTROL.CROSS", "id") as APIMessageComponentEmoji)
286 .setDescription(`${enabled ? "Enabled" : "Disabled"}`)
287 .setValue(id)
288 );
289 }
290 }
TheCodedProf4a6d5712023-01-19 15:54:40 -0500291
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500292 interaction.editReply({embeds: [embed], components: [
293 new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(pageSelect),
294 new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(actionSelect),
295 buttonRow
296 ]});
TheCodedProf4a6d5712023-01-19 15:54:40 -0500297
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500298 let i: StringSelectMenuInteraction | ButtonInteraction;
TheCodedProf4a6d5712023-01-19 15:54:40 -0500299 try {
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500300 i = await m.awaitMessageComponent({ filter: (interaction) => interaction.user.id === interaction.user.id, time: 60000 }) as StringSelectMenuInteraction | ButtonInteraction;
TheCodedProf4a6d5712023-01-19 15:54:40 -0500301 } catch (e) {
302 closed = true;
303 continue;
304 }
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500305
306 if(i.isStringSelectMenu()) {
TheCodedProf4a6d5712023-01-19 15:54:40 -0500307 switch(i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000308 case "page": {
TheCodedProf267563a2023-01-21 17:00:57 -0500309 await i.deferUpdate();
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500310 page = Object.keys(currentObject).indexOf(i.values[0]!);
TheCodedProf4a6d5712023-01-19 15:54:40 -0500311 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000312 }
313 case "action": {
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500314 modified = true;
TheCodedProf4a6d5712023-01-19 15:54:40 -0500315 switch(i.values[0]!) {
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500316 case "edit": {
317 showModal(i, current!)
TheCodedProf4a6d5712023-01-19 15:54:40 -0500318 await interaction.editReply({
319 embeds: [
320 new EmojiEmbed()
321 .setTitle("Stats Channel")
322 .setDescription("Modal opened. If you can't see it, click back and try again.")
323 .setStatus("Success")
324 .setEmoji("SETTINGS.STATS.GREEN")
325 ],
326 components: [
327 new ActionRowBuilder<ButtonBuilder>().addComponents(
328 new ButtonBuilder()
329 .setLabel("Back")
330 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
331 .setStyle(ButtonStyle.Primary)
332 .setCustomId("back")
333 )
334 ]
335 });
TheCodedProf9bc84752023-01-21 05:19:57 -0500336 let out: Discord.ModalSubmitInteraction | null;
337 try {
TheCodedProf01cba762023-02-18 15:55:05 -0500338 out = await modalInteractionCollector(m, interaction.user) as Discord.ModalSubmitInteraction | null;
TheCodedProf9bc84752023-01-21 05:19:57 -0500339 } catch (e) {
340 continue;
341 }
342 if (!out) continue
TheCodedProf9bc84752023-01-21 05:19:57 -0500343 if (out.isButton()) continue;
344 currentObject[Object.keys(currentObject)[page]!]!.name = out.fields.getTextInputValue("text");
TheCodedProf4a6d5712023-01-19 15:54:40 -0500345 break;
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500346 }
347 case "toggleEnabled": {
TheCodedProf267563a2023-01-21 17:00:57 -0500348 await i.deferUpdate();
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500349 currentObject[Object.keys(currentObject)[page]!]!.enabled = !currentObject[Object.keys(currentObject)[page]!]!.enabled;
350 modified = true;
TheCodedProf4a6d5712023-01-19 15:54:40 -0500351 break;
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500352 }
353 case "delete": {
TheCodedProf267563a2023-01-21 17:00:57 -0500354 await i.deferUpdate();
PineaFanb0d0c242023-02-05 10:59:45 +0000355 currentObject = Object.fromEntries(Object.entries(currentObject).filter(([k]) => k !== Object.keys(currentObject)[page]!));
TheCodedProf267563a2023-01-21 17:00:57 -0500356 page = Math.min(page, Object.keys(currentObject).length - 1);
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500357 modified = true;
TheCodedProf4a6d5712023-01-19 15:54:40 -0500358 break;
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500359 }
TheCodedProf4a6d5712023-01-19 15:54:40 -0500360 }
361 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000362 }
TheCodedProf4a6d5712023-01-19 15:54:40 -0500363 }
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500364 } else {
TheCodedProf267563a2023-01-21 17:00:57 -0500365 await i.deferUpdate();
TheCodedProf4a6d5712023-01-19 15:54:40 -0500366 switch(i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000367 case "back": {
TheCodedProf4a6d5712023-01-19 15:54:40 -0500368 page--;
369 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000370 }
371 case "next": {
TheCodedProf4a6d5712023-01-19 15:54:40 -0500372 page++;
373 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000374 }
375 case "add": {
TheCodedProf9bc84752023-01-21 05:19:57 -0500376 currentObject = await addStatsChannel(interaction, m, currentObject);
TheCodedProf267563a2023-01-21 17:00:57 -0500377 page = Object.keys(currentObject).length - 1;
TheCodedProf4a6d5712023-01-19 15:54:40 -0500378 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000379 }
380 case "save": {
Skyler Grey16ecb172023-03-05 07:30:32 +0000381 await client.database.guilds.write(interaction.guild.id, {stats: currentObject});
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500382 singleNotify("statsChannelDeleted", interaction.guild.id, true);
383 modified = false;
Skyler Grey16ecb172023-03-05 07:30:32 +0000384 await client.memory.forceUpdate(interaction.guild.id);
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500385 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000386 }
TheCodedProf4a6d5712023-01-19 15:54:40 -0500387 }
388 }
TheCodedProfc2acbcc2023-01-20 17:23:51 -0500389
PineaFan5d98a4b2023-01-19 16:15:47 +0000390 } while (!closed);
TheCodedProf01cba762023-02-18 15:55:05 -0500391 await interaction.deleteReply()
pineafan63fc5e22022-08-04 22:04:10 +0100392};
pineafan708692b2022-07-24 22:16:22 +0100393
TheCodedProff86ba092023-01-27 17:10:07 -0500394const check = (interaction: CommandInteraction, _partial: boolean = false) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100395 const member = interaction.member as Discord.GuildMember;
TheCodedProfafca98b2023-01-17 22:25:43 -0500396 if (!member.permissions.has("ManageChannels"))
PineaFan0d06edc2023-01-17 22:10:31 +0000397 return "You must have the *Manage Channels* permission to use this command";
pineafan708692b2022-07-24 22:16:22 +0100398 return true;
pineafan63fc5e22022-08-04 22:04:10 +0100399};
pineafan708692b2022-07-24 22:16:22 +0100400
PineaFan538d3752023-01-12 21:48:23 +0000401
pineafan708692b2022-07-24 22:16:22 +0100402export { command };
403export { callback };
Skyler Grey16ecb172023-03-05 07:30:32 +0000404export { check };