blob: dc2c72391b5b0fb748ccfa5555986c4b1d2f6611 [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")
pineafan10ac5542023-03-19 10:06:19 +0000187 .setStatus("Success")
188 // .setEmoji("") // TODO
TheCodedProf8b3da212023-02-02 15:09:55 -0500189 .setDescription(
Skyler Greyda16adf2023-03-05 10:22:12 +0000190 `${emojiFromBoolean(current.NSFW)} **NSFW**\n` + `${emojiFromBoolean(current.size)} **Size**\n`
191 );
TheCodedProf8b3da212023-02-02 15:09:55 -0500192
Skyler Greyda16adf2023-03-05 10:22:12 +0000193 await interaction.editReply({ embeds: [embed], components: [options] });
TheCodedProf8b3da212023-02-02 15:09:55 -0500194
195 let i: ButtonInteraction;
196 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000197 i = (await m.awaitMessageComponent({
198 filter: (i) => interaction.user.id === i.user.id && i.message.id === m.id,
199 time: 300000
200 })) as ButtonInteraction;
TheCodedProf8b3da212023-02-02 15:09:55 -0500201 } catch (e) {
202 return current;
203 }
204 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000205 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000206 case "back": {
TheCodedProf8b3da212023-02-02 15:09:55 -0500207 closed = true;
208 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000209 }
210 case "nsfw": {
TheCodedProf8b3da212023-02-02 15:09:55 -0500211 current.NSFW = !current.NSFW;
212 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000213 }
214 case "size": {
TheCodedProf8b3da212023-02-02 15:09:55 -0500215 current.size = !current.size;
216 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000217 }
TheCodedProf8b3da212023-02-02 15:09:55 -0500218 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000219 } while (!closed);
TheCodedProf8b3da212023-02-02 15:09:55 -0500220 return current;
Skyler Greyda16adf2023-03-05 10:22:12 +0000221};
TheCodedProf8b3da212023-02-02 15:09:55 -0500222
Skyler Greyda16adf2023-03-05 10:22:12 +0000223const wordMenu = async (
224 interaction: StringSelectMenuInteraction,
225 m: Message,
226 current: {
227 enabled: boolean;
228 words: { strict: string[]; loose: string[] };
229 allowed: { users: string[]; roles: string[]; channels: string[] };
230 }
231): Promise<{
232 enabled: boolean;
233 words: { strict: string[]; loose: string[] };
234 allowed: { users: string[]; roles: string[]; channels: string[] };
TheCodedProf8b3da212023-02-02 15:09:55 -0500235}> => {
TheCodedProf486bca32023-02-02 16:49:44 -0500236 let closed = false;
237 do {
Skyler Greyda16adf2023-03-05 10:22:12 +0000238 const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
239 new ButtonBuilder()
240 .setCustomId("back")
241 .setLabel("Back")
242 .setStyle(ButtonStyle.Secondary)
243 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji),
244 new ButtonBuilder()
245 .setCustomId("enabled")
246 .setLabel("Enabled")
247 .setStyle(current.enabled ? ButtonStyle.Success : ButtonStyle.Danger)
248 .setEmoji(emojiFromBoolean(current.enabled, "id") as APIMessageComponentEmoji)
249 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500250
Skyler Greyda16adf2023-03-05 10:22:12 +0000251 const selectMenu = new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
252 new StringSelectMenuBuilder()
253 .setCustomId("edit")
254 .setPlaceholder("Edit... ")
255 .addOptions(
256 new StringSelectMenuOptionBuilder()
257 .setLabel("Words")
258 .setDescription("Edit your list of words to filter")
259 .setValue("words"),
260 new StringSelectMenuOptionBuilder()
261 .setLabel("Allowed Users")
262 .setDescription("Users who will be unaffected by the word filter")
263 .setValue("allowedUsers"),
264 new StringSelectMenuOptionBuilder()
265 .setLabel("Allowed Roles")
266 .setDescription("Roles that will be unaffected by the word filter")
267 .setValue("allowedRoles"),
268 new StringSelectMenuOptionBuilder()
269 .setLabel("Allowed Channels")
270 .setDescription("Channels where the word filter will not apply")
271 .setValue("allowedChannels")
272 )
273 .setDisabled(!current.enabled)
274 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500275
276 const embed = new EmojiEmbed()
277 .setTitle("Word Filters")
278 .setDescription(
279 `${emojiFromBoolean(current.enabled)} **Enabled**\n` +
Skyler Greyda16adf2023-03-05 10:22:12 +0000280 `**Strict Words:** ${listToAndMore(current.words.strict, 5)}\n` +
281 `**Loose Words:** ${listToAndMore(current.words.loose, 5)}\n\n` +
282 `**Users:** ` +
283 listToAndMore(
284 current.allowed.users.map((user) => `<@${user}>`),
285 5
286 ) +
287 `\n` +
288 `**Roles:** ` +
289 listToAndMore(
290 current.allowed.roles.map((role) => `<@&${role}>`),
291 5
292 ) +
293 `\n` +
294 `**Channels:** ` +
295 listToAndMore(
296 current.allowed.channels.map((channel) => `<#${channel}>`),
297 5
298 )
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500299 )
300 .setStatus("Success")
Skyler Greyda16adf2023-03-05 10:22:12 +0000301 .setEmoji("GUILD.SETTINGS.GREEN");
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500302
Skyler Greyda16adf2023-03-05 10:22:12 +0000303 await interaction.editReply({ embeds: [embed], components: [selectMenu, buttons] });
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500304
305 let i: ButtonInteraction | StringSelectMenuInteraction;
306 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000307 i = (await m.awaitMessageComponent({
308 filter: (i) => interaction.user.id === i.user.id && i.message.id === m.id,
309 time: 300000
310 })) as ButtonInteraction | StringSelectMenuInteraction;
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500311 } catch (e) {
312 closed = true;
313 break;
314 }
315
Skyler Greyda16adf2023-03-05 10:22:12 +0000316 if (i.isButton()) {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500317 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000318 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000319 case "back": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500320 closed = true;
321 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000322 }
323 case "enabled": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500324 current.enabled = !current.enabled;
325 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000326 }
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500327 }
328 } else {
Skyler Greyda16adf2023-03-05 10:22:12 +0000329 switch (i.values[0]) {
PineaFanb0d0c242023-02-05 10:59:45 +0000330 case "words": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000331 await interaction.editReply({
332 embeds: [
333 new EmojiEmbed()
334 .setTitle("Word Filter")
335 .setDescription("Modal opened. If you can't see it, click back and try again.")
336 .setStatus("Success")
337 .setEmoji("GUILD.SETTINGS.GREEN")
338 ],
339 components: [
340 new ActionRowBuilder<ButtonBuilder>().addComponents(
341 new ButtonBuilder()
342 .setLabel("Back")
343 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
344 .setStyle(ButtonStyle.Primary)
345 .setCustomId("back")
346 )
347 ]
348 });
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500349 const modal = new ModalBuilder()
350 .setTitle("Word Filter")
351 .setCustomId("wordFilter")
352 .addComponents(
Skyler Greyda16adf2023-03-05 10:22:12 +0000353 new ActionRowBuilder<TextInputBuilder>().addComponents(
354 new TextInputBuilder()
355 .setCustomId("wordStrict")
356 .setLabel("Strict Words")
357 .setPlaceholder(
358 "Matches anywhere in the message, including surrounded by other characters"
359 )
360 .setValue(current.words.strict.join(", "))
361 .setStyle(TextInputStyle.Paragraph)
362 .setRequired(false)
363 ),
364 new ActionRowBuilder<TextInputBuilder>().addComponents(
365 new TextInputBuilder()
366 .setCustomId("wordLoose")
367 .setLabel("Loose Words")
368 .setPlaceholder(
369 "Matches only if the word is by itself, surrounded by spaces or punctuation"
370 )
371 .setValue(current.words.loose.join(", "))
372 .setStyle(TextInputStyle.Paragraph)
373 .setRequired(false)
374 )
375 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500376
377 await i.showModal(modal);
378 let out;
379 try {
TheCodedProf01cba762023-02-18 15:55:05 -0500380 out = await modalInteractionCollector(m, interaction.user);
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500381 } catch (e) {
382 break;
383 }
384 if (!out) break;
Skyler Greyda16adf2023-03-05 10:22:12 +0000385 if (out.isButton()) break;
386 current.words.strict = out.fields
387 .getTextInputValue("wordStrict")
388 .split(",")
389 .map((s) => s.trim())
390 .filter((s) => s.length > 0);
391 current.words.loose = out.fields
392 .getTextInputValue("wordLoose")
393 .split(",")
394 .map((s) => s.trim())
395 .filter((s) => s.length > 0);
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500396 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000397 }
398 case "allowedUsers": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500399 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000400 current.allowed.users = await toSelectMenu(
401 interaction,
402 m,
403 current.allowed.users,
404 "member",
405 "Word Filter"
406 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500407 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000408 }
409 case "allowedRoles": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500410 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000411 current.allowed.roles = await toSelectMenu(
412 interaction,
413 m,
414 current.allowed.roles,
415 "role",
416 "Word Filter"
417 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500418 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000419 }
420 case "allowedChannels": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500421 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000422 current.allowed.channels = await toSelectMenu(
423 interaction,
424 m,
425 current.allowed.channels,
426 "channel",
427 "Word Filter"
428 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500429 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000430 }
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500431 }
432 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000433 } while (!closed);
TheCodedProf486bca32023-02-02 16:49:44 -0500434 return current;
Skyler Greyda16adf2023-03-05 10:22:12 +0000435};
TheCodedProf8b3da212023-02-02 15:09:55 -0500436
Skyler Greyda16adf2023-03-05 10:22:12 +0000437const inviteMenu = async (
438 interaction: StringSelectMenuInteraction,
439 m: Message,
440 current: {
441 enabled: boolean;
442 allowed: { users: string[]; roles: string[]; channels: string[] };
443 }
444): Promise<{
445 enabled: boolean;
446 allowed: { users: string[]; roles: string[]; channels: string[] };
TheCodedProf8b3da212023-02-02 15:09:55 -0500447}> => {
TheCodedProf486bca32023-02-02 16:49:44 -0500448 let closed = false;
449 do {
Skyler Greyda16adf2023-03-05 10:22:12 +0000450 const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
451 new ButtonBuilder()
452 .setCustomId("back")
453 .setLabel("Back")
454 .setStyle(ButtonStyle.Secondary)
455 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji),
456 new ButtonBuilder()
457 .setCustomId("enabled")
458 .setLabel(current.enabled ? "Enabled" : "Disabled")
459 .setStyle(current.enabled ? ButtonStyle.Success : ButtonStyle.Danger)
460 .setEmoji(emojiFromBoolean(current.enabled, "id") as APIMessageComponentEmoji)
461 );
462 const menu = new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
463 new StringSelectMenuBuilder()
464 .setCustomId("toEdit")
465 .setPlaceholder("Edit your allow list")
466 .addOptions(
467 new StringSelectMenuOptionBuilder()
468 .setLabel("Users")
469 .setDescription("Users that are allowed to send invites")
470 .setValue("users"),
471 new StringSelectMenuOptionBuilder()
472 .setLabel("Roles")
473 .setDescription("Roles that are allowed to send invites")
474 .setValue("roles"),
475 new StringSelectMenuOptionBuilder()
476 .setLabel("Channels")
477 .setDescription("Channels that anyone is allowed to send invites in")
478 .setValue("channels")
TheCodedProf486bca32023-02-02 16:49:44 -0500479 )
Skyler Greyda16adf2023-03-05 10:22:12 +0000480 .setDisabled(!current.enabled)
481 );
TheCodedProf486bca32023-02-02 16:49:44 -0500482
483 const embed = new EmojiEmbed()
484 .setTitle("Invite Settings")
485 .setDescription(
Skyler Greyda16adf2023-03-05 10:22:12 +0000486 "Automatically deletes invites sent by users (outside of staff members and self promotion channels)" +
487 `\n\n` +
488 `${emojiFromBoolean(current.enabled)} **${current.enabled ? "Enabled" : "Disabled"}**\n\n` +
489 `**Users:** ` +
490 listToAndMore(
491 current.allowed.users.map((user) => `<@${user}>`),
492 5
493 ) +
494 `\n` +
495 `**Roles:** ` +
496 listToAndMore(
497 current.allowed.roles.map((role) => `<@&${role}>`),
498 5
499 ) +
500 `\n` +
501 `**Channels:** ` +
502 listToAndMore(
503 current.allowed.channels.map((channel) => `<#${channel}>`),
504 5
505 )
TheCodedProf486bca32023-02-02 16:49:44 -0500506 )
507 .setStatus("Success")
Skyler Greyda16adf2023-03-05 10:22:12 +0000508 .setEmoji("GUILD.SETTINGS.GREEN");
TheCodedProf486bca32023-02-02 16:49:44 -0500509
Skyler Greyda16adf2023-03-05 10:22:12 +0000510 await interaction.editReply({ embeds: [embed], components: [menu, buttons] });
TheCodedProf486bca32023-02-02 16:49:44 -0500511
512 let i: ButtonInteraction | StringSelectMenuInteraction;
513 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000514 i = (await m.awaitMessageComponent({
515 filter: (i) => interaction.user.id === i.user.id && i.message.id === m.id,
516 time: 300000
517 })) as ButtonInteraction | StringSelectMenuInteraction;
TheCodedProf486bca32023-02-02 16:49:44 -0500518 } catch (e) {
519 return current;
520 }
521
Skyler Greyda16adf2023-03-05 10:22:12 +0000522 if (i.isButton()) {
TheCodedProf486bca32023-02-02 16:49:44 -0500523 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000524 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000525 case "back": {
TheCodedProf486bca32023-02-02 16:49:44 -0500526 closed = true;
527 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000528 }
529 case "enabled": {
TheCodedProf486bca32023-02-02 16:49:44 -0500530 current.enabled = !current.enabled;
531 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000532 }
TheCodedProf486bca32023-02-02 16:49:44 -0500533 }
534 } else {
535 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000536 switch (i.values[0]) {
PineaFanb0d0c242023-02-05 10:59:45 +0000537 case "users": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000538 current.allowed.users = await toSelectMenu(
539 interaction,
540 m,
541 current.allowed.users,
542 "member",
543 "Invite Settings"
544 );
TheCodedProf486bca32023-02-02 16:49:44 -0500545 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000546 }
547 case "roles": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000548 current.allowed.roles = await toSelectMenu(
549 interaction,
550 m,
551 current.allowed.roles,
552 "role",
553 "Invite Settings"
554 );
TheCodedProf486bca32023-02-02 16:49:44 -0500555 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000556 }
557 case "channels": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000558 current.allowed.channels = await toSelectMenu(
559 interaction,
560 m,
561 current.allowed.channels,
562 "channel",
563 "Invite Settings"
564 );
TheCodedProf486bca32023-02-02 16:49:44 -0500565 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000566 }
TheCodedProf486bca32023-02-02 16:49:44 -0500567 }
568 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000569 } while (!closed);
TheCodedProf486bca32023-02-02 16:49:44 -0500570 return current;
Skyler Greyda16adf2023-03-05 10:22:12 +0000571};
TheCodedProf8b3da212023-02-02 15:09:55 -0500572
Skyler Greyda16adf2023-03-05 10:22:12 +0000573const mentionMenu = async (
574 interaction: StringSelectMenuInteraction,
575 m: Message,
576 current: {
577 mass: number;
578 everyone: boolean;
579 roles: boolean;
580 allowed: {
581 roles: string[];
582 rolesToMention: string[];
583 users: string[];
584 channels: string[];
585 };
TheCodedProf8b3da212023-02-02 15:09:55 -0500586 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000587): Promise<{
588 mass: number;
589 everyone: boolean;
590 roles: boolean;
TheCodedProf8b3da212023-02-02 15:09:55 -0500591 allowed: {
Skyler Greyda16adf2023-03-05 10:22:12 +0000592 roles: string[];
593 rolesToMention: string[];
594 users: string[];
595 channels: string[];
596 };
TheCodedProf8b3da212023-02-02 15:09:55 -0500597}> => {
TheCodedProf486bca32023-02-02 16:49:44 -0500598 let closed = false;
599
600 do {
Skyler Greyda16adf2023-03-05 10:22:12 +0000601 const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
602 new ButtonBuilder()
603 .setCustomId("back")
604 .setLabel("Back")
605 .setStyle(ButtonStyle.Secondary)
606 .setEmoji(getEmojiByName("CONTROL.LEFT", "id") as APIMessageComponentEmoji),
607 new ButtonBuilder()
608 .setCustomId("everyone")
609 .setLabel(current.everyone ? "Everyone" : "No one")
610 .setStyle(current.everyone ? ButtonStyle.Success : ButtonStyle.Danger)
611 .setEmoji(emojiFromBoolean(current.everyone, "id") as APIMessageComponentEmoji),
612 new ButtonBuilder()
613 .setCustomId("roles")
614 .setLabel(current.roles ? "Roles" : "No roles")
615 .setStyle(current.roles ? ButtonStyle.Success : ButtonStyle.Danger)
616 .setEmoji(emojiFromBoolean(current.roles, "id") as APIMessageComponentEmoji)
617 );
618 const menu = new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
619 new StringSelectMenuBuilder()
620 .setCustomId("toEdit")
621 .setPlaceholder("Edit mention settings")
622 .addOptions(
623 new StringSelectMenuOptionBuilder()
624 .setLabel("Mass Mention Amount")
625 .setDescription("The amount of mentions before the bot will delete the message")
626 .setValue("mass"),
627 new StringSelectMenuOptionBuilder()
628 .setLabel("Roles")
629 .setDescription("Roles that are able to be mentioned")
630 .setValue("roles")
631 )
632 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500633
Skyler Greyda16adf2023-03-05 10:22:12 +0000634 const allowedMenu = new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
635 new StringSelectMenuBuilder()
636 .setCustomId("allowed")
637 .setPlaceholder("Edit exceptions")
638 .addOptions(
639 new StringSelectMenuOptionBuilder()
640 .setLabel("Users")
641 .setDescription("Users that are unaffected by the mention filter")
642 .setValue("users"),
643 new StringSelectMenuOptionBuilder()
644 .setLabel("Roles")
645 .setDescription("Roles that are unaffected by the mention filter")
646 .setValue("roles"),
647 new StringSelectMenuOptionBuilder()
648 .setLabel("Channels")
649 .setDescription("Channels where anyone is unaffected by the mention filter")
650 .setValue("channels")
651 )
652 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500653
654 const embed = new EmojiEmbed()
655 .setTitle("Mention Settings")
656 .setDescription(
657 `Log when members mention:\n` +
Skyler Greyda16adf2023-03-05 10:22:12 +0000658 `${emojiFromBoolean(true)} **${current.mass}+ members** in one message\n` +
659 `${emojiFromBoolean(current.everyone)} **Everyone**\n` +
660 `${emojiFromBoolean(current.roles)} **Roles**\n` +
661 (current.allowed.rolesToMention.length > 0
662 ? `> *Except for ${listToAndMore(
663 current.allowed.rolesToMention.map((r) => `<@&${r}>`),
664 3
665 )}*\n`
666 : "") +
667 "\n" +
668 `Except if...\n` +
669 `> ${
670 current.allowed.users.length > 0
671 ? `Member is: ${listToAndMore(
672 current.allowed.users.map((u) => `<@${u}>`),
673 3
674 )}\n`
675 : ""
676 }` +
677 `> ${
678 current.allowed.roles.length > 0
679 ? `Member has role: ${listToAndMore(
680 current.allowed.roles.map((r) => `<@&${r}>`),
681 3
682 )}\n`
683 : ""
684 }` +
685 `> ${
686 current.allowed.channels.length > 0
687 ? `In channel: ${listToAndMore(
688 current.allowed.channels.map((c) => `<#${c}>`),
689 3
690 )}\n`
691 : ""
692 }`
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500693 )
694 .setStatus("Success")
Skyler Greyda16adf2023-03-05 10:22:12 +0000695 .setEmoji("GUILD.SETTINGS.GREEN");
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500696
Skyler Greyda16adf2023-03-05 10:22:12 +0000697 await interaction.editReply({ embeds: [embed], components: [menu, allowedMenu, buttons] });
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500698
699 let i: ButtonInteraction | StringSelectMenuInteraction;
700 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000701 i = (await m.awaitMessageComponent({
702 filter: (i) => interaction.user.id === i.user.id && i.message.id === m.id,
703 time: 300000
704 })) as ButtonInteraction | StringSelectMenuInteraction;
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500705 } catch (e) {
706 closed = true;
707 break;
708 }
709
Skyler Greyda16adf2023-03-05 10:22:12 +0000710 if (i.isButton()) {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500711 await i.deferUpdate();
712 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000713 case "back": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500714 closed = true;
715 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000716 }
717 case "everyone": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500718 current.everyone = !current.everyone;
719 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000720 }
721 case "roles": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500722 current.roles = !current.roles;
723 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000724 }
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500725 }
726 } else {
727 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000728 case "toEdit": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500729 switch (i.values[0]) {
PineaFanb0d0c242023-02-05 10:59:45 +0000730 case "mass": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000731 await interaction.editReply({
732 embeds: [
733 new EmojiEmbed()
734 .setTitle("Word Filter")
735 .setDescription("Modal opened. If you can't see it, click back and try again.")
736 .setStatus("Success")
737 .setEmoji("GUILD.SETTINGS.GREEN")
738 ],
739 components: [
740 new ActionRowBuilder<ButtonBuilder>().addComponents(
741 new ButtonBuilder()
742 .setLabel("Back")
743 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
744 .setStyle(ButtonStyle.Primary)
745 .setCustomId("back")
746 )
747 ]
748 });
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500749 const modal = new ModalBuilder()
750 .setTitle("Mass Mention Amount")
751 .setCustomId("mass")
752 .addComponents(
Skyler Greyda16adf2023-03-05 10:22:12 +0000753 new ActionRowBuilder<TextInputBuilder>().addComponents(
754 new TextInputBuilder()
755 .setCustomId("mass")
756 .setPlaceholder("Amount")
757 .setMinLength(1)
758 .setMaxLength(3)
759 .setStyle(TextInputStyle.Short)
760 )
761 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500762 await i.showModal(modal);
763 let out;
764 try {
TheCodedProf01cba762023-02-18 15:55:05 -0500765 out = await modalInteractionCollector(m, interaction.user);
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500766 } catch (e) {
767 break;
768 }
769 if (!out) break;
Skyler Greyda16adf2023-03-05 10:22:12 +0000770 if (out.isButton()) break;
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500771 current.mass = parseInt(out.fields.getTextInputValue("mass"));
772 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000773 }
774 case "roles": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500775 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000776 current.allowed.rolesToMention = await toSelectMenu(
777 interaction,
778 m,
779 current.allowed.rolesToMention,
780 "role",
781 "Mention Settings"
782 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500783 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000784 }
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500785 }
786 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000787 }
788 case "allowed": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500789 await i.deferUpdate();
790 switch (i.values[0]) {
PineaFanb0d0c242023-02-05 10:59:45 +0000791 case "users": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000792 current.allowed.users = await toSelectMenu(
793 interaction,
794 m,
795 current.allowed.users,
796 "member",
797 "Mention Settings"
798 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500799 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000800 }
801 case "roles": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000802 current.allowed.roles = await toSelectMenu(
803 interaction,
804 m,
805 current.allowed.roles,
806 "role",
807 "Mention Settings"
808 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500809 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000810 }
811 case "channels": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000812 current.allowed.channels = await toSelectMenu(
813 interaction,
814 m,
815 current.allowed.channels,
816 "channel",
817 "Mention Settings"
818 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500819 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000820 }
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500821 }
822 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000823 }
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500824 }
825 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000826 } while (!closed);
827 return current;
828};
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500829
Skyler Greyda16adf2023-03-05 10:22:12 +0000830const cleanMenu = async (
831 interaction: StringSelectMenuInteraction,
832 m: Message,
833 current?: {
834 channels?: string[];
835 allowed?: {
836 roles: string[];
837 users: string[];
838 };
TheCodedProfad0b8202023-02-14 14:27:09 -0500839 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000840): Promise<{
841 channels: string[];
TheCodedProfad0b8202023-02-14 14:27:09 -0500842 allowed: {
Skyler Greyda16adf2023-03-05 10:22:12 +0000843 roles: string[];
844 users: string[];
845 };
TheCodedProfad0b8202023-02-14 14:27:09 -0500846}> => {
847 let closed = false;
Skyler Greyda16adf2023-03-05 10:22:12 +0000848 if (!current) current = { channels: [], allowed: { roles: [], users: [] } };
849 if (!current.channels) current.channels = [];
850 if (!current.allowed) current.allowed = { roles: [], users: [] };
TheCodedProfad0b8202023-02-14 14:27:09 -0500851
Skyler Greyda16adf2023-03-05 10:22:12 +0000852 const channelMenu = new ActionRowBuilder<ChannelSelectMenuBuilder>().addComponents(
853 new ChannelSelectMenuBuilder().setCustomId("toAdd").setPlaceholder("Select a channel")
854 );
TheCodedProfad0b8202023-02-14 14:27:09 -0500855
Skyler Greyda16adf2023-03-05 10:22:12 +0000856 const allowedMenu = new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
857 new StringSelectMenuBuilder()
858 .setCustomId("allowed")
859 .setPlaceholder("Edit exceptions")
860 .addOptions(
861 new StringSelectMenuOptionBuilder()
862 .setLabel("Users")
863 .setDescription("Users that are unaffected by the mention filter")
864 .setValue("users"),
865 new StringSelectMenuOptionBuilder()
866 .setLabel("Roles")
867 .setDescription("Roles that are unaffected by the mention filter")
868 .setValue("roles")
869 )
870 );
TheCodedProfad0b8202023-02-14 14:27:09 -0500871
872 do {
Skyler Greyda16adf2023-03-05 10:22:12 +0000873 const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
874 new ButtonBuilder()
875 .setCustomId("back")
876 .setLabel("Back")
877 .setStyle(ButtonStyle.Primary)
878 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
879 );
TheCodedProfad0b8202023-02-14 14:27:09 -0500880
881 const embed = new EmojiEmbed()
882 .setTitle("Clean Settings")
883 .setEmoji("GUILD.SETTINGS.GREEN")
884 .setDescription(
885 `Current clean channels:\n\n` +
Skyler Greyda16adf2023-03-05 10:22:12 +0000886 `${
887 current.channels.length > 0
888 ? listToAndMore(
889 current.channels.map((c) => `<#${c}>`),
890 10
891 )
892 : "None"
893 }\n\n`
TheCodedProfad0b8202023-02-14 14:27:09 -0500894 )
Skyler Greyda16adf2023-03-05 10:22:12 +0000895 .setStatus("Success");
TheCodedProfad0b8202023-02-14 14:27:09 -0500896
Skyler Greyda16adf2023-03-05 10:22:12 +0000897 await interaction.editReply({ embeds: [embed], components: [channelMenu, allowedMenu, buttons] });
TheCodedProfad0b8202023-02-14 14:27:09 -0500898
899 let i: ButtonInteraction | ChannelSelectMenuInteraction;
900 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000901 i = (await m.awaitMessageComponent({
902 filter: (i) => interaction.user.id === i.user.id && i.message.id === m.id,
903 time: 300000
904 })) as ButtonInteraction | ChannelSelectMenuInteraction;
TheCodedProfad0b8202023-02-14 14:27:09 -0500905 } catch (e) {
906 closed = true;
907 break;
908 }
909 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000910 if (i.isButton()) {
TheCodedProfad0b8202023-02-14 14:27:09 -0500911 switch (i.customId) {
912 case "back": {
913 closed = true;
914 break;
915 }
916 }
917 } else {
918 switch (i.customId) {
919 case "toAdd": {
TheCodedProf1807fb32023-02-20 14:33:48 -0500920 const channelEmbed = new EmojiEmbed()
TheCodedProfad0b8202023-02-14 14:27:09 -0500921 .setTitle("Clean Settings")
922 .setDescription(`Editing <#${i.values[0]}>`)
923 .setEmoji("GUILD.SETTINGS.GREEN")
Skyler Greyda16adf2023-03-05 10:22:12 +0000924 .setStatus("Success");
925 const channelButtons = new ActionRowBuilder<ButtonBuilder>().addComponents(
926 new ButtonBuilder()
927 .setCustomId("back")
928 .setLabel("Back")
929 .setStyle(ButtonStyle.Primary)
930 .setEmoji(getEmojiByName("CONTROL.LEFT", "id")),
931 new ButtonBuilder()
932 .setCustomId("switch")
933 .setLabel(current.channels.includes(i.values[0]!) ? "Remove" : "Add")
934 .setStyle(
935 current.channels.includes(i.values[0]!) ? ButtonStyle.Danger : ButtonStyle.Success
936 )
937 );
TheCodedProfad0b8202023-02-14 14:27:09 -0500938
Skyler Greyda16adf2023-03-05 10:22:12 +0000939 await i.editReply({ embeds: [channelEmbed], components: [channelButtons] });
TheCodedProfad0b8202023-02-14 14:27:09 -0500940 let j: ButtonInteraction;
941 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000942 j = (await m.awaitMessageComponent({
943 filter: (i) => interaction.user.id === i.user.id && i.message.id === m.id,
944 time: 300000
945 })) as ButtonInteraction;
TheCodedProfad0b8202023-02-14 14:27:09 -0500946 } catch (e) {
947 closed = true;
948 break;
949 }
950 await j.deferUpdate();
951 switch (j.customId) {
952 case "back": {
953 break;
954 }
955 case "switch": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000956 if (current.channels.includes(i.values[0]!)) {
TheCodedProfad0b8202023-02-14 14:27:09 -0500957 current.channels.splice(current.channels.indexOf(i.values[0]!), 1);
958 } else {
959 current.channels.push(i.values[0]!);
960 }
961 }
962 }
963 break;
964 }
965 case "allowed": {
966 switch (i.values[0]) {
967 case "users": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000968 current.allowed.users = await toSelectMenu(
969 interaction,
970 m,
971 current.allowed.users,
972 "member",
973 "Mention Settings"
974 );
TheCodedProfad0b8202023-02-14 14:27:09 -0500975 break;
976 }
977 case "roles": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000978 current.allowed.roles = await toSelectMenu(
979 interaction,
980 m,
981 current.allowed.roles,
982 "role",
983 "Mention Settings"
984 );
TheCodedProfad0b8202023-02-14 14:27:09 -0500985 break;
986 }
987 }
988 break;
989 }
990 }
991 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000992 } while (!closed);
TheCodedProfad0b8202023-02-14 14:27:09 -0500993
TheCodedProf1807fb32023-02-20 14:33:48 -0500994 return current as {
Skyler Greyda16adf2023-03-05 10:22:12 +0000995 channels: string[];
TheCodedProf1807fb32023-02-20 14:33:48 -0500996 allowed: {
Skyler Greyda16adf2023-03-05 10:22:12 +0000997 roles: string[];
998 users: string[];
999 };
TheCodedProf1807fb32023-02-20 14:33:48 -05001000 };
Skyler Greyda16adf2023-03-05 10:22:12 +00001001};
TheCodedProfad0b8202023-02-14 14:27:09 -05001002
TheCodedProf8b3da212023-02-02 15:09:55 -05001003const callback = async (interaction: CommandInteraction): Promise<void> => {
1004 if (!interaction.guild) return;
Skyler Greyda16adf2023-03-05 10:22:12 +00001005 const m = await interaction.reply({ embeds: LoadingEmbed, fetchReply: true, ephemeral: true });
TheCodedProf8b3da212023-02-02 15:09:55 -05001006 const config = (await client.database.guilds.read(interaction.guild.id)).filters;
1007
1008 let closed = false;
1009
Skyler Greyda16adf2023-03-05 10:22:12 +00001010 const button = new ActionRowBuilder<ButtonBuilder>().addComponents(
1011 new ButtonBuilder().setCustomId("save").setLabel("Save").setStyle(ButtonStyle.Success)
1012 );
TheCodedProf8b3da212023-02-02 15:09:55 -05001013
1014 do {
Skyler Greyda16adf2023-03-05 10:22:12 +00001015 const selectMenu = new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
1016 new StringSelectMenuBuilder()
1017 .setCustomId("filter")
1018 .setPlaceholder("Select a filter to edit")
1019 .addOptions(
1020 new StringSelectMenuOptionBuilder()
1021 .setLabel("Invites")
1022 .setDescription("Automatically delete messages containing server invites")
1023 .setValue("invites"),
1024 new StringSelectMenuOptionBuilder()
1025 .setLabel("Mentions")
1026 .setDescription("Deletes messages with excessive mentions")
1027 .setValue("mentions"),
1028 new StringSelectMenuOptionBuilder()
1029 .setLabel("Words")
1030 .setDescription("Delete messages containing filtered words")
1031 .setValue("words"),
1032 new StringSelectMenuOptionBuilder()
1033 .setLabel("Malware")
1034 .setDescription("Automatically delete files and links containing malware")
1035 .setValue("malware"),
1036 new StringSelectMenuOptionBuilder()
1037 .setLabel("Images")
1038 .setDescription("Checks performed on images (NSFW, size checking, etc.)")
1039 .setValue("images"),
1040 new StringSelectMenuOptionBuilder()
1041 .setLabel("Clean")
1042 .setDescription("Automatically delete new messages in specific channels")
1043 .setValue("clean")
1044 )
1045 );
TheCodedProf8b3da212023-02-02 15:09:55 -05001046
1047 const embed = new EmojiEmbed()
1048 .setTitle("Automod Settings")
1049 .setDescription(
TheCodedProf486bca32023-02-02 16:49:44 -05001050 `${emojiFromBoolean(config.invite.enabled)} **Invites**\n` +
Skyler Greyda16adf2023-03-05 10:22:12 +00001051 `${emojiFromBoolean(
1052 config.pings.everyone || config.pings.mass > 0 || config.pings.roles
1053 )} **Mentions**\n` +
1054 `${emojiFromBoolean(config.wordFilter.enabled)} **Words**\n` +
1055 `${emojiFromBoolean(config.malware)} **Malware**\n` +
1056 `${emojiFromBoolean(config.images.NSFW || config.images.size)} **Images**\n` +
1057 `${emojiFromBoolean(config.clean.channels.length > 0)} **Clean**\n`
TheCodedProf8b3da212023-02-02 15:09:55 -05001058 )
TheCodedProf486bca32023-02-02 16:49:44 -05001059 .setStatus("Success")
Skyler Greyda16adf2023-03-05 10:22:12 +00001060 .setEmoji("GUILD.SETTINGS.GREEN");
TheCodedProf8b3da212023-02-02 15:09:55 -05001061
Skyler Greyda16adf2023-03-05 10:22:12 +00001062 await interaction.editReply({ embeds: [embed], components: [selectMenu, button] });
TheCodedProf8b3da212023-02-02 15:09:55 -05001063
1064 let i: StringSelectMenuInteraction | ButtonInteraction;
1065 try {
Skyler Greyda16adf2023-03-05 10:22:12 +00001066 i = (await m.awaitMessageComponent({
1067 filter: (i) => i.user.id === interaction.user.id && i.message.id === m.id,
1068 time: 300000
1069 })) as StringSelectMenuInteraction | ButtonInteraction;
TheCodedProf8b3da212023-02-02 15:09:55 -05001070 } catch (e) {
1071 closed = true;
PineaFanb0d0c242023-02-05 10:59:45 +00001072 continue;
TheCodedProf8b3da212023-02-02 15:09:55 -05001073 }
Skyler Greyda16adf2023-03-05 10:22:12 +00001074 if (i.isButton()) {
pineafan6de4da52023-03-07 20:43:44 +00001075 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +00001076 await client.database.guilds.write(interaction.guild.id, { filters: config });
Skyler Grey16ecb172023-03-05 07:30:32 +00001077 await client.memory.forceUpdate(interaction.guild.id);
TheCodedProf8b3da212023-02-02 15:09:55 -05001078 } else {
Skyler Greyda16adf2023-03-05 10:22:12 +00001079 switch (i.values[0]) {
PineaFanb0d0c242023-02-05 10:59:45 +00001080 case "invites": {
pineafan6de4da52023-03-07 20:43:44 +00001081 i.deferUpdate();
TheCodedProf486bca32023-02-02 16:49:44 -05001082 config.invite = await inviteMenu(i, m, config.invite);
TheCodedProf8b3da212023-02-02 15:09:55 -05001083 break;
PineaFanb0d0c242023-02-05 10:59:45 +00001084 }
1085 case "mentions": {
pineafan6de4da52023-03-07 20:43:44 +00001086 i.deferUpdate();
TheCodedProf486bca32023-02-02 16:49:44 -05001087 config.pings = await mentionMenu(i, m, config.pings);
TheCodedProf8b3da212023-02-02 15:09:55 -05001088 break;
PineaFanb0d0c242023-02-05 10:59:45 +00001089 }
1090 case "words": {
TheCodedProf486bca32023-02-02 16:49:44 -05001091 config.wordFilter = await wordMenu(i, m, config.wordFilter);
TheCodedProf8b3da212023-02-02 15:09:55 -05001092 break;
PineaFanb0d0c242023-02-05 10:59:45 +00001093 }
1094 case "malware": {
pineafan6de4da52023-03-07 20:43:44 +00001095 i.deferUpdate();
TheCodedProf8b3da212023-02-02 15:09:55 -05001096 config.malware = !config.malware;
1097 break;
PineaFanb0d0c242023-02-05 10:59:45 +00001098 }
1099 case "images": {
pineafan6de4da52023-03-07 20:43:44 +00001100 i.deferUpdate();
PineaFanb0d0c242023-02-05 10:59:45 +00001101 const next = await imageMenu(i, m, config.images);
1102 config.images = next;
TheCodedProf8b3da212023-02-02 15:09:55 -05001103 break;
PineaFanb0d0c242023-02-05 10:59:45 +00001104 }
TheCodedProfad0b8202023-02-14 14:27:09 -05001105 case "clean": {
pineafan6de4da52023-03-07 20:43:44 +00001106 i.deferUpdate();
TheCodedProfad0b8202023-02-14 14:27:09 -05001107 const next = await cleanMenu(i, m, config.clean);
1108 config.clean = next;
1109 break;
1110 }
TheCodedProf8b3da212023-02-02 15:09:55 -05001111 }
1112 }
Skyler Greyda16adf2023-03-05 10:22:12 +00001113 } while (!closed);
1114 await interaction.deleteReply();
TheCodedProf8b3da212023-02-02 15:09:55 -05001115};
1116
1117const check = (interaction: CommandInteraction, _partial: boolean = false) => {
1118 const member = interaction.member as Discord.GuildMember;
1119 if (!member.permissions.has("ManageMessages"))
1120 return "You must have the *Manage Messages* permission to use this command";
1121 return true;
1122};
1123
1124export { command };
1125export { callback };
1126export { check };