djs-builder 0.4.85 → 0.5.1
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/.tsbuildinfo +1 -1
- package/dist/discord/events-handler/eventLoader.d.ts +7 -0
- package/dist/discord/events-handler/eventLoader.d.ts.map +1 -0
- package/dist/discord/events-handler/eventLoader.js +144 -0
- package/dist/discord/events-handler/eventLoader.js.map +1 -0
- package/dist/discord/events-handler/events.d.ts +5 -0
- package/dist/discord/events-handler/events.d.ts.map +1 -1
- package/dist/discord/events-handler/events.js +11 -7
- package/dist/discord/events-handler/events.js.map +1 -1
- package/dist/discord/events-handler/login.d.ts.map +1 -1
- package/dist/discord/events-handler/login.js +6 -1
- package/dist/discord/events-handler/login.js.map +1 -1
- package/dist/discord/events-handler/prefix-register.d.ts +5 -0
- package/dist/discord/events-handler/prefix-register.d.ts.map +1 -1
- package/dist/discord/events-handler/prefix-register.js +15 -4
- package/dist/discord/events-handler/prefix-register.js.map +1 -1
- package/dist/discord/events-handler/prefix-responder.d.ts +2 -1
- package/dist/discord/events-handler/prefix-responder.d.ts.map +1 -1
- package/dist/discord/events-handler/prefix-responder.js +130 -59
- package/dist/discord/events-handler/prefix-responder.js.map +1 -1
- package/dist/discord/events-handler/prefixLoader.d.ts +5 -1
- package/dist/discord/events-handler/prefixLoader.d.ts.map +1 -1
- package/dist/discord/events-handler/prefixLoader.js +38 -24
- package/dist/discord/events-handler/prefixLoader.js.map +1 -1
- package/dist/discord/events-handler/slash-register.d.ts.map +1 -1
- package/dist/discord/events-handler/slash-register.js +1 -5
- package/dist/discord/events-handler/slash-register.js.map +1 -1
- package/dist/discord/events-handler/slash-responder.d.ts.map +1 -1
- package/dist/discord/events-handler/slash-responder.js +1 -0
- package/dist/discord/events-handler/slash-responder.js.map +1 -1
- package/dist/discord/events-handler/slashLoader.d.ts +5 -1
- package/dist/discord/events-handler/slashLoader.d.ts.map +1 -1
- package/dist/discord/events-handler/slashLoader.js +57 -11
- package/dist/discord/events-handler/slashLoader.js.map +1 -1
- package/dist/discord/events-handler/starter.d.ts.map +1 -1
- package/dist/discord/events-handler/starter.js +2 -6
- package/dist/discord/events-handler/starter.js.map +1 -1
- package/dist/discord/functions/logger.d.ts +1 -1
- package/dist/discord/functions/logger.d.ts.map +1 -1
- package/dist/discord/functions/logger.js +9 -2
- package/dist/discord/functions/logger.js.map +1 -1
- package/dist/discord/types/starter.d.ts +8 -1
- package/dist/discord/types/starter.d.ts.map +1 -1
- package/dist/discord/utils.d.ts +9 -2
- package/dist/discord/utils.d.ts.map +1 -1
- package/dist/discord/utils.js +26 -3
- package/dist/discord/utils.js.map +1 -1
- package/dist/index.d.ts +20 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -2
- package/dist/index.js.map +1 -1
- package/lib/discord/events-handler/eventLoader.ts +130 -0
- package/lib/discord/events-handler/events.ts +11 -12
- package/lib/discord/events-handler/login.ts +7 -1
- package/lib/discord/events-handler/prefix-register.ts +43 -6
- package/lib/discord/events-handler/prefix-responder.ts +141 -61
- package/lib/discord/events-handler/prefixLoader.ts +43 -29
- package/lib/discord/events-handler/slash-register.ts +3 -6
- package/lib/discord/events-handler/slash-responder.ts +1 -0
- package/lib/discord/events-handler/slashLoader.ts +64 -12
- package/lib/discord/events-handler/starter.ts +4 -8
- package/lib/discord/functions/logger.ts +10 -2
- package/lib/discord/types/starter.ts +8 -1
- package/lib/discord/utils.ts +11 -2
- package/lib/index.ts +10 -3
- package/package.json +2 -1
- package/lib/discord/events-handler/events loader.ts +0 -21
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Collection } from 'discord.js';
|
|
2
|
+
import { readdir } from 'fs/promises';
|
|
3
|
+
import { resolve, extname } from 'path';
|
|
4
|
+
import { EventsOptions, Event } from '../types/utils';
|
|
5
|
+
import { logError, logInfo } from '../functions/logger';
|
|
6
|
+
import { botData } from './login';
|
|
7
|
+
const validExtensions = ['.js', '.ts'];
|
|
8
|
+
|
|
9
|
+
export async function eventLoader(client: any, eventsOptions: EventsOptions): Promise<{ events: Collection<string, Event>; success: boolean }> {
|
|
10
|
+
try {
|
|
11
|
+
const eventsPath = botData.get('eventsPath') as string;
|
|
12
|
+
const eventPath = resolve(process.cwd(), eventsPath);
|
|
13
|
+
|
|
14
|
+
const getAllFiles = async (dirPath: string): Promise<string[]> => {
|
|
15
|
+
let files: string[] = [];
|
|
16
|
+
const dirents = await readdir(dirPath, { withFileTypes: true });
|
|
17
|
+
|
|
18
|
+
for (const dirent of dirents) {
|
|
19
|
+
const res = resolve(dirPath, dirent.name);
|
|
20
|
+
if (dirent.isDirectory()) {
|
|
21
|
+
files = files.concat(await getAllFiles(res));
|
|
22
|
+
} else if (validExtensions.includes(extname(dirent.name))) {
|
|
23
|
+
files.push(res);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return files;
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const files = await getAllFiles(eventPath);
|
|
30
|
+
if (files.length === 0) {
|
|
31
|
+
logInfo(`No event files found in directory \`${eventPath}\`.`);
|
|
32
|
+
return { events: new Collection<string, Event>(), success: false };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
client.removeAllListeners();
|
|
36
|
+
|
|
37
|
+
for (const file of files) {
|
|
38
|
+
delete require.cache[require.resolve(file)];
|
|
39
|
+
logInfo(`Unlinked cached module: ${file}`);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const newEvents = new Collection<string, Event>();
|
|
43
|
+
for (const file of files) {
|
|
44
|
+
try {
|
|
45
|
+
const event: Event = await import(file);
|
|
46
|
+
if (eventsOptions.eventBlacklist?.includes(file)) {
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
let eventHandler: (...args: any[]) => Promise<void> = async (...args: any[]) => {
|
|
51
|
+
if (event.initializer) {
|
|
52
|
+
await new Promise(resolve => setTimeout(resolve, event.initializer));
|
|
53
|
+
}
|
|
54
|
+
await event.execute(...args, client);
|
|
55
|
+
|
|
56
|
+
if (event.interval) {
|
|
57
|
+
if (event.intervalId) clearInterval(event.intervalId);
|
|
58
|
+
event.intervalId = setInterval(async () => {
|
|
59
|
+
await event.execute(...args, client);
|
|
60
|
+
}, event.interval);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
if (event.once) {
|
|
65
|
+
client.once(event.name, eventHandler);
|
|
66
|
+
} else {
|
|
67
|
+
client.on(event.name, eventHandler);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (event.maxExecution !== undefined) {
|
|
71
|
+
eventHandler = await limitConcurrency(eventHandler, event.maxExecution);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (event.retryAttempts !== undefined) {
|
|
75
|
+
eventHandler = await withRetry(eventHandler, event.retryAttempts);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
newEvents.set(event.name, event);
|
|
79
|
+
} catch (error: any) {
|
|
80
|
+
logError(`Error re-importing file: ${file}`);
|
|
81
|
+
logError(error.message, error);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
client.eventSize = newEvents.size;
|
|
86
|
+
|
|
87
|
+
return { events: newEvents, success: true };
|
|
88
|
+
} catch (error: any) {
|
|
89
|
+
logError('Error reloading events:');
|
|
90
|
+
logError(error.message, error);
|
|
91
|
+
return { events: new Collection<string, Event>(), success: false };
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
async function limitConcurrency(handler: (...args: any[]) => void, maxConcurrentExecutions: number): Promise<(...args: any[]) => Promise<void>> {
|
|
96
|
+
let executing = 0;
|
|
97
|
+
const queue: any[] = [];
|
|
98
|
+
|
|
99
|
+
return async function(...args: any[]) {
|
|
100
|
+
if (executing < maxConcurrentExecutions) {
|
|
101
|
+
executing++;
|
|
102
|
+
await handler(...args);
|
|
103
|
+
executing--;
|
|
104
|
+
|
|
105
|
+
if (queue.length > 0) {
|
|
106
|
+
const next = queue.shift();
|
|
107
|
+
next();
|
|
108
|
+
}
|
|
109
|
+
} else {
|
|
110
|
+
queue.push(() => handler(...args));
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function withRetry(handler: (...args: any[]) => Promise<void>, retryAttempts: number): Promise<(...args: any[]) => Promise<void>> {
|
|
116
|
+
return async function(...args: any[]) {
|
|
117
|
+
let attempts = 0;
|
|
118
|
+
while (attempts < retryAttempts) {
|
|
119
|
+
try {
|
|
120
|
+
await handler(...args);
|
|
121
|
+
return;
|
|
122
|
+
} catch (error: any) {
|
|
123
|
+
logError('Error executing event:');
|
|
124
|
+
logError(error.message, error);
|
|
125
|
+
attempts++;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
logError('Reached maximum retry attempts.');
|
|
129
|
+
};
|
|
130
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { logSuccess, logError } from '../functions/logger';
|
|
2
1
|
import { readdir, stat } from 'fs/promises';
|
|
3
2
|
import { resolve, join, extname } from 'path';
|
|
4
3
|
import { EventsOptions, Event } from '../types/utils';
|
|
4
|
+
import { logError } from '../functions/logger';
|
|
5
5
|
|
|
6
6
|
const validExtensions = ['.js', '.ts'];
|
|
7
7
|
|
|
8
|
-
async function processEventFile(client: any, eventsOptions: EventsOptions, filePath: string) {
|
|
8
|
+
export async function processEventFile(client: any, eventsOptions: EventsOptions, filePath: string) {
|
|
9
9
|
try {
|
|
10
10
|
const resolvedPath = resolve(process.cwd(), filePath);
|
|
11
11
|
const stats = await stat(resolvedPath);
|
|
@@ -48,11 +48,11 @@ async function processEventFile(client: any, eventsOptions: EventsOptions, fileP
|
|
|
48
48
|
}
|
|
49
49
|
} catch (error: any) {
|
|
50
50
|
logError(`Error in event file: ${filePath}`);
|
|
51
|
-
logError(error.message);
|
|
51
|
+
logError(error.message, error);
|
|
52
52
|
}
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
async function limitConcurrency(handler: (...args: any[]) => void, maxConcurrentExecutions: number): Promise<(...args: any[]) => Promise<void>> {
|
|
55
|
+
export async function limitConcurrency(handler: (...args: any[]) => void, maxConcurrentExecutions: number): Promise<(...args: any[]) => Promise<void>> {
|
|
56
56
|
let executing = 0;
|
|
57
57
|
const queue: any[] = [];
|
|
58
58
|
|
|
@@ -72,7 +72,7 @@ async function limitConcurrency(handler: (...args: any[]) => void, maxConcurrent
|
|
|
72
72
|
};
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
async function withRetry(handler: (...args: any[]) => Promise<void>, retryAttempts: number): Promise<(...args: any[]) => Promise<void>> {
|
|
75
|
+
export async function withRetry(handler: (...args: any[]) => Promise<void>, retryAttempts: number): Promise<(...args: any[]) => Promise<void>> {
|
|
76
76
|
return async function(...args: any[]) {
|
|
77
77
|
let attempts = 0;
|
|
78
78
|
while (attempts < retryAttempts) {
|
|
@@ -81,7 +81,7 @@ async function withRetry(handler: (...args: any[]) => Promise<void>, retryAttemp
|
|
|
81
81
|
return;
|
|
82
82
|
} catch (error: any) {
|
|
83
83
|
logError('Error executing event:');
|
|
84
|
-
logError(error.message);
|
|
84
|
+
logError(error.message, error);
|
|
85
85
|
attempts++;
|
|
86
86
|
}
|
|
87
87
|
}
|
|
@@ -89,7 +89,7 @@ async function withRetry(handler: (...args: any[]) => Promise<void>, retryAttemp
|
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
91
|
|
|
92
|
-
async function processDirectory(client: any, eventsOptions: EventsOptions, directoryPath: string) {
|
|
92
|
+
export async function processDirectory(client: any, eventsOptions: EventsOptions, directoryPath: string) {
|
|
93
93
|
try {
|
|
94
94
|
const filesInDirectory = await readdir(directoryPath);
|
|
95
95
|
for (const file of filesInDirectory) {
|
|
@@ -103,7 +103,7 @@ async function processDirectory(client: any, eventsOptions: EventsOptions, direc
|
|
|
103
103
|
}
|
|
104
104
|
} catch (error: any) {
|
|
105
105
|
logError(`Error while processing directory: ${directoryPath}`);
|
|
106
|
-
logError(error.message);
|
|
106
|
+
logError(error.message, error);
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
|
|
@@ -123,14 +123,13 @@ export async function loadEvents(client: any, eventsOptions: EventsOptions) {
|
|
|
123
123
|
|
|
124
124
|
const eventCount = await countEventFiles(eventsOptions.path, eventsOptions);
|
|
125
125
|
client.eventSize = eventCount;
|
|
126
|
-
logSuccess(`Loaded ${eventCount} events successfully.`);
|
|
127
126
|
} catch (error: any) {
|
|
128
127
|
logError(`Error while loading events from path: ${eventsOptions.path}`);
|
|
129
|
-
logError(error.message);
|
|
128
|
+
logError(error.message, error);
|
|
130
129
|
}
|
|
131
130
|
}
|
|
132
131
|
|
|
133
|
-
async function countEventFiles(filePath: string, eventsOptions: EventsOptions): Promise<number> {
|
|
132
|
+
export async function countEventFiles(filePath: string, eventsOptions: EventsOptions): Promise<number> {
|
|
134
133
|
let count = 0;
|
|
135
134
|
try {
|
|
136
135
|
const resolvedPath = resolve(process.cwd(), filePath);
|
|
@@ -154,7 +153,7 @@ async function countEventFiles(filePath: string, eventsOptions: EventsOptions):
|
|
|
154
153
|
}
|
|
155
154
|
} catch (error: any) {
|
|
156
155
|
logError(`Error counting event files in directory: ${filePath}`);
|
|
157
|
-
logError(error.message);
|
|
156
|
+
logError(error.message, error);
|
|
158
157
|
}
|
|
159
158
|
return count;
|
|
160
159
|
}
|
|
@@ -3,9 +3,11 @@ import { StarterOptions } from '../types/starter';
|
|
|
3
3
|
import { loadPrefix } from './prefix-responder';
|
|
4
4
|
import { loadSlash } from './slash-responder';
|
|
5
5
|
import { readCommands } from './prefix-register';
|
|
6
|
+
|
|
6
7
|
export const botData = new Collection<string, string | string[]>();
|
|
7
8
|
import * as path from 'path';
|
|
8
9
|
import fs from 'fs';
|
|
10
|
+
import { loadEvents } from './events';
|
|
9
11
|
export async function login(djs: Client, options: StarterOptions) {
|
|
10
12
|
|
|
11
13
|
if (!djs) {
|
|
@@ -57,6 +59,10 @@ export async function login(djs: Client, options: StarterOptions) {
|
|
|
57
59
|
botData.set('developers', options.bot.BotInfo.developers);
|
|
58
60
|
}
|
|
59
61
|
|
|
62
|
+
if (options.events) {
|
|
63
|
+
await loadEvents(djs, options.events);
|
|
64
|
+
botData.set('eventsPath', options.events.path);
|
|
65
|
+
}
|
|
60
66
|
|
|
61
67
|
if (options.prefix) {
|
|
62
68
|
await readCommands(djs, options.prefix)
|
|
@@ -66,7 +72,7 @@ export async function login(djs: Client, options: StarterOptions) {
|
|
|
66
72
|
}
|
|
67
73
|
if (options.slash && options.bot.token) {
|
|
68
74
|
await loadSlash(djs, options.bot?.token, options.slash);
|
|
69
|
-
botData.set('
|
|
75
|
+
botData.set('slashCommandPath', options.slash.path);
|
|
70
76
|
if (options.slash.serverId) botData.set('serverIdSlash', options.slash.serverId);
|
|
71
77
|
if (options.slash.global === true) botData.set('globalSlash', 'true');
|
|
72
78
|
if (options.slash.global === false) botData.set('globalSlash', 'false');
|
|
@@ -2,13 +2,40 @@ import { Collection } from 'discord.js';
|
|
|
2
2
|
import { promises as fsPromises } from 'fs';
|
|
3
3
|
import { join, resolve } from 'path';
|
|
4
4
|
import { Command } from '../types/utils';
|
|
5
|
+
import { logError } from '../functions/logger';
|
|
5
6
|
|
|
6
7
|
export const commands = new Collection<string, Command>();
|
|
7
8
|
export const aliases = new Collection<string, string>();
|
|
8
9
|
export const commandNames = new Set<string>();
|
|
9
10
|
|
|
10
|
-
export async function readCommands(client: any, prefix: { path: string }): Promise<Array<{
|
|
11
|
-
|
|
11
|
+
export async function readCommands(client: any, prefix: { path: string }): Promise<Array<{
|
|
12
|
+
name: string;
|
|
13
|
+
usage: string | undefined;
|
|
14
|
+
description: string | undefined;
|
|
15
|
+
aliases: string[] | undefined;
|
|
16
|
+
cooldown: number | undefined;
|
|
17
|
+
developer: boolean | undefined;
|
|
18
|
+
owner: boolean | undefined;
|
|
19
|
+
fastUse: boolean | undefined;
|
|
20
|
+
botPerms: string[] | undefined;
|
|
21
|
+
userPerms: string[] | undefined;
|
|
22
|
+
category: string | undefined;
|
|
23
|
+
accessLevel: string | undefined;
|
|
24
|
+
}>> {
|
|
25
|
+
const commandDetails: Array<{
|
|
26
|
+
name: string;
|
|
27
|
+
usage: string | undefined;
|
|
28
|
+
description: string | undefined;
|
|
29
|
+
aliases: string[] | undefined;
|
|
30
|
+
cooldown: number | undefined;
|
|
31
|
+
developer: boolean | undefined;
|
|
32
|
+
owner: boolean | undefined;
|
|
33
|
+
fastUse: boolean | undefined;
|
|
34
|
+
botPerms: string[] | undefined;
|
|
35
|
+
userPerms: string[] | undefined;
|
|
36
|
+
category: string | undefined;
|
|
37
|
+
accessLevel: string | undefined;
|
|
38
|
+
}> = [];
|
|
12
39
|
|
|
13
40
|
try {
|
|
14
41
|
const resolvedPath = resolve(process.cwd(), prefix.path);
|
|
@@ -34,6 +61,11 @@ export async function readCommands(client: any, prefix: { path: string }): Promi
|
|
|
34
61
|
aliases: [],
|
|
35
62
|
developer: false,
|
|
36
63
|
owner: false,
|
|
64
|
+
fastUse: false,
|
|
65
|
+
botPerms: [],
|
|
66
|
+
userPerms: [],
|
|
67
|
+
category: "Uncategorized",
|
|
68
|
+
accessLevel: undefined,
|
|
37
69
|
...command
|
|
38
70
|
};
|
|
39
71
|
|
|
@@ -55,11 +87,16 @@ export async function readCommands(client: any, prefix: { path: string }): Promi
|
|
|
55
87
|
cooldown: defaultCommand.cooldown,
|
|
56
88
|
developer: defaultCommand.developer,
|
|
57
89
|
owner: defaultCommand.owner,
|
|
90
|
+
fastUse: defaultCommand.fastUse,
|
|
91
|
+
botPerms: defaultCommand.botPerms,
|
|
92
|
+
userPerms: defaultCommand.userPerms,
|
|
93
|
+
category: defaultCommand.category || 'Uncategorized',
|
|
94
|
+
accessLevel: defaultCommand.accessLevel,
|
|
58
95
|
});
|
|
59
96
|
}
|
|
60
97
|
} catch (error: any) {
|
|
61
|
-
|
|
62
|
-
|
|
98
|
+
logError(`Error in file: ${filePath}`);
|
|
99
|
+
logError(error.message, error);
|
|
63
100
|
}
|
|
64
101
|
}
|
|
65
102
|
}
|
|
@@ -68,8 +105,8 @@ export async function readCommands(client: any, prefix: { path: string }): Promi
|
|
|
68
105
|
client.prefixSize = commandDetails.length;
|
|
69
106
|
return commandDetails;
|
|
70
107
|
} catch (error: any) {
|
|
71
|
-
|
|
72
|
-
|
|
108
|
+
logError(`⚠️ Error reading directory: ${prefix.path}`);
|
|
109
|
+
logError(error.message, error);
|
|
73
110
|
return [];
|
|
74
111
|
}
|
|
75
112
|
}
|
|
@@ -1,53 +1,62 @@
|
|
|
1
1
|
import { Client, Message, Collection, EmbedBuilder, TextChannel, PermissionResolvable } from 'discord.js';
|
|
2
2
|
import { commands, aliases } from './prefix-register';
|
|
3
3
|
import { PrefixOptions } from '../types/utils';
|
|
4
|
-
import { getSimilarCommands } from '../functions/utils'
|
|
4
|
+
import { getSimilarCommands } from '../functions/utils';
|
|
5
5
|
import { botData } from './login';
|
|
6
|
+
import { logError } from '../functions/logger';
|
|
7
|
+
|
|
6
8
|
const cooldowns: Collection<string, Collection<string, number>> = new Collection();
|
|
7
9
|
|
|
8
|
-
async function handleMessageCreate(message: Message,
|
|
9
|
-
|
|
10
|
+
export async function handleMessageCreate(message: Message, prefixOptions: PrefixOptions): Promise<void> {
|
|
11
|
+
let botPrefix = prefixOptions.prefix || '!';
|
|
10
12
|
const developers = botData.get('developers') as string[] | undefined;
|
|
11
13
|
const ownerId = botData.get('ownerId') as string;
|
|
12
14
|
|
|
13
|
-
if (message.guild
|
|
15
|
+
if (message.guild) {
|
|
16
|
+
const customPrefixEntry = prefixOptions.customPrefix?.find(entry => entry.serverId === message.guild?.id);
|
|
17
|
+
if (customPrefixEntry) {
|
|
18
|
+
botPrefix = customPrefixEntry.prefix;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (message.guild && message.guild.members.me) {
|
|
14
23
|
const user = message.author;
|
|
15
|
-
const
|
|
16
|
-
const permissionsArray = botData.get('permissions') as string[] | undefined;
|
|
24
|
+
const botPermissions = message.guild.members.me.permissions;
|
|
17
25
|
|
|
18
|
-
if (!
|
|
26
|
+
if (!botPermissions.has('SendMessages')) {
|
|
19
27
|
try {
|
|
20
|
-
user.send(
|
|
21
|
-
} catch (error) {
|
|
28
|
+
await user.send("I'm sorry, but I don't have permission to send messages in this server.");
|
|
29
|
+
} catch (error: any) {
|
|
30
|
+
logError("Failed to send permission error message to user.", error);
|
|
22
31
|
return;
|
|
23
32
|
}
|
|
24
33
|
}
|
|
25
|
-
|
|
34
|
+
|
|
35
|
+
const permissionsArray = botData.get('permissions') as string[] | undefined;
|
|
26
36
|
if (permissionsArray && permissionsArray.length > 0) {
|
|
27
|
-
const missingPermissions = permissionsArray.filter(permission => !
|
|
28
|
-
|
|
37
|
+
const missingPermissions = permissionsArray.filter(permission => !botPermissions.has(permission as PermissionResolvable));
|
|
38
|
+
|
|
29
39
|
if (missingPermissions.length > 0) {
|
|
30
40
|
try {
|
|
31
|
-
user.send(
|
|
32
|
-
} catch (error) {
|
|
41
|
+
await user.send(`I'm sorry, but I don't have permission(s): ${missingPermissions.join(', ')} in this server.`);
|
|
42
|
+
} catch (error: any) {
|
|
43
|
+
logError("Failed to send missing permissions message to user.", error);
|
|
33
44
|
return;
|
|
34
45
|
}
|
|
35
46
|
}
|
|
36
47
|
}
|
|
37
48
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (!message.content.startsWith(botPrefix) || message.author.bot) return;
|
|
41
|
-
|
|
42
|
-
if (prefix.global === false && prefix.serverIds && prefix.serverIds.length > 0) {
|
|
43
49
|
|
|
44
|
-
|
|
45
|
-
|
|
50
|
+
let args = [];
|
|
51
|
+
let commandName: string | undefined;
|
|
46
52
|
|
|
53
|
+
if (message.content.startsWith(botPrefix)) {
|
|
54
|
+
args = message.content.slice(botPrefix.length).trim().split(/ +/);
|
|
55
|
+
commandName = args.shift()?.toLowerCase();
|
|
47
56
|
} else {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
57
|
+
commandName = message.content.split(/ +/)[0].toLowerCase();
|
|
58
|
+
args = message.content.split(/ +/).slice(1);
|
|
59
|
+
}
|
|
51
60
|
|
|
52
61
|
if (!commandName || (!commands.has(commandName) && !aliases.has(commandName))) return;
|
|
53
62
|
|
|
@@ -68,7 +77,6 @@ async function handleMessageCreate(message: Message, prefix: PrefixOptions): Pro
|
|
|
68
77
|
return;
|
|
69
78
|
}
|
|
70
79
|
|
|
71
|
-
|
|
72
80
|
if (command.developer) {
|
|
73
81
|
if (developers && !developers.includes(message.author.id)) {
|
|
74
82
|
if (message.author.id === ownerId) return;
|
|
@@ -77,6 +85,78 @@ async function handleMessageCreate(message: Message, prefix: PrefixOptions): Pro
|
|
|
77
85
|
}
|
|
78
86
|
}
|
|
79
87
|
|
|
88
|
+
if (message.guild) {
|
|
89
|
+
if (command.botPerms && command.botPerms.length > 0) {
|
|
90
|
+
const missingBotPerms = command.botPerms.filter(perm => !message.guild?.members.me?.permissions.has(perm as PermissionResolvable));
|
|
91
|
+
if (missingBotPerms.length > 0) {
|
|
92
|
+
await message.reply(`I'm missing the following permissions to execute this command: ${missingBotPerms.join(', ')}`);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (command.userPerms && command.userPerms.length > 0) {
|
|
98
|
+
const member = message.guild.members.cache.get(message.author.id);
|
|
99
|
+
if (member) {
|
|
100
|
+
const missingUserPerms = command.userPerms.filter(perm => !member.permissions.has(perm as PermissionResolvable));
|
|
101
|
+
if (missingUserPerms.length > 0) {
|
|
102
|
+
await message.reply(`You are missing the following permissions to use this command: ${missingUserPerms.join(', ')}`);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (command.accessLevel) {
|
|
109
|
+
const member = message.guild.members.cache.get(message.author.id);
|
|
110
|
+
if (member) {
|
|
111
|
+
const highestRole = member.roles.highest;
|
|
112
|
+
if (highestRole.id !== command.accessLevel) {
|
|
113
|
+
await message.reply("You do not have the required role to use this command.");
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (command.fastUse && !message.content.startsWith(botPrefix)) {
|
|
121
|
+
try {
|
|
122
|
+
if (command.run) {
|
|
123
|
+
await command.run(message.client, message, args);
|
|
124
|
+
} else if (command.execute) {
|
|
125
|
+
await command.execute(message.client, message, args);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (message.guild) {
|
|
129
|
+
const channel = message.guild.channels.cache.get(prefixOptions.logsId || '') as TextChannel | undefined;
|
|
130
|
+
const userName = message.author.username;
|
|
131
|
+
const userId = message.author.id;
|
|
132
|
+
const serverName = message.guild.name || null;
|
|
133
|
+
const serverId = message.guild.id || null;
|
|
134
|
+
const messageLink = `https://discord.com/channels/${serverId}/${message.channel.id}/${message.id}`;
|
|
135
|
+
|
|
136
|
+
const embedLog = new EmbedBuilder()
|
|
137
|
+
.setColor("Blue")
|
|
138
|
+
.setThumbnail(message.client.user?.displayAvatarURL())
|
|
139
|
+
.setTitle("Use Prefix Command")
|
|
140
|
+
.setTimestamp()
|
|
141
|
+
.addFields(
|
|
142
|
+
{ name: "📧 Cmd:", value: `- ${command.name}`, inline: true },
|
|
143
|
+
{ name: "🤪 User:", value: `- ${userName} (<@${userId}>)`, inline: true },
|
|
144
|
+
{ name: "\u200B", value: "\u200B", inline: true },
|
|
145
|
+
{ name: "🏠 Server:", value: `- ${serverName}.\n- [\`${serverId}\`].`, inline: true },
|
|
146
|
+
{ name: "📩 Message:", value: `- [Link](${messageLink})`, inline: true },
|
|
147
|
+
{ name: "\u200B", value: "\u200B", inline: true },
|
|
148
|
+
{ name: "⏳ Date:", value: `- <t:${Math.floor(Date.now() / 1000)}:R>`, inline: true }
|
|
149
|
+
);
|
|
150
|
+
|
|
151
|
+
if (prefixOptions.logsId && channel) {
|
|
152
|
+
await channel.send({ embeds: [embedLog] });
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
} catch (error: any) {
|
|
156
|
+
logError(`Error executing command ${command.name}`, error);
|
|
157
|
+
}
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
80
160
|
|
|
81
161
|
const now = Date.now();
|
|
82
162
|
const timestamps = cooldowns.get(command.name) || new Collection<string, number>();
|
|
@@ -96,53 +176,53 @@ async function handleMessageCreate(message: Message, prefix: PrefixOptions): Pro
|
|
|
96
176
|
setTimeout(() => timestamps.delete(message.author.id), cooldownAmount);
|
|
97
177
|
cooldowns.set(command.name, timestamps);
|
|
98
178
|
|
|
99
|
-
|
|
100
179
|
try {
|
|
101
180
|
if (command.run) {
|
|
102
|
-
|
|
181
|
+
await command.run(message.client, message, args);
|
|
103
182
|
} else if (command.execute) {
|
|
104
|
-
|
|
183
|
+
await command.execute(message.client, message, args);
|
|
105
184
|
}
|
|
106
185
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
186
|
+
if (message.guild) {
|
|
187
|
+
const channel = message.guild.channels.cache.get(prefixOptions.logsId || '') as TextChannel | undefined;
|
|
188
|
+
const userName = message.author.username;
|
|
189
|
+
const userId = message.author.id;
|
|
190
|
+
const serverName = message.guild.name || null;
|
|
191
|
+
const serverId = message.guild.id || null;
|
|
192
|
+
const messageLink = `https://discord.com/channels/${serverId}/${message.channel.id}/${message.id}`;
|
|
193
|
+
|
|
194
|
+
const embedLog = new EmbedBuilder()
|
|
195
|
+
.setColor("Blue")
|
|
196
|
+
.setThumbnail(message.client.user?.displayAvatarURL())
|
|
197
|
+
.setTitle("Use Prefix Command")
|
|
198
|
+
.setTimestamp()
|
|
199
|
+
.addFields(
|
|
200
|
+
{ name: "📧 Cmd:", value: `- ${command.name}`, inline: true },
|
|
201
|
+
{ name: "🤪 User:", value: `- ${userName} (<@${userId}>)`, inline: true },
|
|
202
|
+
{ name: "\u200B", value: "\u200B", inline: true },
|
|
203
|
+
{ name: "🏠 Server:", value: `- ${serverName}.\n- [\`${serverId}\`].`, inline: true },
|
|
204
|
+
{ name: "📩 Message:", value: `- [Link](${messageLink})`, inline: true },
|
|
205
|
+
{ name: "\u200B", value: "\u200B", inline: true },
|
|
206
|
+
{ name: "⏳ Date:", value: `- <t:${Math.floor(Date.now() / 1000)}:R>`, inline: true }
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
if (prefixOptions.logsId && channel) {
|
|
210
|
+
await channel.send({ embeds: [embedLog] });
|
|
211
|
+
}
|
|
131
212
|
}
|
|
132
|
-
} catch (error) {
|
|
133
|
-
|
|
213
|
+
} catch (error: any) {
|
|
214
|
+
logError(`Error executing command ${command.name}`, error);
|
|
134
215
|
}
|
|
135
|
-
}
|
|
136
216
|
}
|
|
137
217
|
|
|
138
218
|
export async function loadPrefix(client: Client, prefix: PrefixOptions): Promise<void> {
|
|
139
219
|
if (!prefix.prefix) {
|
|
140
|
-
throw new Error("⚠️
|
|
220
|
+
throw new Error("⚠️ No command prefix provided. Please provide a command prefix.");
|
|
141
221
|
}
|
|
142
222
|
|
|
143
|
-
try {
|
|
144
|
-
client.on("messageCreate", async message => await handleMessageCreate(message, prefix));
|
|
145
|
-
} catch (error) {
|
|
146
|
-
|
|
223
|
+
try {
|
|
224
|
+
client.on("messageCreate", async (message) => await handleMessageCreate(message, prefix));
|
|
225
|
+
} catch (error: any) {
|
|
226
|
+
logError("An error occurred while loading prefix.", error);
|
|
147
227
|
}
|
|
148
|
-
}
|
|
228
|
+
}
|