Merge remote-tracking branch 'refs/remotes/origin/development' into development
diff --git a/package-lock.json b/package-lock.json
index 61e0f8f..0615b7e 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -17,6 +17,8 @@
"humanize-duration": "^3.27.1",
"jshaiku": "file:../haiku",
"json-diff": "^0.7.1",
+ "node-tesseract": "^0.2.7",
+ "structured-clone": "^0.2.2",
"tesseract.js": "^2.1.5",
"typescript": "^4.5.5",
"unscan": "^1.1.2"
@@ -904,6 +906,39 @@
}
}
},
+ "node_modules/node-tesseract": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/node-tesseract/-/node-tesseract-0.2.7.tgz",
+ "integrity": "sha1-yPAvuDUaQnByc1d4wFGYI/JgG4Q=",
+ "dependencies": {
+ "glob": "^5.0.10",
+ "node-uuid": "^1.4.1"
+ }
+ },
+ "node_modules/node-tesseract/node_modules/glob": {
+ "version": "5.0.15",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
+ "dependencies": {
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "2 || 3",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/node-uuid": {
+ "version": "1.4.8",
+ "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz",
+ "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc=",
+ "deprecated": "Use uuid module instead",
+ "bin": {
+ "uuid": "bin/uuid"
+ }
+ },
"node_modules/object-inspect": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
@@ -1116,6 +1151,11 @@
"node": ">= 0.8"
}
},
+ "node_modules/structured-clone": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/structured-clone/-/structured-clone-0.2.2.tgz",
+ "integrity": "sha1-rJK2vjGVimQ9sw8TNavGobAt/cI="
+ },
"node_modules/tesseract.js": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/tesseract.js/-/tesseract.js-2.1.5.tgz",
@@ -2004,6 +2044,34 @@
"whatwg-url": "^5.0.0"
}
},
+ "node-tesseract": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/node-tesseract/-/node-tesseract-0.2.7.tgz",
+ "integrity": "sha1-yPAvuDUaQnByc1d4wFGYI/JgG4Q=",
+ "requires": {
+ "glob": "^5.0.10",
+ "node-uuid": "^1.4.1"
+ },
+ "dependencies": {
+ "glob": {
+ "version": "5.0.15",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
+ "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=",
+ "requires": {
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "2 || 3",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ }
+ }
+ },
+ "node-uuid": {
+ "version": "1.4.8",
+ "resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz",
+ "integrity": "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc="
+ },
"object-inspect": {
"version": "1.12.0",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz",
@@ -2161,6 +2229,11 @@
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="
},
+ "structured-clone": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/structured-clone/-/structured-clone-0.2.2.tgz",
+ "integrity": "sha1-rJK2vjGVimQ9sw8TNavGobAt/cI="
+ },
"tesseract.js": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/tesseract.js/-/tesseract.js-2.1.5.tgz",
diff --git a/package.json b/package.json
index dd55984..7287aef 100644
--- a/package.json
+++ b/package.json
@@ -8,6 +8,8 @@
"humanize-duration": "^3.27.1",
"jshaiku": "file:../haiku",
"json-diff": "^0.7.1",
+ "node-tesseract": "^0.2.7",
+ "structured-clone": "^0.2.2",
"tesseract.js": "^2.1.5",
"typescript": "^4.5.5",
"unscan": "^1.1.2"
@@ -35,6 +37,6 @@
"url": "https://github.com/ClicksMinutePer/Nucleus/issues"
},
"homepage": "https://github.com/ClicksMinutePer/Nucleus#readme",
- "private": true,
+ "private": false,
"type": "module"
}
diff --git a/src/automations/guide.ts b/src/automations/guide.ts
index e3cfa25..19a3337 100644
--- a/src/automations/guide.ts
+++ b/src/automations/guide.ts
@@ -1,6 +1,7 @@
import Discord, { MessageActionRow, MessageButton } from "discord.js";
import generateEmojiEmbed from "../utils/generateEmojiEmbed.js";
import getEmojiByName from "../utils/getEmojiByName.js";
+import createPageIndicator from "../utils/createPageIndicator.js";
export default async (guild, interaction?) => {
let c = guild.publicUpdatesChannel ? guild.publicUpdatesChannel : guild.systemChannel;
@@ -39,7 +40,7 @@
`**${getEmojiByName("PUNISH.KICK.RED")} Kick:** The user is removed from the server.\n` +
`**${getEmojiByName("PUNISH.SOFTBAN")} Softban:** Kicks the user, deleting their messages from every channel.\n` +
`**${getEmojiByName("PUNISH.BAN.RED")} Ban:** The user is removed from the server, and they are unable to rejoin.\n` +
- `**${getEmojiByName("PUNISH.BAN.GREEN")} Unban:** The user is able to rejoin the server.\n`
+ `**${getEmojiByName("PUNISH.BAN.GREEN")} Unban:** The user is able to rejoin the server.`
)
.setEmoji("NUCLEUS.LOGO")
.setStatus("Danger"),
@@ -99,8 +100,10 @@
while (true) {
if (interaction) {
+ let em = new Discord.MessageEmbed(pages[page])
+ em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page));
await interaction.editReply({
- embeds: [pages[page].setFooter({text: `Page ${page + 1}/${pages.length}`})],
+ embeds: [em],
components: [new MessageActionRow().addComponents([
new MessageButton().setCustomId("left").setEmoji(getEmojiByName("CONTROL.LEFT", "id")).setStyle("SECONDARY").setDisabled(page === 0),
new MessageButton().setCustomId("right").setEmoji(getEmojiByName("CONTROL.RIGHT", "id")).setStyle("SECONDARY").setDisabled(page === pages.length - 1),
@@ -130,7 +133,13 @@
if (page < pages.length - 1) page++;
} else if (i.component.customId == "close") {
if (interaction) {
- interaction.delete();
+ let em = new Discord.MessageEmbed(pages[page])
+ em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page) + " | Message closed");
+ interaction.editReply({embeds: [em], components: [new MessageActionRow().addComponents([
+ new MessageButton().setCustomId("left").setEmoji(getEmojiByName("CONTROL.LEFT", "id")).setStyle("SECONDARY").setDisabled(true),
+ new MessageButton().setCustomId("right").setEmoji(getEmojiByName("CONTROL.RIGHT", "id")).setStyle("SECONDARY").setDisabled(true),
+ new MessageButton().setCustomId("close").setEmoji(getEmojiByName("CONTROL.CROSS", "id")).setStyle("DANGER").setDisabled(true)
+ ])], fetchReply: true});
} else {
m.delete();
}
@@ -141,8 +150,10 @@
}
}
if (interaction) {
+ let em = new Discord.MessageEmbed(pages[page])
+ em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page) + " | Message timed out");
await interaction.editReply({
- embeds: [pages[page].setFooter({text: `Page ${page + 1}/${pages.length} | Message timed out`})],
+ embeds: [em],
components: [new MessageActionRow().addComponents([
new MessageButton().setCustomId("left").setEmoji(getEmojiByName("CONTROL.LEFT", "id")).setStyle("SECONDARY").setDisabled(true),
new MessageButton().setCustomId("right").setEmoji(getEmojiByName("CONTROL.RIGHT", "id")).setStyle("SECONDARY").setDisabled(true),
@@ -150,8 +161,10 @@
])]
});
} else {
+ let em = new Discord.MessageEmbed(pages[page])
+ em.setDescription(em.description + "\n\n" + createPageIndicator(pages.length, page) + " | Message timed out");
await m.edit({
- embeds: [pages[page].setFooter({text: `Page ${page + 1}/${pages.length} | Message timed out`})],
+ embeds: [em],
components: [new MessageActionRow().addComponents([
new MessageButton().setCustomId("left").setEmoji(getEmojiByName("CONTROL.LEFT", "id")).setStyle("SECONDARY").setDisabled(true),
new MessageButton().setCustomId("right").setEmoji(getEmojiByName("CONTROL.RIGHT", "id")).setStyle("SECONDARY").setDisabled(true),
diff --git a/src/automations/unscan.ts b/src/automations/unscan.ts
index b5c5ffb..d3a2a18 100644
--- a/src/automations/unscan.ts
+++ b/src/automations/unscan.ts
@@ -1,5 +1,5 @@
import * as scan from '../utils/scanners.js'
-import Tesseract from 'tesseract.js';
+import process from 'tesseract.js'
export async function LinkCheck(message): Promise<boolean> {
let links = message.content.match(/https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/gi) ?? []
@@ -70,4 +70,4 @@
export async function TestImage(element): Promise<string> {
return "";
-}
\ No newline at end of file
+}
diff --git a/src/automations/verify.ts b/src/automations/verify.ts
index a60ed07..3d4e658 100644
--- a/src/automations/verify.ts
+++ b/src/automations/verify.ts
@@ -3,12 +3,18 @@
import readConfig from "../utils/readConfig.js";
import fetch from "node-fetch";
import { TestString, NSFWCheck } from "../automations/unscan.js";
+import createPageIndicator from "../utils/createPageIndicator.js";
+
+function step(i) {
+ return "\n\n" + createPageIndicator(5, i);
+}
export default async function(interaction) {
// @ts-ignore
let verify = interaction.client.verify
await interaction.reply({embeds: [new generateEmojiEmbed()
.setTitle("Loading")
+ .setDescription(step(-1))
.setStatus("Danger")
.setEmoji("NUCLEUS.LOADING")
], ephemeral: true, fetchReply: true});
@@ -16,23 +22,23 @@
if ((interaction.member as GuildMember).roles.cache.has(config.verify.role)) {
return await interaction.editReply({embeds: [new generateEmojiEmbed()
.setTitle("Verify")
- .setDescription(`You already have the <@&${config.verify.role}> role`)
+ .setDescription(`You already have the <@&${config.verify.role}> role` + step(0))
.setStatus("Danger")
.setEmoji("CONTROL.BLOCKCROSS")
]});
}
await interaction.editReply({embeds: [new generateEmojiEmbed()
.setTitle("Verify")
- .setDescription(`Checking our servers are up`)
+ .setDescription(`Checking our servers are up` + step(0))
.setStatus("Warning")
.setEmoji("NUCLEUS.LOADING")
]});
try {
- let status = await fetch(`https://clicks.codes`).then(res => res.status);
+ let status = await fetch(`https://clicks.codes/`).then(res => res.status);
if (status != 200) {
return await interaction.editReply({embeds: [new generateEmojiEmbed()
.setTitle("Verify")
- .setDescription(`Our servers appear to be down, please try again later`)
+ .setDescription(`Our servers appear to be down, please try again later` + step(0))
.setStatus("Danger")
.setEmoji("CONTROL.BLOCKCROSS")
]});
@@ -40,7 +46,7 @@
} catch {
return await interaction.editReply({embeds: [new generateEmojiEmbed()
.setTitle("Verify")
- .setDescription(`Our servers appear to be down, please try again later`)
+ .setDescription(`Our servers appear to be down, please try again later` + step(0))
.setStatus("Danger")
.setEmoji("CONTROL.BLOCKCROSS")
], components: [new Discord.MessageActionRow().addComponents([
@@ -57,14 +63,14 @@
if (config.filters.images.NSFW) {
await interaction.editReply({embeds: [new generateEmojiEmbed()
.setTitle("Verify")
- .setDescription(`Checking your avatar is safe for work`)
+ .setDescription(`Checking your avatar is safe for work` + step(1))
.setStatus("Warning")
.setEmoji("NUCLEUS.LOADING")
]});
if (await NSFWCheck((interaction.member as GuildMember).user.avatarURL({format: "png"}))) {
return await interaction.editReply({embeds: [new generateEmojiEmbed()
.setTitle("Verify")
- .setDescription(`Your avatar was detected as NSFW, which we do not allow in this server.\nPlease contact one of our staff members if you believe this is a mistake`)
+ .setDescription(`Your avatar was detected as NSFW, which we do not allow in this server.\nPlease contact one of our staff members if you believe this is a mistake` + step(1))
.setStatus("Danger")
.setEmoji("CONTROL.BLOCKCROSS")
]});
@@ -73,14 +79,14 @@
if (config.filters.wordFilter) {
await interaction.editReply({embeds: [new generateEmojiEmbed()
.setTitle("Verify")
- .setDescription(`Checking your name is allowed`)
+ .setDescription(`Checking your name is allowed` + step(2))
.setStatus("Warning")
.setEmoji("NUCLEUS.LOADING")
]});
if (TestString((interaction.member as Discord.GuildMember).displayName, config.filters.wordFilter.words.loose, config.filters.wordFilter.words.strict) != "none") {
return await interaction.editReply({embeds: [new generateEmojiEmbed()
.setTitle("Verify")
- .setDescription(`Your name contained a word we do not allow in this server.\nPlease contact one of our staff members if you believe this is a mistake`)
+ .setDescription(`Your name contained a word we do not allow in this server.\nPlease contact one of our staff members if you believe this is a mistake` + step(2))
.setStatus("Danger")
.setEmoji("CONTROL.BLOCKCROSS")
]});
@@ -88,7 +94,7 @@
}
await interaction.editReply({embeds: [new generateEmojiEmbed()
.setTitle("Verify")
- .setDescription(`One moment...`)
+ .setDescription(`One moment...` + step(3))
.setStatus("Warning")
.setEmoji("NUCLEUS.LOADING")
]});
@@ -120,7 +126,7 @@
}
await interaction.editReply({embeds: [new generateEmojiEmbed()
.setTitle("Verify")
- .setDescription(`Looking good!\nClick the button below to get verified`)
+ .setDescription(`Looking good!\nClick the button below to get verified` + step(4))
.setStatus("Success")
.setEmoji("MEMBER.JOIN")
], components: [new Discord.MessageActionRow().addComponents([new Discord.MessageButton()
diff --git a/src/commands/user/about.ts b/src/commands/user/about.ts
index b6e2aee..788054e 100644
--- a/src/commands/user/about.ts
+++ b/src/commands/user/about.ts
@@ -4,6 +4,7 @@
import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
import getEmojiByName from "../../utils/getEmojiByName.js";
import generateKeyValueList from "../../utils/generateKeyValueList.js";
+import createPageIndicator from "../../utils/createPageIndicator.js";
const command = (builder: SlashCommandSubcommandBuilder) =>
builder
@@ -120,7 +121,7 @@
"id": `\`${member.id}\``,
"roles": `${member.roles.cache.size - 1}`,
}) + "\n" +
- (s.length > 0 ? s : "*None*")
+ (s.length > 0 ? s : "*None*") + "\n"
)
.setThumbnail(await member.user.displayAvatarURL({dynamic: true})),
new generateEmojiEmbed()
@@ -139,8 +140,10 @@
m = await interaction.reply({embeds: [new generateEmojiEmbed().setTitle("Loading").setEmoji("NUCLEUS.LOADING").setStatus("Danger")], fetchReply: true, ephemeral: true});
let page = 0
while (true) {
+ let em = new Discord.MessageEmbed(embeds[page])
+ em.setDescription(em.description + "\n" + createPageIndicator(embeds.length, page));
await interaction.editReply({
- embeds: [embeds[page].setFooter({text: `Page ${page + 1} of ${embeds.length}`})],
+ embeds: [em],
components: [new MessageActionRow().addComponents([
new MessageButton()
.setEmoji(getEmojiByName("CONTROL.LEFT", "id"))
diff --git a/src/events/commandError.ts b/src/events/commandError.ts
new file mode 100644
index 0000000..ba47426
--- /dev/null
+++ b/src/events/commandError.ts
@@ -0,0 +1,21 @@
+import generateEmojiEmbed from "../utils/generateEmojiEmbed.js";
+
+export const event = 'commandError'
+
+export async function callback(client, interaction, error) {
+ if (interaction.replied || interaction.deferred) {
+ await interaction.followUp({embeds: [new generateEmojiEmbed()
+ .setTitle("Something went wrong")
+ .setDescription(error.message ?? error.toString())
+ .setStatus("Danger")
+ .setEmoji("CONTROL.BLOCKCROSS")
+ ], ephemeral: true})
+ } else {
+ await interaction.reply({embeds: [new generateEmojiEmbed()
+ .setTitle("Something went wrong")
+ .setDescription(error.message ?? error.toString())
+ .setStatus("Danger")
+ .setEmoji("CONTROL.BLOCKCROSS")
+ ], ephemeral: true})
+ }
+}
diff --git a/src/utils/createPageIndicator.ts b/src/utils/createPageIndicator.ts
new file mode 100644
index 0000000..8e18e30
--- /dev/null
+++ b/src/utils/createPageIndicator.ts
@@ -0,0 +1,22 @@
+import getEmojiByName from "./getEmojiByName.js";
+
+function pageIndicator(amount: number, selected: number, showDetails?: boolean | true) {
+ let out = "";
+
+ if (amount == 1) {
+ out += getEmojiByName("TRACKS.SINGLE." + (selected == 0 ? "ACTIVE" : "INACTIVE"));
+ } else {
+ for (let i = 0; i < amount; i++) {
+ out += getEmojiByName("TRACKS.HORIZONTAL." +
+ (i == 0 ? "LEFT" : (i == amount - 1 ? "RIGHT" : "MIDDLE")) + "." +
+ (i == selected ? "ACTIVE" : "INACTIVE")
+ );
+ }
+ }
+ if (showDetails) {
+ out += " Page " + selected + " of " + amount;
+ }
+ return out;
+}
+
+export default pageIndicator;
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index 715459c..4ae6519 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -423,6 +423,17 @@
"has" "^1.0.3"
"has-symbols" "^1.0.1"
+"glob@^5.0.10":
+ "integrity" "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E="
+ "resolved" "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz"
+ "version" "5.0.15"
+ dependencies:
+ "inflight" "^1.0.4"
+ "inherits" "2"
+ "minimatch" "2 || 3"
+ "once" "^1.3.0"
+ "path-is-absolute" "^1.0.0"
+
"glob@^7.1.6":
"integrity" "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q=="
"resolved" "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz"
@@ -609,7 +620,7 @@
"resolved" "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz"
"version" "1.6.0"
-"minimatch@^3.0.4":
+"minimatch@^3.0.4", "minimatch@2 || 3":
"integrity" "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="
"resolved" "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz"
"version" "3.1.2"
@@ -643,6 +654,19 @@
dependencies:
"whatwg-url" "^5.0.0"
+"node-tesseract@^0.2.7":
+ "integrity" "sha1-yPAvuDUaQnByc1d4wFGYI/JgG4Q="
+ "resolved" "https://registry.npmjs.org/node-tesseract/-/node-tesseract-0.2.7.tgz"
+ "version" "0.2.7"
+ dependencies:
+ "glob" "^5.0.10"
+ "node-uuid" "^1.4.1"
+
+"node-uuid@^1.4.1":
+ "integrity" "sha1-sEDrCSOWivq/jTL7HxfxFn/auQc="
+ "resolved" "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.8.tgz"
+ "version" "1.4.8"
+
"object-inspect@^1.9.0":
"integrity" "sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g=="
"resolved" "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.0.tgz"
@@ -785,6 +809,11 @@
"resolved" "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz"
"version" "2.0.1"
+"structured-clone@^0.2.2":
+ "integrity" "sha1-rJK2vjGVimQ9sw8TNavGobAt/cI="
+ "resolved" "https://registry.npmjs.org/structured-clone/-/structured-clone-0.2.2.tgz"
+ "version" "0.2.2"
+
"tesseract.js-core@^2.2.0":
"integrity" "sha512-a8L+OJTbUipBsEDsJhDPlnLB0TY1MkTZqw5dqUwmiDSjUzwvU7HWLg/2+WDRulKUi4LE+7PnHlaBlW0k+V0U0w=="
"resolved" "https://registry.npmjs.org/tesseract.js-core/-/tesseract.js-core-2.2.0.tgz"