djs-next 0.0.1 → 1.0.0-dev.2
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 +29 -51
- package/dist/cli.d.mts +1 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +344 -0
- package/dist/cli.js.map +1 -0
- package/dist/cli.mjs +321 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/index.d.mts +4 -46
- package/dist/index.d.ts +4 -46
- package/dist/index.js +290 -578
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +280 -578
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/src/cli.ts +203 -0
- package/src/client.ts +106 -213
- package/src/index.ts +1 -4
- package/src/plugins/dnxt.ts +176 -215
- package/src/templates/cjs.ts +6 -11
- package/src/templates/esm.ts +4 -11
- package/src/templates/ts.ts +5 -11
- package/src/types.ts +1 -21
- package/src/utils/paginate.ts +13 -32
- package/tsup.config.ts +1 -1
- package/bin/create-djs-next.js +0 -78
- package/src/utils/PaginationBuilder.ts +0 -94
- package/src/utils/prompts.ts +0 -76
- package/test_payload.js +0 -3
- package/test_reply.js +0 -4
package/src/plugins/dnxt.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Message, EmbedBuilder
|
|
1
|
+
import { Message, EmbedBuilder } from 'discord.js';
|
|
2
2
|
import { exec } from 'child_process';
|
|
3
3
|
import util from 'util';
|
|
4
4
|
import os from 'os';
|
|
@@ -11,88 +11,30 @@ import { loadLocales } from '../utils/i18n.js';
|
|
|
11
11
|
|
|
12
12
|
const execAsync = util.promisify(exec);
|
|
13
13
|
|
|
14
|
-
export function
|
|
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> {
|
|
14
|
+
export async function handleDNXT(message: Message, client: DJSNextClient, prefix: 'dnxt' | 'nxt' = 'dnxt') {
|
|
25
15
|
if (message.author.bot) return;
|
|
26
|
-
|
|
27
|
-
if (
|
|
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
|
-
}
|
|
16
|
+
// Make sure only developers can use this
|
|
17
|
+
if (!client['_developers'].includes(message.author.id)) return;
|
|
46
18
|
|
|
47
|
-
|
|
48
|
-
if (!matchedTrigger) return;
|
|
19
|
+
if (!message.content.startsWith(prefix)) return;
|
|
49
20
|
|
|
50
|
-
const args = content.slice(
|
|
21
|
+
const args = message.content.slice(prefix.length).trim().split(/ +/);
|
|
51
22
|
const command = args.shift()?.toLowerCase();
|
|
52
23
|
|
|
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
|
-
|
|
73
24
|
// Root dnxt command (Stats)
|
|
74
25
|
if (!command) {
|
|
75
26
|
const mem = process.memoryUsage();
|
|
27
|
+
const discordJsVersion = require('discord.js/package.json').version;
|
|
76
28
|
const botPing = client.ws.ping;
|
|
77
|
-
const djs = require('discord.js');
|
|
78
29
|
|
|
79
|
-
const
|
|
80
|
-
.
|
|
81
|
-
.
|
|
82
|
-
|
|
83
|
-
)
|
|
84
|
-
.
|
|
85
|
-
|
|
86
|
-
|
|
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
|
-
});
|
|
30
|
+
const text =
|
|
31
|
+
`Module was loaded <t:${Math.floor((Date.now() - client.uptime!) / 1000)}:R>.\n` +
|
|
32
|
+
`DNXT framework plugin, discord.js \`${discordJsVersion}\`, \`Node.js ${process.version}\` on \`${os.type()}\`.\n` +
|
|
33
|
+
`Latencies: \`${botPing}ms\` websocket ping.\n` +
|
|
34
|
+
`Memory: \`${(mem.rss / 1024 / 1024).toFixed(2)} MB\` physical, \`${(mem.heapUsed / 1024 / 1024).toFixed(2)} MB\` heap.\n` +
|
|
35
|
+
`System: \`${os.cpus().length}\` thread(s), \`${(os.uptime() / 60 / 60).toFixed(2)}\` hrs system uptime.`;
|
|
36
|
+
|
|
37
|
+
await message.reply(text);
|
|
96
38
|
return;
|
|
97
39
|
}
|
|
98
40
|
|
|
@@ -113,11 +55,11 @@ export async function handleDNXT(message: Message, client: Client, devPrefix: 'd
|
|
|
113
55
|
const end = process.hrtime.bigint();
|
|
114
56
|
const timeMs = Number(end - start) / 1e6;
|
|
115
57
|
|
|
116
|
-
if (typeof evaled !== 'string') evaled = util.inspect(evaled, { depth: 1
|
|
58
|
+
if (typeof evaled !== 'string') evaled = util.inspect(evaled, { depth: 1 });
|
|
117
59
|
|
|
118
|
-
await sendPaginatedText(message, `✅ **Evaluated in ${timeMs.toFixed(3)}ms**\n`, evaled, '
|
|
60
|
+
await sendPaginatedText(message, `✅ **Evaluated in ${timeMs.toFixed(3)}ms**\n`, evaled, 'js');
|
|
119
61
|
} catch (err: any) {
|
|
120
|
-
await sendPaginatedText(message, `❌ **Evaluation Error**\n`, err.message, '
|
|
62
|
+
await sendPaginatedText(message, `❌ **Evaluation Error**\n`, err.message, 'js');
|
|
121
63
|
}
|
|
122
64
|
return;
|
|
123
65
|
}
|
|
@@ -129,72 +71,53 @@ export async function handleDNXT(message: Message, client: Client, devPrefix: 'd
|
|
|
129
71
|
|
|
130
72
|
try {
|
|
131
73
|
const start = process.hrtime.bigint();
|
|
132
|
-
|
|
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
|
-
}
|
|
74
|
+
const { stdout, stderr } = await execAsync(cmd);
|
|
142
75
|
const end = process.hrtime.bigint();
|
|
143
76
|
const timeMs = Number(end - start) / 1e6;
|
|
144
77
|
|
|
145
|
-
|
|
146
|
-
|
|
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');
|
|
78
|
+
const result = stdout || stderr || 'No output.';
|
|
79
|
+
await sendPaginatedText(message, `✅ **Executed in ${timeMs.toFixed(3)}ms**\n`, result, 'sh');
|
|
151
80
|
} catch (err: any) {
|
|
152
|
-
await sendPaginatedText(message, `❌ **Shell Error**\n`, err.message, '
|
|
81
|
+
await sendPaginatedText(message, `❌ **Shell Error**\n`, err.message, 'sh');
|
|
153
82
|
}
|
|
154
83
|
return;
|
|
155
84
|
}
|
|
156
85
|
|
|
157
86
|
// Load / Unload / Reload
|
|
158
|
-
if (command === '
|
|
87
|
+
if (command === 'reload' || command === 'load') {
|
|
159
88
|
const target = args[0]?.toLowerCase();
|
|
160
89
|
try {
|
|
161
90
|
if (target === 'commands' && client['_commandsDir']) {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
await message.reply(
|
|
91
|
+
client.commands.clear();
|
|
92
|
+
client.commands = await loadAndDeployCommands(client['_commandsDir'], client.token!, client['_clientId']!, client['_guildId']);
|
|
93
|
+
await message.reply('✅ Reloaded commands.');
|
|
165
94
|
} else if (target === 'events' && client['_eventsDir']) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
if (command === 'load' || command === 'reload') await loadEvents(client, client['_eventsDir']);
|
|
171
|
-
await message.reply(`✅ Successfully ${command}ed events.`);
|
|
95
|
+
client.removeAllListeners();
|
|
96
|
+
client['attachCoreListeners']();
|
|
97
|
+
await loadEvents(client, client['_eventsDir']);
|
|
98
|
+
await message.reply('✅ Reloaded events.');
|
|
172
99
|
} else if (target === 'components' && client['_componentsDir']) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
await message.reply(
|
|
100
|
+
client.components.clear();
|
|
101
|
+
client.components = await loadComponents(client['_componentsDir']);
|
|
102
|
+
await message.reply('✅ Reloaded components.');
|
|
176
103
|
} else if (target === 'locales' && client['_localesDir']) {
|
|
177
|
-
|
|
178
|
-
await message.reply(
|
|
104
|
+
loadLocales(client['_localesDir'], client.config.defaultLocale);
|
|
105
|
+
await message.reply('✅ Reloaded locales.');
|
|
179
106
|
} else if (target === 'all' || !target) {
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
if (
|
|
187
|
-
|
|
188
|
-
|
|
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.`);
|
|
107
|
+
client.removeAllListeners();
|
|
108
|
+
client['attachCoreListeners']();
|
|
109
|
+
client.commands.clear();
|
|
110
|
+
client.components.clear();
|
|
111
|
+
if (client['_eventsDir']) await loadEvents(client, client['_eventsDir']);
|
|
112
|
+
if (client['_componentsDir']) client.components = await loadComponents(client['_componentsDir']);
|
|
113
|
+
if (client['_localesDir']) loadLocales(client['_localesDir'], client.config.defaultLocale);
|
|
114
|
+
if (client['_commandsDir']) client.commands = await loadAndDeployCommands(client['_commandsDir'], client.token!, client['_clientId']!, client['_guildId']);
|
|
115
|
+
await message.reply('✅ Reloaded all framework modules.');
|
|
193
116
|
} else {
|
|
194
117
|
await message.reply('❌ Unknown target. Valid targets: `commands, events, components, locales, all`');
|
|
195
118
|
}
|
|
196
119
|
} catch (err: any) {
|
|
197
|
-
await message.reply(`❌
|
|
120
|
+
await message.reply(`❌ **Reload Error:** ${err.message}`);
|
|
198
121
|
}
|
|
199
122
|
return;
|
|
200
123
|
}
|
|
@@ -215,9 +138,48 @@ export async function handleDNXT(message: Message, client: Client, devPrefix: 'd
|
|
|
215
138
|
return;
|
|
216
139
|
}
|
|
217
140
|
|
|
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
|
+
}
|
|
218
166
|
|
|
219
|
-
|
|
220
|
-
|
|
167
|
+
// Source Command (dnxt source <command>)
|
|
168
|
+
if (command === 'source' || command === 'src') {
|
|
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
|
+
}
|
|
221
183
|
|
|
222
184
|
// Curl (dnxt curl <url>)
|
|
223
185
|
if (command === 'curl') {
|
|
@@ -255,11 +217,11 @@ export async function handleDNXT(message: Message, client: Client, devPrefix: 'd
|
|
|
255
217
|
const timeMs = Number(end - start) / 1e6;
|
|
256
218
|
const memDiff = (endMem - startMem) / 1024 / 1024;
|
|
257
219
|
|
|
258
|
-
if (typeof evaled !== 'string') evaled = util.inspect(evaled, { depth: 1
|
|
220
|
+
if (typeof evaled !== 'string') evaled = util.inspect(evaled, { depth: 1 });
|
|
259
221
|
|
|
260
|
-
await sendPaginatedText(message, `⏱️ **Debug Execution**\nTime: \`${timeMs.toFixed(3)}ms\` | Heap Delta: \`${memDiff.toFixed(3)}MB\`\n`, evaled, '
|
|
222
|
+
await sendPaginatedText(message, `⏱️ **Debug Execution**\nTime: \`${timeMs.toFixed(3)}ms\` | Heap Delta: \`${memDiff.toFixed(3)}MB\`\n`, evaled, 'js');
|
|
261
223
|
} catch (err: any) {
|
|
262
|
-
await sendPaginatedText(message, `❌ **Debug Error**\n`, err.message, '
|
|
224
|
+
await sendPaginatedText(message, `❌ **Debug Error**\n`, err.message, 'js');
|
|
263
225
|
}
|
|
264
226
|
return;
|
|
265
227
|
}
|
|
@@ -268,27 +230,59 @@ export async function handleDNXT(message: Message, client: Client, devPrefix: 'd
|
|
|
268
230
|
if (command === 'in') {
|
|
269
231
|
const channelId = args.shift()?.replace(/<#|>/g, '');
|
|
270
232
|
const cmd = args.join(' ');
|
|
271
|
-
if (!channelId || !cmd) return void await message.reply(`❌ Usage: ${
|
|
233
|
+
if (!channelId || !cmd) return void await message.reply(`❌ Usage: ${prefix} in <channel> <command>`);
|
|
272
234
|
try {
|
|
273
235
|
const targetChannel = await client.channels.fetch(channelId);
|
|
274
236
|
if (!targetChannel || !targetChannel.isTextBased()) throw new Error('Invalid Text Channel.');
|
|
275
237
|
|
|
276
238
|
const mockMessage = Object.assign(Object.create(Object.getPrototypeOf(message)), message);
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
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 });
|
|
239
|
+
mockMessage.channel = targetChannel;
|
|
240
|
+
mockMessage.channelId = targetChannel.id;
|
|
241
|
+
mockMessage.content = cmd;
|
|
242
|
+
|
|
285
243
|
client.emit('messageCreate', mockMessage as Message);
|
|
244
|
+
await message.reply(`✅ Redirected execution to <#${targetChannel.id}>.`);
|
|
286
245
|
} catch (e: any) {
|
|
287
246
|
await message.reply(`❌ **In Error:** ${e.message}`);
|
|
288
247
|
}
|
|
289
248
|
return;
|
|
290
249
|
}
|
|
291
250
|
|
|
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
|
+
|
|
292
286
|
// Sync Command (dnxt sync)
|
|
293
287
|
if (command === 'sync') {
|
|
294
288
|
try {
|
|
@@ -301,37 +295,49 @@ export async function handleDNXT(message: Message, client: Client, devPrefix: 'd
|
|
|
301
295
|
return;
|
|
302
296
|
}
|
|
303
297
|
|
|
304
|
-
//
|
|
305
|
-
if (command === '
|
|
306
|
-
|
|
307
|
-
|
|
298
|
+
// SQL Command (dnxt sql <query>)
|
|
299
|
+
if (command === 'sql') {
|
|
300
|
+
const query = args.join(' ');
|
|
301
|
+
if (!query) return void await message.reply(`❌ Usage: ${prefix} sql <query>`);
|
|
308
302
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
303
|
+
try {
|
|
304
|
+
let res: any;
|
|
305
|
+
if (client.db && typeof client.db.$queryRawUnsafe === 'function') {
|
|
306
|
+
res = await client.db.$queryRawUnsafe(query); // Prisma fallback
|
|
307
|
+
} else if (client.db && typeof client.db.query === 'function') {
|
|
308
|
+
res = await client.db.query(query); // PG/MySQL fallback
|
|
309
|
+
} else {
|
|
310
|
+
return void await message.reply('❌ Your configured `client.db` does not expose a recognized raw SQL execution method (`$queryRawUnsafe` or `query`).');
|
|
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
|
+
}
|
|
317
317
|
return;
|
|
318
318
|
}
|
|
319
319
|
|
|
320
|
-
//
|
|
321
|
-
if (command === '
|
|
322
|
-
await message.reply('
|
|
323
|
-
|
|
324
|
-
|
|
320
|
+
// Voice Command (dnxt vc)
|
|
321
|
+
if (command === 'vc' || command === 'voice') {
|
|
322
|
+
if (!message.guild) return void await message.reply('❌ This command must be used in a server.');
|
|
323
|
+
const me = message.guild.members.me;
|
|
324
|
+
if (!me?.voice?.channel) return void await message.reply('❌ Bot is not currently in a voice channel.');
|
|
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);
|
|
325
331
|
return;
|
|
326
332
|
}
|
|
327
333
|
|
|
328
|
-
await message.reply(`❓ Unknown ${
|
|
334
|
+
await message.reply(`❓ Unknown ${prefix} command. Available: \`js, sh, git, cat, curl, su, in, source, debug, reload, tasks, cancel, sync, sql, vc\``);
|
|
329
335
|
}
|
|
330
336
|
|
|
331
337
|
async function sendPaginatedText(message: Message, header: string, content: string, language: string = '') {
|
|
332
|
-
const maxLength =
|
|
338
|
+
const maxLength = 1900;
|
|
333
339
|
if (content.length <= maxLength) {
|
|
334
|
-
await message.reply(
|
|
340
|
+
await message.reply(`${header}\`\`\`${language}\n${content}\n\`\`\``);
|
|
335
341
|
return;
|
|
336
342
|
}
|
|
337
343
|
|
|
@@ -341,78 +347,33 @@ async function sendPaginatedText(message: Message, header: string, content: stri
|
|
|
341
347
|
}
|
|
342
348
|
|
|
343
349
|
let index = 0;
|
|
344
|
-
const
|
|
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
|
-
}
|
|
350
|
+
const reply = await message.reply(`${header}\`\`\`${language}\n${chunks[index]}\n\`\`\`\n*Page 1 of ${chunks.length}*`);
|
|
369
351
|
|
|
370
|
-
|
|
352
|
+
await reply.react('◀️');
|
|
353
|
+
await reply.react('▶️');
|
|
354
|
+
await reply.react('⏹️');
|
|
371
355
|
|
|
372
|
-
const collector = reply.
|
|
373
|
-
filter: (
|
|
356
|
+
const collector = reply.createReactionCollector({
|
|
357
|
+
filter: (reaction, user) => ['◀️', '▶️', '⏹️'].includes(reaction.emoji.name!) && user.id === message.author.id,
|
|
374
358
|
time: 120000
|
|
375
359
|
});
|
|
376
360
|
|
|
377
|
-
collector.on('collect', async (
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
361
|
+
collector.on('collect', async (reaction, user) => {
|
|
362
|
+
await reaction.users.remove(user.id).catch(() => null);
|
|
363
|
+
|
|
364
|
+
if (reaction.emoji.name === '◀️') {
|
|
381
365
|
index = index > 0 ? index - 1 : index;
|
|
382
|
-
} else if (
|
|
366
|
+
} else if (reaction.emoji.name === '▶️') {
|
|
383
367
|
index = index < chunks.length - 1 ? index + 1 : index;
|
|
384
|
-
} else if (
|
|
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);
|
|
368
|
+
} else if (reaction.emoji.name === '⏹️') {
|
|
408
369
|
collector.stop();
|
|
409
370
|
return;
|
|
410
371
|
}
|
|
411
372
|
|
|
412
|
-
await
|
|
373
|
+
await reply.edit(`${header}\`\`\`${language}\n${chunks[index]}\n\`\`\`\n*Page ${index + 1} of ${chunks.length}*`);
|
|
413
374
|
});
|
|
414
375
|
|
|
415
376
|
collector.on('end', () => {
|
|
416
|
-
reply.
|
|
377
|
+
reply.reactions.removeAll().catch(() => null);
|
|
417
378
|
});
|
|
418
379
|
}
|
package/src/templates/cjs.ts
CHANGED
|
@@ -14,17 +14,12 @@ const client = new DJSNextClient({
|
|
|
14
14
|
client.start(process.env.DISCORD_TOKEN);
|
|
15
15
|
`,
|
|
16
16
|
|
|
17
|
-
ping:
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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\\\`\`);
|
|
17
|
+
ping: `module.exports = {
|
|
18
|
+
command: {
|
|
19
|
+
description: 'Replies with Pong!',
|
|
20
|
+
execute: async (interaction) => {
|
|
21
|
+
await interaction.reply('Pong!');
|
|
22
|
+
}
|
|
28
23
|
}
|
|
29
24
|
};
|
|
30
25
|
`,
|
package/src/templates/esm.ts
CHANGED
|
@@ -14,17 +14,10 @@ const client = new DJSNextClient({
|
|
|
14
14
|
client.start(process.env.DISCORD_TOKEN);
|
|
15
15
|
`,
|
|
16
16
|
|
|
17
|
-
ping:
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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\\\`\`);
|
|
17
|
+
ping: `export const command = {
|
|
18
|
+
description: 'Replies with Pong!',
|
|
19
|
+
execute: async (interaction) => {
|
|
20
|
+
await interaction.reply('Pong!');
|
|
28
21
|
}
|
|
29
22
|
};
|
|
30
23
|
`,
|
package/src/templates/ts.ts
CHANGED
|
@@ -16,18 +16,12 @@ 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
|
-
|
|
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\\\`\`);
|
|
19
|
+
export const command: FileCommand = {
|
|
20
|
+
description: 'Replies with Pong!',
|
|
21
|
+
execute: async (interaction) => {
|
|
22
|
+
await interaction.reply('Pong!');
|
|
29
23
|
}
|
|
30
|
-
}
|
|
24
|
+
};
|
|
31
25
|
`,
|
|
32
26
|
|
|
33
27
|
ready: `import { DJSNextEvent, Events } from 'djs-next';
|
package/src/types.ts
CHANGED
|
@@ -12,21 +12,8 @@ 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
|
-
|
|
20
15
|
export interface DJSNextConfig {
|
|
21
16
|
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
|
-
};
|
|
30
17
|
locales?: string[];
|
|
31
18
|
defaultLocale?: string;
|
|
32
19
|
directories?: {
|
|
@@ -36,7 +23,6 @@ export interface DJSNextConfig {
|
|
|
36
23
|
tasks?: string;
|
|
37
24
|
locales?: string;
|
|
38
25
|
};
|
|
39
|
-
cooldownAdapter?: CooldownAdapter;
|
|
40
26
|
}
|
|
41
27
|
|
|
42
28
|
export interface DJSNextClientOptions extends ClientOptions {
|
|
@@ -48,13 +34,9 @@ export interface DJSNextClientOptions extends ClientOptions {
|
|
|
48
34
|
guildId?: string;
|
|
49
35
|
developers?: string[];
|
|
50
36
|
prefixes?: string[] | string;
|
|
51
|
-
|
|
52
|
-
enableTextCommands?: boolean;
|
|
53
|
-
enableMentionPrefix?: boolean | string[];
|
|
54
|
-
enableNoPrefix?: boolean | string[];
|
|
37
|
+
enableMentionPrefix?: boolean;
|
|
55
38
|
middleware?: (interaction: Interaction | Message, client: Client) => Promise<boolean> | boolean;
|
|
56
39
|
config?: DJSNextConfig;
|
|
57
|
-
db?: any;
|
|
58
40
|
}
|
|
59
41
|
|
|
60
42
|
export interface FileTask<DB = any> {
|
|
@@ -73,7 +55,6 @@ export interface FileCommand<DB = any> {
|
|
|
73
55
|
developerOnly?: boolean;
|
|
74
56
|
guildOnly?: boolean;
|
|
75
57
|
aliases?: string[];
|
|
76
|
-
preconditions?: string[];
|
|
77
58
|
execute?: (interaction: ChatInputCommandInteraction, client: Client & { db: DB; t: Function; config: DJSNextConfig }) => Promise<void> | void;
|
|
78
59
|
executeText?: (message: Message, args: string[], client: Client & { db: DB; t: Function; config: DJSNextConfig }) => Promise<void> | void;
|
|
79
60
|
autocomplete?: (interaction: AutocompleteInteraction, client: Client & { db: DB; t: Function; config: DJSNextConfig }) => Promise<void> | void;
|
|
@@ -82,7 +63,6 @@ export interface FileCommand<DB = any> {
|
|
|
82
63
|
export interface FileComponent<DB = any> {
|
|
83
64
|
filepath?: string;
|
|
84
65
|
customId?: string;
|
|
85
|
-
preconditions?: string[];
|
|
86
66
|
execute: (interaction: MessageComponentInteraction | ModalSubmitInteraction, client: Client & { db: DB; t: Function; config: DJSNextConfig }, params?: Record<string, string>) => Promise<void> | void;
|
|
87
67
|
}
|
|
88
68
|
|