blob: 684edf4288df3a17d4caaadf0fe2f91efd995a65 [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")
pineafan9ca34cd2023-03-21 18:45:58 +0000637 .setPlaceholder("Edit allowed list")
Skyler Greyda16adf2023-03-05 10:22:12 +0000638 .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(
pineafan9ca34cd2023-03-21 18:45:58 +0000663 current.allowed.rolesToMention.map((r) => `<@&${r}>`),
664 3
665 )}*\n`
Skyler Greyda16adf2023-03-05 10:22:12 +0000666 : "") +
667 "\n" +
668 `Except if...\n` +
pineafan9ca34cd2023-03-21 18:45:58 +0000669 (current.allowed.users.length > 0
670 ? `> Member is: ${listToAndMore(
671 current.allowed.users.map((u) => `<@${u}>`),
672 3
673 )}\n`
674 : "") +
675 (current.allowed.roles.length > 0
676 ? `> Member has role: ${listToAndMore(
677 current.allowed.roles.map((r) => `<@&${r}>`),
678 3
679 )}\n`
680 : "") +
681 (current.allowed.channels.length > 0
682 ? `> In channel: ${listToAndMore(
683 current.allowed.channels.map((c) => `<#${c}>`),
684 3
685 )}\n`
686 : "") +
687 (current.allowed.users.length == 0 || current.allowed.roles.length == 0 || current.allowed.channels.length == 0 ?
688 "> *No exceptions*\n" : ""
689 )
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500690 )
691 .setStatus("Success")
Skyler Greyda16adf2023-03-05 10:22:12 +0000692 .setEmoji("GUILD.SETTINGS.GREEN");
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500693
Skyler Greyda16adf2023-03-05 10:22:12 +0000694 await interaction.editReply({ embeds: [embed], components: [menu, allowedMenu, buttons] });
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500695
696 let i: ButtonInteraction | StringSelectMenuInteraction;
697 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000698 i = (await m.awaitMessageComponent({
699 filter: (i) => interaction.user.id === i.user.id && i.message.id === m.id,
700 time: 300000
701 })) as ButtonInteraction | StringSelectMenuInteraction;
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500702 } catch (e) {
703 closed = true;
704 break;
705 }
706
Skyler Greyda16adf2023-03-05 10:22:12 +0000707 if (i.isButton()) {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500708 await i.deferUpdate();
709 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000710 case "back": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500711 closed = true;
712 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000713 }
714 case "everyone": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500715 current.everyone = !current.everyone;
716 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000717 }
718 case "roles": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500719 current.roles = !current.roles;
720 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000721 }
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500722 }
723 } else {
724 switch (i.customId) {
PineaFanb0d0c242023-02-05 10:59:45 +0000725 case "toEdit": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500726 switch (i.values[0]) {
PineaFanb0d0c242023-02-05 10:59:45 +0000727 case "mass": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000728 await interaction.editReply({
729 embeds: [
730 new EmojiEmbed()
731 .setTitle("Word Filter")
732 .setDescription("Modal opened. If you can't see it, click back and try again.")
733 .setStatus("Success")
734 .setEmoji("GUILD.SETTINGS.GREEN")
735 ],
736 components: [
737 new ActionRowBuilder<ButtonBuilder>().addComponents(
738 new ButtonBuilder()
739 .setLabel("Back")
740 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
741 .setStyle(ButtonStyle.Primary)
742 .setCustomId("back")
743 )
744 ]
745 });
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500746 const modal = new ModalBuilder()
747 .setTitle("Mass Mention Amount")
748 .setCustomId("mass")
749 .addComponents(
Skyler Greyda16adf2023-03-05 10:22:12 +0000750 new ActionRowBuilder<TextInputBuilder>().addComponents(
751 new TextInputBuilder()
752 .setCustomId("mass")
753 .setPlaceholder("Amount")
754 .setMinLength(1)
755 .setMaxLength(3)
756 .setStyle(TextInputStyle.Short)
757 )
758 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500759 await i.showModal(modal);
760 let out;
761 try {
TheCodedProf01cba762023-02-18 15:55:05 -0500762 out = await modalInteractionCollector(m, interaction.user);
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500763 } catch (e) {
764 break;
765 }
766 if (!out) break;
Skyler Greyda16adf2023-03-05 10:22:12 +0000767 if (out.isButton()) break;
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500768 current.mass = parseInt(out.fields.getTextInputValue("mass"));
769 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000770 }
771 case "roles": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500772 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000773 current.allowed.rolesToMention = await toSelectMenu(
774 interaction,
775 m,
776 current.allowed.rolesToMention,
777 "role",
778 "Mention Settings"
779 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500780 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000781 }
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500782 }
783 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000784 }
785 case "allowed": {
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500786 await i.deferUpdate();
787 switch (i.values[0]) {
PineaFanb0d0c242023-02-05 10:59:45 +0000788 case "users": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000789 current.allowed.users = await toSelectMenu(
790 interaction,
791 m,
792 current.allowed.users,
793 "member",
794 "Mention Settings"
795 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500796 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000797 }
798 case "roles": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000799 current.allowed.roles = await toSelectMenu(
800 interaction,
801 m,
802 current.allowed.roles,
803 "role",
804 "Mention Settings"
805 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500806 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000807 }
808 case "channels": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000809 current.allowed.channels = await toSelectMenu(
810 interaction,
811 m,
812 current.allowed.channels,
813 "channel",
814 "Mention Settings"
815 );
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500816 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000817 }
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500818 }
819 break;
PineaFanb0d0c242023-02-05 10:59:45 +0000820 }
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500821 }
822 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000823 } while (!closed);
824 return current;
825};
TheCodedProf5b53a8c2023-02-03 15:40:26 -0500826
Skyler Greyda16adf2023-03-05 10:22:12 +0000827const cleanMenu = async (
828 interaction: StringSelectMenuInteraction,
829 m: Message,
830 current?: {
831 channels?: string[];
832 allowed?: {
833 roles: string[];
834 users: string[];
835 };
TheCodedProfad0b8202023-02-14 14:27:09 -0500836 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000837): Promise<{
838 channels: string[];
TheCodedProfad0b8202023-02-14 14:27:09 -0500839 allowed: {
Skyler Greyda16adf2023-03-05 10:22:12 +0000840 roles: string[];
841 users: string[];
842 };
TheCodedProfad0b8202023-02-14 14:27:09 -0500843}> => {
844 let closed = false;
Skyler Greyda16adf2023-03-05 10:22:12 +0000845 if (!current) current = { channels: [], allowed: { roles: [], users: [] } };
846 if (!current.channels) current.channels = [];
847 if (!current.allowed) current.allowed = { roles: [], users: [] };
TheCodedProfad0b8202023-02-14 14:27:09 -0500848
Skyler Greyda16adf2023-03-05 10:22:12 +0000849 const channelMenu = new ActionRowBuilder<ChannelSelectMenuBuilder>().addComponents(
850 new ChannelSelectMenuBuilder().setCustomId("toAdd").setPlaceholder("Select a channel")
851 );
TheCodedProfad0b8202023-02-14 14:27:09 -0500852
Skyler Greyda16adf2023-03-05 10:22:12 +0000853 const allowedMenu = new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
854 new StringSelectMenuBuilder()
855 .setCustomId("allowed")
856 .setPlaceholder("Edit exceptions")
857 .addOptions(
858 new StringSelectMenuOptionBuilder()
859 .setLabel("Users")
860 .setDescription("Users that are unaffected by the mention filter")
861 .setValue("users"),
862 new StringSelectMenuOptionBuilder()
863 .setLabel("Roles")
864 .setDescription("Roles that are unaffected by the mention filter")
865 .setValue("roles")
866 )
867 );
TheCodedProfad0b8202023-02-14 14:27:09 -0500868
869 do {
Skyler Greyda16adf2023-03-05 10:22:12 +0000870 const buttons = new ActionRowBuilder<ButtonBuilder>().addComponents(
871 new ButtonBuilder()
872 .setCustomId("back")
873 .setLabel("Back")
874 .setStyle(ButtonStyle.Primary)
875 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
876 );
TheCodedProfad0b8202023-02-14 14:27:09 -0500877
878 const embed = new EmojiEmbed()
879 .setTitle("Clean Settings")
880 .setEmoji("GUILD.SETTINGS.GREEN")
881 .setDescription(
882 `Current clean channels:\n\n` +
Skyler Greyda16adf2023-03-05 10:22:12 +0000883 `${
884 current.channels.length > 0
885 ? listToAndMore(
886 current.channels.map((c) => `<#${c}>`),
887 10
888 )
889 : "None"
890 }\n\n`
TheCodedProfad0b8202023-02-14 14:27:09 -0500891 )
Skyler Greyda16adf2023-03-05 10:22:12 +0000892 .setStatus("Success");
TheCodedProfad0b8202023-02-14 14:27:09 -0500893
Skyler Greyda16adf2023-03-05 10:22:12 +0000894 await interaction.editReply({ embeds: [embed], components: [channelMenu, allowedMenu, buttons] });
TheCodedProfad0b8202023-02-14 14:27:09 -0500895
896 let i: ButtonInteraction | ChannelSelectMenuInteraction;
897 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000898 i = (await m.awaitMessageComponent({
899 filter: (i) => interaction.user.id === i.user.id && i.message.id === m.id,
900 time: 300000
901 })) as ButtonInteraction | ChannelSelectMenuInteraction;
TheCodedProfad0b8202023-02-14 14:27:09 -0500902 } catch (e) {
903 closed = true;
904 break;
905 }
906 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +0000907 if (i.isButton()) {
TheCodedProfad0b8202023-02-14 14:27:09 -0500908 switch (i.customId) {
909 case "back": {
910 closed = true;
911 break;
912 }
913 }
914 } else {
915 switch (i.customId) {
916 case "toAdd": {
TheCodedProf1807fb32023-02-20 14:33:48 -0500917 const channelEmbed = new EmojiEmbed()
TheCodedProfad0b8202023-02-14 14:27:09 -0500918 .setTitle("Clean Settings")
919 .setDescription(`Editing <#${i.values[0]}>`)
920 .setEmoji("GUILD.SETTINGS.GREEN")
Skyler Greyda16adf2023-03-05 10:22:12 +0000921 .setStatus("Success");
922 const channelButtons = new ActionRowBuilder<ButtonBuilder>().addComponents(
923 new ButtonBuilder()
924 .setCustomId("back")
925 .setLabel("Back")
926 .setStyle(ButtonStyle.Primary)
927 .setEmoji(getEmojiByName("CONTROL.LEFT", "id")),
928 new ButtonBuilder()
929 .setCustomId("switch")
930 .setLabel(current.channels.includes(i.values[0]!) ? "Remove" : "Add")
931 .setStyle(
932 current.channels.includes(i.values[0]!) ? ButtonStyle.Danger : ButtonStyle.Success
933 )
934 );
TheCodedProfad0b8202023-02-14 14:27:09 -0500935
Skyler Greyda16adf2023-03-05 10:22:12 +0000936 await i.editReply({ embeds: [channelEmbed], components: [channelButtons] });
TheCodedProfad0b8202023-02-14 14:27:09 -0500937 let j: ButtonInteraction;
938 try {
Skyler Greyda16adf2023-03-05 10:22:12 +0000939 j = (await m.awaitMessageComponent({
940 filter: (i) => interaction.user.id === i.user.id && i.message.id === m.id,
941 time: 300000
942 })) as ButtonInteraction;
TheCodedProfad0b8202023-02-14 14:27:09 -0500943 } catch (e) {
944 closed = true;
945 break;
946 }
947 await j.deferUpdate();
948 switch (j.customId) {
949 case "back": {
950 break;
951 }
952 case "switch": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000953 if (current.channels.includes(i.values[0]!)) {
TheCodedProfad0b8202023-02-14 14:27:09 -0500954 current.channels.splice(current.channels.indexOf(i.values[0]!), 1);
955 } else {
956 current.channels.push(i.values[0]!);
957 }
958 }
959 }
960 break;
961 }
962 case "allowed": {
963 switch (i.values[0]) {
964 case "users": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000965 current.allowed.users = await toSelectMenu(
966 interaction,
967 m,
968 current.allowed.users,
969 "member",
970 "Mention Settings"
971 );
TheCodedProfad0b8202023-02-14 14:27:09 -0500972 break;
973 }
974 case "roles": {
Skyler Greyda16adf2023-03-05 10:22:12 +0000975 current.allowed.roles = await toSelectMenu(
976 interaction,
977 m,
978 current.allowed.roles,
979 "role",
980 "Mention Settings"
981 );
TheCodedProfad0b8202023-02-14 14:27:09 -0500982 break;
983 }
984 }
985 break;
986 }
987 }
988 }
Skyler Greyda16adf2023-03-05 10:22:12 +0000989 } while (!closed);
TheCodedProfad0b8202023-02-14 14:27:09 -0500990
TheCodedProf1807fb32023-02-20 14:33:48 -0500991 return current as {
Skyler Greyda16adf2023-03-05 10:22:12 +0000992 channels: string[];
TheCodedProf1807fb32023-02-20 14:33:48 -0500993 allowed: {
Skyler Greyda16adf2023-03-05 10:22:12 +0000994 roles: string[];
995 users: string[];
996 };
TheCodedProf1807fb32023-02-20 14:33:48 -0500997 };
Skyler Greyda16adf2023-03-05 10:22:12 +0000998};
TheCodedProfad0b8202023-02-14 14:27:09 -0500999
TheCodedProf8b3da212023-02-02 15:09:55 -05001000const callback = async (interaction: CommandInteraction): Promise<void> => {
1001 if (!interaction.guild) return;
Skyler Greyda16adf2023-03-05 10:22:12 +00001002 const m = await interaction.reply({ embeds: LoadingEmbed, fetchReply: true, ephemeral: true });
TheCodedProf8b3da212023-02-02 15:09:55 -05001003 const config = (await client.database.guilds.read(interaction.guild.id)).filters;
1004
1005 let closed = false;
1006
Skyler Greyda16adf2023-03-05 10:22:12 +00001007 const button = new ActionRowBuilder<ButtonBuilder>().addComponents(
1008 new ButtonBuilder().setCustomId("save").setLabel("Save").setStyle(ButtonStyle.Success)
1009 );
TheCodedProf8b3da212023-02-02 15:09:55 -05001010
1011 do {
Skyler Greyda16adf2023-03-05 10:22:12 +00001012 const selectMenu = new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(
1013 new StringSelectMenuBuilder()
1014 .setCustomId("filter")
1015 .setPlaceholder("Select a filter to edit")
1016 .addOptions(
1017 new StringSelectMenuOptionBuilder()
1018 .setLabel("Invites")
1019 .setDescription("Automatically delete messages containing server invites")
1020 .setValue("invites"),
1021 new StringSelectMenuOptionBuilder()
1022 .setLabel("Mentions")
1023 .setDescription("Deletes messages with excessive mentions")
1024 .setValue("mentions"),
1025 new StringSelectMenuOptionBuilder()
1026 .setLabel("Words")
1027 .setDescription("Delete messages containing filtered words")
1028 .setValue("words"),
1029 new StringSelectMenuOptionBuilder()
1030 .setLabel("Malware")
1031 .setDescription("Automatically delete files and links containing malware")
1032 .setValue("malware"),
1033 new StringSelectMenuOptionBuilder()
1034 .setLabel("Images")
1035 .setDescription("Checks performed on images (NSFW, size checking, etc.)")
1036 .setValue("images"),
1037 new StringSelectMenuOptionBuilder()
1038 .setLabel("Clean")
1039 .setDescription("Automatically delete new messages in specific channels")
1040 .setValue("clean")
1041 )
1042 );
TheCodedProf8b3da212023-02-02 15:09:55 -05001043
1044 const embed = new EmojiEmbed()
1045 .setTitle("Automod Settings")
1046 .setDescription(
TheCodedProf486bca32023-02-02 16:49:44 -05001047 `${emojiFromBoolean(config.invite.enabled)} **Invites**\n` +
Skyler Greyda16adf2023-03-05 10:22:12 +00001048 `${emojiFromBoolean(
1049 config.pings.everyone || config.pings.mass > 0 || config.pings.roles
1050 )} **Mentions**\n` +
1051 `${emojiFromBoolean(config.wordFilter.enabled)} **Words**\n` +
1052 `${emojiFromBoolean(config.malware)} **Malware**\n` +
1053 `${emojiFromBoolean(config.images.NSFW || config.images.size)} **Images**\n` +
1054 `${emojiFromBoolean(config.clean.channels.length > 0)} **Clean**\n`
TheCodedProf8b3da212023-02-02 15:09:55 -05001055 )
TheCodedProf486bca32023-02-02 16:49:44 -05001056 .setStatus("Success")
Skyler Greyda16adf2023-03-05 10:22:12 +00001057 .setEmoji("GUILD.SETTINGS.GREEN");
TheCodedProf8b3da212023-02-02 15:09:55 -05001058
Skyler Greyda16adf2023-03-05 10:22:12 +00001059 await interaction.editReply({ embeds: [embed], components: [selectMenu, button] });
TheCodedProf8b3da212023-02-02 15:09:55 -05001060
1061 let i: StringSelectMenuInteraction | ButtonInteraction;
1062 try {
Skyler Greyda16adf2023-03-05 10:22:12 +00001063 i = (await m.awaitMessageComponent({
1064 filter: (i) => i.user.id === interaction.user.id && i.message.id === m.id,
1065 time: 300000
1066 })) as StringSelectMenuInteraction | ButtonInteraction;
TheCodedProf8b3da212023-02-02 15:09:55 -05001067 } catch (e) {
1068 closed = true;
PineaFanb0d0c242023-02-05 10:59:45 +00001069 continue;
TheCodedProf8b3da212023-02-02 15:09:55 -05001070 }
Skyler Greyda16adf2023-03-05 10:22:12 +00001071 if (i.isButton()) {
pineafan6de4da52023-03-07 20:43:44 +00001072 await i.deferUpdate();
Skyler Greyda16adf2023-03-05 10:22:12 +00001073 await client.database.guilds.write(interaction.guild.id, { filters: config });
Skyler Grey16ecb172023-03-05 07:30:32 +00001074 await client.memory.forceUpdate(interaction.guild.id);
TheCodedProf8b3da212023-02-02 15:09:55 -05001075 } else {
Skyler Greyda16adf2023-03-05 10:22:12 +00001076 switch (i.values[0]) {
PineaFanb0d0c242023-02-05 10:59:45 +00001077 case "invites": {
pineafan6de4da52023-03-07 20:43:44 +00001078 i.deferUpdate();
TheCodedProf486bca32023-02-02 16:49:44 -05001079 config.invite = await inviteMenu(i, m, config.invite);
TheCodedProf8b3da212023-02-02 15:09:55 -05001080 break;
PineaFanb0d0c242023-02-05 10:59:45 +00001081 }
1082 case "mentions": {
pineafan6de4da52023-03-07 20:43:44 +00001083 i.deferUpdate();
TheCodedProf486bca32023-02-02 16:49:44 -05001084 config.pings = await mentionMenu(i, m, config.pings);
TheCodedProf8b3da212023-02-02 15:09:55 -05001085 break;
PineaFanb0d0c242023-02-05 10:59:45 +00001086 }
1087 case "words": {
TheCodedProf486bca32023-02-02 16:49:44 -05001088 config.wordFilter = await wordMenu(i, m, config.wordFilter);
TheCodedProf8b3da212023-02-02 15:09:55 -05001089 break;
PineaFanb0d0c242023-02-05 10:59:45 +00001090 }
1091 case "malware": {
pineafan6de4da52023-03-07 20:43:44 +00001092 i.deferUpdate();
TheCodedProf8b3da212023-02-02 15:09:55 -05001093 config.malware = !config.malware;
1094 break;
PineaFanb0d0c242023-02-05 10:59:45 +00001095 }
1096 case "images": {
pineafan6de4da52023-03-07 20:43:44 +00001097 i.deferUpdate();
PineaFanb0d0c242023-02-05 10:59:45 +00001098 const next = await imageMenu(i, m, config.images);
1099 config.images = next;
TheCodedProf8b3da212023-02-02 15:09:55 -05001100 break;
PineaFanb0d0c242023-02-05 10:59:45 +00001101 }
TheCodedProfad0b8202023-02-14 14:27:09 -05001102 case "clean": {
pineafan6de4da52023-03-07 20:43:44 +00001103 i.deferUpdate();
TheCodedProfad0b8202023-02-14 14:27:09 -05001104 const next = await cleanMenu(i, m, config.clean);
1105 config.clean = next;
1106 break;
1107 }
TheCodedProf8b3da212023-02-02 15:09:55 -05001108 }
1109 }
Skyler Greyda16adf2023-03-05 10:22:12 +00001110 } while (!closed);
1111 await interaction.deleteReply();
TheCodedProf8b3da212023-02-02 15:09:55 -05001112};
1113
1114const check = (interaction: CommandInteraction, _partial: boolean = false) => {
1115 const member = interaction.member as Discord.GuildMember;
1116 if (!member.permissions.has("ManageMessages"))
1117 return "You must have the *Manage Messages* permission to use this command";
1118 return true;
1119};
1120
1121export { command };
1122export { callback };
1123export { check };