blob: 728cc5223c654a253a7c54aebe6e1927e68f490c [file] [log] [blame]
Skyler Grey75ea9172022-08-06 10:22:23 +01001import Discord, {
2 CommandInteraction,
3 Message,
4 MessageActionRow,
5 MessageButton,
6 TextInputComponent
7} from "discord.js";
pineafan73a7c4a2022-07-24 10:38:04 +01008import { modalInteractionCollector } from "./dualCollector.js";
pineafan63fc5e22022-08-04 22:04:10 +01009import EmojiEmbed from "./generateEmojiEmbed.js";
pineafan8b4b17f2022-02-27 20:42:52 +000010import getEmojiByName from "./getEmojiByName.js";
pineafan4f164f32022-02-26 22:07:12 +000011
pineafan02ba0232022-07-24 22:16:15 +010012interface CustomBoolean<T> {
13 title: string;
14 disabled: boolean;
15 value: string | null;
pineafan63fc5e22022-08-04 22:04:10 +010016 emoji: string | undefined;
pineafan02ba0232022-07-24 22:16:15 +010017 active: boolean;
18 onClick: () => Promise<T>;
19 response: T | null;
20}
21
pineafan4f164f32022-02-26 22:07:12 +000022class confirmationMessage {
23 interaction: CommandInteraction;
pineafan63fc5e22022-08-04 22:04:10 +010024 title = "";
25 emoji = "";
26 description = "";
Skyler Grey75ea9172022-08-06 10:22:23 +010027 color: "Danger" | "Warning" | "Success" = "Success";
28 customButtons: Record<string, CustomBoolean<unknown>> = {};
pineafan63fc5e22022-08-04 22:04:10 +010029 inverted = false;
pineafan73a7c4a2022-07-24 10:38:04 +010030 reason: string | null = null;
pineafan4f164f32022-02-26 22:07:12 +000031
32 constructor(interaction: CommandInteraction) {
33 this.interaction = interaction;
pineafan4f164f32022-02-26 22:07:12 +000034 }
35
Skyler Grey75ea9172022-08-06 10:22:23 +010036 setTitle(title: string) {
37 this.title = title;
38 return this;
39 }
40 setEmoji(emoji: string) {
41 this.emoji = emoji;
42 return this;
43 }
44 setDescription(description: string) {
45 this.description = description;
46 return this;
47 }
48 setColor(color: "Danger" | "Warning" | "Success") {
49 this.color = color;
50 return this;
51 }
52 setInverted(inverted: boolean) {
53 this.inverted = inverted;
54 return this;
55 }
56 addCustomBoolean(
57 customId: string,
58 title: string,
59 disabled: boolean,
60 callback: () => Promise<unknown> = async () => null,
61 callbackClicked: string | null,
62 emoji?: string,
63 initial?: boolean
64 ) {
65 this.customButtons[customId] = {
66 title: title,
67 disabled: disabled,
68 value: callbackClicked,
69 emoji: emoji,
70 active: initial ?? false,
71 onClick: callback,
72 response: null
73 };
74 return this;
pineafan6fb3e072022-05-20 19:27:23 +010075 }
pineafan73a7c4a2022-07-24 10:38:04 +010076 addReasonButton(reason: string) {
77 this.reason = reason;
78 return this;
79 }
pineafan8b4b17f2022-02-27 20:42:52 +000080 async send(editOnly?: boolean) {
pineafan377794f2022-04-18 19:01:01 +010081 while (true) {
pineafan63fc5e22022-08-04 22:04:10 +010082 const fullComponents = [
pineafan02ba0232022-07-24 22:16:15 +010083 new Discord.MessageButton()
84 .setCustomId("yes")
85 .setLabel("Confirm")
86 .setStyle(this.inverted ? "SUCCESS" : "DANGER")
87 .setEmoji(getEmojiByName("CONTROL.TICK", "id")),
88 new Discord.MessageButton()
89 .setCustomId("no")
90 .setLabel("Cancel")
91 .setStyle("SECONDARY")
92 .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
pineafan63fc5e22022-08-04 22:04:10 +010093 ];
pineafan02ba0232022-07-24 22:16:15 +010094 Object.entries(this.customButtons).forEach(([k, v]) => {
Skyler Grey75ea9172022-08-06 10:22:23 +010095 const button = new Discord.MessageButton()
pineafan02ba0232022-07-24 22:16:15 +010096 .setCustomId(k)
97 .setLabel(v.title)
98 .setStyle(v.active ? "SUCCESS" : "PRIMARY")
Skyler Grey75ea9172022-08-06 10:22:23 +010099 .setDisabled(v.disabled);
100 if (v.emoji !== undefined)
101 button.setEmoji(getEmojiByName(v.emoji, "id"));
102 fullComponents.push(button);
pineafan63fc5e22022-08-04 22:04:10 +0100103 });
Skyler Grey75ea9172022-08-06 10:22:23 +0100104 if (this.reason !== null)
105 fullComponents.push(
106 new Discord.MessageButton()
107 .setCustomId("reason")
108 .setLabel("Edit Reason")
109 .setStyle("PRIMARY")
110 .setEmoji(getEmojiByName("ICONS.EDIT", "id"))
111 .setDisabled(false)
112 );
pineafan63fc5e22022-08-04 22:04:10 +0100113 const components = [];
pineafan02ba0232022-07-24 22:16:15 +0100114 for (let i = 0; i < fullComponents.length; i += 5) {
Skyler Grey75ea9172022-08-06 10:22:23 +0100115 components.push(
116 new MessageActionRow().addComponents(
117 fullComponents.slice(i, i + 5)
118 )
119 );
pineafan02ba0232022-07-24 22:16:15 +0100120 }
pineafan63fc5e22022-08-04 22:04:10 +0100121 const object = {
pineafan377794f2022-04-18 19:01:01 +0100122 embeds: [
pineafan4edb7762022-06-26 19:21:04 +0100123 new EmojiEmbed()
pineafan377794f2022-04-18 19:01:01 +0100124 .setEmoji(this.emoji)
125 .setTitle(this.title)
Skyler Grey75ea9172022-08-06 10:22:23 +0100126 .setDescription(
127 this.description +
128 "\n\n" +
129 Object.values(this.customButtons)
130 .map((v) => {
131 if (v.value === null) return "";
132 return v.active ? `*${v.value}*\n` : "";
133 })
134 .join("")
135 )
pineafan377794f2022-04-18 19:01:01 +0100136 .setStatus(this.color)
pineafan377794f2022-04-18 19:01:01 +0100137 ],
pineafan02ba0232022-07-24 22:16:15 +0100138 components: components,
pineafan377794f2022-04-18 19:01:01 +0100139 ephemeral: true,
140 fetchReply: true
pineafan63fc5e22022-08-04 22:04:10 +0100141 };
Skyler Grey75ea9172022-08-06 10:22:23 +0100142 let m: Message;
pineafan02ba0232022-07-24 22:16:15 +0100143 try {
Skyler Grey75ea9172022-08-06 10:22:23 +0100144 if (editOnly) {
145 m = (await this.interaction.editReply(object)) as Message;
pineafan02ba0232022-07-24 22:16:15 +0100146 } else {
Skyler Grey75ea9172022-08-06 10:22:23 +0100147 m = (await this.interaction.reply(
148 object
149 )) as unknown as Message;
pineafan02ba0232022-07-24 22:16:15 +0100150 }
Skyler Grey75ea9172022-08-06 10:22:23 +0100151 } catch {
152 return { cancelled: true };
153 }
pineafan377794f2022-04-18 19:01:01 +0100154 let component;
155 try {
Skyler Grey75ea9172022-08-06 10:22:23 +0100156 component = await m.awaitMessageComponent({
157 filter: (m) => m.user.id === this.interaction.user.id,
158 time: 300000
159 });
pineafan377794f2022-04-18 19:01:01 +0100160 } catch (e) {
pineafan02ba0232022-07-24 22:16:15 +0100161 return { success: false, components: this.customButtons };
pineafan377794f2022-04-18 19:01:01 +0100162 }
163 if (component.customId === "yes") {
164 component.deferUpdate();
pineafan63fc5e22022-08-04 22:04:10 +0100165 for (const v of Object.values(this.customButtons)) {
166 if (!v.active) continue;
Skyler Grey75ea9172022-08-06 10:22:23 +0100167 try {
168 v.response = await v.onClick();
169 } catch (e) {
170 console.log(e);
171 }
pineafan63fc5e22022-08-04 22:04:10 +0100172 }
pineafan02ba0232022-07-24 22:16:15 +0100173 return { success: true, components: this.customButtons };
pineafan377794f2022-04-18 19:01:01 +0100174 } else if (component.customId === "no") {
175 component.deferUpdate();
pineafan02ba0232022-07-24 22:16:15 +0100176 return { success: false, components: this.customButtons };
pineafan73a7c4a2022-07-24 10:38:04 +0100177 } else if (component.customId === "reason") {
Skyler Grey75ea9172022-08-06 10:22:23 +0100178 await component.showModal(
179 new Discord.Modal()
180 .setCustomId("modal")
181 .setTitle("Editing reason")
182 .addComponents(
183 new MessageActionRow<TextInputComponent>().addComponents(
184 new TextInputComponent()
185 .setCustomId("reason")
186 .setLabel("Reason")
187 .setMaxLength(2000)
188 .setRequired(false)
189 .setStyle("PARAGRAPH")
190 .setPlaceholder("Spammed in #general")
191 .setValue(this.reason ? this.reason : "")
192 )
193 )
194 );
pineafan73a7c4a2022-07-24 10:38:04 +0100195 await this.interaction.editReply({
Skyler Grey75ea9172022-08-06 10:22:23 +0100196 embeds: [
197 new EmojiEmbed()
198 .setTitle(this.title)
199 .setDescription(
200 "Modal opened. If you can't see it, click back and try again."
201 )
202 .setStatus(this.color)
203 .setEmoji(this.emoji)
204 ],
205 components: [
206 new MessageActionRow().addComponents([
207 new MessageButton()
208 .setLabel("Back")
209 .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
210 .setStyle("PRIMARY")
211 .setCustomId("back")
212 ])
213 ]
pineafan73a7c4a2022-07-24 10:38:04 +0100214 });
215 let out;
216 try {
Skyler Grey75ea9172022-08-06 10:22:23 +0100217 out = await modalInteractionCollector(
218 m,
219 (m) => m.channel.id === this.interaction.channel.id,
220 (m) => m.customId === "reason"
221 );
222 } catch (e) {
223 return {};
224 }
225 if (out.fields) {
226 return {
227 newReason: out.fields.getTextInputValue("reason") ?? ""
228 };
229 } else {
230 return { newReason: this.reason };
231 }
pineafan02ba0232022-07-24 22:16:15 +0100232 } else {
233 component.deferUpdate();
Skyler Grey75ea9172022-08-06 10:22:23 +0100234 this.customButtons[component.customId].active =
235 !this.customButtons[component.customId].active;
pineafan02ba0232022-07-24 22:16:15 +0100236 return { components: this.customButtons };
pineafan377794f2022-04-18 19:01:01 +0100237 }
pineafan8b4b17f2022-02-27 20:42:52 +0000238 }
pineafan4f164f32022-02-26 22:07:12 +0000239 }
240}
241
pineafan73a7c4a2022-07-24 10:38:04 +0100242export default confirmationMessage;