Fixed welcome

pull/6/head
pineafan 3 years ago
parent 33d936a67e
commit 41d93567b8
No known key found for this signature in database
GPG Key ID: 0AEF25BAA0FB1C74

6
.gitignore vendored

@ -1,7 +1,11 @@
dist/
.history/
node_modules/
src/config/
src/config/*
!src/config/format.ts
!src/config/default.json
!src/config/emojis.json
src/config/main.json
.vscode/
yarn-error.log
yarn.lock

@ -62,7 +62,7 @@ for (const file of files) {
"message": null,
"role": null,
},
"welcomeRole": data.welcome ? (data.welcome.role !== null ? data.welcome.role.toString() : null) : null,
"role": data.welcome ? (data.welcome.role !== null ? data.welcome.role.toString() : null) : null,
"channel": data.welcome ? (data.welcome.message.text !== null ? data.welcome.message.channel.toString() : null) : null,
"message": data.welcome ? (data.welcome.message.text) : null
},

@ -1,6 +1,6 @@
Role all
Server rules
! A way to add buttons to verify / role menu
verificationRequired on welcome
ROLE MENU SETTINGS

@ -1,11 +1,5 @@
{
"logging": {
"logs": {
"enabled": true,
"toLog": "3fffff"
}
},
"filters": {
"images": {
"NSFW": false,
@ -30,11 +24,5 @@
}
},
"roleMenu": [],
"tracks": [],
"welcome": {
"enabled": false,
"welcomeRole": null,
"channel": null,
"message": null
}
"tracks": []
}

@ -78,7 +78,7 @@ const filterList = {
}
}
const callback = async (interaction: CommandInteraction) => {
const callback = async (interaction: CommandInteraction): Promise<any> => {
await interaction.reply({embeds: LoadingEmbed, ephemeral: true, fetchReply: true})
let filters: Filter[] = [
filterList.member.has.role("959901346000154674"),

@ -17,6 +17,7 @@ export default async function (interaction) {
return await interaction.reply({embeds: [new EmojiEmbed()
.setTitle("Tickets are disabled")
.setDescription("Please enable tickets in the configuration to use this command.")
.setFooter({text: interaction.member.permissions.has("MANAGE_GUILD") ? "You can enable it by running /settings tickets" : ""})
.setStatus("Danger")
.setEmoji("CONTROL.BLOCKCROSS")
], ephemeral: true});

@ -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 };

@ -6,7 +6,7 @@ const command = new SlashCommandBuilder()
.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
}

@ -9,7 +9,7 @@ const command = (builder: SlashCommandSubcommandBuilder) =>
.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")

@ -8,7 +8,7 @@ const command = (builder: SlashCommandSubcommandBuilder) =>
.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(

@ -9,7 +9,7 @@ const command = (builder: SlashCommandSubcommandBuilder) =>
.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")

@ -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 };

@ -1,4 +1,4 @@
const name = "log";
const name = "logs";
const description = "Settings for logging";
export { name, description };

@ -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;
}

@ -144,12 +144,7 @@ const callback = async (interaction: CommandInteraction): Promise<any> => {
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) => {

@ -192,6 +192,11 @@ const callback = async (interaction: CommandInteraction): Promise<any> => {
.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 @@ const callback = async (interaction: CommandInteraction): Promise<any> => {
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;

@ -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 @@ const callback = async (interaction: CommandInteraction): Promise<any> => {
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 @@ const callback = async (interaction: CommandInteraction): Promise<any> => {
.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 @@ const callback = async (interaction: CommandInteraction): Promise<any> => {
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) => {

@ -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 };

@ -9,7 +9,7 @@ const command = new SlashCommandBuilder()
.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")]

@ -79,7 +79,7 @@ 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_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;
}

@ -29,7 +29,8 @@
},
"welcome": {
"enabled": false,
"welcomeRole": null,
"role": null,
"ping": null,
"channel": null,
"message": null
},

@ -61,7 +61,7 @@ export default async function(walkthrough = false) {
if (walkthrough) {
switch (key) {
case "enableDevelopment": {
json[key] = (await getInput("\x1b[36mEnable development mode? \x1b[0m(\x1b[32mY\x1b[0m/\x1b[31mn\x1b[0m) > ") || "Y").toLowerCase() === "y"; break;
json[key] = (await getInput("\x1b[36mEnable development mode? This redisters commands in a single server making it easier to test\x1b[0m(\x1b[32mY\x1b[0m/\x1b[31mn\x1b[0m) > ") || "Y").toLowerCase() === "y"; break;
} case "owners": {
let chosen = "!";
let toWrite = []
@ -80,7 +80,12 @@ export default async function(walkthrough = false) {
}
if (!json.mongoUrl.endsWith("/")) json.mongoUrl += "/";
if (!json.baseUrl.endsWith("/")) json.baseUrl += "/";
let hosts = fs.readFileSync('/etc/hosts', 'utf8').toString().split("\n");
let hosts;
try {
hosts = fs.readFileSync('/etc/hosts', 'utf8').toString().split("\n");
} catch (e) {
return console.log("\x1b[31m⚠ No /etc/hosts found. Please ensure the file exists and is readable. (Windows is not supported, Mac and Linux users should not experience this error)")
}
let localhost = hosts.find(line => line.split(" ")[1] === "localhost");
if (localhost) { localhost = localhost.split(" ")[0]; }
else { localhost = "127.0.0.1" }

@ -5,7 +5,7 @@ export const event = 'commandError'
export async function callback(client, interaction, error) {
if (interaction.replied || interaction.deferred) {
await interaction.followUp({embeds: [new EmojiEmbed()
.setTitle("Something went")
.setTitle("Something went wrong")
.setDescription(error.message ?? error.toString())
.setStatus("Danger")
.setEmoji("CONTROL.BLOCKCROSS")

@ -16,8 +16,16 @@ function getAutocomplete(typed: string, options: string[]): object[] {
return fuse.slice(0, 25).map(option => ({name: option.item, value: option.item}))
}
const validReplacements = ["serverName", "memberCount", "memberCount:bots", "memberCount:humans"]
function generateStatsChannelAutocomplete(typed) {
const validReplacements = ["serverName", "memberCount", "memberCount:bots", "memberCount:humans"]
let autocompletions = []
const beforeLastOpenBracket = typed.match(/(.*){[^{}]{0,15}$/)
if (beforeLastOpenBracket !== null) { for (let replacement of validReplacements) { autocompletions.push(`${beforeLastOpenBracket[1]} {${replacement}}`) } }
else { for (let replacement of validReplacements) { autocompletions.push(`${typed} {${replacement}}`) } }
return getAutocomplete(typed, autocompletions)
}
function generateWelcomeMessageAutocomplete(typed) {
const validReplacements = ["serverName", "memberCount", "memberCount:bots", "memberCount:humans", "member:mention", "member:name"]
let autocompletions = []
const beforeLastOpenBracket = typed.match(/(.*){[^{}]{0,15}$/)
if (beforeLastOpenBracket !== null) { for (let replacement of validReplacements) { autocompletions.push(`${beforeLastOpenBracket[1]} {${replacement}}`) } }
@ -39,6 +47,7 @@ async function interactionCreate(interaction) {
switch (`${interaction.commandName} ${interaction.options.getSubcommandGroup(false)} ${interaction.options.getSubcommand(false)}`) {
case `tag null null`: { return interaction.respond(getAutocomplete(interaction.options.getString("tag"), (await tagAutocomplete(interaction)))) }
case `settings null stats`: { return interaction.respond(generateStatsChannelAutocomplete(interaction.options.getString("name"))) }
case `settings null welcome`: { return interaction.respond(generateWelcomeMessageAutocomplete(interaction.options.getString("message"))) }
}
}
}

@ -17,6 +17,7 @@ export default async function(interaction) {
if ((!config.verify.enabled ) || (!config.verify.role)) return interaction.editReply({embeds: [new EmojiEmbed()
.setTitle("Verify")
.setDescription(`Verify is not enabled on this server`)
.setFooter({text: interaction.member.permissions.has("MANAGE_GUILD") ? "You can enable it by running /settings verify" : ""})
.setStatus("Danger")
.setEmoji("CONTROL.BLOCKCROSS")
], ephemeral: true, fetchReply: true});

@ -1,41 +1,39 @@
import log from '../utils/log.js'
import convertCurlyBracketString from '../utils/convertCurlyBracketString.js'
import client from '../utils/client.js';
import EmojiEmbed from '../utils/generateEmojiEmbed.js';
export async function callback(_, member) {
if (member.bot) return
let config = await client.database.guilds.read(member.guild.id);
if (!config.welcome.enabled) return
if (!config.welcome.verificationRequired.role) {
if (config.welcome.welcomeRole) {
try {
await member.roles.add(config.welcome.welcomeRole)
} catch (err) {
console.error(err)
}
}
}
if (!config.welcome.verificationRequired.message && config.welcome.channel) {
if (config.welcome.channel) {
let string = config.welcome.message
if (string) {
string = await convertCurlyBracketString(string, member.id, member.displayName, member.guild.name, member.guild.members)
if (config.welcome.channel === 'dm') {
try {
await member.send(string)
} catch (err) {
console.error(err)
}
await member.send({
embeds: [new EmojiEmbed()
.setDescription(string)
.setStatus('Success')
]
})
} catch {}
} else {
let channel = await member.client.channels.fetch(config.welcome.channel)
let channel = await member.guild.channels.fetch(config.welcome.channel)
if (channel.guild.id !== member.guild.id) return
if (!channel) return
try {
await channel.send(string)
await channel.send({
embeds: [new EmojiEmbed()
.setDescription(string)
.setStatus('Success')
],
content: (config.welcome.ping ? `<@${config.welcome.ping}>` : '') + `<@${member.id}>`
})
} catch (err) {
console.error(err)
console.error(err) // SEN
}
}
}

@ -49,7 +49,6 @@ export class Guilds {
let out = {$set: {}, $unset: {}}
if (set) out["$set"] = set;
if (unset.length) out["$unset"] = uo;
console.log(out)
await this.guilds.updateOne({ id: guild }, out, { upsert: true });
}
@ -211,7 +210,8 @@ export interface GuildConfig {
message: boolean,
role: string | null
},
welcomeRole: string | null,
role: string | null,
ping: string | null,
channel: string | null,
message: string | null,
}

@ -4,5 +4,6 @@ export const LoadingEmbed = [new EmojiEmbed()
.setTitle("Loading")
.setDescription("One moment...")
.setStatus("Danger")
.setEmoji("NUCLEUS.LOADING")]
.setEmoji("NUCLEUS.LOADING")
]

@ -29,7 +29,7 @@ export class Logger {
entry(value, displayValue) {
return { value: value, displayValue: displayValue }
}
renderChannel(channel: Discord.GuildChannel | Discord.ThreadChannel | Discord.NewsChannel) {
renderChannel(channel: Discord.GuildChannel | Discord.ThreadChannel) {
return `${channel.name} [<#${channel.id}>]`;
}
renderRole(role: Discord.Role) {

@ -11,6 +11,6 @@
"moduleResolution": "node",
"skipLibCheck": true
},
"include": ["src/**/*", "isntaller.js"],
"include": ["src/**/*", "installer.js"],
"exclude": []
}
Loading…
Cancel
Save