blob: 413cedf8872d5b280582d0e0aa8ff1bd924af40d [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),
96 new ButtonBuilder().setCustomId("announce").setLabel("Announce to all Guilds").setStyle(ButtonStyle.Danger)
pineafan1e462ab2023-03-07 21:34:06 +000097 )
98 ]
TheCodedProfe92b9b52023-03-06 17:07:34 -050099 });
100
101 const modal = new ModalBuilder()
102 .addComponents(
pineafan1e462ab2023-03-07 21:34:06 +0000103 new ActionRowBuilder<TextInputBuilder>().addComponents(
104 new TextInputBuilder()
105 .setStyle(TextInputStyle.Short)
106 .setLabel("Guild ID")
107 .setCustomId("guildID")
108 .setPlaceholder("Guild ID")
109 .setMinLength(16)
110 .setMaxLength(25)
111 )
TheCodedProfe92b9b52023-03-06 17:07:34 -0500112 )
113 .setTitle("Admin Panel")
pineafan1e462ab2023-03-07 21:34:06 +0000114 .setCustomId("adminPanel");
TheCodedProfe92b9b52023-03-06 17:07:34 -0500115 let i1: ButtonInteraction;
pineafan1e462ab2023-03-07 21:34:06 +0000116 const channel = await client.channels.fetch(interaction.channelId);
117 if (
118 !channel ||
119 [ChannelType.GuildCategory, ChannelType.GroupDM, ChannelType.GuildStageVoice].includes(channel.type)
120 )
121 return;
TheCodedProfe92b9b52023-03-06 17:07:34 -0500122 // console.log(interaction)
123 if (!("awaitMessageComponent" in channel)) return;
TheCodedProf35e73712023-03-10 17:35:35 -0500124 let GuildID = interaction.guildId;
TheCodedProfe92b9b52023-03-06 17:07:34 -0500125 try {
TheCodedProfa38cbb32023-03-11 17:22:25 -0500126 i1 = await m.awaitMessageComponent<ComponentType.Button>({
127 filter: (i) => i.user.id === interaction.user.id,
TheCodedProfe92b9b52023-03-06 17:07:34 -0500128 time: 300000
pineafan1e462ab2023-03-07 21:34:06 +0000129 });
TheCodedProfa38cbb32023-03-11 17:22:25 -0500130 } catch (e) {
131 console.log(e);
pineafan1e462ab2023-03-07 21:34:06 +0000132 return;
133 }
TheCodedProfa38cbb32023-03-11 17:22:25 -0500134 switch(i1.customId) {
135 case "admin": {
136 if (!GuildID) {
137 await i1.showModal(modal);
138 let out: ModalSubmitInteraction;
139 try {
140 out = await i1.awaitModalSubmit({
141 filter: (i) => i.customId === "adminPanel" && i.user.id === interaction.user.id,
142 time: 300000
143 });
144 } catch {
145 return;
146 }
147 await out.deferUpdate();
148 GuildID = out.fields.getTextInputValue("guildID");
149 } else if (!client.guilds.cache.has(GuildID)) {
150 await interaction.editReply({
151 embeds: [new EmojiEmbed().setTitle("Admin").setDescription("Not in server").setStatus("Danger")],
152 components: []
153 });
154 }
155
156 await interaction.editReply({
157 embeds: [],
158 components: [
159 new ActionRowBuilder<ButtonBuilder>().addComponents(
160 new ButtonBuilder().setCustomId("stats").setLabel("Stats").setStyle(ButtonStyle.Primary),
161 new ButtonBuilder().setCustomId("data").setLabel("Guild data").setStyle(ButtonStyle.Secondary),
162 new ButtonBuilder().setCustomId("cache").setLabel("Reset cache").setStyle(ButtonStyle.Success),
163 new ButtonBuilder().setCustomId("leave").setLabel("Leave").setStyle(ButtonStyle.Danger),
164 new ButtonBuilder().setCustomId("purge").setLabel("Delete data").setStyle(ButtonStyle.Danger)
TheCodedProfe92b9b52023-03-06 17:07:34 -0500165 )
TheCodedProfa38cbb32023-03-11 17:22:25 -0500166 ]
TheCodedProfca29ebb2023-03-10 17:40:09 -0500167 });
TheCodedProfa38cbb32023-03-11 17:22:25 -0500168 let i;
169 try {
170 i = await m.awaitMessageComponent<ComponentType.Button>({
171 filter: (i) => i.user.id === interaction.user.id && i.message.id === m.id,
172 time: 300000
173 });
174 } catch {
175 return;
176 }
177 const guild = (await client.guilds.fetch(GuildID)) as Guild | null;
178 if (!guild) {
179 await i.deferUpdate();
180 await interaction.editReply({
181 embeds: [new EmojiEmbed().setTitle("Admin").setDescription("Not in server").setStatus("Danger")],
182 components: []
183 });
184 return;
185 }
186 if (i.customId === "stats") {
187 await i.deferUpdate();
188 await interaction.editReply({
189 embeds: [
190 new EmojiEmbed()
191 .setTitle("Stats")
192 .setDescription(
193 `**Name:** ${guild.name}\n` +
194 `**ID:** \`${guild.id}\`\n` +
195 `**Owner:** ${client.users.cache.get(guild.ownerId)!.tag}\n` +
196 `**Member Count:** ${guild.memberCount}\n` +
197 `**Created:** <t:${guild.createdTimestamp}:F>\n` +
198 `**Added Nucleus:** <t:${guild.members.me!.joinedTimestamp}:R>\n` +
199 `**Nucleus' Perms:** https://discordapi.com/permissions.html#${guild.members.me!.permissions.valueOf()}\n`
200 )
201 .setStatus("Success")
202 .setEmoji("SETTINGS.STATS.GREEN")
203 ]
204 });
205 } else if (i.customId === "leave") {
206 if (!(await confirm(interaction))) {
207 await interaction.editReply({
208 embeds: [new EmojiEmbed().setTitle("No changes were made").setStatus("Danger")],
209 components: []
210 });
211 return;
212 }
213 await guild.leave();
214 await interaction.editReply({
215 embeds: [
216 new EmojiEmbed()
217 .setTitle("Left")
218 .setDescription(`Left ${guild.name}`)
219 .setStatus("Success")
220 .setEmoji("SETTINGS.STATS.GREEN")
221 ],
222 components: []
223 });
224 } else if (i.customId === "data") {
225 await i.deferUpdate();
226 // Get all the data and convert to a string
227 const data = await client.database.guilds.read(guild.id);
228 const stringified = JSON.stringify(data, null, 2);
229 const buffer = Buffer.from(stringified);
230 const attachment = new AttachmentBuilder(buffer).setName("data.json");
231 await interaction.editReply({
232 embeds: [
233 new EmojiEmbed().setTitle("Data").setDescription(`Data for ${guild.name}`).setStatus("Success")
234 ],
235 components: [],
236 files: [attachment]
237 });
238 } else if (i.customId === "purge") {
239 if (!(await confirm(interaction))) {
240 await interaction.editReply({
241 embeds: [new EmojiEmbed().setTitle("No changes were made").setStatus("Danger")],
242 components: []
243 });
244 return;
245 }
246 await client.database.guilds.delete(GuildID);
247 await client.database.history.delete(GuildID);
248 await client.database.notes.delete(GuildID);
249 await client.database.transcripts.deleteAll(GuildID);
250 await interaction.editReply({
251 embeds: [
252 new EmojiEmbed()
253 .setTitle("Purge")
254 .setDescription(`Deleted data for ${guild.name}`)
255 .setStatus("Success")
256 .setEmoji("SETTINGS.STATS.GREEN")
257 ],
258 components: []
259 });
260 } else if (i.customId === "cache") {
261 await i.deferUpdate();
262 await client.memory.forceUpdate(guild.id);
263 await interaction.editReply({
264 embeds: [
265 new EmojiEmbed()
266 .setTitle("Cache")
267 .setDescription(`Reset cache for ${guild.name}`)
268 .setStatus("Success")
269 .setEmoji("SETTINGS.STATS.GREEN")
270 ],
271 components: []
272 });
273 }
274 break;
TheCodedProfca29ebb2023-03-10 17:40:09 -0500275 }
TheCodedProfa38cbb32023-03-11 17:22:25 -0500276 case "announce": {
277 const channelsToNotify = await client.database.guilds.staffChannels()
278 const modal2 = new ModalBuilder()
279 .addComponents(
280 new ActionRowBuilder<TextInputBuilder>().addComponents(
281 new TextInputBuilder()
282 .setStyle(TextInputStyle.Paragraph)
283 .setLabel("Announcement")
284 .setCustomId("announcement")
285 .setPlaceholder("Announcement...")
286 )
287 )
288 .setTitle("Announcement")
289 .setCustomId("announce");
290 await i1.showModal(modal2);
291 let out: ModalSubmitInteraction;
292 try {
293 out = await i1.awaitModalSubmit({
294 filter: (i) => i.customId === "announce" && i.user.id === interaction.user.id,
295 time: 300000
296 });
297 } catch {
298 return;
299 }
300 await out.deferUpdate();
301 const announcement = out.fields.getTextInputValue("announcement");
TheCodedProfca29ebb2023-03-10 17:40:09 -0500302 await interaction.editReply({
TheCodedProfa38cbb32023-03-11 17:22:25 -0500303 embeds: [
304 new EmojiEmbed()
305 .setTitle("Announcement")
306 .setDescription(`Announcement will be sent to ${channelsToNotify.length} channels.\n\n${announcement}`)
307 .setStatus("Success")
308 .setEmoji("SETTINGS.STATS.GREEN")
309 ],
310 components: [
311 new ActionRowBuilder<ButtonBuilder>().addComponents(
312 new ButtonBuilder().setCustomId("confirm").setLabel("Confirm").setStyle(ButtonStyle.Success),
313 new ButtonBuilder().setCustomId("cancel").setLabel("Cancel").setStyle(ButtonStyle.Danger)
314 )
315 ]
TheCodedProf35e73712023-03-10 17:35:35 -0500316 });
TheCodedProfa38cbb32023-03-11 17:22:25 -0500317
318 let i;
319 try {
320 i = await m.awaitMessageComponent<ComponentType.Button>({
321 filter: (i) => i.user.id === interaction.user.id,
322 time: 300000
323 });
324 } catch {
325 return;
326 }
327 if (i.customId === "confirm") {
328 await i.deferUpdate();
329 await interaction.editReply({
330 embeds: [
331 new EmojiEmbed()
332 .setTitle("Announcement")
333 .setDescription(`Sending to ${channelsToNotify.length} channels. Preview:\n\n${announcement}`)
334 .setStatus("Success")
335 .setEmoji("SETTINGS.STATS.GREEN")
336 ],
337 components: []
338 });
339 const announcementEmbed = new EmojiEmbed()
340 .setTitle("Developer Announcement")
341 .setDescription(announcement)
342 .setStatus("Danger")
343 .setEmoji("NUCLEUS.LOGO")
344 .setFooter({text: `Sent by ${interaction.user.username}`, iconURL: interaction.user.displayAvatarURL()})
345 for (const channel of channelsToNotify) {
346 const ch = await client.channels.fetch(channel) as GuildTextBasedChannel | null;
347 if (!ch) continue;
348 await ch.send({
349 embeds: [announcementEmbed]
350 });
351 }
352 await interaction.editReply({
353 embeds: [
354 new EmojiEmbed()
355 .setTitle("Announcement")
356 .setDescription(`Sent to ${channelsToNotify.length} channels. Preview:\n\n${announcement}`)
357 .setStatus("Success")
358 .setEmoji("SETTINGS.STATS.GREEN")
359 ],
360 components: []
361 })
362 } else if (i.customId === "cancel") {
363 await i.deferUpdate();
364 await interaction.editReply({
365 embeds: [new EmojiEmbed().setTitle("Announcement Cancelled").setStatus("Danger")],
366 components: []
367 });
368 }
369 break;
TheCodedProfca29ebb2023-03-10 17:40:09 -0500370 }
TheCodedProfe92b9b52023-03-06 17:07:34 -0500371 }
372 }
pineafan63fc5e22022-08-04 22:04:10 +0100373};
pineafan4f164f32022-02-26 22:07:12 +0000374
pineafan4f164f32022-02-26 22:07:12 +0000375export { command };
376export { callback };