Merge branch 'development' of github.com:clicksminuteper/nucleus into development
diff --git a/package.json b/package.json
index cba5c39..6ab482d 100644
--- a/package.json
+++ b/package.json
@@ -29,7 +29,7 @@
"build": "tsc",
"start": "node --experimental-json-modules --enable-source-maps dist/index.js",
"dev": "rm -rf dist && eslint . --fix && tsc && node --experimental-json-modules --enable-source-maps dist/index.js",
- "force-dev": "rm -rf dist && eslint . --fix; tsc-suppress && node --experimental-json-modules --enable-source-maps dist/src/index.js",
+ "force-dev": "rm -rf dist && eslint . --fix; tsc-suppress && node --experimental-json-modules --enable-source-maps dist/index.js",
"lint": "echo 'Style checking...'; prettier --check .; echo 'Linting...'; eslint .; echo 'To auto-fix everything possible, please run `yarn lint-fix`'; true",
"lint-fix": "echo 'Fixing eslint issues...'; eslint . --fix; echo 'Reformatting...'; prettier --write --loglevel warn --cache .; true",
"lint-list": "echo 'Style checking...'; prettier --check .; echo 'Linting...'; eslint .; echo 'To view errors in more detail, please run `yarn lint`'; true",
diff --git a/src/events/guildBanAdd.ts b/src/events/guildBanAdd.ts
index 17c4595..a05389f 100644
--- a/src/events/guildBanAdd.ts
+++ b/src/events/guildBanAdd.ts
@@ -1,14 +1,17 @@
+import type { GuildAuditLogsEntry, GuildBan } from 'discord.js';
import { purgeByUser } from "../actions/tickets/delete.js";
import { callback as statsChannelRemove } from "../reflex/statsChannelUpdate.js";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
export const event = "guildBanAdd";
-export async function callback(client, ban) {
- await statsChannelRemove(client, ban.user);
+export async function callback(client: HaikuClient, ban: GuildBan) {
+ await statsChannelRemove(client, undefined, ban.guild, ban.user);
purgeByUser(ban.user.id, ban.guild);
- const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = ban.user.client.logger;
+ const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = client.logger;
const auditLog = await getAuditLog(ban.guild, "MEMBER_BAN_ADD");
- const audit = auditLog.entries.filter((entry) => entry.target.id === ban.user.id).first();
+ 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 data = {
diff --git a/src/events/guildBanRemove.ts b/src/events/guildBanRemove.ts
index 74b7c4e..86d6efe 100644
--- a/src/events/guildBanRemove.ts
+++ b/src/events/guildBanRemove.ts
@@ -1,14 +1,15 @@
+import type { GuildAuditLogsEntry, GuildBan } from 'discord.js';
import { purgeByUser } from "../actions/tickets/delete.js";
-import { callback as statsChannelRemove } from "../reflex/statsChannelUpdate.js";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
export const event = "guildBanRemove";
-export async function callback(client, ban) {
- await statsChannelRemove(client, ban.user);
+export async function callback(client: HaikuClient, ban: GuildBan) {
purgeByUser(ban.user.id, ban.guild);
- const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = ban.user.client.logger;
+ const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = client.logger;
const auditLog = await getAuditLog(ban.guild, "MEMBER_BAN_REMOVE");
- const audit = auditLog.entries.filter((entry) => entry.target.id === ban.user.id).first();
+ 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 data = {
diff --git a/src/events/guildMemberUpdate.ts b/src/events/guildMemberUpdate.ts
index 08730f2..1f21870 100644
--- a/src/events/guildMemberUpdate.ts
+++ b/src/events/guildMemberUpdate.ts
@@ -1,10 +1,14 @@
+import type { GuildAuditLogsEntry, GuildMember } from "discord.js";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
+
export const event = "guildMemberUpdate";
-export async function callback(client, before, after) {
+export async function callback(client: HaikuClient, before: GuildMember, after: GuildMember) {
try {
- const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = after.client.logger;
+ const { log, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = client.logger;
const auditLog = await getAuditLog(after.guild, "MEMBER_UPDATE");
- const audit = auditLog.entries.filter((entry) => entry.target.id === after.id).first();
+ const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === after.id).first();
if (audit.executor.id === client.user.id) return;
if (before.nickname !== after.nickname) {
await client.database.history.create(
@@ -13,8 +17,8 @@
after.user,
audit.executor,
null,
- before.nickname || before.user.username,
- after.nickname || after.user.username
+ before.nickname ?? before.user.username,
+ after.nickname ?? after.user.username
);
const data = {
meta: {
@@ -39,8 +43,8 @@
};
log(data);
} else if (
- before.communicationDisabledUntilTimestamp < new Date().getTime() &&
- after.communicationDisabledUntil > new Date().getTime()
+ (before.communicationDisabledUntilTimestamp ?? 0) < new Date().getTime() &&
+ (after.communicationDisabledUntil ?? 0) > new Date().getTime() // TODO: test this
) {
await client.database.history.create(
"mute",
diff --git a/src/events/guildUpdate.ts b/src/events/guildUpdate.ts
index a165770..ea9008d 100644
--- a/src/events/guildUpdate.ts
+++ b/src/events/guildUpdate.ts
@@ -1,14 +1,17 @@
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
+import type { Guild, GuildAuditLogsEntry } from 'discord.js';
import { callback as statsChannelUpdate } from "../reflex/statsChannelUpdate.js";
export const event = "guildUpdate";
-export async function callback(client, before, after) {
- await statsChannelUpdate(client, after.me);
- const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = after.client.logger;
+export async function callback(client: HaikuClient, before: Guild, after: Guild) {
+ await statsChannelUpdate(client, after.me!);
+ const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
const auditLog = await getAuditLog(after, "GUILD_UPDATE");
- const audit = auditLog.entries.filter((entry) => entry.target.id === after.id).first();
+ const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === after.id).first();
if (audit.executor.id === client.user.id) return;
- const list = {};
+ const list: Record<string, ReturnType<typeof entry>> = {};
const verificationLevels = {
NONE: "Unrestricted",
@@ -28,32 +31,34 @@
NONE: "None",
ELEVATED: "Enabled"
};
+ const beforeOwner = await before.fetchOwner()
+ const afterOwner = await after.fetchOwner()
- if (before.name !== after.name) list.name = entry([before.name, after.name], `${before.name} -> ${after.name}`);
+ if (before.name !== after.name) list["name"] = entry([before.name, after.name], `${before.name} -> ${after.name}`);
if (before.icon !== after.icon)
- list.icon = entry([before.icon, after.icon], `[Before](${before.iconURL()}) -> [After](${after.iconURL()})`);
+ list["icon"] = entry([before.icon, after.icon], `[Before](${before.iconURL()}) -> [After](${after.iconURL()})`);
if (before.splash !== after.splash)
- list.splash = entry(
+ list["splash"] = entry(
[before.splash, after.splash],
`[Before](${before.splashURL()}) -> [After](${after.splashURL()})`
);
if (before.banner !== after.banner)
- list.banner = entry(
+ list["banner"] = entry(
[before.banner, after.banner],
`[Before](${before.bannerURL()}) -> [After](${after.bannerURL()})`
);
- if (before.owner !== after.owner)
- list.owner = entry(
- [before.owner, after.owner],
- `${renderUser(before.owner.user)} -> ${renderUser(after.owner.user)}`
+ if (beforeOwner !== afterOwner)
+ list["owner"] = entry(
+ [beforeOwner, afterOwner],
+ `${renderUser(beforeOwner.user)} -> ${renderUser(afterOwner.user)}`
);
if (before.verificationLevel !== after.verificationLevel)
- list.verificationLevel = entry(
+ list["verificationLevel"] = entry(
[verificationLevels[before.verificationLevel], verificationLevels[after.verificationLevel]],
`${verificationLevels[before.verificationLevel]} -> ${verificationLevels[after.verificationLevel]}`
);
if (before.explicitContentFilter !== after.explicitContentFilter)
- list.explicitContentFilter = entry(
+ list["explicitContentFilter"] = entry(
[
explicitContentFilterLevels[before.explicitContentFilter],
explicitContentFilterLevels[after.explicitContentFilter]
@@ -69,8 +74,8 @@
);
if (!Object.keys(list).length) return;
- list.updated = entry(new Date().getTime(), renderDelta(new Date().getTime()));
- list.updatedBy = entry(audit.executor.id, renderUser(audit.executor));
+ list["updated"] = entry(new Date().getTime(), renderDelta(new Date().getTime()));
+ list["updatedBy"] = entry(audit.executor.id, renderUser(audit.executor));
const data = {
meta: {
type: "guildUpdate",
diff --git a/src/events/interactionCreate.ts b/src/events/interactionCreate.ts
index 5b0aff1..9ee7bee 100644
--- a/src/events/interactionCreate.ts
+++ b/src/events/interactionCreate.ts
@@ -5,10 +5,13 @@
import createTranscript from "../premium/createTranscript.js";
import Fuse from "fuse.js";
import { autocomplete as tagAutocomplete } from "../commands/tag.js";
+import type { AutocompleteInteraction, Interaction, MessageComponentInteraction } from "discord.js";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
export const event = "interactionCreate";
-function getAutocomplete(typed: string, options: string[]): object[] {
+function getAutocomplete(typed: string, options: string[]): {name: string, value: string}[] {
options = options.filter((option) => option.length <= 100); // thanks discord. 6000 character limit on slash command inputs but only 100 for autocomplete.
if (!typed)
return options
@@ -23,7 +26,7 @@
return fuse.slice(0, 25).map((option) => ({ name: option.item, value: option.item }));
}
-function generateStatsChannelAutocomplete(typed) {
+function generateStatsChannelAutocomplete(typed: string) {
const validReplacements = ["serverName", "memberCount", "memberCount:bots", "memberCount:humans"];
const autocompletions = [];
const beforeLastOpenBracket = typed.match(/(.*){[^{}]{0,15}$/);
@@ -38,7 +41,7 @@
}
return getAutocomplete(typed, autocompletions);
}
-function generateWelcomeMessageAutocomplete(typed) {
+function generateWelcomeMessageAutocomplete(typed: string) {
const validReplacements = [
"serverName",
"memberCount",
@@ -61,14 +64,15 @@
return getAutocomplete(typed, autocompletions);
}
-async function interactionCreate(interaction) {
- if (interaction.componentType === "BUTTON") {
- switch (interaction.customId) {
+async function interactionCreate(interaction: Interaction) {
+ if (interaction.type === "MESSAGE_COMPONENT" && (interaction as MessageComponentInteraction).componentType === "BUTTON") {
+ const int = (interaction as MessageComponentInteraction)
+ switch (int.customId) {
case "rolemenu": {
return await roleMenu(interaction);
}
case "verifybutton": {
- return verify(interaction);
+ return verify(int);
}
case "createticket": {
return create(interaction);
@@ -77,32 +81,33 @@
return close(interaction);
}
case "createtranscript": {
- return createTranscript(interaction);
+ return createTranscript(int);
}
}
} else if (interaction.type === "APPLICATION_COMMAND_AUTOCOMPLETE") {
+ const int = (interaction as AutocompleteInteraction)
switch (
- `${interaction.commandName} ${interaction.options.getSubcommandGroup(
+ `${int.commandName} ${int.options.getSubcommandGroup(
false
- )} ${interaction.options.getSubcommand(false)}`
+ )} ${int.options.getSubcommand(false)}`
) {
case "tag null null": {
- return interaction.respond(
- getAutocomplete(interaction.options.getString("tag"), await tagAutocomplete(interaction))
+ return int.respond(
+ getAutocomplete(int.options.getString("tag") ?? "", await tagAutocomplete(int))
);
}
case "settings null stats": {
- return interaction.respond(generateStatsChannelAutocomplete(interaction.options.getString("name")));
+ return int.respond(generateStatsChannelAutocomplete(int.options.getString("name") ?? ""));
}
case "settings null welcome": {
- return interaction.respond(
- generateWelcomeMessageAutocomplete(interaction.options.getString("message"))
+ return int.respond(
+ generateWelcomeMessageAutocomplete(int.options.getString("message") ?? "")
);
}
}
}
}
-export async function callback(client, interaction) {
+export async function callback(_client: HaikuClient, interaction: Interaction) {
await interactionCreate(interaction);
}
diff --git a/src/events/inviteCreate.ts b/src/events/inviteCreate.ts
index 7b23bb2..fb35b7e 100644
--- a/src/events/inviteCreate.ts
+++ b/src/events/inviteCreate.ts
@@ -1,10 +1,15 @@
+import type { GuildAuditLogsEntry, Invite } from "discord.js";
+// @ts-expect-error
import humanizeDuration from "humanize-duration";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
+
export const event = "inviteCreate";
-export async function callback(client, invite) {
- const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = invite.client.logger;
+export async function callback(client: HaikuClient, invite: Invite) {
+ const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = client.logger;
const auditLog = await getAuditLog(invite.guild, "INVITE_CREATE");
- const audit = auditLog.entries.filter((entry) => entry.target.id === invite.id).first();
+ const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === invite.inviterId).first();
if (audit.executor.id === client.user.id) return;
const data = {
meta: {
@@ -23,7 +28,7 @@
created: entry(invite.createdTimestamp, renderDelta(invite.createdTimestamp))
},
hidden: {
- guild: invite.guild.id
+ guild: invite.guild!.id
}
};
log(data);
diff --git a/src/events/inviteDelete.ts b/src/events/inviteDelete.ts
index 2cd3bc5..b07893a 100644
--- a/src/events/inviteDelete.ts
+++ b/src/events/inviteDelete.ts
@@ -1,10 +1,15 @@
+import type { GuildAuditLogsEntry, Invite } from "discord.js";
+// @ts-expect-error
import humanizeDuration from "humanize-duration";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
+
export const event = "inviteDelete";
-export async function callback(client, invite) {
- const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = invite.client.logger;
+export async function callback(client: HaikuClient, invite: Invite) {
+ const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = client.logger;
const auditLog = await getAuditLog(invite.guild, "INVITE_DELETE");
- const audit = auditLog.entries.filter((entry) => entry.target.id === invite.id).first();
+ const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === invite.inviterId).first();
if (audit.executor.id === client.user.id) return;
const data = {
meta: {
@@ -23,7 +28,7 @@
deleted: entry(new Date().getTime(), renderDelta(new Date().getTime()))
},
hidden: {
- guild: invite.guild.id
+ guild: invite.guild!.id
}
};
log(data);
diff --git a/src/events/memberJoin.ts b/src/events/memberJoin.ts
index ebc2934..786c4ec 100644
--- a/src/events/memberJoin.ts
+++ b/src/events/memberJoin.ts
@@ -1,13 +1,15 @@
+import type { GuildMember } from "discord.js";
import { callback as statsChannelAdd } from "../reflex/statsChannelUpdate.js";
import { callback as welcome } from "../reflex/welcome.js";
-import client from "../utils/client.js";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
export const event = "guildMemberAdd";
-export async function callback(_, member) {
- welcome(_, member);
- statsChannelAdd(_, member);
- const { log, NucleusColors, entry, renderUser, renderDelta } = member.client.logger;
+export async function callback(client: HaikuClient, member: GuildMember) {
+ welcome(client, member);
+ statsChannelAdd(client, member);
+ const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
await client.database.history.create("join", member.guild.id, member.user, null, null);
const data = {
meta: {
diff --git a/src/events/memberLeave.ts b/src/events/memberLeave.ts
index 00f6d84..20845d5 100644
--- a/src/events/memberLeave.ts
+++ b/src/events/memberLeave.ts
@@ -1,14 +1,18 @@
+import type { GuildAuditLogsEntry, GuildMember } from "discord.js";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
+
import { purgeByUser } from "../actions/tickets/delete.js";
import { callback as statsChannelRemove } from "../reflex/statsChannelUpdate.js";
export const event = "guildMemberRemove";
-export async function callback(client, member) {
+export async function callback(client: HaikuClient, member: GuildMember) {
purgeByUser(member.id, member.guild);
await statsChannelRemove(client, member);
- const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = member.client.logger;
+ const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
const auditLog = await getAuditLog(member.guild, "MEMBER_KICK");
- const audit = auditLog.entries.filter((entry) => entry.target.id === member.id).first();
+ const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === member.id).first();
let type = "leave";
if (audit) {
if (audit.executor.id === client.user.id) return;
@@ -50,7 +54,7 @@
displayName: "Member Left",
calculateType: "guildMemberUpdate",
color: NucleusColors.red,
- emoji: "MEMBER." + (member.bot ? "BOT." : "") + "LEAVE",
+ emoji: "MEMBER." + (member.user.bot ? "BOT." : "") + "LEAVE",
timestamp: new Date().getTime()
},
list: {
diff --git a/src/events/messageCreate.ts b/src/events/messageCreate.ts
index f690885..d0f059c 100644
--- a/src/events/messageCreate.ts
+++ b/src/events/messageCreate.ts
@@ -5,7 +5,7 @@
import createLogException from "../utils/createLogException.js";
import getEmojiByName from "../utils/getEmojiByName.js";
import client from "../utils/client.js";
-import { callback as a } from "../reflex/statsChannelUpdate.js";
+import { callback as statsChannelUpdate } from "../reflex/statsChannelUpdate.js";
import { Message, ThreadChannel } from "discord.js";
export const event = "messageCreate";
@@ -15,7 +15,7 @@
if (message.author.bot) return;
if (message.channel.type === "DM") return;
try {
- await a(client, await message.guild.members.fetch(message.author.id));
+ await statsChannelUpdate(client, await message.guild.members.fetch(message.author.id));
} catch (e) {
console.log(e);
}
diff --git a/src/events/messageDelete.ts b/src/events/messageDelete.ts
index 3a72876..f2301e0 100644
--- a/src/events/messageDelete.ts
+++ b/src/events/messageDelete.ts
@@ -1,17 +1,20 @@
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
+import type { GuildAuditLogsEntry, Message } from "discord.js";
+
export const event = "messageDelete";
-export async function callback(client, message) {
+export async function callback(client: HaikuClient, message: Message) {
try {
if (message.author.id === client.user.id) return;
- if (client.noLog.includes(`${message.guild.id}/${message.channel.id}/${message.id}`)) return;
- const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } =
- message.channel.client.logger;
+ if (client.noLog.includes(`${message.id}/${message.channel.id}/${message.id}`)) return;
+ const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = client.logger;
const auditLog = await getAuditLog(message.guild, "MEMBER_BAN_ADD");
- const audit = auditLog.entries.filter((entry) => entry.target.id === message.author.id).first();
+ const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === message.author.id).first();
if (audit) {
if (audit.createdAt - 100 < new Date().getTime()) return;
}
- message.reference = message.reference || {};
+ const replyTo = message.reference;
let content = message.cleanContent;
content.replace("`", "\\`");
if (content.length > 256) content = content.substring(0, 253) + "...";
@@ -23,7 +26,7 @@
) ?? []
).length;
let attachmentJump = "";
- const config = (await client.database.guilds.read(message.guild.id)).logging.attachments.saved[
+ const config = (await client.database.guilds.read(message.guild!.id)).logging.attachments.saved[
message.channel.id + message.id
];
if (config) {
@@ -49,14 +52,14 @@
mentions: message.mentions.users.size,
attachments: entry(attachments, attachments + attachmentJump),
repliedTo: entry(
- message.reference.messageId || null,
- message.reference.messageId
- ? `[[Jump to message]](https://discord.com/channels/${message.guild.id}/${message.channel.id}/${message.reference.messageId})`
+ replyTo,
+ replyTo
+ ? `[[Jump to message]](https://discord.com/channels/${message.guild!.id}/${message.channel.id}/${replyTo.messageId})`
: "None"
)
},
hidden: {
- guild: message.channel.guild.id
+ guild: message.guild!.id
}
};
log(data);
diff --git a/src/events/messageEdit.ts b/src/events/messageEdit.ts
index 1470832..89e69de 100644
--- a/src/events/messageEdit.ts
+++ b/src/events/messageEdit.ts
@@ -1,10 +1,14 @@
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
+import type { Message, MessageReference } from "discord.js";
+
export const event = "messageUpdate";
-export async function callback(client, oldMessage, newMessage) {
+export async function callback(client: HaikuClient, oldMessage: Message, newMessage: Message) {
if (newMessage.author.id === client.user.id) return;
- const { log, NucleusColors, entry, renderUser, renderDelta, renderNumberDelta, renderChannel } =
- newMessage.channel.client.logger;
- newMessage.reference = newMessage.reference || {};
+ if (!newMessage.guild) return;
+ const { log, NucleusColors, entry, renderUser, renderDelta, renderNumberDelta, renderChannel } = client.logger;
+ const replyTo: MessageReference | null = newMessage.reference;
let newContent = newMessage.cleanContent.replaceAll("`", "‘");
let oldContent = oldMessage.cleanContent.replaceAll("`", "‘");
let attachmentJump = "";
@@ -37,8 +41,8 @@
renderDelta(new Date(newMessage.createdTimestamp))
),
published: entry(
- new Date(newMessage.editedTimestamp),
- renderDelta(new Date(newMessage.editedTimestamp))
+ new Date(newMessage.editedTimestamp!),
+ renderDelta(new Date(newMessage.editedTimestamp!))
),
mentions: renderNumberDelta(oldMessage.mentions.users.size, newMessage.mentions.users.size),
attachments: entry(
@@ -47,7 +51,7 @@
)
},
hidden: {
- guild: newMessage.channel.guild.id
+ guild: newMessage.guild.id
}
};
return log(data);
@@ -87,14 +91,14 @@
renderNumberDelta(oldMessage.attachments.size, newMessage.attachments.size) + attachmentJump
),
repliedTo: entry(
- newMessage.reference.messageId || null,
- newMessage.reference.messageId
- ? `[[Jump to message]](https://discord.com/channels/${newMessage.guild.id}/${newMessage.channel.id}/${newMessage.reference.messageId})`
+ replyTo,
+ replyTo
+ ? `[[Jump to message]](https://discord.com/channels/${newMessage.guild.id}/${newMessage.channel.id}/${replyTo.messageId})`
: "None"
)
},
hidden: {
- guild: newMessage.channel.guild.id
+ guild: newMessage.guild.id
}
};
log(data);
diff --git a/src/events/roleCreate.ts b/src/events/roleCreate.ts
index f1b0a91..e7a0a5c 100644
--- a/src/events/roleCreate.ts
+++ b/src/events/roleCreate.ts
@@ -1,10 +1,14 @@
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
+import type { GuildAuditLogsEntry, Role } from "discord.js";
+
export const event = "roleCreate";
-export async function callback(client, role) {
- const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderRole } = role.client.logger;
+export async function callback(client: HaikuClient, role: Role) {
+ const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderRole } = client.logger;
if (role.managed) return;
const auditLog = await getAuditLog(role.guild, "ROLE_CREATE");
- const audit = auditLog.entries.filter((entry) => entry.target.id === role.id).first();
+ const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === role.id).first();
if (audit.executor.id === client.user.id) return;
const data = {
meta: {
diff --git a/src/events/roleDelete.ts b/src/events/roleDelete.ts
index 4807e7d..348f211 100644
--- a/src/events/roleDelete.ts
+++ b/src/events/roleDelete.ts
@@ -1,12 +1,15 @@
import getEmojiByName from "../utils/getEmojiByName.js";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
+import type { GuildAuditLogsEntry, Role } from "discord.js";
export const event = "roleDelete";
-export async function callback(client, role) {
- const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = role.client.logger;
+export async function callback(client: HaikuClient, role: Role) {
+ const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
if (role.managed) return;
const auditLog = await getAuditLog(role.guild, "ROLE_DELETE");
- const audit = auditLog.entries.filter((entry) => entry.target.id === role.id).first();
+ const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === role.id).first();
if (audit.executor.id === client.user.id) return;
const data = {
meta: {
diff --git a/src/events/roleUpdate.ts b/src/events/roleUpdate.ts
index 53bbdee..9b75fc0 100644
--- a/src/events/roleUpdate.ts
+++ b/src/events/roleUpdate.ts
@@ -1,15 +1,18 @@
+import type { Role } from "discord.js";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku";
import getEmojiByName from "../utils/getEmojiByName.js";
export const event = "roleUpdate";
-export async function callback(client, or, nr) {
+export async function callback(client: HaikuClient, or: Role, nr: Role) {
const { getAuditLog, log, NucleusColors, entry, renderDelta, renderUser, renderRole } = client.logger;
const auditLog = await getAuditLog(nr.guild, "ROLE_UPDATE");
const audit = auditLog.entries.first();
if (audit.executor.id === client.user.id) return;
- const changes = {
+ const changes: Record<string, ReturnType<typeof entry>> = {
roleId: entry(nr.id, `\`${nr.id}\``),
role: entry(nr.id, renderRole(nr)),
edited: entry(new Date().getTime(), renderDelta(new Date().getTime())),
@@ -21,14 +24,14 @@
mentionable[1] = nr.mentionable ? `${getEmojiByName("CONTROL.TICK")} Yes` : `${getEmojiByName("CONTROL.CROSS")} No`;
hoist[0] = or.hoist ? `${getEmojiByName("CONTROL.TICK")} Yes` : `${getEmojiByName("CONTROL.CROSS")} No`;
hoist[1] = nr.hoist ? `${getEmojiByName("CONTROL.TICK")} Yes` : `${getEmojiByName("CONTROL.CROSS")} No`;
- if (or.name !== nr.name) changes.name = entry([or.name, nr.name], `${or.name} -> ${nr.name}`);
+ if (or.name !== nr.name) changes["name"] = entry([or.name, nr.name], `${or.name} -> ${nr.name}`);
if (or.position !== nr.position)
- changes.position = entry([or.position, nr.position], `${or.position} -> ${nr.position}`);
- if (or.hoist !== nr.hoist) changes.showInMemberList = entry([or.hoist, nr.hoist], `${hoist[0]} -> ${hoist[1]}`);
+ changes["position"] = entry([or.position, nr.position], `${or.position} -> ${nr.position}`);
+ if (or.hoist !== nr.hoist) changes["showInMemberList"] = entry([or.hoist, nr.hoist], `${hoist[0]} -> ${hoist[1]}`);
if (or.mentionable !== nr.mentionable)
- changes.mentionable = entry([or.mentionable, nr.mentionable], `${mentionable[0]} -> ${mentionable[1]}`);
+ changes["mentionable"] = entry([or.mentionable, nr.mentionable], `${mentionable[0]} -> ${mentionable[1]}`);
if (or.hexColor !== nr.hexColor)
- changes.color = entry([or.hexColor, nr.hexColor], `\`${or.hexColor}\` -> \`${nr.hexColor}\``);
+ changes["color"] = entry([or.hexColor, nr.hexColor], `\`${or.hexColor}\` -> \`${nr.hexColor}\``);
if (Object.keys(changes).length === 4) return;
diff --git a/src/events/stickerCreate.ts b/src/events/stickerCreate.ts
index c538bde..01d6c2c 100644
--- a/src/events/stickerCreate.ts
+++ b/src/events/stickerCreate.ts
@@ -1,9 +1,13 @@
-export const event = "stickerCreate";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku"
+import type { GuildAuditLogsEntry, Sticker } from "discord.js";
-export async function callback(client, emoji) {
- const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = emoji.client.logger;
+export const event = "stickerDelete";
+
+export async function callback(client: HaikuClient, emoji: Sticker) {
+ const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
const auditLog = await getAuditLog(emoji.guild, "STICKER_CREATE");
- const audit = auditLog.entries.filter((entry) => entry.target.id === emoji.id).first();
+ const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === emoji.id).first();
if (audit.executor.id === client.user.id) return;
const data = {
meta: {
@@ -21,7 +25,7 @@
created: entry(emoji.createdTimestamp, renderDelta(emoji.createdTimestamp))
},
hidden: {
- guild: emoji.guild.id
+ guild: emoji.guild!.id
}
};
log(data);
diff --git a/src/events/stickerDelete.ts b/src/events/stickerDelete.ts
index 7ac17ce..c9b3fab 100644
--- a/src/events/stickerDelete.ts
+++ b/src/events/stickerDelete.ts
@@ -1,9 +1,13 @@
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku"
+import type { GuildAuditLogsEntry, Sticker } from "discord.js";
+
export const event = "stickerDelete";
-export async function callback(client, emoji) {
- const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = emoji.client.logger;
+export async function callback(client: HaikuClient, emoji: Sticker) {
+ const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
const auditLog = await getAuditLog(emoji.guild, "STICKER_DELETE");
- const audit = auditLog.entries.filter((entry) => entry.target.id === emoji.id).first();
+ const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === emoji.id).first();
if (audit.executor.id === client.user.id) return;
const data = {
meta: {
@@ -22,7 +26,7 @@
deleted: entry(audit.createdTimestamp, renderDelta(audit.createdTimestamp))
},
hidden: {
- guild: emoji.guild.id
+ guild: emoji.guild!.id
}
};
log(data);
diff --git a/src/events/stickerUpdate.ts b/src/events/stickerUpdate.ts
index 662f981..c6e3b6e 100644
--- a/src/events/stickerUpdate.ts
+++ b/src/events/stickerUpdate.ts
@@ -1,17 +1,21 @@
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku"
+import type { Sticker } from "discord.js";
+
export const event = "stickerUpdate";
-export async function callback(client, oe, ne) {
+export async function callback(client: HaikuClient, oe: Sticker, ne: Sticker) {
const { getAuditLog, log, NucleusColors, entry, renderDelta, renderUser } = client.logger;
if (oe.name === ne.name) return;
- const auditLog = await getAuditLog(ne.guild, "EMOJI_UPDATE");
+ const auditLog = await getAuditLog(ne.guild, "STICKER_UPDATE");
const audit = auditLog.entries.first();
if (audit.executor.id === client.user.id) return;
const changes = {
stickerId: entry(ne.id, `\`${ne.id}\``),
edited: entry(ne.createdTimestamp, renderDelta(ne.createdTimestamp)),
- editedBy: entry(audit.executor.id, renderUser((await ne.guild.members.fetch(audit.executor.id)).user)),
+ 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}:\``)
};
const data = {
@@ -25,7 +29,7 @@
},
list: changes,
hidden: {
- guild: ne.guild.id
+ guild: ne.guild!.id
}
};
log(data);
diff --git a/src/events/threadCreate.ts b/src/events/threadCreate.ts
index da3cbae..e8849c9 100644
--- a/src/events/threadCreate.ts
+++ b/src/events/threadCreate.ts
@@ -1,11 +1,19 @@
+import type { GuildAuditLogsEntry, ThreadChannel } from "discord.js";
+// @ts-expect-error
import humanizeDuration from "humanize-duration";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku"
export const event = "threadCreate";
-export async function callback(client, thread) {
- const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = thread.client.logger;
+export async function callback(client: HaikuClient, thread: ThreadChannel) {
+ const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = client.logger;
const auditLog = await getAuditLog(thread.guild, "THREAD_CREATE");
- const audit = auditLog.entries.filter((entry) => entry.target.id === thread.id).first();
+ const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === thread.id).first();
if (audit.executor.id === client.user.id) return;
+ const category = thread.parent ? entry(
+ thread.parent.parent ? thread.parent.parent.name : "None",
+ thread.parent.parent ? renderChannel(thread.parent.parent) : "None"
+ ) : entry(null, "Uncategorised")
const data = {
meta: {
type: "channelCreate",
@@ -19,13 +27,10 @@
threadId: entry(thread.id, `\`${thread.id}\``),
name: entry(thread.name, renderChannel(thread)),
parentChannel: entry(thread.parentId, renderChannel(thread.parent)),
- category: entry(
- thread.parent.parent ? thread.parent.parent.name : "None",
- thread.parent.parent ? renderChannel(thread.parent.parent) : "None"
- ),
+ category: category,
autoArchiveDuration: entry(
thread.autoArchiveDuration,
- humanizeDuration(thread.autoArchiveDuration * 60 * 1000, {
+ humanizeDuration((thread.autoArchiveDuration ?? 0) * 60 * 1000, {
round: true
})
),
diff --git a/src/events/threadDelete.ts b/src/events/threadDelete.ts
index bfae11a..1908b7f 100644
--- a/src/events/threadDelete.ts
+++ b/src/events/threadDelete.ts
@@ -1,11 +1,19 @@
+import type { GuildAuditLogsEntry, ThreadChannel } from "discord.js";
+// @ts-expect-error
import humanizeDuration from "humanize-duration";
+// @ts-expect-error
+import type { HaikuClient } from "jshaiku"
export const event = "threadDelete";
-export async function callback(client, thread) {
- const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = thread.client.logger;
+export async function callback(client: HaikuClient, thread: ThreadChannel) {
+ const { getAuditLog, log, NucleusColors, entry, renderUser, renderDelta, renderChannel } = client.logger;
const auditLog = await getAuditLog(thread.guild, "THREAD_UPDATE");
- const audit = auditLog.entries.filter((entry) => entry.target.id === thread.id).first();
+ const audit = auditLog.entries.filter((entry: GuildAuditLogsEntry) => entry.target!.id === thread.id).first();
if (audit.executor.id === client.user.id) return;
+ const category = thread.parent ? entry(
+ thread.parent.parent ? thread.parent.parent.name : "None",
+ thread.parent.parent ? renderChannel(thread.parent.parent) : "None"
+ ) : entry(null, "Uncategorised")
const data = {
meta: {
type: "channelDelete",
@@ -18,14 +26,11 @@
list: {
threadId: entry(thread.id, `\`${thread.id}\``),
name: entry(thread.name, thread.name),
- parentChannel: entry(thread.parentId, renderChannel(thread.parent)),
- category: entry(
- thread.parent.parent ? thread.parent.parent.name : "None",
- thread.parent.parent ? renderChannel(thread.parent.parent) : "None"
- ),
+ parentChannel: entry(thread.parentId, thread.parent ? renderChannel(thread.parent) : "*None*"),
+ category: category,
autoArchiveDuration: entry(
thread.autoArchiveDuration,
- humanizeDuration(thread.autoArchiveDuration * 60 * 1000, {
+ humanizeDuration((thread.autoArchiveDuration ?? 0) * 60 * 1000, {
round: true
})
),
diff --git a/src/premium/createTranscript.ts b/src/premium/createTranscript.ts
index c60bf23..57720bf 100644
--- a/src/premium/createTranscript.ts
+++ b/src/premium/createTranscript.ts
@@ -1,4 +1,4 @@
-import { CommandInteraction, GuildMember, Message, MessageActionRow, MessageButton, TextChannel } from "discord.js";
+import { CommandInteraction, GuildMember, Message, MessageActionRow, MessageButton, MessageComponentInteraction, TextChannel } from "discord.js";
import EmojiEmbed from "../utils/generateEmojiEmbed.js";
import getEmojiByName from "../utils/getEmojiByName.js";
import { PasteClient, Publicity, ExpireDate } from "pastebin-api";
@@ -7,7 +7,7 @@
const pbClient = new PasteClient(config.pastebinApiKey);
-export default async function (interaction: CommandInteraction) {
+export default async function (interaction: CommandInteraction | MessageComponentInteraction) {
if (interaction.channel === null) return;
if (!(interaction.channel instanceof TextChannel)) return;
const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
diff --git a/src/reflex/statsChannelUpdate.ts b/src/reflex/statsChannelUpdate.ts
index 644a75f..657e90d 100644
--- a/src/reflex/statsChannelUpdate.ts
+++ b/src/reflex/statsChannelUpdate.ts
@@ -1,3 +1,4 @@
+import type { Guild, User } from 'discord.js';
// @ts-expect-error
import type { HaikuClient } from "jshaiku";
import type { GuildMember } from "discord.js";
@@ -9,28 +10,29 @@
name: string;
}
-export async function callback(client: HaikuClient, member: GuildMember) {
- const guild = await client.guilds.fetch(member.guild.id);
+export async function callback(client: HaikuClient, member?: GuildMember, guild?: Guild, user?: User) {
+ if (!member && !guild) return;
+ guild = await client.guilds.fetch(member ? member.guild.id : guild!.id);
+ if (!guild) return;
+ user = user ?? member!.user
const config = await client.database.guilds.read(guild.id);
Object.entries(config.getKey("stats")).forEach(async ([channel, props]) => {
if ((props as PropSchema).enabled) {
let string = (props as PropSchema).name;
if (!string) return;
- string = await convertCurlyBracketString(string, member.id, member.displayName, guild.name, guild.members);
+ string = await convertCurlyBracketString(string, user!.id, user!.username, guild!.name, guild!.members);
let fetchedChannel;
try {
- fetchedChannel = await guild.channels.fetch(channel);
+ fetchedChannel = await guild!.channels.fetch(channel);
} catch (e) {
fetchedChannel = null;
}
if (!fetchedChannel) {
const deleted = config.getKey("stats")[channel];
- console.log(`stats.${channel}`);
- console.log(guild.id);
- await client.database.guilds.write(guild.id, null, `stats.${channel}`);
+ await client.database.guilds.write(guild!.id, null, `stats.${channel}`);
return singleNotify(
"statsChannelDeleted",
- guild.id,
+ 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" +
`The channels name was: ${deleted.name}`,
"Critical"
diff --git a/src/reflex/verify.ts b/src/reflex/verify.ts
index 37f8d6c..f28b291 100644
--- a/src/reflex/verify.ts
+++ b/src/reflex/verify.ts
@@ -1,5 +1,5 @@
import { LoadingEmbed } from "./../utils/defaultEmbeds.js";
-import Discord, { CommandInteraction, GuildMember, Interaction, Permissions, Role } from "discord.js";
+import Discord, { CommandInteraction, GuildMember, Interaction, MessageComponentInteraction, Permissions, Role } from "discord.js";
import EmojiEmbed from "../utils/generateEmojiEmbed.js";
import fetch from "node-fetch";
import { TestString, NSFWCheck } from "./scanners.js";
@@ -21,7 +21,7 @@
return "\n\n" + createPageIndicator(5, i);
}
-export default async function (interaction: CommandInteraction) {
+export default async function (interaction: CommandInteraction | MessageComponentInteraction) {
const verify = client.verify;
await interaction.reply({
embeds: LoadingEmbed,