Fixed welcome
diff --git a/src/commands/createTestButton.ts b/src/commands/createTestButton.ts
deleted file mode 100644
index c04e13d..0000000
--- a/src/commands/createTestButton.ts
+++ /dev/null
@@ -1,35 +0,0 @@
-import { CommandInteraction, MessageActionRow, MessageButton } from "discord.js";
-import { SlashCommandBuilder } from "@discordjs/builders";
-import { WrappedCheck } from "jshaiku";
-
-const command = new SlashCommandBuilder()
- .setName("createtestbutton")
- .setDescription("creates a test button") // TODO: remove for release
-
-const callback = (interaction: CommandInteraction) => {
- interaction.reply({components: [new MessageActionRow().addComponents([
- new MessageButton()
- .setCustomId("createticket")
- .setLabel("Create Ticket")
- .setStyle("PRIMARY")
- .setDisabled(false),
- new MessageButton()
- .setCustomId("verifybutton")
- .setLabel("Verify")
- .setStyle("PRIMARY")
- .setDisabled(false),
- new MessageButton()
- .setCustomId("rolemenu")
- .setLabel("Get roles")
- .setStyle("PRIMARY")
- .setDisabled(false)
- ])]});
-}
-
-const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
- return true;
-}
-
-export { command };
-export { callback };
-export { check };
\ No newline at end of file
diff --git a/src/commands/help.ts b/src/commands/help.ts
index 568a90c..c3b015c 100644
--- a/src/commands/help.ts
+++ b/src/commands/help.ts
@@ -6,7 +6,7 @@
.setName("help")
.setDescription("Shows help for commands")
-const callback = (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
interaction.reply("hel p"); // TODO: FINISH THIS FOR RELEASE
}
diff --git a/src/commands/nucleus/invite.ts b/src/commands/nucleus/invite.ts
index 7f7d4b8..96e1449 100644
--- a/src/commands/nucleus/invite.ts
+++ b/src/commands/nucleus/invite.ts
@@ -9,7 +9,7 @@
.setName("invite")
.setDescription("Invites Nucleus to your server")
-const callback = (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
interaction.reply({embeds: [new EmojiEmbed()
.setTitle("Invite")
.setDescription("You can invite Nucleus to your server by clicking the button below")
diff --git a/src/commands/nucleus/premium.ts b/src/commands/nucleus/premium.ts
index 740ab7b..9d273b9 100644
--- a/src/commands/nucleus/premium.ts
+++ b/src/commands/nucleus/premium.ts
@@ -8,7 +8,7 @@
.setName("premium")
.setDescription("Information about Nucleus Premium")
-const callback = (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
interaction.reply({embeds: [new EmojiEmbed()
.setTitle("Premium")
.setDescription(
diff --git a/src/commands/nucleus/stats.ts b/src/commands/nucleus/stats.ts
index cb10e7a..beea94b 100644
--- a/src/commands/nucleus/stats.ts
+++ b/src/commands/nucleus/stats.ts
@@ -9,7 +9,7 @@
.setName("stats")
.setDescription("Gets the bot's stats")
-const callback = (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
interaction.reply({
embeds: [new EmojiEmbed()
.setTitle("Stats")
diff --git a/src/commands/settings/filters.ts b/src/commands/settings/filters.ts
new file mode 100644
index 0000000..183b91c
--- /dev/null
+++ b/src/commands/settings/filters.ts
@@ -0,0 +1,29 @@
+import { LoadingEmbed } from './../../utils/defaultEmbeds.js';
+import Discord, { CommandInteraction, MessageActionRow, MessageButton, MessageSelectMenu } from "discord.js";
+import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
+import { WrappedCheck } from "jshaiku";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import client from '../../utils/client.js';
+import confirmationMessage from '../../utils/confirmationMessage.js';
+import generateKeyValueList from '../../utils/generateKeyValueList.js';
+import { ChannelType } from 'discord-api-types';
+import getEmojiByName from '../../utils/getEmojiByName.js';
+
+const command = (builder: SlashCommandSubcommandBuilder) =>
+ builder
+ .setName("filter")
+ .setDescription("Setting for message filters")
+
+const callback = async (interaction: CommandInteraction): Promise<any> => {
+
+}
+
+const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
+ let member = (interaction.member as Discord.GuildMember)
+ if (!member.permissions.has("MANAGE_GUILD")) throw "You must have the *Manage Server* permission to use this command"
+ return true;
+}
+
+export { command };
+export { callback };
+export { check };
\ No newline at end of file
diff --git a/src/commands/settings/logs/_meta.ts b/src/commands/settings/logs/_meta.ts
index 15a6fd4..f46987f 100644
--- a/src/commands/settings/logs/_meta.ts
+++ b/src/commands/settings/logs/_meta.ts
@@ -1,4 +1,4 @@
-const name = "log";
+const name = "logs";
const description = "Settings for logging";
export { name, description };
\ No newline at end of file
diff --git a/src/commands/settings/logs/events.ts b/src/commands/settings/logs/events.ts
index dac200c..ef303cb 100644
--- a/src/commands/settings/logs/events.ts
+++ b/src/commands/settings/logs/events.ts
@@ -1,17 +1,106 @@
-import { CommandInteraction } from "discord.js";
+import { LoadingEmbed } from './../../../utils/defaultEmbeds.js';
+import Discord, { CommandInteraction, MessageActionRow, MessageButton, MessageSelectMenu } from "discord.js";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { WrappedCheck } from "jshaiku";
+import EmojiEmbed from "../../../utils/generateEmojiEmbed.js";
+import client from '../../../utils/client.js';
+import { toHexArray, toHexInteger } from "../../../utils/calculate.js";
+
+
+const logs = {
+ "channelUpdate": "Channels created, deleted or modified",
+ "emojiUpdate": "Server emojis modified",
+ "stickerUpdate": "Server stickers modified",
+ "guildUpdate": "Server settings updated",
+ "guildMemberUpdate": "Member updated (i.e. nickname)",
+ "guildMemberPunish": "Members punished (i.e. muted, banned, kicked)",
+ "guildRoleUpdate": "Role settings changed",
+ "guildInviteUpdate": "Server invite created or deleted",
+ "messageUpdate": "Message edited",
+ "messageDelete": "Message deleted",
+ "messageDeleteBulk": "Messages purged",
+ "messageReactionUpdate": "Message reactions cleared",
+ "messageMassPing": "Message pings multiple members at once",
+ "messageAnnounce": "Message published in announcement channel",
+ "threadUpdate": "Thread created or deleted",
+ "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",
+}
const command = (builder: SlashCommandSubcommandBuilder) =>
builder
.setName("events")
.setDescription("Sets what events should be logged")
-const callback = (interaction: CommandInteraction) => {
- interaction.reply("This command is not yet finished [settings/log/events]");
+const callback = async (interaction: CommandInteraction): Promise<any> => {
+ await interaction.reply({embeds: LoadingEmbed, fetchReply: true, ephemeral: true});
+ let m;
+ while (true) {
+ let config = await client.database.guilds.read(interaction.guild.id)
+ let converted = toHexArray(config.logging.logs.toLog)
+ 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 MessageActionRow().addComponents([new MessageSelectMenu()
+ .setPlaceholder("Set events to log")
+ .setMaxValues(Object.keys(logs).length)
+ .setCustomId("logs")
+ .setMinValues(0)
+ .setOptions(Object.keys(logs).map((e, i) => ({
+ label: logs[e],
+ value: i.toString(),
+ default: converted.includes(e)
+ })))
+ ]),
+ new MessageActionRow().addComponents([
+ new MessageButton()
+ .setLabel("Select all")
+ .setStyle("PRIMARY")
+ .setCustomId("all"),
+ new MessageButton()
+ .setLabel("Select none")
+ .setStyle("DANGER")
+ .setCustomId("none")
+ ])
+ ]})
+ let i;
+ try {
+ i = await m.awaitMessageComponent({ time: 300000 });
+ } catch (e) {
+ break
+ }
+ i.deferUpdate()
+ if (i.customId === "logs") {
+ let selected = i.values;
+ let newLogs = toHexInteger(selected.map(e => Object.keys(logs)[parseInt(e)]))
+ await client.database.guilds.write(interaction.guild.id, {"logging.logs.toLog": newLogs})
+ } else if (i.customId === "all") {
+ let 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})
+ } else {
+ break
+ }
+ }
+ 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")
+ .setFooter({text: "Message timed out"})
+ .setStatus("Success")
+ .setEmoji("CHANNEL.TEXT.CREATE")
+ ]})
}
const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
+ let member = (interaction.member as Discord.GuildMember)
+ if (!member.permissions.has("MANAGE_GUILD")) throw "You must have the *Manage Server* permission to use this command"
return true;
}
diff --git a/src/commands/settings/stats.ts b/src/commands/settings/stats.ts
index d972674..be15869 100644
--- a/src/commands/settings/stats.ts
+++ b/src/commands/settings/stats.ts
@@ -144,12 +144,7 @@
await client.database.guilds.write(interaction.guild.id, null, toRemove.map(k => `stats.${k}`));
}
}
- await interaction.editReply({embeds: [new EmojiEmbed()
- .setTitle("Stats Channel")
- .setDescription("The following channels update when someone joins or leaves the server. You can select a channel to remove it from the list.")
- .setStatus("Danger")
- .setEmoji("CHANNEL.TEXT.DELETE")
- ], components: []})
+ await interaction.editReply({embeds: [m.embeds[0].setFooter({text: "Message closed"})], components: []});
}
const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
diff --git a/src/commands/settings/tickets.ts b/src/commands/settings/tickets.ts
index f199ac3..44f974e 100644
--- a/src/commands/settings/tickets.ts
+++ b/src/commands/settings/tickets.ts
@@ -192,6 +192,11 @@
.setEmoji(getEmojiByName("TICKETS.OTHER", "id"))
.setStyle("SECONDARY")
.setCustomId("manageTypes"),
+ new MessageButton()
+ .setLabel("Add create ticket button")
+ .setEmoji(getEmojiByName("TICKETS.SUGGESTION", "id"))
+ .setStyle("PRIMARY")
+ .setCustomId("send"),
])]
});
let i;
@@ -217,6 +222,122 @@
await client.database.guilds.write(interaction.guild.id, null, ["tickets.supportRole"])
data.supportRole = undefined;
} else lastClicked = "sup";
+ } else if (i.component.customId === "send") {
+ const ticketMessages = [
+ {label: "Create ticket", description: "Click the button below to create a ticket"},
+ {label: "Issues, questions or feedback?", description: "Click below to open a ticket and get help from our staff team"},
+ {label: "Contact Us", description: "Click the button below to speak to us privately"},
+ ]
+ while (true) {
+ let enabled = data.enabled && data.category !== null;
+ await interaction.editReply({embeds: [new EmojiEmbed()
+ .setTitle("Ticket Button")
+ .setDescription("Select a message template to send in this channel")
+ .setFooter({text: enabled ? "" : "Tickets are not set up correctly so the button may not work for users. Check the main menu to find which options must be set."})
+ .setStatus(enabled ? "Success" : "Warning")
+ .setEmoji("GUILD.ROLES.CREATE")
+ ], components: [
+ new MessageActionRow().addComponents([
+ new MessageSelectMenu().setOptions(ticketMessages.map((t: {label: string, description: string, value?: string}, index) => {
+ t.value = index.toString(); return t as {value: string, label: string, description: string}
+ })).setCustomId("template").setMaxValues(1).setMinValues(1).setPlaceholder("Select a message template"),
+ ]),
+ new MessageActionRow().addComponents([
+ new MessageButton()
+ .setCustomId("back")
+ .setLabel("Back")
+ .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
+ .setStyle("DANGER"),
+ new MessageButton()
+ .setCustomId("blank")
+ .setLabel("Empty")
+ .setStyle("SECONDARY"),
+ new MessageButton()
+ .setCustomId("custom")
+ .setLabel("Custom")
+ .setEmoji(getEmojiByName("TICKETS.OTHER", "id"))
+ .setStyle("PRIMARY")
+ ])
+ ]});
+ let i;
+ try {
+ i = await m.awaitMessageComponent({time: 300000});
+ } catch(e) { break }
+ if (i.component.customId === "template") {
+ i.deferUpdate()
+ await interaction.channel.send({embeds: [new EmojiEmbed()
+ .setTitle(ticketMessages[parseInt(i.values[0])].label)
+ .setDescription(ticketMessages[parseInt(i.values[0])].description)
+ .setStatus("Success")
+ .setEmoji("GUILD.TICKET.OPEN")
+ ], components: [new MessageActionRow().addComponents([new MessageButton()
+ .setLabel("Create Ticket")
+ .setEmoji(getEmojiByName("CONTROL.TICK", "id"))
+ .setStyle("SUCCESS")
+ .setCustomId("createticket")
+ ])]});
+ break
+ } else if (i.component.customId === "blank") {
+ i.deferUpdate()
+ await interaction.channel.send({components: [new MessageActionRow().addComponents([new MessageButton()
+ .setLabel("Create Ticket")
+ .setEmoji(getEmojiByName("TICKETS.SUGGESTION", "id"))
+ .setStyle("SUCCESS")
+ .setCustomId("createticket")
+ ])]});
+ break
+ } else if (i.component.customId === "custom") {
+ await i.showModal(new Discord.Modal().setCustomId("modal").setTitle(`Enter embed details`).addComponents(
+ new MessageActionRow<TextInputComponent>().addComponents(new TextInputComponent()
+ .setCustomId("title")
+ .setLabel("Title")
+ .setMaxLength(256)
+ .setRequired(true)
+ .setStyle("SHORT")
+ ),
+ new MessageActionRow<TextInputComponent>().addComponents(new TextInputComponent()
+ .setCustomId("description")
+ .setLabel("Description")
+ .setMaxLength(4000)
+ .setRequired(true)
+ .setStyle("PARAGRAPH")
+ )
+ ))
+ await interaction.editReply({
+ embeds: [new EmojiEmbed()
+ .setTitle("Ticket Button")
+ .setDescription("Modal opened. If you can't see it, click back and try again.")
+ .setStatus("Success")
+ .setEmoji("GUILD.TICKET.OPEN")
+ ], components: [new MessageActionRow().addComponents([new MessageButton()
+ .setLabel("Back")
+ .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
+ .setStyle("PRIMARY")
+ .setCustomId("back")
+ ])]
+ });
+ let out;
+ try {
+ out = await modalInteractionCollector(m, (m) => m.channel.id === interaction.channel.id, (m) => m.customId === "modify")
+ } catch (e) { break }
+ if (out.fields) {
+ let title = out.fields.getTextInputValue("title");
+ let description = out.fields.getTextInputValue("description");
+ await interaction.channel.send({embeds: [new EmojiEmbed()
+ .setTitle(title)
+ .setDescription(description)
+ .setStatus("Success")
+ .setEmoji("GUILD.TICKET.OPEN")
+ ], components: [new MessageActionRow().addComponents([new MessageButton()
+ .setLabel("Create Ticket")
+ .setEmoji(getEmojiByName("TICKETS.SUGGESTION", "id"))
+ .setStyle("SUCCESS")
+ .setCustomId("createticket")
+ ])]});
+ break
+ } else { continue }
+ }
+ }
} else if (i.component.customId === "enabled") {
await client.database.guilds.write(interaction.guild.id, { "tickets.enabled": !data.enabled })
data.enabled = !data.enabled;
diff --git a/src/commands/settings/verify.ts b/src/commands/settings/verify.ts
index 14dfe8d..a77f2f4 100644
--- a/src/commands/settings/verify.ts
+++ b/src/commands/settings/verify.ts
@@ -1,11 +1,12 @@
import { LoadingEmbed } from './../../utils/defaultEmbeds.js';
-import Discord, { CommandInteraction, MessageActionRow, MessageButton } from "discord.js";
+import Discord, { CommandInteraction, Emoji, MessageActionRow, MessageButton, MessageSelectMenu, TextInputComponent } from "discord.js";
import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
import confirmationMessage from "../../utils/confirmationMessage.js";
import getEmojiByName from "../../utils/getEmojiByName.js";
import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import { WrappedCheck } from "jshaiku";
import client from "../../utils/client.js";
+import { modalInteractionCollector } from '../../utils/dualCollector.js';
const command = (builder: SlashCommandSubcommandBuilder) =>
builder
@@ -53,7 +54,7 @@
let data = {
meta:{
type: 'verifyRoleChanged',
- displayName: 'Ignored Groups Changed',
+ displayName: 'Verify Role Changed',
calculateType: 'nucleusSettingsUpdated',
color: NucleusColors.green,
emoji: "CONTROL.BLOCKTICK",
@@ -103,7 +104,12 @@
.setLabel(clicks ? "Click again to confirm" : "Reset role")
.setEmoji(getEmojiByName(clicks ? "TICKETS.ISSUE" : "CONTROL.CROSS", "id"))
.setStyle("DANGER")
- .setDisabled(!role)
+ .setDisabled(!role),
+ new MessageButton()
+ .setCustomId("send")
+ .setLabel("Add verify button")
+ .setEmoji(getEmojiByName("TICKETS.SUGGESTION", "id"))
+ .setStyle("PRIMARY")
])]});
let i;
try {
@@ -117,23 +123,127 @@
await client.database.guilds.write(interaction.guild.id, null, ["verify.role", "verify.enabled"])
role = undefined;
}
+ } else if (i.component.customId === "send") {
+ const verifyMessages = [
+ {label: "Verify", description: "Click the button below to get verified"},
+ {label: "Get verified", description: "To get access to the rest of the server, click the button below"},
+ {label: "Ready to verify?", description: "Click the button below to verify yourself"},
+ ]
+ while (true) {
+ await interaction.editReply({embeds: [new EmojiEmbed()
+ .setTitle("Verify Button")
+ .setDescription("Select a message template to send in this channel")
+ .setFooter({text: role ? "" : "You do no have a verify role set so the button will not work."})
+ .setStatus(role ? "Success" : "Warning")
+ .setEmoji("GUILD.ROLES.CREATE")
+ ], components: [
+ new MessageActionRow().addComponents([
+ new MessageSelectMenu().setOptions(verifyMessages.map((t: {label: string, description: string, value?: string}, index) => {
+ t.value = index.toString(); return t as {value: string, label: string, description: string}
+ })).setCustomId("template").setMaxValues(1).setMinValues(1).setPlaceholder("Select a message template"),
+ ]),
+ new MessageActionRow().addComponents([
+ new MessageButton()
+ .setCustomId("back")
+ .setLabel("Back")
+ .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
+ .setStyle("DANGER"),
+ new MessageButton()
+ .setCustomId("blank")
+ .setLabel("Empty")
+ .setStyle("SECONDARY"),
+ new MessageButton()
+ .setCustomId("custom")
+ .setLabel("Custom")
+ .setEmoji(getEmojiByName("TICKETS.OTHER", "id"))
+ .setStyle("PRIMARY")
+ ])
+ ]});
+ let i;
+ try {
+ i = await m.awaitMessageComponent({time: 300000});
+ } catch(e) { break }
+ if (i.component.customId === "template") {
+ i.deferUpdate()
+ await interaction.channel.send({embeds: [new EmojiEmbed()
+ .setTitle(verifyMessages[parseInt(i.values[0])].label)
+ .setDescription(verifyMessages[parseInt(i.values[0])].description)
+ .setStatus("Success")
+ .setEmoji("CONTROL.BLOCKTICK")
+ ], components: [new MessageActionRow().addComponents([new MessageButton()
+ .setLabel("Verify")
+ .setEmoji(getEmojiByName("CONTROL.TICK", "id"))
+ .setStyle("SUCCESS")
+ .setCustomId("verifybutton")
+ ])]});
+ break
+ } else if (i.component.customId === "blank") {
+ i.deferUpdate()
+ await interaction.channel.send({components: [new MessageActionRow().addComponents([new MessageButton()
+ .setLabel("Verify")
+ .setEmoji(getEmojiByName("CONTROL.TICK", "id"))
+ .setStyle("SUCCESS")
+ .setCustomId("verifybutton")
+ ])]});
+ break
+ } else if (i.component.customId === "custom") {
+ await i.showModal(new Discord.Modal().setCustomId("modal").setTitle(`Enter embed details`).addComponents(
+ new MessageActionRow<TextInputComponent>().addComponents(new TextInputComponent()
+ .setCustomId("title")
+ .setLabel("Title")
+ .setMaxLength(256)
+ .setRequired(true)
+ .setStyle("SHORT")
+ ),
+ new MessageActionRow<TextInputComponent>().addComponents(new TextInputComponent()
+ .setCustomId("description")
+ .setLabel("Description")
+ .setMaxLength(4000)
+ .setRequired(true)
+ .setStyle("PARAGRAPH")
+ )
+ ))
+ await interaction.editReply({
+ embeds: [new EmojiEmbed()
+ .setTitle("Verify Button")
+ .setDescription("Modal opened. If you can't see it, click back and try again.")
+ .setStatus("Success")
+ .setEmoji("GUILD.TICKET.OPEN")
+ ], components: [new MessageActionRow().addComponents([new MessageButton()
+ .setLabel("Back")
+ .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
+ .setStyle("PRIMARY")
+ .setCustomId("back")
+ ])]
+ });
+ let out;
+ try {
+ out = await modalInteractionCollector(m, (m) => m.channel.id === interaction.channel.id, (m) => m.customId === "modify")
+ } catch (e) { break }
+ if (out.fields) {
+ let title = out.fields.getTextInputValue("title");
+ let description = out.fields.getTextInputValue("description");
+ await interaction.channel.send({embeds: [new EmojiEmbed()
+ .setTitle(title)
+ .setDescription(description)
+ .setStatus("Success")
+ .setEmoji("CONTROL.BLOCKTICK")
+ ], components: [new MessageActionRow().addComponents([new MessageButton()
+ .setLabel("Verify")
+ .setEmoji(getEmojiByName("CONTROL.TICK", "id"))
+ .setStyle("SUCCESS")
+ .setCustomId("verifybutton")
+ ])]});
+ break
+ } else { continue }
+ }
+ }
} else {
- break
+ i.deferUpdate()
+ break;
}
}
- await interaction.editReply({embeds: [new EmojiEmbed()
- .setTitle("Verify Role")
- .setDescription(role ? `Your verify role is currently set to <@&${role}}>` : `You have not set a verify role`)
- .setStatus("Success")
- .setEmoji("GUILD.ROLE.CREATE")
- .setFooter({text: "Message closed"})
- ], components: [new MessageActionRow().addComponents([new MessageButton()
- .setCustomId("clear")
- .setLabel("Clear")
- .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
- .setStyle("SECONDARY")
- .setDisabled(true),
- ])]});
+ await interaction.editReply({embeds: [m.embeds[0].setFooter({text: "Message closed"})], components: []});
}
const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
diff --git a/src/commands/settings/welcome.ts b/src/commands/settings/welcome.ts
new file mode 100644
index 0000000..1a107ed
--- /dev/null
+++ b/src/commands/settings/welcome.ts
@@ -0,0 +1,209 @@
+import { LoadingEmbed } from './../../utils/defaultEmbeds.js';
+import Discord, { CommandInteraction, MessageActionRow, MessageButton, MessageSelectMenu } from "discord.js";
+import { SlashCommandSubcommandBuilder } from "@discordjs/builders";
+import { WrappedCheck } from "jshaiku";
+import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
+import client from '../../utils/client.js';
+import confirmationMessage from '../../utils/confirmationMessage.js';
+import generateKeyValueList from '../../utils/generateKeyValueList.js';
+import { ChannelType } from 'discord-api-types';
+import getEmojiByName from '../../utils/getEmojiByName.js';
+
+const command = (builder: SlashCommandSubcommandBuilder) =>
+ builder
+ .setName("welcome")
+ .setDescription("Messages and roles sent or given when someone joins the server")
+ .addStringOption(option => option.setName("message").setDescription("The message to send when someone joins the server").setAutocomplete(true))
+ .addRoleOption(option => option.setName("role").setDescription("The role given when someone joins the server"))
+ .addRoleOption(option => option.setName("ping").setDescription("The role pinged when someone joins the server"))
+ .addChannelOption(option => option.setName("channel").setDescription("The channel the welcome message should be sent to").addChannelTypes([
+ ChannelType.GuildText, ChannelType.GuildNews
+ ]))
+
+const callback = async (interaction: CommandInteraction): Promise<any> => {
+ const { renderRole, renderChannel, log, NucleusColors, entry, renderUser } = client.logger
+ await interaction.reply({embeds: LoadingEmbed, fetchReply: true, ephemeral: true});
+ let m;
+ if (interaction.options.getRole("role") || interaction.options.getChannel("channel") || interaction.options.getString("message")) {
+ let role;
+ let ping;
+ let message = interaction.options.getString("message");
+ try {
+ role = interaction.options.getRole("role")
+ ping = interaction.options.getRole("ping")
+ } catch {
+ return await interaction.editReply({embeds: [new EmojiEmbed()
+ .setEmoji("GUILD.ROLES.DELETE")
+ .setTitle("Welcome Events")
+ .setDescription("The role you provided is not a valid role")
+ .setStatus("Danger")
+ ]})
+ }
+ let channel;
+ try {
+ channel = interaction.options.getChannel("channel")
+ } catch {
+ return await interaction.editReply({embeds: [new EmojiEmbed()
+ .setEmoji("GUILD.ROLES.DELETE")
+ .setTitle("Welcome Events")
+ .setDescription("The channel you provided is not a valid channel")
+ .setStatus("Danger")
+ ]})
+ }
+ role = role as Discord.Role
+ ping = ping as Discord.Role
+ channel = channel as Discord.TextChannel
+ let options = {}
+ if (role) options["role"] = renderRole(role)
+ if (ping) options["ping"] = renderRole(ping)
+ if (channel) options["channel"] = renderChannel(channel)
+ if (message) options["message"] = "\n> " + message
+ let confirmation = await new confirmationMessage(interaction)
+ .setEmoji("GUILD.ROLES.EDIT")
+ .setTitle("Welcome Events")
+ .setDescription(generateKeyValueList(options))
+ .setColor("Warning")
+ .setInverted(true)
+ .send(true)
+ if (confirmation.cancelled) return
+ if (confirmation.success) {
+ try {
+ let toChange = {}
+ if (role) toChange["welcome.role"] = role.id
+ if (ping) toChange["welcome.ping"] = ping.id
+ if (channel) toChange["welcome.channel"] = channel.id
+ if (message) toChange["welcome.message"] = message
+ await client.database.guilds.write(interaction.guild.id, toChange);
+ let list = {
+ memberId: entry(interaction.user.id, `\`${interaction.user.id}\``),
+ changedBy: entry(interaction.user.id, renderUser(interaction.user))
+ }
+ if (role) list["role"] = entry(role.id, renderRole(role))
+ if (ping) list["ping"] = entry(ping.id, renderRole(ping))
+ if (channel) list["channel"] = entry(channel.id, renderChannel(channel.id))
+ if (message) list["message"] = entry(message, `\`${message}\``)
+ try {
+ let data = {
+ meta:{
+ type: 'welcomeSettingsUpdated',
+ displayName: 'Welcome Settings Changed',
+ calculateType: 'nucleusSettingsUpdated',
+ color: NucleusColors.green,
+ emoji: "CONTROL.BLOCKTICK",
+ timestamp: new Date().getTime()
+ },
+ list: list,
+ hidden: {
+ guild: interaction.guild.id
+ }
+ }
+ log(data);
+ } catch {}
+ } catch (e) {
+ console.log(e)
+ return interaction.editReply({embeds: [new EmojiEmbed()
+ .setTitle("Welcome Events")
+ .setDescription(`Something went wrong while updating welcome settings`)
+ .setStatus("Danger")
+ .setEmoji("GUILD.ROLES.DELETE")
+ ], components: []});
+ }
+ } else {
+ return interaction.editReply({embeds: [new EmojiEmbed()
+ .setTitle("Welcome Events")
+ .setDescription(`No changes were made`)
+ .setStatus("Success")
+ .setEmoji("GUILD.ROLES.CREATE")
+ ], components: []});
+ }
+ }
+ let lastClicked = null
+ while (true) {
+ let config = await client.database.guilds.read(interaction.guild.id)
+ m = await interaction.editReply({embeds: [new EmojiEmbed()
+ .setTitle("Welcome Events")
+ .setDescription(
+ `**Message:** ${config.welcome.message ? `\n> ${config.welcome.message}` : "*None set*"}\n` +
+ `**Role:** ${config.welcome.role ? renderRole(await interaction.guild.roles.fetch(config.welcome.role)) : "*None set*"}\n` +
+ `**Ping:** ${config.welcome.ping ? renderRole(await interaction.guild.roles.fetch(config.welcome.ping)) : "*None set*"}\n` +
+ `**Channel:** ${config.welcome.channel ? (config.welcome.channel == "dm" ? "DM" : renderChannel(await interaction.guild.channels.fetch(config.welcome.channel))) : "*None set*"}`
+ )
+ .setStatus("Success")
+ .setEmoji("CHANNEL.TEXT.CREATE")
+ ], components: [
+ new MessageActionRow().addComponents([
+ new MessageButton()
+ .setLabel(lastClicked == "clear-message" ? "Click again to confirm" : "Clear Message")
+ .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
+ .setCustomId("clear-message")
+ .setDisabled(!config.welcome.message)
+ .setStyle("DANGER"),
+ new MessageButton()
+ .setLabel(lastClicked == "clear-role" ? "Click again to confirm" : "Clear Role")
+ .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
+ .setCustomId("clear-role")
+ .setDisabled(!config.welcome.role)
+ .setStyle("DANGER"),
+ new MessageButton()
+ .setLabel(lastClicked == "clear-ping" ? "Click again to confirm" : "Clear Ping")
+ .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
+ .setCustomId("clear-ping")
+ .setDisabled(!config.welcome.ping)
+ .setStyle("DANGER"),
+ new MessageButton()
+ .setLabel(lastClicked == "clear-channel" ? "Click again to confirm" : "Clear Channel")
+ .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
+ .setCustomId("clear-channel")
+ .setDisabled(!config.welcome.channel)
+ .setStyle("DANGER"),
+ new MessageButton()
+ .setLabel("Set Channel to DM")
+ .setCustomId("set-channel-dm")
+ .setDisabled(config.welcome.channel == "dm")
+ .setStyle("SECONDARY")
+ ])
+ ]})
+ let i;
+ try {
+ i = await m.awaitMessageComponent({ time: 300000 });
+ } catch (e) {
+ break
+ }
+ i.deferUpdate()
+ if (i.customId == "clear-message") {
+ if (lastClicked == "clear-message") {
+ await client.database.guilds.write(interaction.guild.id, {"welcome.message": null});
+ lastClicked = null
+ } else { lastClicked = "clear-message" }
+ } else if (i.customId == "clear-role") {
+ if (lastClicked == "clear-role") {
+ await client.database.guilds.write(interaction.guild.id, {"welcome.role": null});
+ lastClicked = null
+ } else { lastClicked = "clear-role" }
+ } else if (i.customId == "clear-ping") {
+ if (lastClicked == "clear-ping") {
+ await client.database.guilds.write(interaction.guild.id, {"welcome.ping": null});
+ lastClicked = null
+ } else { lastClicked = "clear-ping" }
+ } else if (i.customId == "clear-channel") {
+ if (lastClicked == "clear-channel") {
+ await client.database.guilds.write(interaction.guild.id, {"welcome.channel": null});
+ lastClicked = null
+ } else { lastClicked = "clear-channel" }
+ } else if (i.customId == "set-channel-dm") {
+ await client.database.guilds.write(interaction.guild.id, {"welcome.channel": "dm"});
+ lastClicked = null
+ }
+ }
+ await interaction.editReply({embeds: [m.embeds[0].setFooter({text: "Message closed"})], components: []});
+}
+
+const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
+ let member = (interaction.member as Discord.GuildMember)
+ if (!member.permissions.has("MANAGE_GUILD")) throw "You must have the *Manage Server* permission to use this command"
+ return true;
+}
+
+export { command };
+export { callback };
+export { check };
\ No newline at end of file
diff --git a/src/commands/tag.ts b/src/commands/tag.ts
index 03b13c6..70d5a75 100644
--- a/src/commands/tag.ts
+++ b/src/commands/tag.ts
@@ -9,7 +9,7 @@
.setDescription("Get and manage the servers tags")
.addStringOption(o => o.setName("tag").setDescription("The tag to get").setAutocomplete(true).setRequired(true))
-const callback = async (interaction: CommandInteraction) => {
+const callback = async (interaction: CommandInteraction): Promise<any> => {
const config = await client.database.guilds.read(interaction.guild.id)
const tags = config.getKey("tags")
const tag = tags[interaction.options.getString("tag")]
diff --git a/src/commands/tags/create.ts b/src/commands/tags/create.ts
index b0a278d..4615def 100644
--- a/src/commands/tags/create.ts
+++ b/src/commands/tags/create.ts
@@ -79,7 +79,7 @@
const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => {
let member = (interaction.member as Discord.GuildMember)
- if (!member.permissions.has("MANAGE_MESSAGES")) throw "You must have the *Manage Server* permission to use this command"
+ if (!member.permissions.has("MANAGE_MESSAGES")) throw "You must have the *Manage Messages* permission to use this command"
return true;
}