djs-next 1.0.0-dev.2 → 1.0.0-dev.3
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 +51 -29
- package/bin/create-djs-next.js +78 -0
- package/dist/index.d.mts +46 -4
- package/dist/index.d.ts +46 -4
- package/dist/index.js +578 -290
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +578 -280
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/client.ts +213 -106
- package/src/index.ts +4 -1
- package/src/plugins/dnxt.ts +215 -176
- package/src/templates/cjs.ts +11 -6
- package/src/templates/esm.ts +11 -4
- package/src/templates/ts.ts +11 -5
- package/src/types.ts +21 -1
- package/src/utils/PaginationBuilder.ts +94 -0
- package/src/utils/paginate.ts +32 -13
- package/src/utils/prompts.ts +76 -0
- package/test_payload.js +3 -0
- package/test_reply.js +4 -0
- package/tsup.config.ts +1 -1
- package/dist/cli.d.mts +0 -1
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +0 -344
- package/dist/cli.js.map +0 -1
- package/dist/cli.mjs +0 -321
- package/dist/cli.mjs.map +0 -1
- package/src/cli.ts +0 -203
package/src/plugins/dnxt.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Message, EmbedBuilder } from 'discord.js';
|
|
1
|
+
import { Message, EmbedBuilder, version as djsVersion } from 'discord.js';
|
|
2
2
|
import { exec } from 'child_process';
|
|
3
3
|
import util from 'util';
|
|
4
4
|
import os from 'os';
|
|
@@ -11,30 +11,88 @@ import { loadLocales } from '../utils/i18n.js';
|
|
|
11
11
|
|
|
12
12
|
const execAsync = util.promisify(exec);
|
|
13
13
|
|
|
14
|
-
export
|
|
14
|
+
export function buildDisplayMessage(content: string, color = 0x525AF1) {
|
|
15
|
+
const djs = require('discord.js');
|
|
16
|
+
const container = new djs.ContainerBuilder()
|
|
17
|
+
.setAccentColor(color)
|
|
18
|
+
.addTextDisplayComponents(
|
|
19
|
+
new djs.TextDisplayBuilder().setContent(content)
|
|
20
|
+
);
|
|
21
|
+
return { components: [container], flags: 32768 };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function handleDNXT(message: Message, client: Client, devPrefix: 'dnxt' | 'nxt'): Promise<void> {
|
|
15
25
|
if (message.author.bot) return;
|
|
16
|
-
|
|
17
|
-
if (
|
|
26
|
+
if (!(client as any)._developers.includes(message.author.id)) return;
|
|
27
|
+
if ((client as any).config?.devGuildId && message.guildId !== (client as any).config.devGuildId) return;
|
|
28
|
+
|
|
29
|
+
const originalReply = message.reply.bind(message);
|
|
30
|
+
message.reply = (async (content: any) => {
|
|
31
|
+
if (typeof content === 'string') {
|
|
32
|
+
return await originalReply({ ...buildDisplayMessage(content), allowedMentions: { repliedUser: false } });
|
|
33
|
+
}
|
|
34
|
+
if (!content.allowedMentions) content.allowedMentions = { repliedUser: false };
|
|
35
|
+
return await originalReply(content);
|
|
36
|
+
}) as any;
|
|
37
|
+
|
|
38
|
+
const content = message.content.trim();
|
|
39
|
+
|
|
40
|
+
// Build a list of valid dev command triggers: e.g. "dnxt", "!dnxt", "?dnxt", "nxt", "!nxt", etc.
|
|
41
|
+
const validTriggers = [devPrefix];
|
|
42
|
+
const clientPrefixes = (client as any)._prefixes || [];
|
|
43
|
+
for (const p of clientPrefixes) {
|
|
44
|
+
if (p !== '') validTriggers.push(`${p}${devPrefix}`);
|
|
45
|
+
}
|
|
18
46
|
|
|
19
|
-
|
|
47
|
+
let matchedTrigger = validTriggers.find(t => content === t || content.startsWith(`${t} `));
|
|
48
|
+
if (!matchedTrigger) return;
|
|
20
49
|
|
|
21
|
-
const args =
|
|
50
|
+
const args = content.slice(matchedTrigger.length).trim().split(/ +/g);
|
|
22
51
|
const command = args.shift()?.toLowerCase();
|
|
23
52
|
|
|
53
|
+
if (command === 'help') {
|
|
54
|
+
const djs = require('discord.js');
|
|
55
|
+
|
|
56
|
+
const container = new djs.ContainerBuilder()
|
|
57
|
+
.setAccentColor(0x525AF1)
|
|
58
|
+
.addTextDisplayComponents(
|
|
59
|
+
new djs.TextDisplayBuilder().setContent(`# 📖 DNXT Toolkit Reference\n> Current prefix trigger: \`${matchedTrigger}\``)
|
|
60
|
+
)
|
|
61
|
+
.addSeparatorComponents(new djs.SeparatorBuilder())
|
|
62
|
+
.addTextDisplayComponents(
|
|
63
|
+
new djs.TextDisplayBuilder().setContent(`### 📊 Core Framework\n- \`${matchedTrigger}\` — Developer system dashboard\n- \`${matchedTrigger} help\` — Shows this reference menu`),
|
|
64
|
+
new djs.TextDisplayBuilder().setContent(`### 💻 Execution & Diagnostics\n- \`${matchedTrigger} js <code>\` — Evaluates raw JS code\n- \`${matchedTrigger} sh <cmd>\` — Runs terminal shell script\n- \`${matchedTrigger} debug <code>\` — Evaluates JS with precise memory deltas`),
|
|
65
|
+
new djs.TextDisplayBuilder().setContent(`### 📂 File System & Network\n- \`${matchedTrigger} cat <file>\` — Reads file contents\n- \`${matchedTrigger} curl <url>\` — Fetches remote URL data\n- \`${matchedTrigger} git <cmd>\` — Executes git repository commands`),
|
|
66
|
+
new djs.TextDisplayBuilder().setContent(`### 🧰 Utilities\n- \`${matchedTrigger} <load|unload|reload> <target>\` — Manages system modules\n- \`${matchedTrigger} sync\` — Forces global slash command sync\n- \`${matchedTrigger} in <channel> <cmd>\` — Executes command in target channel\n- \`${matchedTrigger} restart\` — Restarts the bot completely\n- \`${matchedTrigger} shutdown\` — Stops the bot completely`)
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
await message.reply({ components: [container], flags: 32768, allowedMentions: { repliedUser: false } });
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
24
73
|
// Root dnxt command (Stats)
|
|
25
74
|
if (!command) {
|
|
26
75
|
const mem = process.memoryUsage();
|
|
27
|
-
const discordJsVersion = require('discord.js/package.json').version;
|
|
28
76
|
const botPing = client.ws.ping;
|
|
77
|
+
const djs = require('discord.js');
|
|
29
78
|
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
79
|
+
const container = new djs.ContainerBuilder()
|
|
80
|
+
.setAccentColor(0x525AF1)
|
|
81
|
+
.addTextDisplayComponents(
|
|
82
|
+
new djs.TextDisplayBuilder().setContent(`# 🛠️ Developer System Dashboard\n> **DNXT Framework Engine**`)
|
|
83
|
+
)
|
|
84
|
+
.addSeparatorComponents(new djs.SeparatorBuilder())
|
|
85
|
+
.addTextDisplayComponents(
|
|
86
|
+
new djs.TextDisplayBuilder().setContent(`### 📡 Network Status\n- **System Uptime:** <t:${Math.floor((Date.now() - client.uptime!) / 1000)}:R>\n- **WebSocket Latency:** \`${botPing}ms\``),
|
|
87
|
+
new djs.TextDisplayBuilder().setContent(`### 📦 Host Environment\n- **Discord.js Library:** \`v${djsVersion}\`\n- **Node.js Runtime:** \`${process.version}\`\n- **Operating System:** \`${os.type()}\` (\`${os.cpus().length}\` thread cores, \`${(os.uptime() / 60 / 60).toFixed(2)}\` hrs uptime)`),
|
|
88
|
+
new djs.TextDisplayBuilder().setContent(`### 🧠 Resource Utilization\n- **Physical Memory:** \`${(mem.rss / 1024 / 1024).toFixed(2)} MB\`\n- **Heap Allocated:** \`${(mem.heapUsed / 1024 / 1024).toFixed(2)} MB\``)
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
await message.reply({
|
|
92
|
+
components: [container],
|
|
93
|
+
flags: 32768, // MessageFlags.IsComponentsV2
|
|
94
|
+
allowedMentions: { repliedUser: false }
|
|
95
|
+
});
|
|
38
96
|
return;
|
|
39
97
|
}
|
|
40
98
|
|
|
@@ -55,11 +113,11 @@ export async function handleDNXT(message: Message, client: DJSNextClient, prefix
|
|
|
55
113
|
const end = process.hrtime.bigint();
|
|
56
114
|
const timeMs = Number(end - start) / 1e6;
|
|
57
115
|
|
|
58
|
-
if (typeof evaled !== 'string') evaled = util.inspect(evaled, { depth: 1 });
|
|
116
|
+
if (typeof evaled !== 'string') evaled = util.inspect(evaled, { depth: 1, colors: true });
|
|
59
117
|
|
|
60
|
-
await sendPaginatedText(message, `✅ **Evaluated in ${timeMs.toFixed(3)}ms**\n`, evaled, '
|
|
118
|
+
await sendPaginatedText(message, `✅ **Evaluated in ${timeMs.toFixed(3)}ms**\n`, evaled, 'ansi');
|
|
61
119
|
} catch (err: any) {
|
|
62
|
-
await sendPaginatedText(message, `❌ **Evaluation Error**\n`, err.message, '
|
|
120
|
+
await sendPaginatedText(message, `❌ **Evaluation Error**\n`, err.message, 'ansi');
|
|
63
121
|
}
|
|
64
122
|
return;
|
|
65
123
|
}
|
|
@@ -71,53 +129,72 @@ export async function handleDNXT(message: Message, client: DJSNextClient, prefix
|
|
|
71
129
|
|
|
72
130
|
try {
|
|
73
131
|
const start = process.hrtime.bigint();
|
|
74
|
-
|
|
132
|
+
let stdout = '', stderr = '', code = 0;
|
|
133
|
+
try {
|
|
134
|
+
const result = await execAsync(cmd);
|
|
135
|
+
stdout = result.stdout;
|
|
136
|
+
stderr = result.stderr;
|
|
137
|
+
} catch (err: any) {
|
|
138
|
+
stdout = err.stdout || '';
|
|
139
|
+
stderr = err.stderr || err.message || '';
|
|
140
|
+
code = err.code || 1;
|
|
141
|
+
}
|
|
75
142
|
const end = process.hrtime.bigint();
|
|
76
143
|
const timeMs = Number(end - start) / 1e6;
|
|
77
144
|
|
|
78
|
-
|
|
79
|
-
|
|
145
|
+
let resultText = `$ ${cmd}\n`;
|
|
146
|
+
if (stdout) resultText += `${stdout}\n`;
|
|
147
|
+
if (stderr) resultText += `${stderr}\n`;
|
|
148
|
+
resultText += `\n[status] Return code ${code}`;
|
|
149
|
+
|
|
150
|
+
await sendPaginatedText(message, `✅ **Executed in ${timeMs.toFixed(3)}ms**\n`, resultText, 'ansi');
|
|
80
151
|
} catch (err: any) {
|
|
81
|
-
await sendPaginatedText(message, `❌ **Shell Error**\n`, err.message, '
|
|
152
|
+
await sendPaginatedText(message, `❌ **Shell Error**\n`, err.message, 'ansi');
|
|
82
153
|
}
|
|
83
154
|
return;
|
|
84
155
|
}
|
|
85
156
|
|
|
86
157
|
// Load / Unload / Reload
|
|
87
|
-
if (command === '
|
|
158
|
+
if (command === 'load' || command === 'unload' || command === 'reload') {
|
|
88
159
|
const target = args[0]?.toLowerCase();
|
|
89
160
|
try {
|
|
90
161
|
if (target === 'commands' && client['_commandsDir']) {
|
|
91
|
-
client.commands.clear();
|
|
92
|
-
client.commands = await loadAndDeployCommands(client['_commandsDir'], client.token!, client['_clientId']!, client['_guildId']);
|
|
93
|
-
await message.reply(
|
|
162
|
+
if (command === 'unload' || command === 'reload') client.commands.clear();
|
|
163
|
+
if (command === 'load' || command === 'reload') client.commands = await loadAndDeployCommands(client['_commandsDir'], client.token!, client['_clientId']!, client['_guildId']);
|
|
164
|
+
await message.reply(`✅ Successfully ${command}ed commands.`);
|
|
94
165
|
} else if (target === 'events' && client['_eventsDir']) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
166
|
+
if (command === 'unload' || command === 'reload') {
|
|
167
|
+
client.removeAllListeners();
|
|
168
|
+
client['attachCoreListeners']();
|
|
169
|
+
}
|
|
170
|
+
if (command === 'load' || command === 'reload') await loadEvents(client, client['_eventsDir']);
|
|
171
|
+
await message.reply(`✅ Successfully ${command}ed events.`);
|
|
99
172
|
} else if (target === 'components' && client['_componentsDir']) {
|
|
100
|
-
client.components.clear();
|
|
101
|
-
client.components = await loadComponents(client['_componentsDir']);
|
|
102
|
-
await message.reply(
|
|
173
|
+
if (command === 'unload' || command === 'reload') client.components.clear();
|
|
174
|
+
if (command === 'load' || command === 'reload') client.components = await loadComponents(client['_componentsDir']);
|
|
175
|
+
await message.reply(`✅ Successfully ${command}ed components.`);
|
|
103
176
|
} else if (target === 'locales' && client['_localesDir']) {
|
|
104
|
-
loadLocales(client['_localesDir'], client.config.defaultLocale);
|
|
105
|
-
await message.reply(
|
|
177
|
+
if (command === 'load' || command === 'reload') loadLocales(client['_localesDir'], client.config.defaultLocale);
|
|
178
|
+
await message.reply(`✅ Successfully ${command}ed locales.`);
|
|
106
179
|
} else if (target === 'all' || !target) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if (
|
|
114
|
-
|
|
115
|
-
|
|
180
|
+
if (command === 'unload' || command === 'reload') {
|
|
181
|
+
client.removeAllListeners();
|
|
182
|
+
client['attachCoreListeners']();
|
|
183
|
+
client.commands.clear();
|
|
184
|
+
client.components.clear();
|
|
185
|
+
}
|
|
186
|
+
if (command === 'load' || command === 'reload') {
|
|
187
|
+
if (client['_eventsDir']) await loadEvents(client, client['_eventsDir']);
|
|
188
|
+
if (client['_componentsDir']) client.components = await loadComponents(client['_componentsDir']);
|
|
189
|
+
if (client['_localesDir']) loadLocales(client['_localesDir'], client.config.defaultLocale);
|
|
190
|
+
if (client['_commandsDir']) client.commands = await loadAndDeployCommands(client['_commandsDir'], client.token!, client['_clientId']!, client['_guildId']);
|
|
191
|
+
}
|
|
192
|
+
await message.reply(`✅ Successfully ${command}ed all framework modules.`);
|
|
116
193
|
} else {
|
|
117
194
|
await message.reply('❌ Unknown target. Valid targets: `commands, events, components, locales, all`');
|
|
118
195
|
}
|
|
119
196
|
} catch (err: any) {
|
|
120
|
-
await message.reply(`❌
|
|
197
|
+
await message.reply(`❌ **${command.toUpperCase()} Error:** ${err.message}`);
|
|
121
198
|
}
|
|
122
199
|
return;
|
|
123
200
|
}
|
|
@@ -138,48 +215,9 @@ export async function handleDNXT(message: Message, client: DJSNextClient, prefix
|
|
|
138
215
|
return;
|
|
139
216
|
}
|
|
140
217
|
|
|
141
|
-
// Sudo (Invoke command as another user)
|
|
142
|
-
if (command === 'su' || command === 'sudo') {
|
|
143
|
-
const targetUserId = args.shift();
|
|
144
|
-
const cmd = args.join(' ');
|
|
145
|
-
if (!targetUserId || !cmd) return void await message.reply(`❌ Usage: ${prefix} su <user_id> <command>`);
|
|
146
|
-
|
|
147
|
-
try {
|
|
148
|
-
const targetUser = await client.users.fetch(targetUserId.replace(/<@!?|>/g, ''));
|
|
149
|
-
if (!targetUser) throw new Error('User not found.');
|
|
150
|
-
|
|
151
|
-
// Create a mock message
|
|
152
|
-
const mockMessage = Object.assign(Object.create(Object.getPrototypeOf(message)), message);
|
|
153
|
-
mockMessage.author = targetUser;
|
|
154
|
-
if (message.guild) {
|
|
155
|
-
mockMessage.member = await message.guild.members.fetch(targetUser.id).catch(() => null);
|
|
156
|
-
}
|
|
157
|
-
mockMessage.content = cmd;
|
|
158
|
-
|
|
159
|
-
client.emit('messageCreate', mockMessage as Message);
|
|
160
|
-
await message.reply(`✅ Invoked \`${cmd}\` as **${targetUser.tag}**.`);
|
|
161
|
-
} catch (e: any) {
|
|
162
|
-
await message.reply(`❌ **Sudo Error:** ${e.message}`);
|
|
163
|
-
}
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
218
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const target = args.join(' ');
|
|
170
|
-
if (!target) return void await message.reply('❌ Please provide a command name.');
|
|
171
|
-
const cmdData = client.commands.get(target);
|
|
172
|
-
if (!cmdData || !cmdData.filepath) return void await message.reply('❌ Command not found or has no associated filepath.');
|
|
173
|
-
|
|
174
|
-
try {
|
|
175
|
-
const fs = await import('fs');
|
|
176
|
-
const content = fs.readFileSync(cmdData.filepath, 'utf8');
|
|
177
|
-
await sendPaginatedText(message, `📄 **Source of \`${target}\`**\n`, content, cmdData.filepath.split('.').pop() || '');
|
|
178
|
-
} catch (e: any) {
|
|
179
|
-
await message.reply(`❌ **Error reading source:** ${e.message}`);
|
|
180
|
-
}
|
|
181
|
-
return;
|
|
182
|
-
}
|
|
219
|
+
|
|
220
|
+
|
|
183
221
|
|
|
184
222
|
// Curl (dnxt curl <url>)
|
|
185
223
|
if (command === 'curl') {
|
|
@@ -217,11 +255,11 @@ export async function handleDNXT(message: Message, client: DJSNextClient, prefix
|
|
|
217
255
|
const timeMs = Number(end - start) / 1e6;
|
|
218
256
|
const memDiff = (endMem - startMem) / 1024 / 1024;
|
|
219
257
|
|
|
220
|
-
if (typeof evaled !== 'string') evaled = util.inspect(evaled, { depth: 1 });
|
|
258
|
+
if (typeof evaled !== 'string') evaled = util.inspect(evaled, { depth: 1, colors: true });
|
|
221
259
|
|
|
222
|
-
await sendPaginatedText(message, `⏱️ **Debug Execution**\nTime: \`${timeMs.toFixed(3)}ms\` | Heap Delta: \`${memDiff.toFixed(3)}MB\`\n`, evaled, '
|
|
260
|
+
await sendPaginatedText(message, `⏱️ **Debug Execution**\nTime: \`${timeMs.toFixed(3)}ms\` | Heap Delta: \`${memDiff.toFixed(3)}MB\`\n`, evaled, 'ansi');
|
|
223
261
|
} catch (err: any) {
|
|
224
|
-
await sendPaginatedText(message, `❌ **Debug Error**\n`, err.message, '
|
|
262
|
+
await sendPaginatedText(message, `❌ **Debug Error**\n`, err.message, 'ansi');
|
|
225
263
|
}
|
|
226
264
|
return;
|
|
227
265
|
}
|
|
@@ -230,59 +268,27 @@ export async function handleDNXT(message: Message, client: DJSNextClient, prefix
|
|
|
230
268
|
if (command === 'in') {
|
|
231
269
|
const channelId = args.shift()?.replace(/<#|>/g, '');
|
|
232
270
|
const cmd = args.join(' ');
|
|
233
|
-
if (!channelId || !cmd) return void await message.reply(`❌ Usage: ${
|
|
271
|
+
if (!channelId || !cmd) return void await message.reply(`❌ Usage: ${matchedTrigger} in <#channel|id> <command>`);
|
|
234
272
|
try {
|
|
235
273
|
const targetChannel = await client.channels.fetch(channelId);
|
|
236
274
|
if (!targetChannel || !targetChannel.isTextBased()) throw new Error('Invalid Text Channel.');
|
|
237
275
|
|
|
238
276
|
const mockMessage = Object.assign(Object.create(Object.getPrototypeOf(message)), message);
|
|
239
|
-
mockMessage
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
277
|
+
Object.defineProperty(mockMessage, 'client', { value: client, configurable: true });
|
|
278
|
+
if (message.guild) {
|
|
279
|
+
Object.defineProperty(mockMessage, 'guild', { value: message.guild, configurable: true });
|
|
280
|
+
Object.defineProperty(mockMessage, 'guildId', { value: message.guildId, configurable: true });
|
|
281
|
+
}
|
|
282
|
+
Object.defineProperty(mockMessage, 'channel', { value: targetChannel, configurable: true });
|
|
283
|
+
Object.defineProperty(mockMessage, 'channelId', { value: targetChannel.id, configurable: true });
|
|
284
|
+
Object.defineProperty(mockMessage, 'content', { value: cmd, configurable: true });
|
|
243
285
|
client.emit('messageCreate', mockMessage as Message);
|
|
244
|
-
await message.reply(`✅ Redirected execution to <#${targetChannel.id}>.`);
|
|
245
286
|
} catch (e: any) {
|
|
246
287
|
await message.reply(`❌ **In Error:** ${e.message}`);
|
|
247
288
|
}
|
|
248
289
|
return;
|
|
249
290
|
}
|
|
250
291
|
|
|
251
|
-
// Tasks Command (dnxt tasks)
|
|
252
|
-
if (command === 'tasks') {
|
|
253
|
-
const tasks = (client as any)._activeTasks as Map<string, NodeJS.Timeout>;
|
|
254
|
-
if (!tasks || tasks.size === 0) return void await message.reply('No active background tasks running.');
|
|
255
|
-
|
|
256
|
-
let text = `⚙️ **Active Background Tasks (${tasks.size})**\n`;
|
|
257
|
-
for (const [name] of tasks.entries()) {
|
|
258
|
-
text += `- \`${name.split('/').pop()}\`\n`;
|
|
259
|
-
}
|
|
260
|
-
await sendPaginatedText(message, '', text, '');
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
// Cancel Command (dnxt cancel <task>)
|
|
265
|
-
if (command === 'cancel') {
|
|
266
|
-
const target = args.join(' ');
|
|
267
|
-
if (!target) return void await message.reply(`❌ Usage: ${prefix} cancel <task_name>`);
|
|
268
|
-
|
|
269
|
-
const tasks = (client as any)._activeTasks as Map<string, NodeJS.Timeout>;
|
|
270
|
-
if (!tasks) return void await message.reply('No active tasks to cancel.');
|
|
271
|
-
|
|
272
|
-
let found = false;
|
|
273
|
-
for (const [name, intervalId] of tasks.entries()) {
|
|
274
|
-
if (name.includes(target)) {
|
|
275
|
-
clearInterval(intervalId);
|
|
276
|
-
tasks.delete(name);
|
|
277
|
-
found = true;
|
|
278
|
-
await message.reply(`✅ Cancelled background task: \`${name.split('/').pop()}\``);
|
|
279
|
-
break;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
if (!found) await message.reply('❌ Task not found.');
|
|
283
|
-
return;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
292
|
// Sync Command (dnxt sync)
|
|
287
293
|
if (command === 'sync') {
|
|
288
294
|
try {
|
|
@@ -295,49 +301,37 @@ export async function handleDNXT(message: Message, client: DJSNextClient, prefix
|
|
|
295
301
|
return;
|
|
296
302
|
}
|
|
297
303
|
|
|
298
|
-
//
|
|
299
|
-
if (command === '
|
|
300
|
-
|
|
301
|
-
|
|
304
|
+
// Restart Command (dnxt restart)
|
|
305
|
+
if (command === 'restart') {
|
|
306
|
+
await message.reply('🔄 Restarting framework...');
|
|
307
|
+
client.destroy();
|
|
302
308
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
}
|
|
312
|
-
const inspect = util.inspect(res, { depth: 2 });
|
|
313
|
-
await sendPaginatedText(message, `🗄️ **SQL Query**\n`, inspect, 'js');
|
|
314
|
-
} catch (e: any) {
|
|
315
|
-
await message.reply(`❌ **SQL Error:** ${e.message}`);
|
|
316
|
-
}
|
|
309
|
+
const { spawn } = require('child_process');
|
|
310
|
+
const child = spawn(process.argv[0], process.argv.slice(1), {
|
|
311
|
+
detached: true,
|
|
312
|
+
stdio: 'ignore',
|
|
313
|
+
cwd: process.cwd()
|
|
314
|
+
});
|
|
315
|
+
child.unref();
|
|
316
|
+
process.exit(0);
|
|
317
317
|
return;
|
|
318
318
|
}
|
|
319
319
|
|
|
320
|
-
//
|
|
321
|
-
if (command === '
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
const text = `🎙️ **Voice Debugger**\n` +
|
|
327
|
-
`Channel: <#${me.voice.channel.id}> (\`${me.voice.channel.id}\`)\n` +
|
|
328
|
-
`Muted: ${me.voice.mute} | Deafened: ${me.voice.deaf}\n` +
|
|
329
|
-
`Session ID: \`${me.voice.sessionId || 'None'}\``;
|
|
330
|
-
await message.reply(text);
|
|
320
|
+
// Shutdown Command (dnxt shutdown | stop)
|
|
321
|
+
if (command === 'shutdown' || command === 'stop') {
|
|
322
|
+
await message.reply('🛑 Shutting down framework...');
|
|
323
|
+
client.destroy();
|
|
324
|
+
process.exit(0);
|
|
331
325
|
return;
|
|
332
326
|
}
|
|
333
327
|
|
|
334
|
-
await message.reply(`❓ Unknown ${
|
|
328
|
+
await message.reply(`❓ Unknown ${matchedTrigger} command. Available: \`js, sh, git, cat, curl, in, debug, reload, sync, restart, shutdown\``);
|
|
335
329
|
}
|
|
336
330
|
|
|
337
331
|
async function sendPaginatedText(message: Message, header: string, content: string, language: string = '') {
|
|
338
|
-
const maxLength =
|
|
332
|
+
const maxLength = 800;
|
|
339
333
|
if (content.length <= maxLength) {
|
|
340
|
-
await message.reply(
|
|
334
|
+
await message.reply(buildDisplayMessage(`### ${header.replace(/\\*\\*/g, '')}\n\`\`\`${language}\n${content}\n\`\`\``));
|
|
341
335
|
return;
|
|
342
336
|
}
|
|
343
337
|
|
|
@@ -347,33 +341,78 @@ async function sendPaginatedText(message: Message, header: string, content: stri
|
|
|
347
341
|
}
|
|
348
342
|
|
|
349
343
|
let index = 0;
|
|
350
|
-
const
|
|
344
|
+
const djs = require('discord.js');
|
|
345
|
+
|
|
346
|
+
function buildPage(idx: number) {
|
|
347
|
+
const text = `### ${header.replace(/\\*\\*/g, '')}\n\`\`\`${language}\n${chunks[idx]}\n\`\`\`\n> *Page ${idx + 1} of ${chunks.length}*`;
|
|
348
|
+
const container = new djs.ContainerBuilder()
|
|
349
|
+
.setAccentColor(0x525AF1)
|
|
350
|
+
.addTextDisplayComponents(
|
|
351
|
+
new djs.TextDisplayBuilder().setContent(text)
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
const row1 = new djs.ActionRowBuilder().addComponents(
|
|
355
|
+
new djs.ButtonBuilder().setCustomId('first').setLabel('≪').setStyle(2),
|
|
356
|
+
new djs.ButtonBuilder().setCustomId('prev').setLabel('<').setStyle(2),
|
|
357
|
+
new djs.ButtonBuilder().setCustomId('goto').setLabel('⎘').setStyle(1),
|
|
358
|
+
new djs.ButtonBuilder().setCustomId('next').setLabel('>').setStyle(2),
|
|
359
|
+
new djs.ButtonBuilder().setCustomId('last').setLabel('≫').setStyle(2)
|
|
360
|
+
);
|
|
361
|
+
|
|
362
|
+
const row2 = new djs.ActionRowBuilder().addComponents(
|
|
363
|
+
new djs.ButtonBuilder().setCustomId('stop').setLabel('✖ Close').setStyle(4)
|
|
364
|
+
);
|
|
365
|
+
|
|
366
|
+
container.addActionRowComponents(row1, row2);
|
|
367
|
+
return { components: [container], flags: 32768 };
|
|
368
|
+
}
|
|
351
369
|
|
|
352
|
-
await reply
|
|
353
|
-
await reply.react('▶️');
|
|
354
|
-
await reply.react('⏹️');
|
|
370
|
+
const reply = await message.reply(buildPage(index));
|
|
355
371
|
|
|
356
|
-
const collector = reply.
|
|
357
|
-
filter: (
|
|
372
|
+
const collector = reply.createMessageComponentCollector({
|
|
373
|
+
filter: (i) => ['first', 'prev', 'goto', 'stop', 'next', 'last'].includes(i.customId) && i.user.id === message.author.id,
|
|
358
374
|
time: 120000
|
|
359
375
|
});
|
|
360
376
|
|
|
361
|
-
collector.on('collect', async (
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
if (
|
|
377
|
+
collector.on('collect', async (i) => {
|
|
378
|
+
if (i.customId === 'first') {
|
|
379
|
+
index = 0;
|
|
380
|
+
} else if (i.customId === 'prev') {
|
|
365
381
|
index = index > 0 ? index - 1 : index;
|
|
366
|
-
} else if (
|
|
382
|
+
} else if (i.customId === 'next') {
|
|
367
383
|
index = index < chunks.length - 1 ? index + 1 : index;
|
|
368
|
-
} else if (
|
|
384
|
+
} else if (i.customId === 'last') {
|
|
385
|
+
index = chunks.length - 1;
|
|
386
|
+
} else if (i.customId === 'goto') {
|
|
387
|
+
const modal = new djs.ModalBuilder()
|
|
388
|
+
.setCustomId('goto_modal')
|
|
389
|
+
.setTitle('Go to Page');
|
|
390
|
+
const input = new djs.TextInputBuilder()
|
|
391
|
+
.setCustomId('page_num')
|
|
392
|
+
.setLabel(`Page Number (1-${chunks.length})`)
|
|
393
|
+
.setStyle(1)
|
|
394
|
+
.setRequired(true);
|
|
395
|
+
modal.addComponents(new djs.ActionRowBuilder().addComponents(input));
|
|
396
|
+
await i.showModal(modal);
|
|
397
|
+
try {
|
|
398
|
+
const modalSubmit = await i.awaitModalSubmit({ filter: (mi) => mi.user.id === message.author.id && mi.customId === 'goto_modal', time: 60000 });
|
|
399
|
+
const targetPage = parseInt(modalSubmit.fields.getTextInputValue('page_num'), 10);
|
|
400
|
+
if (!isNaN(targetPage) && targetPage >= 1 && targetPage <= chunks.length) {
|
|
401
|
+
index = targetPage - 1;
|
|
402
|
+
}
|
|
403
|
+
await modalSubmit.update(buildPage(index));
|
|
404
|
+
} catch {}
|
|
405
|
+
return;
|
|
406
|
+
} else if (i.customId === 'stop') {
|
|
407
|
+
await reply.delete().catch(() => null);
|
|
369
408
|
collector.stop();
|
|
370
409
|
return;
|
|
371
410
|
}
|
|
372
411
|
|
|
373
|
-
await
|
|
412
|
+
await i.update(buildPage(index));
|
|
374
413
|
});
|
|
375
414
|
|
|
376
415
|
collector.on('end', () => {
|
|
377
|
-
reply.
|
|
416
|
+
reply.edit({ components: [] }).catch(() => null);
|
|
378
417
|
});
|
|
379
418
|
}
|
package/src/templates/cjs.ts
CHANGED
|
@@ -14,12 +14,17 @@ const client = new DJSNextClient({
|
|
|
14
14
|
client.start(process.env.DISCORD_TOKEN);
|
|
15
15
|
`,
|
|
16
16
|
|
|
17
|
-
ping:
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
ping: `/** @type {import('djs-next').FileCommand} */
|
|
18
|
+
module.exports = {
|
|
19
|
+
description: 'Replies with the actual bot latency!',
|
|
20
|
+
execute: async (interaction, client) => {
|
|
21
|
+
const sent = await interaction.reply({ content: 'Pinging...', withResponse: true });
|
|
22
|
+
const msg = sent.resource?.message || await interaction.fetchReply();
|
|
23
|
+
await interaction.editReply(\`Pong! 🏓\\nWebsocket Latency: \\\`\${client.ws.ping}ms\\\`\\nAPI Latency: \\\`\${msg.createdTimestamp - interaction.createdTimestamp}ms\\\`\`);
|
|
24
|
+
},
|
|
25
|
+
executeText: async (message, args, client) => {
|
|
26
|
+
const sent = await message.reply('Pinging...');
|
|
27
|
+
await sent.edit(\`Pong! 🏓\\nWebsocket Latency: \\\`\${client.ws.ping}ms\\\`\\nAPI Latency: \\\`\${sent.createdTimestamp - message.createdTimestamp}ms\\\`\`);
|
|
23
28
|
}
|
|
24
29
|
};
|
|
25
30
|
`,
|
package/src/templates/esm.ts
CHANGED
|
@@ -14,10 +14,17 @@ const client = new DJSNextClient({
|
|
|
14
14
|
client.start(process.env.DISCORD_TOKEN);
|
|
15
15
|
`,
|
|
16
16
|
|
|
17
|
-
ping:
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
ping: `/** @type {import('djs-next').FileCommand} */
|
|
18
|
+
export default {
|
|
19
|
+
description: 'Replies with the actual bot latency!',
|
|
20
|
+
execute: async (interaction, client) => {
|
|
21
|
+
const sent = await interaction.reply({ content: 'Pinging...', withResponse: true });
|
|
22
|
+
const msg = sent.resource?.message || await interaction.fetchReply();
|
|
23
|
+
await interaction.editReply(\`Pong! 🏓\\nWebsocket Latency: \\\`\${client.ws.ping}ms\\\`\\nAPI Latency: \\\`\${msg.createdTimestamp - interaction.createdTimestamp}ms\\\`\`);
|
|
24
|
+
},
|
|
25
|
+
executeText: async (message, args, client) => {
|
|
26
|
+
const sent = await message.reply('Pinging...');
|
|
27
|
+
await sent.edit(\`Pong! 🏓\\nWebsocket Latency: \\\`\${client.ws.ping}ms\\\`\\nAPI Latency: \\\`\${sent.createdTimestamp - message.createdTimestamp}ms\\\`\`);
|
|
21
28
|
}
|
|
22
29
|
};
|
|
23
30
|
`,
|
package/src/templates/ts.ts
CHANGED
|
@@ -16,12 +16,18 @@ client.start(process.env.DISCORD_TOKEN!);
|
|
|
16
16
|
|
|
17
17
|
ping: `import { FileCommand } from 'djs-next';
|
|
18
18
|
|
|
19
|
-
export
|
|
20
|
-
description: 'Replies with
|
|
21
|
-
execute: async (interaction) => {
|
|
22
|
-
await interaction.reply('
|
|
19
|
+
export default {
|
|
20
|
+
description: 'Replies with the actual bot latency!',
|
|
21
|
+
execute: async (interaction, client) => {
|
|
22
|
+
const sent = await interaction.reply({ content: 'Pinging...', withResponse: true });
|
|
23
|
+
const msg = sent.resource?.message || await interaction.fetchReply();
|
|
24
|
+
await interaction.editReply(\`Pong! 🏓\\nWebsocket Latency: \\\`\${client.ws.ping}ms\\\`\\nAPI Latency: \\\`\${msg.createdTimestamp - interaction.createdTimestamp}ms\\\`\`);
|
|
25
|
+
},
|
|
26
|
+
executeText: async (message, args, client) => {
|
|
27
|
+
const sent = await message.reply('Pinging...');
|
|
28
|
+
await sent.edit(\`Pong! 🏓\\nWebsocket Latency: \\\`\${client.ws.ping}ms\\\`\\nAPI Latency: \\\`\${sent.createdTimestamp - message.createdTimestamp}ms\\\`\`);
|
|
23
29
|
}
|
|
24
|
-
};
|
|
30
|
+
} as FileCommand;
|
|
25
31
|
`,
|
|
26
32
|
|
|
27
33
|
ready: `import { DJSNextEvent, Events } from 'djs-next';
|
package/src/types.ts
CHANGED
|
@@ -12,8 +12,21 @@ import {
|
|
|
12
12
|
Message
|
|
13
13
|
} from 'discord.js';
|
|
14
14
|
|
|
15
|
+
export interface CooldownAdapter {
|
|
16
|
+
get(commandId: string, userId: string): Promise<number | null> | number | null;
|
|
17
|
+
set(commandId: string, userId: string, expirationTime: number): Promise<void> | void;
|
|
18
|
+
}
|
|
19
|
+
|
|
15
20
|
export interface DJSNextConfig {
|
|
16
21
|
devGuildId?: string;
|
|
22
|
+
errorLogChannelId?: string;
|
|
23
|
+
responses?: {
|
|
24
|
+
developerOnly?: string | null;
|
|
25
|
+
guildOnly?: string | null;
|
|
26
|
+
cooldown?: string | null;
|
|
27
|
+
missingPerms?: string | null;
|
|
28
|
+
errorBoundary?: string | null;
|
|
29
|
+
};
|
|
17
30
|
locales?: string[];
|
|
18
31
|
defaultLocale?: string;
|
|
19
32
|
directories?: {
|
|
@@ -23,6 +36,7 @@ export interface DJSNextConfig {
|
|
|
23
36
|
tasks?: string;
|
|
24
37
|
locales?: string;
|
|
25
38
|
};
|
|
39
|
+
cooldownAdapter?: CooldownAdapter;
|
|
26
40
|
}
|
|
27
41
|
|
|
28
42
|
export interface DJSNextClientOptions extends ClientOptions {
|
|
@@ -34,9 +48,13 @@ export interface DJSNextClientOptions extends ClientOptions {
|
|
|
34
48
|
guildId?: string;
|
|
35
49
|
developers?: string[];
|
|
36
50
|
prefixes?: string[] | string;
|
|
37
|
-
|
|
51
|
+
enableSlashCommands?: boolean;
|
|
52
|
+
enableTextCommands?: boolean;
|
|
53
|
+
enableMentionPrefix?: boolean | string[];
|
|
54
|
+
enableNoPrefix?: boolean | string[];
|
|
38
55
|
middleware?: (interaction: Interaction | Message, client: Client) => Promise<boolean> | boolean;
|
|
39
56
|
config?: DJSNextConfig;
|
|
57
|
+
db?: any;
|
|
40
58
|
}
|
|
41
59
|
|
|
42
60
|
export interface FileTask<DB = any> {
|
|
@@ -55,6 +73,7 @@ export interface FileCommand<DB = any> {
|
|
|
55
73
|
developerOnly?: boolean;
|
|
56
74
|
guildOnly?: boolean;
|
|
57
75
|
aliases?: string[];
|
|
76
|
+
preconditions?: string[];
|
|
58
77
|
execute?: (interaction: ChatInputCommandInteraction, client: Client & { db: DB; t: Function; config: DJSNextConfig }) => Promise<void> | void;
|
|
59
78
|
executeText?: (message: Message, args: string[], client: Client & { db: DB; t: Function; config: DJSNextConfig }) => Promise<void> | void;
|
|
60
79
|
autocomplete?: (interaction: AutocompleteInteraction, client: Client & { db: DB; t: Function; config: DJSNextConfig }) => Promise<void> | void;
|
|
@@ -63,6 +82,7 @@ export interface FileCommand<DB = any> {
|
|
|
63
82
|
export interface FileComponent<DB = any> {
|
|
64
83
|
filepath?: string;
|
|
65
84
|
customId?: string;
|
|
85
|
+
preconditions?: string[];
|
|
66
86
|
execute: (interaction: MessageComponentInteraction | ModalSubmitInteraction, client: Client & { db: DB; t: Function; config: DJSNextConfig }, params?: Record<string, string>) => Promise<void> | void;
|
|
67
87
|
}
|
|
68
88
|
|