novaapp-sdk 1.0.9 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +644 -37
- package/dist/index.d.ts +644 -37
- package/dist/index.js +728 -5
- package/dist/index.mjs +717 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -20,14 +20,24 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
ActionRowBuilder: () => ActionRowBuilder,
|
|
24
|
+
ButtonBuilder: () => ButtonBuilder,
|
|
23
25
|
CommandsAPI: () => CommandsAPI,
|
|
26
|
+
EmbedBuilder: () => EmbedBuilder,
|
|
24
27
|
HttpClient: () => HttpClient,
|
|
28
|
+
InteractionOptions: () => InteractionOptions,
|
|
25
29
|
InteractionsAPI: () => InteractionsAPI,
|
|
26
30
|
MembersAPI: () => MembersAPI,
|
|
27
31
|
MessagesAPI: () => MessagesAPI,
|
|
32
|
+
ModalBuilder: () => ModalBuilder,
|
|
28
33
|
NovaClient: () => NovaClient,
|
|
34
|
+
NovaInteraction: () => NovaInteraction,
|
|
29
35
|
PermissionsAPI: () => PermissionsAPI,
|
|
30
|
-
|
|
36
|
+
SelectMenuBuilder: () => SelectMenuBuilder,
|
|
37
|
+
ServersAPI: () => ServersAPI,
|
|
38
|
+
SlashCommandBuilder: () => SlashCommandBuilder,
|
|
39
|
+
SlashCommandOptionBuilder: () => SlashCommandOptionBuilder,
|
|
40
|
+
TextInputBuilder: () => TextInputBuilder
|
|
31
41
|
});
|
|
32
42
|
module.exports = __toCommonJS(index_exports);
|
|
33
43
|
|
|
@@ -273,8 +283,9 @@ var ServersAPI = class {
|
|
|
273
283
|
|
|
274
284
|
// src/api/interactions.ts
|
|
275
285
|
var InteractionsAPI = class {
|
|
276
|
-
constructor(http) {
|
|
286
|
+
constructor(http, emitter) {
|
|
277
287
|
this.http = http;
|
|
288
|
+
this.emitter = emitter;
|
|
278
289
|
}
|
|
279
290
|
/**
|
|
280
291
|
* Acknowledge an interaction without sending a visible response.
|
|
@@ -323,6 +334,71 @@ var InteractionsAPI = class {
|
|
|
323
334
|
const qs = params.toString();
|
|
324
335
|
return this.http.get(`/interactions${qs ? `?${qs}` : ""}`);
|
|
325
336
|
}
|
|
337
|
+
/**
|
|
338
|
+
* Open a modal for the user who triggered an interaction and await their submission.
|
|
339
|
+
*
|
|
340
|
+
* Internally this:
|
|
341
|
+
* 1. Calls `respond(interactionId, { modal })` to push the modal to the client UI.
|
|
342
|
+
* 2. Listens for the next `interactionCreate` event whose type is `MODAL_SUBMIT`
|
|
343
|
+
* and whose `customId` matches your modal's `customId`.
|
|
344
|
+
* 3. Resolves with the submitted `Interaction` (containing `modalData`), or `null`
|
|
345
|
+
* if the user closes the modal without submitting within the timeout.
|
|
346
|
+
*
|
|
347
|
+
* @param interactionId - ID of the triggering interaction.
|
|
348
|
+
* @param modal - Modal definition (title, customId, fields).
|
|
349
|
+
* @param options.timeout - Max milliseconds to wait (default: 300 000 = 5 min).
|
|
350
|
+
*
|
|
351
|
+
* @example
|
|
352
|
+
* client.on('interactionCreate', async (interaction) => {
|
|
353
|
+
* if (interaction.commandName === 'report') {
|
|
354
|
+
* const submitted = await client.interactions.awaitModal(interaction.id, {
|
|
355
|
+
* title: 'Submit a report',
|
|
356
|
+
* customId: 'report_modal',
|
|
357
|
+
* fields: [
|
|
358
|
+
* { customId: 'reason', label: 'Reason', type: 'paragraph', required: true, maxLength: 500 },
|
|
359
|
+
* ],
|
|
360
|
+
* })
|
|
361
|
+
*
|
|
362
|
+
* if (!submitted) {
|
|
363
|
+
* // User dismissed the modal or timed out — nothing to do
|
|
364
|
+
* return
|
|
365
|
+
* }
|
|
366
|
+
*
|
|
367
|
+
* const reason = submitted.modalData?.reason
|
|
368
|
+
* await client.interactions.respond(submitted.id, {
|
|
369
|
+
* content: `Report received: ${reason}`,
|
|
370
|
+
* ephemeral: true,
|
|
371
|
+
* })
|
|
372
|
+
* }
|
|
373
|
+
* })
|
|
374
|
+
*/
|
|
375
|
+
awaitModal(interactionId, modal, options = {}) {
|
|
376
|
+
const ms = options.timeout ?? 3e5;
|
|
377
|
+
let listener = null;
|
|
378
|
+
let timer = null;
|
|
379
|
+
const waitPromise = new Promise((resolve) => {
|
|
380
|
+
timer = setTimeout(() => {
|
|
381
|
+
if (listener) this.emitter.off("interactionCreate", listener);
|
|
382
|
+
resolve(null);
|
|
383
|
+
}, ms);
|
|
384
|
+
listener = (interaction) => {
|
|
385
|
+
if (interaction.type === "MODAL_SUBMIT" && interaction.customId === modal.customId) {
|
|
386
|
+
if (timer) clearTimeout(timer);
|
|
387
|
+
if (listener) this.emitter.off("interactionCreate", listener);
|
|
388
|
+
resolve(interaction);
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
this.emitter.on("interactionCreate", listener);
|
|
392
|
+
});
|
|
393
|
+
return this.respond(interactionId, { modal }).then(
|
|
394
|
+
() => waitPromise,
|
|
395
|
+
(err) => {
|
|
396
|
+
if (timer) clearTimeout(timer);
|
|
397
|
+
if (listener) this.emitter.off("interactionCreate", listener);
|
|
398
|
+
return Promise.reject(err);
|
|
399
|
+
}
|
|
400
|
+
);
|
|
401
|
+
}
|
|
326
402
|
};
|
|
327
403
|
|
|
328
404
|
// src/api/permissions.ts
|
|
@@ -369,6 +445,185 @@ var PermissionsAPI = class {
|
|
|
369
445
|
}
|
|
370
446
|
};
|
|
371
447
|
|
|
448
|
+
// src/structures/NovaInteraction.ts
|
|
449
|
+
var InteractionOptions = class {
|
|
450
|
+
constructor(data) {
|
|
451
|
+
this._map = /* @__PURE__ */ new Map();
|
|
452
|
+
if (data && typeof data === "object") {
|
|
453
|
+
const d = data;
|
|
454
|
+
const opts = Array.isArray(d.options) ? d.options : [];
|
|
455
|
+
for (const o of opts) {
|
|
456
|
+
if (o?.name != null) this._map.set(String(o.name), o.value);
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
/** Whether this option was supplied by the user. */
|
|
461
|
+
has(name) {
|
|
462
|
+
return this._map.has(name);
|
|
463
|
+
}
|
|
464
|
+
getString(name, required = false) {
|
|
465
|
+
const v = this._map.get(name);
|
|
466
|
+
if (required && (v == null || v === "")) throw new Error(`Required option "${name}" is missing`);
|
|
467
|
+
return v != null ? String(v) : null;
|
|
468
|
+
}
|
|
469
|
+
getInteger(name, required = false) {
|
|
470
|
+
const v = this._map.get(name);
|
|
471
|
+
if (required && v == null) throw new Error(`Required option "${name}" is missing`);
|
|
472
|
+
return v != null ? Math.trunc(Number(v)) : null;
|
|
473
|
+
}
|
|
474
|
+
getNumber(name, required = false) {
|
|
475
|
+
const v = this._map.get(name);
|
|
476
|
+
if (required && v == null) throw new Error(`Required option "${name}" is missing`);
|
|
477
|
+
return v != null ? Number(v) : null;
|
|
478
|
+
}
|
|
479
|
+
/** Returns `true` or `false`, or `null` if not supplied. */
|
|
480
|
+
getBoolean(name) {
|
|
481
|
+
const v = this._map.get(name);
|
|
482
|
+
return v != null ? Boolean(v) : null;
|
|
483
|
+
}
|
|
484
|
+
getUser(name, required = false) {
|
|
485
|
+
return this.getString(name, required);
|
|
486
|
+
}
|
|
487
|
+
getChannel(name, required = false) {
|
|
488
|
+
return this.getString(name, required);
|
|
489
|
+
}
|
|
490
|
+
getRole(name, required = false) {
|
|
491
|
+
return this.getString(name, required);
|
|
492
|
+
}
|
|
493
|
+
};
|
|
494
|
+
var NovaInteraction = class _NovaInteraction {
|
|
495
|
+
constructor(_raw, _api) {
|
|
496
|
+
this._raw = _raw;
|
|
497
|
+
this._api = _api;
|
|
498
|
+
this.id = _raw.id;
|
|
499
|
+
this.type = _raw.type;
|
|
500
|
+
this.commandName = _raw.commandName ?? null;
|
|
501
|
+
this.customId = _raw.customId ?? null;
|
|
502
|
+
this.userId = _raw.userId;
|
|
503
|
+
this.channelId = _raw.channelId;
|
|
504
|
+
this.serverId = _raw.serverId ?? null;
|
|
505
|
+
this.triggerMsgId = _raw.triggerMsgId ?? null;
|
|
506
|
+
this.values = _raw.values ?? [];
|
|
507
|
+
this.modalData = _raw.modalData ?? {};
|
|
508
|
+
this.createdAt = _raw.createdAt;
|
|
509
|
+
this.options = new InteractionOptions(_raw.data);
|
|
510
|
+
}
|
|
511
|
+
// ── Type guards ─────────────────────────────────────────────────────────────
|
|
512
|
+
/** `true` when triggered by a `/slash` command. */
|
|
513
|
+
isSlashCommand() {
|
|
514
|
+
return this.type === "SLASH_COMMAND";
|
|
515
|
+
}
|
|
516
|
+
/** `true` when triggered by a `!prefix` command. */
|
|
517
|
+
isPrefixCommand() {
|
|
518
|
+
return this.type === "PREFIX_COMMAND";
|
|
519
|
+
}
|
|
520
|
+
/** `true` for both slash and prefix commands. */
|
|
521
|
+
isCommand() {
|
|
522
|
+
return this.isSlashCommand() || this.isPrefixCommand();
|
|
523
|
+
}
|
|
524
|
+
/** `true` when a button component was clicked. */
|
|
525
|
+
isButton() {
|
|
526
|
+
return this.type === "BUTTON_CLICK";
|
|
527
|
+
}
|
|
528
|
+
/** `true` when a select-menu option was chosen. */
|
|
529
|
+
isSelectMenu() {
|
|
530
|
+
return this.type === "SELECT_MENU";
|
|
531
|
+
}
|
|
532
|
+
/** `true` when the user submitted a modal form. */
|
|
533
|
+
isModalSubmit() {
|
|
534
|
+
return this.type === "MODAL_SUBMIT";
|
|
535
|
+
}
|
|
536
|
+
/** `true` during autocomplete suggestion requests. */
|
|
537
|
+
isAutocomplete() {
|
|
538
|
+
return this.type === "AUTOCOMPLETE";
|
|
539
|
+
}
|
|
540
|
+
/** `true` when triggered via a context-menu command. */
|
|
541
|
+
isContextMenu() {
|
|
542
|
+
return this.type === "CONTEXT_MENU";
|
|
543
|
+
}
|
|
544
|
+
// ── Actions ─────────────────────────────────────────────────────────────────
|
|
545
|
+
/**
|
|
546
|
+
* Respond with a message.
|
|
547
|
+
* Accepts a plain string or a full options object.
|
|
548
|
+
*
|
|
549
|
+
* @example
|
|
550
|
+
* await interaction.reply('Pong! 🏓')
|
|
551
|
+
* await interaction.reply({ content: 'Done!', ephemeral: true })
|
|
552
|
+
* await interaction.reply({ embed: new EmbedBuilder().setTitle('Stats').toJSON() })
|
|
553
|
+
*/
|
|
554
|
+
reply(options) {
|
|
555
|
+
return this._api.respond(this.id, typeof options === "string" ? { content: options } : options);
|
|
556
|
+
}
|
|
557
|
+
/**
|
|
558
|
+
* Respond with a message **only visible to the user** who triggered the interaction.
|
|
559
|
+
*
|
|
560
|
+
* @example
|
|
561
|
+
* await interaction.replyEphemeral('Only you can see this!')
|
|
562
|
+
*/
|
|
563
|
+
replyEphemeral(options) {
|
|
564
|
+
const resolved = typeof options === "string" ? { content: options } : options;
|
|
565
|
+
return this._api.respond(this.id, { ...resolved, ephemeral: true });
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Acknowledge the interaction without sending a response yet.
|
|
569
|
+
* Shows a loading indicator to the user.
|
|
570
|
+
* Follow up with `interaction.editReply()` when you're done.
|
|
571
|
+
*
|
|
572
|
+
* @example
|
|
573
|
+
* await interaction.defer()
|
|
574
|
+
* const data = await fetchSomeSlow()
|
|
575
|
+
* await interaction.editReply({ content: `Result: ${data}` })
|
|
576
|
+
*/
|
|
577
|
+
defer() {
|
|
578
|
+
return this._api.ack(this.id);
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* Edit the previous reply (e.g. after `defer()`).
|
|
582
|
+
*
|
|
583
|
+
* @example
|
|
584
|
+
* await interaction.defer()
|
|
585
|
+
* await interaction.editReply(`Done — processed ${count} items.`)
|
|
586
|
+
*/
|
|
587
|
+
editReply(options) {
|
|
588
|
+
return this._api.respond(this.id, typeof options === "string" ? { content: options } : options);
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Open a **modal dialog** and return the user's submission as a new `NovaInteraction`.
|
|
592
|
+
* Returns `null` if the user closes the modal or the timeout expires (default: 5 min).
|
|
593
|
+
*
|
|
594
|
+
* **This is the recommended way to open modals.**
|
|
595
|
+
*
|
|
596
|
+
* @example
|
|
597
|
+
* const submitted = await interaction.openModal(
|
|
598
|
+
* new ModalBuilder()
|
|
599
|
+
* .setTitle('Submit a report')
|
|
600
|
+
* .setCustomId('report_modal')
|
|
601
|
+
* .addField(
|
|
602
|
+
* new TextInputBuilder()
|
|
603
|
+
* .setCustomId('reason')
|
|
604
|
+
* .setLabel('Reason')
|
|
605
|
+
* .setStyle('paragraph')
|
|
606
|
+
* .setRequired(true)
|
|
607
|
+
* )
|
|
608
|
+
* )
|
|
609
|
+
*
|
|
610
|
+
* if (!submitted) return // user dismissed or timed out
|
|
611
|
+
*
|
|
612
|
+
* const reason = submitted.modalData.reason
|
|
613
|
+
* await submitted.replyEphemeral(`Report received: ${reason}`)
|
|
614
|
+
*/
|
|
615
|
+
async openModal(modal, options = {}) {
|
|
616
|
+
const def = "toJSON" in modal && typeof modal.toJSON === "function" ? modal.toJSON() : modal;
|
|
617
|
+
const raw = await this._api.awaitModal(this.id, def, options);
|
|
618
|
+
if (!raw) return null;
|
|
619
|
+
return new _NovaInteraction(raw, this._api);
|
|
620
|
+
}
|
|
621
|
+
/** Returns the raw interaction data from the gateway. */
|
|
622
|
+
toJSON() {
|
|
623
|
+
return { ...this._raw };
|
|
624
|
+
}
|
|
625
|
+
};
|
|
626
|
+
|
|
372
627
|
// src/client.ts
|
|
373
628
|
var EVENT_MAP = {
|
|
374
629
|
"message.created": "messageCreate",
|
|
@@ -386,6 +641,10 @@ var NovaClient = class extends import_node_events.EventEmitter {
|
|
|
386
641
|
/** The authenticated bot application. Available after `ready` fires. */
|
|
387
642
|
this.botUser = null;
|
|
388
643
|
this.socket = null;
|
|
644
|
+
// ── Command / component routing ───────────────────────────────────────────────────
|
|
645
|
+
this._commandHandlers = /* @__PURE__ */ new Map();
|
|
646
|
+
this._buttonHandlers = /* @__PURE__ */ new Map();
|
|
647
|
+
this._selectHandlers = /* @__PURE__ */ new Map();
|
|
389
648
|
if (!options.token) {
|
|
390
649
|
throw new Error("[nova-bot-sdk] A bot token is required.");
|
|
391
650
|
}
|
|
@@ -401,7 +660,7 @@ var NovaClient = class extends import_node_events.EventEmitter {
|
|
|
401
660
|
this.commands = new CommandsAPI(this.http);
|
|
402
661
|
this.members = new MembersAPI(this.http);
|
|
403
662
|
this.servers = new ServersAPI(this.http);
|
|
404
|
-
this.interactions = new InteractionsAPI(this.http);
|
|
663
|
+
this.interactions = new InteractionsAPI(this.http, this);
|
|
405
664
|
this.permissions = new PermissionsAPI(this.http);
|
|
406
665
|
this.on("error", () => {
|
|
407
666
|
});
|
|
@@ -416,6 +675,44 @@ var NovaClient = class extends import_node_events.EventEmitter {
|
|
|
416
675
|
process.exit(0);
|
|
417
676
|
});
|
|
418
677
|
}
|
|
678
|
+
/**
|
|
679
|
+
* Register a handler for a slash or prefix command by name.
|
|
680
|
+
* Automatically routes `interactionCreate` events whose `commandName` matches.
|
|
681
|
+
*
|
|
682
|
+
* @example
|
|
683
|
+
* client.command('ping', async (interaction) => {
|
|
684
|
+
* await interaction.reply('Pong! 🏓')
|
|
685
|
+
* })
|
|
686
|
+
*/
|
|
687
|
+
command(name, handler) {
|
|
688
|
+
this._commandHandlers.set(name, handler);
|
|
689
|
+
return this;
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Register a handler for a button by its `customId`.
|
|
693
|
+
*
|
|
694
|
+
* @example
|
|
695
|
+
* client.button('confirm_delete', async (interaction) => {
|
|
696
|
+
* await interaction.replyEphemeral('Deleted.')
|
|
697
|
+
* })
|
|
698
|
+
*/
|
|
699
|
+
button(customId, handler) {
|
|
700
|
+
this._buttonHandlers.set(customId, handler);
|
|
701
|
+
return this;
|
|
702
|
+
}
|
|
703
|
+
/**
|
|
704
|
+
* Register a handler for a select menu by its `customId`.
|
|
705
|
+
*
|
|
706
|
+
* @example
|
|
707
|
+
* client.selectMenu('colour_pick', async (interaction) => {
|
|
708
|
+
* const chosen = interaction.values[0]
|
|
709
|
+
* await interaction.reply(`You picked: ${chosen}`)
|
|
710
|
+
* })
|
|
711
|
+
*/
|
|
712
|
+
selectMenu(customId, handler) {
|
|
713
|
+
this._selectHandlers.set(customId, handler);
|
|
714
|
+
return this;
|
|
715
|
+
}
|
|
419
716
|
/**
|
|
420
717
|
* Connect to the Nova WebSocket gateway.
|
|
421
718
|
* Resolves when the `ready` event is received.
|
|
@@ -453,8 +750,19 @@ var NovaClient = class extends import_node_events.EventEmitter {
|
|
|
453
750
|
this.emit("ready", this.botUser);
|
|
454
751
|
resolve();
|
|
455
752
|
});
|
|
456
|
-
this.socket.on("interaction:created", (
|
|
753
|
+
this.socket.on("interaction:created", (raw) => {
|
|
754
|
+
const interaction = new NovaInteraction(raw, this.interactions);
|
|
457
755
|
this.emit("interactionCreate", interaction);
|
|
756
|
+
const run = (h) => {
|
|
757
|
+
if (h) Promise.resolve(h(interaction)).catch((e) => this.emit("error", e));
|
|
758
|
+
};
|
|
759
|
+
if (interaction.isCommand() && interaction.commandName) {
|
|
760
|
+
run(this._commandHandlers.get(interaction.commandName));
|
|
761
|
+
} else if (interaction.isButton() && interaction.customId) {
|
|
762
|
+
run(this._buttonHandlers.get(interaction.customId));
|
|
763
|
+
} else if (interaction.isSelectMenu() && interaction.customId) {
|
|
764
|
+
run(this._selectHandlers.get(interaction.customId));
|
|
765
|
+
}
|
|
458
766
|
});
|
|
459
767
|
this.socket.on("bot:event", (event) => {
|
|
460
768
|
this.emit("event", event);
|
|
@@ -538,14 +846,429 @@ var NovaClient = class extends import_node_events.EventEmitter {
|
|
|
538
846
|
return super.emit(event, ...args);
|
|
539
847
|
}
|
|
540
848
|
};
|
|
849
|
+
|
|
850
|
+
// src/builders/EmbedBuilder.ts
|
|
851
|
+
var EmbedBuilder = class {
|
|
852
|
+
constructor() {
|
|
853
|
+
this._data = {};
|
|
854
|
+
}
|
|
855
|
+
/** Set the embed title (shown in bold at the top). */
|
|
856
|
+
setTitle(title) {
|
|
857
|
+
this._data.title = title;
|
|
858
|
+
return this;
|
|
859
|
+
}
|
|
860
|
+
/** Set the main description text (supports markdown). */
|
|
861
|
+
setDescription(description) {
|
|
862
|
+
this._data.description = description;
|
|
863
|
+
return this;
|
|
864
|
+
}
|
|
865
|
+
/**
|
|
866
|
+
* Set the accent colour.
|
|
867
|
+
* @param color Hex string — e.g. `'#5865F2'` or `'5865F2'`
|
|
868
|
+
*/
|
|
869
|
+
setColor(color) {
|
|
870
|
+
this._data.color = color.startsWith("#") ? color : `#${color}`;
|
|
871
|
+
return this;
|
|
872
|
+
}
|
|
873
|
+
/** Make the title a clickable hyperlink. */
|
|
874
|
+
setUrl(url) {
|
|
875
|
+
this._data.url = url;
|
|
876
|
+
return this;
|
|
877
|
+
}
|
|
878
|
+
/** Small image shown in the top-right corner. */
|
|
879
|
+
setThumbnail(url) {
|
|
880
|
+
this._data.thumbnail = url;
|
|
881
|
+
return this;
|
|
882
|
+
}
|
|
883
|
+
/** Large image shown below the fields. */
|
|
884
|
+
setImage(url) {
|
|
885
|
+
this._data.image = url;
|
|
886
|
+
return this;
|
|
887
|
+
}
|
|
888
|
+
/** Footer text shown at the very bottom of the embed. */
|
|
889
|
+
setFooter(text) {
|
|
890
|
+
this._data.footer = text;
|
|
891
|
+
return this;
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* Add a timestamp to the footer line.
|
|
895
|
+
* @param date Defaults to `new Date()`.
|
|
896
|
+
*/
|
|
897
|
+
setTimestamp(date) {
|
|
898
|
+
const d = date instanceof Date ? date : date != null ? new Date(date) : /* @__PURE__ */ new Date();
|
|
899
|
+
this._data.timestamp = d.toISOString();
|
|
900
|
+
return this;
|
|
901
|
+
}
|
|
902
|
+
/** Author name + optional icon shown above the title. */
|
|
903
|
+
setAuthor(author) {
|
|
904
|
+
this._data.author = author;
|
|
905
|
+
return this;
|
|
906
|
+
}
|
|
907
|
+
/**
|
|
908
|
+
* Add a single field.
|
|
909
|
+
* @param inline Pass `true` to render this field side-by-side with adjacent inline fields.
|
|
910
|
+
*/
|
|
911
|
+
addField(name, value, inline) {
|
|
912
|
+
if (!this._data.fields) this._data.fields = [];
|
|
913
|
+
this._data.fields.push({ name, value, inline });
|
|
914
|
+
return this;
|
|
915
|
+
}
|
|
916
|
+
/** Add multiple fields at once. */
|
|
917
|
+
addFields(...fields) {
|
|
918
|
+
if (!this._data.fields) this._data.fields = [];
|
|
919
|
+
this._data.fields.push(...fields);
|
|
920
|
+
return this;
|
|
921
|
+
}
|
|
922
|
+
/** Replace all fields. */
|
|
923
|
+
setFields(fields) {
|
|
924
|
+
this._data.fields = [...fields];
|
|
925
|
+
return this;
|
|
926
|
+
}
|
|
927
|
+
/** Serialise to a plain `Embed` object you can pass to any API call. */
|
|
928
|
+
toJSON() {
|
|
929
|
+
return {
|
|
930
|
+
...this._data,
|
|
931
|
+
fields: this._data.fields ? [...this._data.fields] : void 0
|
|
932
|
+
};
|
|
933
|
+
}
|
|
934
|
+
};
|
|
935
|
+
|
|
936
|
+
// src/builders/ButtonBuilder.ts
|
|
937
|
+
var ButtonBuilder = class {
|
|
938
|
+
constructor() {
|
|
939
|
+
this._customId = "";
|
|
940
|
+
this._label = "";
|
|
941
|
+
this._style = "primary";
|
|
942
|
+
this._disabled = false;
|
|
943
|
+
}
|
|
944
|
+
/** Custom ID returned in the `BUTTON_CLICK` interaction. Not required for `link` style buttons. */
|
|
945
|
+
setCustomId(customId) {
|
|
946
|
+
this._customId = customId;
|
|
947
|
+
return this;
|
|
948
|
+
}
|
|
949
|
+
/** Text displayed on the button. */
|
|
950
|
+
setLabel(label) {
|
|
951
|
+
this._label = label;
|
|
952
|
+
return this;
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* Visual style:
|
|
956
|
+
* - `primary` — blurple / brand colour
|
|
957
|
+
* - `secondary` — grey
|
|
958
|
+
* - `success` — green
|
|
959
|
+
* - `danger` — red
|
|
960
|
+
* - `link` — grey, navigates to a URL instead of creating an interaction
|
|
961
|
+
*/
|
|
962
|
+
setStyle(style) {
|
|
963
|
+
this._style = style;
|
|
964
|
+
return this;
|
|
965
|
+
}
|
|
966
|
+
/** Emoji shown to the left of the label (unicode or custom e.g. `'👋'`). */
|
|
967
|
+
setEmoji(emoji) {
|
|
968
|
+
this._emoji = emoji;
|
|
969
|
+
return this;
|
|
970
|
+
}
|
|
971
|
+
/**
|
|
972
|
+
* URL for `link` style buttons.
|
|
973
|
+
* Sets the style to `'link'` automatically.
|
|
974
|
+
*/
|
|
975
|
+
setUrl(url) {
|
|
976
|
+
this._url = url;
|
|
977
|
+
this._style = "link";
|
|
978
|
+
return this;
|
|
979
|
+
}
|
|
980
|
+
/** Prevent users from clicking the button. */
|
|
981
|
+
setDisabled(disabled = true) {
|
|
982
|
+
this._disabled = disabled;
|
|
983
|
+
return this;
|
|
984
|
+
}
|
|
985
|
+
toJSON() {
|
|
986
|
+
return {
|
|
987
|
+
type: "button",
|
|
988
|
+
customId: this._customId,
|
|
989
|
+
label: this._label || void 0,
|
|
990
|
+
style: this._style,
|
|
991
|
+
emoji: this._emoji,
|
|
992
|
+
url: this._url,
|
|
993
|
+
disabled: this._disabled || void 0
|
|
994
|
+
};
|
|
995
|
+
}
|
|
996
|
+
};
|
|
997
|
+
|
|
998
|
+
// src/builders/SelectMenuBuilder.ts
|
|
999
|
+
var SelectMenuBuilder = class {
|
|
1000
|
+
constructor() {
|
|
1001
|
+
this._customId = "";
|
|
1002
|
+
this._disabled = false;
|
|
1003
|
+
this._options = [];
|
|
1004
|
+
}
|
|
1005
|
+
/** Custom ID returned in the `SELECT_MENU` interaction. */
|
|
1006
|
+
setCustomId(customId) {
|
|
1007
|
+
this._customId = customId;
|
|
1008
|
+
return this;
|
|
1009
|
+
}
|
|
1010
|
+
/** Greyed-out hint shown when nothing is selected. */
|
|
1011
|
+
setPlaceholder(placeholder) {
|
|
1012
|
+
this._placeholder = placeholder;
|
|
1013
|
+
return this;
|
|
1014
|
+
}
|
|
1015
|
+
/** Prevent users from interacting with the menu. */
|
|
1016
|
+
setDisabled(disabled = true) {
|
|
1017
|
+
this._disabled = disabled;
|
|
1018
|
+
return this;
|
|
1019
|
+
}
|
|
1020
|
+
/** Add a single option. */
|
|
1021
|
+
addOption(option) {
|
|
1022
|
+
this._options.push(option);
|
|
1023
|
+
return this;
|
|
1024
|
+
}
|
|
1025
|
+
/** Add multiple options at once. */
|
|
1026
|
+
addOptions(...options) {
|
|
1027
|
+
this._options.push(...options);
|
|
1028
|
+
return this;
|
|
1029
|
+
}
|
|
1030
|
+
/** Replace all options. */
|
|
1031
|
+
setOptions(options) {
|
|
1032
|
+
this._options.splice(0, this._options.length, ...options);
|
|
1033
|
+
return this;
|
|
1034
|
+
}
|
|
1035
|
+
toJSON() {
|
|
1036
|
+
return {
|
|
1037
|
+
type: "select",
|
|
1038
|
+
customId: this._customId,
|
|
1039
|
+
placeholder: this._placeholder,
|
|
1040
|
+
disabled: this._disabled || void 0,
|
|
1041
|
+
options: [...this._options]
|
|
1042
|
+
};
|
|
1043
|
+
}
|
|
1044
|
+
};
|
|
1045
|
+
|
|
1046
|
+
// src/builders/ActionRowBuilder.ts
|
|
1047
|
+
var ActionRowBuilder = class {
|
|
1048
|
+
constructor() {
|
|
1049
|
+
this._components = [];
|
|
1050
|
+
}
|
|
1051
|
+
/** Add a single component (button or select menu). */
|
|
1052
|
+
addComponent(component) {
|
|
1053
|
+
this._components.push(component);
|
|
1054
|
+
return this;
|
|
1055
|
+
}
|
|
1056
|
+
/** Add multiple components at once. */
|
|
1057
|
+
addComponents(...components) {
|
|
1058
|
+
this._components.push(...components);
|
|
1059
|
+
return this;
|
|
1060
|
+
}
|
|
1061
|
+
/**
|
|
1062
|
+
* Serialise to a flat `MessageComponent[]` array — the format accepted by all API calls.
|
|
1063
|
+
*/
|
|
1064
|
+
toJSON() {
|
|
1065
|
+
return this._components.map((c) => c.toJSON());
|
|
1066
|
+
}
|
|
1067
|
+
};
|
|
1068
|
+
|
|
1069
|
+
// src/builders/ModalBuilder.ts
|
|
1070
|
+
var ModalBuilder = class {
|
|
1071
|
+
constructor() {
|
|
1072
|
+
this._title = "";
|
|
1073
|
+
this._customId = "";
|
|
1074
|
+
this._fields = [];
|
|
1075
|
+
}
|
|
1076
|
+
/** Title shown at the top of the modal dialog. */
|
|
1077
|
+
setTitle(title) {
|
|
1078
|
+
this._title = title;
|
|
1079
|
+
return this;
|
|
1080
|
+
}
|
|
1081
|
+
/** Custom ID passed back with the `MODAL_SUBMIT` interaction. */
|
|
1082
|
+
setCustomId(customId) {
|
|
1083
|
+
this._customId = customId;
|
|
1084
|
+
return this;
|
|
1085
|
+
}
|
|
1086
|
+
/** Add a single text-input field. */
|
|
1087
|
+
addField(field) {
|
|
1088
|
+
this._fields.push("toJSON" in field ? field.toJSON() : field);
|
|
1089
|
+
return this;
|
|
1090
|
+
}
|
|
1091
|
+
/** Add multiple fields at once. */
|
|
1092
|
+
addFields(...fields) {
|
|
1093
|
+
for (const f of fields) this.addField(f);
|
|
1094
|
+
return this;
|
|
1095
|
+
}
|
|
1096
|
+
toJSON() {
|
|
1097
|
+
if (!this._title) throw new Error("ModalBuilder: title is required \u2014 call .setTitle()");
|
|
1098
|
+
if (!this._customId) throw new Error("ModalBuilder: customId is required \u2014 call .setCustomId()");
|
|
1099
|
+
if (this._fields.length === 0) throw new Error("ModalBuilder: at least one field is required \u2014 call .addField()");
|
|
1100
|
+
return { title: this._title, customId: this._customId, fields: [...this._fields] };
|
|
1101
|
+
}
|
|
1102
|
+
};
|
|
1103
|
+
|
|
1104
|
+
// src/builders/TextInputBuilder.ts
|
|
1105
|
+
var TextInputBuilder = class {
|
|
1106
|
+
constructor() {
|
|
1107
|
+
this._data = {
|
|
1108
|
+
customId: "",
|
|
1109
|
+
label: "",
|
|
1110
|
+
type: "short"
|
|
1111
|
+
};
|
|
1112
|
+
}
|
|
1113
|
+
/** Unique ID for this field — the key in `interaction.modalData` on submit. */
|
|
1114
|
+
setCustomId(customId) {
|
|
1115
|
+
this._data.customId = customId;
|
|
1116
|
+
return this;
|
|
1117
|
+
}
|
|
1118
|
+
/** Label shown above the input inside the modal. */
|
|
1119
|
+
setLabel(label) {
|
|
1120
|
+
this._data.label = label;
|
|
1121
|
+
return this;
|
|
1122
|
+
}
|
|
1123
|
+
/**
|
|
1124
|
+
* Input style:
|
|
1125
|
+
* - `'short'` — single-line text input
|
|
1126
|
+
* - `'paragraph'` — multi-line textarea
|
|
1127
|
+
*/
|
|
1128
|
+
setStyle(style) {
|
|
1129
|
+
this._data.type = style;
|
|
1130
|
+
return this;
|
|
1131
|
+
}
|
|
1132
|
+
/** Greyed-out hint text shown when the field is empty. */
|
|
1133
|
+
setPlaceholder(placeholder) {
|
|
1134
|
+
this._data.placeholder = placeholder;
|
|
1135
|
+
return this;
|
|
1136
|
+
}
|
|
1137
|
+
/** Whether the user must fill in this field before submitting. */
|
|
1138
|
+
setRequired(required = true) {
|
|
1139
|
+
this._data.required = required;
|
|
1140
|
+
return this;
|
|
1141
|
+
}
|
|
1142
|
+
/** Minimum number of characters required. */
|
|
1143
|
+
setMinLength(min) {
|
|
1144
|
+
this._data.minLength = min;
|
|
1145
|
+
return this;
|
|
1146
|
+
}
|
|
1147
|
+
/** Maximum number of characters allowed. */
|
|
1148
|
+
setMaxLength(max) {
|
|
1149
|
+
this._data.maxLength = max;
|
|
1150
|
+
return this;
|
|
1151
|
+
}
|
|
1152
|
+
/** Pre-filled default value. */
|
|
1153
|
+
setValue(value) {
|
|
1154
|
+
this._data.value = value;
|
|
1155
|
+
return this;
|
|
1156
|
+
}
|
|
1157
|
+
toJSON() {
|
|
1158
|
+
return { ...this._data };
|
|
1159
|
+
}
|
|
1160
|
+
};
|
|
1161
|
+
|
|
1162
|
+
// src/builders/SlashCommandBuilder.ts
|
|
1163
|
+
var SlashCommandOptionBuilder = class {
|
|
1164
|
+
constructor(type) {
|
|
1165
|
+
this._data = { name: "", description: "", type };
|
|
1166
|
+
}
|
|
1167
|
+
/** Internal option name (lowercase, no spaces). Shown after `/command ` in the client UI. */
|
|
1168
|
+
setName(name) {
|
|
1169
|
+
this._data.name = name;
|
|
1170
|
+
return this;
|
|
1171
|
+
}
|
|
1172
|
+
/** Short human-readable description shown in the command picker. */
|
|
1173
|
+
setDescription(description) {
|
|
1174
|
+
this._data.description = description;
|
|
1175
|
+
return this;
|
|
1176
|
+
}
|
|
1177
|
+
/** Whether users must supply this option before sending the command. */
|
|
1178
|
+
setRequired(required = true) {
|
|
1179
|
+
this._data.required = required;
|
|
1180
|
+
return this;
|
|
1181
|
+
}
|
|
1182
|
+
/**
|
|
1183
|
+
* Restrict the option to specific values.
|
|
1184
|
+
* The picker will show these as autocomplete suggestions.
|
|
1185
|
+
*/
|
|
1186
|
+
addChoice(name, value) {
|
|
1187
|
+
if (!this._data.choices) this._data.choices = [];
|
|
1188
|
+
this._data.choices.push({ name, value });
|
|
1189
|
+
return this;
|
|
1190
|
+
}
|
|
1191
|
+
/** Set all allowed choices at once. */
|
|
1192
|
+
setChoices(choices) {
|
|
1193
|
+
this._data.choices = [...choices];
|
|
1194
|
+
return this;
|
|
1195
|
+
}
|
|
1196
|
+
toJSON() {
|
|
1197
|
+
return { ...this._data };
|
|
1198
|
+
}
|
|
1199
|
+
};
|
|
1200
|
+
var SlashCommandBuilder = class {
|
|
1201
|
+
constructor() {
|
|
1202
|
+
this._data = {
|
|
1203
|
+
name: "",
|
|
1204
|
+
description: "",
|
|
1205
|
+
options: []
|
|
1206
|
+
};
|
|
1207
|
+
}
|
|
1208
|
+
/** Command name — lowercase, no spaces (e.g. `'ban'`, `'server-info'`). */
|
|
1209
|
+
setName(name) {
|
|
1210
|
+
this._data.name = name;
|
|
1211
|
+
return this;
|
|
1212
|
+
}
|
|
1213
|
+
/** Short description shown in the command picker UI. */
|
|
1214
|
+
setDescription(description) {
|
|
1215
|
+
this._data.description = description;
|
|
1216
|
+
return this;
|
|
1217
|
+
}
|
|
1218
|
+
/** Add a text (string) option. */
|
|
1219
|
+
addStringOption(fn) {
|
|
1220
|
+
this._data.options.push(fn(new SlashCommandOptionBuilder("STRING")).toJSON());
|
|
1221
|
+
return this;
|
|
1222
|
+
}
|
|
1223
|
+
/** Add an integer (whole number) option. */
|
|
1224
|
+
addIntegerOption(fn) {
|
|
1225
|
+
this._data.options.push(fn(new SlashCommandOptionBuilder("INTEGER")).toJSON());
|
|
1226
|
+
return this;
|
|
1227
|
+
}
|
|
1228
|
+
/** Add a boolean (true/false) option. */
|
|
1229
|
+
addBooleanOption(fn) {
|
|
1230
|
+
this._data.options.push(fn(new SlashCommandOptionBuilder("BOOLEAN")).toJSON());
|
|
1231
|
+
return this;
|
|
1232
|
+
}
|
|
1233
|
+
/** Add a user-mention option (returns a user ID string). */
|
|
1234
|
+
addUserOption(fn) {
|
|
1235
|
+
this._data.options.push(fn(new SlashCommandOptionBuilder("USER")).toJSON());
|
|
1236
|
+
return this;
|
|
1237
|
+
}
|
|
1238
|
+
/** Add a channel-mention option (returns a channel ID string). */
|
|
1239
|
+
addChannelOption(fn) {
|
|
1240
|
+
this._data.options.push(fn(new SlashCommandOptionBuilder("CHANNEL")).toJSON());
|
|
1241
|
+
return this;
|
|
1242
|
+
}
|
|
1243
|
+
/** Add a role-mention option (returns a role ID string). */
|
|
1244
|
+
addRoleOption(fn) {
|
|
1245
|
+
this._data.options.push(fn(new SlashCommandOptionBuilder("ROLE")).toJSON());
|
|
1246
|
+
return this;
|
|
1247
|
+
}
|
|
1248
|
+
toJSON() {
|
|
1249
|
+
if (!this._data.name) throw new Error("SlashCommandBuilder: name is required \u2014 call .setName()");
|
|
1250
|
+
if (!this._data.description) throw new Error("SlashCommandBuilder: description is required \u2014 call .setDescription()");
|
|
1251
|
+
return { ...this._data, options: [...this._data.options ?? []] };
|
|
1252
|
+
}
|
|
1253
|
+
};
|
|
541
1254
|
// Annotate the CommonJS export names for ESM import in node:
|
|
542
1255
|
0 && (module.exports = {
|
|
1256
|
+
ActionRowBuilder,
|
|
1257
|
+
ButtonBuilder,
|
|
543
1258
|
CommandsAPI,
|
|
1259
|
+
EmbedBuilder,
|
|
544
1260
|
HttpClient,
|
|
1261
|
+
InteractionOptions,
|
|
545
1262
|
InteractionsAPI,
|
|
546
1263
|
MembersAPI,
|
|
547
1264
|
MessagesAPI,
|
|
1265
|
+
ModalBuilder,
|
|
548
1266
|
NovaClient,
|
|
1267
|
+
NovaInteraction,
|
|
549
1268
|
PermissionsAPI,
|
|
550
|
-
|
|
1269
|
+
SelectMenuBuilder,
|
|
1270
|
+
ServersAPI,
|
|
1271
|
+
SlashCommandBuilder,
|
|
1272
|
+
SlashCommandOptionBuilder,
|
|
1273
|
+
TextInputBuilder
|
|
551
1274
|
});
|