possibly finished current features
diff --git a/src/commands/settings/logs/attachment.ts b/src/commands/settings/logs/attachment.ts
index 6f825bc..545e3ff 100644
--- a/src/commands/settings/logs/attachment.ts
+++ b/src/commands/settings/logs/attachment.ts
@@ -1,195 +1,105 @@
import { LoadingEmbed } from "../../../utils/defaults.js";
-import { ChannelType } from "discord-api-types/v9";
-import Discord, { CommandInteraction, ActionRowBuilder, ButtonBuilder, ButtonStyle, ButtonInteraction } from "discord.js";
+import Discord, { CommandInteraction, ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelSelectMenuBuilder } from "discord.js";
import EmojiEmbed from "../../../utils/generateEmojiEmbed.js";
-import confirmationMessage from "../../../utils/confirmationMessage.js";
import getEmojiByName from "../../../utils/getEmojiByName.js";
import type { SlashCommandSubcommandBuilder } from "discord.js";
import client from "../../../utils/client.js";
+import { getCommandMentionByName } from "../../../utils/getCommandDataByName.js";
const command = (builder: SlashCommandSubcommandBuilder) =>
builder
.setName("attachments")
.setDescription("Where attachments should be logged to (Premium only)")
- .addChannelOption((option) =>
- option
- .setName("channel")
- .setDescription("The channel to log attachments in")
- .addChannelTypes(ChannelType.GuildText)
- .setRequired(false)
- );
const callback = async (interaction: CommandInteraction): Promise<unknown> => {
- const m = (await interaction.reply({
+ await interaction.reply({
embeds: LoadingEmbed,
ephemeral: true,
fetchReply: true
- })) as Discord.Message;
- if (interaction.options.get("channel")?.channel) {
- let channel;
- try {
- channel = interaction.options.get("channel")?.channel;
- } catch {
- return await interaction.editReply({
- embeds: [
- new EmojiEmbed()
- .setEmoji("CHANNEL.TEXT.DELETE")
- .setTitle("Attachment Log Channel")
- .setDescription("The channel you provided is not a valid channel")
- .setStatus("Danger")
- ]
- });
- }
- channel = channel as Discord.TextChannel;
- if (channel.guild.id !== interaction.guild!.id) {
- return interaction.editReply({
- embeds: [
- new EmojiEmbed()
- .setTitle("Attachment Log Channel")
- .setDescription("You must choose a channel in this server")
- .setStatus("Danger")
- .setEmoji("CHANNEL.TEXT.DELETE")
- ]
- });
- }
- const confirmation = await new confirmationMessage(interaction)
- .setEmoji("CHANNEL.TEXT.EDIT")
- .setTitle("Attachment Log Channel")
- .setDescription(
- "This will be the channel all attachments will be sent to.\n\n" +
- `Are you sure you want to set the attachment log channel to <#${channel.id}>?`
- )
- .setColor("Warning")
- .setFailedMessage("No changes were made", "Success", "CHANNEL.TEXT.CREATE")
- .setInverted(true)
- .send(true);
- if (confirmation.cancelled) return;
- if (confirmation.success) {
- try {
- await client.database.guilds.write(interaction.guild!.id, {
- "logging.attachments.channel": channel.id
- });
- const { log, NucleusColors, entry, renderUser, renderChannel } = client.logger;
- const data = {
- meta: {
- type: "attachmentChannelUpdate",
- displayName: "Attachment Log Channel Updated",
- calculateType: "nucleusSettingsUpdated",
- color: NucleusColors.yellow,
- emoji: "CHANNEL.TEXT.EDIT",
- timestamp: new Date().getTime()
- },
- list: {
- memberId: entry(interaction.user.id, `\`${interaction.user.id}\``),
- changedBy: entry(interaction.user.id, renderUser(interaction.user)),
- channel: entry(channel.id, renderChannel(channel))
- },
- hidden: {
- guild: interaction.guild!.id
- }
- };
- log(data);
- } catch (e) {
- return interaction.editReply({
- embeds: [
- new EmojiEmbed()
- .setTitle("Attachment Log Channel")
- .setDescription("Something went wrong and the attachment log channel could not be set")
- .setStatus("Danger")
- .setEmoji("CHANNEL.TEXT.DELETE")
- ],
- components: []
- });
- }
- } else {
- return interaction.editReply({
- embeds: [
- new EmojiEmbed()
- .setTitle("Attachment Log Channel")
- .setDescription("No changes were made")
- .setStatus("Success")
- .setEmoji("CHANNEL.TEXT.CREATE")
- ],
- components: []
- });
- }
- }
- let clicks = 0;
- const data = await client.database.guilds.read(interaction.guild!.id);
- let channel = data.logging.staff.channel;
+ })
- let timedOut = false;
- while (!timedOut) {
- await interaction.editReply({
- embeds: [
- new EmojiEmbed()
- .setTitle("Attachment Log Channel")
- .setDescription(
- channel
- ? `Your attachment log channel is currently set to <#${channel}>`
- : "This server does not have an attachment log channel" +
- (await client.database.premium.hasPremium(interaction.guild!.id)
- ? ""
- : "\n\nThis server does not have premium, so this feature is disabled")
- )
- .setStatus("Success")
- .setEmoji("CHANNEL.TEXT.CREATE")
- ],
- components: [
- new ActionRowBuilder<ButtonBuilder>().addComponents([
- new ButtonBuilder()
- .setCustomId("clear")
- .setLabel(clicks ? "Click again to confirm" : "Reset channel")
- .setEmoji(getEmojiByName(clicks ? "TICKETS.ISSUE" : "CONTROL.CROSS", "id"))
- .setStyle(ButtonStyle.Danger)
- .setDisabled(!channel)
- ])
- ]
- });
- let i;
- try {
- i = await m.awaitMessageComponent({
- time: 300000,
- filter: (i) => { return i.user.id === interaction.user.id && i.channel!.id === interaction.channel!.id && i.message.id === m.id }
- });
- } catch (e) {
- timedOut = true;
- continue;
- }
- await i.deferUpdate();
- if ((i.component as unknown as ButtonInteraction).customId === "clear") {
- clicks ++;
- if (clicks === 2) {
- clicks = 0;
- await client.database.guilds.write(interaction.guild!.id, null, ["logging.announcements.channel"]);
- channel = null;
- }
- }
- }
- await interaction.editReply({
+ if(!client.database.premium.hasPremium(interaction.guild!.id)) return interaction.editReply({
embeds: [
new EmojiEmbed()
- .setTitle("Attachment Log Channel")
- .setDescription(
- channel
- ? `Your attachment log channel is currently set to <#${channel}>`
- : "This server does not have an attachment log channel"
- )
- .setStatus("Success")
- .setEmoji("CHANNEL.TEXT.CREATE")
- .setFooter({ text: "Message closed" })
- ],
- components: [
- new ActionRowBuilder<ButtonBuilder>().addComponents([
+ .setTitle("Premium Required")
+ .setDescription(`This feature is exclusive to ${getCommandMentionByName("nucleus/premium")} servers.`)
+ .setStatus("Danger")
+ .setEmoji("NUCLEUS.PREMIUM")
+ ]
+ });
+
+ let data = await client.database.guilds.read(interaction.guild!.id);
+ let channel = data.logging.staff.channel;
+
+ let closed = false;
+ do {
+ const channelMenu = new ActionRowBuilder<ChannelSelectMenuBuilder>()
+ .addComponents(
+ new ChannelSelectMenuBuilder()
+ .setCustomId("channel")
+ .setPlaceholder("Select a channel")
+ );
+ const buttons = new ActionRowBuilder<ButtonBuilder>()
+ .addComponents(
new ButtonBuilder()
.setCustomId("clear")
.setLabel("Clear")
- .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
- .setStyle(ButtonStyle.Secondary)
- .setDisabled(true)
- ])
- ]
- });
+ .setStyle(ButtonStyle.Danger)
+ .setEmoji(getEmojiByName("CONTROL.CROSS", "id") as Discord.APIMessageComponentEmoji)
+ .setDisabled(!channel),
+ new ButtonBuilder()
+ .setCustomId("save")
+ .setLabel("Save")
+ .setStyle(ButtonStyle.Success)
+ .setEmoji(getEmojiByName("ICONS.SAVE", "id") as Discord.APIMessageComponentEmoji)
+ .setDisabled(channel === data.logging.staff.channel)
+ );
+
+ const embed = new EmojiEmbed()
+ .setTitle("Attachments")
+ .setDescription(
+ `The channel to send all attachments from the server, allowing you to check them if they are deleted` +
+ `**Channel:** ${channel ? `<#${channel}>` : "*None*"}\n`
+ )
+ .setStatus("Success")
+ .setEmoji("CHANNEL.TEXT.CREATE")
+
+ await interaction.editReply({
+ embeds: [embed],
+ components: [channelMenu, buttons]
+ });
+
+ let i: Discord.ButtonInteraction | Discord.SelectMenuInteraction;
+ try {
+ i = (await interaction.channel!.awaitMessageComponent({
+ filter: (i) => i.user.id === interaction.user.id,
+ time: 300000
+ })) as Discord.ButtonInteraction | Discord.SelectMenuInteraction;
+ } catch (e) {
+ closed = true;
+ break;
+ }
+ await i.deferUpdate();
+ if(i.isButton()) {
+ switch (i.customId) {
+ case "clear": {
+ channel = null;
+ break;
+ }
+ case "save": {
+ await client.database.guilds.write(interaction.guild!.id, {
+ "logging.attachments.channel": channel
+ });
+ data = await client.database.guilds.read(interaction.guild!.id);
+ break;
+ }
+ }
+ } else {
+ channel = i.values[0]!;
+ }
+
+ } while (!closed);
+ await interaction.deleteReply()
};
const check = (interaction: CommandInteraction, _partial: boolean = false) => {
diff --git a/src/commands/settings/logs/events.ts b/src/commands/settings/logs/events.ts
index f2ec13a..a1f24fa 100644
--- a/src/commands/settings/logs/events.ts
+++ b/src/commands/settings/logs/events.ts
@@ -1,9 +1,11 @@
import { LoadingEmbed } from "../../../utils/defaults.js";
-import Discord, { CommandInteraction, Message, ActionRowBuilder, ButtonBuilder, ButtonStyle, StringSelectMenuBuilder, EmbedBuilder } from "discord.js";
-import { SlashCommandSubcommandBuilder, StringSelectMenuOptionBuilder } from "discord.js";
-import EmojiEmbed from "../../../utils/generateEmojiEmbed.js";
+import Discord, { CommandInteraction, ActionRowBuilder, ChannelSelectMenuBuilder, ChannelType, ButtonBuilder, ButtonStyle, StringSelectMenuBuilder, StringSelectMenuOptionBuilder, ButtonInteraction, StringSelectMenuInteraction, ChannelSelectMenuInteraction, APIMessageComponentEmoji } from "discord.js";
+import type { SlashCommandSubcommandBuilder } from "discord.js";
import client from "../../../utils/client.js";
+import compare from "lodash";
import { toHexArray, toHexInteger } from "../../../utils/calculate.js";
+import EmojiEmbed from "../../../utils/generateEmojiEmbed.js";
+import getEmojiByName from "../../../utils/getEmojiByName.js";
const logs: Record<string, string> = {
channelUpdate: "Channels created, deleted or modified",
@@ -24,85 +26,135 @@
webhookUpdate: "Webhooks created or deleted",
guildMemberVerify: "Member runs verify",
autoModeratorDeleted: "Messages auto deleted by Nucleus",
- nucleusSettingsUpdated: "Nucleus' settings updated by a moderator",
- ticketUpdate: "Tickets created or deleted"
+ ticketUpdate: "Tickets created or deleted",
+ //nucleusSettingsUpdated: "Nucleus' settings updated by a moderator" // TODO
};
const command = (builder: SlashCommandSubcommandBuilder) =>
- builder.setName("events").setDescription("Sets what events should be logged");
+ builder
+ .setName("events")
+ .setDescription("The general log channel for the server, and setting what events to show")
const callback = async (interaction: CommandInteraction): Promise<void> => {
- await interaction.reply({
+ const m = (await interaction.reply({
embeds: LoadingEmbed,
- fetchReply: true,
- ephemeral: true
- });
- let m: Message;
- let timedOut = false;
+ ephemeral: true,
+ fetchReply: true
+ })) as Discord.Message;
+
+ let config = await client.database.guilds.read(interaction.guild!.id);
+ let data = Object.assign({}, config.logging.logs);
+ let closed = false;
+ let show = false;
do {
- const config = await client.database.guilds.read(interaction.guild!.id);
- const converted = toHexArray(config.logging.logs.toLog);
- const selectPane = new StringSelectMenuBuilder()
- .setPlaceholder("Set events to log")
- .setMaxValues(Object.keys(logs).length)
- .setCustomId("logs")
- .setMinValues(0)
- Object.keys(logs).map((e, i) => {
- selectPane.addOptions(new StringSelectMenuOptionBuilder()
- .setLabel(logs[e]!)
- .setValue(i.toString())
- .setDefault(converted.includes(e))
+ const channelMenu = new ActionRowBuilder<ChannelSelectMenuBuilder>()
+ .addComponents(
+ new ChannelSelectMenuBuilder()
+ .setCustomId("channel")
+ .setPlaceholder("Select a channel")
+ .setChannelTypes(ChannelType.GuildText)
+ )
+ const buttons = new ActionRowBuilder<ButtonBuilder>()
+ .addComponents(
+ new ButtonBuilder()
+ .setCustomId("switch")
+ .setLabel(data.enabled ? "Enabled" : "Disabled")
+ .setStyle(data.enabled ? ButtonStyle.Success : ButtonStyle.Danger)
+ .setEmoji(getEmojiByName((data.enabled ? "CONTROL.TICK" : "CONTROL.CROSS"), "id") as APIMessageComponentEmoji),
+ new ButtonBuilder()
+ .setCustomId("remove")
+ .setLabel("Remove")
+ .setStyle(ButtonStyle.Danger)
+ .setDisabled(!data.channel),
+ new ButtonBuilder()
+ .setCustomId("show")
+ .setLabel("Manage Events")
+ .setStyle(ButtonStyle.Primary),
+ new ButtonBuilder()
+ .setCustomId("save")
+ .setLabel("Save")
+ .setStyle(ButtonStyle.Success)
+ .setDisabled(compare.isEqual(data, config.logging.logs))
+ )
+
+ const converted = toHexArray(data.toLog);
+ const toLogMenu = new ActionRowBuilder<StringSelectMenuBuilder>()
+ .addComponents(
+ new StringSelectMenuBuilder()
+ .setPlaceholder("Set events to log")
+ .setMaxValues(Object.keys(logs).length)
+ .setCustomId("logs")
+ .setMinValues(0)
+ )
+ Object.keys(logs).map((e) => {
+ toLogMenu.components[0]!.addOptions(
+ new StringSelectMenuOptionBuilder()
+ .setLabel(logs[e]!)
+ .setValue(e)
+ .setDefault(converted.includes(e))
)
});
- m = (await interaction.editReply({
- embeds: [
- new EmojiEmbed()
- .setTitle("Logging Events")
- .setDescription(
- "Below are the events being logged in the server. You can toggle them on and off in the dropdown"
- )
- .setStatus("Success")
- .setEmoji("CHANNEL.TEXT.CREATE")
- ],
- components: [
- new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(selectPane),
- new ActionRowBuilder<ButtonBuilder>().addComponents([
- new ButtonBuilder().setLabel("Select all").setStyle(ButtonStyle.Primary).setCustomId("all"),
- new ButtonBuilder().setLabel("Select none").setStyle(ButtonStyle.Danger).setCustomId("none")
- ])
- ]
- })) as Message;
- let i;
+
+ const embed = new EmojiEmbed()
+ .setTitle("General Log Channel")
+ .setStatus("Success")
+ .setEmoji("CHANNEL.TEXT.CREATE")
+ .setDescription(
+ `This is the channel that all events you set to be logged will be stored\n` +
+ `**Channel:** ${data.channel ? `<#${data.channel}>` : "None"}\n`
+ )
+
+ let components: ActionRowBuilder<ButtonBuilder | ChannelSelectMenuBuilder | StringSelectMenuBuilder>[] = [channelMenu, buttons];
+ if(show) components.push(toLogMenu);
+
+ await interaction.editReply({
+ embeds: [embed],
+ components: components
+ });
+
+ let i: ButtonInteraction | StringSelectMenuInteraction | ChannelSelectMenuInteraction;
try {
i = await m.awaitMessageComponent({
- time: 300000,
- filter: (i) => { return i.user.id === interaction.user.id && i.channel!.id === interaction.channel!.id && i.message.id === m.id }
- });
+ filter: (i) => i.user.id === interaction.user.id,
+ time: 300000
+ }) as ButtonInteraction | StringSelectMenuInteraction | ChannelSelectMenuInteraction;
} catch (e) {
- timedOut = true;
- continue;
+ closed = true;
+ break;
}
- await i.deferUpdate();
- if (i.isStringSelectMenu() && i.customId === "logs") {
- const selected = i.values;
- const newLogs = toHexInteger(selected.map((e: string) => Object.keys(logs)[parseInt(e)]!));
- await client.database.guilds.write(interaction.guild!.id, {
- "logging.logs.toLog": newLogs
- });
- } else if (i.customId === "all") {
- const newLogs = toHexInteger(Object.keys(logs).map((e) => e));
- await client.database.guilds.write(interaction.guild!.id, {
- "logging.logs.toLog": newLogs
- });
- } else if (i.customId === "none") {
- await client.database.guilds.write(interaction.guild!.id, {
- "logging.logs.toLog": 0
- });
- }
- } while (!timedOut);
- await interaction.editReply({ embeds: [new EmbedBuilder(m.embeds[0]!.data).setFooter({ text: "Message timed out" })] });
- return;
+ await i.deferUpdate();
+
+ if(i.isButton()) {
+ switch(i.customId) {
+ case "show": {
+ show = !show;
+ break;
+ }
+ case "switch": {
+ data.enabled = !data.enabled;
+ break;
+ }
+ case "save": {
+ await client.database.guilds.write(interaction.guild!.id, {"logging.logs": data});
+ config = await client.database.guilds.read(interaction.guild!.id);
+ data = Object.assign({}, config.logging.logs);
+ break;
+ }
+ case "remove": {
+ data.channel = null;
+ break;
+ }
+ }
+ } else if(i.isStringSelectMenu()) {
+ let hex = toHexInteger(i.values);
+ data.toLog = hex;
+ } else if(i.isChannelSelectMenu()) {
+ data.channel = i.values[0]!;
+ }
+
+ } while (!closed);
+ await interaction.deleteReply()
};
const check = (interaction: CommandInteraction, _partial: boolean = false) => {
diff --git a/src/commands/settings/logs/general.ts b/src/commands/settings/logs/general.ts
deleted file mode 100644
index 9861d26..0000000
--- a/src/commands/settings/logs/general.ts
+++ /dev/null
@@ -1,197 +0,0 @@
-import { LoadingEmbed } from "../../../utils/defaults.js";
-import { ChannelType } from "discord-api-types/v9";
-import Discord, { CommandInteraction, ActionRowBuilder, ButtonBuilder, ButtonStyle, ButtonInteraction, ButtonComponent } from "discord.js";
-import EmojiEmbed from "../../../utils/generateEmojiEmbed.js";
-import confirmationMessage from "../../../utils/confirmationMessage.js";
-import getEmojiByName from "../../../utils/getEmojiByName.js";
-import type { SlashCommandSubcommandBuilder } from "discord.js";
-import client from "../../../utils/client.js";
-
-const command = (builder: SlashCommandSubcommandBuilder) =>
- builder
- .setName("general")
- .setDescription("Sets or shows the log channel")
- .addChannelOption((option) =>
- option
- .setName("channel")
- .setDescription("The channel to set the log channel to")
- .addChannelTypes(ChannelType.GuildText)
- );
-
-const callback = async (interaction: CommandInteraction): Promise<unknown> => {
- const m = (await interaction.reply({
- embeds: LoadingEmbed,
- ephemeral: true,
- fetchReply: true
- })) as Discord.Message;
- if (interaction.options.get("channel")?.channel) {
- let channel;
- try {
- channel = interaction.options.get("channel")?.channel;
- } catch {
- return await interaction.editReply({
- embeds: [
- new EmojiEmbed()
- .setEmoji("CHANNEL.TEXT.DELETE")
- .setTitle("Log Channel")
- .setDescription("The channel you provided is not a valid channel")
- .setStatus("Danger")
- ]
- });
- }
- channel = channel as Discord.TextChannel;
- if (channel.guild.id !== interaction.guild!.id) {
- return interaction.editReply({
- embeds: [
- new EmojiEmbed()
- .setTitle("Log Channel")
- .setDescription("You must choose a channel in this server")
- .setStatus("Danger")
- .setEmoji("CHANNEL.TEXT.DELETE")
- ]
- });
- }
- const confirmation = await new confirmationMessage(interaction)
- .setEmoji("CHANNEL.TEXT.EDIT")
- .setTitle("Log Channel")
- .setDescription(`Are you sure you want to set the log channel to <#${channel.id}>?`)
- .setColor("Warning")
- .setFailedMessage("No changes were made", "Success", "CHANNEL.TEXT.CREATE")
- .setInverted(true)
- .send(true);
- if (confirmation.cancelled) return;
- if (confirmation.success) {
- try {
- await client.database.guilds.write(interaction.guild!.id, {
- "logging.logs.channel": channel.id
- });
- const { log, NucleusColors, entry, renderUser, renderChannel } = client.logger;
- const data = {
- meta: {
- type: "logChannelUpdate",
- displayName: "Log Channel Changed",
- calculateType: "nucleusSettingsUpdated",
- color: NucleusColors.yellow,
- emoji: "CHANNEL.TEXT.EDIT",
- timestamp: new Date().getTime()
- },
- list: {
- memberId: entry(interaction.user.id, `\`${interaction.user.id}\``),
- changedBy: entry(interaction.user.id, renderUser(interaction.user)),
- channel: entry(channel.id, renderChannel(channel))
- },
- hidden: {
- guild: channel.guild.id
- }
- };
- log(data);
- } catch (e) {
- console.log(e);
- return interaction.editReply({
- embeds: [
- new EmojiEmbed()
- .setTitle("Log Channel")
- .setDescription("Something went wrong and the log channel could not be set")
- .setStatus("Danger")
- .setEmoji("CHANNEL.TEXT.DELETE")
- ],
- components: []
- });
- }
- } else {
- return interaction.editReply({
- embeds: [
- new EmojiEmbed()
- .setTitle("Log Channel")
- .setDescription("No changes were made")
- .setStatus("Success")
- .setEmoji("CHANNEL.TEXT.CREATE")
- ],
- components: []
- });
- }
- }
- let clicks = 0;
- const data = await client.database.guilds.read(interaction.guild!.id);
- let channel = data.logging.logs.channel;
- let timedOut = false;
- while (!timedOut) {
- await interaction.editReply({
- embeds: [
- new EmojiEmbed()
- .setTitle("Log channel")
- .setDescription(
- channel
- ? `Your log channel is currently set to <#${channel}>`
- : "This server does not have a log channel"
- )
- .setStatus("Success")
- .setEmoji("CHANNEL.TEXT.CREATE")
- ],
- components: [
- new ActionRowBuilder<ButtonBuilder>().addComponents([
- new ButtonBuilder()
- .setCustomId("clear")
- .setLabel(clicks ? "Click again to confirm" : "Reset channel")
- .setEmoji(getEmojiByName(clicks ? "TICKETS.ISSUE" : "CONTROL.CROSS", "id"))
- .setStyle(ButtonStyle.Danger)
- .setDisabled(!channel)
- ])
- ]
- });
- let i: ButtonInteraction;
- try {
- i = await m.awaitMessageComponent({
- time: 300000,
- filter: (i) => { return i.user.id === interaction.user.id && i.channel!.id === interaction.channel!.id && i.message.id === m.id }
- }) as ButtonInteraction;
- } catch (e) {
- timedOut = true;
- }
- i = i!
- await i.deferUpdate();
- if ((i.component as ButtonComponent).customId === "clear") {
- clicks ++;
- if (clicks === 2) {
- clicks = 0;
- await client.database.guilds.write(interaction.guild!.id, null, ["logging.logs.channel"]);
- channel = null;
- }
- }
- }
- await interaction.editReply({
- embeds: [
- new EmojiEmbed()
- .setTitle("Log channel")
- .setDescription(
- channel
- ? `Your log channel is currently set to <#${channel}>`
- : "This server does not have a log channel"
- )
- .setStatus("Success")
- .setEmoji("CHANNEL.TEXT.CREATE")
- .setFooter({ text: "Message closed" })
- ],
- components: [
- new ActionRowBuilder<ButtonBuilder>().addComponents([
- new ButtonBuilder()
- .setCustomId("clear")
- .setLabel("Clear")
- .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
- .setStyle(ButtonStyle.Secondary)
- .setDisabled(true)
- ])
- ]
- });
-};
-
-const check = (interaction: CommandInteraction, _partial: boolean = false) => {
- const member = interaction.member as Discord.GuildMember;
- if (!member.permissions.has("ManageGuild"))
- return "You must have the *Manage Server* permission to use this command";
- return true;
-};
-
-export { command };
-export { callback };
-export { check };
diff --git a/src/commands/settings/logs/warnings.ts b/src/commands/settings/logs/warnings.ts
index 3855d34..6e5482c 100644
--- a/src/commands/settings/logs/warnings.ts
+++ b/src/commands/settings/logs/warnings.ts
@@ -1,8 +1,6 @@
import { LoadingEmbed } from "../../../utils/defaults.js";
-import { ChannelType } from "discord-api-types/v9";
-import Discord, { CommandInteraction, ActionRowBuilder, ButtonBuilder, ButtonStyle, ButtonComponent } from "discord.js";
+import Discord, { CommandInteraction, ActionRowBuilder, ButtonBuilder, ButtonStyle, ChannelSelectMenuBuilder } from "discord.js";
import EmojiEmbed from "../../../utils/generateEmojiEmbed.js";
-import confirmationMessage from "../../../utils/confirmationMessage.js";
import getEmojiByName from "../../../utils/getEmojiByName.js";
import type { SlashCommandSubcommandBuilder } from "discord.js";
import client from "../../../utils/client.js";
@@ -11,182 +9,86 @@
builder
.setName("warnings")
.setDescription("Settings for the staff notifications channel")
- .addChannelOption((option) =>
- option
- .setName("channel")
- .setDescription("The channel to set the staff notifications channel to")
- .addChannelTypes(ChannelType.GuildText)
- .setRequired(false)
- );
const callback = async (interaction: CommandInteraction): Promise<unknown> => {
if (!interaction.guild) return;
- const m = (await interaction.reply({
+ await interaction.reply({
embeds: LoadingEmbed,
ephemeral: true,
fetchReply: true
- })) as Discord.Message;
- if (interaction.options.get("channel")?.channel) {
- let channel;
- try {
- channel = interaction.options.get("channel")?.channel;
- } catch {
- return await interaction.editReply({
- embeds: [
- new EmojiEmbed()
- .setEmoji("CHANNEL.TEXT.DELETE")
- .setTitle("Staff Notifications Channel")
- .setDescription("The channel you provided is not a valid channel")
- .setStatus("Danger")
- ]
- });
- }
- channel = channel as Discord.TextChannel;
- if (channel.guild.id !== interaction.guild.id) {
- return interaction.editReply({
- embeds: [
- new EmojiEmbed()
- .setTitle("Staff Notifications Channel")
- .setDescription("You must choose a channel in this server")
- .setStatus("Danger")
- .setEmoji("CHANNEL.TEXT.DELETE")
- ]
- });
- }
- const confirmation = await new confirmationMessage(interaction)
- .setEmoji("CHANNEL.TEXT.EDIT")
- .setTitle("Staff Notifications Channel")
- .setDescription(
- "This will be the channel all notifications, updates, user reports etc. will be sent to.\n\n" +
- `Are you sure you want to set the staff notifications channel to <#${channel.id}>?`
- )
- .setColor("Warning")
- .setFailedMessage("No changes were made", "Success", "CHANNEL.TEXT.CREATE")
- .setInverted(true)
- .send(true);
- if (confirmation.cancelled) return;
- if (confirmation.success) {
- try {
- await client.database.guilds.write(interaction.guild.id, {
- "logging.staff.channel": channel.id
- });
- const { log, NucleusColors, entry, renderUser, renderChannel } = client.logger;
- const data = {
- meta: {
- type: "staffChannelUpdate",
- displayName: "Staff Notifications Channel Updated",
- calculateType: "nucleusSettingsUpdated",
- color: NucleusColors.yellow,
- emoji: "CHANNEL.TEXT.EDIT",
- timestamp: new Date().getTime()
- },
- list: {
- memberId: entry(interaction.user.id, `\`${interaction.user.id}\``),
- changedBy: entry(interaction.user.id, renderUser(interaction.user)),
- channel: entry(channel.id, renderChannel(channel))
- },
- hidden: {
- guild: interaction.guild.id
- }
- };
- log(data);
- } catch (e) {
- return interaction.editReply({
- embeds: [
- new EmojiEmbed()
- .setTitle("Staff Notifications Channel")
- .setDescription("Something went wrong and the staff notifications channel could not be set")
- .setStatus("Danger")
- .setEmoji("CHANNEL.TEXT.DELETE")
- ],
- components: []
- });
- }
- } else {
- return interaction.editReply({
- embeds: [
- new EmojiEmbed()
- .setTitle("Staff Notifications Channel")
- .setDescription("No changes were made")
- .setStatus("Success")
- .setEmoji("CHANNEL.TEXT.CREATE")
- ],
- components: []
- });
- }
- }
- let clicks = 0;
- const data = await client.database.guilds.read(interaction.guild.id);
+ })
+
+ let data = await client.database.guilds.read(interaction.guild.id);
let channel = data.logging.staff.channel;
- let timedOut = false;
- while (!timedOut) {
- await interaction.editReply({
- embeds: [
- new EmojiEmbed()
- .setTitle("Staff Notifications channel")
- .setDescription(
- channel
- ? `Your staff notifications channel is currently set to <#${channel}>`
- : "This server does not have a staff notifications channel"
- )
- .setStatus("Success")
- .setEmoji("CHANNEL.TEXT.CREATE")
- ],
- components: [
- new ActionRowBuilder<ButtonBuilder>().addComponents([
- new ButtonBuilder()
- .setCustomId("clear")
- .setLabel(clicks ? "Click again to confirm" : "Reset channel")
- .setEmoji(getEmojiByName(clicks ? "TICKETS.ISSUE" : "CONTROL.CROSS", "id"))
- .setStyle(ButtonStyle.Danger)
- .setDisabled(!channel)
- ])
- ]
- });
- let i;
- try {
- i = await m.awaitMessageComponent({
- time: 300000,
- filter: (i) => { return i.user.id === interaction.user.id && i.channel!.id === interaction.channel!.id && i.message.id === m.id }
- });
- } catch (e) {
- timedOut = true;
- continue;
- }
- await i.deferUpdate();
- if ((i.component as ButtonComponent).customId === "clear") {
- clicks ++;
- if (clicks === 2) {
- clicks = 0;
- await client.database.guilds.write(interaction.guild.id, null, ["logging.staff.channel"]);
- channel = null;
- }
- }
- }
- await interaction.editReply({
- embeds: [
- new EmojiEmbed()
- .setTitle("Staff Notifications channel")
- .setDescription(
- channel
- ? `Your staff notifications channel is currently set to <#${channel}>`
- : "This server does not have a staff notifications channel"
- )
- .setStatus("Success")
- .setEmoji("CHANNEL.TEXT.CREATE")
- .setFooter({ text: "Message closed" })
- ],
- components: [
- new ActionRowBuilder<ButtonBuilder>().addComponents([
+ let closed = false;
+ do {
+ const channelMenu = new ActionRowBuilder<ChannelSelectMenuBuilder>()
+ .addComponents(
+ new ChannelSelectMenuBuilder()
+ .setCustomId("channel")
+ .setPlaceholder("Select a channel")
+ );
+ const buttons = new ActionRowBuilder<ButtonBuilder>()
+ .addComponents(
new ButtonBuilder()
.setCustomId("clear")
.setLabel("Clear")
- .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
- .setStyle(ButtonStyle.Secondary)
- .setDisabled(true)
- ])
- ]
- });
+ .setStyle(ButtonStyle.Danger)
+ .setEmoji(getEmojiByName("CONTROL.CROSS", "id") as Discord.APIMessageComponentEmoji)
+ .setDisabled(!channel),
+ new ButtonBuilder()
+ .setCustomId("save")
+ .setLabel("Save")
+ .setStyle(ButtonStyle.Success)
+ .setEmoji(getEmojiByName("ICONS.SAVE", "id") as Discord.APIMessageComponentEmoji)
+ .setDisabled(channel === data.logging.staff.channel)
+ );
+
+ const embed = new EmojiEmbed()
+ .setTitle("Staff Notifications Channel")
+ .setStatus("Success")
+ .setEmoji("CHANNEL.TEXT.CREATE")
+ .setDescription(
+ `Logs which require an action from a moderator or administrator will be sent to this channel.\n` +
+ `**Channel:** ${channel ? `<#${channel}>` : "*None*"}\n`
+ )
+
+ await interaction.editReply({
+ embeds: [embed],
+ components: [channelMenu, buttons]
+ });
+
+ let i: Discord.ButtonInteraction | Discord.SelectMenuInteraction;
+ try {
+ i = (await interaction.channel!.awaitMessageComponent({
+ filter: (i) => i.user.id === interaction.user.id,
+ time: 300000
+ })) as Discord.ButtonInteraction | Discord.SelectMenuInteraction;
+ } catch (e) {
+ closed = true;
+ break;
+ }
+ await i.deferUpdate();
+ if(i.isButton()) {
+ switch (i.customId) {
+ case "clear": {
+ channel = null;
+ break;
+ }
+ case "save": {
+ await client.database.guilds.write(interaction.guild!.id, {
+ "logging.warnings.channel": channel
+ });
+ data = await client.database.guilds.read(interaction.guild!.id);
+ break;
+ }
+ }
+ } else {
+ channel = i.values[0]!;
+ }
+ } while (!closed);
+
+ await interaction.deleteReply()
};
const check = (interaction: CommandInteraction, _partial: boolean = false) => {