djs-builder 0.5.41 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +140 -303
- package/function/function.js +236 -0
- package/function/log.js +736 -0
- package/handler/helper.js +277 -0
- package/handler/starter.js +335 -0
- package/package.json +10 -42
- package/.tsbuildinfo +0 -1
- package/dist/discord/builder/components/Buttons.d.ts +0 -22
- package/dist/discord/builder/components/Buttons.d.ts.map +0 -1
- package/dist/discord/builder/components/Buttons.js +0 -91
- package/dist/discord/builder/components/Buttons.js.map +0 -1
- package/dist/discord/builder/components/Menus.d.ts +0 -31
- package/dist/discord/builder/components/Menus.d.ts.map +0 -1
- package/dist/discord/builder/components/Menus.js +0 -82
- package/dist/discord/builder/components/Menus.js.map +0 -1
- package/dist/discord/builder/permissions/perms.d.ts +0 -6
- package/dist/discord/builder/permissions/perms.d.ts.map +0 -1
- package/dist/discord/builder/permissions/perms.js +0 -66
- package/dist/discord/builder/permissions/perms.js.map +0 -1
- package/dist/discord/builder/system/Pagination.d.ts +0 -70
- package/dist/discord/builder/system/Pagination.d.ts.map +0 -1
- package/dist/discord/builder/system/Pagination.js +0 -227
- package/dist/discord/builder/system/Pagination.js.map +0 -1
- package/dist/discord/builder/system/collectors.d.ts +0 -27
- package/dist/discord/builder/system/collectors.d.ts.map +0 -1
- package/dist/discord/builder/system/collectors.js +0 -137
- package/dist/discord/builder/system/collectors.js.map +0 -1
- package/dist/discord/builder/utils.d.ts +0 -5
- package/dist/discord/builder/utils.d.ts.map +0 -1
- package/dist/discord/builder/utils.js +0 -10
- package/dist/discord/builder/utils.js.map +0 -1
- package/dist/discord/events-handler/eventLoader.d.ts +0 -13
- package/dist/discord/events-handler/eventLoader.d.ts.map +0 -1
- package/dist/discord/events-handler/eventLoader.js +0 -169
- package/dist/discord/events-handler/eventLoader.js.map +0 -1
- package/dist/discord/events-handler/events.d.ts +0 -8
- package/dist/discord/events-handler/events.d.ts.map +0 -1
- package/dist/discord/events-handler/events.js +0 -186
- package/dist/discord/events-handler/events.js.map +0 -1
- package/dist/discord/events-handler/login.d.ts +0 -9
- package/dist/discord/events-handler/login.d.ts.map +0 -1
- package/dist/discord/events-handler/login.js +0 -273
- package/dist/discord/events-handler/login.js.map +0 -1
- package/dist/discord/events-handler/prefix-register.d.ts +0 -23
- package/dist/discord/events-handler/prefix-register.d.ts.map +0 -1
- package/dist/discord/events-handler/prefix-register.js +0 -109
- package/dist/discord/events-handler/prefix-register.js.map +0 -1
- package/dist/discord/events-handler/prefix-responder.d.ts +0 -5
- package/dist/discord/events-handler/prefix-responder.d.ts.map +0 -1
- package/dist/discord/events-handler/prefix-responder.js +0 -155
- package/dist/discord/events-handler/prefix-responder.js.map +0 -1
- package/dist/discord/events-handler/prefixLoader.d.ts +0 -7
- package/dist/discord/events-handler/prefixLoader.d.ts.map +0 -1
- package/dist/discord/events-handler/prefixLoader.js +0 -74
- package/dist/discord/events-handler/prefixLoader.js.map +0 -1
- package/dist/discord/events-handler/slash-register.d.ts +0 -4
- package/dist/discord/events-handler/slash-register.d.ts.map +0 -1
- package/dist/discord/events-handler/slash-register.js +0 -85
- package/dist/discord/events-handler/slash-register.js.map +0 -1
- package/dist/discord/events-handler/slash-responder.d.ts +0 -3
- package/dist/discord/events-handler/slash-responder.d.ts.map +0 -1
- package/dist/discord/events-handler/slash-responder.js +0 -112
- package/dist/discord/events-handler/slash-responder.js.map +0 -1
- package/dist/discord/events-handler/slashLoader.d.ts +0 -7
- package/dist/discord/events-handler/slashLoader.d.ts.map +0 -1
- package/dist/discord/events-handler/slashLoader.js +0 -94
- package/dist/discord/events-handler/slashLoader.js.map +0 -1
- package/dist/discord/events-handler/starter.d.ts +0 -6
- package/dist/discord/events-handler/starter.d.ts.map +0 -1
- package/dist/discord/events-handler/starter.js +0 -85
- package/dist/discord/events-handler/starter.js.map +0 -1
- package/dist/discord/functions/anticrash.d.ts +0 -3
- package/dist/discord/functions/anticrash.d.ts.map +0 -1
- package/dist/discord/functions/anticrash.js +0 -55
- package/dist/discord/functions/anticrash.js.map +0 -1
- package/dist/discord/functions/devLogs.d.ts +0 -2
- package/dist/discord/functions/devLogs.d.ts.map +0 -1
- package/dist/discord/functions/devLogs.js +0 -137
- package/dist/discord/functions/devLogs.js.map +0 -1
- package/dist/discord/functions/logger.d.ts +0 -5
- package/dist/discord/functions/logger.d.ts.map +0 -1
- package/dist/discord/functions/logger.js +0 -57
- package/dist/discord/functions/logger.js.map +0 -1
- package/dist/discord/functions/mongoDb.d.ts +0 -4
- package/dist/discord/functions/mongoDb.d.ts.map +0 -1
- package/dist/discord/functions/mongoDb.js +0 -39
- package/dist/discord/functions/mongoDb.js.map +0 -1
- package/dist/discord/functions/similarity.d.ts +0 -3
- package/dist/discord/functions/similarity.d.ts.map +0 -1
- package/dist/discord/functions/similarity.js +0 -56
- package/dist/discord/functions/similarity.js.map +0 -1
- package/dist/discord/functions/terminal.d.ts +0 -2
- package/dist/discord/functions/terminal.d.ts.map +0 -1
- package/dist/discord/functions/terminal.js +0 -127
- package/dist/discord/functions/terminal.js.map +0 -1
- package/dist/discord/functions/utils.d.ts +0 -5
- package/dist/discord/functions/utils.d.ts.map +0 -1
- package/dist/discord/functions/utils.js +0 -11
- package/dist/discord/functions/utils.js.map +0 -1
- package/dist/discord/functions/versedb.d.ts +0 -3
- package/dist/discord/functions/versedb.d.ts.map +0 -1
- package/dist/discord/functions/versedb.js +0 -21
- package/dist/discord/functions/versedb.js.map +0 -1
- package/dist/discord/games/X-O.d.ts +0 -20
- package/dist/discord/games/X-O.d.ts.map +0 -1
- package/dist/discord/games/X-O.js +0 -166
- package/dist/discord/games/X-O.js.map +0 -1
- package/dist/discord/games/rps.d.ts +0 -21
- package/dist/discord/games/rps.d.ts.map +0 -1
- package/dist/discord/games/rps.js +0 -99
- package/dist/discord/games/rps.js.map +0 -1
- package/dist/discord/types/starter.d.ts +0 -144
- package/dist/discord/types/starter.d.ts.map +0 -1
- package/dist/discord/types/starter.js +0 -3
- package/dist/discord/types/starter.js.map +0 -1
- package/dist/discord/types/utils.d.ts +0 -3
- package/dist/discord/types/utils.d.ts.map +0 -1
- package/dist/discord/types/utils.js +0 -3
- package/dist/discord/types/utils.js.map +0 -1
- package/dist/discord/utils.d.ts +0 -15
- package/dist/discord/utils.d.ts.map +0 -1
- package/dist/discord/utils.js +0 -41
- package/dist/discord/utils.js.map +0 -1
- package/dist/index.d.ts +0 -4
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -71
- package/dist/index.js.map +0 -1
- package/lib/discord/builder/components/Buttons.ts +0 -123
- package/lib/discord/builder/components/Menus.ts +0 -106
- package/lib/discord/builder/permissions/perms.ts +0 -66
- package/lib/discord/builder/system/Pagination.ts +0 -323
- package/lib/discord/builder/system/collectors.ts +0 -197
- package/lib/discord/builder/utils.ts +0 -9
- package/lib/discord/events-handler/eventLoader.ts +0 -166
- package/lib/discord/events-handler/events.ts +0 -160
- package/lib/discord/events-handler/login.ts +0 -265
- package/lib/discord/events-handler/prefix-register.ts +0 -117
- package/lib/discord/events-handler/prefix-responder.ts +0 -176
- package/lib/discord/events-handler/prefixLoader.ts +0 -83
- package/lib/discord/events-handler/slash-register.ts +0 -81
- package/lib/discord/events-handler/slash-responder.ts +0 -136
- package/lib/discord/events-handler/slashLoader.ts +0 -104
- package/lib/discord/events-handler/starter.ts +0 -85
- package/lib/discord/functions/anticrash.ts +0 -60
- package/lib/discord/functions/devLogs.ts +0 -128
- package/lib/discord/functions/logger.ts +0 -58
- package/lib/discord/functions/mongoDb.ts +0 -38
- package/lib/discord/functions/similarity.ts +0 -70
- package/lib/discord/functions/terminal.ts +0 -162
- package/lib/discord/functions/utils.ts +0 -4
- package/lib/discord/functions/versedb.ts +0 -17
- package/lib/discord/types/starter.ts +0 -158
- package/lib/discord/types/utils.ts +0 -2
- package/lib/discord/utils.ts +0 -17
- package/lib/index.ts +0 -37
- package/tsconfig.json +0 -21
|
@@ -1,176 +0,0 @@
|
|
|
1
|
-
import { Client, Message, Collection, EmbedBuilder, TextChannel, PermissionResolvable } from 'discord.js';
|
|
2
|
-
import { getSimilarCommands } from '../functions/utils';
|
|
3
|
-
import { botData } from './login';
|
|
4
|
-
import { logError } from '../functions/logger';
|
|
5
|
-
import { PrefixOptions } from '../types/starter';
|
|
6
|
-
|
|
7
|
-
const cooldowns: Collection<string, Collection<string, number>> = new Collection();
|
|
8
|
-
|
|
9
|
-
export async function handleMessageCreate(message: Message, prefixOptions: PrefixOptions): Promise<void> {
|
|
10
|
-
if (message.author.bot) return;
|
|
11
|
-
|
|
12
|
-
let botPrefix = prefixOptions.prefix || '!';
|
|
13
|
-
const developers = botData.get('developers') as string[] | undefined;
|
|
14
|
-
const ownerId = botData.get('ownerId') as string;
|
|
15
|
-
|
|
16
|
-
if (message.guild) {
|
|
17
|
-
const customPrefixEntry = prefixOptions.customPrefix?.find(entry => entry.serverId === message.guild?.id);
|
|
18
|
-
if (customPrefixEntry) {
|
|
19
|
-
botPrefix = customPrefixEntry.prefix;
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
let args = [];
|
|
24
|
-
let commandName: string | undefined;
|
|
25
|
-
|
|
26
|
-
if (message.content.startsWith(botPrefix)) {
|
|
27
|
-
args = message.content.slice(botPrefix.length).trim().split(/ +/);
|
|
28
|
-
commandName = args.shift()?.toLowerCase();
|
|
29
|
-
} else {
|
|
30
|
-
commandName = message.content.split(/ +/)[0].toLowerCase();
|
|
31
|
-
args = message.content.split(/ +/).slice(1);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (!commandName) return;
|
|
35
|
-
|
|
36
|
-
const command = (message.client as any).prefixCommands.find((cmd: any) => cmd.name === commandName)
|
|
37
|
-
|| (message.client as any).prefixCommands.find((cmd: any) => cmd.aliases.includes(commandName));
|
|
38
|
-
|
|
39
|
-
if (!command) {
|
|
40
|
-
if (message.content.startsWith(botPrefix) && prefixOptions.similarity) {
|
|
41
|
-
const similarCommands = getSimilarCommands(commandName, (message.client as any).prefixCommands);
|
|
42
|
-
if (similarCommands.length > 0) {
|
|
43
|
-
await message.reply(`Command not found. Did you mean: ${similarCommands.join(', ')}?`);
|
|
44
|
-
} else {
|
|
45
|
-
await message.reply(`Command '${commandName}' doesn't exist.`);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (command.owner && message.author.id !== ownerId) {
|
|
53
|
-
await message.reply(`Only the bot owner can use this command.`);
|
|
54
|
-
return;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
if (command.developer && (!developers || !developers.includes(message.author.id)) && message.author.id !== ownerId) {
|
|
58
|
-
await message.reply("You are not authorized to use this command.");
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
if (message.guild) {
|
|
63
|
-
if (command.botPerms && command.botPerms.length > 0) {
|
|
64
|
-
const missingBotPerms = command.botPerms.filter((perm: any) => !message.guild?.members.me?.permissions.has(perm as PermissionResolvable));
|
|
65
|
-
if (missingBotPerms.length > 0) {
|
|
66
|
-
await message.reply(`I'm missing the following permissions to execute this command: ${missingBotPerms.join(', ')}`);
|
|
67
|
-
return;
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
if (command.userPerms && command.userPerms.length > 0) {
|
|
72
|
-
const member = message.guild.members.cache.get(message.author.id);
|
|
73
|
-
if (member) {
|
|
74
|
-
const missingUserPerms = command.userPerms.filter((perm: any) => !member.permissions.has(perm as PermissionResolvable));
|
|
75
|
-
if (missingUserPerms.length > 0) {
|
|
76
|
-
await message.reply(`You are missing the following permissions to use this command: ${missingUserPerms.join(', ')}`);
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (command.accessLevel) {
|
|
83
|
-
const member = message.guild.members.cache.get(message.author.id);
|
|
84
|
-
if (member) {
|
|
85
|
-
const accessRole = message.guild.roles.cache.get(command.accessLevel);
|
|
86
|
-
if (!accessRole) {
|
|
87
|
-
await message.reply("The required role does not exist in this server.");
|
|
88
|
-
return;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const hasRequiredRole = member.roles.cache.some(role => role.id === command.accessLevel || role.position > accessRole.position);
|
|
92
|
-
if (!hasRequiredRole) {
|
|
93
|
-
await message.reply("You do not have the required role or a role higher than it to use this command.");
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Handle cooldowns
|
|
101
|
-
const now = Date.now();
|
|
102
|
-
const timestamps = cooldowns.get(command.name) || new Collection<string, number>();
|
|
103
|
-
const cooldownAmount = (command.cooldown || 3) * 1000;
|
|
104
|
-
|
|
105
|
-
if (timestamps.has(message.author.id)) {
|
|
106
|
-
const expirationTime = timestamps.get(message.author.id) || 0;
|
|
107
|
-
const timeLeft = (expirationTime - now) / 1000;
|
|
108
|
-
|
|
109
|
-
if (now < expirationTime) {
|
|
110
|
-
await message.reply(`Please wait ${timeLeft.toFixed(1)} more second(s) before reusing the \`${command.name}\` command.`);
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
timestamps.set(message.author.id, now);
|
|
116
|
-
setTimeout(() => timestamps.delete(message.author.id), cooldownAmount);
|
|
117
|
-
cooldowns.set(command.name, timestamps);
|
|
118
|
-
|
|
119
|
-
try {
|
|
120
|
-
if (command && command.fastUse && !message.content.startsWith(botPrefix)) {
|
|
121
|
-
if (command.method) {
|
|
122
|
-
command.method(message.client, message, args);
|
|
123
|
-
} else {
|
|
124
|
-
logError(`Error executing command ${command.name}`);
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
else {
|
|
128
|
-
if (command && command.method) {
|
|
129
|
-
command.method(message.client, message, args);
|
|
130
|
-
} else {
|
|
131
|
-
logError(`Error executing command ${command.name}`);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
if (message.guild && prefixOptions.logsId && commandName) {
|
|
135
|
-
const channel = message.guild.channels.cache.get(prefixOptions.logsId) as TextChannel;
|
|
136
|
-
if (channel) {
|
|
137
|
-
const userName = message.author.username;
|
|
138
|
-
const userId = message.author.id;
|
|
139
|
-
const serverName = message.guild.name || null;
|
|
140
|
-
const serverId = message.guild.id || null;
|
|
141
|
-
const messageLink = `https://discord.com/channels/${serverId}/${message.channel.id}/${message.id}`;
|
|
142
|
-
|
|
143
|
-
const embedLog = new EmbedBuilder()
|
|
144
|
-
.setColor("Blue")
|
|
145
|
-
.setThumbnail(message.client.user?.displayAvatarURL())
|
|
146
|
-
.setTitle("Use Prefix Command")
|
|
147
|
-
.setTimestamp()
|
|
148
|
-
.addFields(
|
|
149
|
-
{ name: "📧 Cmd:", value: `- ${commandName}`, inline: true },
|
|
150
|
-
{ name: "🤪 User:", value: `- ${userName} (<@${userId}>)`, inline: true },
|
|
151
|
-
{ name: "\u200B", value: "\u200B", inline: true },
|
|
152
|
-
{ name: "🏠 Server:", value: `- ${serverName}.\n- [\`${serverId}\`].`, inline: true },
|
|
153
|
-
{ name: "📩 Message:", value: `- [Link](${messageLink})`, inline: true },
|
|
154
|
-
{ name: "\u200B", value: "\u200B", inline: true },
|
|
155
|
-
{ name: "⏳ Date:", value: `- <t:${Math.floor(Date.now() / 1000)}:R>`, inline: true }
|
|
156
|
-
);
|
|
157
|
-
|
|
158
|
-
await channel.send({ embeds: [embedLog] });
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
} catch (error: any) {
|
|
162
|
-
logError(`Error executing command ${command.name}`, error);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
export async function loadPrefix(client: Client, prefix: PrefixOptions): Promise<void> {
|
|
167
|
-
if (!prefix.prefix) {
|
|
168
|
-
throw new Error("⚠️ No command prefix provided. Please provide a command prefix.");
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
try {
|
|
172
|
-
client.on("messageCreate", async (message) => await handleMessageCreate(message, prefix));
|
|
173
|
-
} catch (error: any) {
|
|
174
|
-
logError("An error occurred while loading prefix.", error);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
import { Client, Collection } from 'discord.js';
|
|
2
|
-
import { readdir } from 'fs/promises';
|
|
3
|
-
import { join, resolve, extname } from 'path';
|
|
4
|
-
import { commands, aliases, commandNames } from './prefix-register';
|
|
5
|
-
import { readCommands } from './prefix-register';
|
|
6
|
-
import { logError, logInfo } from '../functions/logger';
|
|
7
|
-
import { botData } from './login';
|
|
8
|
-
import { watch } from 'fs';
|
|
9
|
-
const validExtensions = ['.js', '.ts'];
|
|
10
|
-
|
|
11
|
-
export async function prefixLoader(client: any): Promise<{ commands: Collection<string, any>; success: boolean }> {
|
|
12
|
-
try {
|
|
13
|
-
|
|
14
|
-
const prefixPath = botData.get('prefixPath') as string;
|
|
15
|
-
|
|
16
|
-
commands.clear();
|
|
17
|
-
aliases.clear();
|
|
18
|
-
commandNames.clear();
|
|
19
|
-
client.prefixCommands = [];
|
|
20
|
-
client.prefixSize = 0;
|
|
21
|
-
|
|
22
|
-
const resolvedPath = resolve(process.cwd(), prefixPath);
|
|
23
|
-
const dirents = await readdir(resolvedPath, { withFileTypes: true });
|
|
24
|
-
|
|
25
|
-
const filePaths: string[] = [];
|
|
26
|
-
for (const dirent of dirents) {
|
|
27
|
-
if (dirent.isDirectory()) {
|
|
28
|
-
const folderPath = join(resolvedPath, dirent.name);
|
|
29
|
-
const files = await readdir(folderPath);
|
|
30
|
-
for (const file of files) {
|
|
31
|
-
if (validExtensions.includes(extname(file))) {
|
|
32
|
-
filePaths.push(join(folderPath, file));
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
} else if (validExtensions.includes(extname(dirent.name))) {
|
|
36
|
-
filePaths.push(join(resolvedPath, dirent.name));
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
for (const filePath of filePaths) {
|
|
41
|
-
delete require.cache[require.resolve(filePath)];
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const commandDetails = await readCommands(client, { path: prefixPath });
|
|
45
|
-
client.prefixCommands = commandDetails;
|
|
46
|
-
client.prefixSize = commandDetails.length;
|
|
47
|
-
|
|
48
|
-
return { commands: commands, success: true };
|
|
49
|
-
} catch (error: any) {
|
|
50
|
-
logError('Error reloading commands:');
|
|
51
|
-
logError(error.message, error);
|
|
52
|
-
|
|
53
|
-
return { commands: new Collection(), success: false };
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
export function autoPrefixLoader(client: Client, DEBOUNCE_DELAY: number = 10000) {
|
|
59
|
-
|
|
60
|
-
const slashPath = botData.get('slashCommandPath') as string;
|
|
61
|
-
const commandPath = resolve(process.cwd(), slashPath);
|
|
62
|
-
|
|
63
|
-
let debounceTimer: NodeJS.Timeout | null = null;
|
|
64
|
-
|
|
65
|
-
const handleReload = async () => {
|
|
66
|
-
if (debounceTimer) {
|
|
67
|
-
clearTimeout(debounceTimer);
|
|
68
|
-
}
|
|
69
|
-
debounceTimer = setTimeout(async () => {
|
|
70
|
-
await prefixLoader(client);
|
|
71
|
-
logInfo('Slash commands successfully reloaded after debounce.');
|
|
72
|
-
}, DEBOUNCE_DELAY);
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
watch(commandPath, { recursive: false }, (eventType: any, filename: any) => {
|
|
76
|
-
if (filename && validExtensions.includes(extname(filename))) {
|
|
77
|
-
logInfo(`Detected ${eventType} in ${filename}, waiting for debouncing...`);
|
|
78
|
-
handleReload();
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
logInfo('Started watching for changes in slash commands...');
|
|
83
|
-
}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { Collection, Guild } from 'discord.js';
|
|
2
|
-
import { REST } from '@discordjs/rest';
|
|
3
|
-
import { Routes } from 'discord-api-types/v10';
|
|
4
|
-
import { readdir } from 'fs/promises';
|
|
5
|
-
import path from 'path';
|
|
6
|
-
import { SlashOptions } from '../types/starter';
|
|
7
|
-
import { logError } from '../functions/logger';
|
|
8
|
-
|
|
9
|
-
async function loadCommand(filePath: string) {
|
|
10
|
-
try {
|
|
11
|
-
const command = require(filePath);
|
|
12
|
-
if (command.data) {
|
|
13
|
-
command.data.cooldown = command.cooldown && !isNaN(command.cooldown) ? command.cooldown : 0;
|
|
14
|
-
command.data.botPerms = command.botPerms || [];
|
|
15
|
-
command.data.userPerms = command.userPerms || [];
|
|
16
|
-
command.data.owner = command.owner || false;
|
|
17
|
-
command.data.developer = command.developer || false;
|
|
18
|
-
command.data.category = command.category || 'Uncategorized';
|
|
19
|
-
return command;
|
|
20
|
-
}
|
|
21
|
-
} catch (error: any) {
|
|
22
|
-
logError(`Error loading command from file: ${filePath}`);
|
|
23
|
-
logError(error.message);
|
|
24
|
-
}
|
|
25
|
-
return null;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export async function registerSlashCommands(client: any, token: string, slash: SlashOptions): Promise<Collection<string, any>> {
|
|
29
|
-
if (!token) {
|
|
30
|
-
throw new Error("⚠️ Please provide valid bot token to register slash commands.");
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const slashCommands = new Collection<string, any>();
|
|
34
|
-
const rest = new REST({ version: '10' }).setToken(token);
|
|
35
|
-
|
|
36
|
-
try {
|
|
37
|
-
const resolvedPath = path.join(process.cwd(), slash.path);
|
|
38
|
-
const dirents = await readdir(resolvedPath, { withFileTypes: true });
|
|
39
|
-
|
|
40
|
-
for (const dirent of dirents) {
|
|
41
|
-
const folderPath = path.join(resolvedPath, dirent.name);
|
|
42
|
-
if (dirent.isDirectory()) {
|
|
43
|
-
const files = await readdir(folderPath);
|
|
44
|
-
for (const file of files) {
|
|
45
|
-
const command = await loadCommand(path.join(folderPath, file));
|
|
46
|
-
if (command) {
|
|
47
|
-
slashCommands.set(command.data.name, command);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
} else {
|
|
51
|
-
const command = await loadCommand(path.join(resolvedPath, dirent.name));
|
|
52
|
-
if (command) {
|
|
53
|
-
slashCommands.set(command.data.name, command);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
const slashCommandArray = Array.from(slashCommands.values()).map(command => command.data.toJSON());
|
|
59
|
-
|
|
60
|
-
if (slash.global && !slash.serverId) {
|
|
61
|
-
await rest.put(Routes.applicationCommands(client.user?.id || ''), { body: slashCommandArray });
|
|
62
|
-
} else if (!slash.global && slash.serverId) {
|
|
63
|
-
const guild = client.guilds.cache.get(slash.serverId) as Guild | undefined;
|
|
64
|
-
if (guild) {
|
|
65
|
-
await rest.put(Routes.applicationGuildCommands(client.user?.id || '', guild.id), { body: slashCommandArray });
|
|
66
|
-
} else {
|
|
67
|
-
logError(`Guild with ID ${slash.serverId} not found.`);
|
|
68
|
-
}
|
|
69
|
-
} else {
|
|
70
|
-
await rest.put(Routes.applicationCommands(client.user?.id || ''), { body: slashCommandArray });
|
|
71
|
-
}
|
|
72
|
-
} catch (error: any) {
|
|
73
|
-
logError('Error registering slash commands:');
|
|
74
|
-
logError(error.message);
|
|
75
|
-
console.error(error);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
client.slashCommands = slashCommands;
|
|
79
|
-
client.slashSize = slashCommands.size;
|
|
80
|
-
return slashCommands;
|
|
81
|
-
}
|
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Collection,
|
|
3
|
-
Interaction,
|
|
4
|
-
EmbedBuilder,
|
|
5
|
-
Snowflake,
|
|
6
|
-
PermissionResolvable,
|
|
7
|
-
TextChannel
|
|
8
|
-
} from 'discord.js';
|
|
9
|
-
import { registerSlashCommands } from './slash-register';
|
|
10
|
-
import { SlashOptions } from '../types/starter';
|
|
11
|
-
import { logWarning, logError, logInfo } from '../functions/logger';
|
|
12
|
-
|
|
13
|
-
export async function loadSlash(client: any, token: string, options: SlashOptions): Promise<void> {
|
|
14
|
-
const slashCommands = await registerSlashCommands(client, token, options);
|
|
15
|
-
|
|
16
|
-
if (!slashCommands || slashCommands.size === 0) {
|
|
17
|
-
logWarning('No registered slash commands. SlashHandler won\'t work.');
|
|
18
|
-
return;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const interactionCooldowns: Collection<Snowflake, Collection<string, number>> = new Collection();
|
|
22
|
-
|
|
23
|
-
client.on('interactionCreate', async (interaction: Interaction) => {
|
|
24
|
-
// Ensure we are handling the correct type of interaction
|
|
25
|
-
if (!interaction.isCommand() && !interaction.isChatInputCommand() && !interaction.isContextMenuCommand()) {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const guild = interaction.guild; // Get the guild once for better readability
|
|
30
|
-
const user = interaction.user;
|
|
31
|
-
|
|
32
|
-
if (guild) {
|
|
33
|
-
const botData = new Collection<string, string | string[]>();
|
|
34
|
-
const permissionsArray = botData.get('permissions') as string[] | undefined;
|
|
35
|
-
|
|
36
|
-
// Check if bot has permission to send messages
|
|
37
|
-
if (!guild.members.me?.permissions.has('SendMessages')) {
|
|
38
|
-
try {
|
|
39
|
-
await user.send({ content: "I'm sorry, but I don't have permission to send messages in this server." });
|
|
40
|
-
} catch (error) {
|
|
41
|
-
return; // Ignore errors when sending the message
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Check for missing permissions
|
|
46
|
-
if (permissionsArray && permissionsArray.length > 0) {
|
|
47
|
-
const missingPermissions = permissionsArray.filter(permission => !guild.members.me?.permissions.has(permission as PermissionResolvable));
|
|
48
|
-
|
|
49
|
-
if (missingPermissions.length > 0) {
|
|
50
|
-
try {
|
|
51
|
-
await user.send({ content: `I'm sorry, but I don't have permission(s): ${missingPermissions.join(', ')} in this server.` });
|
|
52
|
-
} catch (error) {
|
|
53
|
-
return; // Ignore errors when sending the message
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const commandName = interaction.commandName;
|
|
60
|
-
const command = slashCommands.get(commandName);
|
|
61
|
-
|
|
62
|
-
if (!command) return;
|
|
63
|
-
|
|
64
|
-
// Handle command cooldowns
|
|
65
|
-
if (command.cooldown && !isNaN(command.cooldown)) {
|
|
66
|
-
const userCooldowns = interactionCooldowns.get(interaction.user.id) || new Collection<string, number>();
|
|
67
|
-
const cooldownExpiration = userCooldowns.get(command.data.name);
|
|
68
|
-
if (cooldownExpiration && cooldownExpiration > Date.now()) {
|
|
69
|
-
const remainingCooldown = (cooldownExpiration - Date.now()) / 1000;
|
|
70
|
-
await interaction.reply(`Command is on cooldown. Please wait ${remainingCooldown.toFixed(1)} seconds.`);
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
userCooldowns.set(command.data.name, Date.now() + command.cooldown * 1000);
|
|
74
|
-
interactionCooldowns.set(interaction.user.id, userCooldowns);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
const startExecutionTime = Date.now();
|
|
78
|
-
|
|
79
|
-
try {
|
|
80
|
-
if (command.run) {
|
|
81
|
-
await command.run.length === 2 ? command.run(interaction, client) : command.run(interaction);
|
|
82
|
-
} else if (command.execute) {
|
|
83
|
-
await command.execute.length === 2 ? command.execute(interaction, client) : command.execute(interaction);
|
|
84
|
-
} else {
|
|
85
|
-
logWarning(`Command "${command.data.name}" has neither run nor execute method.`);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Logging command usage
|
|
89
|
-
if (options.logsId && guild) {
|
|
90
|
-
const channel = guild.channels.cache.get(options.logsId as string) as TextChannel;
|
|
91
|
-
if (channel) {
|
|
92
|
-
const userName = user.username;
|
|
93
|
-
const userId = user.id;
|
|
94
|
-
const serverName = guild.name || 'Unknown Server';
|
|
95
|
-
const serverId = guild.id || 'Unknown ID';
|
|
96
|
-
let messageLink = '';
|
|
97
|
-
|
|
98
|
-
if (interaction.channel) {
|
|
99
|
-
messageLink = `https://discord.com/channels/${serverId}/${interaction.channel.id}/${interaction.id}`;
|
|
100
|
-
} else {
|
|
101
|
-
messageLink = 'Unknown';
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const embedLog = new EmbedBuilder()
|
|
105
|
-
.setColor("Blue")
|
|
106
|
-
.setThumbnail(interaction.client.user?.displayAvatarURL())
|
|
107
|
-
.setTitle("Use Slash Command")
|
|
108
|
-
.setTimestamp()
|
|
109
|
-
.addFields(
|
|
110
|
-
{ name: "📧 Cmd:", value: `- ${command.data.name}`, inline: true },
|
|
111
|
-
{ name: "🤪 User:", value: `- ${userName} (<@${userId}>)`, inline: true },
|
|
112
|
-
{ name: "\u200B", value: "\u200B", inline: true },
|
|
113
|
-
{ name: "🏠 Server:", value: `- ${serverName}.\n- [\`${serverId}\`].`, inline: true },
|
|
114
|
-
{ name: "📩 Message:", value: `- [Link](${messageLink})`, inline: true },
|
|
115
|
-
{ name: "\u200B", value: "\u200B", inline: true },
|
|
116
|
-
{ name: "⏳ Date:", value: `- <t:${Math.floor(Date.now() / 1000)}:R>`, inline: true }
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
await channel.send({ embeds: [embedLog] });
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
const executionTime = Date.now() - startExecutionTime;
|
|
124
|
-
if (executionTime > 3000) {
|
|
125
|
-
logInfo(`Command "${command.data.name}" took ${executionTime}ms to execute.`);
|
|
126
|
-
}
|
|
127
|
-
} catch (error: any) {
|
|
128
|
-
logError(`Error executing command "${command.data.name}":`);
|
|
129
|
-
logError(error.message);
|
|
130
|
-
console.error(error);
|
|
131
|
-
if (interaction.channel) {
|
|
132
|
-
await interaction.channel.send({ content: 'An error occurred while executing the command.' });
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
});
|
|
136
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { Client, Collection } from 'discord.js';
|
|
2
|
-
import { REST } from '@discordjs/rest';
|
|
3
|
-
import { Routes } from 'discord-api-types/v10';
|
|
4
|
-
import { readdir } from 'fs/promises';
|
|
5
|
-
import { resolve, extname } from 'path';
|
|
6
|
-
import { botData } from './login';
|
|
7
|
-
import { logError, logInfo } from '../functions/logger';
|
|
8
|
-
import { watch } from 'fs';
|
|
9
|
-
|
|
10
|
-
const validExtensions = ['.js', '.ts'];
|
|
11
|
-
|
|
12
|
-
export async function slashLoader(client: any): Promise<{ commands: Collection<string, any>; success: boolean }> {
|
|
13
|
-
try {
|
|
14
|
-
const slashPath = botData.get('slashCommandPath') as string;
|
|
15
|
-
const token = botData.get('botToken') as string;
|
|
16
|
-
|
|
17
|
-
const commandPath = resolve(process.cwd(), slashPath);
|
|
18
|
-
|
|
19
|
-
const getAllFiles = async (dirPath: string): Promise<string[]> => {
|
|
20
|
-
let files: string[] = [];
|
|
21
|
-
const dirents = await readdir(dirPath, { withFileTypes: true });
|
|
22
|
-
|
|
23
|
-
for (const dirent of dirents) {
|
|
24
|
-
const res = resolve(dirPath, dirent.name);
|
|
25
|
-
if (dirent.isDirectory()) {
|
|
26
|
-
files = files.concat(await getAllFiles(res));
|
|
27
|
-
} else if (validExtensions.includes(extname(dirent.name))) {
|
|
28
|
-
files.push(res);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
return files;
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
const files = await getAllFiles(commandPath);
|
|
35
|
-
if (files.length === 0) {
|
|
36
|
-
logInfo(`No command files found in directory \`${commandPath}\`.`);
|
|
37
|
-
return { commands: new Collection<string, any>(), success: false };
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
for (const file of files) {
|
|
41
|
-
delete require.cache[require.resolve(file)];
|
|
42
|
-
logInfo(`Unlinked cached module: ${file}`);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
const newCommands = new Collection<string, any>();
|
|
46
|
-
for (const file of files) {
|
|
47
|
-
try {
|
|
48
|
-
const command = require(file);
|
|
49
|
-
if (command.data) {
|
|
50
|
-
command.cooldown = command.cooldown || 0;
|
|
51
|
-
command.owner = command.owner || false;
|
|
52
|
-
command.developer = command.developer || false;
|
|
53
|
-
command.botPerms = command.botPerms || [];
|
|
54
|
-
command.userPerms = command.userPerms || [];
|
|
55
|
-
|
|
56
|
-
client.slashCommands.set(command.data.name, command);
|
|
57
|
-
newCommands.set(command.data.name, command);
|
|
58
|
-
}
|
|
59
|
-
} catch (error: any) {
|
|
60
|
-
logError(`Error re-importing file: ${file}`);
|
|
61
|
-
logError(error.message);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const rest = new REST({ version: '10' }).setToken(token);
|
|
66
|
-
const slashCommandArray = Array.from(newCommands.values()).map((command: any) => command.data.toJSON());
|
|
67
|
-
|
|
68
|
-
await rest.put(Routes.applicationCommands(client.user?.id || ''), { body: [] });
|
|
69
|
-
await rest.put(Routes.applicationCommands(client.user?.id || ''), { body: slashCommandArray });
|
|
70
|
-
|
|
71
|
-
return { commands: newCommands, success: true };
|
|
72
|
-
} catch (error: any) {
|
|
73
|
-
logError('Error reloading slash commands:');
|
|
74
|
-
logError(error.message, error);
|
|
75
|
-
return { commands: new Collection<string, any>(), success: false };
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
export function autoSlashLoader(client: Client, DEBOUNCE_DELAY: number = 10000) {
|
|
80
|
-
|
|
81
|
-
const slashPath = botData.get('slashCommandPath') as string;
|
|
82
|
-
const commandPath = resolve(process.cwd(), slashPath);
|
|
83
|
-
|
|
84
|
-
let debounceTimer: NodeJS.Timeout | null = null;
|
|
85
|
-
|
|
86
|
-
const handleReload = async () => {
|
|
87
|
-
if (debounceTimer) {
|
|
88
|
-
clearTimeout(debounceTimer);
|
|
89
|
-
}
|
|
90
|
-
debounceTimer = setTimeout(async () => {
|
|
91
|
-
await slashLoader(client);
|
|
92
|
-
logInfo('Slash commands successfully reloaded after debounce.');
|
|
93
|
-
}, DEBOUNCE_DELAY);
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
watch(commandPath, { recursive: false }, (eventType: any, filename: any) => {
|
|
97
|
-
if (filename && validExtensions.includes(extname(filename))) {
|
|
98
|
-
logInfo(`Detected ${eventType} in ${filename}, waiting for debouncing...`);
|
|
99
|
-
handleReload();
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
logInfo('Started watching for changes in slash commands...');
|
|
104
|
-
}
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { StarterOptions, StarterInterface, } from '../types/utils';
|
|
2
|
-
import { mongoConnect, getDb, verseConnect } from '../functions/utils';
|
|
3
|
-
const wait = require('node:timers/promises').setTimeout;
|
|
4
|
-
import { botData, login } from './login';
|
|
5
|
-
import { AntiCrash } from '../functions/anticrash';
|
|
6
|
-
import { loadEvents } from './events';
|
|
7
|
-
import { MessageCollector, InteractionCollector, ShardingManager, ShardClientUtil } from 'discord.js';
|
|
8
|
-
import path from 'path';
|
|
9
|
-
import fs from 'fs';
|
|
10
|
-
import { logError, logInfo, logSuccess } from '../utils';
|
|
11
|
-
|
|
12
|
-
export class Starter implements StarterInterface {
|
|
13
|
-
async start(djs: any, options: StarterOptions): Promise<any> {
|
|
14
|
-
let mongoDb;
|
|
15
|
-
let verseDb;
|
|
16
|
-
|
|
17
|
-
if (options.sharding?.enable) {
|
|
18
|
-
try {
|
|
19
|
-
const packageJson = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8'));
|
|
20
|
-
const mainFile = packageJson.main || 'index.js';
|
|
21
|
-
|
|
22
|
-
const manager = new ShardingManager(path.join(process.cwd(), mainFile), {
|
|
23
|
-
totalShards: options.sharding.totalShards || 'auto',
|
|
24
|
-
mode: options.sharding.mode || 'process',
|
|
25
|
-
shardList: options.sharding.shardList || 'auto',
|
|
26
|
-
respawn: options.sharding.respawn !== undefined ? options.sharding.respawn : true,
|
|
27
|
-
silent: options.sharding.silent || false,
|
|
28
|
-
shardArgs: options.sharding.shardArgs || [],
|
|
29
|
-
token: options.sharding.token || options.bot?.token,
|
|
30
|
-
execArgv: options.sharding.execArgv || process.execArgv,
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
manager.on('shardCreate', shard => logInfo(`Launched shard ${shard.id}`));
|
|
34
|
-
await manager.spawn();
|
|
35
|
-
djs.shard = manager;
|
|
36
|
-
djs.shardClient = ShardClientUtil.singleton(djs, options?.sharding?.mode || 'process');
|
|
37
|
-
logSuccess('Sharding setup complete and shards spawned.');
|
|
38
|
-
} catch (error: any) {
|
|
39
|
-
logError('Failed to setup sharding', error);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
try {
|
|
43
|
-
if (options.bot?.Database?.mongo) {
|
|
44
|
-
await mongoConnect(options.bot.Database.mongo.mongoURI, options.bot.Database.mongo.dbName || 'djsbuilder');
|
|
45
|
-
mongoDb = await getDb();
|
|
46
|
-
}
|
|
47
|
-
if (options.bot?.Database?.verse) {
|
|
48
|
-
verseDb = await verseConnect(options.bot.Database.verse);
|
|
49
|
-
}
|
|
50
|
-
if (options.events) {
|
|
51
|
-
await loadEvents(djs, options.events);
|
|
52
|
-
botData.set('eventsPath', options.events.path);
|
|
53
|
-
}
|
|
54
|
-
if (options.bot) {
|
|
55
|
-
await login(djs, options);
|
|
56
|
-
}
|
|
57
|
-
if (options.anticrash?.enable) {
|
|
58
|
-
await AntiCrash(djs, options)
|
|
59
|
-
}
|
|
60
|
-
} catch (error: any) {
|
|
61
|
-
console.error('An error occurred during bot startup:', error.message);
|
|
62
|
-
await this.handleStartupError(error, djs, options);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
await wait(2_000)
|
|
66
|
-
return {
|
|
67
|
-
mongodb: mongoDb,
|
|
68
|
-
versedb: verseDb,
|
|
69
|
-
slashSize: djs.slashSize || 0,
|
|
70
|
-
prefixSize: djs.prefixSize || 0,
|
|
71
|
-
eventSize: djs.eventSize || 0,
|
|
72
|
-
client: djs
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async handleStartupError(error: any, djs: any, options: StarterOptions) {
|
|
77
|
-
console.error('Error during bot startup:', error);
|
|
78
|
-
setTimeout(() => {
|
|
79
|
-
this.start(djs, options);
|
|
80
|
-
}, 5000);
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|