blob: d8464f0b9ce811103c99967484107402c7bf3bd4 [file] [log] [blame]
TheCodedProf8b3da212023-02-02 15:09:55 -05001import type Discord from "discord.js";
Skyler Greyda16adf2023-03-05 10:22:12 +00002import {
3 ActionRowBuilder,
TheCodedProf5b53a8c2023-02-03 15:40:26 -05004 AnySelectMenuInteraction,
5 APIMessageComponentEmoji,
6 ButtonBuilder,
7 ButtonInteraction,
8 ButtonStyle,
9 ChannelSelectMenuBuilder,
10 ChannelSelectMenuInteraction,
11 CommandInteraction,
TheCodedProf5b53a8c2023-02-03 15:40:26 -050012 Message,
TheCodedProf5b53a8c2023-02-03 15:40:26 -050013 ModalBuilder,
TheCodedProf5b53a8c2023-02-03 15:40:26 -050014 RoleSelectMenuBuilder,
15 RoleSelectMenuInteraction,
16 StringSelectMenuBuilder,
17 StringSelectMenuInteraction,
18 StringSelectMenuOptionBuilder,
19 TextInputBuilder,
20 TextInputStyle,
21 UserSelectMenuBuilder,
22 UserSelectMenuInteraction
23} from "discord.js";
TheCodedProf8b3da212023-02-02 15:09:55 -050024import type { SlashCommandSubcommandBuilder } from "discord.js";
25import { LoadingEmbed } from "../../utils/defaults.js";
26import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
27import client from "../../utils/client.js";
28import getEmojiByName from "../../utils/getEmojiByName.js";
TheCodedProf5b53a8c2023-02-03 15:40:26 -050029import { modalInteractionCollector } from "../../utils/dualCollector.js";
TheCodedProf1f675042023-02-16 17:01:29 -050030import listToAndMore from "../../utils/listToAndMore.js";
TheCodedProf8b3da212023-02-02 15:09:55 -050031
32const command = (builder: SlashCommandSubcommandBuilder) =>
33 builder.setName("automod").setDescription("Setting for automatic moderation features");
34
Skyler Greyda16adf2023-03-05 10:22:12 +000035const emojiFromBoolean = (bool: boolean, id?: string) =>
36 bool ? getEmojiByName("CONTROL.TICK", id) : getEmojiByName("CONTROL.CROSS", id);
TheCodedProf8b3da212023-02-02 15:09:55 -050037
Skyler Greyda16adf2023-03-05 10:22:12 +000038const toSelectMenu = async (
39 interaction: StringSelectMenuInteraction,
40 m: Message,
41 ids: string[],
42 type: "member" | "role" | "channel",
43 title: string
44): Promise<string[]> => {
45 const back = new ActionRowBuilder<ButtonBuilder>().addComponents(
46 new ButtonBuilder()
47 .setCustomId("back")
48 .setLabel("Back")
49 .setStyle(ButtonStyle.Secondary)
50 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji)
51 );
TheCodedProf486bca32023-02-02 16:49:44 -050052 let closed;
53 do {
Skyler Greyda16adf2023-03-05 10:22:12 +000054 let render: string[] = [];
TheCodedProf486bca32023-02-02 16:49:44 -050055 let mapped: string[] = [];
56 let menu: UserSelectMenuBuilder | RoleSelectMenuBuilder | ChannelSelectMenuBuilder;
Skyler Greyda16adf2023-03-05 10:22:12 +000057 switch (type) {
PineaFanb0d0c242023-02-05 10:59:45 +000058 case "member": {
TheCodedProf486bca32023-02-02 16:49:44 -050059 menu = new UserSelectMenuBuilder().setCustomId("user").setPlaceholder("Select users").setMaxValues(25);
Skyler Greyda16adf2023-03-05 10:22:12 +000060 mapped = await Promise.all(
61 ids.map(async (id) => {
62 return (await client.users.fetch(id).then((user) => user.tag)) || "Unknown User";
63 })
64 );
65 render = ids.map((id) => client.logger.renderUser(id));
TheCodedProf486bca32023-02-02 16:49:44 -050066 break;
PineaFanb0d0c242023-02-05 10:59:45 +000067 }
68 case "role": {
TheCodedProf486bca32023-02-02 16:49:44 -050069 menu = new RoleSelectMenuBuilder().setCustomId("role").setPlaceholder("Select roles").setMaxValues(25);
Skyler Greyda16adf2023-03-05 10:22:12 +000070 mapped = await Promise.all(
71 ids.map(async (id) => {
72 return await interaction.guild!.roles.fetch(id).then((role) => role?.name ?? "Unknown Role");
73 })
74 );
75 render = ids.map((id) => client.logger.renderRole(id, interaction.guild!));
TheCodedProf486bca32023-02-02 16:49:44 -050076 break;
PineaFanb0d0c242023-02-05 10:59:45 +000077 }
78 case "channel": {
Skyler Greyda16adf2023-03-05 10:22:12 +000079 menu = new ChannelSelectMenuBuilder()
80 .setCustomId("channel")
81 .setPlaceholder("Select channels")
82 .setMaxValues(25);
83 mapped = await Promise.all(
84 ids.map(async (id) => {
85 return await interaction
86 .guild!.channels.fetch(id)
87 .then((channel) => channel?.name ?? "Unknown Role");
88 })
89 );
90 render = ids.map((id) => client.logger.renderChannel(id));
TheCodedProf486bca32023-02-02 16:49:44 -050091 break;
PineaFanb0d0c242023-02-05 10:59:45 +000092 }
TheCodedProf486bca32023-02-02 16:49:44 -050093 }
Skyler Greyda16adf2023-03-05 10:22:12 +000094 const removeOptions = new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
95 new StringSelectMenuBuilder()
96 .setCustomId("remove")
97 .setPlaceholder("Remove")
98 .addOptions(
99 mapped.map((name, i) => new StringSelectMenuOptionBuilder().setLabel(name).setValue(ids[i]!))
100 )
101 .setDisabled(ids.length === 0)
102 );
TheCodedProf486bca32023-02-02 16:49:44 -0500103
104 const embed = new EmojiEmbed()
105 .setTitle(title)
106 .setEmoji(getEmojiByName("GUILD.SETTINGS.GREEN"))
107 .setDescription(`Select ${type}s:\n\nCurrent:\n` + (render.length > 0 ? render.join("\n") : "None"))
108 .setStatus("Success");
PineaFanb0d0c242023-02-05 10:59:45 +0000109 const components: ActionRowBuilder<
Skyler Greyda16adf2023-03-05 10:22:12 +0000110 | StringSelectMenuBuilder
111 | ButtonBuilder
112 | ChannelSelectMenuBuilder
113 | UserSelectMenuBuilder
114 | RoleSelectMenuBuilder
115 >[] = [new ActionRowBuilder<typeof menu>().addComponents(menu)];
116 if (ids.length > 0) components.push(removeOptions);
TheCodedProf486bca32023-02-02 16:49:44 -0500117 components.push(back);
118
Skyler Greyda16adf2023-03-05 10:22:12 +0000119 await interaction.editReply({ embeds: [embed], components: components });
TheCodedProf486bca32023-02-02 16:49:44 -0500120
121 let i: AnySelectMenuInteraction | ButtonInteraction;
122 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000123 i = await m.awaitMessageComponent({ filter: (i) => i.user.id === interaction.user.id, time: 300000 });
124 } catch (e) {
TheCodedProf486bca32023-02-02 16:49:44 -0500125 closed = true;
PineaFanb0d0c242023-02-05 10:59:45 +0000126 continue;
TheCodedProf486bca32023-02-02 16:49:44 -0500127 }
128
Skyler Greyda16adf2023-03-05 10:22:12 +0000129 if (i.isButton()) {
TheCodedProf486bca32023-02-02 16:49:44 -0500130 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000131 if (i.customId === "back") {
TheCodedProf486bca32023-02-02 16:49:44 -0500132 closed = true;
133 break;
134 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000135 } else if (i.isStringSelectMenu()) {
TheCodedProf486bca32023-02-02 16:49:44 -0500136 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000137 if (i.customId === "remove") {
138 ids = ids.filter((id) => id !== (i as StringSelectMenuInteraction).values[0]);
139 if (ids.length === 0) {
TheCodedProf486bca32023-02-02 16:49:44 -0500140 menu.data.disabled = true;
141 }
142 }
143 } else {
144 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000145 if (i.customId === "user") {
TheCodedProf486bca32023-02-02 16:49:44 -0500146 ids = ids.concat((i as UserSelectMenuInteraction).values);
Skyler Greyda16adf2023-03-05 10:22:12 +0000147 } else if (i.customId === "role") {
TheCodedProf486bca32023-02-02 16:49:44 -0500148 ids = ids.concat((i as RoleSelectMenuInteraction).values);
Skyler Greyda16adf2023-03-05 10:22:12 +0000149 } else if (i.customId === "channel") {
TheCodedProf486bca32023-02-02 16:49:44 -0500150 ids = ids.concat((i as ChannelSelectMenuInteraction).values);
151 }
152 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000153 } while (!closed);
TheCodedProf486bca32023-02-02 16:49:44 -0500154 return ids;
Skyler Greyda16adf2023-03-05 10:22:12 +0000155};
TheCodedProf8b3da212023-02-02 15:09:55 -0500156
Skyler Greyda16adf2023-03-05 10:22:12 +0000157const imageMenu = async (
158 interaction: StringSelectMenuInteraction,
159 m: Message,
160 current: {
161 NSFW: boolean;
162 size: boolean;
163 }
164): Promise<{ NSFW: boolean; size: boolean }> => {
TheCodedProf8b3da212023-02-02 15:09:55 -0500165 let closed = false;
166 do {
Skyler Greyda16adf2023-03-05 10:22:12 +0000167 const options = new ActionRowBuilder<ButtonBuilder>().addComponents(
168 new ButtonBuilder()
169 .setCustomId("back")
170 .setLabel("Back")
171 .setStyle(ButtonStyle.Secondary)
172 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji),
173 new ButtonBuilder()
174 .setCustomId("nsfw")
175 .setLabel("NSFW")
176 .setStyle(current.NSFW ? ButtonStyle.Success : ButtonStyle.Danger)
177 .setEmoji(emojiFromBoolean(current.NSFW, "id") as APIMessageComponentEmoji),
178 new ButtonBuilder()
179 .setCustomId("size")
180 .setLabel("Size")
181 .setStyle(current.size ? ButtonStyle.Success : ButtonStyle.Danger)
182 .setEmoji(emojiFromBoolean(current.size, "id") as APIMessageComponentEmoji)
183 );
TheCodedProf8b3da212023-02-02 15:09:55 -0500184
185 const embed = new EmojiEmbed()
186 .setTitle("Image Settings")
187 .setDescription(
Skyler Greyda16adf2023-03-05 10:22:12 +0000188 `${emojiFromBoolean(current.NSFW)} **NSFW**\n` + `${emojiFromBoolean(current.size)} **Size**\n`
189 );
TheCodedProf8b3da212023-02-02 15:09:55 -0500190
Skyler Greyda16adf2023-03-05 10:22:12 +0000191 await interaction.editReply({ embeds: [embed], components: [options] });
TheCodedProf8b3da212023-02-02 15:09:55 -0500192
193 let i: ButtonInteraction;
194 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000195 i = (await m.awaitMessageComponent({
196 filter: (i) => interaction.user.id === i.user.id && i.message.id === m.id,
197 time: 300000
198 })) as ButtonInteraction;
TheCodedProf8b3da212023-02-02 15:09:55 -0500199 } catch (e) {
200 return current;
201 }
202 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000203 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000204 case "back": {
TheCodedProf8b3da212023-02-02 15:09:55 -0500205 closed = true;
206 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000207 }
208 case "nsfw": {
TheCodedProf8b3da212023-02-02 15:09:55 -0500209 current.NSFW = !current.NSFW;
210 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000211 }
212 case "size": {
TheCodedProf8b3da212023-02-02 15:09:55 -0500213 current.size = !current.size;
214 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000215 }
TheCodedProf8b3da212023-02-02 15:09:55 -0500216 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000217 } while (!closed);
TheCodedProf8b3da212023-02-02 15:09:55 -0500218 return current;
Skyler Greyda16adf2023-03-05 10:22:12 +0000219};
TheCodedProf8b3da212023-02-02 15:09:55 -0500220
Skyler Greyda16adf2023-03-05 10:22:12 +0000221const wordMenu = async (
222 interaction: StringSelectMenuInteraction,
223 m: Message,
224 current: {
225 enabled: boolean;
226 words: { strict: string[]; loose: string[] };
227 allowed: { users: string[]; roles: string[]; channels: string[] };
228 }
229): Promise<{
230 enabled: boolean;
231 words: { strict: string[]; loose: string[] };
232 allowed: { users: string[]; roles: string[]; channels: string[] };
TheCodedProf8b3da212023-02-02 15:09:55 -0500233}> => {
TheCodedProf486bca32023-02-02 16:49:44 -0500234 let closed = false;
235 do {
Skyler Greyda16adf2023-03-05 10:22:12 +0000236 const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
237 new ButtonBuilder()
238 .setCustomId("back")
239 .setLabel("Back")
240 .setStyle(ButtonStyle.Secondary)
241 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji),
242 new ButtonBuilder()
243 .setCustomId("enabled")
244 .setLabel("Enabled")
245 .setStyle(current.enabled ? ButtonStyle.Success : ButtonStyle.Danger)
246 .setEmoji(emojiFromBoolean(current.enabled, "id") as APIMessageComponentEmoji)
247 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500248
Skyler Greyda16adf2023-03-05 10:22:12 +0000249 const selectMenu = new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
250 new StringSelectMenuBuilder()
251 .setCustomId("edit")
252 .setPlaceholder("Edit... ")
253 .addOptions(
254 new StringSelectMenuOptionBuilder()
255 .setLabel("Words")
256 .setDescription("Edit your list of words to filter")
257 .setValue("words"),
258 new StringSelectMenuOptionBuilder()
259 .setLabel("Allowed Users")
260 .setDescription("Users who will be unaffected by the word filter")
261 .setValue("allowedUsers"),
262 new StringSelectMenuOptionBuilder()
263 .setLabel("Allowed Roles")
264 .setDescription("Roles that will be unaffected by the word filter")
265 .setValue("allowedRoles"),
266 new StringSelectMenuOptionBuilder()
267 .setLabel("Allowed Channels")
268 .setDescription("Channels where the word filter will not apply")
269 .setValue("allowedChannels")
270 )
271 .setDisabled(!current.enabled)
272 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500273
274 const embed = new EmojiEmbed()
275 .setTitle("Word Filters")
276 .setDescription(
277 `${emojiFromBoolean(current.enabled)} **Enabled**\n` +
Skyler Greyda16adf2023-03-05 10:22:12 +0000278 `**Strict Words:** ${listToAndMore(current.words.strict, 5)}\n` +
279 `**Loose Words:** ${listToAndMore(current.words.loose, 5)}\n\n` +
280 `**Users:** ` +
281 listToAndMore(
282 current.allowed.users.map((user) => `<@${user}>`),
283 5
284 ) +
285 `\n` +
286 `**Roles:** ` +
287 listToAndMore(
288 current.allowed.roles.map((role) => `<@&${role}>`),
289 5
290 ) +
291 `\n` +
292 `**Channels:** ` +
293 listToAndMore(
294 current.allowed.channels.map((channel) => `<#${channel}>`),
295 5
296 )
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500297 )
298 .setStatus("Success")
Skyler Greyda16adf2023-03-05 10:22:12 +0000299 .setEmoji("GUILD.SETTINGS.GREEN");
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500300
Skyler Greyda16adf2023-03-05 10:22:12 +0000301 await interaction.editReply({ embeds: [embed], components: [selectMenu, buttons] });
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500302
303 let i: ButtonInteraction | StringSelectMenuInteraction;
304 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000305 i = (await m.awaitMessageComponent({
306 filter: (i) => interaction.user.id === i.user.id && i.message.id === m.id,
307 time: 300000
308 })) as ButtonInteraction | StringSelectMenuInteraction;
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500309 } catch (e) {
310 closed = true;
311 break;
312 }
313
Skyler Greyda16adf2023-03-05 10:22:12 +0000314 if (i.isButton()) {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500315 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000316 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000317 case "back": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500318 closed = true;
319 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000320 }
321 case "enabled": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500322 current.enabled = !current.enabled;
323 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000324 }
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500325 }
326 } else {
Skyler Greyda16adf2023-03-05 10:22:12 +0000327 switch (i.values[0]) {
PineaFanb0d0c242023-02-05 10:59:45 +0000328 case "words": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000329 await interaction.editReply({
330 embeds: [
331 new EmojiEmbed()
332 .setTitle("Word Filter")
333 .setDescription("Modal opened. If you can't see it, click back and try again.")
334 .setStatus("Success")
335 .setEmoji("GUILD.SETTINGS.GREEN")
336 ],
337 components: [
338 new ActionRowBuilder<ButtonBuilder>().addComponents(
339 new ButtonBuilder()
340 .setLabel("Back")
341 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
342 .setStyle(ButtonStyle.Primary)
343 .setCustomId("back")
344 )
345 ]
346 });
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500347 const modal = new ModalBuilder()
348 .setTitle("Word Filter")
349 .setCustomId("wordFilter")
350 .addComponents(
Skyler Greyda16adf2023-03-05 10:22:12 +0000351 new ActionRowBuilder<TextInputBuilder>().addComponents(
352 new TextInputBuilder()
353 .setCustomId("wordStrict")
354 .setLabel("Strict Words")
355 .setPlaceholder(
356 "Matches anywhere in the message, including surrounded by other characters"
357 )
358 .setValue(current.words.strict.join(", "))
359 .setStyle(TextInputStyle.Paragraph)
360 .setRequired(false)
361 ),
362 new ActionRowBuilder<TextInputBuilder>().addComponents(
363 new TextInputBuilder()
364 .setCustomId("wordLoose")
365 .setLabel("Loose Words")
366 .setPlaceholder(
367 "Matches only if the word is by itself, surrounded by spaces or punctuation"
368 )
369 .setValue(current.words.loose.join(", "))
370 .setStyle(TextInputStyle.Paragraph)
371 .setRequired(false)
372 )
373 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500374
375 await i.showModal(modal);
376 let out;
377 try {
TheCodedProf01cba762023-02-18 15:55:05 -0500378 out = await modalInteractionCollector(m, interaction.user);
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500379 } catch (e) {
380 break;
381 }
382 if (!out) break;
Skyler Greyda16adf2023-03-05 10:22:12 +0000383 if (out.isButton()) break;
384 current.words.strict = out.fields
385 .getTextInputValue("wordStrict")
386 .split(",")
387 .map((s) => s.trim())
388 .filter((s) => s.length > 0);
389 current.words.loose = out.fields
390 .getTextInputValue("wordLoose")
391 .split(",")
392 .map((s) => s.trim())
393 .filter((s) => s.length > 0);
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500394 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000395 }
396 case "allowedUsers": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500397 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000398 current.allowed.users = await toSelectMenu(
399 interaction,
400 m,
401 current.allowed.users,
402 "member",
403 "Word Filter"
404 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500405 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000406 }
407 case "allowedRoles": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500408 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000409 current.allowed.roles = await toSelectMenu(
410 interaction,
411 m,
412 current.allowed.roles,
413 "role",
414 "Word Filter"
415 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500416 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000417 }
418 case "allowedChannels": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500419 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000420 current.allowed.channels = await toSelectMenu(
421 interaction,
422 m,
423 current.allowed.channels,
424 "channel",
425 "Word Filter"
426 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500427 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000428 }
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500429 }
430 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000431 } while (!closed);
TheCodedProf486bca32023-02-02 16:49:44 -0500432 return current;
Skyler Greyda16adf2023-03-05 10:22:12 +0000433};
TheCodedProf8b3da212023-02-02 15:09:55 -0500434
Skyler Greyda16adf2023-03-05 10:22:12 +0000435const inviteMenu = async (
436 interaction: StringSelectMenuInteraction,
437 m: Message,
438 current: {
439 enabled: boolean;
440 allowed: { users: string[]; roles: string[]; channels: string[] };
441 }
442): Promise<{
443 enabled: boolean;
444 allowed: { users: string[]; roles: string[]; channels: string[] };
TheCodedProf8b3da212023-02-02 15:09:55 -0500445}> => {
TheCodedProf486bca32023-02-02 16:49:44 -0500446 let closed = false;
447 do {
Skyler Greyda16adf2023-03-05 10:22:12 +0000448 const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
449 new ButtonBuilder()
450 .setCustomId("back")
451 .setLabel("Back")
452 .setStyle(ButtonStyle.Secondary)
453 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji),
454 new ButtonBuilder()
455 .setCustomId("enabled")
456 .setLabel(current.enabled ? "Enabled" : "Disabled")
457 .setStyle(current.enabled ? ButtonStyle.Success : ButtonStyle.Danger)
458 .setEmoji(emojiFromBoolean(current.enabled, "id") as APIMessageComponentEmoji)
459 );
460 const menu = new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
461 new StringSelectMenuBuilder()
462 .setCustomId("toEdit")
463 .setPlaceholder("Edit your allow list")
464 .addOptions(
465 new StringSelectMenuOptionBuilder()
466 .setLabel("Users")
467 .setDescription("Users that are allowed to send invites")
468 .setValue("users"),
469 new StringSelectMenuOptionBuilder()
470 .setLabel("Roles")
471 .setDescription("Roles that are allowed to send invites")
472 .setValue("roles"),
473 new StringSelectMenuOptionBuilder()
474 .setLabel("Channels")
475 .setDescription("Channels that anyone is allowed to send invites in")
476 .setValue("channels")
TheCodedProf486bca32023-02-02 16:49:44 -0500477 )
Skyler Greyda16adf2023-03-05 10:22:12 +0000478 .setDisabled(!current.enabled)
479 );
TheCodedProf486bca32023-02-02 16:49:44 -0500480
481 const embed = new EmojiEmbed()
482 .setTitle("Invite Settings")
483 .setDescription(
Skyler Greyda16adf2023-03-05 10:22:12 +0000484 "Automatically deletes invites sent by users (outside of staff members and self promotion channels)" +
485 `\n\n` +
486 `${emojiFromBoolean(current.enabled)} **${current.enabled ? "Enabled" : "Disabled"}**\n\n` +
487 `**Users:** ` +
488 listToAndMore(
489 current.allowed.users.map((user) => `<@${user}>`),
490 5
491 ) +
492 `\n` +
493 `**Roles:** ` +
494 listToAndMore(
495 current.allowed.roles.map((role) => `<@&${role}>`),
496 5
497 ) +
498 `\n` +
499 `**Channels:** ` +
500 listToAndMore(
501 current.allowed.channels.map((channel) => `<#${channel}>`),
502 5
503 )
TheCodedProf486bca32023-02-02 16:49:44 -0500504 )
505 .setStatus("Success")
Skyler Greyda16adf2023-03-05 10:22:12 +0000506 .setEmoji("GUILD.SETTINGS.GREEN");
TheCodedProf486bca32023-02-02 16:49:44 -0500507
Skyler Greyda16adf2023-03-05 10:22:12 +0000508 await interaction.editReply({ embeds: [embed], components: [menu, buttons] });
TheCodedProf486bca32023-02-02 16:49:44 -0500509
510 let i: ButtonInteraction | StringSelectMenuInteraction;
511 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000512 i = (await m.awaitMessageComponent({
513 filter: (i) => interaction.user.id === i.user.id && i.message.id === m.id,
514 time: 300000
515 })) as ButtonInteraction | StringSelectMenuInteraction;
TheCodedProf486bca32023-02-02 16:49:44 -0500516 } catch (e) {
517 return current;
518 }
519
Skyler Greyda16adf2023-03-05 10:22:12 +0000520 if (i.isButton()) {
TheCodedProf486bca32023-02-02 16:49:44 -0500521 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000522 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000523 case "back": {
TheCodedProf486bca32023-02-02 16:49:44 -0500524 closed = true;
525 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000526 }
527 case "enabled": {
TheCodedProf486bca32023-02-02 16:49:44 -0500528 current.enabled = !current.enabled;
529 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000530 }
TheCodedProf486bca32023-02-02 16:49:44 -0500531 }
532 } else {
533 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000534 switch (i.values[0]) {
PineaFanb0d0c242023-02-05 10:59:45 +0000535 case "users": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000536 current.allowed.users = await toSelectMenu(
537 interaction,
538 m,
539 current.allowed.users,
540 "member",
541 "Invite Settings"
542 );
TheCodedProf486bca32023-02-02 16:49:44 -0500543 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000544 }
545 case "roles": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000546 current.allowed.roles = await toSelectMenu(
547 interaction,
548 m,
549 current.allowed.roles,
550 "role",
551 "Invite Settings"
552 );
TheCodedProf486bca32023-02-02 16:49:44 -0500553 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000554 }
555 case "channels": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000556 current.allowed.channels = await toSelectMenu(
557 interaction,
558 m,
559 current.allowed.channels,
560 "channel",
561 "Invite Settings"
562 );
TheCodedProf486bca32023-02-02 16:49:44 -0500563 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000564 }
TheCodedProf486bca32023-02-02 16:49:44 -0500565 }
566 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000567 } while (!closed);
TheCodedProf486bca32023-02-02 16:49:44 -0500568 return current;
Skyler Greyda16adf2023-03-05 10:22:12 +0000569};
TheCodedProf8b3da212023-02-02 15:09:55 -0500570
Skyler Greyda16adf2023-03-05 10:22:12 +0000571const mentionMenu = async (
572 interaction: StringSelectMenuInteraction,
573 m: Message,
574 current: {
575 mass: number;
576 everyone: boolean;
577 roles: boolean;
578 allowed: {
579 roles: string[];
580 rolesToMention: string[];
581 users: string[];
582 channels: string[];
583 };
TheCodedProf8b3da212023-02-02 15:09:55 -0500584 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000585): Promise<{
586 mass: number;
587 everyone: boolean;
588 roles: boolean;
TheCodedProf8b3da212023-02-02 15:09:55 -0500589 allowed: {
Skyler Greyda16adf2023-03-05 10:22:12 +0000590 roles: string[];
591 rolesToMention: string[];
592 users: string[];
593 channels: string[];
594 };
TheCodedProf8b3da212023-02-02 15:09:55 -0500595}> => {
TheCodedProf486bca32023-02-02 16:49:44 -0500596 let closed = false;
597
598 do {
Skyler Greyda16adf2023-03-05 10:22:12 +0000599 const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
600 new ButtonBuilder()
601 .setCustomId("back")
602 .setLabel("Back")
603 .setStyle(ButtonStyle.Secondary)
604 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji),
605 new ButtonBuilder()
606 .setCustomId("everyone")
607 .setLabel(current.everyone ? "Everyone" : "No one")
608 .setStyle(current.everyone ? ButtonStyle.Success : ButtonStyle.Danger)
609 .setEmoji(emojiFromBoolean(current.everyone, "id") as APIMessageComponentEmoji),
610 new ButtonBuilder()
611 .setCustomId("roles")
612 .setLabel(current.roles ? "Roles" : "No roles")
613 .setStyle(current.roles ? ButtonStyle.Success : ButtonStyle.Danger)
614 .setEmoji(emojiFromBoolean(current.roles, "id") as APIMessageComponentEmoji)
615 );
616 const menu = new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
617 new StringSelectMenuBuilder()
618 .setCustomId("toEdit")
619 .setPlaceholder("Edit mention settings")
620 .addOptions(
621 new StringSelectMenuOptionBuilder()
622 .setLabel("Mass Mention Amount")
623 .setDescription("The amount of mentions before the bot will delete the message")
624 .setValue("mass"),
625 new StringSelectMenuOptionBuilder()
626 .setLabel("Roles")
627 .setDescription("Roles that are able to be mentioned")
628 .setValue("roles")
629 )
630 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500631
Skyler Greyda16adf2023-03-05 10:22:12 +0000632 const allowedMenu = new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
633 new StringSelectMenuBuilder()
634 .setCustomId("allowed")
635 .setPlaceholder("Edit exceptions")
636 .addOptions(
637 new StringSelectMenuOptionBuilder()
638 .setLabel("Users")
639 .setDescription("Users that are unaffected by the mention filter")
640 .setValue("users"),
641 new StringSelectMenuOptionBuilder()
642 .setLabel("Roles")
643 .setDescription("Roles that are unaffected by the mention filter")
644 .setValue("roles"),
645 new StringSelectMenuOptionBuilder()
646 .setLabel("Channels")
647 .setDescription("Channels where anyone is unaffected by the mention filter")
648 .setValue("channels")
649 )
650 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500651
652 const embed = new EmojiEmbed()
653 .setTitle("Mention Settings")
654 .setDescription(
655 `Log when members mention:\n` +
Skyler Greyda16adf2023-03-05 10:22:12 +0000656 `${emojiFromBoolean(true)} **${current.mass}+ members** in one message\n` +
657 `${emojiFromBoolean(current.everyone)} **Everyone**\n` +
658 `${emojiFromBoolean(current.roles)} **Roles**\n` +
659 (current.allowed.rolesToMention.length > 0
660 ? `> *Except for ${listToAndMore(
661 current.allowed.rolesToMention.map((r) => `<@&${r}>`),
662 3
663 )}*\n`
664 : "") +
665 "\n" +
666 `Except if...\n` +
667 `> ${
668 current.allowed.users.length > 0
669 ? `Member is: ${listToAndMore(
670 current.allowed.users.map((u) => `<@${u}>`),
671 3
672 )}\n`
673 : ""
674 }` +
675 `> ${
676 current.allowed.roles.length > 0
677 ? `Member has role: ${listToAndMore(
678 current.allowed.roles.map((r) => `<@&${r}>`),
679 3
680 )}\n`
681 : ""
682 }` +
683 `> ${
684 current.allowed.channels.length > 0
685 ? `In channel: ${listToAndMore(
686 current.allowed.channels.map((c) => `<#${c}>`),
687 3
688 )}\n`
689 : ""
690 }`
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500691 )
692 .setStatus("Success")
Skyler Greyda16adf2023-03-05 10:22:12 +0000693 .setEmoji("GUILD.SETTINGS.GREEN");
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500694
Skyler Greyda16adf2023-03-05 10:22:12 +0000695 await interaction.editReply({ embeds: [embed], components: [menu, allowedMenu, buttons] });
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500696
697 let i: ButtonInteraction | StringSelectMenuInteraction;
698 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000699 i = (await m.awaitMessageComponent({
700 filter: (i) => interaction.user.id === i.user.id && i.message.id === m.id,
701 time: 300000
702 })) as ButtonInteraction | StringSelectMenuInteraction;
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500703 } catch (e) {
704 closed = true;
705 break;
706 }
707
Skyler Greyda16adf2023-03-05 10:22:12 +0000708 if (i.isButton()) {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500709 await i.deferUpdate();
710 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000711 case "back": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500712 closed = true;
713 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000714 }
715 case "everyone": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500716 current.everyone = !current.everyone;
717 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000718 }
719 case "roles": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500720 current.roles = !current.roles;
721 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000722 }
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500723 }
724 } else {
725 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000726 case "toEdit": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500727 switch (i.values[0]) {
PineaFanb0d0c242023-02-05 10:59:45 +0000728 case "mass": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000729 await interaction.editReply({
730 embeds: [
731 new EmojiEmbed()
732 .setTitle("Word Filter")
733 .setDescription("Modal opened. If you can't see it, click back and try again.")
734 .setStatus("Success")
735 .setEmoji("GUILD.SETTINGS.GREEN")
736 ],
737 components: [
738 new ActionRowBuilder<ButtonBuilder>().addComponents(
739 new ButtonBuilder()
740 .setLabel("Back")
741 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
742 .setStyle(ButtonStyle.Primary)
743 .setCustomId("back")
744 )
745 ]
746 });
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500747 const modal = new ModalBuilder()
748 .setTitle("Mass Mention Amount")
749 .setCustomId("mass")
750 .addComponents(
Skyler Greyda16adf2023-03-05 10:22:12 +0000751 new ActionRowBuilder<TextInputBuilder>().addComponents(
752 new TextInputBuilder()
753 .setCustomId("mass")
754 .setPlaceholder("Amount")
755 .setMinLength(1)
756 .setMaxLength(3)
757 .setStyle(TextInputStyle.Short)
758 )
759 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500760 await i.showModal(modal);
761 let out;
762 try {
TheCodedProf01cba762023-02-18 15:55:05 -0500763 out = await modalInteractionCollector(m, interaction.user);
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500764 } catch (e) {
765 break;
766 }
767 if (!out) break;
Skyler Greyda16adf2023-03-05 10:22:12 +0000768 if (out.isButton()) break;
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500769 current.mass = parseInt(out.fields.getTextInputValue("mass"));
770 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000771 }
772 case "roles": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500773 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000774 current.allowed.rolesToMention = await toSelectMenu(
775 interaction,
776 m,
777 current.allowed.rolesToMention,
778 "role",
779 "Mention Settings"
780 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500781 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000782 }
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500783 }
784 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000785 }
786 case "allowed": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500787 await i.deferUpdate();
788 switch (i.values[0]) {
PineaFanb0d0c242023-02-05 10:59:45 +0000789 case "users": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000790 current.allowed.users = await toSelectMenu(
791 interaction,
792 m,
793 current.allowed.users,
794 "member",
795 "Mention Settings"
796 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500797 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000798 }
799 case "roles": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000800 current.allowed.roles = await toSelectMenu(
801 interaction,
802 m,
803 current.allowed.roles,
804 "role",
805 "Mention Settings"
806 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500807 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000808 }
809 case "channels": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000810 current.allowed.channels = await toSelectMenu(
811 interaction,
812 m,
813 current.allowed.channels,
814 "channel",
815 "Mention Settings"
816 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500817 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000818 }
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500819 }
820 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000821 }
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500822 }
823 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000824 } while (!closed);
825 return current;
826};
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500827
Skyler Greyda16adf2023-03-05 10:22:12 +0000828const cleanMenu = async (
829 interaction: StringSelectMenuInteraction,
830 m: Message,
831 current?: {
832 channels?: string[];
833 allowed?: {
834 roles: string[];
835 users: string[];
836 };
TheCodedProfad0b8202023-02-14 14:27:09 -0500837 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000838): Promise<{
839 channels: string[];
TheCodedProfad0b8202023-02-14 14:27:09 -0500840 allowed: {
Skyler Greyda16adf2023-03-05 10:22:12 +0000841 roles: string[];
842 users: string[];
843 };
TheCodedProfad0b8202023-02-14 14:27:09 -0500844}> => {
845 let closed = false;
Skyler Greyda16adf2023-03-05 10:22:12 +0000846 if (!current) current = { channels: [], allowed: { roles: [], users: [] } };
847 if (!current.channels) current.channels = [];
848 if (!current.allowed) current.allowed = { roles: [], users: [] };
TheCodedProfad0b8202023-02-14 14:27:09 -0500849
Skyler Greyda16adf2023-03-05 10:22:12 +0000850 const channelMenu = new ActionRowBuilder<ChannelSelectMenuBuilder>().addComponents(
851 new ChannelSelectMenuBuilder().setCustomId("toAdd").setPlaceholder("Select a channel")
852 );
TheCodedProfad0b8202023-02-14 14:27:09 -0500853
Skyler Greyda16adf2023-03-05 10:22:12 +0000854 const allowedMenu = new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
855 new StringSelectMenuBuilder()
856 .setCustomId("allowed")
857 .setPlaceholder("Edit exceptions")
858 .addOptions(
859 new StringSelectMenuOptionBuilder()
860 .setLabel("Users")
861 .setDescription("Users that are unaffected by the mention filter")
862 .setValue("users"),
863 new StringSelectMenuOptionBuilder()
864 .setLabel("Roles")
865 .setDescription("Roles that are unaffected by the mention filter")
866 .setValue("roles")
867 )
868 );
TheCodedProfad0b8202023-02-14 14:27:09 -0500869
870 do {
Skyler Greyda16adf2023-03-05 10:22:12 +0000871 const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
872 new ButtonBuilder()
873 .setCustomId("back")
874 .setLabel("Back")
875 .setStyle(ButtonStyle.Primary)
876 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
877 );
TheCodedProfad0b8202023-02-14 14:27:09 -0500878
879 const embed = new EmojiEmbed()
880 .setTitle("Clean Settings")
881 .setEmoji("GUILD.SETTINGS.GREEN")
882 .setDescription(
883 `Current clean channels:\n\n` +
Skyler Greyda16adf2023-03-05 10:22:12 +0000884 `${
885 current.channels.length > 0
886 ? listToAndMore(
887 current.channels.map((c) => `<#${c}>`),
888 10
889 )
890 : "None"
891 }\n\n`
TheCodedProfad0b8202023-02-14 14:27:09 -0500892 )
Skyler Greyda16adf2023-03-05 10:22:12 +0000893 .setStatus("Success");
TheCodedProfad0b8202023-02-14 14:27:09 -0500894
Skyler Greyda16adf2023-03-05 10:22:12 +0000895 await interaction.editReply({ embeds: [embed], components: [channelMenu, allowedMenu, buttons] });
TheCodedProfad0b8202023-02-14 14:27:09 -0500896
897 let i: ButtonInteraction | ChannelSelectMenuInteraction;
898 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000899 i = (await m.awaitMessageComponent({
900 filter: (i) => interaction.user.id === i.user.id && i.message.id === m.id,
901 time: 300000
902 })) as ButtonInteraction | ChannelSelectMenuInteraction;
TheCodedProfad0b8202023-02-14 14:27:09 -0500903 } catch (e) {
904 closed = true;
905 break;
906 }
907 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000908 if (i.isButton()) {
TheCodedProfad0b8202023-02-14 14:27:09 -0500909 switch (i.customId) {
910 case "back": {
911 closed = true;
912 break;
913 }
914 }
915 } else {
916 switch (i.customId) {
917 case "toAdd": {
TheCodedProf1807fb32023-02-20 14:33:48 -0500918 const channelEmbed = new EmojiEmbed()
TheCodedProfad0b8202023-02-14 14:27:09 -0500919 .setTitle("Clean Settings")
920 .setDescription(`Editing <#${i.values[0]}>`)
921 .setEmoji("GUILD.SETTINGS.GREEN")
Skyler Greyda16adf2023-03-05 10:22:12 +0000922 .setStatus("Success");
923 const channelButtons = new ActionRowBuilder<ButtonBuilder>().addComponents(
924 new ButtonBuilder()
925 .setCustomId("back")
926 .setLabel("Back")
927 .setStyle(ButtonStyle.Primary)
928 .setEmoji(getEmojiByName("CONTROL.LEFT", "id")),
929 new ButtonBuilder()
930 .setCustomId("switch")
931 .setLabel(current.channels.includes(i.values[0]!) ? "Remove" : "Add")
932 .setStyle(
933 current.channels.includes(i.values[0]!) ? ButtonStyle.Danger : ButtonStyle.Success
934 )
935 );
TheCodedProfad0b8202023-02-14 14:27:09 -0500936
Skyler Greyda16adf2023-03-05 10:22:12 +0000937 await i.editReply({ embeds: [channelEmbed], components: [channelButtons] });
TheCodedProfad0b8202023-02-14 14:27:09 -0500938 let j: ButtonInteraction;
939 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000940 j = (await m.awaitMessageComponent({
941 filter: (i) => interaction.user.id === i.user.id && i.message.id === m.id,
942 time: 300000
943 })) as ButtonInteraction;
TheCodedProfad0b8202023-02-14 14:27:09 -0500944 } catch (e) {
945 closed = true;
946 break;
947 }
948 await j.deferUpdate();
949 switch (j.customId) {
950 case "back": {
951 break;
952 }
953 case "switch": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000954 if (current.channels.includes(i.values[0]!)) {
TheCodedProfad0b8202023-02-14 14:27:09 -0500955 current.channels.splice(current.channels.indexOf(i.values[0]!), 1);
956 } else {
957 current.channels.push(i.values[0]!);
958 }
959 }
960 }
961 break;
962 }
963 case "allowed": {
964 switch (i.values[0]) {
965 case "users": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000966 current.allowed.users = await toSelectMenu(
967 interaction,
968 m,
969 current.allowed.users,
970 "member",
971 "Mention Settings"
972 );
TheCodedProfad0b8202023-02-14 14:27:09 -0500973 break;
974 }
975 case "roles": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000976 current.allowed.roles = await toSelectMenu(
977 interaction,
978 m,
979 current.allowed.roles,
980 "role",
981 "Mention Settings"
982 );
TheCodedProfad0b8202023-02-14 14:27:09 -0500983 break;
984 }
985 }
986 break;
987 }
988 }
989 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000990 } while (!closed);
TheCodedProfad0b8202023-02-14 14:27:09 -0500991
TheCodedProf1807fb32023-02-20 14:33:48 -0500992 return current as {
Skyler Greyda16adf2023-03-05 10:22:12 +0000993 channels: string[];
TheCodedProf1807fb32023-02-20 14:33:48 -0500994 allowed: {
Skyler Greyda16adf2023-03-05 10:22:12 +0000995 roles: string[];
996 users: string[];
997 };
TheCodedProf1807fb32023-02-20 14:33:48 -0500998 };
Skyler Greyda16adf2023-03-05 10:22:12 +0000999};
TheCodedProfad0b8202023-02-14 14:27:09 -05001000
TheCodedProf8b3da212023-02-02 15:09:55 -05001001const callback = async (interaction: CommandInteraction): Promise<void> => {
1002 if (!interaction.guild) return;
Skyler Greyda16adf2023-03-05 10:22:12 +00001003 const m = await interaction.reply({ embeds: LoadingEmbed, fetchReply: true, ephemeral: true });
TheCodedProf8b3da212023-02-02 15:09:55 -05001004 const config = (await client.database.guilds.read(interaction.guild.id)).filters;
1005
1006 let closed = false;
1007
Skyler Greyda16adf2023-03-05 10:22:12 +00001008 const button = new ActionRowBuilder<ButtonBuilder>().addComponents(
1009 new ButtonBuilder().setCustomId("save").setLabel("Save").setStyle(ButtonStyle.Success)
1010 );
TheCodedProf8b3da212023-02-02 15:09:55 -05001011
1012 do {
Skyler Greyda16adf2023-03-05 10:22:12 +00001013 const selectMenu = new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
1014 new StringSelectMenuBuilder()
1015 .setCustomId("filter")
1016 .setPlaceholder("Select a filter to edit")
1017 .addOptions(
1018 new StringSelectMenuOptionBuilder()
1019 .setLabel("Invites")
1020 .setDescription("Automatically delete messages containing server invites")
1021 .setValue("invites"),
1022 new StringSelectMenuOptionBuilder()
1023 .setLabel("Mentions")
1024 .setDescription("Deletes messages with excessive mentions")
1025 .setValue("mentions"),
1026 new StringSelectMenuOptionBuilder()
1027 .setLabel("Words")
1028 .setDescription("Delete messages containing filtered words")
1029 .setValue("words"),
1030 new StringSelectMenuOptionBuilder()
1031 .setLabel("Malware")
1032 .setDescription("Automatically delete files and links containing malware")
1033 .setValue("malware"),
1034 new StringSelectMenuOptionBuilder()
1035 .setLabel("Images")
1036 .setDescription("Checks performed on images (NSFW, size checking, etc.)")
1037 .setValue("images"),
1038 new StringSelectMenuOptionBuilder()
1039 .setLabel("Clean")
1040 .setDescription("Automatically delete new messages in specific channels")
1041 .setValue("clean")
1042 )
1043 );
TheCodedProf8b3da212023-02-02 15:09:55 -05001044
1045 const embed = new EmojiEmbed()
1046 .setTitle("Automod Settings")
1047 .setDescription(
TheCodedProf486bca32023-02-02 16:49:44 -05001048 `${emojiFromBoolean(config.invite.enabled)} **Invites**\n` +
Skyler Greyda16adf2023-03-05 10:22:12 +00001049 `${emojiFromBoolean(
1050 config.pings.everyone || config.pings.mass > 0 || config.pings.roles
1051 )} **Mentions**\n` +
1052 `${emojiFromBoolean(config.wordFilter.enabled)} **Words**\n` +
1053 `${emojiFromBoolean(config.malware)} **Malware**\n` +
1054 `${emojiFromBoolean(config.images.NSFW || config.images.size)} **Images**\n` +
1055 `${emojiFromBoolean(config.clean.channels.length > 0)} **Clean**\n`
TheCodedProf8b3da212023-02-02 15:09:55 -05001056 )
TheCodedProf486bca32023-02-02 16:49:44 -05001057 .setStatus("Success")
Skyler Greyda16adf2023-03-05 10:22:12 +00001058 .setEmoji("GUILD.SETTINGS.GREEN");
TheCodedProf8b3da212023-02-02 15:09:55 -05001059
Skyler Greyda16adf2023-03-05 10:22:12 +00001060 await interaction.editReply({ embeds: [embed], components: [selectMenu, button] });
TheCodedProf8b3da212023-02-02 15:09:55 -05001061
1062 let i: StringSelectMenuInteraction | ButtonInteraction;
1063 try {
Skyler Greyda16adf2023-03-05 10:22:12 +00001064 i = (await m.awaitMessageComponent({
1065 filter: (i) => i.user.id === interaction.user.id && i.message.id === m.id,
1066 time: 300000
1067 })) as StringSelectMenuInteraction | ButtonInteraction;
TheCodedProf8b3da212023-02-02 15:09:55 -05001068 } catch (e) {
1069 closed = true;
PineaFanb0d0c242023-02-05 10:59:45 +00001070 continue;
TheCodedProf8b3da212023-02-02 15:09:55 -05001071 }
Skyler Greyda16adf2023-03-05 10:22:12 +00001072 if (i.isButton()) {
pineafan6de4da52023-03-07 20:43:44 +00001073 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +00001074 await client.database.guilds.write(interaction.guild.id, { filters: config });
Skyler Grey16ecb172023-03-05 07:30:32 +00001075 await client.memory.forceUpdate(interaction.guild.id);
TheCodedProf8b3da212023-02-02 15:09:55 -05001076 } else {
Skyler Greyda16adf2023-03-05 10:22:12 +00001077 switch (i.values[0]) {
PineaFanb0d0c242023-02-05 10:59:45 +00001078 case "invites": {
pineafan6de4da52023-03-07 20:43:44 +00001079 i.deferUpdate();
TheCodedProf486bca32023-02-02 16:49:44 -05001080 config.invite = await inviteMenu(i, m, config.invite);
TheCodedProf8b3da212023-02-02 15:09:55 -05001081 break;
PineaFanb0d0c242023-02-05 10:59:45 +00001082 }
1083 case "mentions": {
pineafan6de4da52023-03-07 20:43:44 +00001084 i.deferUpdate();
TheCodedProf486bca32023-02-02 16:49:44 -05001085 config.pings = await mentionMenu(i, m, config.pings);
TheCodedProf8b3da212023-02-02 15:09:55 -05001086 break;
PineaFanb0d0c242023-02-05 10:59:45 +00001087 }
1088 case "words": {
TheCodedProf486bca32023-02-02 16:49:44 -05001089 config.wordFilter = await wordMenu(i, m, config.wordFilter);
TheCodedProf8b3da212023-02-02 15:09:55 -05001090 break;
PineaFanb0d0c242023-02-05 10:59:45 +00001091 }
1092 case "malware": {
Skyler Greyd1157312023-03-08 10:07:38 +00001093 await i.deferUpdate();
TheCodedProf8b3da212023-02-02 15:09:55 -05001094 config.malware = !config.malware;
1095 break;
PineaFanb0d0c242023-02-05 10:59:45 +00001096 }
1097 case "images": {
Skyler Greyd1157312023-03-08 10:07:38 +00001098 await i.deferUpdate();
PineaFanb0d0c242023-02-05 10:59:45 +00001099 const next = await imageMenu(i, m, config.images);
1100 config.images = next;
TheCodedProf8b3da212023-02-02 15:09:55 -05001101 break;
PineaFanb0d0c242023-02-05 10:59:45 +00001102 }
TheCodedProfad0b8202023-02-14 14:27:09 -05001103 case "clean": {
Skyler Greyd1157312023-03-08 10:07:38 +00001104 await i.deferUpdate();
TheCodedProfad0b8202023-02-14 14:27:09 -05001105 const next = await cleanMenu(i, m, config.clean);
1106 config.clean = next;
1107 break;
1108 }
TheCodedProf8b3da212023-02-02 15:09:55 -05001109 }
1110 }
Skyler Greyda16adf2023-03-05 10:22:12 +00001111 } while (!closed);
1112 await interaction.deleteReply();
TheCodedProf8b3da212023-02-02 15:09:55 -05001113};
1114
1115const check = (interaction: CommandInteraction, _partial: boolean = false) => {
1116 const member = interaction.member as Discord.GuildMember;
1117 if (!member.permissions.has("ManageMessages"))
1118 return "You must have the *Manage Messages* permission to use this command";
1119 return true;
1120};
1121
1122export { command };
1123export { callback };
1124export { check };