Working on viewas

pull/17/head
PineaFan 3 years ago
parent 538d375729
commit 1dee28f37e
No known key found for this signature in database
GPG Key ID: D404018735F488C9

@ -23,6 +23,7 @@
"node-tesseract-ocr": "^2.2.1", "node-tesseract-ocr": "^2.2.1",
"pastebin-api": "^5.1.1", "pastebin-api": "^5.1.1",
"structured-clone": "^0.2.2", "structured-clone": "^0.2.2",
"systeminformation": "^5.17.3",
"typescript": "^5.0.0-dev.20230102", "typescript": "^5.0.0-dev.20230102",
"uuid": "^8.3.2" "uuid": "^8.3.2"
}, },

@ -1,4 +1,4 @@
import { LoadingEmbed } from './../../utils/defaultEmbeds.js'; import { LoadingEmbed } from '../../utils/defaultEmbeds.js';
import type { HistorySchema } from "../../utils/database.js"; import type { HistorySchema } from "../../utils/database.js";
import Discord, { import Discord, {
CommandInteraction, CommandInteraction,
@ -22,8 +22,8 @@ import pageIndicator from "../../utils/createPageIndicator.js";
const command = (builder: SlashCommandSubcommandBuilder) => const command = (builder: SlashCommandSubcommandBuilder) =>
builder builder
.setName("info") .setName("about")
// .setNameLocalizations({"ru": "about", "zh-CN": "history", "zh-TW": "notes", "pt-BR": "flags"}) // .setNameLocalizations({"ru": "info", "zh-CN": "history", "zh-TW": "notes", "pt-BR": "flags"})
.setDescription("Shows moderator information about a user") .setDescription("Shows moderator information about a user")
.addUserOption((option) => .addUserOption((option) =>
option.setName("user").setDescription("The user to get information about").setRequired(true) option.setName("user").setDescription("The user to get information about").setRequired(true)

@ -59,6 +59,7 @@ const callback = async (interaction: CommandInteraction): Promise<void> => {
) )
.setColor("Danger") .setColor("Danger")
.addReasonButton(reason ?? "") .addReasonButton(reason ?? "")
.setFailedMessage("No changes were made", "Success", "PUNISH.BAN.GREEN")
.send(reason !== null); .send(reason !== null);
reason = reason ?? ""; reason = reason ?? "";
if (confirmation.cancelled) timedOut = true; if (confirmation.cancelled) timedOut = true;
@ -66,116 +67,103 @@ const callback = async (interaction: CommandInteraction): Promise<void> => {
else if (confirmation.newReason) reason = confirmation.newReason; else if (confirmation.newReason) reason = confirmation.newReason;
else if (confirmation.components) notify = confirmation.components["notify"]!.active; else if (confirmation.components) notify = confirmation.components["notify"]!.active;
} while (!timedOut && !chosen) } while (!timedOut && !chosen)
if (timedOut) return; if (timedOut || !confirmation.success) return;
if (confirmation.success) { reason = reason.length ? reason : null
reason = reason.length ? reason : null let dmSent = false;
let dmSent = false; let dmMessage;
let dmMessage; const config = await client.database.guilds.read(interaction.guild.id);
const config = await client.database.guilds.read(interaction.guild.id); try {
try { if (notify) {
if (notify) { if (reason) { reason = reason.split("\n").map((line) => "> " + line).join("\n") }
if (reason) { reason = reason.split("\n").map((line) => "> " + line).join("\n") } const messageData: {
const messageData: { embeds: EmojiEmbed[];
embeds: EmojiEmbed[]; components: ActionRowBuilder<ButtonBuilder>[];
components: ActionRowBuilder<ButtonBuilder>[]; } = {
} = {
embeds: [
new EmojiEmbed()
.setEmoji("PUNISH.BAN.RED")
.setTitle("Banned")
.setDescription(
`You have been banned in ${interaction.guild.name}` +
(reason ? ` for:\n${reason}` : ".\n*No reason was provided.*")
)
.setStatus("Danger")
],
components: []
};
if (config.moderation.ban.text && config.moderation.ban.link) {
messageData.embeds[0]!.setFooter(LinkWarningFooter)
messageData.components.push(new ActionRowBuilder<Discord.ButtonBuilder>()
.addComponents(new ButtonBuilder()
.setStyle(ButtonStyle.Link)
.setLabel(config.moderation.ban.text)
.setURL(config.moderation.ban.link)
)
)
}
dmMessage = await (interaction.options.getMember("user") as GuildMember).send(messageData);
dmSent = true;
}
} catch {
dmSent = false;
}
try {
const member = interaction.options.getMember("user") as GuildMember;
const days: number = interaction.options.get("delete")?.value as number | null ?? 0;
member.ban({
deleteMessageSeconds: days * 24 * 60 * 60,
reason: reason ?? "*No reason provided*"
});
await client.database.history.create("ban", interaction.guild.id, member.user, interaction.user, reason);
const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
const data = {
meta: {
type: "memberBan",
displayName: "Member Banned",
calculateType: "guildMemberPunish",
color: NucleusColors.red,
emoji: "PUNISH.BAN.RED",
timestamp: new Date().getTime()
},
list: {
memberId: entry(member.user.id, `\`${member.user.id}\``),
name: entry(member.user.id, renderUser(member.user)),
banned: entry(new Date().getTime().toString(), renderDelta(new Date().getTime())),
bannedBy: entry(interaction.user.id, renderUser(interaction.user)),
reason: entry(reason, reason ? `\n> ${reason}` : "*No reason provided.*"),
accountCreated: entry(member.user.createdAt.toString(), renderDelta(member.user.createdAt.getTime())),
serverMemberCount: interaction.guild.memberCount
},
hidden: {
guild: interaction.guild.id
}
};
log(data);
} catch {
await interaction.editReply({
embeds: [ embeds: [
new EmojiEmbed() new EmojiEmbed()
.setEmoji("PUNISH.BAN.RED") .setEmoji("PUNISH.BAN.RED")
.setTitle("Ban") .setTitle("Banned")
.setDescription("Something went wrong and the user was not banned") .setDescription(
`You have been banned in ${interaction.guild.name}` +
(reason ? ` for:\n${reason}` : ".\n*No reason was provided.*")
)
.setStatus("Danger") .setStatus("Danger")
], ],
components: [] components: []
}); };
if (dmSent && dmMessage) await dmMessage.delete(); if (config.moderation.ban.text && config.moderation.ban.link) {
return; messageData.embeds[0]!.setFooter(LinkWarningFooter)
messageData.components.push(new ActionRowBuilder<Discord.ButtonBuilder>()
.addComponents(new ButtonBuilder()
.setStyle(ButtonStyle.Link)
.setLabel(config.moderation.ban.text)
.setURL(config.moderation.ban.link)
)
)
}
dmMessage = await (interaction.options.getMember("user") as GuildMember).send(messageData);
dmSent = true;
} }
const failed = !dmSent && notify; } catch {
await interaction.editReply({ dmSent = false;
embeds: [ }
new EmojiEmbed() try {
.setEmoji(`PUNISH.BAN.${failed ? "YELLOW" : "GREEN"}`) const member = interaction.options.getMember("user") as GuildMember;
.setTitle("Ban") const days: number = interaction.options.get("delete")?.value as number | null ?? 0;
.setDescription("The member was banned" + (failed ? ", but could not be notified" : "")) member.ban({
.setStatus(failed ? "Warning" : "Success") deleteMessageSeconds: days * 24 * 60 * 60,
], reason: reason ?? "*No reason provided*"
components: []
}); });
} else { await client.database.history.create("ban", interaction.guild.id, member.user, interaction.user, reason);
const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
const data = {
meta: {
type: "memberBan",
displayName: "Member Banned",
calculateType: "guildMemberPunish",
color: NucleusColors.red,
emoji: "PUNISH.BAN.RED",
timestamp: new Date().getTime()
},
list: {
memberId: entry(member.user.id, `\`${member.user.id}\``),
name: entry(member.user.id, renderUser(member.user)),
banned: entry(new Date().getTime().toString(), renderDelta(new Date().getTime())),
bannedBy: entry(interaction.user.id, renderUser(interaction.user)),
reason: entry(reason, reason ? `\n> ${reason}` : "*No reason provided.*"),
accountCreated: entry(member.user.createdAt.toString(), renderDelta(member.user.createdAt.getTime())),
serverMemberCount: interaction.guild.memberCount
},
hidden: {
guild: interaction.guild.id
}
};
log(data);
} catch {
await interaction.editReply({ await interaction.editReply({
embeds: [ embeds: [
new EmojiEmbed() new EmojiEmbed()
.setEmoji("PUNISH.BAN.GREEN") .setEmoji("PUNISH.BAN.RED")
.setTitle("Ban") .setTitle("Ban")
.setDescription("No changes were made") .setDescription("Something went wrong and the user was not banned")
.setStatus("Success") .setStatus("Danger")
], ],
components: [] components: []
}); });
if (dmSent && dmMessage) await dmMessage.delete();
return;
} }
const failed = !dmSent && notify;
await interaction.editReply({
embeds: [
new EmojiEmbed()
.setEmoji(`PUNISH.BAN.${failed ? "YELLOW" : "GREEN"}`)
.setTitle("Ban")
.setDescription("The member was banned" + (failed ? ", but could not be notified" : ""))
.setStatus(failed ? "Warning" : "Success")
],
components: []
});
}; };
const check = async (interaction: CommandInteraction) => { const check = async (interaction: CommandInteraction) => {

@ -47,6 +47,7 @@ const callback = async (interaction: CommandInteraction): Promise<unknown> => {
notify notify
) )
.addReasonButton(reason ?? "") .addReasonButton(reason ?? "")
.setFailedMessage("No changes were made", "Success", "PUNISH.KICK.GREEN")
.send(reason !== null); .send(reason !== null);
reason = reason ?? ""; reason = reason ?? "";
if (confirmation.cancelled) timedOut = true; if (confirmation.cancelled) timedOut = true;
@ -56,20 +57,7 @@ const callback = async (interaction: CommandInteraction): Promise<unknown> => {
notify = confirmation.components["notify"]!.active; notify = confirmation.components["notify"]!.active;
} }
} while (!timedOut && !success) } while (!timedOut && !success)
if (timedOut) return; if (timedOut || !confirmation.success) return;
if (!confirmation.success) {
await interaction.editReply({
embeds: [
new EmojiEmbed()
.setEmoji("PUNISH.KICK.GREEN")
.setTitle("Kick")
.setDescription("No changes were made")
.setStatus("Success")
],
components: []
});
return;
}
let dmSent = false; let dmSent = false;
let dmMessage; let dmMessage;
const config = await client.database.guilds.read(interaction.guild.id); const config = await client.database.guilds.read(interaction.guild.id);

@ -207,6 +207,7 @@ const callback = async (interaction: CommandInteraction): Promise<unknown> => {
notify notify
) )
.addReasonButton(reason ?? "") .addReasonButton(reason ?? "")
.setFailedMessage("No changes were made", "Success", "PUNISH.MUTE.GREEN")
.send(true); .send(true);
reason = reason ?? ""; reason = reason ?? "";
if (confirmation.cancelled) timedOut = true; if (confirmation.cancelled) timedOut = true;
@ -217,20 +218,7 @@ const callback = async (interaction: CommandInteraction): Promise<unknown> => {
createAppealTicket = confirmation.components["appeal"]!.active; createAppealTicket = confirmation.components["appeal"]!.active;
} }
} while (!timedOut && !success) } while (!timedOut && !success)
if (timedOut) return; if (timedOut || !confirmation.success) return;
if (!confirmation.success) {
await interaction.editReply({
embeds: [
new EmojiEmbed()
.setEmoji("PUNISH.BAN.GREEN")
.setTitle("Softban")
.setDescription("No changes were made")
.setStatus("Success")
],
components: []
});
return;
}
const status: {timeout: boolean | null, role: boolean | null, dm: boolean | null} = {timeout: null, role: null, dm: null}; const status: {timeout: boolean | null, role: boolean | null, dm: boolean | null} = {timeout: null, role: null, dm: null};
let dmMessage; let dmMessage;
try { try {

@ -169,22 +169,22 @@ const callback = async (interaction: CommandInteraction): Promise<unknown> => {
const check = (interaction: CommandInteraction) => { const check = (interaction: CommandInteraction) => {
const member = interaction.member as GuildMember; const member = interaction.member as GuildMember;
const me = interaction.guild.me!; const me = interaction.guild!.members.me!;
const apply = interaction.options.getMember("user") as GuildMember; const apply = interaction.options.getMember("user") as GuildMember;
if (member === null || me === null || apply === null) throw new Error("That member is not in the server");
const memberPos = member.roles.cache.size ? member.roles.highest.position : 0; const memberPos = member.roles.cache.size ? member.roles.highest.position : 0;
const mePos = me.roles.cache.size ? me.roles.highest.position : 0; const mePos = me.roles.cache.size ? me.roles.highest.position : 0;
const applyPos = apply.roles.cache.size ? apply.roles.highest.position : 0; const applyPos = apply.roles.cache.size ? apply.roles.highest.position : 0;
if (!interaction.guild) return false;
// Do not allow any changing of the owner // Do not allow any changing of the owner
if (member.id === interaction.guild.ownerId) throw new Error("You cannot change the owner's nickname"); if (member.id === interaction.guild.ownerId) throw new Error("You cannot change the owner's nickname");
// Check if Nucleus can change the nickname // Check if Nucleus can change the nickname
if (!(mePos > applyPos)) throw new Error("I do not have a role higher than that member"); if (!(mePos > applyPos)) throw new Error("I do not have a role higher than that member");
// Check if Nucleus has permission to change the nickname // Check if Nucleus has permission to change the nickname
if (!me.permissions.has("MANAGE_NICKNAMES")) throw new Error("I do not have the *Manage Nicknames* permission"); if (!me.permissions.has("ManageNicknames")) throw new Error("I do not have the *Manage Nicknames* permission");
// Allow the owner to change anyone's nickname // Allow the owner to change anyone's nickname
if (member.id === interaction.guild.ownerId) return true; if (member.id === interaction.guild.ownerId) return true;
// Check if the user has manage_nicknames permission // Check if the user has manage_nicknames permission
if (!member.permissions.has("MANAGE_NICKNAMES")) if (!member.permissions.has("ManageNicknames"))
throw new Error("You do not have the *Manage Nicknames* permission"); throw new Error("You do not have the *Manage Nicknames* permission");
// Allow changing your own nickname // Allow changing your own nickname
if (member === apply) return true; if (member === apply) return true;

@ -240,170 +240,158 @@ const callback = async (interaction: CommandInteraction): Promise<unknown> => {
}) })
) )
.setColor("Danger") .setColor("Danger")
.setFailedMessage("No changes were made", "Success", "CHANNEL.PURGE.GREEN")
.send(); .send();
if (confirmation.cancelled) return; if (confirmation.cancelled || !confirmation.success) return;
if (confirmation.success) { let messages;
let messages; try {
try { if (!user) {
if (!user) { const toDelete = await (interaction.channel as TextChannel).messages.fetch({
const toDelete = await (interaction.channel as TextChannel).messages.fetch({ limit: interaction.options.get("amount")?.value as number
limit: interaction.options.get("amount")?.value as number
});
messages = await (channel as TextChannel).bulkDelete(toDelete, true);
} else {
const toDelete = (
await (
await (interaction.channel as TextChannel).messages.fetch({
limit: 100
})
).filter((m) => m.author.id === user.id)
).first(interaction.options.get("amount")?.value as number);
messages = await (channel as TextChannel).bulkDelete(toDelete, true);
}
} catch (e) {
await interaction.editReply({
embeds: [
new EmojiEmbed()
.setEmoji("CHANNEL.PURGE.RED")
.setTitle("Purge")
.setDescription("Something went wrong and no messages were deleted")
.setStatus("Danger")
],
components: []
});
}
if (!messages) {
await interaction.editReply({
embeds: [
new EmojiEmbed()
.setEmoji("CHANNEL.PURGE.RED")
.setTitle("Purge")
.setDescription("No messages could be deleted")
.setStatus("Danger")
],
components: []
}); });
return; messages = await (channel as TextChannel).bulkDelete(toDelete, true);
} else {
const toDelete = (
await (
await (interaction.channel as TextChannel).messages.fetch({
limit: 100
})
).filter((m) => m.author.id === user.id)
).first(interaction.options.get("amount")?.value as number);
messages = await (channel as TextChannel).bulkDelete(toDelete, true);
} }
if (user) { } catch (e) {
await client.database.history.create( await interaction.editReply({
"purge", embeds: [
interaction.guild.id, new EmojiEmbed()
user.user, .setEmoji("CHANNEL.PURGE.RED")
interaction.user, .setTitle("Purge")
(interaction.options.get("reason")?.value as (string | null)) ?? "*No reason provided*", .setDescription("Something went wrong and no messages were deleted")
null, .setStatus("Danger")
null, ],
messages.size.toString() components: []
); });
}
if (!messages) {
await interaction.editReply({
embeds: [
new EmojiEmbed()
.setEmoji("CHANNEL.PURGE.RED")
.setTitle("Purge")
.setDescription("No messages could be deleted")
.setStatus("Danger")
],
components: []
});
return;
}
if (user) {
await client.database.history.create(
"purge",
interaction.guild.id,
user.user,
interaction.user,
(interaction.options.get("reason")?.value as (string | null)) ?? "*No reason provided*",
null,
null,
messages.size.toString()
);
}
const { log, NucleusColors, entry, renderUser, renderChannel } = client.logger;
const data = {
meta: {
type: "channelPurge",
displayName: "Channel Purged",
calculateType: "messageDelete",
color: NucleusColors.red,
emoji: "PUNISH.BAN.RED",
timestamp: new Date().getTime()
},
list: {
memberId: entry(interaction.user.id, `\`${interaction.user.id}\``),
purgedBy: entry(interaction.user.id, renderUser(interaction.user)),
channel: entry(interaction.channel!.id, renderChannel(interaction.channel! as GuildChannel)),
messagesCleared: entry(messages.size.toString(), messages.size.toString())
},
hidden: {
guild: interaction.guild.id
} }
const { log, NucleusColors, entry, renderUser, renderChannel } = client.logger; };
const data = { log(data);
meta: { let out = "";
type: "channelPurge", messages.reverse().forEach((message) => {
displayName: "Channel Purged", if (!message) {
calculateType: "messageDelete", out += "Unknown message\n\n"
color: NucleusColors.red, } else {
emoji: "PUNISH.BAN.RED", const author = message.author ?? { username: "Unknown", discriminator: "0000", id: "Unknown" };
timestamp: new Date().getTime() out += `${author.username}#${author.discriminator} (${author.id}) [${new Date(
}, message.createdTimestamp
list: { ).toISOString()}]\n`;
memberId: entry(interaction.user.id, `\`${interaction.user.id}\``), if (message.content) {
purgedBy: entry(interaction.user.id, renderUser(interaction.user)), const lines = message.content.split("\n");
channel: entry(interaction.channel!.id, renderChannel(interaction.channel! as GuildChannel)), lines.forEach((line) => {
messagesCleared: entry(messages.size.toString(), messages.size.toString()) out += `> ${line}\n`;
}, });
hidden: {
guild: interaction.guild.id
} }
}; if (message.attachments.size > 0) {
log(data); message.attachments.forEach((attachment) => {
let out = ""; out += `Attachment > ${attachment.url}\n`;
messages.reverse().forEach((message) => { });
if (!message) {
out += "Unknown message\n\n"
} else {
const author = message.author ?? { username: "Unknown", discriminator: "0000", id: "Unknown" };
out += `${author.username}#${author.discriminator} (${author.id}) [${new Date(
message.createdTimestamp
).toISOString()}]\n`;
if (message.content) {
const lines = message.content.split("\n");
lines.forEach((line) => {
out += `> ${line}\n`;
});
}
if (message.attachments.size > 0) {
message.attachments.forEach((attachment) => {
out += `Attachment > ${attachment.url}\n`;
});
}
out += "\n\n";
} }
out += "\n\n";
}
});
const attachmentObject = {
attachment: Buffer.from(out),
name: `purge-${channel.id}-${Date.now()}.txt`,
description: "Purge log"
};
const m = (await interaction.editReply({
embeds: [
new EmojiEmbed()
.setEmoji("CHANNEL.PURGE.GREEN")
.setTitle("Purge")
.setDescription("Messages cleared")
.setStatus("Success")
],
components: [
new Discord.ActionRowBuilder<ButtonBuilder>().addComponents([
new Discord.ButtonBuilder()
.setCustomId("download")
.setLabel("Download transcript")
.setStyle(ButtonStyle.Success)
.setEmoji(getEmojiByName("CONTROL.DOWNLOAD", "id"))
])
]
})) as Discord.Message;
let component;
try {
component = await m.awaitMessageComponent({
filter: (m) => m.user.id === interaction.user.id,
time: 300000
}); });
const attachmentObject = { } catch {
attachment: Buffer.from(out), return;
name: `purge-${channel.id}-${Date.now()}.txt`, }
description: "Purge log" if (component.customId === "download") {
}; interaction.editReply({
const m = (await interaction.editReply({
embeds: [ embeds: [
new EmojiEmbed() new EmojiEmbed()
.setEmoji("CHANNEL.PURGE.GREEN") .setEmoji("CHANNEL.PURGE.GREEN")
.setTitle("Purge") .setTitle("Purge")
.setDescription("Messages cleared") .setDescription("Transcript uploaded above")
.setStatus("Success") .setStatus("Success")
], ],
components: [ components: [],
new Discord.ActionRowBuilder<ButtonBuilder>().addComponents([ files: [attachmentObject]
new Discord.ButtonBuilder() });
.setCustomId("download")
.setLabel("Download transcript")
.setStyle(ButtonStyle.Success)
.setEmoji(getEmojiByName("CONTROL.DOWNLOAD", "id"))
])
]
})) as Discord.Message;
let component;
try {
component = await m.awaitMessageComponent({
filter: (m) => m.user.id === interaction.user.id,
time: 300000
});
} catch {
return;
}
if (component.customId === "download") {
interaction.editReply({
embeds: [
new EmojiEmbed()
.setEmoji("CHANNEL.PURGE.GREEN")
.setTitle("Purge")
.setDescription("Transcript uploaded above")
.setStatus("Success")
],
components: [],
files: [attachmentObject]
});
} else {
interaction.editReply({
embeds: [
new EmojiEmbed()
.setEmoji("CHANNEL.PURGE.GREEN")
.setTitle("Purge")
.setDescription("Messages cleared")
.setStatus("Success")
],
components: []
});
}
} else { } else {
await interaction.editReply({ interaction.editReply({
embeds: [ embeds: [
new EmojiEmbed() new EmojiEmbed()
.setEmoji("CHANNEL.PURGE.GREEN") .setEmoji("CHANNEL.PURGE.GREEN")
.setTitle("Purge") .setTitle("Purge")
.setDescription("No changes were made") .setDescription("Messages cleared")
.setStatus("Success") .setStatus("Success")
], ],
components: [] components: []

@ -47,45 +47,33 @@ const callback = async (interaction: CommandInteraction): Promise<void> => {
}) + "Are you sure you want to set the slowmode in this channel?" }) + "Are you sure you want to set the slowmode in this channel?"
) )
.setColor("Danger") .setColor("Danger")
.setFailedMessage("No changes were made", "Danger", "CHANNEL.SLOWMODE.ON")
.send(); .send();
if (confirmation.cancelled) return; if (confirmation.cancelled || !confirmation.success) return;
if (confirmation.success) { try {
try { (interaction.channel as TextChannel).setRateLimitPerUser(time);
(interaction.channel as TextChannel).setRateLimitPerUser(time); } catch (e) {
} catch (e) {
await interaction.editReply({
embeds: [
new EmojiEmbed()
.setEmoji("CHANNEL.SLOWMODE.OFF")
.setTitle("Slowmode")
.setDescription("Something went wrong while setting the slowmode")
.setStatus("Danger")
],
components: []
});
}
await interaction.editReply({ await interaction.editReply({
embeds: [ embeds: [
new EmojiEmbed() new EmojiEmbed()
.setEmoji("CHANNEL.SLOWMODE.ON") .setEmoji("CHANNEL.SLOWMODE.OFF")
.setTitle("Slowmode") .setTitle("Slowmode")
.setDescription("The channel slowmode was set successfully") .setDescription("Something went wrong while setting the slowmode")
.setStatus("Success") .setStatus("Danger")
],
components: []
});
} else {
await interaction.editReply({
embeds: [
new EmojiEmbed()
.setEmoji("CHANNEL.SLOWMODE.ON")
.setTitle("Slowmode")
.setDescription("No changes were made")
.setStatus("Success")
], ],
components: [] components: []
}); });
} }
await interaction.editReply({
embeds: [
new EmojiEmbed()
.setEmoji("CHANNEL.SLOWMODE.ON")
.setTitle("Slowmode")
.setDescription("The channel slowmode was set successfully")
.setStatus("Success")
],
components: []
});
}; };
const check = (interaction: CommandInteraction) => { const check = (interaction: CommandInteraction) => {

@ -1,13 +1,13 @@
import Discord, { import Discord, {
CategoryChannel,
CommandInteraction, CommandInteraction,
GuildMember, GuildMember,
ActionRowBuilder, ActionRowBuilder,
ButtonBuilder, ButtonBuilder,
SelectMenuBuilder, ButtonStyle,
ButtonStyle NonThreadGuildBasedChannel
} from "discord.js"; } from "discord.js";
import type { SlashCommandSubcommandBuilder } from "@discordjs/builders"; import type { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import type { GuildBasedChannel } from "discord.js";
import EmojiEmbed from "../../utils/generateEmojiEmbed.js"; import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
import getEmojiByName from "../../utils/getEmojiByName.js"; import getEmojiByName from "../../utils/getEmojiByName.js";
import pageIndicator from "../../utils/createPageIndicator.js"; import pageIndicator from "../../utils/createPageIndicator.js";
@ -19,145 +19,185 @@ const command = (builder: SlashCommandSubcommandBuilder) =>
.addUserOption((option) => option.setName("member").setDescription("The member to view as").setRequired(true)); .addUserOption((option) => option.setName("member").setDescription("The member to view as").setRequired(true));
const callback = async (interaction: CommandInteraction): Promise<void> => { const callback = async (interaction: CommandInteraction): Promise<void> => {
let channels = []; /*
let m; * {
interaction.guild.channels.cache.forEach((channel) => { categoryObject: channel[],
if (!channel.parent && channel.type !== "GUILD_CATEGORY") channels.push(channel); categoryObject: channel[],
"null": channel[]
}
*/
const channels: Record<string, GuildBasedChannel[]> = {"": [] as GuildBasedChannel[]};
interaction.guild!.channels.fetch().then(channelCollection => {
channelCollection.forEach(channel => {
if (!channel) return; // if no channel
if (channel.type === Discord.ChannelType.GuildCategory) {
if(!channels[channel!.id]) channels[channel!.id] = [channel];
} else if (channel.parent) {
if (!channels[channel.parent.id]) channels[channel.parent.id] = [channel];
else (channels[channel.parent.id as string])!.push(channel);
} else {
channels[""]!.push(channel);
}
});
}); });
channels = [channels];
channels = channels.concat( const member = interaction.options.getMember("member") as Discord.GuildMember;
interaction.guild.channels.cache const autoSortBelow = [Discord.ChannelType.GuildVoice, Discord.ChannelType.GuildStageVoice];
.filter((c) => c.type === "GUILD_CATEGORY") // for each category, sort its channels. This should be based on the order of the channels, with voice and stage channels sorted below text
.map((c) => (c as CategoryChannel).children.map((c) => c)) channels = Object.values(channels).map((c) => {
); return c.sort((a: GuildBasedChannel, b: GuildBasedChannel) => {
const autoSortBelow = ["GUILD_VOICE", "GUILD_STAGE_VOICE"]; if (a.type === Discord.ChannelType.PrivateThread || b.type === Discord.ChannelType.PrivateThread)
channels = channels.map((c) => if (autoSortBelow.includes(a.type) && autoSortBelow.includes(b.type)) return a.position ?? 0 - b.position ;
c.sort((a, b) => {
if (autoSortBelow.includes(a.type) && autoSortBelow.includes(b.type)) return a.position - b.position;
if (autoSortBelow.includes(a.type)) return 1; if (autoSortBelow.includes(a.type)) return 1;
if (autoSortBelow.includes(b.type)) return -1; if (autoSortBelow.includes(b.type)) return -1;
return a.position - b.position; return a - b;
})
);
// Sort all arrays by the position of the first channels parent position
channels = channels.sort((a, b) => {
if (!a[0].parent) return -1;
if (!b[0].parent) return 1;
return a[0].parent.position - b[0].parent.position;
});
const member = interaction.options.getMember("member") as Discord.GuildMember;
m = await interaction.reply({
embeds: [
new EmojiEmbed()
.setEmoji("MEMBER.JOIN")
.setTitle("Viewing as " + member.displayName)
.setStatus("Success")
],
ephemeral: true,
fetchReply: true
});
let page = 0;
let timedOut = false;
while (!timedOut) {
m = await interaction.editReply({
embeds: [
new EmojiEmbed()
.setEmoji("MEMBER.JOIN")
.setTitle("Viewing as " + member.displayName)
.setStatus("Success")
.setDescription(
`**${channels[page][0].parent ? channels[page][0].parent.name : "Uncategorised"}**` +
"\n" +
channels[page]
.map((c) => {
let channelType = c.type;
if (interaction.guild.rulesChannelId === c.id) channelType = "RULES";
else if ("nsfw" in c && c.nsfw) channelType += "_NSFW";
return c.permissionsFor(member).has("VIEW_CHANNEL")
? `${getEmojiByName("ICONS.CHANNEL." + channelType)} ${c.name}\n` +
(() => {
if ("threads" in c && c.threads.cache.size > 0) {
return (
c.threads.cache
.map(
(t) =>
` ${
getEmojiByName("ICONS.CHANNEL.THREAD_PIPE") +
" " +
getEmojiByName("ICONS.CHANNEL.THREAD_CHANNEL")
} ${t.name}`
)
.join("\n") + "\n"
);
}
return "";
})()
: "";
})
.join("") +
"\n" +
pageIndicator(channels.length, page)
)
],
components: [
new ActionRowBuilder().addComponents([
new SelectMenuBuilder()
.setOptions(
channels.map((c, index) => ({
label: c[0].parent ? c[0].parent.name : "Uncategorised",
value: index.toString(),
default: page === index
}))
)
.setCustomId("select")
.setMaxValues(1)
.setMinValues(1)
.setPlaceholder("Select a category")
]),
new ActionRowBuilder().addComponents([
new ButtonBuilder()
.setLabel(
page === 0
? ""
: channels[page - 1][0].parent
? channels[page - 1][0].parent.name
: "Uncategorised"
)
.setDisabled(page === 0)
.setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
.setStyle(ButtonStyle.Primary)
.setCustomId("previous"),
new ButtonBuilder()
.setLabel(
page === channels.length - 1
? ""
: channels[page + 1][0].parent
? channels[page + 1][0].parent.name
: "Uncategorised"
)
.setDisabled(page === channels.length - 1)
.setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
.setStyle(ButtonStyle.Primary)
.setCustomId("next")
])
]
}); });
let i;
try {
i = await m.awaitMessageComponent({ time: 300000 });
} catch (e) {
timedOut = true;
continue;
}
i.deferUpdate();
if (i.customId === "next") {
page++;
} else if (i.customId === "previous") {
page--;
} else if (i.customId === "select") {
page = parseInt(i.values[0]);
}
} }
//OLD CODE START
// const unprocessedChannels: GuildBasedChannel[] = [];
// let m;
// interaction.guild!.channels.cache.forEach((channel) => {
// if (!channel.parent && channel.type !== Discord.ChannelType.GuildCategory) unprocessedChannels.push(channel);
// });
// let channels: GuildBasedChannel[][] = [unprocessedChannels];
// channels = channels.concat(
// interaction.guild!.channels.cache
// .filter((c) => c.type === Discord.ChannelType.GuildCategory)
// .map((c) => (c as CategoryChannel).children.map((c) => c))
// );
// const autoSortBelow = ["GUILD_VOICE", "GUILD_STAGE_VOICE"];
// channels = channels.map((c) =>
// c.sort((a, b) => {
// if (autoSortBelow.includes(a.type) && autoSortBelow.includes(b.type)) return a.position - b.position;
// if (autoSortBelow.includes(a.type)) return 1;
// if (autoSortBelow.includes(b.type)) return -1;
// return a.position - b.position;
// })
// );
// // Sort all arrays by the position of the first channels parent position
// channels = channels.sort((a, b) => {
// if (!a[0].parent) return -1;
// if (!b[0].parent) return 1;
// return a[0].parent.position - b[0].parent.position;
// });
// const member = interaction.options.getMember("member") as Discord.GuildMember;
// m = await interaction.reply({
// embeds: [
// new EmojiEmbed()
// .setEmoji("MEMBER.JOIN")
// .setTitle("Viewing as " + member.displayName)
// .setStatus("Success")
// ],
// ephemeral: true,
// fetchReply: true
// });
// let page = 0;
// let timedOut = false;
// while (!timedOut) {
// m = await interaction.editReply({
// embeds: [
// new EmojiEmbed()
// .setEmoji("MEMBER.JOIN")
// .setTitle("Viewing as " + member.displayName)
// .setStatus("Success")
// .setDescription(
// `**${channels[page][0].parent ? channels[page][0].parent.name : "Uncategorised"}**` +
// "\n" +
// channels[page]
// .map((c) => {
// let channelType = c.type;
// if (interaction.guild.rulesChannelId === c.id) channelType = "RULES";
// else if ("nsfw" in c && c.nsfw) channelType += "_NSFW";
// return c.permissionsFor(member).has("VIEW_CHANNEL")
// ? `${getEmojiByName("ICONS.CHANNEL." + channelType)} ${c.name}\n` +
// (() => {
// if ("threads" in c && c.threads.cache.size > 0) {
// return (
// c.threads.cache
// .map(
// (t) =>
// ` ${
// getEmojiByName("ICONS.CHANNEL.THREAD_PIPE") +
// " " +
// getEmojiByName("ICONS.CHANNEL.THREAD_CHANNEL")
// } ${t.name}`
// )
// .join("\n") + "\n"
// );
// }
// return "";
// })()
// : "";
// })
// .join("") +
// "\n" +
// pageIndicator(channels.length, page)
// )
// ],
// components: [
// new ActionRowBuilder().addComponents([
// new SelectMenuBuilder()
// .setOptions(
// channels.map((c, index) => ({
// label: c[0].parent ? c[0].parent.name : "Uncategorised",
// value: index.toString(),
// default: page === index
// }))
// )
// .setCustomId("select")
// .setMaxValues(1)
// .setMinValues(1)
// .setPlaceholder("Select a category")
// ]),
// new ActionRowBuilder().addComponents([
// new ButtonBuilder()
// .setLabel(
// page === 0
// ? ""
// : channels[page - 1][0].parent
// ? channels[page - 1][0].parent.name
// : "Uncategorised"
// )
// .setDisabled(page === 0)
// .setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
// .setStyle(ButtonStyle.Primary)
// .setCustomId("previous"),
// new ButtonBuilder()
// .setLabel(
// page === channels.length - 1
// ? ""
// : channels[page + 1][0].parent
// ? channels[page + 1][0].parent.name
// : "Uncategorised"
// )
// .setDisabled(page === channels.length - 1)
// .setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
// .setStyle(ButtonStyle.Primary)
// .setCustomId("next")
// ])
// ]
// });
// let i;
// try {
// i = await m.awaitMessageComponent({ time: 300000 });
// } catch (e) {
// timedOut = true;
// continue;
// }
// i.deferUpdate();
// if (i.customId === "next") {
// page++;
// } else if (i.customId === "previous") {
// page--;
// } else if (i.customId === "select") {
// page = parseInt(i.values[0]);
// }
// }
}; };
const check = (interaction: CommandInteraction) => { const check = (interaction: CommandInteraction) => {

@ -56,6 +56,7 @@ const callback = async (interaction: CommandInteraction): Promise<unknown> => {
notify notify
) )
.addReasonButton(reason ?? "") .addReasonButton(reason ?? "")
.setFailedMessage("No changes were made", "Success", "PUNISH.WARN.GREEN")
.send(reason !== null); .send(reason !== null);
reason = reason ?? ""; reason = reason ?? "";
if (confirmation.cancelled) timedOut = true; if (confirmation.cancelled) timedOut = true;
@ -66,20 +67,7 @@ const callback = async (interaction: CommandInteraction): Promise<unknown> => {
createAppealTicket = confirmation.components["appeal"]!.active; createAppealTicket = confirmation.components["appeal"]!.active;
} }
} while (!timedOut && !success) } while (!timedOut && !success)
if (timedOut) return; if (timedOut || !confirmation.success) return;
if (!confirmation.success) {
await interaction.editReply({
embeds: [
new EmojiEmbed()
.setEmoji("PUNISH.WARN.GREEN")
.setTitle("Warn")
.setDescription("No changes were made")
.setStatus("Success")
],
components: []
});
return;
}
let dmSent = false; let dmSent = false;
const config = await client.database.guilds.read(interaction.guild.id); const config = await client.database.guilds.read(interaction.guild.id);
try { try {

@ -1,9 +1,11 @@
import type { CommandInteraction } from "discord.js"; import { LoadingEmbed } from './../../utils/defaultEmbeds.js';
import type Discord from "discord.js"; import { ButtonStyle, CommandInteraction } from "discord.js";
import Discord from "discord.js";
import type { SlashCommandSubcommandBuilder } from "@discordjs/builders"; import type { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import confirmationMessage from "../../utils/confirmationMessage.js"; import confirmationMessage from "../../utils/confirmationMessage.js";
import EmojiEmbed from "../../utils/generateEmojiEmbed.js"; import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
import client from "../../utils/client.js"; import client from "../../utils/client.js";
import getEmojiByName from '../../utils/getEmojiByName.js';
const command = (builder: SlashCommandSubcommandBuilder) => const command = (builder: SlashCommandSubcommandBuilder) =>
builder builder
@ -17,6 +19,7 @@ const callback = async (interaction: CommandInteraction): Promise<void> => {
await interaction.guild?.members.fetch(interaction.member!.user.id) await interaction.guild?.members.fetch(interaction.member!.user.id)
const { renderUser } = client.logger; const { renderUser } = client.logger;
const suggestion = interaction.options.get("suggestion")?.value as string; const suggestion = interaction.options.get("suggestion")?.value as string;
await interaction.reply({embeds: LoadingEmbed, ephemeral: true})
const confirmation = await new confirmationMessage(interaction) const confirmation = await new confirmationMessage(interaction)
.setEmoji("ICONS.OPP.ADD") .setEmoji("ICONS.OPP.ADD")
.setTitle("Suggest") .setTitle("Suggest")
@ -26,7 +29,7 @@ const callback = async (interaction: CommandInteraction): Promise<void> => {
) )
.setColor("Danger") .setColor("Danger")
.setInverted(true) .setInverted(true)
.send(); .send(true);
if (confirmation.cancelled) return; if (confirmation.cancelled) return;
if (confirmation.success) { if (confirmation.success) {
await (client.channels.cache.get("955161206459600976") as Discord.TextChannel).send({ await (client.channels.cache.get("955161206459600976") as Discord.TextChannel).send({
@ -34,11 +37,22 @@ const callback = async (interaction: CommandInteraction): Promise<void> => {
new EmojiEmbed() new EmojiEmbed()
.setTitle("Suggestion") .setTitle("Suggestion")
.setDescription( .setDescription(
`**From:** ${renderUser(interaction.member!.user as Discord.User)}\n**Suggestion:**\n> ${suggestion}` `**From:** ${renderUser(interaction.member!.user as Discord.User)}\n**Suggestion:**\n> ${suggestion}\n\n` +
`**Server:** ${interaction.guild!.name} (${interaction.guild!.id})\n`,
) )
.setStatus("Danger") .setStatus("Warning")
.setEmoji("NUCLEUS.LOGO") ], components: [new Discord.ActionRowBuilder<Discord.ButtonBuilder>().addComponents(
] new Discord.ButtonBuilder()
.setCustomId("suggestionAccept")
.setLabel("Accept")
.setStyle(ButtonStyle.Secondary)
.setEmoji(getEmojiByName("ICONS.ADD", "id")),
new Discord.ButtonBuilder()
.setCustomId("suggestionDeny")
.setLabel("Delete")
.setStyle(ButtonStyle.Secondary)
.setEmoji(getEmojiByName("ICONS.REMOVE", "id"))
)]
}); });
await interaction.editReply({ await interaction.editReply({
embeds: [ embeds: [

@ -5,7 +5,9 @@ import close from "../actions/tickets/delete.js";
import createTranscript from "../premium/createTranscript.js"; import createTranscript from "../premium/createTranscript.js";
import type { Interaction } from "discord.js"; import type { Interaction } from "discord.js";
import type Discord from "discord.js";
import type { NucleusClient } from "../utils/client.js"; import type { NucleusClient } from "../utils/client.js";
import EmojiEmbed from "../utils/generateEmojiEmbed.js";
export const event = "interactionCreate"; export const event = "interactionCreate";
@ -18,20 +20,29 @@ async function interactionCreate(interaction: Interaction) {
case "createticket": { return await create(interaction); } case "createticket": { return await create(interaction); }
case "closeticket": { return await close(interaction); } case "closeticket": { return await close(interaction); }
case "createtranscript": { return await createTranscript(interaction); } case "createtranscript": { return await createTranscript(interaction); }
case "suggestionAccept": { return await modifySuggestion(interaction, true); }
case "suggestionDeny": { return await modifySuggestion(interaction, false); }
} }
// } else if (interaction.type === "APPLICATION_COMMAND_AUTOCOMPLETE") {
// const int = interaction as AutocompleteInteraction;
// switch (`${int.commandName} ${int.options.getSubcommandGroup(false)} ${int.options.getSubcommand(false)}`) {
// case "settings null stats": {
// return int.respond(generateStatsChannelAutocomplete(int.options.getString("name") ?? ""));
// }
// case "settings null welcome": {
// return int.respond(generateWelcomeMessageAutocomplete(int.options.getString("message") ?? ""));
// }
// }
} }
} }
async function modifySuggestion(interaction: Discord.MessageComponentInteraction, accept: boolean) {
const message = await interaction.message;
await message.fetch();
if (message.embeds.length === 0) return;
const embed = message.embeds[0];
const newColour = accept ? "Success" : "Danger";
const footer = {text: `Suggestion ${accept ? "accepted" : "denied"} by ${interaction.user.tag}`, iconURL: interaction.user.displayAvatarURL()};
const newEmbed = new EmojiEmbed()
.setTitle(embed!.title!)
.setDescription(embed!.description!)
.setFooter(footer)
.setStatus(newColour);
await interaction.update({embeds: [newEmbed], components: []});
}
export async function callback(_client: NucleusClient, interaction: Interaction) { export async function callback(_client: NucleusClient, interaction: Interaction) {
await interactionCreate(interaction); await interactionCreate(interaction);
} }

@ -30,7 +30,9 @@ class confirmationMessage {
title = ""; title = "";
emoji = ""; emoji = "";
redEmoji: string | null = null; redEmoji: string | null = null;
timeoutText: string | null = null; failedMessage: string | null = null;
failedEmoji: string | null = null;
failedStatus: "Success" | "Danger" | "Warning" | null = null;
description = ""; description = "";
color: "Danger" | "Warning" | "Success" = "Success"; color: "Danger" | "Warning" | "Success" = "Success";
customButtons: Record<string, CustomBoolean<unknown>> = {}; customButtons: Record<string, CustomBoolean<unknown>> = {};
@ -45,14 +47,13 @@ class confirmationMessage {
this.title = title; this.title = title;
return this; return this;
} }
setEmoji(emoji: string, redEmoji?: string) { setEmoji(emoji: string) {
this.emoji = emoji; this.emoji = emoji;
if (redEmoji) this.redEmoji = redEmoji; // TODO: go through all confirmation messages and change them to use this, and not do their own edits
return this; return this;
} }
setDescription(description: string, timedOut?: string) { setDescription(description: string, timedOut?: string) {
this.description = description; this.description = description;
if (timedOut) this.timeoutText = timedOut; // TODO also this if (timedOut) this.failedMessage = timedOut;
return this; return this;
} }
setColor(color: "Danger" | "Warning" | "Success") { setColor(color: "Danger" | "Warning" | "Success") {
@ -63,6 +64,12 @@ class confirmationMessage {
this.inverted = inverted; this.inverted = inverted;
return this; return this;
} }
setFailedMessage(text: string, failedStatus: "Success" | "Danger" | "Warning" | null, failedEmoji: string | null = null) {
this.failedMessage = text;
this.failedStatus = failedStatus;
this.failedEmoji = failedEmoji;
return this;
}
addCustomBoolean( addCustomBoolean(
customId: string, customId: string,
title: string, title: string,
@ -243,8 +250,7 @@ class confirmationMessage {
out = await modalInteractionCollector( out = await modalInteractionCollector(
m, m,
(m: Interaction) => (m: Interaction) =>
(m as MessageComponentInteraction | ModalSubmitInteraction).channelId === (m as MessageComponentInteraction | ModalSubmitInteraction).channelId === this.interaction.channelId,
this.interaction.channelId,
(m) => m.customId === "reason" (m) => m.customId === "reason"
); );
} catch (e) { } catch (e) {
@ -277,6 +283,17 @@ class confirmationMessage {
await this.timeoutError() await this.timeoutError()
returnValue.cancelled = true; returnValue.cancelled = true;
} }
if (success == false) {
await this.interaction.editReply({
embeds: [new EmojiEmbed()
.setTitle(this.title)
.setDescription(this.failedMessage ?? "")
.setStatus(this.failedStatus ?? "Danger")
.setEmoji(this.failedEmoji ?? this.redEmoji ?? this.emoji)
], components: []
});
return {success: false}
}
if (newReason) returnValue.newReason = newReason; if (newReason) returnValue.newReason = newReason;
const typedReturnValue = returnValue as {cancelled: true} | const typedReturnValue = returnValue as {cancelled: true} |
@ -294,10 +311,10 @@ class confirmationMessage {
.setTitle(this.title) .setTitle(this.title)
.setDescription("We closed this message because it was not used for a while.") .setDescription("We closed this message because it was not used for a while.")
.setStatus("Danger") .setStatus("Danger")
.setEmoji(this.redEmoji ?? this.emoji) .setEmoji("CONTROL.BLOCKCROSS")
], ],
components: [] components: []
}) })
} }
} }

@ -1,7 +1,9 @@
import client from "../client.js"; import client from "../client.js";
import { resourceUsage } from "process"; import * as CP from 'child_process';
import { spawn } from "child_process"; import * as process from 'process';
import systeminformation from "systeminformation";
import config from "../../config/main.json" assert { type: "json" }; import config from "../../config/main.json" assert { type: "json" };
import singleNotify from "../singleNotify.js";
const discordPing = () => { const discordPing = () => {
@ -18,17 +20,11 @@ const databaseReadTime = async () => {
return end - start; return end - start;
} }
const resources = () => { const resources = async () => {
const current = resourceUsage();
const temperatureRaw = spawn("acpi", ["-t"])
let temperatureData: number = 0;
temperatureRaw.stdout.on("data", (data) => {
return temperatureData = data.toString().split(", ")[1].split(" ")[0]; // °C
})
return { return {
memory: current.sharedMemorySize, memory: process.memoryUsage().rss / 1024 / 1024,
cpu: current.userCPUTime + current.systemCPUTime, cpu: parseFloat(CP.execSync(`ps -p ${process.pid} -o %cpu=`).toString().trim()),
temperature: temperatureData temperature: (await systeminformation.cpuTemperature()).main
} }
} }
@ -36,12 +32,24 @@ const record = async () => {
const results = { const results = {
discord: discordPing(), discord: discordPing(),
databaseRead: await databaseReadTime(), databaseRead: await databaseReadTime(),
resources: resources() resources: await resources()
};
if (results.discord > 1000 || results.databaseRead > 500 || results.resources.cpu > 100) {
singleNotify(
"performanceTest",
config.developmentGuildID,
`Discord ping time: \`${results.discord}ms\`\nDatabase read time: \`${results.databaseRead}ms\`\nCPU usage: \`${results.resources.cpu}%\`\nMemory usage: \`${results.resources.memory}MB\`\nCPU temperature: \`${results.resources.temperature}°C\``,
"Critical",
config.owners
)
} else {
singleNotify("performanceTest", config.developmentGuildID, true)
} }
client.database.performanceTest.record(results) client.database.performanceTest.record(results)
setInterval(async () => { setTimeout(async () => {
record(); await record();
}, 10 * 1000); }, 60 * 1000);
} }
export { record }; export { record };

@ -13,7 +13,8 @@ export default async function (
type: string, type: string,
guild: string, guild: string,
message: string | true, message: string | true,
severity: "Critical" | "Warning" | "Info" = "Info" severity: "Critical" | "Warning" | "Info" = "Info",
pings?: string[]
) { ) {
const data = await client.database.guilds.read(guild); const data = await client.database.guilds.read(guild);
if (data.logging.staff.channel === null) return; if (data.logging.staff.channel === null) return;
@ -30,6 +31,11 @@ export default async function (
const channel = await client.channels.fetch(data.logging.staff.channel); const channel = await client.channels.fetch(data.logging.staff.channel);
if (!channel) return; if (!channel) return;
if (!channel.isTextBased()) return; if (!channel.isTextBased()) return;
if (pings) {
await channel.send({
content: pings.map((ping) => `<@${ping}>`).join(" ")
});
}
await channel.send({ await channel.send({
embeds: [ embeds: [
new EmojiEmbed() new EmojiEmbed()

Loading…
Cancel
Save