blob: e27ee6977710aba1d22d1c7d6cb7f083455b3efa [file] [log] [blame]
pineafan63fc5e22022-08-04 22:04:10 +01001import { callback as roleMenu } from "../actions/roleMenu.js";
pineafan73a7c4a2022-07-24 10:38:04 +01002import verify from "../reflex/verify.js";
3import create from "../actions/tickets/create.js";
4import close from "../actions/tickets/delete.js";
5import createTranscript from "../premium/createTranscript.js";
PineaFana34d04b2023-01-03 22:05:42 +00006
TheCodedProf35e73712023-03-10 17:35:35 -05007import { ActionRowBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, Interaction, InteractionEditReplyOptions, ModalBuilder, ModalSubmitInteraction, TextInputBuilder, TextInputStyle } from "discord.js";
PineaFan752af462022-12-31 21:59:38 +00008import type { NucleusClient } from "../utils/client.js";
PineaFan1dee28f2023-01-16 22:09:07 +00009import EmojiEmbed from "../utils/generateEmojiEmbed.js";
pineafanad54d752022-04-18 19:01:43 +010010
pineafan6de4da52023-03-07 20:43:44 +000011import { callback as banCallback, check as banCheck } from "../commands/mod/ban.js";
12import { callback as kickCallback, check as kickCheck } from "../commands/mod/kick.js";
13import { callback as muteCallback, check as muteCheck } from "../commands/mod/mute.js";
14import { callback as nicknameCallback, check as nicknameCheck } from "../commands/mod/nick.js";
15import { callback as warnCallback, check as warnCheck } from "../commands/mod/warn.js";
TheCodedProf35e73712023-03-10 17:35:35 -050016import client from "../utils/client.js";
pineafan6de4da52023-03-07 20:43:44 +000017
pineafan63fc5e22022-08-04 22:04:10 +010018export const event = "interactionCreate";
pineafanad54d752022-04-18 19:01:43 +010019
pineafan6de4da52023-03-07 20:43:44 +000020async function errorMessage(interaction: ButtonInteraction, message: string) {
21 await interaction.reply({
pineafan1e462ab2023-03-07 21:34:06 +000022 embeds: [new EmojiEmbed().setDescription(message).setStatus("Danger")],
pineafan6de4da52023-03-07 20:43:44 +000023 ephemeral: true,
24 components: []
25 });
26}
27
pineafan0f5cc782022-08-12 21:55:42 +010028async function interactionCreate(interaction: Interaction) {
PineaFana34d04b2023-01-03 22:05:42 +000029 if (interaction.isButton()) {
TheCodedProf35e73712023-03-10 17:35:35 -050030 if (interaction.customId.endsWith(":Suggestion")) {
31 const value = interaction.customId.startsWith("accept") || interaction.customId.startsWith("implement") ? true : false
32 return await modifySuggestion(interaction, value);
33 }
PineaFan538d3752023-01-12 21:48:23 +000034 switch (interaction.customId) {
Skyler Greyda16adf2023-03-05 10:22:12 +000035 case "rolemenu": {
36 return await roleMenu(interaction);
37 }
38 case "verifybutton": {
39 return await verify(interaction);
40 }
41 case "createticket": {
42 return await create(interaction);
43 }
44 case "closeticket": {
45 return await close(interaction);
46 }
47 case "createtranscript": {
48 return await createTranscript(interaction);
49 }
pineafan02ba0232022-07-24 22:16:15 +010050 }
pineafan6de4da52023-03-07 20:43:44 +000051 // Mod actions
52 if (interaction.customId.startsWith("mod:")) {
53 const action = interaction.customId.split(":")[1];
54 const memberId = interaction.customId.split(":")[2];
55 const member = await interaction.guild?.members.fetch(memberId!);
56 switch (action) {
57 case "kick": {
TheCodedProf35e73712023-03-10 17:35:35 -050058 const check = kickCheck(interaction, false, member);
pineafan6de4da52023-03-07 20:43:44 +000059 if (check !== true) return await errorMessage(interaction, check!);
60 return await kickCallback(interaction, member);
pineafan1e462ab2023-03-07 21:34:06 +000061 }
62 case "ban": {
TheCodedProf35e73712023-03-10 17:35:35 -050063 const check = banCheck(interaction, false, member);
pineafan6de4da52023-03-07 20:43:44 +000064 if (check !== true) return await errorMessage(interaction, check!);
65 return await banCallback(interaction, member);
pineafan1e462ab2023-03-07 21:34:06 +000066 }
67 case "mute": {
TheCodedProf35e73712023-03-10 17:35:35 -050068 const check = muteCheck(interaction, false, member);
pineafan6de4da52023-03-07 20:43:44 +000069 if (check !== true) return await errorMessage(interaction, check!);
70 return await muteCallback(interaction, member);
pineafan1e462ab2023-03-07 21:34:06 +000071 }
72 case "nickname": {
TheCodedProf35e73712023-03-10 17:35:35 -050073 const check = nicknameCheck(interaction, false, member);
pineafan6de4da52023-03-07 20:43:44 +000074 if (check !== true) return await errorMessage(interaction, check || "Something went wrong");
75 return await nicknameCallback(interaction, member);
pineafan1e462ab2023-03-07 21:34:06 +000076 }
77 case "warn": {
TheCodedProf35e73712023-03-10 17:35:35 -050078 const check = warnCheck(interaction, false, member);
pineafan6de4da52023-03-07 20:43:44 +000079 if (check !== true) return await errorMessage(interaction, check!);
80 return await warnCallback(interaction, member);
81 }
82 }
83 }
pineafanad54d752022-04-18 19:01:43 +010084 }
85}
86
TheCodedProf35e73712023-03-10 17:35:35 -050087const getReason = async (buttonInteraction: ButtonInteraction, prompt: string) => {
88 const modal = new ModalBuilder()
89 .addComponents(
90 new ActionRowBuilder<TextInputBuilder>().addComponents(
91 new TextInputBuilder()
92 .setStyle(TextInputStyle.Paragraph)
93 .setLabel(prompt)
94 .setCustomId("typed")
95 )
96 )
97 .setTitle("Reason")
98 .setCustomId("modal");
99 await buttonInteraction.showModal(modal);
100 let out: ModalSubmitInteraction;
101 try {
102 out = await buttonInteraction.awaitModalSubmit({
103 filter: (i) => i.customId === "modal" && i.user.id === buttonInteraction.user.id,
104 time: 300000
105 });
106 } catch {
107 return null;
108 }
109 await out.deferUpdate();
110 return out.fields.getTextInputValue("typed");
111}
112
113async function modifySuggestion(interaction: ButtonInteraction, accept: boolean) {
114 const message = interaction.message;
PineaFan1dee28f2023-01-16 22:09:07 +0000115 await message.fetch();
116 if (message.embeds.length === 0) return;
TheCodedProf35e73712023-03-10 17:35:35 -0500117 const embed = message.embeds[0]!;
118 const issueNum = embed.footer!.text
119 if(!issueNum) return;
120 const issue = {
121 owner: "ClicksMinutePer",
122 repo: "Nucleus",
123 issue_number: parseInt(issueNum)
124 }
125 let name = "Unknown";
126 const components: InteractionEditReplyOptions["components"] = [];
127 switch(interaction.customId) {
128 case "accept:Suggestion": {
129 name = "Accepted";
130 await interaction.deferUpdate();
131 await client.GitHub.rest.issues.createComment({...issue, body: "Suggestion accepted by " + interaction.user.tag});
132 components.push(new ActionRowBuilder<ButtonBuilder>().addComponents(
133 new ButtonBuilder().setCustomId("close:Suggestion").setLabel("Close").setStyle(ButtonStyle.Secondary),
134 new ButtonBuilder().setCustomId("implemented:Suggestion").setLabel("Implemented").setStyle(ButtonStyle.Secondary)
135 ))
136 break;
137 }
138 case "deny:Suggestion": {
139 name = "Denied";
140 const reason = await getReason(interaction, "Reason for denial");
141 await client.GitHub.rest.issues.createComment({...issue, body: "Suggestion denied by " + interaction.user.tag + " for reason:\n>" + reason});
142 await client.GitHub.rest.issues.update({...issue, state: "closed", state_reason: "not_planned"});
143 // await client.GitHub.rest.issues.lock({...issue, lock_reason: "resolved"})
144 components.push(new ActionRowBuilder<ButtonBuilder>().addComponents(
145 new ButtonBuilder().setCustomId("lock:Suggestion").setLabel("Lock").setStyle(ButtonStyle.Danger)
146 ))
147 break;
148 }
149 case "close:Suggestion": {
150 name = "Closed";
151 const reason = await getReason(interaction, "Reason for closing");
152 await client.GitHub.rest.issues.createComment({...issue, body: "Suggestion closed by " + interaction.user.tag + " for reason:\n>" + reason});
153 await client.GitHub.rest.issues.update({...issue, state: "closed"});
154 // await client.GitHub.rest.issues.lock({...issue})
155 components.push(new ActionRowBuilder<ButtonBuilder>().addComponents(
156 new ButtonBuilder().setCustomId("lock:Suggestion").setLabel("Lock").setStyle(ButtonStyle.Danger)
157 ))
158 break;
159 }
160 case "implement:Suggestion": {
161 name = "Implemented";
162 await interaction.deferUpdate();
163 await client.GitHub.rest.issues.createComment({...issue, body: "Suggestion implemented"});
164 await client.GitHub.rest.issues.update({...issue, state: "closed", state_reason: "completed"});
165 await client.GitHub.rest.issues.lock({...issue, lock_reason: "resolved"})
166 break;
167 }
168 case "lock:Suggestion": {
169 name = "Locked";
170 await interaction.deferUpdate();
171 await client.GitHub.rest.issues.lock({...issue});
172 break;
173 }
174 case "spam:Suggestion": {
175 name = "Marked as Spam";
176 await interaction.deferUpdate();
177 await client.GitHub.rest.issues.update({...issue, state: "closed", state_reason: "not_planned"});
178 await client.GitHub.rest.issues.lock({...issue, lock_reason: "spam"})
179 break;
180 }
181 }
182
TheCodedProf46518a42023-02-18 17:08:23 -0500183 const newcolor = accept ? "Success" : "Danger";
TheCodedProf35e73712023-03-10 17:35:35 -0500184 const newEmoji = accept ? "ICONS.ADD" : "ICONS.OPP.ADD";
PineaFan1dee28f2023-01-16 22:09:07 +0000185
186 const newEmbed = new EmojiEmbed()
TheCodedProf35e73712023-03-10 17:35:35 -0500187 .setEmoji(newEmoji)
188 .setTitle(embed!.title!.replace(/.+> /, ""))
PineaFan1dee28f2023-01-16 22:09:07 +0000189 .setDescription(embed!.description!)
TheCodedProf35e73712023-03-10 17:35:35 -0500190 .setFields({
191 name: name + " by",
192 value: interaction.user.tag,
193 })
194 .setStatus(newcolor)
195 .setFooter(embed!.footer);
PineaFan1dee28f2023-01-16 22:09:07 +0000196
TheCodedProf35e73712023-03-10 17:35:35 -0500197 await interaction.editReply({
198 embeds: [newEmbed],
199 components: components
200 });
PineaFan1dee28f2023-01-16 22:09:07 +0000201}
202
PineaFan752af462022-12-31 21:59:38 +0000203export async function callback(_client: NucleusClient, interaction: Interaction) {
pineafan63fc5e22022-08-04 22:04:10 +0100204 await interactionCreate(interaction);
Skyler Grey75ea9172022-08-06 10:22:23 +0100205}