diff --git a/src/constants/index.js b/src/constants/index.js index fdcb5a1b..9aaae42a 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -1,4 +1,26 @@ import path from "node:path"; +import { GatewayIntentBits } from "discord.js"; +import { AsyncLocalStorage } from "node:async_hooks"; export const PROJECT_ROOT = path.join(import.meta.dirname, ".."); export const CONFIG_PATH = path.join(PROJECT_ROOT, "..", "config.json"); +export const CLIENT_INTENTS = [ + GatewayIntentBits.Guilds, + GatewayIntentBits.GuildMembers, + GatewayIntentBits.GuildModeration, + GatewayIntentBits.GuildEmojisAndStickers, + GatewayIntentBits.GuildIntegrations, + GatewayIntentBits.GuildInvites, + GatewayIntentBits.GuildVoiceStates, + GatewayIntentBits.GuildPresences, + GatewayIntentBits.GuildMessages, + GatewayIntentBits.GuildMessageReactions, + GatewayIntentBits.GuildMessageTyping, + GatewayIntentBits.MessageContent, + GatewayIntentBits.DirectMessageTyping, + GatewayIntentBits.DirectMessages, + GatewayIntentBits.DirectMessageReactions, +]; +export const CLIENT_ALLOWED_MENTIONS = { parse: ["everyone", "roles", "users"] }; + +export const SUPER_CONTEXT = new AsyncLocalStorage(); diff --git a/src/handlers/command-handler/index.js b/src/handlers/command-handler/index.js index 6afbb311..53b6271f 100644 --- a/src/handlers/command-handler/index.js +++ b/src/handlers/command-handler/index.js @@ -1,6 +1,6 @@ import { resolve } from "node:path"; import logger from "../../helpers/logger.js"; -import { client } from "../../index.js"; +import useClient from "../../utils/use-client.js"; import { getFilePaths } from "../../utils/index.js"; import { toFileURL } from "../../utils/resolve-file.js"; import registerCommands from "./functions/registerCommands.js"; @@ -8,6 +8,7 @@ import registerCommands from "./functions/registerCommands.js"; export const commands = []; export const init = async () => { + const client = useClient(); await buildCommands(); await registerCommands({ @@ -17,6 +18,7 @@ export const init = async () => { }; const buildCommands = async () => { + const client = useClient(); const cmdPath = resolve(client.configService.get("paths.commands")); const commandFilePaths = (await getFilePaths(cmdPath, true)).filter(path => path.endsWith(".js")); diff --git a/src/handlers/event-handler/index.js b/src/handlers/event-handler/index.js index a057b156..c63d2dc7 100644 --- a/src/handlers/event-handler/index.js +++ b/src/handlers/event-handler/index.js @@ -1,6 +1,6 @@ import { resolve } from "node:path"; import logger from "../../helpers/logger.js"; -import { client } from "../../index.js"; +import useClient from "../../utils/use-client.js"; import { getFilePaths } from "../../utils/index.js"; import { toFileURL } from "../../utils/resolve-file.js"; @@ -12,6 +12,7 @@ export const init = async () => { }; const buildEvents = async () => { + const client = useClient(); try { const eventPath = resolve(client.configService.get("paths.events")); const eventFilePaths = (await getFilePaths(eventPath, true)).filter(path => path.endsWith(".js")); @@ -37,6 +38,7 @@ const buildEvents = async () => { }; const registerEvents = async () => { + const client = useClient(); for (const { data, run } of events) { if (data.once) client.once(data.name, run); else client.on(data.name, run); diff --git a/src/index.js b/src/index.js index 79600f71..70f4de55 100644 --- a/src/index.js +++ b/src/index.js @@ -1,26 +1,10 @@ -import { GatewayIntentBits } from "discord.js"; import { ExtendedClient } from "./structures/client.js"; import logger from "./helpers/logger.js"; +import { CLIENT_INTENTS, CLIENT_ALLOWED_MENTIONS } from "./constants/index.js"; -export const client = new ExtendedClient({ - intents: [ - GatewayIntentBits.Guilds, - GatewayIntentBits.GuildMembers, - GatewayIntentBits.GuildModeration, - GatewayIntentBits.GuildEmojisAndStickers, - GatewayIntentBits.GuildIntegrations, - GatewayIntentBits.GuildInvites, - GatewayIntentBits.GuildVoiceStates, - GatewayIntentBits.GuildPresences, - GatewayIntentBits.GuildMessages, - GatewayIntentBits.GuildMessageReactions, - GatewayIntentBits.GuildMessageTyping, - GatewayIntentBits.MessageContent, - GatewayIntentBits.DirectMessageTyping, - GatewayIntentBits.DirectMessages, - GatewayIntentBits.DirectMessageReactions, - ], - allowedMentions: { parse: ["everyone", "roles", "users"] }, +const client = new ExtendedClient({ + intents: CLIENT_INTENTS, + allowedMentions: CLIENT_ALLOWED_MENTIONS, }); client.init(); diff --git a/src/models/GuildModel.js b/src/models/GuildModel.js index da3b57f2..d52c2a54 100644 --- a/src/models/GuildModel.js +++ b/src/models/GuildModel.js @@ -1,5 +1,7 @@ import { model, Schema } from "mongoose"; -import { client } from "../index.js"; +import useClient from "../utils/use-client.js"; + +const client = useClient(); export default model( "Guild", diff --git a/src/structures/client.js b/src/structures/client.js index c55a5ac3..a25c9f47 100644 --- a/src/structures/client.js +++ b/src/structures/client.js @@ -5,17 +5,23 @@ import { init as initEvents } from "../handlers/event-handler/index.js"; import logger from "../helpers/logger.js"; import ConfigService from "../services/config/index.js"; import InternationalizationService from "../services/languages/index.js"; +import { SUPER_CONTEXT } from "../constants/index.js"; export class ExtendedClient extends Client { /** * @param {import("discord.js").ClientOptions} options */ constructor(options) { + if (SUPER_CONTEXT.getStore()) { + return SUPER_CONTEXT.getStore(); + } super(options); this.configService = new ConfigService(); this.adapter = new MongooseAdapter(this.configService.get("mongoDB")); this.i18n = new InternationalizationService(this); + + SUPER_CONTEXT.enterWith(this); } async init() { diff --git a/src/utils/create-embed.js b/src/utils/create-embed.js index dbf1c281..27199569 100644 --- a/src/utils/create-embed.js +++ b/src/utils/create-embed.js @@ -1,14 +1,15 @@ import { EmbedBuilder } from "discord.js"; -import { client } from "../index.js"; - +import useClient from "../utils/use-client.js"; /** * * @param {import("discord.js").EmbedData} data - embed data * @returns The generated EmbedBuilder instance. */ -export const createEmbed = data => +export const createEmbed = data => { + const client = useClient(); new EmbedBuilder({ footer: typeof data.footer === "object" ? data.footer : data.footer ? { text: data.footer } : client.configService.get("embed.footer"), color: data.color ?? client.configService.get("embed.color"), ...data, }); +}; diff --git a/src/utils/use-client.js b/src/utils/use-client.js new file mode 100644 index 00000000..3514ce05 --- /dev/null +++ b/src/utils/use-client.js @@ -0,0 +1,16 @@ +import { SUPER_CONTEXT } from "../constants/index.js"; + +/** + * Returns the instance of the client. + * + * @throws {Error} Client is not initialized. Please initialize it first. + * + * @returns {import("../structures/client.js").ExtendedClient} The client instance. + */ +export default function useClient() { + const store = SUPER_CONTEXT.getStore(); + if (!store) { + throw new Error("Client is not initialized. Please initialize it first."); + } + return store; +}