Update to latest (#44)
All commits already reviewed by PineappleFan
diff --git a/.eslintignore b/.eslintignore
index d7b2f7f..a753b6e 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -1 +1,2 @@
-ClicksMigratingProblems/**/*
\ No newline at end of file
+ClicksMigratingProblems/**/*
+src/reflex/nsfwjs/**/*
diff --git a/.eslintrc.json b/.eslintrc.json
index 165e759..7db4826 100644
--- a/.eslintrc.json
+++ b/.eslintrc.json
@@ -23,6 +23,8 @@
"caughtErrorsIgnorePattern": "^_"
}
],
- "@typescript-eslint/no-explicit-any": "error"
+ "@typescript-eslint/no-explicit-any": "error",
+ "@typescript-eslint/no-misused-promises": "error",
+ "@typescript-eslint/no-floating-promises": "error"
}
}
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 2780970..68e5d1f 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -4,7 +4,6 @@
title: "[BUG]"
labels: "\U0001F41B Bug"
assignees: PineaFan
-
---
[Describe the bug in one line, keep it concise]
@@ -13,6 +12,7 @@
The name of the command (e.g. /settings filters) or the feature (e.g. Message edit logs)
**Steps to reproduce:**
+
1. Run ...
2. Press ...
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index 0357118..a8178cb 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -4,7 +4,6 @@
title: "[FEATURE]"
labels: "✓ Feature"
assignees: PineaFan
-
---
**Is this related to a bug? If so, briefly explain the bug below**
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index c1da375..325f0d8 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -22,6 +22,8 @@
with:
node-version: 19.x
- run: yarn install --immutable
+ - name: Show versions
+ run: yarn run versions
- name: Compile
run: yarn build
- name: Run prettier and eslint
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..da4b2df
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,4 @@
+[submodule "src/reflex/nsfwjs"]
+ path = src/reflex/nsfwjs
+ url = https://github.com/infinitered/nsfwjs
+ shallow = true
diff --git a/.prettierignore b/.prettierignore
index 6deb598..1d61cc6 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -21,3 +21,4 @@
ClicksMigratingProblems/oldData copy/
.direnv/
+src/reflex/nsfwjs/**/*
diff --git a/flake.nix b/flake.nix
index c11ea5f..bdbd76c 100644
--- a/flake.nix
+++ b/flake.nix
@@ -8,7 +8,7 @@
pkgs = nixpkgs.legacyPackages.${system};
in {
devShells.default = pkgs.mkShell {
- packages = [ pkgs.yarn pkgs.nodejs-19_x pkgs.typescript pkgs.act ];
+ packages = [ pkgs.nodejs-19_x pkgs.nodePackages_latest.yarn ];
};
});
}
diff --git a/package.json b/package.json
index 629c6dd..c619c61 100644
--- a/package.json
+++ b/package.json
@@ -2,9 +2,10 @@
"dependencies": {
"@hokify/agenda": "^6.2.12",
"@tensorflow/tfjs": "^3.18.0",
- "@tensorflow/tfjs-node": "^4.2.0",
+ "@tensorflow/tfjs-node": "^3.18.0",
"@total-typescript/ts-reset": "^0.3.7",
"@tsconfig/node18-strictest-esm": "^1.0.0",
+ "@types/gm": "^1.25.0",
"@types/node": "^18.14.6",
"@ungap/structured-clone": "^1.0.1",
"agenda": "^4.3.0",
@@ -15,6 +16,8 @@
"eslint": "^8.21.0",
"express": "^4.18.1",
"fuse.js": "^6.6.2",
+ "gifencoder": "^2.0.1",
+ "gm": "^1.25.0",
"humanize-duration": "^3.27.1",
"immutable": "^4.1.0",
"lodash": "^4.17.21",
@@ -26,22 +29,28 @@
"structured-clone": "^0.2.2",
"systeminformation": "^5.17.3"
},
+ "resolutions": {
+ "discord-api-types": "0.37.23"
+ },
"name": "nucleus",
"version": "0.0.1",
"description": "Nucleus: The core of your server",
"main": "dist/index.js",
"scripts": {
- "build": "tsc",
+ "build": "tsc && yarn copy-files",
+ "copy-files": "copyfiles -u 1 src/reflex/nsfwjs/example/nsfw_demo/public/model/**/* dist/",
"start": "node --experimental-json-modules --enable-source-maps dist/index.js",
- "dev": "rm -rf dist && eslint src --fix && tsc && node --experimental-json-modules --enable-source-maps dist/index.js",
- "force-dev": "clear; rm -rf dist; tsc-suppress && node --experimental-json-modules --enable-source-maps dist/index.js",
+ "dev": "rm -rf dist && eslint src --fix && yarn build && node --experimental-json-modules --enable-source-maps dist/index.js",
+ "force-dev": "clear; rm -rf dist; tsc-suppress && yarn copy-files && node --experimental-json-modules --enable-source-maps dist/index.js",
"lint": "echo 'Style checking...'; prettier --check .; echo 'Linting...'; eslint src; echo 'To auto-fix everything possible, please run `yarn lint-fix`'; true",
+ "lint-no-stylecheck": "echo 'Linting...'; eslint src; echo 'A full lint and style check is required for PRs to be accepted. Please run `yarn lint` before committing'; true",
"lint-fix": "echo 'Fixing eslint issues...'; eslint src --fix; echo 'Reformatting...'; prettier --write --loglevel warn --cache .; true",
"lint-list": "echo 'Style checking...'; prettier --check .; echo 'Linting...'; eslint src; echo 'To view errors in more detail, please run `yarn lint`'; true",
"lint-ci": "echo 'Style checking...' && prettier --check . && echo 'Linting...' && eslint src",
"setup": "node Installer.js",
"win-force-build": "clear | rm -r dist | tsc-suppress",
- "audit-fix": "yarn-audit-fix"
+ "audit-fix": "yarn-audit-fix",
+ "versions": "yarn versions && yarn list && node --version"
},
"repository": {
"type": "git",
@@ -61,9 +70,11 @@
"type": "module",
"devDependencies": {
"@types/clamscan": "^2.0.4",
+ "@types/gifencoder": "^2.0.1",
"@types/lodash": "^4.14.191",
"@typescript-eslint/eslint-plugin": "^5.32.0",
"@typescript-eslint/parser": "^5.32.0",
+ "copyfiles": "^2.4.1",
"eslint-config-prettier": "^8.5.0",
"prettier": "^2.7.1",
"prettier-eslint": "^15.0.1",
diff --git a/src/actions/createModActionTicket.ts b/src/actions/createModActionTicket.ts
index ea85255..6b34739 100644
--- a/src/actions/createModActionTicket.ts
+++ b/src/actions/createModActionTicket.ts
@@ -115,8 +115,8 @@
type: Discord.ChannelType.PrivateThread,
reason: "Creating ticket"
})) as Discord.PrivateThreadChannel;
- c.members.add(user.id);
- c.members.add(createdBy.id);
+ await c.members.add(user.id);
+ await c.members.add(createdBy.id);
try {
await c.send({
content:
@@ -174,7 +174,7 @@
guild: guild.id
}
};
- log(data);
+ await log(data);
return c.id;
}
diff --git a/src/actions/roleMenu.ts b/src/actions/roleMenu.ts
index 9796b28..6997393 100644
--- a/src/actions/roleMenu.ts
+++ b/src/actions/roleMenu.ts
@@ -175,7 +175,7 @@
console.log(e);
return;
}
- component.deferUpdate();
+ await component.deferUpdate();
}
}
@@ -246,7 +246,7 @@
console.log(e);
return;
}
- component.deferUpdate();
+ await component.deferUpdate();
if (component.customId === "back") {
page = Math.max(0, page - 1);
} else if (component.customId === "next") {
diff --git a/src/actions/tickets/create.ts b/src/actions/tickets/create.ts
index 26236d8..8dafe52 100644
--- a/src/actions/tickets/create.ts
+++ b/src/actions/tickets/create.ts
@@ -155,7 +155,7 @@
new ActionRowBuilder<ButtonBuilder>().addComponents(formattedTicketTypes.slice(i, i + 5))
);
}
- component.update({
+ await component.update({
embeds: [
new EmojiEmbed()
.setTitle("Create Ticket")
@@ -280,7 +280,7 @@
type: Discord.ChannelType.PrivateThread,
reason: "Creating ticket"
})) as Discord.PrivateThreadChannel;
- c.members.add(interaction.member!.user.id);
+ await c.members.add(interaction.member!.user.id);
try {
await c.send({
content:
@@ -357,7 +357,7 @@
guild: interaction.guild.id
}
};
- log(data);
+ await log(data);
await interaction.editReply({
embeds: [
new EmojiEmbed()
diff --git a/src/actions/tickets/delete.ts b/src/actions/tickets/delete.ts
index 1c1e464..769bc32 100644
--- a/src/actions/tickets/delete.ts
+++ b/src/actions/tickets/delete.ts
@@ -78,7 +78,7 @@
guild: interaction.guild.id
}
};
- log(data);
+ await log(data);
await channel.delete();
} else if (status === "Active") {
@@ -86,12 +86,12 @@
// Archive the ticket
await interaction.channel.fetch();
if (channel.isThread()) {
- channel.setName(`${channel.name.replace("Active", "Archived")}`);
- channel.members.remove(channel.name.split(" - ")[1]!);
+ await channel.setName(`${channel.name.replace("Active", "Archived")}`);
+ await channel.members.remove(channel.name.split(" - ")[1]!);
} else {
- channel.setTopic(`${(channel.topic ?? "").replace("Active", "Archived")}`);
+ await channel.setTopic(`${(channel.topic ?? "").replace("Active", "Archived")}`);
if (!channel.topic!.includes("Archived")) {
- channel.setTopic("0 Archived");
+ await channel.setTopic("0 Archived");
}
await channel.permissionOverwrites.delete(channel.topic!.split(" ")[0]!);
}
@@ -153,7 +153,7 @@
guild: interaction.guild.id
}
};
- log(data);
+ await log(data);
}
return;
}
@@ -170,28 +170,28 @@
if (tickets.type === Discord.ChannelType.GuildCategory) {
// For channels, the topic is the user ID, then the word Active
const category = tickets as Discord.CategoryChannel;
- category.children.cache.forEach((element) => {
+ for (const [_id, element] of category.children.cache) {
if (!(element.type === Discord.ChannelType.GuildText)) return;
if (!((element as Discord.TextChannel).topic ?? "").includes(member)) return;
try {
- element.delete();
+ await element.delete();
deleted++;
} catch (e) {
console.error(e);
}
- });
+ }
} else {
// For threads, the name is the users name, id, then the word Active
const channel = tickets as Discord.TextChannel;
- channel.threads.cache.forEach((element: Discord.ThreadChannel) => {
+ for (const [_id, element] of channel.threads.cache) {
if (!element.name.includes(member)) return;
try {
- element.delete();
+ await element.delete();
deleted++;
} catch (e) {
console.error(e);
}
- });
+ }
}
if (!deleted) return;
const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
@@ -214,7 +214,7 @@
guild: guild
}
};
- log(data);
+ await log(data);
}
export { purgeByUser };
diff --git a/src/api/index.ts b/src/api/index.ts
index 4b849f1..41f281d 100644
--- a/src/api/index.ts
+++ b/src/api/index.ts
@@ -35,7 +35,7 @@
await member.roles.add(client.verify[code]!.rID);
const interaction = client.verify[code]!.interaction;
- interaction.editReply({
+ await interaction.editReply({
embeds: [
new EmojiEmbed()
.setTitle("Verify")
@@ -70,7 +70,7 @@
guild: guild.id
}
};
- log(data);
+ await log(data);
} catch {
res.sendStatus(500);
}
@@ -80,12 +80,12 @@
}
});
- app.get("/verify/:code", jsonParser, function (req: express.Request, res: express.Response) {
+ app.get("/verify/:code", jsonParser, async function (req: express.Request, res: express.Response) {
const code = req.params.code;
if (client.verify[code]) {
try {
const interaction = client.verify[code]!.interaction;
- interaction.editReply({
+ await interaction.editReply({
embeds: [
new EmojiEmbed()
.setTitle("Verify")
@@ -124,12 +124,12 @@
}
});
- app.get("/rolemenu/:code", jsonParser, function (req: express.Request, res: express.Response) {
+ app.get("/rolemenu/:code", jsonParser, async function (req: express.Request, res: express.Response) {
const code = req.params.code;
if (client.roleMenu[code] !== undefined) {
try {
const interaction = client.roleMenu[code]!.interaction;
- interaction.editReply({
+ await interaction.editReply({
embeds: [
new EmojiEmbed()
.setTitle("Roles")
diff --git a/src/commands/mod/about.ts b/src/commands/mod/about.ts
index 8736054..6f8b74c 100644
--- a/src/commands/mod/about.ts
+++ b/src/commands/mod/about.ts
@@ -266,7 +266,7 @@
}
});
} catch (e) {
- interaction.editReply({
+ await interaction.editReply({
embeds: [
new EmojiEmbed()
.setEmoji("MEMBER.JOIN")
diff --git a/src/commands/mod/ban.ts b/src/commands/mod/ban.ts
index 91e074d..41d1252 100644
--- a/src/commands/mod/ban.ts
+++ b/src/commands/mod/ban.ts
@@ -126,7 +126,7 @@
dmSent = false;
}
try {
- member.ban({
+ await member.ban({
deleteMessageSeconds: deleteDays * 24 * 60 * 60,
reason: reason ?? "*No reason provided*"
});
@@ -159,7 +159,7 @@
guild: interaction.guild.id
}
};
- log(data);
+ await log(data);
} catch {
await interaction.editReply({
embeds: [
diff --git a/src/commands/mod/kick.ts b/src/commands/mod/kick.ts
index 4ef78c8..f9242fe 100644
--- a/src/commands/mod/kick.ts
+++ b/src/commands/mod/kick.ts
@@ -114,7 +114,7 @@
dmSent = false;
}
try {
- member.kick(reason || "No reason provided");
+ await member.kick(reason || "No reason provided");
await client.database.history.create("kick", interaction.guild.id, member.user, interaction.user, reason);
const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
const timeInServer = member.joinedTimestamp
@@ -157,7 +157,7 @@
data.list.joined = entry(member.joinedTimestamp.toString(), renderDelta(member.joinedTimestamp));
}
await client.database.history.create("kick", interaction.guild.id, member.user, interaction.user, reason);
- log(data);
+ await log(data);
} catch {
await interaction.editReply({
embeds: [
diff --git a/src/commands/mod/mute.ts b/src/commands/mod/mute.ts
index 2266a1a..0cfe660 100644
--- a/src/commands/mod/mute.ts
+++ b/src/commands/mod/mute.ts
@@ -132,7 +132,7 @@
} catch {
return;
}
- component.deferUpdate();
+ await component.deferUpdate();
if (component.customId === "cancel")
return interaction.editReply({
embeds: [
@@ -389,7 +389,7 @@
guild: interaction.guild.id
}
};
- log(data);
+ await log(data);
const failed = !status.dm && notify;
await interaction.editReply({
embeds: [
diff --git a/src/commands/mod/nick.ts b/src/commands/mod/nick.ts
index cfdcf47..a8d4ab8 100644
--- a/src/commands/mod/nick.ts
+++ b/src/commands/mod/nick.ts
@@ -153,7 +153,7 @@
let before: string | null;
try {
before = member.nickname;
- member.setNickname(newNickname ?? null, "Nucleus Nickname command");
+ await member.setNickname(newNickname ?? null, "Nucleus Nickname command");
await client.database.history.create(
"nickname",
interaction.guild!.id,
@@ -202,7 +202,7 @@
guild: interaction.guild!.id
}
};
- log(data);
+ await log(data);
const failed = !dmSent && notify;
await interaction.editReply({
embeds: [
diff --git a/src/commands/mod/purge.ts b/src/commands/mod/purge.ts
index dadab04..1170c33 100644
--- a/src/commands/mod/purge.ts
+++ b/src/commands/mod/purge.ts
@@ -100,7 +100,7 @@
})) as Discord.Message;
let component;
try {
- component = m.awaitMessageComponent({
+ component = await m.awaitMessageComponent({
filter: (i) => i.user.id === interaction.user.id && i.channel!.id === interaction.channel!.id,
time: 300000
});
@@ -108,12 +108,12 @@
timedOut = true;
continue;
}
- (await component).deferUpdate();
- if ((await component).customId === "done") {
+ await component.deferUpdate();
+ if (component.customId === "done") {
amountSelected = true;
continue;
}
- const amount = parseInt((await component).customId);
+ const amount = parseInt(component.customId);
let messages: Discord.Message[] = [];
await (interaction.channel as TextChannel).messages.fetch({ limit: amount }).then(async (ms) => {
@@ -167,7 +167,7 @@
guild: interaction.guild.id
}
};
- log(data);
+ await log(data);
const newOut = await client.database.transcripts.createTranscript(
"purge",
deleted,
@@ -209,7 +209,7 @@
return;
}
if (component.customId === "download") {
- interaction.editReply({
+ await interaction.editReply({
embeds: [
new EmojiEmbed()
.setEmoji("CHANNEL.PURGE.GREEN")
@@ -221,7 +221,7 @@
files: [attachmentObject]
});
} else {
- interaction.editReply({
+ await interaction.editReply({
embeds: [
new EmojiEmbed()
.setEmoji("CHANNEL.PURGE.GREEN")
@@ -261,12 +261,12 @@
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);
+ 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) {
@@ -326,7 +326,7 @@
guild: interaction.guild.id
}
};
- log(data);
+ await log(data);
const messageArray: Message[] = messages
.filter(
(message) =>
diff --git a/src/commands/mod/slowmode.ts b/src/commands/mod/slowmode.ts
index ba88c00..8fe9f16 100644
--- a/src/commands/mod/slowmode.ts
+++ b/src/commands/mod/slowmode.ts
@@ -51,7 +51,7 @@
.send();
if (confirmation.cancelled || !confirmation.success) return;
try {
- (interaction.channel as TextChannel).setRateLimitPerUser(time);
+ await (interaction.channel as TextChannel).setRateLimitPerUser(time);
} catch (e) {
await interaction.editReply({
embeds: [
diff --git a/src/commands/mod/softban.ts b/src/commands/mod/softban.ts
index cd03d1a..984bb6b 100644
--- a/src/commands/mod/softban.ts
+++ b/src/commands/mod/softban.ts
@@ -128,7 +128,7 @@
try {
const member = interaction.options.getMember("user") as GuildMember;
const days: number = (interaction.options.get("delete")?.value as number | null) ?? 0;
- member.ban({
+ await member.ban({
deleteMessageSeconds: days * 24 * 60 * 60,
reason: reason ?? "*No reason provided*"
});
@@ -162,7 +162,7 @@
guild: interaction.guild.id
}
};
- log(data);
+ await log(data);
} catch {
await interaction.editReply({
embeds: [
diff --git a/src/commands/mod/unban.ts b/src/commands/mod/unban.ts
index 7397414..1c1a877 100644
--- a/src/commands/mod/unban.ts
+++ b/src/commands/mod/unban.ts
@@ -76,7 +76,7 @@
guild: interaction.guild.id
}
};
- log(data);
+ await log(data);
} catch {
await interaction.editReply({
embeds: [
diff --git a/src/commands/mod/unmute.ts b/src/commands/mod/unmute.ts
index f248a3b..516bd39 100644
--- a/src/commands/mod/unmute.ts
+++ b/src/commands/mod/unmute.ts
@@ -76,7 +76,7 @@
}
const member = interaction.options.getMember("user") as GuildMember;
try {
- member.timeout(0, reason ?? "*No reason provided*");
+ await member.timeout(0, reason ?? "*No reason provided*");
} catch {
await interaction.editReply({
embeds: [
@@ -122,7 +122,7 @@
guild: interaction.guild.id
}
};
- log(data);
+ await log(data);
const failed = !dmSent && notify;
await interaction.editReply({
embeds: [
diff --git a/src/commands/mod/warn.ts b/src/commands/mod/warn.ts
index 232219b..0424d48 100644
--- a/src/commands/mod/warn.ts
+++ b/src/commands/mod/warn.ts
@@ -153,7 +153,7 @@
}
};
await client.database.history.create("warn", interaction.guild.id, member.user, interaction.user, reason);
- log(data);
+ await log(data);
const failed = !dmSent && notify;
if (!failed) {
await interaction.editReply({
diff --git a/src/commands/nucleus/guide.ts b/src/commands/nucleus/guide.ts
index d05e265..c95e78c 100644
--- a/src/commands/nucleus/guide.ts
+++ b/src/commands/nucleus/guide.ts
@@ -6,7 +6,7 @@
builder.setName("guide").setDescription("Shows the welcome guide for the bot");
const callback = async (interaction: CommandInteraction) => {
- guide(interaction.guild!, interaction);
+ await guide(interaction.guild!, interaction);
};
export { command };
diff --git a/src/commands/nucleus/invite.ts b/src/commands/nucleus/invite.ts
index 9f78cc5..0307c68 100644
--- a/src/commands/nucleus/invite.ts
+++ b/src/commands/nucleus/invite.ts
@@ -7,7 +7,7 @@
builder.setName("invite").setDescription("Invites Nucleus to your server");
const callback = async (interaction: CommandInteraction): Promise<void> => {
- interaction.reply({
+ await interaction.reply({
embeds: [
new EmojiEmbed()
.setTitle("Invite")
diff --git a/src/commands/nucleus/ping.ts b/src/commands/nucleus/ping.ts
index 62988bb..8a9ca87 100644
--- a/src/commands/nucleus/ping.ts
+++ b/src/commands/nucleus/ping.ts
@@ -13,7 +13,7 @@
const initial = Date.now();
await interaction.reply({ embeds: LoadingEmbed, ephemeral: true });
const ping = Date.now() - initial;
- interaction.editReply({
+ await interaction.editReply({
embeds: [
new EmojiEmbed()
.setTitle("Ping")
diff --git a/src/commands/nucleus/premium.ts b/src/commands/nucleus/premium.ts
index 4effb23..f544045 100644
--- a/src/commands/nucleus/premium.ts
+++ b/src/commands/nucleus/premium.ts
@@ -106,7 +106,7 @@
const member = await (await interaction.client.guilds.fetch("684492926528651336")).members
.fetch(interaction.user.id)
.catch(() => {
- interaction.editReply({
+ void interaction.editReply({
embeds: [
new EmojiEmbed()
.setTitle("Premium")
@@ -197,7 +197,7 @@
if ((dbMember?.appliesTo.length ?? 0) > 0)
userPremiumServers = "\nIf you want to remove premium from a server, run this command in your DMs with me.";
- interaction.editReply({
+ await interaction.editReply({
embeds: [
new EmojiEmbed()
.setTitle("Premium")
@@ -216,10 +216,10 @@
} catch (e) {
return;
}
- i.deferUpdate();
+ await i.deferUpdate();
const guild = i.guild!;
if (count - appliesTo.length <= 0) {
- interaction.editReply({
+ await interaction.editReply({
embeds: [
new EmojiEmbed()
.setTitle("Premium")
@@ -235,7 +235,7 @@
});
} else {
await client.database.premium.addPremium(interaction.user.id, guild.id);
- interaction.editReply({
+ await interaction.editReply({
embeds: [
new EmojiEmbed()
.setTitle("Premium")
diff --git a/src/commands/nucleus/stats.ts b/src/commands/nucleus/stats.ts
index 294ee27..a7f9b3b 100644
--- a/src/commands/nucleus/stats.ts
+++ b/src/commands/nucleus/stats.ts
@@ -35,7 +35,7 @@
fetchReply: true
});
if (config.owners.includes(interaction.user.id)) {
- interaction.editReply({
+ await interaction.editReply({
embeds: [
new EmojiEmbed()
.setTitle("Admin")
@@ -96,7 +96,7 @@
} catch {
return;
}
- out.deferUpdate();
+ await out.deferUpdate();
const GuildID = out.fields.getTextInputValue("guildID");
if (!client.guilds.cache.has(GuildID)) {
await interaction.editReply({
@@ -126,7 +126,7 @@
} catch {
return;
}
- i.deferUpdate();
+ await i.deferUpdate();
const guild = (await client.guilds.fetch(GuildID)) as Guild | null;
if (!guild) {
await interaction.editReply({
diff --git a/src/commands/privacy.ts b/src/commands/privacy.ts
index 590e866..3a671ed 100644
--- a/src/commands/privacy.ts
+++ b/src/commands/privacy.ts
@@ -214,7 +214,7 @@
const em = new Discord.EmbedBuilder(pages[page]!.embed);
em.setDescription(em.data.description + "\n\n" + createPageIndicator(pages.length, page));
em.setFooter({ text: "Message closed" });
- interaction.editReply({ embeds: [em], components: [] });
+ await interaction.editReply({ embeds: [em], components: [] });
return;
}
}
diff --git a/src/commands/server/about.ts b/src/commands/server/about.ts
index 815b9e6..1857653 100644
--- a/src/commands/server/about.ts
+++ b/src/commands/server/about.ts
@@ -32,7 +32,7 @@
const callback = async (interaction: CommandInteraction): Promise<void> => {
const guild = interaction.guild!;
const { renderUser, renderDelta } = client.logger;
- interaction.reply({
+ await interaction.reply({
embeds: [
new EmojiEmbed()
.setTitle("Server Info")
diff --git a/src/commands/settings/automod.ts b/src/commands/settings/automod.ts
index db4a1c4..b65eb4c 100644
--- a/src/commands/settings/automod.ts
+++ b/src/commands/settings/automod.ts
@@ -1076,32 +1076,33 @@
} else {
switch (i.values[0]) {
case "invites": {
- i.deferUpdate();
+ await i.deferUpdate();
config.invite = await inviteMenu(i, m, config.invite);
break;
}
case "mentions": {
- i.deferUpdate();
+ await i.deferUpdate();
config.pings = await mentionMenu(i, m, config.pings);
break;
}
case "words": {
+ await i.deferUpdate();
config.wordFilter = await wordMenu(i, m, config.wordFilter);
break;
}
case "malware": {
- i.deferUpdate();
+ await i.deferUpdate();
config.malware = !config.malware;
break;
}
case "images": {
- i.deferUpdate();
+ await i.deferUpdate();
const next = await imageMenu(i, m, config.images);
config.images = next;
break;
}
case "clean": {
- i.deferUpdate();
+ await i.deferUpdate();
const next = await cleanMenu(i, m, config.clean);
config.clean = next;
break;
diff --git a/src/commands/settings/logs/warnings.ts b/src/commands/settings/logs/warnings.ts
index 38b645a..a810560 100644
--- a/src/commands/settings/logs/warnings.ts
+++ b/src/commands/settings/logs/warnings.ts
@@ -5,12 +5,14 @@
ButtonBuilder,
ButtonStyle,
ChannelSelectMenuBuilder,
- ChannelType
+ ChannelType,
+ ComponentType
} from "discord.js";
import EmojiEmbed from "../../../utils/generateEmojiEmbed.js";
import getEmojiByName from "../../../utils/getEmojiByName.js";
import type { SlashCommandSubcommandBuilder } from "discord.js";
import client from "../../../utils/client.js";
+import _ from "lodash";
const command = (builder: SlashCommandSubcommandBuilder) =>
builder.setName("warnings").setDescription("Settings for the staff notifications channel");
@@ -24,7 +26,7 @@
});
let data = await client.database.guilds.read(interaction.guild.id);
- let channel = data.logging.staff.channel;
+ let channel = _.clone(data.logging.staff.channel);
let closed = false;
do {
const channelMenu = new ActionRowBuilder<ChannelSelectMenuBuilder>().addComponents(
@@ -45,7 +47,7 @@
.setLabel("Save")
.setStyle(ButtonStyle.Success)
.setEmoji(getEmojiByName("ICONS.SAVE", "id") as Discord.APIMessageComponentEmoji)
- .setDisabled(channel === data.logging.staff.channel)
+ .setDisabled(_.isEqual(channel, data.logging.staff.channel))
);
const embed = new EmojiEmbed()
@@ -62,12 +64,12 @@
components: [channelMenu, buttons]
});
- let i: Discord.ButtonInteraction | Discord.SelectMenuInteraction;
+ let i: Discord.ButtonInteraction | Discord.ChannelSelectMenuInteraction;
try {
- i = (await interaction.channel!.awaitMessageComponent({
+ i = await interaction.channel!.awaitMessageComponent<ComponentType.Button | ComponentType.ChannelSelect>({
filter: (i: Discord.Interaction) => i.user.id === interaction.user.id,
time: 300000
- })) as Discord.ButtonInteraction | Discord.SelectMenuInteraction;
+ });
} catch (e) {
closed = true;
continue;
@@ -81,7 +83,7 @@
}
case "save": {
await client.database.guilds.write(interaction.guild!.id, {
- "logging.warnings.channel": channel
+ "logging.staff.channel": channel
});
data = await client.database.guilds.read(interaction.guild!.id);
await client.memory.forceUpdate(interaction.guild!.id);
diff --git a/src/commands/settings/rolemenu.ts b/src/commands/settings/rolemenu.ts
index e683e4f..7da9dfe 100644
--- a/src/commands/settings/rolemenu.ts
+++ b/src/commands/settings/rolemenu.ts
@@ -89,7 +89,7 @@
out = null;
}
if (!out) return;
- out.deferUpdate();
+ await out.deferUpdate();
if (out.isButton()) return;
const values = out.values;
@@ -218,7 +218,7 @@
`**Max:** ${data.max}\n`
);
- interaction.editReply({ embeds: [embed], components: [previewSelect, buttons] });
+ await interaction.editReply({ embeds: [embed], components: [previewSelect, buttons] });
let i: StringSelectMenuInteraction | ButtonInteraction;
try {
i = (await m.awaitMessageComponent({
@@ -304,7 +304,7 @@
}\n`
);
- interaction.editReply({
+ await interaction.editReply({
embeds: [embed],
components: [new ActionRowBuilder<RoleSelectMenuBuilder>().addComponents(roleSelect), buttons]
});
diff --git a/src/commands/settings/stats.ts b/src/commands/settings/stats.ts
index d4e4439..ed2fc6f 100644
--- a/src/commands/settings/stats.ts
+++ b/src/commands/settings/stats.ts
@@ -198,7 +198,7 @@
)
]
});
- showModal(i, { name: newChannelName, enabled: newChannelEnabled });
+ await showModal(i, { name: newChannelName, enabled: newChannelEnabled });
const out: Discord.ModalSubmitInteraction | ButtonInteraction | null =
await modalInteractionCollector(m, interaction.user);
@@ -336,7 +336,7 @@
}
}
- interaction.editReply({
+ await interaction.editReply({
embeds: [embed],
components: [
new ActionRowBuilder<StringSelectMenuBuilder>().addComponents(pageSelect),
@@ -367,7 +367,7 @@
modified = true;
switch (i.values[0]!) {
case "edit": {
- showModal(i, current!);
+ await showModal(i, current!);
await interaction.editReply({
embeds: [
new EmojiEmbed()
@@ -439,7 +439,7 @@
}
case "save": {
await client.database.guilds.write(interaction.guild.id, { stats: currentObject });
- singleNotify("statsChannelDeleted", interaction.guild.id, true);
+ await singleNotify("statsChannelDeleted", interaction.guild.id, true);
modified = false;
await client.memory.forceUpdate(interaction.guild.id);
break;
diff --git a/src/commands/settings/tracks.ts b/src/commands/settings/tracks.ts
index 625bcfb..60a7eae 100644
--- a/src/commands/settings/tracks.ts
+++ b/src/commands/settings/tracks.ts
@@ -142,7 +142,7 @@
out = null;
}
if (!out) return;
- out.deferUpdate();
+ await out.deferUpdate();
if (out.isButton()) return;
const values = out.values;
@@ -268,7 +268,7 @@
];
if (current.track.length >= 1) comps.splice(1, 0, selectMenu);
- interaction.editReply({ embeds: [embed], components: comps });
+ await interaction.editReply({ embeds: [embed], components: comps });
let out: ButtonInteraction | RoleSelectMenuInteraction | StringSelectMenuInteraction | null;
@@ -286,7 +286,7 @@
if (out.isButton()) {
switch (out.customId) {
case "back": {
- out.deferUpdate();
+ await out.deferUpdate();
closed = true;
break;
}
@@ -295,23 +295,23 @@
break;
}
case "reorder": {
- out.deferUpdate();
+ await out.deferUpdate();
current.track = (await reorderTracks(interaction, out, message, roles, current.track))!;
break;
}
case "retainPrevious": {
- out.deferUpdate();
+ await out.deferUpdate();
current.retainPrevious = !current.retainPrevious;
break;
}
case "nullable": {
- out.deferUpdate();
+ await out.deferUpdate();
current.nullable = !current.nullable;
break;
}
}
} else if (out.isStringSelectMenu()) {
- out.deferUpdate();
+ await out.deferUpdate();
switch (out.customId) {
case "removeRole": {
const index = current.track.findIndex(
@@ -322,7 +322,7 @@
}
}
} else {
- out.deferUpdate();
+ await out.deferUpdate();
switch (out.customId) {
case "addRole": {
const role = out.values![0]!;
@@ -476,7 +476,7 @@
break;
}
case "save": {
- client.database.guilds.write(interaction.guild!.id, { tracks: tracks });
+ await client.database.guilds.write(interaction.guild!.id, { tracks: tracks });
modified = false;
await client.memory.forceUpdate(interaction.guild!.id);
break;
diff --git a/src/commands/settings/verify.ts b/src/commands/settings/verify.ts
index e2318fc..05c4764 100644
--- a/src/commands/settings/verify.ts
+++ b/src/commands/settings/verify.ts
@@ -82,7 +82,7 @@
if (i.isButton()) {
switch (i.customId) {
case "save": {
- client.database.guilds.write(interaction.guild.id, { verify: data });
+ await client.database.guilds.write(interaction.guild.id, { verify: data });
config = await client.database.guilds.read(interaction.guild.id);
data = Object.assign({}, config.verify);
await client.memory.forceUpdate(interaction.guild.id);
diff --git a/src/commands/user/role.ts b/src/commands/user/role.ts
index 74b6c41..9a0a462 100644
--- a/src/commands/user/role.ts
+++ b/src/commands/user/role.ts
@@ -129,7 +129,7 @@
continue;
}
- i.deferUpdate();
+ await i.deferUpdate();
if (i.isButton()) {
switch (i.customId) {
case "roleSave": {
diff --git a/src/commands/user/track.ts b/src/commands/user/track.ts
index 19b9da2..ee69868 100644
--- a/src/commands/user/track.ts
+++ b/src/commands/user/track.ts
@@ -178,7 +178,7 @@
timedOut = true;
continue;
}
- component.deferUpdate();
+ await component.deferUpdate();
if (component.customId === "conflict") {
const rolesToRemove = selected.filter(
(role) => role !== (component as StringSelectMenuInteraction).values[0]
diff --git a/src/commands/verify.ts b/src/commands/verify.ts
index 0dd8b24..4bbe50f 100644
--- a/src/commands/verify.ts
+++ b/src/commands/verify.ts
@@ -5,7 +5,7 @@
const command = new SlashCommandBuilder().setName("verify").setDescription("Get verified in the server");
const callback = async (interaction: CommandInteraction): Promise<void> => {
- verify(interaction);
+ await verify(interaction);
};
export { command };
diff --git a/src/config/main.d.ts b/src/config/main.d.ts
index 99c460d..419414a 100644
--- a/src/config/main.d.ts
+++ b/src/config/main.d.ts
@@ -19,6 +19,7 @@
};
baseUrl: string;
rapidApiKey: string;
+ clamavSocket: string;
};
export default config;
diff --git a/src/context/messages/purgeto.ts b/src/context/messages/purgeto.ts
index 4f0ea1e..a75a281 100644
--- a/src/context/messages/purgeto.ts
+++ b/src/context/messages/purgeto.ts
@@ -19,14 +19,14 @@
async function waitForButton(m: Discord.Message, member: Discord.GuildMember): Promise<boolean> {
let component;
try {
- component = m.awaitMessageComponent({
+ component = await m.awaitMessageComponent({
time: 200000,
filter: (i) => i.user.id === member.id && i.channel!.id === m.channel.id && i.message.id === m.id
});
} catch (e) {
return false;
}
- (await component).deferUpdate();
+ await component.deferUpdate();
return true;
}
@@ -210,7 +210,7 @@
guild: interaction.guild!.id
}
};
- log(data);
+ await log(data);
const messages: Message[] = deleted
.map((m) => m)
.filter((m) => m instanceof Message)
diff --git a/src/events/channelCreate.ts b/src/events/channelCreate.ts
index 90a7f6d..8fd6b35 100644
--- a/src/events/channelCreate.ts
+++ b/src/events/channelCreate.ts
@@ -81,5 +81,5 @@
guild: channel.guild.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/channelDelete.ts b/src/events/channelDelete.ts
index 8dffd38..b79c2da 100644
--- a/src/events/channelDelete.ts
+++ b/src/events/channelDelete.ts
@@ -123,5 +123,5 @@
guild: channel.guild.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/channelUpdate.ts b/src/events/channelUpdate.ts
index 6491cc9..adfe87f 100644
--- a/src/events/channelUpdate.ts
+++ b/src/events/channelUpdate.ts
@@ -301,5 +301,5 @@
guild: newChannel.guild.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/emojiCreate.ts b/src/events/emojiCreate.ts
index 96f7909..873defa 100644
--- a/src/events/emojiCreate.ts
+++ b/src/events/emojiCreate.ts
@@ -30,5 +30,5 @@
guild: emoji.guild.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/emojiDelete.ts b/src/events/emojiDelete.ts
index 52822cb..21ade1d 100644
--- a/src/events/emojiDelete.ts
+++ b/src/events/emojiDelete.ts
@@ -31,5 +31,5 @@
guild: emoji.guild.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/emojiUpdate.ts b/src/events/emojiUpdate.ts
index 173f5c5..236a799 100644
--- a/src/events/emojiUpdate.ts
+++ b/src/events/emojiUpdate.ts
@@ -37,5 +37,5 @@
guild: newEmoji.guild.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/guildBanAdd.ts b/src/events/guildBanAdd.ts
index 6036ddf..c8f3446 100644
--- a/src/events/guildBanAdd.ts
+++ b/src/events/guildBanAdd.ts
@@ -9,7 +9,7 @@
export async function callback(client: NucleusClient, ban: GuildBan) {
const { log, isLogging, NucleusColors, entry, renderUser, renderDelta, getAuditLog } = client.logger;
await statsChannelRemove(ban.user, ban.guild);
- purgeByUser(ban.user.id, ban.guild.id);
+ await purgeByUser(ban.user.id, ban.guild.id);
if (!(await isLogging(ban.guild.id, "guildMemberPunish"))) return;
const auditLog: GuildAuditLogsEntry | undefined = (await getAuditLog(ban.guild, AuditLogEvent.MemberBanAdd)).filter(
(entry: GuildAuditLogsEntry) => (entry.target! as User).id === ban.user.id
@@ -39,5 +39,5 @@
guild: ban.guild.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/guildBanRemove.ts b/src/events/guildBanRemove.ts
index fc916ba..64d9de3 100644
--- a/src/events/guildBanRemove.ts
+++ b/src/events/guildBanRemove.ts
@@ -33,5 +33,5 @@
guild: ban.guild.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/guildCreate.ts b/src/events/guildCreate.ts
index ff6c6b2..f5e43a9 100644
--- a/src/events/guildCreate.ts
+++ b/src/events/guildCreate.ts
@@ -5,5 +5,5 @@
export const event = "guildCreate";
export async function callback(_client: NucleusClient, guild: Guild) {
- guide(guild);
+ await guide(guild);
}
diff --git a/src/events/guildMemberUpdate.ts b/src/events/guildMemberUpdate.ts
index 34a52b8..4e512ee 100644
--- a/src/events/guildMemberUpdate.ts
+++ b/src/events/guildMemberUpdate.ts
@@ -12,6 +12,8 @@
await client.database.premium.checkAllPremium(after);
}
+ if (before.displayAvatarURL({ forceStatic: true }) !== after.displayAvatarURL({ forceStatic: true }))
+ await doMemberChecks(after);
if (!before.roles.cache.equals(after.roles.cache)) {
const auditLog = (await getAuditLog(after.guild, AuditLogEvent.MemberRoleUpdate)).filter(
(entry: GuildAuditLogsEntry) => (entry.target as GuildMember)!.id === after.id
@@ -84,7 +86,7 @@
});
}
data = Object.assign(data, { list: list });
- log(data);
+ await log(data);
}
}
const auditLog = (await getAuditLog(after.guild, AuditLogEvent.MemberUpdate)).filter(
@@ -93,7 +95,7 @@
if (!auditLog) return;
if (auditLog.executor!.id === client.user!.id) return;
if (before.nickname !== after.nickname) {
- doMemberChecks(after, after.guild);
+ await doMemberChecks(after);
await client.database.history.create(
"nickname",
after.guild.id,
@@ -123,7 +125,7 @@
guild: after.guild.id
}
};
- log(data);
+ await log(data);
}
if (
(before.communicationDisabledUntilTimestamp ?? 0) < Date.now() &&
@@ -163,12 +165,16 @@
guild: after.guild.id
}
};
- log(data);
- client.database.eventScheduler.schedule("naturalUnmute", after.communicationDisabledUntil?.toISOString()!, {
- guild: after.guild.id,
- user: after.id,
- expires: after.communicationDisabledUntilTimestamp
- });
+ await log(data);
+ await client.database.eventScheduler.schedule(
+ "naturalUnmute",
+ after.communicationDisabledUntil?.toISOString()!,
+ {
+ guild: after.guild.id,
+ user: after.id,
+ expires: after.communicationDisabledUntilTimestamp
+ }
+ );
}
if (
after.communicationDisabledUntil === null &&
@@ -204,8 +210,8 @@
guild: after.guild.id
}
};
- log(data);
- client.database.eventScheduler.cancel("naturalUnmute", {
+ await log(data);
+ await client.database.eventScheduler.cancel("naturalUnmute", {
guild: after.guild.id,
user: after.id,
expires: before.communicationDisabledUntilTimestamp
diff --git a/src/events/guildUpdate.ts b/src/events/guildUpdate.ts
index c48c82f..27c609d 100644
--- a/src/events/guildUpdate.ts
+++ b/src/events/guildUpdate.ts
@@ -93,5 +93,5 @@
guild: after.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/inviteCreate.ts b/src/events/inviteCreate.ts
index 240965c..6e28d95 100644
--- a/src/events/inviteCreate.ts
+++ b/src/events/inviteCreate.ts
@@ -33,5 +33,5 @@
guild: invite.guild!.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/inviteDelete.ts b/src/events/inviteDelete.ts
index 81285c7..89bd226 100644
--- a/src/events/inviteDelete.ts
+++ b/src/events/inviteDelete.ts
@@ -33,5 +33,5 @@
guild: invite.guild!.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/memberJoin.ts b/src/events/memberJoin.ts
index 66abe28..55f9ba8 100644
--- a/src/events/memberJoin.ts
+++ b/src/events/memberJoin.ts
@@ -7,9 +7,9 @@
export const event = "guildMemberAdd";
export async function callback(client: NucleusClient, member: GuildMember) {
- welcome(member);
- statsChannelAdd(member.user, member.guild);
- doMemberChecks(member, member.guild);
+ await welcome(member);
+ await statsChannelAdd(member.user, member.guild);
+ await doMemberChecks(member);
const { log, isLogging, NucleusColors, entry, renderUser, renderDelta } = client.logger;
if (!(await isLogging(member.guild.id, "guildMemberUpdate"))) return;
await client.database.history.create("join", member.guild.id, member.user, null, null);
@@ -33,5 +33,5 @@
guild: member.guild.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/memberLeave.ts b/src/events/memberLeave.ts
index e80ea0b..1ca50c6 100644
--- a/src/events/memberLeave.ts
+++ b/src/events/memberLeave.ts
@@ -8,7 +8,7 @@
export async function callback(client: NucleusClient, member: GuildMember) {
const startTime = Date.now() - 10 * 1000;
- purgeByUser(member.id, member.guild.id);
+ await purgeByUser(member.id, member.guild.id);
await statsChannelRemove(member.user, member.guild);
const { getAuditLog, isLogging, log, NucleusColors, entry, renderUser, renderDelta } = client.logger;
if (!(await isLogging(member.guild.id, "guildMemberUpdate"))) return;
@@ -95,5 +95,5 @@
}
};
}
- log(data);
+ await log(data);
}
diff --git a/src/events/messageCreate.ts b/src/events/messageCreate.ts
index 0281fa1..cc69bf0 100644
--- a/src/events/messageCreate.ts
+++ b/src/events/messageCreate.ts
@@ -23,7 +23,11 @@
if (message.channel.permissionsFor(message.guild.members.me!)!.has("ManageMessages")) {
await message.crosspost();
} else {
- singleNotify(`Nucleus does not have Manage Messages in <#${message.channel.id}>`, message.guild.id, true);
+ await singleNotify(
+ `Nucleus does not have Manage Messages in <#${message.channel.id}>`,
+ message.guild.id,
+ true
+ );
}
}
@@ -71,7 +75,7 @@
if (!config.filters.invite.allowed.channels.includes(message.channel.id)) {
if (/(?:https?:\/\/)?discord(?:app)?\.(?:com\/invite|gg)\/[a-zA-Z0-9]+\/?/.test(content)) {
messageException(message.guild.id, message.channel.id, message.id);
- message.delete();
+ await message.delete();
const data = {
meta: {
type: "messageDelete",
@@ -101,42 +105,42 @@
for (const element of fileNames.files) {
const url = element.url ? element.url : element.local;
if (
- /\.(j(pe?g|fif)|a?png|gifv?|w(eb[mp]|av)|mp([34]|eg-\d)|ogg|avi|h\.26(4|5)|cda)$/.test(
+ /\.(jpg|jpeg|png|apng|gif|gifv|webm|webp|mp4|wav|mp3|ogg|jfif|mpeg-\d|avi|h\.264|h\.265)$/.test(
url.toLowerCase()
)
) {
- // jpg|jpeg|png|apng|gif|gifv|webm|webp|mp4|wav|mp3|ogg|jfif|MPEG-#|avi|h.264|h.265
+ // j(pe?g|fif)|a?png|gifv?|w(eb[mp]|av)|mp([34]|eg-\d)|ogg|avi|h\.26(4|5)
+ // ^no
if (
config.filters.images.NSFW &&
- !(message.channel instanceof ThreadChannel ? message.channel.parent?.nsfw : message.channel.nsfw)
+ !(message.channel instanceof ThreadChannel ? message.channel.parent?.nsfw : message.channel.nsfw) &&
+ (await NSFWCheck(element.url))
) {
- if (await NSFWCheck(url)) {
- messageException(message.guild.id, message.channel.id, message.id);
- await message.delete();
- const data = {
- meta: {
- type: "messageDelete",
- displayName: "Message Deleted",
- calculateType: "autoModeratorDeleted",
- color: NucleusColors.red,
- emoji: "MESSAGE.DELETE",
- timestamp: Date.now()
- },
- separate: {
- start:
- filter +
- " Image detected as NSFW\n\n" +
- (content
- ? `**Message:**\n\`\`\`${content}\`\`\``
- : "**Message:** *Message had no content*")
- },
- list: list,
- hidden: {
- guild: message.channel.guild.id
- }
- };
- return log(data);
- }
+ messageException(message.guild.id, message.channel.id, message.id);
+ await message.delete();
+ const data = {
+ meta: {
+ type: "messageDelete",
+ displayName: "Message Deleted",
+ calculateType: "autoModeratorDeleted",
+ color: NucleusColors.red,
+ emoji: "MESSAGE.DELETE",
+ timestamp: Date.now()
+ },
+ separate: {
+ start:
+ filter +
+ " Image detected as NSFW\n\n" +
+ (content
+ ? `**Message:**\n\`\`\`${content}\`\`\``
+ : "**Message:** *Message had no content*")
+ },
+ list: list,
+ hidden: {
+ guild: message.channel.guild.id
+ }
+ };
+ return log(data);
}
if (config.filters.wordFilter.enabled) {
const text = await TestImage(url);
@@ -205,34 +209,30 @@
}
}
}
- if (config.filters.malware) {
- if (!(await MalwareCheck(url))) {
- messageException(message.guild.id, message.channel.id, message.id);
- await message.delete();
- const data = {
- meta: {
- type: "messageDelete",
- displayName: "Message Deleted",
- calculateType: "autoModeratorDeleted",
- color: NucleusColors.red,
- emoji: "MESSAGE.DELETE",
- timestamp: Date.now()
- },
- separate: {
- start:
- filter +
- " File detected as malware\n\n" +
- (content
- ? `**Message:**\n\`\`\`${content}\`\`\``
- : "**Message:** *Message had no content*")
- },
- list: list,
- hidden: {
- guild: message.channel.guild.id
- }
- };
- return log(data);
- }
+ if (config.filters.malware && (await MalwareCheck(url))) {
+ messageException(message.guild.id, message.channel.id, message.id);
+ await message.delete();
+ const data = {
+ meta: {
+ type: "messageDelete",
+ displayName: "Message Deleted",
+ calculateType: "autoModeratorDeleted",
+ color: NucleusColors.red,
+ emoji: "MESSAGE.DELETE",
+ timestamp: Date.now()
+ },
+ separate: {
+ start:
+ filter +
+ " File detected as malware\n\n" +
+ (content ? `**Message:**\n\`\`\`${content}\`\`\`` : "**Message:** *Message had no content*")
+ },
+ list: list,
+ hidden: {
+ guild: message.channel.guild.id
+ }
+ };
+ return log(data);
}
}
}
diff --git a/src/events/messageDelete.ts b/src/events/messageDelete.ts
index c29bfd0..b847400 100644
--- a/src/events/messageDelete.ts
+++ b/src/events/messageDelete.ts
@@ -68,5 +68,5 @@
guild: message.guild!.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/messageEdit.ts b/src/events/messageEdit.ts
index 67796c7..270da00 100644
--- a/src/events/messageEdit.ts
+++ b/src/events/messageEdit.ts
@@ -44,7 +44,7 @@
renderChannel(newMessage.channel as Discord.GuildBasedChannel)
),
sent: entry(newMessage.createdTimestamp, renderDelta(newMessage.createdTimestamp)),
- published: entry(newMessage.editedTimestamp!, renderDelta(newMessage.editedTimestamp!)),
+ published: entry(Date.now(), renderDelta(Date.now())),
mentions: renderNumberDelta(oldMessage.mentions.users.size, newMessage.mentions.users.size),
attachments: entry(
renderNumberDelta(oldMessage.attachments.size, newMessage.attachments.size),
@@ -103,5 +103,5 @@
guild: newMessage.guild.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/roleCreate.ts b/src/events/roleCreate.ts
index 9b900f8..ea85b4d 100644
--- a/src/events/roleCreate.ts
+++ b/src/events/roleCreate.ts
@@ -30,5 +30,5 @@
guild: role.guild.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/roleDelete.ts b/src/events/roleDelete.ts
index e83d557..1802518 100644
--- a/src/events/roleDelete.ts
+++ b/src/events/roleDelete.ts
@@ -42,5 +42,5 @@
guild: role.guild.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/roleUpdate.ts b/src/events/roleUpdate.ts
index 236bc0f..c15cf01 100644
--- a/src/events/roleUpdate.ts
+++ b/src/events/roleUpdate.ts
@@ -74,5 +74,5 @@
guild: newRole.guild.id
}
}; // TODO: make our own page for this
- log(data);
+ await log(data);
}
diff --git a/src/events/stickerCreate.ts b/src/events/stickerCreate.ts
index 01944fc..bc8adb8 100644
--- a/src/events/stickerCreate.ts
+++ b/src/events/stickerCreate.ts
@@ -32,5 +32,5 @@
guild: sticker.guild!.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/stickerDelete.ts b/src/events/stickerDelete.ts
index a348b73..7704c49 100644
--- a/src/events/stickerDelete.ts
+++ b/src/events/stickerDelete.ts
@@ -30,5 +30,5 @@
guild: sticker.guild!.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/stickerUpdate.ts b/src/events/stickerUpdate.ts
index c42f775..4be1a3d 100644
--- a/src/events/stickerUpdate.ts
+++ b/src/events/stickerUpdate.ts
@@ -35,5 +35,5 @@
guild: newSticker.guild!.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/threadCreate.ts b/src/events/threadCreate.ts
index cefaf3b..42cda47 100644
--- a/src/events/threadCreate.ts
+++ b/src/events/threadCreate.ts
@@ -44,5 +44,5 @@
guild: thread.guild.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/threadDelete.ts b/src/events/threadDelete.ts
index ecbf4cf..fba6592 100644
--- a/src/events/threadDelete.ts
+++ b/src/events/threadDelete.ts
@@ -46,5 +46,5 @@
guild: thread.guild.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/threadUpdate.ts b/src/events/threadUpdate.ts
index 510ec30..e28abf1 100644
--- a/src/events/threadUpdate.ts
+++ b/src/events/threadUpdate.ts
@@ -55,5 +55,5 @@
guild: newThread.guild.id
}
};
- log(data);
+ await log(data);
}
diff --git a/src/events/webhookUpdate.ts b/src/events/webhookUpdate.ts
index 438c66e..c4a4efb 100644
--- a/src/events/webhookUpdate.ts
+++ b/src/events/webhookUpdate.ts
@@ -130,7 +130,7 @@
guild: channel.guild.id
}
};
- log(data);
+ await log(data);
} catch (e) {
console.log(e);
}
diff --git a/src/index.ts b/src/index.ts
index 50a1526..b3883a1 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -8,7 +8,7 @@
client.on("ready", async () => {
console.log(`Logged in as ${client.user!.tag}!`);
- register();
+ await register();
runServer(client);
if (config.enableDevelopment) {
client.fetchedCommands = await client.guilds.cache.get(config.developmentGuildID)?.commands.fetch()!;
diff --git a/src/premium/attachmentLogs.ts b/src/premium/attachmentLogs.ts
index e719f22..9bb216d 100644
--- a/src/premium/attachmentLogs.ts
+++ b/src/premium/attachmentLogs.ts
@@ -36,7 +36,7 @@
if (await client.database.premium.hasPremium(message.guild.id)) {
const channel = (await client.database.guilds.read(message.guild.id)).logging.attachments.channel;
if (!channel) {
- singleNotify(
+ await singleNotify(
"noAttachmentLogChannel",
message.guild.id,
`No channel set for attachment logging. You can set one with ${getCommandMentionByName(
@@ -48,7 +48,7 @@
}
const channelObj = await message.guild.channels.fetch(channel);
if (!channelObj) {
- singleNotify(
+ await singleNotify(
"attachmentLogChannelDeleted",
message.guild.id,
`Your attachment history channel was deleted or is not longer accessible. You can set a new one with ${getCommandMentionByName(
@@ -75,7 +75,7 @@
],
files: attachments.map((file) => file.local)
});
- client.database.guilds.write(message.guild.id, {
+ await client.database.guilds.write(message.guild.id, {
[`logging.attachments.saved.${message.channel.id}${message.id}`]: m.url
});
return { files: attachments, jump: m.url };
diff --git a/src/premium/createTranscript.ts b/src/premium/createTranscript.ts
index 7a1f57f..fa1f7a4 100644
--- a/src/premium/createTranscript.ts
+++ b/src/premium/createTranscript.ts
@@ -134,7 +134,7 @@
guild: interaction.guild!.id
}
};
- log(data);
+ await log(data);
await interaction.channel.delete();
return;
}
diff --git a/src/reflex/guide.ts b/src/reflex/guide.ts
index 1901d34..59c12c7 100644
--- a/src/reflex/guide.ts
+++ b/src/reflex/guide.ts
@@ -353,12 +353,12 @@
const em = new Discord.EmbedBuilder(pages[page]!.embed);
em.setDescription(em.data.description + "\n\n" + createPageIndicator(pages.length, page));
em.setFooter({ text: "Message closed" });
- interaction.editReply({
+ await interaction.editReply({
embeds: [em],
components: []
});
} else {
- m.delete();
+ await m.delete();
}
}
};
diff --git a/src/reflex/nsfwjs b/src/reflex/nsfwjs
new file mode 160000
index 0000000..f482648
--- /dev/null
+++ b/src/reflex/nsfwjs
@@ -0,0 +1 @@
+Subproject commit f48264888bc1b2a805e4b20a5e5c82e11cb4754a
diff --git a/src/reflex/scanners.ts b/src/reflex/scanners.ts
index 53c8c9b..c6a0e32 100644
--- a/src/reflex/scanners.ts
+++ b/src/reflex/scanners.ts
@@ -6,99 +6,97 @@
import client from "../utils/client.js";
import { createHash } from "crypto";
import * as nsfwjs from "nsfwjs";
-// import * as clamscan from "clamscan";
-import * as tf from "@tensorflow/tfjs";
+import ClamScan from "clamscan";
+import * as tf from "@tensorflow/tfjs-node";
import EmojiEmbed from "../utils/generateEmojiEmbed.js";
import getEmojiByName from "../utils/getEmojiByName.js";
import { ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js";
+import config from "../config/main.js";
+import gm from "gm";
interface NSFWSchema {
nsfw: boolean;
errored?: boolean;
}
interface MalwareSchema {
- safe: boolean;
+ malware: boolean;
errored?: boolean;
}
-const nsfw_model = await nsfwjs.load();
+const nsfw_model = await nsfwjs.load("file://dist/reflex/nsfwjs/example/nsfw_demo/public/model/", { size: 299 });
+const clamscanner = await new ClamScan().init({
+ clamdscan: {
+ socket: config.clamavSocket
+ }
+});
-export async function testNSFW(link: string): Promise<NSFWSchema> {
- const [fileStream, hash] = await streamAttachment(link);
+export async function testNSFW(url: string): Promise<NSFWSchema> {
+ const [fileStream, hash] = await streamAttachment(url);
const alreadyHaveCheck = await client.database.scanCache.read(hash);
- if (alreadyHaveCheck?.nsfw) return { nsfw: alreadyHaveCheck.nsfw };
+ if (alreadyHaveCheck && "nsfw" in alreadyHaveCheck!) {
+ return { nsfw: alreadyHaveCheck.nsfw };
+ }
- const image = tf.tensor3d(new Uint8Array(fileStream));
+ const converted = (await new Promise((resolve, reject) =>
+ gm(fileStream)
+ .command("convert")
+ .toBuffer("PNG", (err, buf) => {
+ if (err) return reject(err);
+ resolve(buf);
+ })
+ )) as Buffer;
- const predictions = (await nsfw_model.classify(image, 1))[0]!;
- image.dispose();
+ const img = tf.node.decodeImage(converted, 3, undefined, false) as tf.Tensor3D;
- return { nsfw: predictions.className === "Hentai" || predictions.className === "Porn" };
+ const predictions = (await nsfw_model.classify(img, 1))[0]!;
+ img.dispose();
+ console.log(2, predictions);
+
+ const nsfw = predictions.className === "Hentai" || predictions.className === "Porn";
+ await client.database.scanCache.write(hash, "nsfw", nsfw);
+
+ return { nsfw };
}
export async function testMalware(link: string): Promise<MalwareSchema> {
- const [_, hash] = await saveAttachment(link);
+ const [fileName, hash] = await saveAttachment(link);
const alreadyHaveCheck = await client.database.scanCache.read(hash);
- if (alreadyHaveCheck?.malware) return { safe: alreadyHaveCheck.malware };
- return { safe: true };
- // const data = new URLSearchParams();
- // // const f = createReadStream(p);
- // data.append("file", f.read(fs.statSync(p).size));
- // const result = await fetch("https://unscan.p.rapidapi.com/malware", {
- // method: "POST",
- // headers: {
- // "X-RapidAPI-Key": client.config.rapidApiKey,
- // "X-RapidAPI-Host": "unscan.p.rapidapi.com"
- // },
- // body: data
- // })
- // .then((response) =>
- // response.status === 200 ? (response.json() as Promise<MalwareSchema>) : { safe: true, errored: true }
- // )
- // .catch((err) => {
- // console.error(err);
- // return { safe: true, errored: true };
- // });
- // if (!result.errored) {
- // client.database.scanCache.write(hash, "malware", result.safe);
- // }
- // return { safe: result.safe };
+ if (alreadyHaveCheck?.malware !== undefined) return { malware: alreadyHaveCheck.malware };
+ let malware;
+ try {
+ malware = (await clamscanner.scanFile(fileName)).isInfected;
+ } catch (e) {
+ return { malware: true };
+ }
+ await client.database.scanCache.write(hash, "malware", malware);
+ return { malware };
}
export async function testLink(link: string): Promise<{ safe: boolean; tags: string[] }> {
const alreadyHaveCheck = await client.database.scanCache.read(link);
- if (alreadyHaveCheck?.bad_link) return { safe: alreadyHaveCheck.bad_link, tags: alreadyHaveCheck.tags };
- const scanned: { safe?: boolean; tags?: string[] } = await fetch("https://unscan.p.rapidapi.com/link", {
- method: "POST",
- headers: {
- "X-RapidAPI-Key": client.config.rapidApiKey,
- "X-RapidAPI-Host": "unscan.p.rapidapi.com"
- },
- body: `{"link":"${link}"}`
- })
- .then((response) => response.json() as Promise<MalwareSchema>)
- .catch((err) => {
- console.error(err);
- return { safe: true, tags: [] };
- });
- client.database.scanCache.write(link, "bad_link", scanned.safe ?? true, scanned.tags ?? []);
- return {
- safe: scanned.safe ?? true,
- tags: scanned.tags ?? []
- };
+ if (alreadyHaveCheck?.bad_link !== undefined)
+ return { safe: alreadyHaveCheck.bad_link, tags: alreadyHaveCheck.tags ?? [] };
+ return { safe: true, tags: [] };
+ // const scanned: { safe?: boolean; tags?: string[] } = {}
+ // await client.database.scanCache.write(link, "bad_link", scanned.safe ?? true, scanned.tags ?? []);
+ // return {
+ // safe: scanned.safe ?? true,
+ // tags: scanned.tags ?? []
+ // };
}
-export async function streamAttachment(link: string): Promise<[ArrayBuffer, string]> {
+export async function streamAttachment(link: string): Promise<[Buffer, string]> {
const image = await (await fetch(link)).arrayBuffer();
const enc = new TextDecoder("utf-8");
- return [image, createHash("sha512").update(enc.decode(image), "base64").digest("base64")];
+ const buf = Buffer.from(image);
+ return [buf, createHash("sha512").update(enc.decode(image), "base64").digest("base64")];
}
export async function saveAttachment(link: string): Promise<[string, string]> {
const image = await (await fetch(link)).arrayBuffer();
- const fileName = generateFileName(link.split("/").pop()!.split(".").pop()!);
+ const fileName = await generateFileName(link.split("/").pop()!.split(".").pop()!);
const enc = new TextDecoder("utf-8");
- writeFileSync(fileName, new DataView(image), "base64");
+ writeFileSync(fileName, new DataView(image));
return [fileName, createHash("sha512").update(enc.decode(image), "base64").digest("base64")];
}
@@ -153,10 +151,11 @@
return detectionsTypes as string[];
}
-export async function NSFWCheck(element: string): Promise<boolean> {
+export async function NSFWCheck(url: string): Promise<boolean> {
try {
- return (await testNSFW(element)).nsfw;
- } catch {
+ return (await testNSFW(url)).nsfw;
+ } catch (e) {
+ console.log(e);
return false;
}
}
@@ -169,7 +168,7 @@
export async function MalwareCheck(element: string): Promise<boolean> {
try {
- return (await testMalware(element)).safe;
+ return (await testMalware(element)).malware;
} catch {
return true;
}
@@ -203,34 +202,43 @@
oem: 1,
psm: 3
});
+ console.log(text);
return text;
}
-export async function doMemberChecks(member: Discord.GuildMember, guild: Discord.Guild): Promise<void> {
+export async function doMemberChecks(member: Discord.GuildMember): Promise<void> {
if (member.user.bot) return;
+ console.log("Checking member " + member.user.tag);
+ const guild = member.guild;
const guildData = await client.database.guilds.read(guild.id);
if (!guildData.logging.staff.channel) return;
const [loose, strict] = [guildData.filters.wordFilter.words.loose, guildData.filters.wordFilter.words.strict];
+ console.log(1, loose, strict);
// Does the username contain filtered words
const usernameCheck = TestString(member.user.username, loose, strict, guildData.filters.wordFilter.enabled);
+ console.log(2, usernameCheck);
// Does the nickname contain filtered words
const nicknameCheck = TestString(member.nickname ?? "", loose, strict, guildData.filters.wordFilter.enabled);
+ console.log(3, nicknameCheck);
// Does the profile picture contain filtered words
const avatarTextCheck = TestString(
- (await TestImage(member.user.displayAvatarURL({ forceStatic: true }))) ?? "",
+ (await TestImage(member.displayAvatarURL({ forceStatic: true }))) ?? "",
loose,
strict,
guildData.filters.wordFilter.enabled
);
+ console.log(4, avatarTextCheck);
// Is the profile picture NSFW
- const avatarCheck =
- guildData.filters.images.NSFW && (await NSFWCheck(member.user.displayAvatarURL({ forceStatic: true })));
+ const avatar = member.displayAvatarURL({ extension: "png", size: 1024, forceStatic: true });
+ const avatarCheck = guildData.filters.images.NSFW && (await NSFWCheck(avatar));
+ console.log(5, avatarCheck);
// Does the username contain an invite
const inviteCheck = guildData.filters.invite.enabled && /discord\.gg\/[a-zA-Z0-9]+/gi.test(member.user.username);
+ console.log(6, inviteCheck);
// Does the nickname contain an invite
const nicknameInviteCheck =
guildData.filters.invite.enabled && /discord\.gg\/[a-zA-Z0-9]+/gi.test(member.nickname ?? "");
-
+ console.log(7, nicknameInviteCheck);
if (
usernameCheck !== null ||
nicknameCheck !== null ||
@@ -257,7 +265,7 @@
}
if (avatarTextCheck !== null) {
infractions.push(
- `Profile picture contains a ${avatarTextCheck.type}ly filtered word: ${avatarTextCheck.word}`
+ `Profile picture contains a ${avatarTextCheck.type}ly filtered word (${avatarTextCheck.word})`
);
}
if (infractions.length === 0) return;
@@ -294,7 +302,7 @@
.setLabel("Ban")
.setStyle(ButtonStyle.Danger)
].concat(
- usernameCheck !== null || nicknameCheck !== null || avatarTextCheck !== null
+ usernameCheck !== null || nicknameCheck !== null
? [
new ButtonBuilder()
.setCustomId(`mod:nickname:${member.user.id}`)
diff --git a/src/reflex/statsChannelUpdate.ts b/src/reflex/statsChannelUpdate.ts
index e3c7a2a..1b9379b 100644
--- a/src/reflex/statsChannelUpdate.ts
+++ b/src/reflex/statsChannelUpdate.ts
@@ -12,34 +12,43 @@
export async function callback(user: User, guild: Guild) {
guild = await client.guilds.fetch(guild.id);
const config = await client.database.guilds.read(guild.id);
- Object.entries(config.stats).forEach(async ([channel, props]) => {
- if ((props as PropSchema).enabled) {
- let string = (props as PropSchema).name;
- if (!string) return;
- string = await convertCurlyBracketString(string, user!.id, user!.username, guild!.name, guild!.members);
- let fetchedChannel;
- try {
- fetchedChannel = await guild.channels.fetch(channel);
- } catch (e) {
- fetchedChannel = null;
- }
- if (!fetchedChannel) {
- const deleted = config.stats[channel];
- await client.database.guilds.write(guild.id, null, `stats.${channel}`);
- return singleNotify(
- "statsChannelDeleted",
- guild.id,
- `One or more of your stats channels have been deleted. You can use ${getCommandMentionByName(
- "settings/stats"
- )}.\n` + `The channels name was: ${deleted!.name}`,
- "Critical"
- );
- }
- try {
- await fetchedChannel.setName(string.slice(0, 100));
- } catch (e) {
- console.error(e);
- }
- }
- });
+ Object.entries(config.stats).forEach(
+ ([channel, props]) =>
+ void (async () => {
+ if ((props as PropSchema).enabled) {
+ let string = (props as PropSchema).name;
+ if (!string) return;
+ string = await convertCurlyBracketString(
+ string,
+ user!.id,
+ user!.username,
+ guild!.name,
+ guild!.members
+ );
+ let fetchedChannel;
+ try {
+ fetchedChannel = await guild.channels.fetch(channel);
+ } catch (e) {
+ fetchedChannel = null;
+ }
+ if (!fetchedChannel) {
+ const deleted = config.stats[channel];
+ await client.database.guilds.write(guild.id, null, `stats.${channel}`);
+ return singleNotify(
+ "statsChannelDeleted",
+ guild.id,
+ `One or more of your stats channels have been deleted. You can use ${getCommandMentionByName(
+ "settings/stats"
+ )}.\n` + `The channels name was: ${deleted!.name}`,
+ "Critical"
+ );
+ }
+ try {
+ await fetchedChannel.setName(string.slice(0, 100));
+ } catch (e) {
+ console.error(e);
+ }
+ }
+ })()
+ );
}
diff --git a/src/reflex/verify.ts b/src/reflex/verify.ts
index a5991de..540fb4d 100644
--- a/src/reflex/verify.ts
+++ b/src/reflex/verify.ts
@@ -208,7 +208,7 @@
.setEmoji("CONTROL.BLOCKCROSS")
]
});
- singleNotify(
+ await singleNotify(
"verifyRoleDeleted",
interaction.guild!.id,
`The role given when a member is verified has been deleted. Use ${getCommandMentionByName(
diff --git a/src/reflex/welcome.ts b/src/reflex/welcome.ts
index 8e471c6..33f1651 100644
--- a/src/reflex/welcome.ts
+++ b/src/reflex/welcome.ts
@@ -45,7 +45,7 @@
content: (config.welcome.ping ? `<@&${config.welcome.ping}>` : "") + `<@${member.id}>`
});
} catch (err) {
- singleNotify(
+ await singleNotify(
"welcomeChannelDeleted",
member.guild.id,
`The welcome channel has been deleted or is no longer accessible. Use ${getCommandMentionByName(
diff --git a/src/utils/commandRegistration/register.ts b/src/utils/commandRegistration/register.ts
index fbd052f..d76617c 100644
--- a/src/utils/commandRegistration/register.ts
+++ b/src/utils/commandRegistration/register.ts
@@ -181,11 +181,19 @@
client.on("interactionCreate", async (interaction: Interaction) => {
if (interaction.isUserContextMenuCommand()) {
const commandName = "contextCommands/user/" + interaction.commandName;
- execute(client.commands[commandName]![0]?.check, client.commands[commandName]![0]?.callback, interaction);
+ await execute(
+ client.commands[commandName]![0]?.check,
+ client.commands[commandName]![0]?.callback,
+ interaction
+ );
return;
} else if (interaction.isMessageContextMenuCommand()) {
const commandName = "contextCommands/message/" + interaction.commandName;
- execute(client.commands[commandName]![0]?.check, client.commands[commandName]![0]?.callback, interaction);
+ await execute(
+ client.commands[commandName]![0]?.check,
+ client.commands[commandName]![0]?.callback,
+ interaction
+ );
return;
} else if (interaction.isAutocomplete()) {
const commandName = interaction.commandName;
@@ -203,7 +211,7 @@
const formatted = (choices ?? []).map((choice) => {
return { name: choice, value: choice };
});
- interaction.respond(formatted);
+ await interaction.respond(formatted);
} else if (interaction.isChatInputCommand()) {
const commandName = interaction.commandName;
const subcommandGroupName = interaction.options.getSubcommandGroup(false);
@@ -219,7 +227,7 @@
const command = client.commands[fullCommandName]![0];
const callback = command?.callback;
const check = command?.check;
- execute(check, callback, interaction);
+ await execute(check, callback, interaction);
}
});
}
diff --git a/src/utils/confirmationMessage.ts b/src/utils/confirmationMessage.ts
index 7b3bd31..59befe6 100644
--- a/src/utils/confirmationMessage.ts
+++ b/src/utils/confirmationMessage.ts
@@ -228,7 +228,7 @@
break;
}
if (component.customId === "yes") {
- component.deferUpdate();
+ await component.deferUpdate();
for (const v of Object.values(this.customButtons)) {
if (!v.active) continue;
try {
@@ -241,7 +241,7 @@
returnComponents = true;
continue;
} else if (component.customId === "no") {
- component.deferUpdate();
+ await component.deferUpdate();
success = false;
returnComponents = true;
continue;
@@ -291,10 +291,13 @@
cancelled = true;
continue;
}
- if (out === null || out.isButton()) {
+ if (out === null) {
cancelled = true;
continue;
}
+ if (out.isButton()) {
+ continue;
+ }
if (out instanceof ModalSubmitInteraction) {
newReason = out.fields.getTextInputValue("reason");
continue;
@@ -339,7 +342,11 @@
cancelled = true;
continue;
}
- if (out === null || out.isButton()) {
+ if (out === null) {
+ cancelled = true;
+ continue;
+ }
+ if (out.isButton()) {
continue;
}
if (out instanceof ModalSubmitInteraction) {
@@ -348,7 +355,7 @@
returnComponents = true;
continue;
} else {
- component.deferUpdate();
+ await component.deferUpdate();
this.customButtons[component.customId]!.active = !this.customButtons[component.customId]!.active;
returnComponents = true;
continue;
diff --git a/src/utils/database.ts b/src/utils/database.ts
index a107d06..51b2bca 100644
--- a/src/utils/database.ts
+++ b/src/utils/database.ts
@@ -268,7 +268,7 @@
const doc = await this.transcripts.insertOne(Object.assign(transcript, { code: code }), collectionOptions);
if (doc.acknowledged) {
- client.database.eventScheduler.schedule(
+ await client.database.eventScheduler.schedule(
"deleteTranscript",
(Date.now() + 1000 * 60 * 60 * 24 * 7).toString(),
{ guild: transcript.guild, code: code, iv: iv, key: key }
@@ -591,7 +591,7 @@
nsfw?: boolean;
malware?: boolean;
bad_link?: boolean;
- tags: string[];
+ tags?: string[];
}
export class ScanCache {
@@ -606,9 +606,30 @@
}
async write(hash: string, type: "nsfw" | "malware" | "bad_link", data: boolean, tags?: string[]) {
- await this.scanCache.insertOne(
- { hash: hash, [type]: data, tags: tags ?? [], addedAt: new Date() },
- collectionOptions
+ await this.scanCache.updateOne(
+ { hash: hash },
+ {
+ $set: (() => {
+ switch (type) {
+ case "nsfw": {
+ return { nsfw: data, addedAt: new Date() };
+ }
+ case "malware": {
+ return { malware: data, addedAt: new Date() };
+ }
+ case "bad_link": {
+ return { bad_link: data, tags: tags ?? [], addedAt: new Date() };
+ }
+ default: {
+ throw new Error("Invalid type");
+ }
+ }
+ })()
+ // No you can't just do { [type]: data }, yes it's a typescript error, no I don't know how to fix it
+ // cleanly, yes it would be marginally more elegant, no it's not essential, yes I'd be happy to review
+ // PRs that did improve this snippet
+ },
+ Object.assign({ upsert: true }, collectionOptions)
);
}
diff --git a/src/utils/dualCollector.ts b/src/utils/dualCollector.ts
index bf9b0c0..e96ff5d 100644
--- a/src/utils/dualCollector.ts
+++ b/src/utils/dualCollector.ts
@@ -32,11 +32,7 @@
time: 300000
})
.on("collect", (m) => {
- try {
- m.delete();
- } catch (e) {
- client.emit("error", e as Error);
- }
+ void m.delete().catch();
resolve(m);
});
mes.on("end", () => {
diff --git a/src/utils/eventScheduler.ts b/src/utils/eventScheduler.ts
index 34bb28e..48eee63 100644
--- a/src/utils/eventScheduler.ts
+++ b/src/utils/eventScheduler.ts
@@ -79,13 +79,13 @@
guild: guild.id
}
};
- log(data);
+ await log(data);
});
}
async start() {
await new Promise((resolve) => this.agenda.once("ready", resolve));
- this.agenda.start();
+ await this.agenda.start();
return this;
}
@@ -95,8 +95,8 @@
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
- cancel(name: string, data: any) {
- this.agenda.cancel({ name, data });
+ async cancel(name: string, data: any) {
+ await this.agenda.cancel({ name, data });
}
}
diff --git a/src/utils/log.ts b/src/utils/log.ts
index b29f365..8c8c0c9 100644
--- a/src/utils/log.ts
+++ b/src/utils/log.ts
@@ -127,7 +127,7 @@
)
.setTimestamp(log.meta.timestamp)
.setColor(log.meta.color);
- channel.send({ embeds: [embed] });
+ await channel.send({ embeds: [embed] });
}
}
},
diff --git a/src/utils/performanceTesting/record.ts b/src/utils/performanceTesting/record.ts
index 89f3ead..34ed206 100644
--- a/src/utils/performanceTesting/record.ts
+++ b/src/utils/performanceTesting/record.ts
@@ -14,7 +14,7 @@
const user = guild.ownerId;
const currentYear = new Date().getFullYear();
const start = Date.now();
- client.database.history.read(guild.id, user, currentYear - 1);
+ await client.database.history.read(guild.id, user, currentYear - 1);
const end = Date.now();
return end - start;
};
@@ -35,7 +35,7 @@
resources: await resources()
};
if (results.discord > 1000 || results.databaseRead > 500 || results.resources.cpu > 100) {
- singleNotify(
+ await singleNotify(
"performanceTest",
config.developmentGuildID,
`Discord ping time: \`${results.discord}ms\`\nDatabase read time: \`${
@@ -47,12 +47,12 @@
config.owners
);
} else {
- singleNotify("performanceTest", config.developmentGuildID, true);
+ await singleNotify("performanceTest", config.developmentGuildID, true);
}
- client.database.performanceTest.record(results);
- setTimeout(async () => {
- await record();
+ await client.database.performanceTest.record(results);
+ setTimeout(() => {
+ void record();
}, 60 * 1000);
};
diff --git a/src/utils/temp/generateFileName.ts b/src/utils/temp/generateFileName.ts
index 109478d..8feefbb 100644
--- a/src/utils/temp/generateFileName.ts
+++ b/src/utils/temp/generateFileName.ts
@@ -6,13 +6,13 @@
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
-export default function generateFileName(ending: string): string {
+export default async function generateFileName(ending: string): Promise<string> {
let fileName = crypto.randomBytes(35).toString("hex");
fileName = fileName.replace(/([a-zA-Z0-9]{8})/g, "$1-");
if (fs.existsSync(`./${fileName}`)) {
- fileName = generateFileName(ending);
+ fileName = await generateFileName(ending);
}
- client.database.eventScheduler.schedule("deleteFile", (Date.now() + 60 * 1000).toString(), {
+ await client.database.eventScheduler.schedule("deleteFile", (Date.now() + 60 * 1000).toString(), {
fileName: `${fileName}.${ending}`
});
return path.join(__dirname, fileName + "." + ending);
diff --git a/tsconfig.json b/tsconfig.json
index 8b0fe7d..1df2f7d 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -14,5 +14,5 @@
"noImplicitReturns": false
},
"include": ["src/**/*", "src/*", "src/config/main.d.ts", "src/config/main.ts"],
- "exclude": ["src/Unfinished/**/*"]
+ "exclude": ["src/Unfinished/**/*", "src/reflex/nsfwjs/**/*"]
}