blob: b7594bad2012cfeb8dec5c23664ed72db32b100e [file] [log] [blame]
pineafan1e462ab2023-03-07 21:34:06 +00001import {
2 ActionRowBuilder,
3 AttachmentBuilder,
4 ButtonBuilder,
5 ButtonInteraction,
6 ButtonStyle,
7 ChannelType,
8 CommandInteraction,
9 ComponentType,
10 Guild,
TheCodedProfa38cbb32023-03-11 17:22:25 -050011 GuildTextBasedChannel,
pineafan1e462ab2023-03-07 21:34:06 +000012 ModalBuilder,
13 ModalSubmitInteraction,
14 TextInputBuilder,
15 TextInputStyle
16} from "discord.js";
TheCodedProff86ba092023-01-27 17:10:07 -050017import type { SlashCommandSubcommandBuilder } from "discord.js";
pineafan4edb7762022-06-26 19:21:04 +010018import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
pineafan63fc5e22022-08-04 22:04:10 +010019import client from "../../utils/client.js";
TheCodedProfe92b9b52023-03-06 17:07:34 -050020import config from "../../config/main.js";
pineafan4f164f32022-02-26 22:07:12 +000021
22const command = (builder: SlashCommandSubcommandBuilder) =>
Skyler Grey75ea9172022-08-06 10:22:23 +010023 builder.setName("stats").setDescription("Gets the bot's stats");
pineafan4f164f32022-02-26 22:07:12 +000024
TheCodedProf35e73712023-03-10 17:35:35 -050025const confirm = async (interaction: CommandInteraction) => {
26 const requiredTexts = [
27 "just do it",
28 "yes, do as i say!",
29 "clicksminuteper/nucleus",
30 "i've said it once i'll say it again",
31 "no, i've changed my mind",
32 "this incident will be reported",
33 "coded told me to",
34 "mini told me to",
35 "pinea told me to",
36 "what's a java script",
37 "it's a feature not a bug",
38 "that never happened during testing"
TheCodedProfca29ebb2023-03-10 17:40:09 -050039 ];
TheCodedProf35e73712023-03-10 17:35:35 -050040 const chosen = requiredTexts[Math.floor(Math.random() * (requiredTexts.length - 1))]!;
41
42 const modal = new ModalBuilder()
TheCodedProfca29ebb2023-03-10 17:40:09 -050043 .addComponents(
44 new ActionRowBuilder<TextInputBuilder>().addComponents(
45 new TextInputBuilder()
46 .setStyle(TextInputStyle.Short)
47 .setLabel(`Type "${chosen}" below`)
48 .setCustomId("confirm")
49 .setPlaceholder("Guild ID")
50 .setMinLength(chosen.length)
51 .setMaxLength(chosen.length)
TheCodedProf35e73712023-03-10 17:35:35 -050052 )
TheCodedProfca29ebb2023-03-10 17:40:09 -050053 )
54 .setTitle("Admin Panel")
55 .setCustomId("adminPanel");
TheCodedProf35e73712023-03-10 17:35:35 -050056 await interaction.showModal(modal);
57 let out: ModalSubmitInteraction;
58 try {
59 out = await interaction.awaitModalSubmit({
60 filter: (i) => i.customId === "adminPanel" && i.user.id === interaction.user.id,
61 time: 300000
62 });
63 } catch {
64 return;
65 }
66 await out.deferUpdate();
67 const typed = out.fields.getTextInputValue("confirm");
TheCodedProfca29ebb2023-03-10 17:40:09 -050068 return typed.toLowerCase() === chosen.toLowerCase();
69};
TheCodedProf35e73712023-03-10 17:35:35 -050070
pineafanbd02b4a2022-08-05 22:01:38 +010071const callback = async (interaction: CommandInteraction): Promise<void> => {
pineafan1e462ab2023-03-07 21:34:06 +000072 const description = `**Servers:** ${client.guilds.cache.size}\n` + `**Ping:** \`${client.ws.ping * 2}ms\``;
TheCodedProfe92b9b52023-03-06 17:07:34 -050073 const m = await interaction.reply({
Skyler Grey75ea9172022-08-06 10:22:23 +010074 embeds: [
75 new EmojiEmbed()
76 .setTitle("Stats")
TheCodedProfe92b9b52023-03-06 17:07:34 -050077 .setDescription(description)
Skyler Grey75ea9172022-08-06 10:22:23 +010078 .setStatus("Success")
TheCodedProf4a6d5712023-01-19 15:54:40 -050079 .setEmoji("SETTINGS.STATS.GREEN")
Skyler Grey75ea9172022-08-06 10:22:23 +010080 ],
TheCodedProfe92b9b52023-03-06 17:07:34 -050081 ephemeral: true,
82 fetchReply: true
pineafan377794f2022-04-18 19:01:01 +010083 });
TheCodedProfe92b9b52023-03-06 17:07:34 -050084 if (config.owners.includes(interaction.user.id)) {
Skyler Greyf4f21c42023-03-08 14:36:29 +000085 await interaction.editReply({
TheCodedProfe92b9b52023-03-06 17:07:34 -050086 embeds: [
87 new EmojiEmbed()
88 .setTitle("Admin")
89 .setDescription(description)
90 .setStatus("Success")
91 .setEmoji("SETTINGS.STATS.GREEN")
pineafan1e462ab2023-03-07 21:34:06 +000092 ],
93 components: [
94 new ActionRowBuilder<ButtonBuilder>().addComponents(
TheCodedProfa38cbb32023-03-11 17:22:25 -050095 new ButtonBuilder().setCustomId("admin").setLabel("Admin Panel").setStyle(ButtonStyle.Primary),
TheCodedProf528de572023-03-11 17:28:29 -050096 new ButtonBuilder()
97 .setCustomId("announce")
98 .setLabel("Announce to all Guilds")
99 .setStyle(ButtonStyle.Danger)
pineafan1e462ab2023-03-07 21:34:06 +0000100 )
101 ]
TheCodedProfe92b9b52023-03-06 17:07:34 -0500102 });
103
104 const modal = new ModalBuilder()
105 .addComponents(
pineafan1e462ab2023-03-07 21:34:06 +0000106 new ActionRowBuilder<TextInputBuilder>().addComponents(
107 new TextInputBuilder()
108 .setStyle(TextInputStyle.Short)
109 .setLabel("Guild ID")
110 .setCustomId("guildID")
111 .setPlaceholder("Guild ID")
112 .setMinLength(16)
113 .setMaxLength(25)
114 )
TheCodedProfe92b9b52023-03-06 17:07:34 -0500115 )
116 .setTitle("Admin Panel")
pineafan1e462ab2023-03-07 21:34:06 +0000117 .setCustomId("adminPanel");
TheCodedProfe92b9b52023-03-06 17:07:34 -0500118 let i1: ButtonInteraction;
pineafan1e462ab2023-03-07 21:34:06 +0000119 const channel = await client.channels.fetch(interaction.channelId);
120 if (
121 !channel ||
122 [ChannelType.GuildCategory, ChannelType.GroupDM, ChannelType.GuildStageVoice].includes(channel.type)
123 )
124 return;
TheCodedProfe92b9b52023-03-06 17:07:34 -0500125 // console.log(interaction)
126 if (!("awaitMessageComponent" in channel)) return;
TheCodedProf35e73712023-03-10 17:35:35 -0500127 let GuildID = interaction.guildId;
TheCodedProfe92b9b52023-03-06 17:07:34 -0500128 try {
TheCodedProfa38cbb32023-03-11 17:22:25 -0500129 i1 = await m.awaitMessageComponent<ComponentType.Button>({
130 filter: (i) => i.user.id === interaction.user.id,
TheCodedProfe92b9b52023-03-06 17:07:34 -0500131 time: 300000
pineafan1e462ab2023-03-07 21:34:06 +0000132 });
TheCodedProfa38cbb32023-03-11 17:22:25 -0500133 } catch (e) {
134 console.log(e);
pineafan1e462ab2023-03-07 21:34:06 +0000135 return;
136 }
TheCodedProf528de572023-03-11 17:28:29 -0500137 switch (i1.customId) {
TheCodedProfa38cbb32023-03-11 17:22:25 -0500138 case "admin": {
139 if (!GuildID) {
140 await i1.showModal(modal);
141 let out: ModalSubmitInteraction;
142 try {
143 out = await i1.awaitModalSubmit({
144 filter: (i) => i.customId === "adminPanel" && i.user.id === interaction.user.id,
145 time: 300000
146 });
147 } catch {
148 return;
149 }
150 await out.deferUpdate();
151 GuildID = out.fields.getTextInputValue("guildID");
152 } else if (!client.guilds.cache.has(GuildID)) {
153 await interaction.editReply({
TheCodedProf528de572023-03-11 17:28:29 -0500154 embeds: [
155 new EmojiEmbed().setTitle("Admin").setDescription("Not in server").setStatus("Danger")
156 ],
TheCodedProfa38cbb32023-03-11 17:22:25 -0500157 components: []
158 });
159 }
160
161 await interaction.editReply({
162 embeds: [],
163 components: [
164 new ActionRowBuilder<ButtonBuilder>().addComponents(
165 new ButtonBuilder().setCustomId("stats").setLabel("Stats").setStyle(ButtonStyle.Primary),
TheCodedProf528de572023-03-11 17:28:29 -0500166 new ButtonBuilder()
167 .setCustomId("data")
168 .setLabel("Guild data")
169 .setStyle(ButtonStyle.Secondary),
170 new ButtonBuilder()
171 .setCustomId("cache")
172 .setLabel("Reset cache")
173 .setStyle(ButtonStyle.Success),
TheCodedProfa38cbb32023-03-11 17:22:25 -0500174 new ButtonBuilder().setCustomId("leave").setLabel("Leave").setStyle(ButtonStyle.Danger),
TheCodedProf528de572023-03-11 17:28:29 -0500175 new ButtonBuilder()
176 .setCustomId("purge")
177 .setLabel("Delete data")
178 .setStyle(ButtonStyle.Danger)
TheCodedProfe92b9b52023-03-06 17:07:34 -0500179 )
TheCodedProfa38cbb32023-03-11 17:22:25 -0500180 ]
TheCodedProfca29ebb2023-03-10 17:40:09 -0500181 });
TheCodedProfa38cbb32023-03-11 17:22:25 -0500182 let i;
183 try {
184 i = await m.awaitMessageComponent<ComponentType.Button>({
185 filter: (i) => i.user.id === interaction.user.id && i.message.id === m.id,
186 time: 300000
187 });
188 } catch {
189 return;
190 }
191 const guild = (await client.guilds.fetch(GuildID)) as Guild | null;
Skyler Greya325d262023-03-15 00:08:01 +0000192 await i.deferUpdate();
TheCodedProfa38cbb32023-03-11 17:22:25 -0500193 if (!guild) {
TheCodedProfa38cbb32023-03-11 17:22:25 -0500194 await interaction.editReply({
TheCodedProf528de572023-03-11 17:28:29 -0500195 embeds: [
196 new EmojiEmbed().setTitle("Admin").setDescription("Not in server").setStatus("Danger")
197 ],
TheCodedProfa38cbb32023-03-11 17:22:25 -0500198 components: []
199 });
200 return;
201 }
202 if (i.customId === "stats") {
TheCodedProfa38cbb32023-03-11 17:22:25 -0500203 await interaction.editReply({
204 embeds: [
205 new EmojiEmbed()
206 .setTitle("Stats")
207 .setDescription(
208 `**Name:** ${guild.name}\n` +
209 `**ID:** \`${guild.id}\`\n` +
210 `**Owner:** ${client.users.cache.get(guild.ownerId)!.tag}\n` +
211 `**Member Count:** ${guild.memberCount}\n` +
212 `**Created:** <t:${guild.createdTimestamp}:F>\n` +
213 `**Added Nucleus:** <t:${guild.members.me!.joinedTimestamp}:R>\n` +
214 `**Nucleus' Perms:** https://discordapi.com/permissions.html#${guild.members.me!.permissions.valueOf()}\n`
215 )
216 .setStatus("Success")
217 .setEmoji("SETTINGS.STATS.GREEN")
218 ]
219 });
220 } else if (i.customId === "leave") {
221 if (!(await confirm(interaction))) {
222 await interaction.editReply({
223 embeds: [new EmojiEmbed().setTitle("No changes were made").setStatus("Danger")],
224 components: []
225 });
226 return;
227 }
228 await guild.leave();
229 await interaction.editReply({
230 embeds: [
231 new EmojiEmbed()
232 .setTitle("Left")
233 .setDescription(`Left ${guild.name}`)
234 .setStatus("Success")
235 .setEmoji("SETTINGS.STATS.GREEN")
236 ],
237 components: []
238 });
239 } else if (i.customId === "data") {
TheCodedProfa38cbb32023-03-11 17:22:25 -0500240 // Get all the data and convert to a string
241 const data = await client.database.guilds.read(guild.id);
242 const stringified = JSON.stringify(data, null, 2);
243 const buffer = Buffer.from(stringified);
244 const attachment = new AttachmentBuilder(buffer).setName("data.json");
245 await interaction.editReply({
246 embeds: [
TheCodedProf528de572023-03-11 17:28:29 -0500247 new EmojiEmbed()
248 .setTitle("Data")
249 .setDescription(`Data for ${guild.name}`)
250 .setStatus("Success")
TheCodedProfa38cbb32023-03-11 17:22:25 -0500251 ],
252 components: [],
253 files: [attachment]
254 });
255 } else if (i.customId === "purge") {
256 if (!(await confirm(interaction))) {
257 await interaction.editReply({
258 embeds: [new EmojiEmbed().setTitle("No changes were made").setStatus("Danger")],
259 components: []
260 });
261 return;
262 }
263 await client.database.guilds.delete(GuildID);
264 await client.database.history.delete(GuildID);
265 await client.database.notes.delete(GuildID);
266 await client.database.transcripts.deleteAll(GuildID);
267 await interaction.editReply({
268 embeds: [
269 new EmojiEmbed()
270 .setTitle("Purge")
271 .setDescription(`Deleted data for ${guild.name}`)
272 .setStatus("Success")
273 .setEmoji("SETTINGS.STATS.GREEN")
274 ],
275 components: []
276 });
277 } else if (i.customId === "cache") {
TheCodedProfa38cbb32023-03-11 17:22:25 -0500278 await client.memory.forceUpdate(guild.id);
279 await interaction.editReply({
280 embeds: [
281 new EmojiEmbed()
282 .setTitle("Cache")
283 .setDescription(`Reset cache for ${guild.name}`)
284 .setStatus("Success")
285 .setEmoji("SETTINGS.STATS.GREEN")
286 ],
287 components: []
288 });
289 }
290 break;
TheCodedProfca29ebb2023-03-10 17:40:09 -0500291 }
TheCodedProfa38cbb32023-03-11 17:22:25 -0500292 case "announce": {
TheCodedProf528de572023-03-11 17:28:29 -0500293 const channelsToNotify = await client.database.guilds.staffChannels();
TheCodedProfa38cbb32023-03-11 17:22:25 -0500294 const modal2 = new ModalBuilder()
295 .addComponents(
296 new ActionRowBuilder<TextInputBuilder>().addComponents(
297 new TextInputBuilder()
298 .setStyle(TextInputStyle.Paragraph)
299 .setLabel("Announcement")
300 .setCustomId("announcement")
301 .setPlaceholder("Announcement...")
302 )
303 )
304 .setTitle("Announcement")
305 .setCustomId("announce");
306 await i1.showModal(modal2);
307 let out: ModalSubmitInteraction;
308 try {
309 out = await i1.awaitModalSubmit({
310 filter: (i) => i.customId === "announce" && i.user.id === interaction.user.id,
311 time: 300000
312 });
313 } catch {
314 return;
315 }
316 await out.deferUpdate();
317 const announcement = out.fields.getTextInputValue("announcement");
TheCodedProfca29ebb2023-03-10 17:40:09 -0500318 await interaction.editReply({
TheCodedProfa38cbb32023-03-11 17:22:25 -0500319 embeds: [
320 new EmojiEmbed()
321 .setTitle("Announcement")
TheCodedProf528de572023-03-11 17:28:29 -0500322 .setDescription(
323 `Announcement will be sent to ${channelsToNotify.length} channels.\n\n${announcement}`
324 )
TheCodedProfa38cbb32023-03-11 17:22:25 -0500325 .setStatus("Success")
326 .setEmoji("SETTINGS.STATS.GREEN")
327 ],
328 components: [
329 new ActionRowBuilder<ButtonBuilder>().addComponents(
TheCodedProf528de572023-03-11 17:28:29 -0500330 new ButtonBuilder()
331 .setCustomId("confirm")
332 .setLabel("Confirm")
333 .setStyle(ButtonStyle.Success),
TheCodedProfa38cbb32023-03-11 17:22:25 -0500334 new ButtonBuilder().setCustomId("cancel").setLabel("Cancel").setStyle(ButtonStyle.Danger)
335 )
336 ]
TheCodedProf35e73712023-03-10 17:35:35 -0500337 });
TheCodedProfa38cbb32023-03-11 17:22:25 -0500338
339 let i;
340 try {
341 i = await m.awaitMessageComponent<ComponentType.Button>({
342 filter: (i) => i.user.id === interaction.user.id,
343 time: 300000
344 });
345 } catch {
346 return;
347 }
348 if (i.customId === "confirm") {
349 await i.deferUpdate();
350 await interaction.editReply({
351 embeds: [
352 new EmojiEmbed()
353 .setTitle("Announcement")
TheCodedProf528de572023-03-11 17:28:29 -0500354 .setDescription(
355 `Sending to ${channelsToNotify.length} channels. Preview:\n\n${announcement}`
356 )
TheCodedProfa38cbb32023-03-11 17:22:25 -0500357 .setStatus("Success")
358 .setEmoji("SETTINGS.STATS.GREEN")
359 ],
360 components: []
361 });
362 const announcementEmbed = new EmojiEmbed()
363 .setTitle("Developer Announcement")
364 .setDescription(announcement)
365 .setStatus("Danger")
366 .setEmoji("NUCLEUS.LOGO")
TheCodedProf528de572023-03-11 17:28:29 -0500367 .setFooter({
368 text: `Sent by ${interaction.user.username}`,
369 iconURL: interaction.user.displayAvatarURL()
370 });
TheCodedProfa38cbb32023-03-11 17:22:25 -0500371 for (const channel of channelsToNotify) {
TheCodedProf528de572023-03-11 17:28:29 -0500372 const ch = (await client.channels.fetch(channel)) as GuildTextBasedChannel | null;
TheCodedProfa38cbb32023-03-11 17:22:25 -0500373 if (!ch) continue;
374 await ch.send({
375 embeds: [announcementEmbed]
376 });
377 }
378 await interaction.editReply({
379 embeds: [
380 new EmojiEmbed()
381 .setTitle("Announcement")
TheCodedProf528de572023-03-11 17:28:29 -0500382 .setDescription(
383 `Sent to ${channelsToNotify.length} channels. Preview:\n\n${announcement}`
384 )
TheCodedProfa38cbb32023-03-11 17:22:25 -0500385 .setStatus("Success")
386 .setEmoji("SETTINGS.STATS.GREEN")
387 ],
388 components: []
TheCodedProf528de572023-03-11 17:28:29 -0500389 });
TheCodedProfa38cbb32023-03-11 17:22:25 -0500390 } else if (i.customId === "cancel") {
391 await i.deferUpdate();
392 await interaction.editReply({
393 embeds: [new EmojiEmbed().setTitle("Announcement Cancelled").setStatus("Danger")],
394 components: []
395 });
396 }
397 break;
TheCodedProfca29ebb2023-03-10 17:40:09 -0500398 }
TheCodedProfe92b9b52023-03-06 17:07:34 -0500399 }
400 }
pineafan63fc5e22022-08-04 22:04:10 +0100401};
pineafan4f164f32022-02-26 22:07:12 +0000402
pineafan4f164f32022-02-26 22:07:12 +0000403export { command };
404export { callback };