1import { readdirSync, statSync } from 'node:fs'
2import { join } from 'node:path'
3import { Client, Collection } from 'discord.js'
4import { Bot, Command, Event } from '@/types/bot'
5import Logger from '@/classes/logger'
6
7const isProd = process.env.NODE_ENV === 'production'
8
9export const commands = new Collection<string, Command>()
10export const events = new Collection<string, Event>()
11
12export function loadCommands(path: string) {
13 Logger.log('debug', `Loading commands from ${path}`)
14
15 try {
16 const files = readdirSync(path)
17
18 for (const file of files) {
19 const filePath = join(path, file)
20 const stat = statSync(filePath)
21
22 if (stat.isDirectory()) {
23 loadCommands(filePath)
24 continue
25 }
26
27 const fileExtension = isProd ? '.js' : '.ts'
28 if (!file.endsWith(fileExtension)) {
29 continue
30 }
31
32 try {
33 const command = require(filePath)
34
35 if (!command.default?.data?.name) {
36 Logger.log(
37 'warn',
38 `Command ${file} is missing required properties`,
39 'Commands',
40 )
41 continue
42 }
43
44 commands.set(command.default.data.name, command.default)
45 Logger.log('info', `Loaded command: ${file}`, 'Commands')
46 } catch (error: any) {
47 Logger.log(
48 'error',
49 `Failed to load command: ${file}: ${error.message}`,
50 'Commands',
51 )
52 }
53 }
54 } catch (error: any) {
55 Logger.log(
56 'error',
57 `Failed to read directory ${path}: ${error.message}`,
58 'Commands',
59 )
60 }
61}
62
63export function loadEvents(path: string, client: Bot<Client>) {
64 Logger.log('debug', `Loading events from ${path}`)
65
66 try {
67 const files = readdirSync(path)
68
69 for (const file of files) {
70 const filePath = join(path, file)
71 const fileExtension = isProd ? '.js' : '.ts'
72
73 if (!file.endsWith(fileExtension)) {
74 continue
75 }
76
77 try {
78 const event = require(filePath)
79
80 if (!event.default?.name || !event.default?.execute) {
81 Logger.log(
82 'warn',
83 `Event ${file} is missing required properties`,
84 'Events',
85 )
86 continue
87 }
88
89 const execute = (...args: any[]) =>
90 event.default.execute(client, ...args)
91
92 if (event.default.once) {
93 client.once(event.default.name, execute)
94 } else {
95 client.on(event.default.name, execute)
96 }
97
98 events.set(event.default.name, event.default)
99 Logger.log(
100 'debug',
101 `Loaded event: ${file} (${event.default.name})`,
102 'Events',
103 )
104 } catch (error: any) {
105 Logger.log(
106 'error',
107 `Failed to load event: ${file}: ${error.message}`,
108 'Events',
109 )
110 }
111 }
112
113 Logger.log('debug', `Loaded ${events.size} events`, 'Events')
114 } catch (error: any) {
115 Logger.log(
116 'error',
117 `Failed to read directory ${path}: ${error.message}`,
118 'Events',
119 )
120 }
121}
122
123export function getCommands() {
124 return commands
125}
126
127export function getEvents() {
128 return events
129}
130