blob: a8c7ab4b1859a6efadbb1f4636de7731cd93b20a [file] [log] [blame]
Skyler Grey75ea9172022-08-06 10:22:23 +01001import Discord, {
2 CommandInteraction,
Skyler Grey11236ba2022-08-08 21:13:33 +01003 Interaction,
Skyler Grey75ea9172022-08-06 10:22:23 +01004 Message,
5 MessageActionRow,
6 MessageButton,
Skyler Grey11236ba2022-08-08 21:13:33 +01007 MessageComponentInteraction,
8 ModalSubmitInteraction,
Skyler Grey75ea9172022-08-06 10:22:23 +01009 TextInputComponent
10} from "discord.js";
pineafan73a7c4a2022-07-24 10:38:04 +010011import { modalInteractionCollector } from "./dualCollector.js";
pineafan63fc5e22022-08-04 22:04:10 +010012import EmojiEmbed from "./generateEmojiEmbed.js";
pineafan8b4b17f2022-02-27 20:42:52 +000013import getEmojiByName from "./getEmojiByName.js";
pineafan4f164f32022-02-26 22:07:12 +000014
pineafan02ba0232022-07-24 22:16:15 +010015interface CustomBoolean<T> {
16 title: string;
17 disabled: boolean;
18 value: string | null;
pineafan63fc5e22022-08-04 22:04:10 +010019 emoji: string | undefined;
pineafan02ba0232022-07-24 22:16:15 +010020 active: boolean;
21 onClick: () => Promise<T>;
22 response: T | null;
23}
24
pineafan4f164f32022-02-26 22:07:12 +000025class confirmationMessage {
26 interaction: CommandInteraction;
pineafan63fc5e22022-08-04 22:04:10 +010027 title = "";
28 emoji = "";
29 description = "";
Skyler Grey75ea9172022-08-06 10:22:23 +010030 color: "Danger" | "Warning" | "Success" = "Success";
31 customButtons: Record<string, CustomBoolean<unknown>> = {};
pineafan63fc5e22022-08-04 22:04:10 +010032 inverted = false;
pineafan73a7c4a2022-07-24 10:38:04 +010033 reason: string | null = null;
pineafan4f164f32022-02-26 22:07:12 +000034
35 constructor(interaction: CommandInteraction) {
36 this.interaction = interaction;
pineafan4f164f32022-02-26 22:07:12 +000037 }
38
Skyler Grey75ea9172022-08-06 10:22:23 +010039 setTitle(title: string) {
40 this.title = title;
41 return this;
42 }
43 setEmoji(emoji: string) {
44 this.emoji = emoji;
45 return this;
46 }
47 setDescription(description: string) {
48 this.description = description;
49 return this;
50 }
51 setColor(color: "Danger" | "Warning" | "Success") {
52 this.color = color;
53 return this;
54 }
55 setInverted(inverted: boolean) {
56 this.inverted = inverted;
57 return this;
58 }
59 addCustomBoolean(
60 customId: string,
61 title: string,
62 disabled: boolean,
63 callback: () => Promise<unknown> = async () => null,
64 callbackClicked: string | null,
65 emoji?: string,
66 initial?: boolean
67 ) {
68 this.customButtons[customId] = {
69 title: title,
70 disabled: disabled,
71 value: callbackClicked,
72 emoji: emoji,
73 active: initial ?? false,
74 onClick: callback,
75 response: null
76 };
77 return this;
pineafan6fb3e072022-05-20 19:27:23 +010078 }
pineafan73a7c4a2022-07-24 10:38:04 +010079 addReasonButton(reason: string) {
80 this.reason = reason;
81 return this;
82 }
Skyler Grey11236ba2022-08-08 21:13:33 +010083 async send(editOnly?: boolean): Promise<{
84 success?: boolean;
85 cancelled?: boolean;
86 components?: Record<string, CustomBoolean<unknown>>;
87 newReason?: string;
88 }> {
pineafan377794f2022-04-18 19:01:01 +010089 while (true) {
pineafan63fc5e22022-08-04 22:04:10 +010090 const fullComponents = [
pineafan02ba0232022-07-24 22:16:15 +010091 new Discord.MessageButton()
92 .setCustomId("yes")
93 .setLabel("Confirm")
94 .setStyle(this.inverted ? "SUCCESS" : "DANGER")
95 .setEmoji(getEmojiByName("CONTROL.TICK", "id")),
96 new Discord.MessageButton()
97 .setCustomId("no")
98 .setLabel("Cancel")
99 .setStyle("SECONDARY")
100 .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
pineafan63fc5e22022-08-04 22:04:10 +0100101 ];
pineafan02ba0232022-07-24 22:16:15 +0100102 Object.entries(this.customButtons).forEach(([k, v]) => {
Skyler Grey75ea9172022-08-06 10:22:23 +0100103 const button = new Discord.MessageButton()
pineafan02ba0232022-07-24 22:16:15 +0100104 .setCustomId(k)
105 .setLabel(v.title)
106 .setStyle(v.active ? "SUCCESS" : "PRIMARY")
Skyler Grey75ea9172022-08-06 10:22:23 +0100107 .setDisabled(v.disabled);
Skyler Grey11236ba2022-08-08 21:13:33 +0100108 if (v.emoji !== undefined) button.setEmoji(getEmojiByName(v.emoji, "id"));
Skyler Grey75ea9172022-08-06 10:22:23 +0100109 fullComponents.push(button);
pineafan63fc5e22022-08-04 22:04:10 +0100110 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100111 if (this.reason !== null)
112 fullComponents.push(
113 new Discord.MessageButton()
114 .setCustomId("reason")
115 .setLabel("Edit Reason")
116 .setStyle("PRIMARY")
117 .setEmoji(getEmojiByName("ICONS.EDIT", "id"))
118 .setDisabled(false)
119 );
pineafan63fc5e22022-08-04 22:04:10 +0100120 const components = [];
pineafan02ba0232022-07-24 22:16:15 +0100121 for (let i = 0; i < fullComponents.length; i += 5) {
Skyler Grey11236ba2022-08-08 21:13:33 +0100122 components.push(new MessageActionRow().addComponents(fullComponents.slice(i, i + 5)));
pineafan02ba0232022-07-24 22:16:15 +0100123 }
pineafan63fc5e22022-08-04 22:04:10 +0100124 const object = {
pineafan377794f2022-04-18 19:01:01 +0100125 embeds: [
pineafan4edb7762022-06-26 19:21:04 +0100126 new EmojiEmbed()
pineafan377794f2022-04-18 19:01:01 +0100127 .setEmoji(this.emoji)
128 .setTitle(this.title)
Skyler Grey75ea9172022-08-06 10:22:23 +0100129 .setDescription(
130 this.description +
131 "\n\n" +
132 Object.values(this.customButtons)
133 .map((v) => {
134 if (v.value === null) return "";
135 return v.active ? `*${v.value}*\n` : "";
136 })
137 .join("")
138 )
pineafan377794f2022-04-18 19:01:01 +0100139 .setStatus(this.color)
pineafan377794f2022-04-18 19:01:01 +0100140 ],
pineafan02ba0232022-07-24 22:16:15 +0100141 components: components,
pineafan377794f2022-04-18 19:01:01 +0100142 ephemeral: true,
143 fetchReply: true
pineafan63fc5e22022-08-04 22:04:10 +0100144 };
Skyler Grey75ea9172022-08-06 10:22:23 +0100145 let m: Message;
pineafan02ba0232022-07-24 22:16:15 +0100146 try {
Skyler Grey75ea9172022-08-06 10:22:23 +0100147 if (editOnly) {
148 m = (await this.interaction.editReply(object)) as Message;
pineafan02ba0232022-07-24 22:16:15 +0100149 } else {
Skyler Grey11236ba2022-08-08 21:13:33 +0100150 m = (await this.interaction.reply(object)) as unknown as Message;
pineafan02ba0232022-07-24 22:16:15 +0100151 }
Skyler Grey75ea9172022-08-06 10:22:23 +0100152 } catch {
153 return { cancelled: true };
154 }
pineafan377794f2022-04-18 19:01:01 +0100155 let component;
156 try {
Skyler Grey75ea9172022-08-06 10:22:23 +0100157 component = await m.awaitMessageComponent({
158 filter: (m) => m.user.id === this.interaction.user.id,
159 time: 300000
160 });
pineafan377794f2022-04-18 19:01:01 +0100161 } catch (e) {
pineafan02ba0232022-07-24 22:16:15 +0100162 return { success: false, components: this.customButtons };
pineafan377794f2022-04-18 19:01:01 +0100163 }
164 if (component.customId === "yes") {
165 component.deferUpdate();
pineafan63fc5e22022-08-04 22:04:10 +0100166 for (const v of Object.values(this.customButtons)) {
167 if (!v.active) continue;
Skyler Grey75ea9172022-08-06 10:22:23 +0100168 try {
169 v.response = await v.onClick();
170 } catch (e) {
171 console.log(e);
172 }
pineafan63fc5e22022-08-04 22:04:10 +0100173 }
pineafan02ba0232022-07-24 22:16:15 +0100174 return { success: true, components: this.customButtons };
pineafan377794f2022-04-18 19:01:01 +0100175 } else if (component.customId === "no") {
176 component.deferUpdate();
pineafan02ba0232022-07-24 22:16:15 +0100177 return { success: false, components: this.customButtons };
pineafan73a7c4a2022-07-24 10:38:04 +0100178 } else if (component.customId === "reason") {
Skyler Grey75ea9172022-08-06 10:22:23 +0100179 await component.showModal(
180 new Discord.Modal()
181 .setCustomId("modal")
182 .setTitle("Editing reason")
183 .addComponents(
184 new MessageActionRow<TextInputComponent>().addComponents(
185 new TextInputComponent()
186 .setCustomId("reason")
187 .setLabel("Reason")
188 .setMaxLength(2000)
189 .setRequired(false)
190 .setStyle("PARAGRAPH")
191 .setPlaceholder("Spammed in #general")
192 .setValue(this.reason ? this.reason : "")
193 )
194 )
195 );
pineafan73a7c4a2022-07-24 10:38:04 +0100196 await this.interaction.editReply({
Skyler Grey75ea9172022-08-06 10:22:23 +0100197 embeds: [
198 new EmojiEmbed()
199 .setTitle(this.title)
Skyler Grey11236ba2022-08-08 21:13:33 +0100200 .setDescription("Modal opened. If you can't see it, click back and try again.")
Skyler Grey75ea9172022-08-06 10:22:23 +0100201 .setStatus(this.color)
202 .setEmoji(this.emoji)
203 ],
204 components: [
205 new MessageActionRow().addComponents([
206 new MessageButton()
207 .setLabel("Back")
208 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
209 .setStyle("PRIMARY")
210 .setCustomId("back")
211 ])
212 ]
pineafan73a7c4a2022-07-24 10:38:04 +0100213 });
214 let out;
215 try {
Skyler Grey75ea9172022-08-06 10:22:23 +0100216 out = await modalInteractionCollector(
217 m,
Skyler Grey11236ba2022-08-08 21:13:33 +0100218 (m: Interaction) =>
219 (m as MessageComponentInteraction | ModalSubmitInteraction).channelId ===
220 this.interaction.channelId,
Skyler Grey75ea9172022-08-06 10:22:23 +0100221 (m) => m.customId === "reason"
222 );
223 } catch (e) {
Skyler Grey11236ba2022-08-08 21:13:33 +0100224 return { cancelled: true };
Skyler Grey75ea9172022-08-06 10:22:23 +0100225 }
Skyler Grey11236ba2022-08-08 21:13:33 +0100226 if (out === null) {
227 return { cancelled: true };
228 }
229 if (out instanceof ModalSubmitInteraction) {
Skyler Grey75ea9172022-08-06 10:22:23 +0100230 return {
Skyler Grey11236ba2022-08-08 21:13:33 +0100231 newReason: out.fields.getTextInputValue("reason")
Skyler Grey75ea9172022-08-06 10:22:23 +0100232 };
233 } else {
Skyler Grey11236ba2022-08-08 21:13:33 +0100234 return { components: this.customButtons };
Skyler Grey75ea9172022-08-06 10:22:23 +0100235 }
pineafan02ba0232022-07-24 22:16:15 +0100236 } else {
237 component.deferUpdate();
Skyler Grey11236ba2022-08-08 21:13:33 +0100238 this.customButtons[component.customId]!.active = !this.customButtons[component.customId]!.active;
pineafan02ba0232022-07-24 22:16:15 +0100239 return { components: this.customButtons };
pineafan377794f2022-04-18 19:01:01 +0100240 }
pineafan8b4b17f2022-02-27 20:42:52 +0000241 }
pineafan4f164f32022-02-26 22:07:12 +0000242 }
243}
244
pineafan73a7c4a2022-07-24 10:38:04 +0100245export default confirmationMessage;