All commands and some events finished
diff --git a/src/actions/createModActionTicket.ts b/src/actions/createModActionTicket.ts
index 481666b..d6e9cd9 100644
--- a/src/actions/createModActionTicket.ts
+++ b/src/actions/createModActionTicket.ts
@@ -6,7 +6,7 @@
export async function create(
guild: Discord.Guild,
- member: Discord.User,
+ user: Discord.User,
createdBy: Discord.User,
reason: string | null,
customReason?: string
@@ -14,7 +14,7 @@
const config = await client.database.guilds.read(guild.id);
const { log, NucleusColors, entry, renderUser, renderChannel, renderDelta } = client.logger;
const overwrites = [{
- id: member,
+ id: user,
allow: ["ViewChannel", "SendMessages", "AttachFiles", "AddReactions", "ReadMessageHistory"],
type: OverwriteType.Member
}] as unknown as Discord.OverwriteResolvable[];
@@ -30,78 +30,146 @@
type: OverwriteType.Role
});
}
+ const targetChannel: Discord.CategoryChannel | Discord.TextChannel = (await guild.channels.fetch(config.tickets.category!))! as Discord.CategoryChannel | Discord.TextChannel;
- let c;
- try {
- c = await guild.channels.create({
- name: member.username,
- type: ChannelType.GuildText,
- topic: `${member.id} Active`,
- parent: config.tickets.category,
- nsfw: false,
- permissionOverwrites: overwrites as Discord.OverwriteResolvable[],
- reason: "Creating ticket"
- });
- } catch (e) {
- return null;
- }
- try {
- await c.send({
- content:
- `<@${member.id}>` + (config.tickets.supportRole !== null ? ` • <@&${config.tickets.supportRole}>` : ""),
- allowedMentions: {
- users: [member.id],
- roles: config.tickets.supportRole !== null ? [config.tickets.supportRole] : []
+ let c: Discord.TextChannel | Discord.PrivateThreadChannel;
+ if (targetChannel.type === Discord.ChannelType.GuildCategory) {
+ const overwrites = [
+ {
+ id: user,
+ allow: ["ViewChannel", "SendMessages", "AttachFiles", "AddReactions", "ReadMessageHistory"],
+ type: Discord.OverwriteType.Member
}
+ ] as Discord.OverwriteResolvable[];
+ overwrites.push({
+ id: guild.roles.everyone,
+ deny: ["ViewChannel"],
+ type: Discord.OverwriteType.Role
});
- await c.send({
- embeds: [
- new EmojiEmbed()
- .setTitle("New Ticket")
- .setDescription(
- "Ticket created by a Moderator\n" +
+ if (config.tickets.supportRole !== null) {
+ overwrites.push({
+ id: guild.roles.cache.get(config.tickets.supportRole)!,
+ allow: ["ViewChannel", "SendMessages", "AttachFiles", "AddReactions", "ReadMessageHistory"],
+ type: Discord.OverwriteType.Role
+ });
+ }
+
+ try {
+ c = await guild.channels.create({
+ name: `${user.username.toLowerCase()}`,
+ type: ChannelType.GuildText,
+ topic: `${user.id} Active`,
+ parent: config.tickets.category,
+ nsfw: false,
+ permissionOverwrites: overwrites as Discord.OverwriteResolvable[],
+ reason: "Creating ticket"
+ });
+ } catch (e) {
+ return null;
+ }
+ try {
+ await c.send({
+ content:
+ `<@${user.id}>` +
+ (config.tickets.supportRole !== null ? ` • <@&${config.tickets.supportRole}>` : ""),
+ allowedMentions: {
+ users: [user.id],
+ roles: config.tickets.supportRole !== null ? [config.tickets.supportRole] : []
+ }
+ });
+ await c.send({
+ embeds: [
+ new EmojiEmbed()
+ .setTitle("New Ticket")
+ .setDescription(
+ "Ticket created by a Moderator\n" +
`**Support type:** ${customReason ? customReason : "Appeal submission"}\n` +
(reason !== null ? `**Reason:**\n> ${reason}\n` : "") +
`**Ticket ID:** \`${c.id}\`\n` +
`Type ${await getCommandMentionByName("ticket/close")} to close this ticket.`
- )
- .setStatus("Success")
- .setEmoji("GUILD.TICKET.OPEN")
- ],
- components: [
- new ActionRowBuilder<Discord.ButtonBuilder>().addComponents([
- new ButtonBuilder()
- .setLabel("Close")
- .setStyle(ButtonStyle.Danger)
- .setCustomId("closeticket")
- .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
- ])
- ]
- });
- const data = {
- meta: {
- type: "ticketCreate",
- displayName: "Ticket Created",
- calculateType: "ticketUpdate",
- color: NucleusColors.green,
- emoji: "GUILD.TICKET.OPEN",
- timestamp: new Date().getTime()
- },
- list: {
- ticketFor: entry(member.id, renderUser(member)),
- createdBy: entry(createdBy.id, renderUser(createdBy)),
- created: entry((new Date().getTime()).toString(), renderDelta(new Date().getTime())),
- ticketChannel: entry(c.id, renderChannel(c))
- },
- hidden: {
- guild: guild.id
- }
- };
- log(data);
- } catch (e) {
- console.log(e);
- return null;
+ )
+ .setStatus("Success")
+ .setEmoji("GUILD.TICKET.OPEN")
+ ],
+ components: [
+ new ActionRowBuilder<ButtonBuilder>().addComponents([
+ new ButtonBuilder()
+ .setLabel("Close")
+ .setStyle(ButtonStyle.Danger)
+ .setCustomId("closeticket")
+ .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
+ ])
+ ]
+ });
+ } catch (e) {
+ return null;
+ }
+ } else {
+ c = await targetChannel.threads.create({name: `${user.username} - ${user.id} - Active`,
+ autoArchiveDuration: 60 * 24 * 7,
+ type: Discord.ChannelType.PrivateThread,
+ reason: "Creating ticket"
+ }) as Discord.PrivateThreadChannel;
+ c.members.add(user.id);
+ c.members.add(createdBy.id);
+ try {
+ await c.send({
+ content:
+ `<@${user.id}>` +
+ (config.tickets.supportRole !== null ? ` • <@&${config.tickets.supportRole}>` : ""),
+ allowedMentions: {
+ users: [user.id],
+ roles: config.tickets.supportRole !== null ? [config.tickets.supportRole] : []
+ }
+ });
+ await c.send({
+ embeds: [
+ new EmojiEmbed()
+ .setTitle("New Ticket")
+ .setDescription(
+ "Ticket created by a Moderator\n" +
+ `**Support type:** ${customReason ? customReason : "Appeal submission"}\n` +
+ (reason !== null ? `**Reason:**\n> ${reason}\n` : "") +
+ `**Ticket ID:** \`${c.id}\`\n` +
+ `Type ${await getCommandMentionByName("ticket/close")} to close this ticket.`
+ )
+ .setStatus("Success")
+ .setEmoji("GUILD.TICKET.OPEN")
+ ],
+ components: [
+ new ActionRowBuilder<ButtonBuilder>().addComponents([
+ new ButtonBuilder()
+ .setLabel("Close")
+ .setStyle(ButtonStyle.Danger)
+ .setCustomId("closeticket")
+ .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
+ ])
+ ]
+ });
+ } catch (e) {
+ return null;
+ }
}
+ const data = {
+ meta: {
+ type: "ticketCreate",
+ displayName: "Ticket Created",
+ calculateType: "ticketUpdate",
+ color: NucleusColors.green,
+ emoji: "GUILD.TICKET.OPEN",
+ timestamp: new Date().getTime()
+ },
+ list: {
+ ticketFor: entry(user.id, renderUser(user)),
+ createdBy: entry(createdBy.id, renderUser(createdBy)),
+ created: entry((new Date().getTime()).toString(), renderDelta(new Date().getTime())),
+ ticketChannel: entry(c.id, renderChannel(c))
+ },
+ hidden: {
+ guild: guild.id
+ }
+ };
+ log(data);
return c.id;
}
diff --git a/src/commands/mod/nick.ts b/src/commands/mod/nick.ts
index 1fbde64..abb695d 100644
--- a/src/commands/mod/nick.ts
+++ b/src/commands/mod/nick.ts
@@ -1,9 +1,11 @@
-import type { CommandInteraction, GuildMember } from "discord.js";
+import { LinkWarningFooter } from './../../utils/defaults.js';
+import { ActionRowBuilder, ButtonBuilder, CommandInteraction, GuildMember, ButtonStyle, Message } from "discord.js";
import type { SlashCommandSubcommandBuilder } from "@discordjs/builders";
import confirmationMessage from "../../utils/confirmationMessage.js";
import EmojiEmbed from "../../utils/generateEmojiEmbed.js";
import keyValueList from "../../utils/generateKeyValueList.js";
import client from "../../utils/client.js";
+import { areTicketsEnabled, create } from "../../actions/createModActionTicket.js";
const command = (builder: SlashCommandSubcommandBuilder) => builder
@@ -17,123 +19,122 @@
const callback = async (interaction: CommandInteraction): Promise<unknown> => {
- const { renderUser } = client.logger;
+ const { log, NucleusColors, entry, renderDelta, renderUser } = client.logger;
// TODO:[Modals] Replace this with a modal
let notify = true;
let confirmation;
let timedOut = false;
let success = false;
- while (!timedOut && !success) {
+ let createAppealTicket = false;
+ let firstRun = true;
+ do {
confirmation = await new confirmationMessage(interaction)
.setEmoji("PUNISH.NICKNAME.RED")
.setTitle("Nickname")
.setDescription(
keyValueList({
- user: renderUser(interaction.options.getUser("user")),
+ user: renderUser(interaction.options.getUser("user")!),
"new nickname": `${
- interaction.options.getString("name") ? interaction.options.getString("name") : "*No nickname*"
+ interaction.options.get("name")?.value as string ? interaction.options.get("name")?.value as string : "*No nickname*"
}`
}) +
- `The user **will${notify ? "" : " not"}** be notified\n\n` +
- `Are you sure you want to ${interaction.options.getString("name") ? "change" : "clear"} <@!${
+ `Are you sure you want to ${interaction.options.get("name")?.value as string ? "change" : "clear"} <@!${
(interaction.options.getMember("user") as GuildMember).id
}>'s nickname?`
)
.setColor("Danger")
.addCustomBoolean(
+ "appeal",
+ "Create appeal ticket",
+ !(await areTicketsEnabled(interaction.guild!.id)),
+ async () => await create(interaction.guild!, interaction.options.getUser("user")!, interaction.user, "Nickname changed"),
+ "An appeal ticket will be created",
+ null,
+ "CONTROL.TICKET",
+ createAppealTicket
+ )
+ .addCustomBoolean(
"notify",
"Notify user",
false,
null,
- null,
+ "The user will be sent a DM",
null,
"ICONS.NOTIFY." + (notify ? "ON" : "OFF"),
notify
)
- .send(interaction.options.getString("name") !== null);
+ .setFailedMessage("No changes were made", "Success", "PUNISH.NICKNAME.GREEN")
+ .send(!firstRun);
+ firstRun = false;
if (confirmation.cancelled) timedOut = true;
- else if (confirmation.success) success = true;
+ else if (confirmation.success !== undefined) success = true;
else if (confirmation.components) {
- notify = confirmation.components.notify.active;
+ notify = confirmation.components['notify']!.active;
+ createAppealTicket = confirmation.components["appeal"]!.active;
}
- }
- if (timedOut) {
- return await interaction.editReply({
- embeds: [
- new EmojiEmbed()
- .setEmoji("PUNISH.NICKNAME.GREEN")
- .setTitle("Nickname")
- .setDescription("No changes were made")
- .setStatus("Success")
- ],
- components: []
- });
- }
- let dmd = false;
- let dm;
+ } while (!timedOut && !success);
+ if (timedOut || !success) return;
+ let dmSent = false;
+ let dmMessage: Message;
+ const config = await client.database.guilds.read(interaction.guild!.id);
try {
if (notify) {
- dm = await (interaction.options.getMember("user") as GuildMember).send({
+ const messageData: {
+ embeds: EmojiEmbed[];
+ components: ActionRowBuilder<ButtonBuilder>[];
+ } = {
embeds: [
new EmojiEmbed()
.setEmoji("PUNISH.NICKNAME.RED")
.setTitle("Nickname changed")
.setDescription(
- `Your nickname was ${interaction.options.getString("name") ? "changed" : "cleared"} in ${
- interaction.guild.name
+ `Your nickname was ${interaction.options.get("name")?.value as string ? "changed" : "cleared"} in ${
+ interaction.guild!.name
}.` +
- (interaction.options.getString("name")
- ? ` it is now: ${interaction.options.getString("name")}`
+ (interaction.options.get("name")?.value as string
+ ? ` it is now: ${interaction.options.get("name")?.value as string}`
: "") +
"\n\n" +
- (confirmation.components.appeal.response
- ? `You can appeal this here: <#${confirmation.components.appeal.response}>`
+ (createAppealTicket
+ ? `You can appeal this in the ticket created in <#${confirmation.components!["appeal"]!.response}>`
: "")
)
.setStatus("Danger")
- ]
- });
- dmd = true;
+ ], components: []
+ };
+ if (config.moderation.nick.text && config.moderation.nick.link) {
+ messageData.embeds[0]!.setFooter(LinkWarningFooter)
+ messageData.components.push(new ActionRowBuilder<ButtonBuilder>()
+ .addComponents(new ButtonBuilder()
+ .setStyle(ButtonStyle.Link)
+ .setLabel(config.moderation.nick.text)
+ .setURL(config.moderation.nick.link.replaceAll("{id}", (interaction.options.getMember("user") as GuildMember).id))
+ )
+ )
+ }
+ dmMessage = await (interaction.options.getMember("user") as GuildMember).send(messageData);
+ dmSent = true;
}
} catch {
- dmd = false;
+ dmSent = false;
}
+ let member: GuildMember;
+ let before: string | null;
+ let nickname: string | undefined;
try {
- const member = interaction.options.getMember("user") as GuildMember;
- const before = member.nickname;
- const nickname = interaction.options.getString("name");
+ member = interaction.options.getMember("user") as GuildMember;
+ before = member.nickname;
+ nickname = interaction.options.get("name")?.value as string | undefined;
member.setNickname(nickname ?? null, "Nucleus Nickname command");
await client.database.history.create(
"nickname",
- interaction.guild.id,
+ interaction.guild!.id,
member.user,
interaction.user,
null,
before,
nickname
);
- const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
- const data = {
- meta: {
- type: "memberUpdate",
- displayName: "Member Updated",
- calculateType: "guildMemberUpdate",
- color: NucleusColors.yellow,
- emoji: "PUNISH.NICKNAME.YELLOW",
- timestamp: new Date().getTime()
- },
- list: {
- memberId: entry(member.id, `\`${member.id}\``),
- before: entry(before, before ? before : "*None*"),
- after: entry(nickname, nickname ? nickname : "*None*"),
- updated: entry(new Date().getTime(), renderDelta(new Date().getTime())),
- updatedBy: entry(interaction.user.id, renderUser(interaction.user))
- },
- hidden: {
- guild: interaction.guild.id
- }
- };
- log(data);
} catch {
await interaction.editReply({
embeds: [
@@ -145,10 +146,31 @@
],
components: []
});
- if (dmd) await dm.delete();
+ if (dmSent) await dmMessage!.delete();
return;
}
- const failed = !dmd && notify;
+ const data = {
+ meta: {
+ type: "memberUpdate",
+ displayName: "Member Updated",
+ calculateType: "guildMemberUpdate",
+ color: NucleusColors.yellow,
+ emoji: "PUNISH.NICKNAME.YELLOW",
+ timestamp: new Date().getTime()
+ },
+ list: {
+ memberId: entry(member.id, `\`${member.id}\``),
+ before: entry(before, before ?? "*No nickname set*"),
+ after: entry(nickname ?? null, nickname ?? "*No nickname set*"),
+ updated: entry(new Date().getTime(), renderDelta(new Date().getTime())),
+ updatedBy: entry(interaction.user.id, renderUser(interaction.user))
+ },
+ hidden: {
+ guild: interaction.guild!.id
+ }
+ };
+ log(data);
+ const failed = !dmSent && notify;
await interaction.editReply({
embeds: [
new EmojiEmbed()
@@ -157,8 +179,8 @@
.setDescription(
"The members nickname was changed" +
(failed ? ", but was not notified" : "") +
- (confirmation.components.appeal.response
- ? ` and an appeal ticket was opened in <#${confirmation.components.appeal.response}>`
+ (confirmation.components!["appeal"]!.response !== null
+ ? ` and an appeal ticket was opened in <#${confirmation.components!["appeal"]!.response}>`
: "")
)
.setStatus(failed ? "Warning" : "Success")
diff --git a/src/commands/mod/warn.ts b/src/commands/mod/warn.ts
index 8e96078..38aa4ad 100644
--- a/src/commands/mod/warn.ts
+++ b/src/commands/mod/warn.ts
@@ -67,7 +67,7 @@
createAppealTicket = confirmation.components["appeal"]!.active;
}
} while (!timedOut && !success)
- if (timedOut || !confirmation.success) return;
+ if (timedOut || !success) return;
let dmSent = false;
const config = await client.database.guilds.read(interaction.guild.id);
try {
diff --git a/src/events/channelUpdate.ts b/src/events/channelUpdate.ts
index df212a2..67577f8 100644
--- a/src/events/channelUpdate.ts
+++ b/src/events/channelUpdate.ts
@@ -1,39 +1,40 @@
+import { GuildChannel, AuditLogEvent } from 'discord.js';
import humanizeDuration from "humanize-duration";
+import type { NucleusClient } from "../utils/client.js";
import getEmojiByName from "../utils/getEmojiByName.js";
export const event = "channelUpdate";
-export async function callback(client, oc, nc) {
- const config = await client.memory.readGuildInfo(nc.guild.id);
- return;
+export async function callback(client: NucleusClient, oldChannel: GuildChannel, newChannel: GuildChannel) {
+ const config = await client.memory.readGuildInfo(newChannel.guild.id);
const { getAuditLog, log, NucleusColors, entry, renderDelta, renderUser, renderChannel } = client.logger;
- if (nc.parent && nc.parent.id === config.tickets.category) return;
+ if (newChannel.parent && newChannel.parent.id === config.tickets.category) return;
- const auditLog = await getAuditLog(nc.guild, "CHANNEL_UPDATE");
- const audit = auditLog.entries.filter((entry) => entry.target.id === nc.id).first();
+ const auditLog = await getAuditLog(newChannel.guild, "CHANNEL_UPDATE");
+ const audit = auditLog.entries.filter((entry) => entry.target.id === newChannel.id).first();
if (audit.executor.id === client.user.id) return;
let emoji: string;
let readableType: string;
let displayName: string;
const changes = {
- channelId: entry(nc.id, `\`${nc.id}\``),
- channel: entry(nc.id, renderChannel(nc)),
+ channelId: entry(newChannel.id, `\`${newChannel.id}\``),
+ channel: entry(newChannel.id, renderChannel(newChannel)),
edited: entry(new Date().getTime(), renderDelta(new Date().getTime())),
- editedBy: entry(audit.executor.id, renderUser((await nc.guild.members.fetch(audit.executor.id)).user))
+ editedBy: entry(audit.executor.id, renderUser((await newChannel.guild.members.fetch(audit.executor.id)).user))
};
- if (oc.name !== nc.name) changes.name = entry([oc.name, nc.name], `${oc.name} -> ${nc.name}`);
- if (oc.position !== nc.position)
- changes.position = entry([oc.position, nc.position], `${oc.position} -> ${nc.position}`);
+ if (oldChannel.name !== newChannel.name) changes.name = entry([oldChannel.name, newChannel.name], `${oldChannel.name} -> ${newChannel.name}`);
+ if (oldChannel.position !== newChannel.position)
+ changes.position = entry([oldChannel.position, newChannel.position], `${oldChannel.position} -> ${newChannel.position}`);
- switch (nc.type) {
+ switch (newChannel.type) {
case "GUILD_TEXT": {
emoji = "CHANNEL.TEXT.EDIT";
readableType = "Text";
displayName = "Text Channel";
- let oldTopic = oc.topic,
- newTopic = nc.topic;
+ let oldTopic = oldChannel.topic,
+ newTopic = newChannel.topic;
if (oldTopic) {
if (oldTopic.length > 256)
oldTopic = `\`\`\`\n${oldTopic.replace("`", "'").substring(0, 253) + "..."}\n\`\`\``;
@@ -49,15 +50,15 @@
newTopic = "None";
}
const nsfw = ["", ""];
- nsfw[0] = oc.nsfw ? `${getEmojiByName("CONTROL.TICK")} Yes` : `${getEmojiByName("CONTROL.CROSS")} No`;
- nsfw[1] = nc.nsfw ? `${getEmojiByName("CONTROL.TICK")} Yes` : `${getEmojiByName("CONTROL.CROSS")} No`;
- if (oc.topic !== nc.topic)
- changes.description = entry([oc.topic, nc.topic], `\nBefore: ${oldTopic}\nAfter: ${newTopic}`);
- if (oc.nsfw !== nc.nsfw) changes.nsfw = entry([oc.nsfw, nc.nsfw], `${nsfw[0]} -> ${nsfw[1]}`);
- if (oc.rateLimitPerUser !== nc.rateLimitPerUser)
+ nsfw[0] = oldChannel.nsfw ? `${getEmojiByName("CONTROL.TICK")} Yes` : `${getEmojiByName("CONTROL.CROSS")} No`;
+ nsfw[1] = newChannel.nsfw ? `${getEmojiByName("CONTROL.TICK")} Yes` : `${getEmojiByName("CONTROL.CROSS")} No`;
+ if (oldChannel.topic !== newChannel.topic)
+ changes.description = entry([oldChannel.topic, newChannel.topic], `\nBefore: ${oldTopic}\nAfter: ${newTopic}`);
+ if (oldChannel.nsfw !== newChannel.nsfw) changes.nsfw = entry([oldChannel.nsfw, newChannel.nsfw], `${nsfw[0]} -> ${nsfw[1]}`);
+ if (oldChannel.rateLimitPerUser !== newChannel.rateLimitPerUser)
changes.rateLimitPerUser = entry(
- [oc.rateLimitPerUser, nc.rateLimitPerUser],
- `${humanizeDuration(oc.rateLimitPerUser * 1000)} -> ${humanizeDuration(nc.rateLimitPerUser * 1000)}`
+ [oldChannel.rateLimitPerUser, newChannel.rateLimitPerUser],
+ `${humanizeDuration(oldChannel.rateLimitPerUser * 1000)} -> ${humanizeDuration(newChannel.rateLimitPerUser * 1000)}`
);
break;
@@ -66,8 +67,8 @@
emoji = "CHANNEL.TEXT.EDIT";
readableType = "News";
displayName = "News Channel";
- let oldTopic = oc.topic,
- newTopic = nc.topic;
+ let oldTopic = oldChannel.topic,
+ newTopic = newChannel.topic;
if (oldTopic) {
if (oldTopic.length > 256)
oldTopic = `\`\`\`\n${oldTopic.replace("`", "'").substring(0, 253) + "..."}\n\`\`\``;
@@ -82,25 +83,25 @@
} else {
newTopic = "None";
}
- if (oc.nsfw !== nc.nsfw)
- changes.nsfw = entry([oc.nsfw, nc.nsfw], `${oc.nsfw ? "On" : "Off"} -> ${nc.nsfw ? "On" : "Off"}`);
+ if (oldChannel.nsfw !== newChannel.nsfw)
+ changes.nsfw = entry([oldChannel.nsfw, newChannel.nsfw], `${oldChannel.nsfw ? "On" : "Off"} -> ${newChannel.nsfw ? "On" : "Off"}`);
break;
}
case "GUILD_VOICE": {
emoji = "CHANNEL.VOICE.EDIT";
readableType = "Voice";
displayName = "Voice Channel";
- if (oc.bitrate !== nc.bitrate)
- changes.bitrate = entry([oc.bitrate, nc.bitrate], `${oc.bitrate} -> ${nc.bitrate}`);
- if (oc.userLimit !== nc.userLimit)
+ if (oldChannel.bitrate !== newChannel.bitrate)
+ changes.bitrate = entry([oldChannel.bitrate, newChannel.bitrate], `${oldChannel.bitrate} -> ${newChannel.bitrate}`);
+ if (oldChannel.userLimit !== newChannel.userLimit)
changes.maxUsers = entry(
- [oc.userLimit, nc.userLimit],
- `${oc.userLimit ? oc.userLimit : "Unlimited"} -> ${nc.userLimit}`
+ [oldChannel.userLimit, newChannel.userLimit],
+ `${oldChannel.userLimit ? oldChannel.userLimit : "Unlimited"} -> ${newChannel.userLimit}`
);
- if (oc.rtcRegion !== nc.rtcRegion)
+ if (oldChannel.rtcRegion !== newChannel.rtcRegion)
changes.region = entry(
- [oc.rtcRegion, nc.rtcRegion],
- `${oc.rtcRegion || "Automatic"} -> ${nc.rtcRegion || "Automatic"}`
+ [oldChannel.rtcRegion, newChannel.rtcRegion],
+ `${oldChannel.rtcRegion || "Automatic"} -> ${newChannel.rtcRegion || "Automatic"}`
);
break;
}
@@ -108,8 +109,8 @@
emoji = "CHANNEL.VOICE.EDIT";
readableType = "Stage";
displayName = "Stage Channel";
- let oldTopic = oc.topic,
- newTopic = nc.topic;
+ let oldTopic = oldChannel.topic,
+ newTopic = newChannel.topic;
if (oldTopic) {
if (oldTopic.length > 256)
oldTopic = `\`\`\`\n${oldTopic.replace("`", "'").substring(0, 253) + "..."}\n\`\`\``;
@@ -124,17 +125,17 @@
} else {
newTopic = "None";
}
- if (oc.bitrate !== nc.bitrate)
- changes.bitrate = entry([oc.bitrate, nc.bitrate], `${oc.bitrate} -> ${nc.bitrate}`);
- if (oc.userLimit !== nc.userLimit)
+ if (oldChannel.bitrate !== newChannel.bitrate)
+ changes.bitrate = entry([oldChannel.bitrate, newChannel.bitrate], `${oldChannel.bitrate} -> ${newChannel.bitrate}`);
+ if (oldChannel.userLimit !== newChannel.userLimit)
changes.maxUsers = entry(
- [oc.userLimit, nc.userLimit],
- `${oc.userLimit ? oc.userLimit : "Unlimited"} -> ${nc.userLimit}`
+ [oldChannel.userLimit, newChannel.userLimit],
+ `${oldChannel.userLimit ? oldChannel.userLimit : "Unlimited"} -> ${newChannel.userLimit}`
);
- if (oc.rtcRegion !== nc.rtcRegion)
+ if (oldChannel.rtcRegion !== newChannel.rtcRegion)
changes.region = entry(
- [oc.rtcRegion, nc.rtcRegion],
- `${oc.rtcRegion || "Automatic"} -> ${nc.rtcRegion || "Automatic"}`
+ [oldChannel.rtcRegion, newChannel.rtcRegion],
+ `${oldChannel.rtcRegion || "Automatic"} -> ${newChannel.rtcRegion || "Automatic"}`
);
break;
}
@@ -150,9 +151,9 @@
displayName = "Channel";
}
}
- const t = oc.type.split("_")[1];
- if (oc.type !== nc.type)
- changes.type = entry([oc.type, nc.type], `${t[0] + t.splice(1).toLowerCase()} -> ${readableType}`);
+ const t = oldChannel.type.split("_")[1];
+ if (oldChannel.type !== newChannel.type)
+ changes.type = entry([oldChannel.type, newChannel.type], `${t[0] + t.splice(1).toLowerCase()} -> ${readableType}`);
if (!(Object.values(changes).length - 4)) return;
const data = {
meta: {
@@ -165,7 +166,7 @@
},
list: changes,
hidden: {
- guild: nc.guild.id
+ guild: newChannel.guild.id
}
};
log(data);
diff --git a/src/events/emojiCreate.ts b/src/events/emojiCreate.ts
index b4e9dfa..8023abc 100644
--- a/src/events/emojiCreate.ts
+++ b/src/events/emojiCreate.ts
@@ -1,10 +1,14 @@
+import { AuditLogEvent } from 'discord.js';
+import type { NucleusClient } from "../utils/client.js";
+import type { GuildEmoji, GuildAuditLogsEntry } from 'discord.js'
export const event = "emojiCreate";
-export async function callback(client, emoji) {
- const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderEmoji } = emoji.client.logger;
- const auditLog = await getAuditLog(emoji.guild, "EMOJI_CREATE");
- const audit = auditLog.entries.filter((entry) => entry.target.id === emoji.id).first();
- if (audit.executor.id === client.user.id) return;
+export async function callback(client: NucleusClient, emoji: GuildEmoji) {
+ const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderEmoji } = client.logger;
+ const auditLog = (await getAuditLog(emoji.guild, AuditLogEvent.EmojiCreate))
+ .filter((entry: GuildAuditLogsEntry) => (entry.target as GuildEmoji)!.id === emoji.id)[0];
+ if (!auditLog) return;
+ if (auditLog.executor!.id === client.user!.id) return;
const data = {
meta: {
type: "emojiCreate",
@@ -17,7 +21,7 @@
list: {
emojiId: entry(emoji.id, `\`${emoji.id}\``),
emoji: entry(emoji.name, renderEmoji(emoji)),
- createdBy: entry(audit.executor.id, renderUser(audit.executor)),
+ createdBy: entry(auditLog.executor!.id, renderUser(auditLog.executor!)),
created: entry(emoji.createdTimestamp, renderDelta(emoji.createdTimestamp))
},
hidden: {
@@ -26,3 +30,4 @@
};
log(data);
}
+
diff --git a/src/events/emojiDelete.ts b/src/events/emojiDelete.ts
index c4b1535..f607cf4 100644
--- a/src/events/emojiDelete.ts
+++ b/src/events/emojiDelete.ts
@@ -1,10 +1,14 @@
+import { AuditLogEvent } from 'discord.js';
+import type { NucleusClient } from "../utils/client.js";
+import type { GuildEmoji, GuildAuditLogsEntry } from 'discord.js'
export const event = "emojiDelete";
-export async function callback(client, emoji) {
- const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderEmoji } = emoji.client.logger;
- const auditLog = await getAuditLog(emoji.guild, "EMOJI_DELETE");
- const audit = auditLog.entries.filter((entry) => entry.target.id === emoji.id).first();
- if (audit.executor.id === client.user.id) return;
+export async function callback(client: NucleusClient, emoji: GuildEmoji) {
+ const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderEmoji } = client.logger;
+ const auditLog = (await getAuditLog(emoji.guild, AuditLogEvent.EmojiCreate))
+ .filter((entry: GuildAuditLogsEntry) => (entry.target as GuildEmoji)!.id === emoji.id)[0];
+ if (!auditLog) return;
+ if (auditLog.executor!.id === client.user!.id) return;
const data = {
meta: {
type: "emojiDelete",
@@ -12,14 +16,14 @@
calculateType: "emojiUpdate",
color: NucleusColors.red,
emoji: "GUILD.EMOJI.DELETE",
- timestamp: audit.createdTimestamp
+ timestamp: auditLog.createdTimestamp
},
list: {
emojiId: entry(emoji.id, `\`${emoji.id}\``),
emoji: entry(emoji.name, renderEmoji(emoji)),
- deletedBy: entry(audit.executor.id, renderUser(audit.executor)),
+ deletedBy: entry(auditLog.executor!.id, renderUser(auditLog.executor!)),
created: entry(emoji.createdTimestamp, renderDelta(emoji.createdTimestamp)),
- deleted: entry(audit.createdTimestamp, renderDelta(audit.createdTimestamp))
+ deleted: entry(auditLog.createdTimestamp, renderDelta(auditLog.createdTimestamp))
},
hidden: {
guild: emoji.guild.id
diff --git a/src/events/emojiUpdate.ts b/src/events/emojiUpdate.ts
index 66227d4..201dd42 100644
--- a/src/events/emojiUpdate.ts
+++ b/src/events/emojiUpdate.ts
@@ -1,19 +1,22 @@
+import { AuditLogEvent } from 'discord.js';
+import type { NucleusClient } from "../utils/client.js";
+import type { GuildEmoji, GuildAuditLogsEntry } from 'discord.js'
export const event = "emojiUpdate";
-export async function callback(client, oe, ne) {
+export async function callback(client: NucleusClient, oldEmoji: GuildEmoji, newEmoji: GuildEmoji) {
const { getAuditLog, log, NucleusColors, entry, renderDelta, renderUser, renderEmoji } = client.logger;
- if (oe.name === ne.name) return;
- const auditLog = await getAuditLog(ne.guild, "EMOJI_UPDATE");
- const audit = auditLog.entries.first();
- if (audit.executor.id === client.user.id) return;
+ const auditLog = (await getAuditLog(newEmoji.guild, AuditLogEvent.EmojiCreate))
+ .filter((entry: GuildAuditLogsEntry) => (entry.target as GuildEmoji)!.id === newEmoji.id)[0];
+ if (!auditLog) return;
+ if (auditLog.executor!.id === client.user!.id) return;
const changes = {
- emojiId: entry(ne.id, `\`${ne.id}\``),
- emoji: entry(ne.id, renderEmoji(ne)),
- edited: entry(ne.createdTimestamp, renderDelta(ne.createdTimestamp)),
- editedBy: entry(audit.executor.id, renderUser((await ne.guild.members.fetch(audit.executor.id)).user)),
- name: entry([oe.name, ne.name], `\`:${oe.name}:\` -> \`:${ne.name}:\``)
+ emojiId: entry(newEmoji.id, `\`${newEmoji.id}\``),
+ emoji: entry(newEmoji.id, renderEmoji(newEmoji)),
+ edited: entry(newEmoji.createdTimestamp, renderDelta(newEmoji.createdTimestamp)),
+ editedBy: entry(auditLog.executor!.id, renderUser((await newEmoji.guild.members.fetch(auditLog.executor!.id)).user)),
+ name: entry([oldEmoji.name!, newEmoji.name!], `\`:${oldEmoji.name}:\` -> \`:${newEmoji.name}:\``)
};
const data = {
meta: {
@@ -22,11 +25,11 @@
calculateType: "emojiUpdate",
color: NucleusColors.yellow,
emoji: "GUILD.EMOJI.EDIT",
- timestamp: audit.createdTimestamp
+ timestamp: auditLog.createdTimestamp
},
list: changes,
hidden: {
- guild: ne.guild.id
+ guild: newEmoji.guild.id
}
};
log(data);
diff --git a/src/events/guildBanAdd.ts b/src/events/guildBanAdd.ts
index 5fd0b49..3d96245 100644
--- a/src/events/guildBanAdd.ts
+++ b/src/events/guildBanAdd.ts
@@ -1,4 +1,5 @@
-import type { GuildAuditLogsEntry, GuildBan } from "discord.js";
+import type { GuildAuditLogsEntry, GuildBan, User } from "discord.js";
+import { AuditLogEvent } from 'discord.js';
import { purgeByUser } from "../actions/tickets/delete.js";
import { callback as statsChannelRemove } from "../reflex/statsChannelUpdate.js";
import type { NucleusClient } from "../utils/client.js";
@@ -7,12 +8,13 @@
export async function callback(client: NucleusClient, ban: GuildBan) {
await statsChannelRemove(client, undefined, ban.guild, ban.user);
- purgeByUser(ban.user.id, ban.guild);
+ purgeByUser(ban.user.id, ban.guild.id);
const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = client.logger;
- const auditLog = await getAuditLog(ban.guild, "MEMBER_BAN_ADD");
- const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === ban.user.id).first();
- if (audit.executor.id === client.user.id) return;
- await client.database.history.create("ban", ban.guild.id, ban.user, audit.executor, audit.reason);
+ const auditLog: GuildAuditLogsEntry | undefined = (await getAuditLog(ban.guild, AuditLogEvent.EmojiCreate))
+ .filter((entry: GuildAuditLogsEntry) => ((entry.target! as User).id === ban.user.id))[0];
+ if (!auditLog) return;
+ if (auditLog.executor!.id === client.user!.id) return;
+ await client.database.history.create("ban", ban.guild.id, ban.user, auditLog.executor, auditLog.reason);
const data = {
meta: {
type: "memberBan",
@@ -26,9 +28,9 @@
memberId: entry(ban.user.id, `\`${ban.user.id}\``),
name: entry(ban.user.id, renderUser(ban.user)),
banned: entry(new Date().getTime(), renderDelta(new Date().getTime())),
- bannedBy: entry(audit.executor.id, renderUser(audit.executor)),
- reason: entry(audit.reason, audit.reason ? `\n> ${audit.reason}` : "*No reason provided.*"),
- accountCreated: entry(ban.user.createdAt, renderDelta(ban.user.createdAt)),
+ bannedBy: entry(auditLog.executor!.id, renderUser(auditLog.executor!)),
+ reason: entry(auditLog.reason, auditLog.reason ? `\n> ${auditLog.reason}` : "*No reason provided.*"),
+ accountCreated: entry(ban.user.createdTimestamp, renderDelta(ban.user.createdTimestamp)),
serverMemberCount: ban.guild.memberCount
},
hidden: {
diff --git a/src/events/guildBanRemove.ts b/src/events/guildBanRemove.ts
index f9b427a..bcb70d5 100644
--- a/src/events/guildBanRemove.ts
+++ b/src/events/guildBanRemove.ts
@@ -1,16 +1,18 @@
-import type { GuildAuditLogsEntry, GuildBan } from "discord.js";
+import type { GuildAuditLogsEntry, GuildBan, User } from "discord.js";
+import { AuditLogEvent } from "discord.js";
import { purgeByUser } from "../actions/tickets/delete.js";
import type { NucleusClient } from "../utils/client.js";
export const event = "guildBanRemove";
export async function callback(client: NucleusClient, ban: GuildBan) {
- purgeByUser(ban.user.id, ban.guild);
+ purgeByUser(ban.user.id, ban.guild.id);
const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = client.logger;
- const auditLog = await getAuditLog(ban.guild, "MEMBER_BAN_REMOVE");
- const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === ban.user.id).first();
- if (audit.executor.id === client.user.id) return;
- await client.database.history.create("unban", ban.guild.id, ban.user, audit.executor, audit.reason);
+ const auditLog = (await getAuditLog(ban.guild, AuditLogEvent.EmojiCreate))
+ .filter((entry: GuildAuditLogsEntry) => ((entry.target! as User).id === ban.user.id))[0];
+ if (!auditLog) return;
+ if (auditLog.executor!.id === client.user!.id) return;
+ await client.database.history.create("unban", ban.guild.id, ban.user, auditLog.executor, auditLog.reason);
const data = {
meta: {
type: "memberUnban",
@@ -24,8 +26,8 @@
memberId: entry(ban.user.id, `\`${ban.user.id}\``),
name: entry(ban.user.id, renderUser(ban.user)),
unbanned: entry(new Date().getTime(), renderDelta(new Date().getTime())),
- unbannedBy: entry(audit.executor.id, renderUser(audit.executor)),
- accountCreated: entry(ban.user.createdAt, renderDelta(ban.user.createdAt))
+ unbannedBy: entry(auditLog.executor!.id, renderUser(auditLog.executor!)),
+ accountCreated: entry(ban.user.createdTimestamp, renderDelta(ban.user.createdTimestamp))
},
hidden: {
guild: ban.guild.id
diff --git a/src/premium/attachmentLogs.ts b/src/premium/attachmentLogs.ts
index abda27d..8cfe080 100644
--- a/src/premium/attachmentLogs.ts
+++ b/src/premium/attachmentLogs.ts
@@ -1,3 +1,4 @@
+import { getCommandMentionByName } from './../utils/getCommandMentionByName';
import client from "../utils/client.js";
import keyValueList from "../utils/generateKeyValueList.js";
import singleNotify from "../utils/singleNotify.js";
@@ -37,7 +38,7 @@
singleNotify(
"noAttachmentLogChannel",
message.guild.id,
- "No channel set for attachment logging",
+ `No channel set for attachment logging. You can set one with ${await getCommandMentionByName("settings/logs/attachments")}`,
"Warning"
);
return { files: attachments };
@@ -47,7 +48,7 @@
singleNotify(
"attachmentLogChannelDeleted",
message.guild.id,
- "Attachment history channel was deleted",
+ `Your attachment history channel was deleted or is not longer accessible. You can set a new one with ${await getCommandMentionByName("settings/logs/attachments")}`,
"Warning"
);
return { files: attachments };
diff --git a/src/reflex/guide.ts b/src/reflex/guide.ts
index b539aac..6829ef2 100644
--- a/src/reflex/guide.ts
+++ b/src/reflex/guide.ts
@@ -3,45 +3,18 @@
ActionRowBuilder,
ButtonBuilder,
MessageComponentInteraction,
- MessageSelectOptionData,
+ StringSelectMenuInteraction,
Guild,
CommandInteraction,
GuildTextBasedChannel,
Message,
- SelectMenuInteraction,
- ButtonStyle
+ ButtonStyle,
+ ChannelType
} from "discord.js";
import EmojiEmbed from "../utils/generateEmojiEmbed.js";
import getEmojiByName from "../utils/getEmojiByName.js";
import createPageIndicator from "../utils/createPageIndicator.js";
-
-class Embed {
- embed: Discord.EmbedBuilder;
- title: string;
- description = "";
- pageId = 0;
-
- constructor() {
- this.embed = new Discord.EmbedBuilder();
- this.title = "";
- }
- setEmbed(embed: Discord.EmbedBuilder) {
- this.embed = embed;
- return this;
- }
- setTitle(title: string) {
- this.title = title;
- return this;
- }
- setDescription(description: string) {
- this.description = description;
- return this;
- }
- setPageId(pageId: number) {
- this.pageId = pageId;
- return this;
- }
-}
+import { Embed } from "../utils/defaults.js";
export default async (guild: Guild, interaction?: CommandInteraction) => {
let c: GuildTextBasedChannel | null = guild.publicUpdatesChannel ? guild.publicUpdatesChannel : guild.systemChannel;
@@ -50,14 +23,14 @@
: (guild.channels.cache.find(
(ch) =>
[
- "GUILD_TEXT",
- "GUILD_NEWS",
- "GUILD_NEWS_THREAD",
- "GUILD_PRIVATE_THREAD",
- "GUILD_PUBLIC_THREAD"
+ ChannelType.GuildText,
+ ChannelType.GuildAnnouncement,
+ ChannelType.PublicThread,
+ ChannelType.PrivateThread,
+ ChannelType.AnnouncementThread
].includes(ch.type) &&
- ch.permissionsFor(guild.roles.everyone).has("SEND_MESSAGES") &&
- ch.permissionsFor(guild.me!).has("EMBED_LINKS")
+ ch.permissionsFor(guild.roles.everyone).has("SendMessages") &&
+ ch.permissionsFor(guild.members.me!).has("EmbedLinks")
) as GuildTextBasedChannel | undefined) ?? null;
if (interaction) c = interaction.channel as GuildTextBasedChannel;
if (!c) {
@@ -226,7 +199,7 @@
let page = 0;
const publicFilter = async (component: MessageComponentInteraction) => {
- return (component.member as Discord.GuildMember).permissions.has("MANAGE_GUILD");
+ return (component.member as Discord.GuildMember).permissions.has("ManageGuild");
};
let selectPaneOpen = false;
@@ -234,20 +207,20 @@
let cancelled = false;
let timedOut = false;
while (!cancelled && !timedOut) {
- let selectPane: ActionRowBuilder[] = [];
+ let selectPane: ActionRowBuilder<Discord.StringSelectMenuBuilder | ButtonBuilder>[] = [];
if (selectPaneOpen) {
- const options: MessageSelectOptionData[] = [];
+ const options: Discord.StringSelectMenuOptionBuilder[] = [];
pages.forEach((embed) => {
- options.push({
- label: embed.title,
- value: embed.pageId.toString(),
- description: embed.description || ""
- });
+ options.push(new Discord.StringSelectMenuOptionBuilder()
+ .setLabel(embed.title)
+ .setValue(embed.pageId.toString())
+ .setDescription(embed.description || "")
+ );
});
selectPane = [
- new ActionRowBuilder().addComponents([
- new Discord.SelectMenuBuilder()
+ new ActionRowBuilder<Discord.StringSelectMenuBuilder>().addComponents([
+ new Discord.StringSelectMenuBuilder()
.addOptions(options)
.setCustomId("page")
.setMaxValues(1)
@@ -255,8 +228,8 @@
])
];
}
- const components = selectPane.concat([
- new ActionRowBuilder().addComponents([
+ const components: ActionRowBuilder<ButtonBuilder | Discord.StringSelectMenuBuilder>[] = selectPane.concat([
+ new ActionRowBuilder<ButtonBuilder>().addComponents(
new ButtonBuilder()
.setCustomId("left")
.setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
@@ -272,18 +245,18 @@
.setEmoji(getEmojiByName("CONTROL.RIGHT", "id"))
.setStyle(ButtonStyle.Secondary)
.setDisabled(page === pages.length - 1)
- ])
+ )
]);
if (interaction) {
const em = new Discord.EmbedBuilder(pages[page]!.embed);
- em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page));
+ em.setDescription(em.data.description + "\n\n" + createPageIndicator(pages.length, page));
await interaction.editReply({
embeds: [em],
components: components
});
} else {
const em = new Discord.EmbedBuilder(pages[page]!.embed);
- em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page));
+ em.setDescription(em.data.description + "\n\n" + createPageIndicator(pages.length, page));
(await m.edit({
embeds: [em],
components: components
@@ -313,7 +286,7 @@
} else if (i.component.customId === "select") {
selectPaneOpen = !selectPaneOpen;
} else if (i.component.customId === "page") {
- page = parseInt((i as SelectMenuInteraction).values[0]!);
+ page = parseInt((i as StringSelectMenuInteraction).values[0]!);
selectPaneOpen = false;
} else {
cancelled = true;
@@ -322,7 +295,7 @@
if (timedOut) {
if (interaction) {
const em = new Discord.EmbedBuilder(pages[page]!.embed);
- em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page)).setFooter({
+ em.setDescription(em.data.description + "\n\n" + createPageIndicator(pages.length, page)).setFooter({
text: "Message timed out"
});
await interaction.editReply({
@@ -331,7 +304,7 @@
});
} else {
const em = new Discord.EmbedBuilder(pages[page]!.embed);
- em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page)).setFooter({
+ em.setDescription(em.data.description + "\n\n" + createPageIndicator(pages.length, page)).setFooter({
text: "Message timed out"
});
await m.edit({
@@ -342,7 +315,7 @@
} else {
if (interaction) {
const em = new Discord.EmbedBuilder(pages[page]!.embed);
- em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page));
+ em.setDescription(em.data.description + "\n\n" + createPageIndicator(pages.length, page));
em.setFooter({ text: "Message closed" });
interaction.editReply({
embeds: [em],
diff --git a/src/reflex/statsChannelUpdate.ts b/src/reflex/statsChannelUpdate.ts
index 2e12429..db705d9 100644
--- a/src/reflex/statsChannelUpdate.ts
+++ b/src/reflex/statsChannelUpdate.ts
@@ -1,3 +1,4 @@
+import { getCommandMentionByName } from '../utils/getCommandMentionByName.js';
import type { Guild, User } from "discord.js";
import type { NucleusClient } from "../utils/client.js";
import type { GuildMember } from "discord.js";
@@ -31,7 +32,7 @@
return singleNotify(
"statsChannelDeleted",
guild!.id,
- "One or more of your stats channels have been deleted. Please use `/settings stats` if you wish to add the channel again.\n" +
+ `One or more of your stats channels have been deleted. You can use ${await getCommandMentionByName("settings/stats")}.\n` +
`The channels name was: ${deleted!.name}`,
"Critical"
);
diff --git a/src/reflex/welcome.ts b/src/reflex/welcome.ts
index 7722086..87bb81a 100644
--- a/src/reflex/welcome.ts
+++ b/src/reflex/welcome.ts
@@ -1,3 +1,4 @@
+import { getCommandMentionByName } from './../utils/getCommandMentionByName.js';
import type { NucleusClient } from "../utils/client.js";
import convertCurlyBracketString from "../utils/convertCurlyBracketString.js";
import client from "../utils/client.js";
@@ -26,7 +27,7 @@
});
} else {
const channel: GuildChannel | null = await member.guild.channels.fetch(config.welcome.channel) as GuildChannel | null;
- if (!channel) return; // TODO: SEN
+ if (!channel) return await singleNotify("welcomeChannelDeleted", member.guild.id, `The welcome channel has been deleted or is no longer accessible. Use ${await getCommandMentionByName("settings/welcome")} to set a new one`, "Warning")
if (!(channel instanceof BaseGuildTextChannel)) return;
if (channel.guild.id !== member.guild.id) return;
try {
@@ -38,7 +39,7 @@
singleNotify(
"welcomeChannelDeleted",
member.guild.id,
- "The welcome channel has been deleted or is no longer accessible. Use /settings welcome to set a new one",
+ `The welcome channel has been deleted or is no longer accessible. Use ${await getCommandMentionByName("settings/welcome")} to set a new one`,
"Warning"
)
}
diff --git a/src/utils/database.ts b/src/utils/database.ts
index a62e148..1e8e990 100644
--- a/src/utils/database.ts
+++ b/src/utils/database.ts
@@ -313,6 +313,10 @@
text: null;
link: null;
};
+ nick: {
+ text: string | null;
+ link: string | null;
+ }
};
tracks: {
name: string;
diff --git a/src/utils/log.ts b/src/utils/log.ts
index 4565251..d4e2a82 100644
--- a/src/utils/log.ts
+++ b/src/utils/log.ts
@@ -25,7 +25,7 @@
const delta = num2 - num1;
return `${num1} -> ${num2} (${delta > 0 ? "+" : ""}${delta})`;
},
- entry(value: string | number | boolean | null, displayValue: string): { value: string | boolean | null; displayValue: string } {
+ entry(value: string | number | boolean | null | string[], displayValue: string): { value: string | boolean | null | string[]; displayValue: string } {
if (typeof value === "number") value = value.toString();
return { value: value, displayValue: displayValue };
},