Nucleus stats
diff --git a/src/commands/settings/stats.ts b/src/commands/settings/stats.ts
index 118afc2..7dd9cf4 100644
--- a/src/commands/settings/stats.ts
+++ b/src/commands/settings/stats.ts
@@ -1,5 +1,5 @@
import { LoadingEmbed } from "../../utils/defaults.js";
-import Discord, { CommandInteraction, Message, ActionRowBuilder, StringSelectMenuBuilder, ButtonBuilder, ButtonStyle, StringSelectMenuOptionBuilder, APIMessageComponentEmoji, TextInputBuilder, StringSelectMenuInteraction, ButtonInteraction } from "discord.js";
+import Discord, { CommandInteraction, Message, ActionRowBuilder, StringSelectMenuBuilder, ButtonBuilder, ButtonStyle, StringSelectMenuOptionBuilder, APIMessageComponentEmoji, TextInputBuilder, StringSelectMenuInteraction, ButtonInteraction, MessageComponentInteraction, ChannelSelectMenuBuilder, ChannelSelectMenuInteraction } from "discord.js";
import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
import type { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import client from "../../utils/client.js";
@@ -16,7 +16,7 @@
.setDescription("Controls channels which update when someone joins or leaves the server")
-const showModal = async (interaction: StringSelectMenuInteraction, current: { enabled: boolean; name: string; }) => {
+const showModal = async (interaction: MessageComponentInteraction, current: { enabled: boolean; name: string; }) => {
await interaction.showModal(
new Discord.ModalBuilder()
.setCustomId("modal")
@@ -71,6 +71,144 @@
);
}
+type ObjectSchema = Record<string, {name: string, enabled: boolean}>
+
+/*
+let out: Discord.ModalSubmitInteraction | null = null;
+try {
+ out = await modalInteractionCollector(
+ m,
+ (m) => m.channel!.id === interaction.channel!.id,
+ (_) => true
+ ) as Discord.ModalSubmitInteraction | null;
+} catch (e) {
+ continue;
+}
+if (!out) continue
+out = out!;
+if (!out.fields) continue;
+if (out.isButton()) continue;
+const name = out.fields.getTextInputValue("text")
+*/
+
+const addStatsChannel = async (interaction: CommandInteraction, m: Message, currentObject: ObjectSchema): Promise<ObjectSchema> => {
+ let closed = false;
+ let cancelled = false;
+ const originalObject = Object.fromEntries(Object.entries(currentObject).map(([k, v]) => [k, {...v}]));
+ let newChannel: string | undefined;
+ let newChannelName: string = "{memberCount:all}-members";
+ let newChannelEnabled: boolean = true;
+ do {
+ await interaction.editReply({
+ embeds: [new EmojiEmbed()
+ .setTitle("Stats Channel")
+ .setDescription(
+ `New stats channel` + (newChannel ? ` in <#${newChannel}>` : "") + "\n\n" +
+ `**Name:** \`${newChannelName}\`\n` +
+ `**Preview:** ${await convertCurlyBracketString(newChannelName, interaction.user!.id, interaction.user.username, interaction.guild!.name, interaction.guild!.members)}\n` +
+ `**Enabled:** ${newChannelEnabled ? "Yes" : "No"}\n\n`
+ )
+ .setEmoji("SETTINGS.STATS.GREEN")
+ .setStatus("Success")
+ ], components: [
+ new ActionRowBuilder<ChannelSelectMenuBuilder>().addComponents(
+ new ChannelSelectMenuBuilder()
+ .setCustomId("channel")
+ ),
+ new ActionRowBuilder<ButtonBuilder>().addComponents(
+ new ButtonBuilder()
+ .setLabel("Cancel")
+ .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
+ .setStyle(ButtonStyle.Danger)
+ .setCustomId("back"),
+ new ButtonBuilder()
+ .setLabel("Save")
+ .setEmoji(getEmojiByName("ICONS.SAVE", "id"))
+ .setStyle(ButtonStyle.Success)
+ .setCustomId("save"),
+ new ButtonBuilder()
+ .setLabel("Edit name")
+ .setEmoji(getEmojiByName("ICONS.EDIT", "id"))
+ .setStyle(ButtonStyle.Primary)
+ .setCustomId("editName"),
+ new ButtonBuilder()
+ .setLabel(newChannelEnabled ? "Enabled" : "Disabled")
+ .setEmoji(getEmojiByName(newChannelEnabled ? "CONTROL.TICK" : "CONTROL.CROSS", "id"))
+ .setStyle(ButtonStyle.Secondary)
+ .setCustomId("toggleEnabled")
+ )
+ ]
+ });
+ let i: ButtonInteraction | ChannelSelectMenuInteraction;
+ try {
+ i = await m.awaitMessageComponent({ time: 300000, filter: (i) => { return i.user.id === interaction.user.id && i.channel!.id === interaction.channel!.id }}) as ButtonInteraction | ChannelSelectMenuInteraction;
+ } catch (e) {
+ closed = true;
+ cancelled = true;
+ break;
+ }
+ if (i.isButton()) {
+ switch (i.customId) {
+ case "back":
+ if(!i.deferred) await i.deferUpdate();
+ closed = true;
+ break;
+ case "save":
+ if(!i.deferred) await i.deferUpdate(); //I'm lost...
+ if (newChannel) {
+ currentObject[newChannel] = {
+ name: newChannelName,
+ enabled: newChannelEnabled
+ }
+ }
+ closed = true;
+ break;
+ case "editName":
+ await interaction.editReply({
+ embeds: [new EmojiEmbed()
+ .setTitle("Stats Channel")
+ .setDescription("Modal opened. If you can't see it, click back and try again.")
+ .setStatus("Success")
+ .setEmoji("SETTINGS.STATS.GREEN")
+ ],
+ components: [
+ new ActionRowBuilder<ButtonBuilder>().addComponents(
+ new ButtonBuilder()
+ .setLabel("Back")
+ .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
+ .setStyle(ButtonStyle.Primary)
+ .setCustomId("back")
+ )
+ ]
+ });
+ showModal(i, {name: newChannelName, enabled: newChannelEnabled})
+
+ const out = await modalInteractionCollector(
+ m,
+ (m) => m.channel!.id === interaction.channel!.id,
+ (_) => true
+ ) as Discord.ModalSubmitInteraction | null;
+ if (!out) continue;
+ if (!out.fields) continue;
+ if (out.isButton()) continue;
+ newChannelName = out.fields.getTextInputValue("text");
+ break;
+ case "toggleEnabled":
+ if(!i.deferred) await i.deferUpdate();
+ newChannelEnabled = !newChannelEnabled;
+ break;
+ }
+ } else {
+ if(!i.deferred) await i.deferUpdate();
+ if (i.customId === "channel") {
+ newChannel = i.values[0];
+ }
+ }
+ } while (!closed)
+ if (cancelled) return originalObject;
+ if (!(newChannel && newChannelName && newChannelEnabled)) return originalObject;
+ return currentObject; // check 157
+}
const callback = async (interaction: CommandInteraction) => {
if (!interaction.guild) return;
const { renderChannel } = client.logger;
@@ -78,7 +216,7 @@
let page = 0;
let closed = false;
const config = await client.database.guilds.read(interaction.guild.id);
- const currentObject = config.stats;
+ let currentObject: ObjectSchema = config.stats;
let modified = false;
do {
let embed = new EmojiEmbed()
@@ -209,6 +347,20 @@
)
]
});
+ let out: Discord.ModalSubmitInteraction | null;
+ try {
+ out = await modalInteractionCollector(
+ m,
+ (m) => m.channel!.id === interaction.channel!.id,
+ (_) => true
+ ) as Discord.ModalSubmitInteraction | null;
+ } catch (e) {
+ continue;
+ }
+ if (!out) continue
+ if (!out.fields) continue
+ if (out.isButton()) continue;
+ currentObject[Object.keys(currentObject)[page]!]!.name = out.fields.getTextInputValue("text");
break;
}
case "toggleEnabled": {
@@ -236,6 +388,7 @@
page++;
break;
case "add":
+ currentObject = await addStatsChannel(interaction, m, currentObject);
break;
case "save":
client.database.guilds.write(interaction.guild.id, {stats: currentObject});
diff --git a/src/utils/dualCollector.ts b/src/utils/dualCollector.ts
index 1a57a85..64e87b8 100644
--- a/src/utils/dualCollector.ts
+++ b/src/utils/dualCollector.ts
@@ -58,8 +58,9 @@
filter: (i: MessageComponentInteraction) => interactionFilter(i),
time: 300000
})
- .on("collect", (i: ButtonInteraction) => {
+ .on("collect", async (i: ButtonInteraction) => {
mod.stop();
+ if (!i.deferred) await i.deferUpdate();
resolve(i);
});
const mod = new InteractionCollector(client as Client, {
@@ -67,12 +68,11 @@
time: 300000
}).on("collect", async (i: ModalSubmitInteraction) => {
int.stop();
- await i.deferUpdate();
+ if (!i.deferred) await i.deferUpdate();
resolve(i);
});
});
} catch (e) {
- console.log(e);
return null;
}
return out;