blob: d410da8fcd94214f7c9ca1dfbffd0a8161a5ea15 [file] [log] [blame]
import {
ActionRowBuilder,
AttachmentBuilder,
ButtonBuilder,
ButtonInteraction,
ButtonStyle,
ChannelType,
CommandInteraction,
ComponentType,
Guild,
GuildTextBasedChannel,
ModalBuilder,
ModalSubmitInteraction,
TextInputBuilder,
TextInputStyle
} from "discord.js";
import type { SlashCommandSubcommandBuilder } from "discord.js";
import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
import client from "../../utils/client.js";
import config from "../../config/main.js";
const command = (builder: SlashCommandSubcommandBuilder) =>
builder.setName("stats").setDescription("Gets the bot's stats");
const confirm = async (interaction: ButtonInteraction) => {
const requiredTexts = [
"just do it",
"yes, do as i say!",
"clicksminuteper/nucleus",
"i've said it once i'll say it again",
"no, i've changed my mind",
"this incident will be reported",
"coded told me to",
"mini told me to",
"pinea told me to",
"what's a java script",
"it's a feature not a bug",
"that never happened during testing"
];
const chosen = requiredTexts[Math.floor(Math.random() * (requiredTexts.length - 1))]!;
const modal = new ModalBuilder()
.addComponents(
new ActionRowBuilder<TextInputBuilder>().addComponents(
new TextInputBuilder()
.setStyle(TextInputStyle.Short)
.setLabel(`Type "${chosen}" below`)
.setCustomId("confirm")
.setPlaceholder("1234567890")
.setMinLength(chosen.length)
.setMaxLength(chosen.length)
)
)
.setTitle("Admin Panel")
.setCustomId("adminPanel");
await interaction.showModal(modal);
let out: ModalSubmitInteraction;
try {
out = await interaction.awaitModalSubmit({
filter: (i) => i.customId === "adminPanel" && i.user.id === interaction.user.id,
time: 300000
});
} catch {
return;
}
await out.deferUpdate();
const typed = out.fields.getTextInputValue("confirm");
return typed.toLowerCase() === chosen.toLowerCase();
};
const callback = async (interaction: CommandInteraction): Promise<void> => {
const description = `**Servers:** ${client.guilds.cache.size}\n` + `**Ping:** \`${client.ws.ping * 2}ms\``;
const m = await interaction.reply({
embeds: [
new EmojiEmbed()
.setTitle("Stats")
.setDescription(description)
.setStatus("Success")
.setEmoji("SETTINGS.STATS.GREEN")
],
ephemeral: true,
fetchReply: true
});
if (config.owners.includes(interaction.user.id)) {
await interaction.editReply({
embeds: [
new EmojiEmbed()
.setTitle("Admin")
.setDescription(description)
.setStatus("Success")
.setEmoji("SETTINGS.STATS.GREEN")
],
components: [
new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder().setCustomId("admin").setLabel("Admin Panel").setStyle(ButtonStyle.Primary),
new ButtonBuilder()
.setCustomId("announce")
.setLabel("Announce to all Guilds")
.setStyle(ButtonStyle.Danger)
)
]
});
const modal = new ModalBuilder()
.addComponents(
new ActionRowBuilder<TextInputBuilder>().addComponents(
new TextInputBuilder()
.setStyle(TextInputStyle.Short)
.setLabel("Guild ID")
.setCustomId("guildID")
.setPlaceholder("Guild ID")
.setMinLength(16)
.setMaxLength(25)
)
)
.setTitle("Admin Panel")
.setCustomId("adminPanel");
let i1: ButtonInteraction;
const channel = await client.channels.fetch(interaction.channelId);
if (
!channel ||
[ChannelType.GuildCategory, ChannelType.GroupDM, ChannelType.GuildStageVoice].includes(channel.type)
)
return;
// console.log(interaction)
if (!("awaitMessageComponent" in channel)) return;
let GuildID = interaction.guildId;
try {
i1 = await m.awaitMessageComponent<ComponentType.Button>({
filter: (i) => i.user.id === interaction.user.id,
time: 300000
});
} catch (e) {
console.log(e);
return;
}
switch (i1.customId) {
case "admin": {
if (!GuildID) {
await i1.showModal(modal);
let out: ModalSubmitInteraction;
try {
out = await i1.awaitModalSubmit({
filter: (i) => i.customId === "adminPanel" && i.user.id === interaction.user.id,
time: 300000
});
} catch {
return;
}
await out.deferUpdate();
GuildID = out.fields.getTextInputValue("guildID");
} else if (!client.guilds.cache.has(GuildID)) {
await interaction.editReply({
embeds: [
new EmojiEmbed().setTitle("Admin").setDescription("Not in server").setStatus("Danger")
],
components: []
});
}
await interaction.editReply({
embeds: [],
components: [
new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder().setCustomId("stats").setLabel("Stats").setStyle(ButtonStyle.Primary),
new ButtonBuilder()
.setCustomId("data")
.setLabel("Guild data")
.setStyle(ButtonStyle.Secondary),
new ButtonBuilder()
.setCustomId("cache")
.setLabel("Reset cache")
.setStyle(ButtonStyle.Success),
new ButtonBuilder().setCustomId("leave").setLabel("Leave").setStyle(ButtonStyle.Danger),
new ButtonBuilder()
.setCustomId("purge")
.setLabel("Delete data")
.setStyle(ButtonStyle.Danger)
)
]
});
let i;
try {
i = await m.awaitMessageComponent<ComponentType.Button>({
filter: (i) => i.user.id === interaction.user.id && i.message.id === m.id,
time: 300000
});
} catch {
return;
}
const guild = (await client.guilds.fetch(GuildID)) as Guild | null;
if (!guild) {
await i.deferUpdate();
await interaction.editReply({
embeds: [
new EmojiEmbed().setTitle("Admin").setDescription("Not in server").setStatus("Danger")
],
components: []
});
return;
}
if (i.customId === "stats") {
await i.deferUpdate();
await interaction.editReply({
embeds: [
new EmojiEmbed()
.setTitle("Stats")
.setDescription(
`**Name:** ${guild.name}\n` +
`**ID:** \`${guild.id}\`\n` +
`**Owner:** ${client.users.cache.get(guild.ownerId)!.tag}\n` +
`**Member Count:** ${guild.memberCount}\n` +
`**Created:** <t:${guild.createdTimestamp}:F>\n` +
`**Added Nucleus:** <t:${guild.members.me!.joinedTimestamp}:R>\n` +
`**Nucleus' Perms:** https://discordapi.com/permissions.html#${guild.members.me!.permissions.valueOf()}\n`
)
.setStatus("Success")
.setEmoji("SETTINGS.STATS.GREEN")
]
});
} else if (i.customId === "leave") {
if (!(await confirm(i))) {
await interaction.editReply({
embeds: [new EmojiEmbed().setTitle("No changes were made").setStatus("Danger")],
components: []
});
return;
}
await guild.leave();
await interaction.editReply({
embeds: [
new EmojiEmbed()
.setTitle("Left")
.setDescription(`Left ${guild.name}`)
.setStatus("Success")
.setEmoji("SETTINGS.STATS.GREEN")
],
components: []
});
} else if (i.customId === "data") {
await i.deferUpdate();
// Get all the data and convert to a string
const data = await client.database.guilds.read(guild.id);
const stringified = JSON.stringify(data, null, 2);
const buffer = Buffer.from(stringified);
const attachment = new AttachmentBuilder(buffer).setName("data.json");
await interaction.editReply({
embeds: [
new EmojiEmbed()
.setTitle("Data")
.setDescription(`Data for ${guild.name}`)
.setStatus("Success")
],
components: [],
files: [attachment]
});
} else if (i.customId === "purge") {
if (!(await confirm(i))) {
await interaction.editReply({
embeds: [new EmojiEmbed().setTitle("No changes were made").setStatus("Danger")],
components: []
});
return;
}
await client.database.guilds.delete(GuildID);
await client.database.history.delete(GuildID);
await client.database.notes.delete(GuildID);
await client.database.transcripts.deleteAll(GuildID);
await interaction.editReply({
embeds: [
new EmojiEmbed()
.setTitle("Purge")
.setDescription(`Deleted data for ${guild.name}`)
.setStatus("Success")
.setEmoji("SETTINGS.STATS.GREEN")
],
components: []
});
} else if (i.customId === "cache") {
await i.deferUpdate();
await client.memory.forceUpdate(guild.id);
await interaction.editReply({
embeds: [
new EmojiEmbed()
.setTitle("Cache")
.setDescription(`Reset cache for ${guild.name}`)
.setStatus("Success")
.setEmoji("SETTINGS.STATS.GREEN")
],
components: []
});
}
break;
}
case "announce": {
const channelsToNotify = await client.database.guilds.staffChannels();
const modal2 = new ModalBuilder()
.addComponents(
new ActionRowBuilder<TextInputBuilder>().addComponents(
new TextInputBuilder()
.setStyle(TextInputStyle.Paragraph)
.setLabel("Announcement")
.setCustomId("announcement")
.setPlaceholder("Announcement...")
)
)
.setTitle("Announcement")
.setCustomId("announce");
await i1.showModal(modal2);
let out: ModalSubmitInteraction;
try {
out = await i1.awaitModalSubmit({
filter: (i) => i.customId === "announce" && i.user.id === interaction.user.id,
time: 300000
});
} catch {
return;
}
await out.deferUpdate();
const announcement = out.fields.getTextInputValue("announcement");
await interaction.editReply({
embeds: [
new EmojiEmbed()
.setTitle("Announcement")
.setDescription(
`Announcement will be sent to ${channelsToNotify.length} channels.\n\n${announcement}`
)
.setStatus("Success")
.setEmoji("SETTINGS.STATS.GREEN")
],
components: [
new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setCustomId("confirm")
.setLabel("Confirm")
.setStyle(ButtonStyle.Success),
new ButtonBuilder().setCustomId("cancel").setLabel("Cancel").setStyle(ButtonStyle.Danger)
)
]
});
let i;
try {
i = await m.awaitMessageComponent<ComponentType.Button>({
filter: (i) => i.user.id === interaction.user.id,
time: 300000
});
} catch {
return;
}
if (i.customId === "confirm") {
await i.deferUpdate();
await interaction.editReply({
embeds: [
new EmojiEmbed()
.setTitle("Announcement")
.setDescription(
`Sending to ${channelsToNotify.length} channels. Preview:\n\n${announcement}`
)
.setStatus("Success")
.setEmoji("SETTINGS.STATS.GREEN")
],
components: []
});
const announcementEmbed = new EmojiEmbed()
.setTitle("Developer Announcement")
.setDescription(announcement)
.setStatus("Danger")
.setEmoji("NUCLEUS.LOGO")
.setFooter({
text: `Sent by ${interaction.user.username}`,
iconURL: interaction.user.displayAvatarURL()
});
for (const channel of channelsToNotify) {
const ch = (await client.channels.fetch(channel)) as GuildTextBasedChannel | null;
if (!ch) continue;
await ch.send({
embeds: [announcementEmbed]
});
}
await interaction.editReply({
embeds: [
new EmojiEmbed()
.setTitle("Announcement")
.setDescription(
`Sent to ${channelsToNotify.length} channels. Preview:\n\n${announcement}`
)
.setStatus("Success")
.setEmoji("SETTINGS.STATS.GREEN")
],
components: []
});
} else if (i.customId === "cancel") {
await i.deferUpdate();
await interaction.editReply({
embeds: [new EmojiEmbed().setTitle("Announcement Cancelled").setStatus("Danger")],
components: []
});
}
break;
}
}
}
};
export { command };
export { callback };