blob: fd58d127549fc3e1c6f3fae6d1f39ed17e088ffd [file] [log] [blame]
pineafanbd02b4a2022-08-05 22:01:38 +01001import Discord, { CommandInteraction, MessageActionRow, MessageButton, TextInputComponent } from "discord.js";
pineafan73a7c4a2022-07-24 10:38:04 +01002import { modalInteractionCollector } from "./dualCollector.js";
pineafan63fc5e22022-08-04 22:04:10 +01003import EmojiEmbed from "./generateEmojiEmbed.js";
pineafan8b4b17f2022-02-27 20:42:52 +00004import getEmojiByName from "./getEmojiByName.js";
pineafan4f164f32022-02-26 22:07:12 +00005
pineafan02ba0232022-07-24 22:16:15 +01006
7interface CustomBoolean<T> {
8 title: string;
9 disabled: boolean;
10 value: string | null;
pineafan63fc5e22022-08-04 22:04:10 +010011 emoji: string | undefined;
pineafan02ba0232022-07-24 22:16:15 +010012 active: boolean;
13 onClick: () => Promise<T>;
14 response: T | null;
15}
16
pineafan4f164f32022-02-26 22:07:12 +000017class confirmationMessage {
18 interaction: CommandInteraction;
pineafan63fc5e22022-08-04 22:04:10 +010019 title = "";
20 emoji = "";
21 description = "";
22 color = "";
pineafan02ba0232022-07-24 22:16:15 +010023 customButtons: {[index:string]: CustomBoolean<unknown>} = {};
pineafan63fc5e22022-08-04 22:04:10 +010024 inverted = false;
pineafan73a7c4a2022-07-24 10:38:04 +010025 reason: string | null = null;
pineafan4f164f32022-02-26 22:07:12 +000026
27 constructor(interaction: CommandInteraction) {
28 this.interaction = interaction;
pineafan4f164f32022-02-26 22:07:12 +000029 }
30
pineafan63fc5e22022-08-04 22:04:10 +010031 setTitle(title: string) { this.title = title; return this; }
32 setEmoji(emoji: string) { this.emoji = emoji; return this; }
33 setDescription(description: string) { this.description = description; return this; }
34 setColor(color: string) { this.color = color; return this; }
35 setInverted(inverted: boolean) { this.inverted = inverted; return this; }
pineafan02ba0232022-07-24 22:16:15 +010036 addCustomBoolean(customId: string, title: string, disabled: boolean, callback: () => Promise<unknown> | null, callbackClicked: string | null, emoji?: string, initial?: boolean) { this.customButtons[customId] = {
pineafan63fc5e22022-08-04 22:04:10 +010037 title: title,
38 disabled: disabled,
39 value: callbackClicked,
40 emoji: emoji,
41 active: initial ?? false,
42 onClick: callback ?? (() => null),
43 response: null
44 };
45 return this;
pineafan6fb3e072022-05-20 19:27:23 +010046 }
pineafan73a7c4a2022-07-24 10:38:04 +010047 addReasonButton(reason: string) {
48 this.reason = reason;
49 return this;
50 }
pineafan8b4b17f2022-02-27 20:42:52 +000051 async send(editOnly?: boolean) {
pineafan377794f2022-04-18 19:01:01 +010052 while (true) {
pineafan63fc5e22022-08-04 22:04:10 +010053 const fullComponents = [
pineafan02ba0232022-07-24 22:16:15 +010054 new Discord.MessageButton()
55 .setCustomId("yes")
56 .setLabel("Confirm")
57 .setStyle(this.inverted ? "SUCCESS" : "DANGER")
58 .setEmoji(getEmojiByName("CONTROL.TICK", "id")),
59 new Discord.MessageButton()
60 .setCustomId("no")
61 .setLabel("Cancel")
62 .setStyle("SECONDARY")
63 .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
pineafan63fc5e22022-08-04 22:04:10 +010064 ];
pineafan02ba0232022-07-24 22:16:15 +010065 Object.entries(this.customButtons).forEach(([k, v]) => {
66 fullComponents.push(new Discord.MessageButton()
67 .setCustomId(k)
68 .setLabel(v.title)
69 .setStyle(v.active ? "SUCCESS" : "PRIMARY")
70 .setEmoji(getEmojiByName(v.emoji, "id"))
pineafan63fc5e22022-08-04 22:04:10 +010071 .setDisabled(v.disabled));
72 });
pineafan02ba0232022-07-24 22:16:15 +010073 if (this.reason !== null) fullComponents.push(new Discord.MessageButton()
74 .setCustomId("reason")
pineafan63fc5e22022-08-04 22:04:10 +010075 .setLabel("Edit Reason")
pineafan02ba0232022-07-24 22:16:15 +010076 .setStyle("PRIMARY")
77 .setEmoji(getEmojiByName("ICONS.EDIT", "id"))
78 .setDisabled(false)
pineafan63fc5e22022-08-04 22:04:10 +010079 );
80 const components = [];
pineafan02ba0232022-07-24 22:16:15 +010081 for (let i = 0; i < fullComponents.length; i += 5) {
82 components.push(new MessageActionRow().addComponents(fullComponents.slice(i, i + 5)));
83 }
pineafan63fc5e22022-08-04 22:04:10 +010084 const object = {
pineafan377794f2022-04-18 19:01:01 +010085 embeds: [
pineafan4edb7762022-06-26 19:21:04 +010086 new EmojiEmbed()
pineafan377794f2022-04-18 19:01:01 +010087 .setEmoji(this.emoji)
88 .setTitle(this.title)
pineafan02ba0232022-07-24 22:16:15 +010089 .setDescription(this.description + "\n\n" + Object.values(this.customButtons).map(v => {
90 if (v.value === null) return "";
91 return v.active ? `*${v.value}*\n` : "";
92 }).join(""))
pineafan377794f2022-04-18 19:01:01 +010093 .setStatus(this.color)
pineafan377794f2022-04-18 19:01:01 +010094 ],
pineafan02ba0232022-07-24 22:16:15 +010095 components: components,
pineafan377794f2022-04-18 19:01:01 +010096 ephemeral: true,
97 fetchReply: true
pineafan63fc5e22022-08-04 22:04:10 +010098 };
pineafan377794f2022-04-18 19:01:01 +010099 let m;
pineafan02ba0232022-07-24 22:16:15 +0100100 try {
101 if ( editOnly ) {
102 m = await this.interaction.editReply(object);
103 } else {
pineafan63fc5e22022-08-04 22:04:10 +0100104 m = await this.interaction.reply(object);
pineafan02ba0232022-07-24 22:16:15 +0100105 }
pineafan63fc5e22022-08-04 22:04:10 +0100106 } catch { return { cancelled: true }; }
pineafan377794f2022-04-18 19:01:01 +0100107 let component;
108 try {
pineafanbd02b4a2022-08-05 22:01:38 +0100109 component = await m.awaitMessageComponent({filter: (m) => m.user.id === this.interaction.user.id, time: 300000});
pineafan377794f2022-04-18 19:01:01 +0100110 } catch (e) {
pineafan02ba0232022-07-24 22:16:15 +0100111 return { success: false, components: this.customButtons };
pineafan377794f2022-04-18 19:01:01 +0100112 }
113 if (component.customId === "yes") {
114 component.deferUpdate();
pineafan63fc5e22022-08-04 22:04:10 +0100115 for (const v of Object.values(this.customButtons)) {
116 if (!v.active) continue;
pineafan02ba0232022-07-24 22:16:15 +0100117 try { v.response = await v.onClick(); }
pineafan63fc5e22022-08-04 22:04:10 +0100118 catch (e) { console.log(e); }
119 }
pineafan02ba0232022-07-24 22:16:15 +0100120 return { success: true, components: this.customButtons };
pineafan377794f2022-04-18 19:01:01 +0100121 } else if (component.customId === "no") {
122 component.deferUpdate();
pineafan02ba0232022-07-24 22:16:15 +0100123 return { success: false, components: this.customButtons };
pineafan73a7c4a2022-07-24 10:38:04 +0100124 } else if (component.customId === "reason") {
pineafan63fc5e22022-08-04 22:04:10 +0100125 await component.showModal(new Discord.Modal().setCustomId("modal").setTitle("Editing reason").addComponents(
pineafan02ba0232022-07-24 22:16:15 +0100126 new MessageActionRow<TextInputComponent>().addComponents(new TextInputComponent()
pineafan73a7c4a2022-07-24 10:38:04 +0100127 .setCustomId("reason")
128 .setLabel("Reason")
129 .setMaxLength(2000)
130 .setRequired(false)
131 .setStyle("PARAGRAPH")
132 .setPlaceholder("Spammed in #general")
133 .setValue(this.reason ? this.reason : "")
134 )
pineafan63fc5e22022-08-04 22:04:10 +0100135 ));
pineafan73a7c4a2022-07-24 10:38:04 +0100136 await this.interaction.editReply({
137 embeds: [new EmojiEmbed()
138 .setTitle(this.title)
139 .setDescription("Modal opened. If you can't see it, click back and try again.")
140 .setStatus(this.color)
141 .setEmoji(this.emoji)
142 ], components: [new MessageActionRow().addComponents([new MessageButton()
143 .setLabel("Back")
144 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
145 .setStyle("PRIMARY")
146 .setCustomId("back")
147 ])]
148 });
149 let out;
150 try {
pineafan63fc5e22022-08-04 22:04:10 +0100151 out = await modalInteractionCollector(m, (m) => m.channel.id === this.interaction.channel.id, (m) => m.customId === "reason");
152 } catch (e) { return {}; }
pineafan02ba0232022-07-24 22:16:15 +0100153 if (out.fields) { return { newReason: out.fields.getTextInputValue("reason") ?? "" }; }
pineafan63fc5e22022-08-04 22:04:10 +0100154 else { return { newReason: this.reason }; }
pineafan02ba0232022-07-24 22:16:15 +0100155 } else {
156 component.deferUpdate();
157 this.customButtons[component.customId].active = !this.customButtons[component.customId].active;
158 return { components: this.customButtons };
pineafan377794f2022-04-18 19:01:01 +0100159 }
pineafan8b4b17f2022-02-27 20:42:52 +0000160 }
pineafan4f164f32022-02-26 22:07:12 +0000161 }
162}
163
pineafan73a7c4a2022-07-24 10:38:04 +0100164export default confirmationMessage;