djs-next 0.0.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.
Potentially problematic release.
This version of djs-next might be problematic. Click here for more details.
- package/README.md +250 -0
- package/assets/djs-next.png +0 -0
- package/bin/create-djs-next.js +78 -0
- package/dist/index.d.mts +161 -0
- package/dist/index.d.ts +161 -0
- package/dist/index.js +1283 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1259 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +45 -0
- package/src/client.ts +492 -0
- package/src/handlers/commandHandler.ts +139 -0
- package/src/handlers/componentHandler.ts +31 -0
- package/src/handlers/eventHandler.ts +37 -0
- package/src/handlers/taskHandler.ts +38 -0
- package/src/handlers/utils.ts +25 -0
- package/src/index.ts +10 -0
- package/src/plugins/dnxt.ts +418 -0
- package/src/templates/cjs.ts +54 -0
- package/src/templates/esm.ts +50 -0
- package/src/templates/ts.ts +53 -0
- package/src/test/client.test.ts +8 -0
- package/src/types.ts +94 -0
- package/src/utils/PaginationBuilder.ts +94 -0
- package/src/utils/configLoader.ts +27 -0
- package/src/utils/i18n.ts +57 -0
- package/src/utils/paginate.ts +90 -0
- package/src/utils/prompts.ts +76 -0
- package/test_payload.js +3 -0
- package/test_reply.js +4 -0
- package/tsconfig.json +16 -0
- package/tsup.config.ts +10 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1283 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
21
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
22
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
23
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
24
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
25
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
26
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
27
|
+
mod
|
|
28
|
+
));
|
|
29
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
|
+
|
|
31
|
+
// src/index.ts
|
|
32
|
+
var index_exports = {};
|
|
33
|
+
__export(index_exports, {
|
|
34
|
+
DJSNextClient: () => DJSNextClient,
|
|
35
|
+
PaginationBuilder: () => PaginationBuilder,
|
|
36
|
+
confirmPrompt: () => confirmPrompt,
|
|
37
|
+
defineConfig: () => defineConfig,
|
|
38
|
+
getLocalesCache: () => getLocalesCache,
|
|
39
|
+
loadConfig: () => loadConfig,
|
|
40
|
+
loadLocales: () => loadLocales,
|
|
41
|
+
paginate: () => paginate,
|
|
42
|
+
translate: () => translate
|
|
43
|
+
});
|
|
44
|
+
module.exports = __toCommonJS(index_exports);
|
|
45
|
+
var import_config = require("dotenv/config");
|
|
46
|
+
|
|
47
|
+
// src/client.ts
|
|
48
|
+
var import_discord4 = require("discord.js");
|
|
49
|
+
|
|
50
|
+
// src/handlers/commandHandler.ts
|
|
51
|
+
var import_discord = require("discord.js");
|
|
52
|
+
var import_fs2 = __toESM(require("fs"));
|
|
53
|
+
var import_path2 = __toESM(require("path"));
|
|
54
|
+
var import_url = require("url");
|
|
55
|
+
|
|
56
|
+
// src/handlers/utils.ts
|
|
57
|
+
var import_fs = __toESM(require("fs"));
|
|
58
|
+
var import_path = __toESM(require("path"));
|
|
59
|
+
function getAllFiles(dirPath, arrayOfFiles = []) {
|
|
60
|
+
const files = import_fs.default.readdirSync(dirPath);
|
|
61
|
+
files.forEach((file) => {
|
|
62
|
+
const fullPath = import_path.default.join(dirPath, file);
|
|
63
|
+
if (import_fs.default.statSync(fullPath).isDirectory()) {
|
|
64
|
+
arrayOfFiles = getAllFiles(fullPath, arrayOfFiles);
|
|
65
|
+
} else {
|
|
66
|
+
if (file.endsWith(".js") || file.endsWith(".ts") || file.endsWith(".mjs") || file.endsWith(".cjs")) {
|
|
67
|
+
if (!file.endsWith(".d.ts")) {
|
|
68
|
+
arrayOfFiles.push(fullPath);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
return arrayOfFiles;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/handlers/commandHandler.ts
|
|
77
|
+
async function loadAndDeployCommands(commandsDir, token, clientId, guildId) {
|
|
78
|
+
const flatCommands = new import_discord.Collection();
|
|
79
|
+
if (!import_fs2.default.existsSync(commandsDir)) {
|
|
80
|
+
console.warn(`[djs-next] Commands directory "${commandsDir}" does not exist.`);
|
|
81
|
+
return flatCommands;
|
|
82
|
+
}
|
|
83
|
+
const commandFiles = getAllFiles(commandsDir);
|
|
84
|
+
const rootNodes = /* @__PURE__ */ new Map();
|
|
85
|
+
function getOrCreateNode(pathParts) {
|
|
86
|
+
let currentMap = rootNodes;
|
|
87
|
+
let currentNode;
|
|
88
|
+
for (const part of pathParts) {
|
|
89
|
+
if (!currentMap.has(part)) {
|
|
90
|
+
currentMap.set(part, {
|
|
91
|
+
name: part,
|
|
92
|
+
description: `${part} command`,
|
|
93
|
+
// Fallback description
|
|
94
|
+
options: [],
|
|
95
|
+
children: /* @__PURE__ */ new Map()
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
currentNode = currentMap.get(part);
|
|
99
|
+
currentMap = currentNode.children;
|
|
100
|
+
}
|
|
101
|
+
return currentNode;
|
|
102
|
+
}
|
|
103
|
+
for (const file of commandFiles) {
|
|
104
|
+
const relativePath = import_path2.default.relative(commandsDir, file);
|
|
105
|
+
const parsed = import_path2.default.parse(relativePath);
|
|
106
|
+
const dirParts = parsed.dir ? parsed.dir.split(import_path2.default.sep) : [];
|
|
107
|
+
const name = parsed.name;
|
|
108
|
+
const pathParts = [...dirParts];
|
|
109
|
+
if (name !== "index") {
|
|
110
|
+
pathParts.push(name);
|
|
111
|
+
}
|
|
112
|
+
if (pathParts.length === 0) continue;
|
|
113
|
+
if (pathParts.length > 3) {
|
|
114
|
+
console.warn(`[djs-next] Command path too deep (Discord allows max 3 levels): ${relativePath}`);
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
const module2 = await import((0, import_url.pathToFileURL)(file).href);
|
|
118
|
+
const commandData = module2.default || module2.command || module2;
|
|
119
|
+
if (commandData) commandData.filepath = file;
|
|
120
|
+
const node = getOrCreateNode(pathParts);
|
|
121
|
+
if (commandData.description) node.description = commandData.description;
|
|
122
|
+
if (commandData.options) node.options = commandData.options;
|
|
123
|
+
if (commandData.execute) {
|
|
124
|
+
node.execute = commandData.execute;
|
|
125
|
+
flatCommands.set(pathParts.join(" "), commandData);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
function buildCommandJSON(node, depth) {
|
|
129
|
+
const json = {
|
|
130
|
+
name: node.name,
|
|
131
|
+
description: node.description
|
|
132
|
+
};
|
|
133
|
+
if (node.children.size > 0) {
|
|
134
|
+
json.options = [];
|
|
135
|
+
for (const [_, childNode] of node.children) {
|
|
136
|
+
const childJson = buildCommandJSON(childNode, depth + 1);
|
|
137
|
+
if (depth === 0) {
|
|
138
|
+
childJson.type = childNode.children.size > 0 ? 2 : 1;
|
|
139
|
+
} else if (depth === 1) {
|
|
140
|
+
childJson.type = 1;
|
|
141
|
+
}
|
|
142
|
+
json.options.push(childJson);
|
|
143
|
+
}
|
|
144
|
+
} else if (node.options && node.options.length > 0) {
|
|
145
|
+
json.options = node.options;
|
|
146
|
+
}
|
|
147
|
+
return json;
|
|
148
|
+
}
|
|
149
|
+
const commandsData = Array.from(rootNodes.values()).map((node) => buildCommandJSON(node, 0));
|
|
150
|
+
const rest = new import_discord.REST({ version: "10" }).setToken(token);
|
|
151
|
+
try {
|
|
152
|
+
console.log(`[djs-next] Started refreshing ${commandsData.length} File-System application (/) commands.`);
|
|
153
|
+
let data;
|
|
154
|
+
if (guildId) {
|
|
155
|
+
data = await rest.put(
|
|
156
|
+
import_discord.Routes.applicationGuildCommands(clientId, guildId),
|
|
157
|
+
{ body: commandsData }
|
|
158
|
+
);
|
|
159
|
+
} else {
|
|
160
|
+
data = await rest.put(
|
|
161
|
+
import_discord.Routes.applicationCommands(clientId),
|
|
162
|
+
{ body: commandsData }
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
console.log(`[djs-next] Successfully reloaded ${data.length} File-System application (/) commands.`);
|
|
166
|
+
} catch (error) {
|
|
167
|
+
console.error(`[djs-next] Failed to deploy commands:`, error);
|
|
168
|
+
}
|
|
169
|
+
return flatCommands;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// src/handlers/eventHandler.ts
|
|
173
|
+
var import_fs3 = __toESM(require("fs"));
|
|
174
|
+
var import_url2 = require("url");
|
|
175
|
+
async function loadEvents(client2, eventsDir) {
|
|
176
|
+
if (!import_fs3.default.existsSync(eventsDir)) {
|
|
177
|
+
console.warn(`[djs-next] Events directory "${eventsDir}" does not exist.`);
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const eventFiles = getAllFiles(eventsDir);
|
|
181
|
+
let loadedEvents = 0;
|
|
182
|
+
for (const file of eventFiles) {
|
|
183
|
+
const eventModule = await import((0, import_url2.pathToFileURL)(file).href);
|
|
184
|
+
const eventData = eventModule.default?.event || eventModule.event || eventModule.default || eventModule;
|
|
185
|
+
if (eventData) eventData.filepath = file;
|
|
186
|
+
if (!eventData || !eventData.name || !eventData.execute) {
|
|
187
|
+
console.warn(`[djs-next] The event at ${file} is missing a required "name" or "execute" property.`);
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
if (eventData.once) {
|
|
191
|
+
client2.once(eventData.name, (...args2) => eventData.execute(client2, ...args2));
|
|
192
|
+
} else {
|
|
193
|
+
client2.on(eventData.name, (...args2) => eventData.execute(client2, ...args2));
|
|
194
|
+
}
|
|
195
|
+
loadedEvents++;
|
|
196
|
+
}
|
|
197
|
+
if (loadedEvents > 0) {
|
|
198
|
+
console.log(`[djs-next] Successfully loaded ${loadedEvents} events.`);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// src/handlers/componentHandler.ts
|
|
203
|
+
var import_discord2 = require("discord.js");
|
|
204
|
+
var import_fs4 = __toESM(require("fs"));
|
|
205
|
+
var import_path3 = __toESM(require("path"));
|
|
206
|
+
var import_url3 = require("url");
|
|
207
|
+
async function loadComponents(componentsDir) {
|
|
208
|
+
const components2 = new import_discord2.Collection();
|
|
209
|
+
if (!import_fs4.default.existsSync(componentsDir)) return components2;
|
|
210
|
+
const files = getAllFiles(componentsDir);
|
|
211
|
+
for (const file of files) {
|
|
212
|
+
const module2 = await import((0, import_url3.pathToFileURL)(file).href);
|
|
213
|
+
const componentData = module2.default || module2.component || module2;
|
|
214
|
+
if (componentData) componentData.filepath = file;
|
|
215
|
+
if (!componentData || !componentData.execute) continue;
|
|
216
|
+
const parsed = import_path3.default.parse(file);
|
|
217
|
+
const customId = componentData.customId || parsed.name;
|
|
218
|
+
components2.set(customId, componentData);
|
|
219
|
+
}
|
|
220
|
+
console.log(`[djs-next] Successfully loaded ${components2.size} components.`);
|
|
221
|
+
return components2;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// src/handlers/taskHandler.ts
|
|
225
|
+
var import_fs5 = __toESM(require("fs"));
|
|
226
|
+
var import_url4 = require("url");
|
|
227
|
+
async function loadTasks(client2, tasksDir) {
|
|
228
|
+
if (!import_fs5.default.existsSync(tasksDir)) return;
|
|
229
|
+
const files = getAllFiles(tasksDir);
|
|
230
|
+
let loaded = 0;
|
|
231
|
+
for (const file of files) {
|
|
232
|
+
const module2 = await import((0, import_url4.pathToFileURL)(file).href);
|
|
233
|
+
const taskData = module2.default || module2.task || module2;
|
|
234
|
+
if (taskData) taskData.filepath = file;
|
|
235
|
+
if (!taskData || !taskData.interval || !taskData.execute) continue;
|
|
236
|
+
const intervalId = setInterval(async () => {
|
|
237
|
+
try {
|
|
238
|
+
await taskData.execute(client2);
|
|
239
|
+
} catch (error) {
|
|
240
|
+
console.error(`[djs-next] Background Task error at ${file}:`, error);
|
|
241
|
+
}
|
|
242
|
+
}, taskData.interval);
|
|
243
|
+
if (!client2._activeTasks) client2._activeTasks = /* @__PURE__ */ new Map();
|
|
244
|
+
client2._activeTasks.set(file, intervalId);
|
|
245
|
+
loaded++;
|
|
246
|
+
}
|
|
247
|
+
if (loaded > 0) {
|
|
248
|
+
console.log(`[djs-next] Successfully scheduled ${loaded} background tasks.`);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// src/client.ts
|
|
253
|
+
var import_path6 = __toESM(require("path"));
|
|
254
|
+
var import_fs8 = __toESM(require("fs"));
|
|
255
|
+
var import_url6 = require("url");
|
|
256
|
+
|
|
257
|
+
// src/utils/configLoader.ts
|
|
258
|
+
var import_path4 = __toESM(require("path"));
|
|
259
|
+
var import_fs6 = __toESM(require("fs"));
|
|
260
|
+
var import_url5 = require("url");
|
|
261
|
+
async function loadConfig() {
|
|
262
|
+
const exts = [".js", ".mjs", ".cjs", ".ts", ".mts", ".cts"];
|
|
263
|
+
const cwd = process.cwd();
|
|
264
|
+
for (const ext of exts) {
|
|
265
|
+
const configPath = import_path4.default.join(cwd, `djs-next.config${ext}`);
|
|
266
|
+
if (import_fs6.default.existsSync(configPath)) {
|
|
267
|
+
try {
|
|
268
|
+
const configModule = await import((0, import_url5.pathToFileURL)(configPath).href);
|
|
269
|
+
return configModule.default || configModule;
|
|
270
|
+
} catch (err) {
|
|
271
|
+
console.error(`[djs-next] Error loading config file ${configPath}:`, err);
|
|
272
|
+
return {};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
return {};
|
|
277
|
+
}
|
|
278
|
+
function defineConfig(config2) {
|
|
279
|
+
return config2;
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// src/utils/i18n.ts
|
|
283
|
+
var import_fs7 = __toESM(require("fs"));
|
|
284
|
+
var import_path5 = __toESM(require("path"));
|
|
285
|
+
var localesCache = {};
|
|
286
|
+
var defaultLoc = "en";
|
|
287
|
+
function loadLocales(localesDir, defaultLocale) {
|
|
288
|
+
if (defaultLocale) defaultLoc = defaultLocale;
|
|
289
|
+
if (!import_fs7.default.existsSync(localesDir)) return;
|
|
290
|
+
const files = import_fs7.default.readdirSync(localesDir);
|
|
291
|
+
for (const file of files) {
|
|
292
|
+
if (file.endsWith(".json")) {
|
|
293
|
+
const lang = file.replace(".json", "");
|
|
294
|
+
const content2 = import_fs7.default.readFileSync(import_path5.default.join(localesDir, file), "utf8");
|
|
295
|
+
try {
|
|
296
|
+
localesCache[lang] = JSON.parse(content2);
|
|
297
|
+
} catch (e) {
|
|
298
|
+
console.error(`[djs-next] Failed to parse locale file: ${file}`, e);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
function translate(key, locale = defaultLoc, variables) {
|
|
304
|
+
const dict = localesCache[locale] || localesCache[defaultLoc] || {};
|
|
305
|
+
const keys = key.split(".");
|
|
306
|
+
let value = dict;
|
|
307
|
+
for (const k of keys) {
|
|
308
|
+
if (value && typeof value === "object") {
|
|
309
|
+
value = value[k];
|
|
310
|
+
} else {
|
|
311
|
+
value = void 0;
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
if (typeof value !== "string") {
|
|
316
|
+
return key;
|
|
317
|
+
}
|
|
318
|
+
if (variables) {
|
|
319
|
+
for (const [varKey, varValue] of Object.entries(variables)) {
|
|
320
|
+
value = value.replace(new RegExp(`{{s*${varKey}s*}}`, "g"), String(varValue));
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
return value;
|
|
324
|
+
}
|
|
325
|
+
function getLocalesCache() {
|
|
326
|
+
return localesCache;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// src/plugins/dnxt.ts
|
|
330
|
+
var import_discord3 = require("discord.js");
|
|
331
|
+
var import_child_process = require("child_process");
|
|
332
|
+
var import_util = __toESM(require("util"));
|
|
333
|
+
var import_os = __toESM(require("os"));
|
|
334
|
+
var execAsync = import_util.default.promisify(import_child_process.exec);
|
|
335
|
+
function buildDisplayMessage(content2, color = 5397233) {
|
|
336
|
+
const djs = require("discord.js");
|
|
337
|
+
const container = new djs.ContainerBuilder().setAccentColor(color).addTextDisplayComponents(
|
|
338
|
+
new djs.TextDisplayBuilder().setContent(content2)
|
|
339
|
+
);
|
|
340
|
+
return { components: [container], flags: 32768 };
|
|
341
|
+
}
|
|
342
|
+
async function handleDNXT(message, client, devPrefix) {
|
|
343
|
+
if (message.author.bot) return;
|
|
344
|
+
if (!client._developers.includes(message.author.id)) return;
|
|
345
|
+
if (client.config?.devGuildId && message.guildId !== client.config.devGuildId) return;
|
|
346
|
+
const originalReply = message.reply.bind(message);
|
|
347
|
+
message.reply = (async (content2) => {
|
|
348
|
+
if (typeof content2 === "string") {
|
|
349
|
+
return await originalReply({ ...buildDisplayMessage(content2), allowedMentions: { repliedUser: false } });
|
|
350
|
+
}
|
|
351
|
+
if (!content2.allowedMentions) content2.allowedMentions = { repliedUser: false };
|
|
352
|
+
return await originalReply(content2);
|
|
353
|
+
});
|
|
354
|
+
const content = message.content.trim();
|
|
355
|
+
const validTriggers = [devPrefix];
|
|
356
|
+
const clientPrefixes = client._prefixes || [];
|
|
357
|
+
for (const p of clientPrefixes) {
|
|
358
|
+
if (p !== "") validTriggers.push(`${p}${devPrefix}`);
|
|
359
|
+
}
|
|
360
|
+
let matchedTrigger = validTriggers.find((t) => content === t || content.startsWith(`${t} `));
|
|
361
|
+
if (!matchedTrigger) return;
|
|
362
|
+
const args = content.slice(matchedTrigger.length).trim().split(/ +/g);
|
|
363
|
+
const command = args.shift()?.toLowerCase();
|
|
364
|
+
if (command === "help") {
|
|
365
|
+
const djs = require("discord.js");
|
|
366
|
+
const container = new djs.ContainerBuilder().setAccentColor(5397233).addTextDisplayComponents(
|
|
367
|
+
new djs.TextDisplayBuilder().setContent(`# \u{1F4D6} DNXT Toolkit Reference
|
|
368
|
+
> Current prefix trigger: \`${matchedTrigger}\``)
|
|
369
|
+
).addSeparatorComponents(new djs.SeparatorBuilder()).addTextDisplayComponents(
|
|
370
|
+
new djs.TextDisplayBuilder().setContent(`### \u{1F4CA} Core Framework
|
|
371
|
+
- \`${matchedTrigger}\` \u2014 Developer system dashboard
|
|
372
|
+
- \`${matchedTrigger} help\` \u2014 Shows this reference menu`),
|
|
373
|
+
new djs.TextDisplayBuilder().setContent(`### \u{1F4BB} Execution & Diagnostics
|
|
374
|
+
- \`${matchedTrigger} js <code>\` \u2014 Evaluates raw JS code
|
|
375
|
+
- \`${matchedTrigger} sh <cmd>\` \u2014 Runs terminal shell script
|
|
376
|
+
- \`${matchedTrigger} debug <code>\` \u2014 Evaluates JS with precise memory deltas`),
|
|
377
|
+
new djs.TextDisplayBuilder().setContent(`### \u{1F4C2} File System & Network
|
|
378
|
+
- \`${matchedTrigger} cat <file>\` \u2014 Reads file contents
|
|
379
|
+
- \`${matchedTrigger} curl <url>\` \u2014 Fetches remote URL data
|
|
380
|
+
- \`${matchedTrigger} git <cmd>\` \u2014 Executes git repository commands`),
|
|
381
|
+
new djs.TextDisplayBuilder().setContent(`### \u{1F9F0} Utilities
|
|
382
|
+
- \`${matchedTrigger} <load|unload|reload> <target>\` \u2014 Manages system modules
|
|
383
|
+
- \`${matchedTrigger} sync\` \u2014 Forces global slash command sync
|
|
384
|
+
- \`${matchedTrigger} in <channel> <cmd>\` \u2014 Executes command in target channel
|
|
385
|
+
- \`${matchedTrigger} restart\` \u2014 Restarts the bot completely
|
|
386
|
+
- \`${matchedTrigger} shutdown\` \u2014 Stops the bot completely`)
|
|
387
|
+
);
|
|
388
|
+
await message.reply({ components: [container], flags: 32768, allowedMentions: { repliedUser: false } });
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
if (!command) {
|
|
392
|
+
const mem = process.memoryUsage();
|
|
393
|
+
const botPing = client.ws.ping;
|
|
394
|
+
const djs = require("discord.js");
|
|
395
|
+
const container = new djs.ContainerBuilder().setAccentColor(5397233).addTextDisplayComponents(
|
|
396
|
+
new djs.TextDisplayBuilder().setContent(`# \u{1F6E0}\uFE0F Developer System Dashboard
|
|
397
|
+
> **DNXT Framework Engine**`)
|
|
398
|
+
).addSeparatorComponents(new djs.SeparatorBuilder()).addTextDisplayComponents(
|
|
399
|
+
new djs.TextDisplayBuilder().setContent(`### \u{1F4E1} Network Status
|
|
400
|
+
- **System Uptime:** <t:${Math.floor((Date.now() - client.uptime) / 1e3)}:R>
|
|
401
|
+
- **WebSocket Latency:** \`${botPing}ms\``),
|
|
402
|
+
new djs.TextDisplayBuilder().setContent(`### \u{1F4E6} Host Environment
|
|
403
|
+
- **Discord.js Library:** \`v${import_discord3.version}\`
|
|
404
|
+
- **Node.js Runtime:** \`${process.version}\`
|
|
405
|
+
- **Operating System:** \`${import_os.default.type()}\` (\`${import_os.default.cpus().length}\` thread cores, \`${(import_os.default.uptime() / 60 / 60).toFixed(2)}\` hrs uptime)`),
|
|
406
|
+
new djs.TextDisplayBuilder().setContent(`### \u{1F9E0} Resource Utilization
|
|
407
|
+
- **Physical Memory:** \`${(mem.rss / 1024 / 1024).toFixed(2)} MB\`
|
|
408
|
+
- **Heap Allocated:** \`${(mem.heapUsed / 1024 / 1024).toFixed(2)} MB\``)
|
|
409
|
+
);
|
|
410
|
+
await message.reply({
|
|
411
|
+
components: [container],
|
|
412
|
+
flags: 32768,
|
|
413
|
+
// MessageFlags.IsComponentsV2
|
|
414
|
+
allowedMentions: { repliedUser: false }
|
|
415
|
+
});
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
if (command === "js" || command === "eval" || command === "py") {
|
|
419
|
+
let code = args.join(" ");
|
|
420
|
+
if (code.startsWith("```js") || code.startsWith("```py")) code = code.replace(/^```[a-z]*|```$/g, "");
|
|
421
|
+
else if (code.startsWith("```")) code = code.replace(/^```|```$/g, "");
|
|
422
|
+
if (!code) return void await message.reply("\u274C Please provide code to evaluate.");
|
|
423
|
+
try {
|
|
424
|
+
const start = process.hrtime.bigint();
|
|
425
|
+
const { commands, components, config } = client;
|
|
426
|
+
let evaled = await eval(`(async () => { ${code} })()`);
|
|
427
|
+
const end = process.hrtime.bigint();
|
|
428
|
+
const timeMs = Number(end - start) / 1e6;
|
|
429
|
+
if (typeof evaled !== "string") evaled = import_util.default.inspect(evaled, { depth: 1, colors: true });
|
|
430
|
+
await sendPaginatedText(message, `\u2705 **Evaluated in ${timeMs.toFixed(3)}ms**
|
|
431
|
+
`, evaled, "ansi");
|
|
432
|
+
} catch (err) {
|
|
433
|
+
await sendPaginatedText(message, `\u274C **Evaluation Error**
|
|
434
|
+
`, err.message, "ansi");
|
|
435
|
+
}
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
if (command === "sh" || command === "shell" || command === "git") {
|
|
439
|
+
const cmd = command === "git" ? "git " + args.join(" ") : args.join(" ");
|
|
440
|
+
if (!cmd) return void await message.reply("\u274C Please provide a command to execute.");
|
|
441
|
+
try {
|
|
442
|
+
const start2 = process.hrtime.bigint();
|
|
443
|
+
let stdout = "", stderr = "", code2 = 0;
|
|
444
|
+
try {
|
|
445
|
+
const result = await execAsync(cmd);
|
|
446
|
+
stdout = result.stdout;
|
|
447
|
+
stderr = result.stderr;
|
|
448
|
+
} catch (err) {
|
|
449
|
+
stdout = err.stdout || "";
|
|
450
|
+
stderr = err.stderr || err.message || "";
|
|
451
|
+
code2 = err.code || 1;
|
|
452
|
+
}
|
|
453
|
+
const end2 = process.hrtime.bigint();
|
|
454
|
+
const timeMs2 = Number(end2 - start2) / 1e6;
|
|
455
|
+
let resultText = `$ ${cmd}
|
|
456
|
+
`;
|
|
457
|
+
if (stdout) resultText += `${stdout}
|
|
458
|
+
`;
|
|
459
|
+
if (stderr) resultText += `${stderr}
|
|
460
|
+
`;
|
|
461
|
+
resultText += `
|
|
462
|
+
[status] Return code ${code2}`;
|
|
463
|
+
await sendPaginatedText(message, `\u2705 **Executed in ${timeMs2.toFixed(3)}ms**
|
|
464
|
+
`, resultText, "ansi");
|
|
465
|
+
} catch (err) {
|
|
466
|
+
await sendPaginatedText(message, `\u274C **Shell Error**
|
|
467
|
+
`, err.message, "ansi");
|
|
468
|
+
}
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
if (command === "load" || command === "unload" || command === "reload") {
|
|
472
|
+
const target = args[0]?.toLowerCase();
|
|
473
|
+
try {
|
|
474
|
+
if (target === "commands" && client["_commandsDir"]) {
|
|
475
|
+
if (command === "unload" || command === "reload") client.commands.clear();
|
|
476
|
+
if (command === "load" || command === "reload") client.commands = await loadAndDeployCommands(client["_commandsDir"], client.token, client["_clientId"], client["_guildId"]);
|
|
477
|
+
await message.reply(`\u2705 Successfully ${command}ed commands.`);
|
|
478
|
+
} else if (target === "events" && client["_eventsDir"]) {
|
|
479
|
+
if (command === "unload" || command === "reload") {
|
|
480
|
+
client.removeAllListeners();
|
|
481
|
+
client["attachCoreListeners"]();
|
|
482
|
+
}
|
|
483
|
+
if (command === "load" || command === "reload") await loadEvents(client, client["_eventsDir"]);
|
|
484
|
+
await message.reply(`\u2705 Successfully ${command}ed events.`);
|
|
485
|
+
} else if (target === "components" && client["_componentsDir"]) {
|
|
486
|
+
if (command === "unload" || command === "reload") client.components.clear();
|
|
487
|
+
if (command === "load" || command === "reload") client.components = await loadComponents(client["_componentsDir"]);
|
|
488
|
+
await message.reply(`\u2705 Successfully ${command}ed components.`);
|
|
489
|
+
} else if (target === "locales" && client["_localesDir"]) {
|
|
490
|
+
if (command === "load" || command === "reload") loadLocales(client["_localesDir"], client.config.defaultLocale);
|
|
491
|
+
await message.reply(`\u2705 Successfully ${command}ed locales.`);
|
|
492
|
+
} else if (target === "all" || !target) {
|
|
493
|
+
if (command === "unload" || command === "reload") {
|
|
494
|
+
client.removeAllListeners();
|
|
495
|
+
client["attachCoreListeners"]();
|
|
496
|
+
client.commands.clear();
|
|
497
|
+
client.components.clear();
|
|
498
|
+
}
|
|
499
|
+
if (command === "load" || command === "reload") {
|
|
500
|
+
if (client["_eventsDir"]) await loadEvents(client, client["_eventsDir"]);
|
|
501
|
+
if (client["_componentsDir"]) client.components = await loadComponents(client["_componentsDir"]);
|
|
502
|
+
if (client["_localesDir"]) loadLocales(client["_localesDir"], client.config.defaultLocale);
|
|
503
|
+
if (client["_commandsDir"]) client.commands = await loadAndDeployCommands(client["_commandsDir"], client.token, client["_clientId"], client["_guildId"]);
|
|
504
|
+
}
|
|
505
|
+
await message.reply(`\u2705 Successfully ${command}ed all framework modules.`);
|
|
506
|
+
} else {
|
|
507
|
+
await message.reply("\u274C Unknown target. Valid targets: `commands, events, components, locales, all`");
|
|
508
|
+
}
|
|
509
|
+
} catch (err) {
|
|
510
|
+
await message.reply(`\u274C **${command.toUpperCase()} Error:** ${err.message}`);
|
|
511
|
+
}
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
if (command === "cat") {
|
|
515
|
+
const fs9 = await import("fs");
|
|
516
|
+
const path7 = await import("path");
|
|
517
|
+
const file = args.join(" ");
|
|
518
|
+
if (!file) return void await message.reply("\u274C Please provide a file to read.");
|
|
519
|
+
try {
|
|
520
|
+
const content2 = fs9.readFileSync(path7.resolve(process.cwd(), file), "utf8");
|
|
521
|
+
await sendPaginatedText(message, `\u{1F4C4} **${file}**
|
|
522
|
+
`, content2, file.split(".").pop() || "");
|
|
523
|
+
} catch (e) {
|
|
524
|
+
await message.reply(`\u274C **Error reading file:** ${e.message}`);
|
|
525
|
+
}
|
|
526
|
+
return;
|
|
527
|
+
}
|
|
528
|
+
if (command === "curl") {
|
|
529
|
+
const url = args[0];
|
|
530
|
+
if (!url) return void await message.reply("\u274C Please provide a URL.");
|
|
531
|
+
try {
|
|
532
|
+
const res = await fetch(url);
|
|
533
|
+
const text = await res.text();
|
|
534
|
+
await sendPaginatedText(message, `\u{1F310} **Fetched from \`${url}\`**
|
|
535
|
+
`, text, "html");
|
|
536
|
+
} catch (e) {
|
|
537
|
+
await message.reply(`\u274C **Curl Error:** ${e.message}`);
|
|
538
|
+
}
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
if (command === "debug") {
|
|
542
|
+
let code = args.join(" ");
|
|
543
|
+
if (code.startsWith("```js") || code.startsWith("```py")) code = code.replace(/^```[a-z]*|```$/g, "");
|
|
544
|
+
else if (code.startsWith("```")) code = code.replace(/^```|```$/g, "");
|
|
545
|
+
if (!code) return void await message.reply("\u274C Please provide code to debug.");
|
|
546
|
+
try {
|
|
547
|
+
const startMem = process.memoryUsage().heapUsed;
|
|
548
|
+
const start = process.hrtime.bigint();
|
|
549
|
+
const { commands, components, config } = client;
|
|
550
|
+
let evaled = await eval(`(async () => { ${code} })()`);
|
|
551
|
+
const end = process.hrtime.bigint();
|
|
552
|
+
const endMem = process.memoryUsage().heapUsed;
|
|
553
|
+
const timeMs = Number(end - start) / 1e6;
|
|
554
|
+
const memDiff = (endMem - startMem) / 1024 / 1024;
|
|
555
|
+
if (typeof evaled !== "string") evaled = import_util.default.inspect(evaled, { depth: 1, colors: true });
|
|
556
|
+
await sendPaginatedText(message, `\u23F1\uFE0F **Debug Execution**
|
|
557
|
+
Time: \`${timeMs.toFixed(3)}ms\` | Heap Delta: \`${memDiff.toFixed(3)}MB\`
|
|
558
|
+
`, evaled, "ansi");
|
|
559
|
+
} catch (err) {
|
|
560
|
+
await sendPaginatedText(message, `\u274C **Debug Error**
|
|
561
|
+
`, err.message, "ansi");
|
|
562
|
+
}
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
if (command === "in") {
|
|
566
|
+
const channelId = args.shift()?.replace(/<#|>/g, "");
|
|
567
|
+
const cmd = args.join(" ");
|
|
568
|
+
if (!channelId || !cmd) return void await message.reply(`\u274C Usage: ${matchedTrigger} in <#channel|id> <command>`);
|
|
569
|
+
try {
|
|
570
|
+
const targetChannel = await client.channels.fetch(channelId);
|
|
571
|
+
if (!targetChannel || !targetChannel.isTextBased()) throw new Error("Invalid Text Channel.");
|
|
572
|
+
const mockMessage = Object.assign(Object.create(Object.getPrototypeOf(message)), message);
|
|
573
|
+
Object.defineProperty(mockMessage, "client", { value: client, configurable: true });
|
|
574
|
+
if (message.guild) {
|
|
575
|
+
Object.defineProperty(mockMessage, "guild", { value: message.guild, configurable: true });
|
|
576
|
+
Object.defineProperty(mockMessage, "guildId", { value: message.guildId, configurable: true });
|
|
577
|
+
}
|
|
578
|
+
Object.defineProperty(mockMessage, "channel", { value: targetChannel, configurable: true });
|
|
579
|
+
Object.defineProperty(mockMessage, "channelId", { value: targetChannel.id, configurable: true });
|
|
580
|
+
Object.defineProperty(mockMessage, "content", { value: cmd, configurable: true });
|
|
581
|
+
client.emit("messageCreate", mockMessage);
|
|
582
|
+
} catch (e) {
|
|
583
|
+
await message.reply(`\u274C **In Error:** ${e.message}`);
|
|
584
|
+
}
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
if (command === "sync") {
|
|
588
|
+
try {
|
|
589
|
+
await message.reply("\u{1F504} Force syncing slash commands...");
|
|
590
|
+
await loadAndDeployCommands(client._commandsDir, client.token, client._clientId, client._guildId);
|
|
591
|
+
await message.reply("\u2705 Slash commands synchronized globally/locally.");
|
|
592
|
+
} catch (e) {
|
|
593
|
+
await message.reply(`\u274C **Sync Error:** ${e.message}`);
|
|
594
|
+
}
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
if (command === "restart") {
|
|
598
|
+
await message.reply("\u{1F504} Restarting framework...");
|
|
599
|
+
client.destroy();
|
|
600
|
+
const { spawn } = require("child_process");
|
|
601
|
+
const child = spawn(process.argv[0], process.argv.slice(1), {
|
|
602
|
+
detached: true,
|
|
603
|
+
stdio: "ignore",
|
|
604
|
+
cwd: process.cwd()
|
|
605
|
+
});
|
|
606
|
+
child.unref();
|
|
607
|
+
process.exit(0);
|
|
608
|
+
return;
|
|
609
|
+
}
|
|
610
|
+
if (command === "shutdown" || command === "stop") {
|
|
611
|
+
await message.reply("\u{1F6D1} Shutting down framework...");
|
|
612
|
+
client.destroy();
|
|
613
|
+
process.exit(0);
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
616
|
+
await message.reply(`\u2753 Unknown ${matchedTrigger} command. Available: \`js, sh, git, cat, curl, in, debug, reload, sync, restart, shutdown\``);
|
|
617
|
+
}
|
|
618
|
+
async function sendPaginatedText(message2, header, content2, language = "") {
|
|
619
|
+
const maxLength = 800;
|
|
620
|
+
if (content2.length <= maxLength) {
|
|
621
|
+
await message2.reply(buildDisplayMessage(`### ${header.replace(/\\*\\*/g, "")}
|
|
622
|
+
\`\`\`${language}
|
|
623
|
+
${content2}
|
|
624
|
+
\`\`\``));
|
|
625
|
+
return;
|
|
626
|
+
}
|
|
627
|
+
const chunks = [];
|
|
628
|
+
for (let i = 0; i < content2.length; i += maxLength) {
|
|
629
|
+
chunks.push(content2.substring(i, i + maxLength));
|
|
630
|
+
}
|
|
631
|
+
let index = 0;
|
|
632
|
+
const djs = require("discord.js");
|
|
633
|
+
function buildPage(idx) {
|
|
634
|
+
const text = `### ${header.replace(/\\*\\*/g, "")}
|
|
635
|
+
\`\`\`${language}
|
|
636
|
+
${chunks[idx]}
|
|
637
|
+
\`\`\`
|
|
638
|
+
> *Page ${idx + 1} of ${chunks.length}*`;
|
|
639
|
+
const container = new djs.ContainerBuilder().setAccentColor(5397233).addTextDisplayComponents(
|
|
640
|
+
new djs.TextDisplayBuilder().setContent(text)
|
|
641
|
+
);
|
|
642
|
+
const row1 = new djs.ActionRowBuilder().addComponents(
|
|
643
|
+
new djs.ButtonBuilder().setCustomId("first").setLabel("\u226A").setStyle(2),
|
|
644
|
+
new djs.ButtonBuilder().setCustomId("prev").setLabel("\uFF1C").setStyle(2),
|
|
645
|
+
new djs.ButtonBuilder().setCustomId("goto").setLabel("\u2398").setStyle(1),
|
|
646
|
+
new djs.ButtonBuilder().setCustomId("next").setLabel("\uFF1E").setStyle(2),
|
|
647
|
+
new djs.ButtonBuilder().setCustomId("last").setLabel("\u226B").setStyle(2)
|
|
648
|
+
);
|
|
649
|
+
const row2 = new djs.ActionRowBuilder().addComponents(
|
|
650
|
+
new djs.ButtonBuilder().setCustomId("stop").setLabel("\u2716 Close").setStyle(4)
|
|
651
|
+
);
|
|
652
|
+
container.addActionRowComponents(row1, row2);
|
|
653
|
+
return { components: [container], flags: 32768 };
|
|
654
|
+
}
|
|
655
|
+
const reply = await message2.reply(buildPage(index));
|
|
656
|
+
const collector = reply.createMessageComponentCollector({
|
|
657
|
+
filter: (i) => ["first", "prev", "goto", "stop", "next", "last"].includes(i.customId) && i.user.id === message2.author.id,
|
|
658
|
+
time: 12e4
|
|
659
|
+
});
|
|
660
|
+
collector.on("collect", async (i) => {
|
|
661
|
+
if (i.customId === "first") {
|
|
662
|
+
index = 0;
|
|
663
|
+
} else if (i.customId === "prev") {
|
|
664
|
+
index = index > 0 ? index - 1 : index;
|
|
665
|
+
} else if (i.customId === "next") {
|
|
666
|
+
index = index < chunks.length - 1 ? index + 1 : index;
|
|
667
|
+
} else if (i.customId === "last") {
|
|
668
|
+
index = chunks.length - 1;
|
|
669
|
+
} else if (i.customId === "goto") {
|
|
670
|
+
const modal = new djs.ModalBuilder().setCustomId("goto_modal").setTitle("Go to Page");
|
|
671
|
+
const input = new djs.TextInputBuilder().setCustomId("page_num").setLabel(`Page Number (1-${chunks.length})`).setStyle(1).setRequired(true);
|
|
672
|
+
modal.addComponents(new djs.ActionRowBuilder().addComponents(input));
|
|
673
|
+
await i.showModal(modal);
|
|
674
|
+
try {
|
|
675
|
+
const modalSubmit = await i.awaitModalSubmit({ filter: (mi) => mi.user.id === message2.author.id && mi.customId === "goto_modal", time: 6e4 });
|
|
676
|
+
const targetPage = parseInt(modalSubmit.fields.getTextInputValue("page_num"), 10);
|
|
677
|
+
if (!isNaN(targetPage) && targetPage >= 1 && targetPage <= chunks.length) {
|
|
678
|
+
index = targetPage - 1;
|
|
679
|
+
}
|
|
680
|
+
await modalSubmit.update(buildPage(index));
|
|
681
|
+
} catch {
|
|
682
|
+
}
|
|
683
|
+
return;
|
|
684
|
+
} else if (i.customId === "stop") {
|
|
685
|
+
await reply.delete().catch(() => null);
|
|
686
|
+
collector.stop();
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
await i.update(buildPage(index));
|
|
690
|
+
});
|
|
691
|
+
collector.on("end", () => {
|
|
692
|
+
reply.edit({ components: [] }).catch(() => null);
|
|
693
|
+
});
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
// src/client.ts
|
|
697
|
+
var DJSNextClient = class extends import_discord4.Client {
|
|
698
|
+
commands;
|
|
699
|
+
components;
|
|
700
|
+
cooldowns;
|
|
701
|
+
config = {};
|
|
702
|
+
t = translate;
|
|
703
|
+
db;
|
|
704
|
+
_commandsDir;
|
|
705
|
+
_eventsDir;
|
|
706
|
+
_componentsDir;
|
|
707
|
+
_tasksDir;
|
|
708
|
+
_localesDir;
|
|
709
|
+
_clientId;
|
|
710
|
+
_guildId;
|
|
711
|
+
_developers;
|
|
712
|
+
_middleware;
|
|
713
|
+
_prefixes;
|
|
714
|
+
_enableSlashCommands;
|
|
715
|
+
_enableTextCommands;
|
|
716
|
+
_enableMentionPrefix;
|
|
717
|
+
_enableNoPrefix;
|
|
718
|
+
constructor(options) {
|
|
719
|
+
super(options);
|
|
720
|
+
this.commands = new import_discord4.Collection();
|
|
721
|
+
this.components = new import_discord4.Collection();
|
|
722
|
+
this.cooldowns = new import_discord4.Collection();
|
|
723
|
+
this._commandsDir = options.commandsDir ? import_path6.default.resolve(process.cwd(), options.commandsDir) : void 0;
|
|
724
|
+
this._eventsDir = options.eventsDir ? import_path6.default.resolve(process.cwd(), options.eventsDir) : void 0;
|
|
725
|
+
this._componentsDir = options.componentsDir ? import_path6.default.resolve(process.cwd(), options.componentsDir) : void 0;
|
|
726
|
+
this._tasksDir = options.tasksDir ? import_path6.default.resolve(process.cwd(), options.tasksDir) : void 0;
|
|
727
|
+
this._clientId = options.clientId;
|
|
728
|
+
this._guildId = options.guildId;
|
|
729
|
+
this._developers = options.developers || [];
|
|
730
|
+
this._middleware = options.middleware;
|
|
731
|
+
const prefs = options.prefixes || [];
|
|
732
|
+
this._prefixes = Array.isArray(prefs) ? prefs : [prefs];
|
|
733
|
+
this._prefixes = this._prefixes.filter((p) => p !== "");
|
|
734
|
+
this._enableSlashCommands = options.enableSlashCommands ?? true;
|
|
735
|
+
this._enableTextCommands = options.enableTextCommands ?? true;
|
|
736
|
+
this._enableMentionPrefix = options.enableMentionPrefix ?? true;
|
|
737
|
+
this._enableNoPrefix = options.enableNoPrefix ?? false;
|
|
738
|
+
if (options.db) this.db = options.db;
|
|
739
|
+
this.attachCoreListeners();
|
|
740
|
+
}
|
|
741
|
+
attachCoreListeners() {
|
|
742
|
+
this.on("interactionCreate", async (interaction) => {
|
|
743
|
+
if (this._middleware) {
|
|
744
|
+
try {
|
|
745
|
+
const shouldContinue = await this._middleware(interaction, this);
|
|
746
|
+
if (!shouldContinue) return;
|
|
747
|
+
} catch (error) {
|
|
748
|
+
console.error(`[djs-next] Middleware error:`, error);
|
|
749
|
+
return;
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
if (interaction.isChatInputCommand()) {
|
|
753
|
+
if (!this._enableSlashCommands) return;
|
|
754
|
+
let commandKey = interaction.commandName;
|
|
755
|
+
const group = interaction.options.getSubcommandGroup(false);
|
|
756
|
+
const sub = interaction.options.getSubcommand(false);
|
|
757
|
+
if (group) commandKey += ` ${group}`;
|
|
758
|
+
if (sub) commandKey += ` ${sub}`;
|
|
759
|
+
const command2 = this.commands.get(commandKey);
|
|
760
|
+
if (!command2 || !command2.execute) return;
|
|
761
|
+
if (!await this.handlePreconditions(command2, interaction, commandKey)) return;
|
|
762
|
+
try {
|
|
763
|
+
await command2.execute(interaction, this);
|
|
764
|
+
} catch (error) {
|
|
765
|
+
await this.handleCommandError(error, commandKey, interaction);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
if (interaction.isAutocomplete()) {
|
|
769
|
+
let commandKey = interaction.commandName;
|
|
770
|
+
const group = interaction.options.getSubcommandGroup(false);
|
|
771
|
+
const sub = interaction.options.getSubcommand(false);
|
|
772
|
+
if (group) commandKey += ` ${group}`;
|
|
773
|
+
if (sub) commandKey += ` ${sub}`;
|
|
774
|
+
const command2 = this.commands.get(commandKey);
|
|
775
|
+
if (command2 && command2.autocomplete) {
|
|
776
|
+
try {
|
|
777
|
+
await command2.autocomplete(interaction, this);
|
|
778
|
+
} catch (error) {
|
|
779
|
+
console.error(`[djs-next] Error executing autocomplete for: "${commandKey}"`, error);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
if (interaction.isMessageComponent() || interaction.isModalSubmit()) {
|
|
784
|
+
if (interaction.customId === "djs_prev" || interaction.customId === "djs_next") return;
|
|
785
|
+
let component = this.components.get(interaction.customId);
|
|
786
|
+
let params = {};
|
|
787
|
+
if (!component) {
|
|
788
|
+
for (const [key, comp] of this.components) {
|
|
789
|
+
if (!key.includes("[")) continue;
|
|
790
|
+
const escapedKey = key.replace(/[.*+?^${}()|\\-]/g, "\\$&");
|
|
791
|
+
const regexStr = "^" + escapedKey.replace(/\\\[([^\]]+)\\\]/g, "(?<$1>.+)") + "$";
|
|
792
|
+
const match = interaction.customId.match(new RegExp(regexStr));
|
|
793
|
+
if (match) {
|
|
794
|
+
component = comp;
|
|
795
|
+
if (match.groups) params = match.groups;
|
|
796
|
+
break;
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
if (component) {
|
|
801
|
+
if (!await this.handlePreconditions(component, interaction, interaction.customId)) return;
|
|
802
|
+
try {
|
|
803
|
+
await component.execute(interaction, this, params);
|
|
804
|
+
} catch (error) {
|
|
805
|
+
await this.handleCommandError(error, interaction.customId, interaction);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
}
|
|
809
|
+
});
|
|
810
|
+
this.on("messageCreate", async (message2) => {
|
|
811
|
+
if (message2.author.bot) return;
|
|
812
|
+
if (!this._enableTextCommands) return;
|
|
813
|
+
if (this._middleware) {
|
|
814
|
+
try {
|
|
815
|
+
const shouldContinue = await this._middleware(message2, this);
|
|
816
|
+
if (!shouldContinue) return;
|
|
817
|
+
} catch (error) {
|
|
818
|
+
console.error(`[djs-next] Middleware error (Message):`, error);
|
|
819
|
+
return;
|
|
820
|
+
}
|
|
821
|
+
}
|
|
822
|
+
let content2 = message2.content.trim();
|
|
823
|
+
let matchedPrefix = "";
|
|
824
|
+
let isCommand = false;
|
|
825
|
+
const mentionRegex = new RegExp(`^<@!?${this.user?.id}>\\s*`);
|
|
826
|
+
const canUseMention = this._enableMentionPrefix === true || Array.isArray(this._enableMentionPrefix) && this._enableMentionPrefix.includes(message2.author.id);
|
|
827
|
+
if (canUseMention && mentionRegex.test(content2)) {
|
|
828
|
+
matchedPrefix = content2.match(mentionRegex)[0];
|
|
829
|
+
isCommand = true;
|
|
830
|
+
} else {
|
|
831
|
+
const sortedPrefs = [...this._prefixes].sort((a, b) => b.length - a.length);
|
|
832
|
+
for (const p of sortedPrefs) {
|
|
833
|
+
if (content2.startsWith(p)) {
|
|
834
|
+
matchedPrefix = p;
|
|
835
|
+
isCommand = true;
|
|
836
|
+
break;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
const canUseNoPrefix = this._enableNoPrefix === true || Array.isArray(this._enableNoPrefix) && this._enableNoPrefix.includes(message2.author.id);
|
|
840
|
+
if (!isCommand && canUseNoPrefix) {
|
|
841
|
+
isCommand = true;
|
|
842
|
+
matchedPrefix = "";
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
if (!isCommand) return;
|
|
846
|
+
const args2 = content2.slice(matchedPrefix.length).trim().split(/ +/g);
|
|
847
|
+
const commandName = args2.shift()?.toLowerCase();
|
|
848
|
+
if (!commandName) return;
|
|
849
|
+
let command2 = this.commands.get(commandName);
|
|
850
|
+
if (!command2) {
|
|
851
|
+
command2 = this.commands.find((c) => c.aliases?.includes(commandName) || false);
|
|
852
|
+
}
|
|
853
|
+
if (!command2 || !command2.executeText) return;
|
|
854
|
+
if (!await this.handlePreconditions(command2, message2, commandName)) return;
|
|
855
|
+
try {
|
|
856
|
+
await command2.executeText(message2, args2, this);
|
|
857
|
+
} catch (error) {
|
|
858
|
+
await this.handleCommandError(error, commandName, message2);
|
|
859
|
+
}
|
|
860
|
+
});
|
|
861
|
+
}
|
|
862
|
+
async start(token) {
|
|
863
|
+
if (!token) throw new Error("[djs-next] A token must be provided to start the bot.");
|
|
864
|
+
this.config = await loadConfig();
|
|
865
|
+
this._guildId = this._guildId || this.config.devGuildId;
|
|
866
|
+
if (!this._commandsDir) this._commandsDir = import_path6.default.resolve(process.cwd(), this.config.directories?.commands || "src/commands");
|
|
867
|
+
if (!this._eventsDir) this._eventsDir = import_path6.default.resolve(process.cwd(), this.config.directories?.events || "src/events");
|
|
868
|
+
if (!this._componentsDir) this._componentsDir = import_path6.default.resolve(process.cwd(), this.config.directories?.components || "src/components");
|
|
869
|
+
if (!this._tasksDir) this._tasksDir = import_path6.default.resolve(process.cwd(), this.config.directories?.tasks || "src/tasks");
|
|
870
|
+
if (!this._localesDir) this._localesDir = import_path6.default.resolve(process.cwd(), this.config.directories?.locales || "src/locales");
|
|
871
|
+
if (import_fs8.default.existsSync(this._localesDir)) loadLocales(this._localesDir, this.config.defaultLocale);
|
|
872
|
+
if (!this._middleware) {
|
|
873
|
+
const exts = [".js", ".mjs", ".cjs", ".ts", ".mts", ".cts"];
|
|
874
|
+
const cwd = process.cwd();
|
|
875
|
+
for (const ext of exts) {
|
|
876
|
+
const mwPath = import_path6.default.join(cwd, `middleware${ext}`);
|
|
877
|
+
if (import_fs8.default.existsSync(mwPath)) {
|
|
878
|
+
try {
|
|
879
|
+
const mwModule = await import((0, import_url6.pathToFileURL)(mwPath).href);
|
|
880
|
+
this._middleware = mwModule.default?.middleware || mwModule.middleware || mwModule.default || mwModule;
|
|
881
|
+
if (this._middleware) {
|
|
882
|
+
console.log(`[djs-next] Loaded global middleware.`);
|
|
883
|
+
break;
|
|
884
|
+
}
|
|
885
|
+
} catch (err) {
|
|
886
|
+
console.error(`[djs-next] Error loading middleware file ${mwPath}:`, err);
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
}
|
|
891
|
+
if (import_fs8.default.existsSync(this._eventsDir)) await loadEvents(this, this._eventsDir);
|
|
892
|
+
if (import_fs8.default.existsSync(this._componentsDir)) this.components = await loadComponents(this._componentsDir);
|
|
893
|
+
if (import_fs8.default.existsSync(this._tasksDir)) await loadTasks(this, this._tasksDir);
|
|
894
|
+
await this.login(token);
|
|
895
|
+
console.log(`[djs-next] Bot is ready and logged in as ${this.user?.tag}!`);
|
|
896
|
+
if (import_fs8.default.existsSync(this._commandsDir)) {
|
|
897
|
+
this._clientId = this._clientId || this.user.id;
|
|
898
|
+
this.commands = await loadAndDeployCommands(this._commandsDir, token, this._clientId, this._guildId);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
enableDevTools(prefix = "dnxt") {
|
|
902
|
+
if (prefix !== "dnxt" && prefix !== "nxt") {
|
|
903
|
+
throw new Error(`[djs-next] Developer Tools prefix must be either 'dnxt' or 'nxt'. Received: ${prefix}`);
|
|
904
|
+
}
|
|
905
|
+
this.on("messageCreate", async (message2) => {
|
|
906
|
+
await handleDNXT(message2, this, prefix);
|
|
907
|
+
});
|
|
908
|
+
console.log(`[djs-next] \u{1F6E0}\uFE0F Developer Tools enabled. Use "${prefix}" in chat. Ensure MessageContent intent is enabled!`);
|
|
909
|
+
}
|
|
910
|
+
async enableHMR() {
|
|
911
|
+
try {
|
|
912
|
+
const chokidar = await import("chokidar");
|
|
913
|
+
console.log(`[djs-next] \u{1F504} HMR Enabled. Watching for file changes...`);
|
|
914
|
+
const watcher = chokidar.watch([
|
|
915
|
+
this._commandsDir,
|
|
916
|
+
this._eventsDir,
|
|
917
|
+
this._componentsDir,
|
|
918
|
+
this._localesDir
|
|
919
|
+
].filter(Boolean), { ignoreInitial: true });
|
|
920
|
+
watcher.on("change", async (filePath) => {
|
|
921
|
+
console.log(`[djs-next] \u267B\uFE0F File changed: ${filePath}. Reloading...`);
|
|
922
|
+
this.removeAllListeners();
|
|
923
|
+
this.commands.clear();
|
|
924
|
+
this.components.clear();
|
|
925
|
+
this.attachCoreListeners();
|
|
926
|
+
if (this._eventsDir) await loadEvents(this, this._eventsDir);
|
|
927
|
+
if (this._componentsDir) this.components = await loadComponents(this._componentsDir);
|
|
928
|
+
if (this._commandsDir && this._clientId) {
|
|
929
|
+
this.commands = await loadAndDeployCommands(this._commandsDir, this.token, this._clientId, this._guildId);
|
|
930
|
+
}
|
|
931
|
+
if (this._localesDir) loadLocales(this._localesDir, this.config.defaultLocale);
|
|
932
|
+
console.log(`[djs-next] \u2705 Hot Reload complete.`);
|
|
933
|
+
});
|
|
934
|
+
} catch (e) {
|
|
935
|
+
console.warn(`[djs-next] chokidar not installed. HMR is disabled. Please run "npm install chokidar" to use this feature.`);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
async handleCommandError(error, commandKey, context) {
|
|
939
|
+
console.error(`[djs-next] Error executing command/component: "${commandKey}"`, error);
|
|
940
|
+
const djs = require("discord.js");
|
|
941
|
+
if (this.config.responses?.errorBoundary === null) {
|
|
942
|
+
} else {
|
|
943
|
+
try {
|
|
944
|
+
const errorContent = this.config.responses?.errorBoundary || `### \u26A0\uFE0F Execution Error
|
|
945
|
+
> The framework encountered a fatal error while executing \`${commandKey}\`.`;
|
|
946
|
+
const codeBlock = `\`\`\`js
|
|
947
|
+
${String(error.stack || error.message).substring(0, 1500)}
|
|
948
|
+
\`\`\``;
|
|
949
|
+
if ("commandName" in context || "customId" in context) {
|
|
950
|
+
const container = new djs.ContainerBuilder().setAccentColor(15548997).addTextDisplayComponents(new djs.TextDisplayBuilder().setContent(errorContent)).addSeparatorComponents(new djs.SeparatorBuilder()).addTextDisplayComponents(new djs.TextDisplayBuilder().setContent(codeBlock));
|
|
951
|
+
const payload = { components: [container], flags: 32768, ephemeral: true };
|
|
952
|
+
const i = context;
|
|
953
|
+
if (i.isRepliable()) {
|
|
954
|
+
if (i.replied || i.deferred) await i.followUp(payload);
|
|
955
|
+
else await i.reply(payload);
|
|
956
|
+
}
|
|
957
|
+
} else {
|
|
958
|
+
const embed = new djs.EmbedBuilder().setColor(15548997).setDescription(`${errorContent}
|
|
959
|
+
|
|
960
|
+
${codeBlock}`);
|
|
961
|
+
const m = context;
|
|
962
|
+
await m.reply({ embeds: [embed] });
|
|
963
|
+
}
|
|
964
|
+
} catch (e) {
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
if (this.config.errorLogChannelId) {
|
|
968
|
+
try {
|
|
969
|
+
const channel = await this.channels.fetch(this.config.errorLogChannelId);
|
|
970
|
+
if (channel && channel.isTextBased()) {
|
|
971
|
+
const userId = "user" in context ? context.user.id : context.author.id;
|
|
972
|
+
await channel.send(`\u{1F6A8} **Global Error Boundary Caught Exception**
|
|
973
|
+
**Context:** \`${commandKey}\`
|
|
974
|
+
**User:** <@${userId}>
|
|
975
|
+
\`\`\`js
|
|
976
|
+
${String(error.stack || error.message).substring(0, 1900)}
|
|
977
|
+
\`\`\``);
|
|
978
|
+
}
|
|
979
|
+
} catch (e) {
|
|
980
|
+
console.error(`[djs-next] Failed to send error to log channel:`, e);
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
async handlePreconditions(command2, context, commandKey) {
|
|
985
|
+
const userId = "user" in context ? context.user.id : context.author.id;
|
|
986
|
+
const isGuild = "guild" in context && context.guild !== null;
|
|
987
|
+
const member = context.member;
|
|
988
|
+
const sendErr = async (msg) => {
|
|
989
|
+
if (msg === null) return;
|
|
990
|
+
if ("reply" in context && typeof context.reply === "function") {
|
|
991
|
+
try {
|
|
992
|
+
if ("replied" in context && context.isRepliable() && (context.replied || context.deferred)) {
|
|
993
|
+
await context.followUp({ content: msg, ephemeral: true });
|
|
994
|
+
} else {
|
|
995
|
+
await context.reply({ content: msg, ephemeral: true, allowedMentions: { repliedUser: false } });
|
|
996
|
+
}
|
|
997
|
+
} catch (e) {
|
|
998
|
+
}
|
|
999
|
+
}
|
|
1000
|
+
};
|
|
1001
|
+
if ("developerOnly" in command2 && command2.developerOnly && !this._developers.includes(userId)) {
|
|
1002
|
+
await sendErr(this.config.responses?.developerOnly !== void 0 ? this.config.responses.developerOnly : "Only developers can use this command.");
|
|
1003
|
+
return false;
|
|
1004
|
+
}
|
|
1005
|
+
if ("guildOnly" in command2 && command2.guildOnly && !isGuild) {
|
|
1006
|
+
await sendErr(this.config.responses?.guildOnly !== void 0 ? this.config.responses.guildOnly : "This command can only be used in a server.");
|
|
1007
|
+
return false;
|
|
1008
|
+
}
|
|
1009
|
+
if ("userPermissions" in command2 && command2.userPermissions && member?.permissions) {
|
|
1010
|
+
const missing = member.permissions.missing(command2.userPermissions);
|
|
1011
|
+
if (missing.length > 0) {
|
|
1012
|
+
await sendErr(this.config.responses?.missingPerms !== void 0 ? this.config.responses.missingPerms === null ? null : this.config.responses.missingPerms.replace("{perms}", missing.join(", ")) : `You are missing permissions: \`${missing.join(", ")}\``);
|
|
1013
|
+
return false;
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
if ("botPermissions" in command2 && command2.botPermissions && context.guild?.members.me?.permissions) {
|
|
1017
|
+
const missing = context.guild.members.me.permissions.missing(command2.botPermissions);
|
|
1018
|
+
if (missing.length > 0) {
|
|
1019
|
+
await sendErr(this.config.responses?.missingPerms !== void 0 ? this.config.responses.missingPerms === null ? null : this.config.responses.missingPerms.replace("{perms}", missing.join(", ")) : `I am missing permissions to run this: \`${missing.join(", ")}\``);
|
|
1020
|
+
return false;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
let totalCooldown = "cooldown" in command2 && command2.cooldown ? command2.cooldown * 1e3 : 0;
|
|
1024
|
+
if (command2.preconditions) {
|
|
1025
|
+
for (const pre of command2.preconditions) {
|
|
1026
|
+
const parts = pre.split(":");
|
|
1027
|
+
const type = parts[0].toLowerCase();
|
|
1028
|
+
const val = parts.slice(1).join(":");
|
|
1029
|
+
if (type === "owneronly" || type === "developeronly") {
|
|
1030
|
+
if (!this._developers.includes(userId)) {
|
|
1031
|
+
await sendErr(this.config.responses?.developerOnly !== void 0 ? this.config.responses.developerOnly : "Only developers can use this command.");
|
|
1032
|
+
return false;
|
|
1033
|
+
}
|
|
1034
|
+
} else if (type === "guildonly") {
|
|
1035
|
+
if (!isGuild) {
|
|
1036
|
+
await sendErr(this.config.responses?.guildOnly !== void 0 ? this.config.responses.guildOnly : "This command can only be used in a server.");
|
|
1037
|
+
return false;
|
|
1038
|
+
}
|
|
1039
|
+
} else if (type === "requireperms") {
|
|
1040
|
+
const perms = val.split(",").map((p) => p.trim());
|
|
1041
|
+
if (member?.permissions) {
|
|
1042
|
+
const missing = member.permissions.missing(perms);
|
|
1043
|
+
if (missing.length > 0) {
|
|
1044
|
+
await sendErr(this.config.responses?.missingPerms !== void 0 ? this.config.responses.missingPerms === null ? null : this.config.responses.missingPerms.replace("{perms}", missing.join(", ")) : `You are missing permissions: \`${missing.join(", ")}\``);
|
|
1045
|
+
return false;
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
} else if (type === "cooldown") {
|
|
1049
|
+
const match = val.match(/(\d+)(s|m|h)/);
|
|
1050
|
+
if (match) {
|
|
1051
|
+
let amount = parseInt(match[1]) * 1e3;
|
|
1052
|
+
if (match[2] === "m") amount *= 60;
|
|
1053
|
+
if (match[2] === "h") amount *= 3600;
|
|
1054
|
+
totalCooldown = Math.max(totalCooldown, amount);
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
if (totalCooldown > 0) {
|
|
1060
|
+
const now = Date.now();
|
|
1061
|
+
if (this.config.cooldownAdapter) {
|
|
1062
|
+
const lastUsed = await this.config.cooldownAdapter.get(commandKey, userId);
|
|
1063
|
+
if (lastUsed) {
|
|
1064
|
+
const expirationTime = lastUsed + totalCooldown;
|
|
1065
|
+
if (now < expirationTime) {
|
|
1066
|
+
const timeStr = `<t:${Math.round(expirationTime / 1e3)}:R>`;
|
|
1067
|
+
await sendErr(this.config.responses?.cooldown !== void 0 ? this.config.responses.cooldown === null ? null : this.config.responses.cooldown.replace("{time}", timeStr) : `Please wait, you are on a cooldown. You can use it again ${timeStr}.`);
|
|
1068
|
+
return false;
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
await this.config.cooldownAdapter.set(commandKey, userId, now);
|
|
1072
|
+
} else {
|
|
1073
|
+
if (!this.cooldowns.has(commandKey)) this.cooldowns.set(commandKey, new import_discord4.Collection());
|
|
1074
|
+
const timestamps = this.cooldowns.get(commandKey);
|
|
1075
|
+
if (timestamps.has(userId)) {
|
|
1076
|
+
const expirationTime = timestamps.get(userId) + totalCooldown;
|
|
1077
|
+
if (now < expirationTime) {
|
|
1078
|
+
const timeStr = `<t:${Math.round(expirationTime / 1e3)}:R>`;
|
|
1079
|
+
await sendErr(this.config.responses?.cooldown !== void 0 ? this.config.responses.cooldown === null ? null : this.config.responses.cooldown.replace("{time}", timeStr) : `Please wait, you are on a cooldown. You can use it again ${timeStr}.`);
|
|
1080
|
+
return false;
|
|
1081
|
+
}
|
|
1082
|
+
}
|
|
1083
|
+
timestamps.set(userId, now);
|
|
1084
|
+
setTimeout(() => timestamps.delete(userId), totalCooldown);
|
|
1085
|
+
}
|
|
1086
|
+
}
|
|
1087
|
+
return true;
|
|
1088
|
+
}
|
|
1089
|
+
};
|
|
1090
|
+
|
|
1091
|
+
// src/utils/paginate.ts
|
|
1092
|
+
var import_discord5 = require("discord.js");
|
|
1093
|
+
async function paginate(context, pages, time = 6e4) {
|
|
1094
|
+
const isMessage = "author" in context;
|
|
1095
|
+
if (!isMessage) {
|
|
1096
|
+
if (!context.deferred && !context.replied) {
|
|
1097
|
+
await context.deferReply();
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
if (pages.length === 1) {
|
|
1101
|
+
if (isMessage) {
|
|
1102
|
+
return context.reply({ embeds: [pages[0]], components: [] });
|
|
1103
|
+
} else {
|
|
1104
|
+
return context.editReply({ embeds: [pages[0]], components: [] });
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
let index = 0;
|
|
1108
|
+
const prevButton = new import_discord5.ButtonBuilder().setCustomId("djs_prev").setLabel("Previous").setStyle(import_discord5.ButtonStyle.Primary).setDisabled(true);
|
|
1109
|
+
const nextButton = new import_discord5.ButtonBuilder().setCustomId("djs_next").setLabel("Next").setStyle(import_discord5.ButtonStyle.Primary);
|
|
1110
|
+
const row = new import_discord5.ActionRowBuilder().addComponents(prevButton, nextButton);
|
|
1111
|
+
let message2;
|
|
1112
|
+
if (isMessage) {
|
|
1113
|
+
message2 = await context.reply({
|
|
1114
|
+
embeds: [pages[index]],
|
|
1115
|
+
components: [row]
|
|
1116
|
+
});
|
|
1117
|
+
} else {
|
|
1118
|
+
message2 = await context.editReply({
|
|
1119
|
+
embeds: [pages[index]],
|
|
1120
|
+
components: [row]
|
|
1121
|
+
});
|
|
1122
|
+
}
|
|
1123
|
+
const collector = message2.createMessageComponentCollector({
|
|
1124
|
+
filter: (i) => i.user.id === (isMessage ? context.author.id : context.user.id),
|
|
1125
|
+
time
|
|
1126
|
+
});
|
|
1127
|
+
collector.on("collect", async (i) => {
|
|
1128
|
+
if (i.customId === "djs_prev") {
|
|
1129
|
+
index = index > 0 ? index - 1 : index;
|
|
1130
|
+
} else if (i.customId === "djs_next") {
|
|
1131
|
+
index = index < pages.length - 1 ? index + 1 : index;
|
|
1132
|
+
}
|
|
1133
|
+
prevButton.setDisabled(index === 0);
|
|
1134
|
+
nextButton.setDisabled(index === pages.length - 1);
|
|
1135
|
+
await i.update({
|
|
1136
|
+
embeds: [pages[index]],
|
|
1137
|
+
components: [new import_discord5.ActionRowBuilder().addComponents(prevButton, nextButton)]
|
|
1138
|
+
});
|
|
1139
|
+
});
|
|
1140
|
+
collector.on("end", async () => {
|
|
1141
|
+
prevButton.setDisabled(true);
|
|
1142
|
+
nextButton.setDisabled(true);
|
|
1143
|
+
if (message2.editable) {
|
|
1144
|
+
await message2.edit({
|
|
1145
|
+
components: [new import_discord5.ActionRowBuilder().addComponents(prevButton, nextButton)]
|
|
1146
|
+
}).catch(() => {
|
|
1147
|
+
});
|
|
1148
|
+
}
|
|
1149
|
+
});
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
// src/utils/prompts.ts
|
|
1153
|
+
var import_discord6 = require("discord.js");
|
|
1154
|
+
async function confirmPrompt(context, content2, time = 3e4) {
|
|
1155
|
+
const isMessage = "author" in context;
|
|
1156
|
+
if (!isMessage) {
|
|
1157
|
+
if (!context.deferred && !context.replied) {
|
|
1158
|
+
await context.deferReply();
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
const yesButton = new import_discord6.ButtonBuilder().setCustomId("djs_prompt_yes").setLabel("Yes").setStyle(import_discord6.ButtonStyle.Success);
|
|
1162
|
+
const noButton = new import_discord6.ButtonBuilder().setCustomId("djs_prompt_no").setLabel("No").setStyle(import_discord6.ButtonStyle.Danger);
|
|
1163
|
+
const row = new import_discord6.ActionRowBuilder().addComponents(yesButton, noButton);
|
|
1164
|
+
const payload = { components: [row] };
|
|
1165
|
+
if (typeof content2 === "string") {
|
|
1166
|
+
payload.content = content2;
|
|
1167
|
+
} else {
|
|
1168
|
+
payload.embeds = [content2];
|
|
1169
|
+
}
|
|
1170
|
+
let message2;
|
|
1171
|
+
if (isMessage) {
|
|
1172
|
+
message2 = await context.reply(payload);
|
|
1173
|
+
} else {
|
|
1174
|
+
message2 = await context.editReply(payload);
|
|
1175
|
+
}
|
|
1176
|
+
try {
|
|
1177
|
+
const interaction = await message2.awaitMessageComponent({
|
|
1178
|
+
filter: (i) => i.user.id === (isMessage ? context.author.id : context.user.id),
|
|
1179
|
+
time
|
|
1180
|
+
});
|
|
1181
|
+
if (interaction.customId === "djs_prompt_yes") {
|
|
1182
|
+
await interaction.update({ components: [] });
|
|
1183
|
+
return true;
|
|
1184
|
+
} else {
|
|
1185
|
+
await interaction.update({ components: [] });
|
|
1186
|
+
return false;
|
|
1187
|
+
}
|
|
1188
|
+
} catch (error) {
|
|
1189
|
+
if (message2.editable) {
|
|
1190
|
+
await message2.edit({ components: [] }).catch(() => {
|
|
1191
|
+
});
|
|
1192
|
+
}
|
|
1193
|
+
return null;
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
// src/utils/PaginationBuilder.ts
|
|
1198
|
+
var import_discord7 = require("discord.js");
|
|
1199
|
+
var PaginationBuilder = class {
|
|
1200
|
+
pages = [];
|
|
1201
|
+
timeout = 6e4;
|
|
1202
|
+
constructor(pages) {
|
|
1203
|
+
if (pages) this.pages = pages;
|
|
1204
|
+
}
|
|
1205
|
+
addPage(embed) {
|
|
1206
|
+
this.pages.push(embed);
|
|
1207
|
+
return this;
|
|
1208
|
+
}
|
|
1209
|
+
setPages(pages) {
|
|
1210
|
+
this.pages = pages;
|
|
1211
|
+
return this;
|
|
1212
|
+
}
|
|
1213
|
+
setTimeout(ms) {
|
|
1214
|
+
this.timeout = ms;
|
|
1215
|
+
return this;
|
|
1216
|
+
}
|
|
1217
|
+
async build(target) {
|
|
1218
|
+
if (this.pages.length === 0) throw new Error("[djs-next] PaginationBuilder requires at least one page.");
|
|
1219
|
+
if (this.pages.length === 1) {
|
|
1220
|
+
if (target instanceof import_discord7.CommandInteraction) {
|
|
1221
|
+
if (target.deferred || target.replied) {
|
|
1222
|
+
return await target.editReply({ embeds: [this.pages[0]] });
|
|
1223
|
+
}
|
|
1224
|
+
return await target.reply({ embeds: [this.pages[0]], fetchReply: true });
|
|
1225
|
+
} else {
|
|
1226
|
+
return await target.reply({ embeds: [this.pages[0]] });
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
let currentPage = 0;
|
|
1230
|
+
const row = new import_discord7.ActionRowBuilder().addComponents(
|
|
1231
|
+
new import_discord7.ButtonBuilder().setCustomId("prev").setLabel("\u25C0").setStyle(import_discord7.ButtonStyle.Primary).setDisabled(true),
|
|
1232
|
+
new import_discord7.ButtonBuilder().setCustomId("page").setLabel(`1 / ${this.pages.length}`).setStyle(import_discord7.ButtonStyle.Secondary).setDisabled(true),
|
|
1233
|
+
new import_discord7.ButtonBuilder().setCustomId("next").setLabel("\u25B6").setStyle(import_discord7.ButtonStyle.Primary)
|
|
1234
|
+
);
|
|
1235
|
+
let replyMsg;
|
|
1236
|
+
if (target instanceof import_discord7.CommandInteraction) {
|
|
1237
|
+
if (target.deferred || target.replied) {
|
|
1238
|
+
replyMsg = await target.editReply({ embeds: [this.pages[0]], components: [row] });
|
|
1239
|
+
} else {
|
|
1240
|
+
replyMsg = await target.reply({ embeds: [this.pages[0]], components: [row], fetchReply: true });
|
|
1241
|
+
}
|
|
1242
|
+
} else {
|
|
1243
|
+
replyMsg = await target.reply({ embeds: [this.pages[0]], components: [row] });
|
|
1244
|
+
}
|
|
1245
|
+
const userId = target instanceof import_discord7.CommandInteraction ? target.user.id : target.author.id;
|
|
1246
|
+
const collector = replyMsg.createMessageComponentCollector({
|
|
1247
|
+
componentType: import_discord7.ComponentType.Button,
|
|
1248
|
+
time: this.timeout,
|
|
1249
|
+
filter: (i) => i.user.id === userId
|
|
1250
|
+
});
|
|
1251
|
+
collector.on("collect", async (i) => {
|
|
1252
|
+
if (i.customId === "prev") currentPage--;
|
|
1253
|
+
else if (i.customId === "next") currentPage++;
|
|
1254
|
+
const newRow = new import_discord7.ActionRowBuilder().addComponents(
|
|
1255
|
+
new import_discord7.ButtonBuilder().setCustomId("prev").setLabel("\u25C0").setStyle(import_discord7.ButtonStyle.Primary).setDisabled(currentPage === 0),
|
|
1256
|
+
new import_discord7.ButtonBuilder().setCustomId("page").setLabel(`${currentPage + 1} / ${this.pages.length}`).setStyle(import_discord7.ButtonStyle.Secondary).setDisabled(true),
|
|
1257
|
+
new import_discord7.ButtonBuilder().setCustomId("next").setLabel("\u25B6").setStyle(import_discord7.ButtonStyle.Primary).setDisabled(currentPage === this.pages.length - 1)
|
|
1258
|
+
);
|
|
1259
|
+
await i.update({ embeds: [this.pages[currentPage]], components: [newRow] });
|
|
1260
|
+
});
|
|
1261
|
+
collector.on("end", () => {
|
|
1262
|
+
replyMsg.edit({ components: [] }).catch(() => null);
|
|
1263
|
+
});
|
|
1264
|
+
return replyMsg;
|
|
1265
|
+
}
|
|
1266
|
+
};
|
|
1267
|
+
|
|
1268
|
+
// src/index.ts
|
|
1269
|
+
__reExport(index_exports, require("discord.js"), module.exports);
|
|
1270
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1271
|
+
0 && (module.exports = {
|
|
1272
|
+
DJSNextClient,
|
|
1273
|
+
PaginationBuilder,
|
|
1274
|
+
confirmPrompt,
|
|
1275
|
+
defineConfig,
|
|
1276
|
+
getLocalesCache,
|
|
1277
|
+
loadConfig,
|
|
1278
|
+
loadLocales,
|
|
1279
|
+
paginate,
|
|
1280
|
+
translate,
|
|
1281
|
+
...require("discord.js")
|
|
1282
|
+
});
|
|
1283
|
+
//# sourceMappingURL=index.js.map
|