COMMAND REGISTRATION WORKS
diff --git a/src/utils/client.ts b/src/utils/client.ts
index 1795cfa..7d608c7 100644
--- a/src/utils/client.ts
+++ b/src/utils/client.ts
@@ -1,13 +1,39 @@
-// @ts-expect-error
-import { HaikuClient } from "jshaiku";
-import { Intents } from "discord.js";
-import config from "../config/main.json" assert { type: "json" };
+import { Client } from 'discord.js';
+import { Logger } from "../utils/log.js";
+import Memory from "../utils/memory.js";
+import type { VerifySchema } from "../reflex/verify.js";
+import { Guilds, History, ModNotes, Premium } from "../utils/database.js";
+import EventScheduler from "../utils/eventScheduler.js";
+import type { RoleMenuSchema } from "../actions/roleMenu.js";
-const client = new HaikuClient(
- {
- intents: new Intents(32767).bitfield // This is a way of specifying all intents w/o having to type them out
- },
- config
-);
+
+class NucleusClient extends Client {
+ logger = Logger;
+ verify: Record<string, VerifySchema> = {};
+ roleMenu: Record<string, RoleMenuSchema> = {};
+ memory: Memory = new Memory() as Memory;
+ noLog: string[] = [];
+ database: {
+ guilds: Guilds;
+ history: History;
+ notes: ModNotes;
+ premium: Premium;
+ eventScheduler: EventScheduler;
+ };
+
+ constructor(database: typeof NucleusClient.prototype.database) {
+ super({ intents: 32767 });
+ this.database = database;
+ }
+}
+
+const client = new NucleusClient({
+ guilds: new Guilds(),
+ history: new History(),
+ notes: new ModNotes(),
+ premium: new Premium(),
+ eventScheduler: new EventScheduler()
+});
export default client;
+export { NucleusClient };
\ No newline at end of file
diff --git a/src/utils/commandRegistration/getFilesInFolder.ts b/src/utils/commandRegistration/getFilesInFolder.ts
new file mode 100644
index 0000000..a669065
--- /dev/null
+++ b/src/utils/commandRegistration/getFilesInFolder.ts
@@ -0,0 +1,23 @@
+import fs from "fs";
+
+export default async function getSubcommandsInFolder(path: string) {
+ const files = fs.readdirSync(path, { withFileTypes: true }).filter(
+ file => !file.name.endsWith(".ts") && !file.name.endsWith(".map")
+ );
+ const subcommands = [];
+ const subcommandGroups = [];
+ for (const file of files) {
+ if (file.name === "_meta.js") continue;
+ // If its a folder
+ if (file.isDirectory()) {
+ // Get the _meta.ts file
+ console.log(`│ ├─ Loading subcommand group ${file.name}}`)
+ subcommandGroups.push((await import(`../../../${path}/${file.name}/_meta.js`)).command);
+ } else if (file.name.endsWith(".js")) {
+ // If its a file
+ console.log(`│ ├─ Loading subcommand ${file.name}}`)
+ subcommands.push((await import(`../../../${path}/${file.name}`)).command);
+ }
+ }
+ return {subcommands, subcommandGroups};
+}
diff --git a/src/utils/commandRegistration/register.ts b/src/utils/commandRegistration/register.ts
new file mode 100644
index 0000000..af0b5fc
--- /dev/null
+++ b/src/utils/commandRegistration/register.ts
@@ -0,0 +1,61 @@
+import { SlashCommandBuilder } from 'discord.js';
+import config from "../../config/main.json" assert { type: "json" };
+import client from "../client.js";
+import fs from "fs";
+
+
+async function registerCommands() {
+ const developmentMode = config.enableDevelopment;
+ const commands = [];
+
+ const files = fs.readdirSync(config.commandsFolder, { withFileTypes: true }).filter(
+ file => !file.name.endsWith(".ts") && !file.name.endsWith(".map")
+ );
+ console.log(`Registering ${files.length} commands`)
+ let i = 0;
+ for (const file of files) {
+ // Box drawing characters: | └ ─ ┌ ┐ ┘ ┬ ┤ ├ ┴ ┼
+ console.log(`├─ ${file.name}`)
+ if (file.isDirectory()) {
+ commands.push((await import(`../../../${config.commandsFolder}/${file.name}/_meta.js`)).command);
+ } else if (file.name.endsWith(".js")) {
+ commands.push((await import(`../../../${config.commandsFolder}/${file.name}`)).command);
+ }
+ i++;
+ console.log(`├─ Loaded ${file.name} [${i} / ${files.length}]`)
+ }
+ console.log(`Loaded ${commands.length} commands, processing...`)
+ const processed = []
+
+ for (const subcommand of commands) {
+ if (subcommand instanceof Function) {
+ processed.push(subcommand(new SlashCommandBuilder()))
+ } else {
+ processed.push(subcommand)
+ }
+ }
+
+ console.log(`Processed ${commands.length} commands, registering...`)
+
+ if (developmentMode) {
+ const guild = await client.guilds.fetch(config.developmentGuildID);
+ guild.commands.set([])
+ guild.commands.set(processed);
+ console.log(`Commands registered in ${guild.name}`)
+ } else {
+ client.application!.commands.set([])
+ client.application!.commands.set(processed);
+ console.log(`Commands registered globally`)
+ }
+
+};
+
+async function registerEvents() {
+ // pass
+};
+
+export default async function register() {
+ console.log("> Registering commands")
+ await registerCommands();
+ await registerEvents();
+};
diff --git a/src/utils/commandRegistration/slashCommandBuilder.ts b/src/utils/commandRegistration/slashCommandBuilder.ts
new file mode 100644
index 0000000..719855f
--- /dev/null
+++ b/src/utils/commandRegistration/slashCommandBuilder.ts
@@ -0,0 +1,37 @@
+import type { SlashCommandSubcommandGroupBuilder } from "@discordjs/builders";
+import type { SlashCommandBuilder } from "discord.js";
+import config from "../../config/main.json" assert { type: "json" };
+import getSubcommandsInFolder from "./getFilesInFolder.js";
+
+
+export async function group(name: string, description: string, path: string) {
+ const fetched = await getSubcommandsInFolder(config.commandsFolder + "/" + path)
+ return (subcommandGroup: SlashCommandSubcommandGroupBuilder) => {
+ subcommandGroup
+ .setName(name)
+ .setDescription(description)
+
+ for (const subcommand of fetched.subcommands) {
+ subcommandGroup.addSubcommand(subcommand);
+ };
+
+ return subcommandGroup;
+ };
+}
+
+export async function command(name: string, description: string, path: string) {
+ const fetched = await getSubcommandsInFolder(config.commandsFolder + "/" + path);
+ console.log(`│ ├─ Loaded ${fetched.subcommands.length} subcommands and ${fetched.subcommandGroups.length} subcommand groups for ${name}`)
+ return (command: SlashCommandBuilder) => {
+ command.setName(name)
+ command.setDescription(description)
+
+ for (const subcommand of fetched.subcommands) {
+ command.addSubcommand(subcommand);
+ }
+ for (const group of fetched.subcommandGroups) {
+ command.addSubcommandGroup(group);
+ };
+ return command;
+ };
+}
diff --git a/src/utils/log.ts b/src/utils/log.ts
index e4ac4cd..a578b69 100644
--- a/src/utils/log.ts
+++ b/src/utils/log.ts
@@ -7,58 +7,54 @@
const wait = promisify(setTimeout);
-export class Logger {
+
+export const Logger = {
renderUser(user: Discord.User | string) {
if (typeof user === "string") return `${user} [<@${user}>]`;
return `${user.username} [<@${user.id}>]`;
- }
+ },
renderTime(t: number) {
t = Math.floor((t /= 1000));
return `<t:${t}:D> at <t:${t}:T>`;
- }
+ },
renderDelta(t: number) {
t = Math.floor((t /= 1000));
return `<t:${t}:R> (<t:${t}:D> at <t:${t}:T>)`;
- }
+ },
renderNumberDelta(num1: number, num2: number) {
const delta = num2 - num1;
return `${num1} -> ${num2} (${delta > 0 ? "+" : ""}${delta})`;
- }
+ },
entry(value: string, displayValue: string): { value: string; displayValue: string } {
return { value: value, displayValue: displayValue };
- }
+ },
renderChannel(channel: Discord.GuildChannel | Discord.ThreadChannel) {
return `${channel.name} [<#${channel.id}>]`;
- }
+ },
renderRole(role: Discord.Role) {
return `${role.name} [<@&${role.id}>]`;
- }
+ },
renderEmoji(emoji: Discord.GuildEmoji) {
return `<${emoji.animated ? "a" : ""}:${emoji.name}:${emoji.id}> [\`:${emoji.name}:\`]`;
- }
-
- public readonly NucleusColors: Record<string, number> = {
+ },
+ NucleusColors: {
red: 0xf27878,
yellow: 0xf2d478,
green: 0x68d49e
- };
-
- async getAuditLog(
- guild: Discord.Guild,
- event: Discord.GuildAuditLogsResolvable
- ): Promise<Discord.GuildAuditLogsEntry[]> {
+ },
+ async getAuditLog(guild: Discord.Guild, event: Discord.GuildAuditLogsResolvable): Promise<Discord.GuildAuditLogsEntry[]> {
await wait(250);
const auditLog = await guild.fetchAuditLogs({ type: event });
return auditLog as unknown as Discord.GuildAuditLogsEntry[];
- }
-
+ },
// eslint-disable-next-line @typescript-eslint/no-explicit-any
async log(log: any): Promise<void> {
const config = await client.database.guilds.read(log.hidden.guild);
if (!config.logging.logs.enabled) return;
if (!(log.meta.calculateType === true)) {
if (!toHexArray(config.logging.logs.toLog).includes(log.meta.calculateType))
- return console.log("Not logging this type of event");
+ console.log("Not logging this type of event");
+ return;
}
if (config.logging.logs.channel) {
const channel = (await client.channels.fetch(config.logging.logs.channel)) as Discord.TextChannel | null;
@@ -79,8 +75,8 @@
.setTitle(`${getEmojiByName(log.meta.emoji)} ${log.meta.displayName}`)
.setDescription(
(log.separate.start ? log.separate.start + "\n" : "") +
- generateKeyValueList(description) +
- (log.separate.end ? "\n" + log.separate.end : "")
+ generateKeyValueList(description) +
+ (log.separate.end ? "\n" + log.separate.end : "")
)
.setTimestamp(log.meta.timestamp)
.setColor(log.meta.color);
@@ -88,6 +84,7 @@
}
}
}
-}
+};
+
export default {};