novaapp-sdk 1.0.7 → 1.0.10
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 +162 -2
- package/dist/index.d.ts +162 -2
- package/dist/index.js +135 -6
- package/dist/index.mjs +134 -6
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -128,12 +128,53 @@ interface Interaction {
|
|
|
128
128
|
commandName?: string | null;
|
|
129
129
|
customId?: string | null;
|
|
130
130
|
data?: unknown;
|
|
131
|
+
/** For SELECT_MENU interactions — the chosen option values. */
|
|
132
|
+
values?: string[];
|
|
133
|
+
/** For MODAL_SUBMIT interactions — field customId → submitted value. */
|
|
134
|
+
modalData?: Record<string, string>;
|
|
131
135
|
userId: string;
|
|
132
136
|
channelId: string;
|
|
133
137
|
serverId?: string | null;
|
|
134
138
|
triggerMsgId?: string | null;
|
|
135
139
|
createdAt: string;
|
|
136
140
|
}
|
|
141
|
+
/** A single text input field inside a bot modal. */
|
|
142
|
+
interface BotModalField {
|
|
143
|
+
/** Unique field ID — returned as key in `modalData` on MODAL_SUBMIT. */
|
|
144
|
+
customId: string;
|
|
145
|
+
/** Label displayed above the input. */
|
|
146
|
+
label: string;
|
|
147
|
+
/** `'short'` = single-line input, `'paragraph'` = multi-line textarea. */
|
|
148
|
+
type: 'short' | 'paragraph';
|
|
149
|
+
placeholder?: string;
|
|
150
|
+
required?: boolean;
|
|
151
|
+
minLength?: number;
|
|
152
|
+
maxLength?: number;
|
|
153
|
+
/** Optional pre-filled default value. */
|
|
154
|
+
value?: string;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Pass this as `modal` inside `client.interactions.respond()` to open a
|
|
158
|
+
* modal dialog on the user's client instead of sending a message.
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* await client.interactions.respond(interaction.id, {
|
|
162
|
+
* modal: {
|
|
163
|
+
* title: 'Submit a report',
|
|
164
|
+
* customId: 'report_modal',
|
|
165
|
+
* fields: [
|
|
166
|
+
* { customId: 'reason', label: 'Reason', type: 'paragraph', required: true },
|
|
167
|
+
* ],
|
|
168
|
+
* },
|
|
169
|
+
* })
|
|
170
|
+
*/
|
|
171
|
+
interface BotModalDefinition {
|
|
172
|
+
/** Title shown at the top of the modal dialog. */
|
|
173
|
+
title: string;
|
|
174
|
+
/** Custom ID passed back with the MODAL_SUBMIT interaction. */
|
|
175
|
+
customId: string;
|
|
176
|
+
fields: BotModalField[];
|
|
177
|
+
}
|
|
137
178
|
interface SlashCommandOption {
|
|
138
179
|
name: string;
|
|
139
180
|
description: string;
|
|
@@ -210,6 +251,11 @@ interface RespondInteractionOptions {
|
|
|
210
251
|
embed?: Embed;
|
|
211
252
|
components?: MessageComponent[];
|
|
212
253
|
ephemeral?: boolean;
|
|
254
|
+
/**
|
|
255
|
+
* Open a modal dialog on the user's client instead of sending a message.
|
|
256
|
+
* When set, all other fields are ignored.
|
|
257
|
+
*/
|
|
258
|
+
modal?: BotModalDefinition;
|
|
213
259
|
}
|
|
214
260
|
interface FetchMessagesOptions {
|
|
215
261
|
limit?: number;
|
|
@@ -222,6 +268,39 @@ interface PollInteractionsOptions {
|
|
|
222
268
|
limit?: number;
|
|
223
269
|
since?: string;
|
|
224
270
|
}
|
|
271
|
+
/** A raw permission record stored for a specific scope (server, role, or channel). */
|
|
272
|
+
interface BotPermissionRecord {
|
|
273
|
+
id: string;
|
|
274
|
+
botId: string;
|
|
275
|
+
serverId: string;
|
|
276
|
+
/** `null` means this record is server-wide (not channel-scoped). */
|
|
277
|
+
channelId: string | null;
|
|
278
|
+
/** `null` means this record applies to all roles. */
|
|
279
|
+
roleId: string | null;
|
|
280
|
+
/** Key-value map of permission name → granted flag. */
|
|
281
|
+
permissions: Record<string, boolean>;
|
|
282
|
+
createdAt: string;
|
|
283
|
+
updatedAt: string;
|
|
284
|
+
}
|
|
285
|
+
/** Response from `client.permissions.get()`. */
|
|
286
|
+
interface PermissionsResult {
|
|
287
|
+
/**
|
|
288
|
+
* Merged, effective permissions for the requested scope.
|
|
289
|
+
* Merging order (highest wins): channel > role > server-wide.
|
|
290
|
+
*/
|
|
291
|
+
permissions: Record<string, boolean>;
|
|
292
|
+
/** All raw permission records matching the query scope. */
|
|
293
|
+
records: BotPermissionRecord[];
|
|
294
|
+
}
|
|
295
|
+
/** Options accepted by `client.permissions.get()`. */
|
|
296
|
+
interface PermissionsQueryOptions {
|
|
297
|
+
/** The server to query permissions for (required). */
|
|
298
|
+
serverId: string;
|
|
299
|
+
/** Narrow the scope to a specific channel. */
|
|
300
|
+
channelId?: string;
|
|
301
|
+
/** Narrow the scope to a specific role. */
|
|
302
|
+
roleId?: string;
|
|
303
|
+
}
|
|
225
304
|
interface NovaClientOptions {
|
|
226
305
|
/** Your bot token — starts with "nova_bot_" */
|
|
227
306
|
token: string;
|
|
@@ -419,7 +498,8 @@ declare class ServersAPI {
|
|
|
419
498
|
|
|
420
499
|
declare class InteractionsAPI {
|
|
421
500
|
private readonly http;
|
|
422
|
-
|
|
501
|
+
private readonly emitter;
|
|
502
|
+
constructor(http: HttpClient, emitter: EventEmitter);
|
|
423
503
|
/**
|
|
424
504
|
* Acknowledge an interaction without sending a visible response.
|
|
425
505
|
* Shows a loading state to the user. You must follow up with `respond()`.
|
|
@@ -459,6 +539,84 @@ declare class InteractionsAPI {
|
|
|
459
539
|
* }
|
|
460
540
|
*/
|
|
461
541
|
poll(options?: PollInteractionsOptions): Promise<Interaction[]>;
|
|
542
|
+
/**
|
|
543
|
+
* Open a modal for the user who triggered an interaction and await their submission.
|
|
544
|
+
*
|
|
545
|
+
* Internally this:
|
|
546
|
+
* 1. Calls `respond(interactionId, { modal })` to push the modal to the client UI.
|
|
547
|
+
* 2. Listens for the next `interactionCreate` event whose type is `MODAL_SUBMIT`
|
|
548
|
+
* and whose `customId` matches your modal's `customId`.
|
|
549
|
+
* 3. Resolves with the submitted `Interaction` (containing `modalData`), or `null`
|
|
550
|
+
* if the user closes the modal without submitting within the timeout.
|
|
551
|
+
*
|
|
552
|
+
* @param interactionId - ID of the triggering interaction.
|
|
553
|
+
* @param modal - Modal definition (title, customId, fields).
|
|
554
|
+
* @param options.timeout - Max milliseconds to wait (default: 300 000 = 5 min).
|
|
555
|
+
*
|
|
556
|
+
* @example
|
|
557
|
+
* client.on('interactionCreate', async (interaction) => {
|
|
558
|
+
* if (interaction.commandName === 'report') {
|
|
559
|
+
* const submitted = await client.interactions.awaitModal(interaction.id, {
|
|
560
|
+
* title: 'Submit a report',
|
|
561
|
+
* customId: 'report_modal',
|
|
562
|
+
* fields: [
|
|
563
|
+
* { customId: 'reason', label: 'Reason', type: 'paragraph', required: true, maxLength: 500 },
|
|
564
|
+
* ],
|
|
565
|
+
* })
|
|
566
|
+
*
|
|
567
|
+
* if (!submitted) {
|
|
568
|
+
* // User dismissed the modal or timed out — nothing to do
|
|
569
|
+
* return
|
|
570
|
+
* }
|
|
571
|
+
*
|
|
572
|
+
* const reason = submitted.modalData?.reason
|
|
573
|
+
* await client.interactions.respond(submitted.id, {
|
|
574
|
+
* content: `Report received: ${reason}`,
|
|
575
|
+
* ephemeral: true,
|
|
576
|
+
* })
|
|
577
|
+
* }
|
|
578
|
+
* })
|
|
579
|
+
*/
|
|
580
|
+
awaitModal(interactionId: string, modal: BotModalDefinition, options?: {
|
|
581
|
+
timeout?: number;
|
|
582
|
+
}): Promise<Interaction | null>;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
declare class PermissionsAPI {
|
|
586
|
+
private readonly http;
|
|
587
|
+
constructor(http: HttpClient);
|
|
588
|
+
/**
|
|
589
|
+
* Fetch the bot's effective permissions for a given scope.
|
|
590
|
+
*
|
|
591
|
+
* Permissions are merged in priority order:
|
|
592
|
+
* 1. Server-wide base permissions
|
|
593
|
+
* 2. Role override (if `roleId` provided)
|
|
594
|
+
* 3. Channel override (if `channelId` provided, highest priority)
|
|
595
|
+
*
|
|
596
|
+
* `serverId` is required. `channelId` and `roleId` are optional filters.
|
|
597
|
+
*
|
|
598
|
+
* @example
|
|
599
|
+
* // Effective server-wide permissions
|
|
600
|
+
* const { permissions } = await client.permissions.get({
|
|
601
|
+
* serverId: 'server-id',
|
|
602
|
+
* })
|
|
603
|
+
* console.log(permissions) // { kick_members: true, ban_members: false, ... }
|
|
604
|
+
*
|
|
605
|
+
* @example
|
|
606
|
+
* // Scoped to a specific channel
|
|
607
|
+
* const { permissions } = await client.permissions.get({
|
|
608
|
+
* serverId: 'server-id',
|
|
609
|
+
* channelId: 'channel-id',
|
|
610
|
+
* })
|
|
611
|
+
*
|
|
612
|
+
* @example
|
|
613
|
+
* // Scoped to a specific role
|
|
614
|
+
* const { permissions } = await client.permissions.get({
|
|
615
|
+
* serverId: 'server-id',
|
|
616
|
+
* roleId: 'role-id',
|
|
617
|
+
* })
|
|
618
|
+
*/
|
|
619
|
+
get(options: PermissionsQueryOptions): Promise<PermissionsResult>;
|
|
462
620
|
}
|
|
463
621
|
|
|
464
622
|
/**
|
|
@@ -494,6 +652,8 @@ declare class NovaClient extends EventEmitter {
|
|
|
494
652
|
readonly servers: ServersAPI;
|
|
495
653
|
/** Acknowledge and respond to interactions. */
|
|
496
654
|
readonly interactions: InteractionsAPI;
|
|
655
|
+
/** Query the bot's effective permissions within a server, channel, or role scope. */
|
|
656
|
+
readonly permissions: PermissionsAPI;
|
|
497
657
|
private socket;
|
|
498
658
|
private readonly http;
|
|
499
659
|
private readonly options;
|
|
@@ -536,4 +696,4 @@ declare class NovaClient extends EventEmitter {
|
|
|
536
696
|
emit(event: string | symbol, ...args: unknown[]): boolean;
|
|
537
697
|
}
|
|
538
698
|
|
|
539
|
-
export { type Attachment, type BotApplication, type BotEvent, type BotEventType, type BotUser, CommandsAPI, type ContextCommandDefinition, type EditMessageOptions, type Embed, type EmbedField, type FetchMembersOptions, type FetchMessagesOptions, HttpClient, type Interaction, type InteractionType, InteractionsAPI, type Member, MembersAPI, type Message, type MessageComponent, MessagesAPI, NovaClient, type NovaClientEvents, type NovaClientOptions, type NovaServer, type PollInteractionsOptions, type PrefixCommandDefinition, type Reaction, type RegisteredContextCommand, type RegisteredPrefixCommand, type RegisteredSlashCommand, type RespondInteractionOptions, type SendMessageOptions, ServersAPI, type SlashCommandDefinition, type SlashCommandOption };
|
|
699
|
+
export { type Attachment, type BotApplication, type BotEvent, type BotEventType, type BotModalDefinition, type BotModalField, type BotPermissionRecord, type BotUser, CommandsAPI, type ContextCommandDefinition, type EditMessageOptions, type Embed, type EmbedField, type FetchMembersOptions, type FetchMessagesOptions, HttpClient, type Interaction, type InteractionType, InteractionsAPI, type Member, MembersAPI, type Message, type MessageComponent, MessagesAPI, NovaClient, type NovaClientEvents, type NovaClientOptions, type NovaServer, PermissionsAPI, type PermissionsQueryOptions, type PermissionsResult, type PollInteractionsOptions, type PrefixCommandDefinition, type Reaction, type RegisteredContextCommand, type RegisteredPrefixCommand, type RegisteredSlashCommand, type RespondInteractionOptions, type SendMessageOptions, ServersAPI, type SlashCommandDefinition, type SlashCommandOption };
|
package/dist/index.d.ts
CHANGED
|
@@ -128,12 +128,53 @@ interface Interaction {
|
|
|
128
128
|
commandName?: string | null;
|
|
129
129
|
customId?: string | null;
|
|
130
130
|
data?: unknown;
|
|
131
|
+
/** For SELECT_MENU interactions — the chosen option values. */
|
|
132
|
+
values?: string[];
|
|
133
|
+
/** For MODAL_SUBMIT interactions — field customId → submitted value. */
|
|
134
|
+
modalData?: Record<string, string>;
|
|
131
135
|
userId: string;
|
|
132
136
|
channelId: string;
|
|
133
137
|
serverId?: string | null;
|
|
134
138
|
triggerMsgId?: string | null;
|
|
135
139
|
createdAt: string;
|
|
136
140
|
}
|
|
141
|
+
/** A single text input field inside a bot modal. */
|
|
142
|
+
interface BotModalField {
|
|
143
|
+
/** Unique field ID — returned as key in `modalData` on MODAL_SUBMIT. */
|
|
144
|
+
customId: string;
|
|
145
|
+
/** Label displayed above the input. */
|
|
146
|
+
label: string;
|
|
147
|
+
/** `'short'` = single-line input, `'paragraph'` = multi-line textarea. */
|
|
148
|
+
type: 'short' | 'paragraph';
|
|
149
|
+
placeholder?: string;
|
|
150
|
+
required?: boolean;
|
|
151
|
+
minLength?: number;
|
|
152
|
+
maxLength?: number;
|
|
153
|
+
/** Optional pre-filled default value. */
|
|
154
|
+
value?: string;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Pass this as `modal` inside `client.interactions.respond()` to open a
|
|
158
|
+
* modal dialog on the user's client instead of sending a message.
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* await client.interactions.respond(interaction.id, {
|
|
162
|
+
* modal: {
|
|
163
|
+
* title: 'Submit a report',
|
|
164
|
+
* customId: 'report_modal',
|
|
165
|
+
* fields: [
|
|
166
|
+
* { customId: 'reason', label: 'Reason', type: 'paragraph', required: true },
|
|
167
|
+
* ],
|
|
168
|
+
* },
|
|
169
|
+
* })
|
|
170
|
+
*/
|
|
171
|
+
interface BotModalDefinition {
|
|
172
|
+
/** Title shown at the top of the modal dialog. */
|
|
173
|
+
title: string;
|
|
174
|
+
/** Custom ID passed back with the MODAL_SUBMIT interaction. */
|
|
175
|
+
customId: string;
|
|
176
|
+
fields: BotModalField[];
|
|
177
|
+
}
|
|
137
178
|
interface SlashCommandOption {
|
|
138
179
|
name: string;
|
|
139
180
|
description: string;
|
|
@@ -210,6 +251,11 @@ interface RespondInteractionOptions {
|
|
|
210
251
|
embed?: Embed;
|
|
211
252
|
components?: MessageComponent[];
|
|
212
253
|
ephemeral?: boolean;
|
|
254
|
+
/**
|
|
255
|
+
* Open a modal dialog on the user's client instead of sending a message.
|
|
256
|
+
* When set, all other fields are ignored.
|
|
257
|
+
*/
|
|
258
|
+
modal?: BotModalDefinition;
|
|
213
259
|
}
|
|
214
260
|
interface FetchMessagesOptions {
|
|
215
261
|
limit?: number;
|
|
@@ -222,6 +268,39 @@ interface PollInteractionsOptions {
|
|
|
222
268
|
limit?: number;
|
|
223
269
|
since?: string;
|
|
224
270
|
}
|
|
271
|
+
/** A raw permission record stored for a specific scope (server, role, or channel). */
|
|
272
|
+
interface BotPermissionRecord {
|
|
273
|
+
id: string;
|
|
274
|
+
botId: string;
|
|
275
|
+
serverId: string;
|
|
276
|
+
/** `null` means this record is server-wide (not channel-scoped). */
|
|
277
|
+
channelId: string | null;
|
|
278
|
+
/** `null` means this record applies to all roles. */
|
|
279
|
+
roleId: string | null;
|
|
280
|
+
/** Key-value map of permission name → granted flag. */
|
|
281
|
+
permissions: Record<string, boolean>;
|
|
282
|
+
createdAt: string;
|
|
283
|
+
updatedAt: string;
|
|
284
|
+
}
|
|
285
|
+
/** Response from `client.permissions.get()`. */
|
|
286
|
+
interface PermissionsResult {
|
|
287
|
+
/**
|
|
288
|
+
* Merged, effective permissions for the requested scope.
|
|
289
|
+
* Merging order (highest wins): channel > role > server-wide.
|
|
290
|
+
*/
|
|
291
|
+
permissions: Record<string, boolean>;
|
|
292
|
+
/** All raw permission records matching the query scope. */
|
|
293
|
+
records: BotPermissionRecord[];
|
|
294
|
+
}
|
|
295
|
+
/** Options accepted by `client.permissions.get()`. */
|
|
296
|
+
interface PermissionsQueryOptions {
|
|
297
|
+
/** The server to query permissions for (required). */
|
|
298
|
+
serverId: string;
|
|
299
|
+
/** Narrow the scope to a specific channel. */
|
|
300
|
+
channelId?: string;
|
|
301
|
+
/** Narrow the scope to a specific role. */
|
|
302
|
+
roleId?: string;
|
|
303
|
+
}
|
|
225
304
|
interface NovaClientOptions {
|
|
226
305
|
/** Your bot token — starts with "nova_bot_" */
|
|
227
306
|
token: string;
|
|
@@ -419,7 +498,8 @@ declare class ServersAPI {
|
|
|
419
498
|
|
|
420
499
|
declare class InteractionsAPI {
|
|
421
500
|
private readonly http;
|
|
422
|
-
|
|
501
|
+
private readonly emitter;
|
|
502
|
+
constructor(http: HttpClient, emitter: EventEmitter);
|
|
423
503
|
/**
|
|
424
504
|
* Acknowledge an interaction without sending a visible response.
|
|
425
505
|
* Shows a loading state to the user. You must follow up with `respond()`.
|
|
@@ -459,6 +539,84 @@ declare class InteractionsAPI {
|
|
|
459
539
|
* }
|
|
460
540
|
*/
|
|
461
541
|
poll(options?: PollInteractionsOptions): Promise<Interaction[]>;
|
|
542
|
+
/**
|
|
543
|
+
* Open a modal for the user who triggered an interaction and await their submission.
|
|
544
|
+
*
|
|
545
|
+
* Internally this:
|
|
546
|
+
* 1. Calls `respond(interactionId, { modal })` to push the modal to the client UI.
|
|
547
|
+
* 2. Listens for the next `interactionCreate` event whose type is `MODAL_SUBMIT`
|
|
548
|
+
* and whose `customId` matches your modal's `customId`.
|
|
549
|
+
* 3. Resolves with the submitted `Interaction` (containing `modalData`), or `null`
|
|
550
|
+
* if the user closes the modal without submitting within the timeout.
|
|
551
|
+
*
|
|
552
|
+
* @param interactionId - ID of the triggering interaction.
|
|
553
|
+
* @param modal - Modal definition (title, customId, fields).
|
|
554
|
+
* @param options.timeout - Max milliseconds to wait (default: 300 000 = 5 min).
|
|
555
|
+
*
|
|
556
|
+
* @example
|
|
557
|
+
* client.on('interactionCreate', async (interaction) => {
|
|
558
|
+
* if (interaction.commandName === 'report') {
|
|
559
|
+
* const submitted = await client.interactions.awaitModal(interaction.id, {
|
|
560
|
+
* title: 'Submit a report',
|
|
561
|
+
* customId: 'report_modal',
|
|
562
|
+
* fields: [
|
|
563
|
+
* { customId: 'reason', label: 'Reason', type: 'paragraph', required: true, maxLength: 500 },
|
|
564
|
+
* ],
|
|
565
|
+
* })
|
|
566
|
+
*
|
|
567
|
+
* if (!submitted) {
|
|
568
|
+
* // User dismissed the modal or timed out — nothing to do
|
|
569
|
+
* return
|
|
570
|
+
* }
|
|
571
|
+
*
|
|
572
|
+
* const reason = submitted.modalData?.reason
|
|
573
|
+
* await client.interactions.respond(submitted.id, {
|
|
574
|
+
* content: `Report received: ${reason}`,
|
|
575
|
+
* ephemeral: true,
|
|
576
|
+
* })
|
|
577
|
+
* }
|
|
578
|
+
* })
|
|
579
|
+
*/
|
|
580
|
+
awaitModal(interactionId: string, modal: BotModalDefinition, options?: {
|
|
581
|
+
timeout?: number;
|
|
582
|
+
}): Promise<Interaction | null>;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
declare class PermissionsAPI {
|
|
586
|
+
private readonly http;
|
|
587
|
+
constructor(http: HttpClient);
|
|
588
|
+
/**
|
|
589
|
+
* Fetch the bot's effective permissions for a given scope.
|
|
590
|
+
*
|
|
591
|
+
* Permissions are merged in priority order:
|
|
592
|
+
* 1. Server-wide base permissions
|
|
593
|
+
* 2. Role override (if `roleId` provided)
|
|
594
|
+
* 3. Channel override (if `channelId` provided, highest priority)
|
|
595
|
+
*
|
|
596
|
+
* `serverId` is required. `channelId` and `roleId` are optional filters.
|
|
597
|
+
*
|
|
598
|
+
* @example
|
|
599
|
+
* // Effective server-wide permissions
|
|
600
|
+
* const { permissions } = await client.permissions.get({
|
|
601
|
+
* serverId: 'server-id',
|
|
602
|
+
* })
|
|
603
|
+
* console.log(permissions) // { kick_members: true, ban_members: false, ... }
|
|
604
|
+
*
|
|
605
|
+
* @example
|
|
606
|
+
* // Scoped to a specific channel
|
|
607
|
+
* const { permissions } = await client.permissions.get({
|
|
608
|
+
* serverId: 'server-id',
|
|
609
|
+
* channelId: 'channel-id',
|
|
610
|
+
* })
|
|
611
|
+
*
|
|
612
|
+
* @example
|
|
613
|
+
* // Scoped to a specific role
|
|
614
|
+
* const { permissions } = await client.permissions.get({
|
|
615
|
+
* serverId: 'server-id',
|
|
616
|
+
* roleId: 'role-id',
|
|
617
|
+
* })
|
|
618
|
+
*/
|
|
619
|
+
get(options: PermissionsQueryOptions): Promise<PermissionsResult>;
|
|
462
620
|
}
|
|
463
621
|
|
|
464
622
|
/**
|
|
@@ -494,6 +652,8 @@ declare class NovaClient extends EventEmitter {
|
|
|
494
652
|
readonly servers: ServersAPI;
|
|
495
653
|
/** Acknowledge and respond to interactions. */
|
|
496
654
|
readonly interactions: InteractionsAPI;
|
|
655
|
+
/** Query the bot's effective permissions within a server, channel, or role scope. */
|
|
656
|
+
readonly permissions: PermissionsAPI;
|
|
497
657
|
private socket;
|
|
498
658
|
private readonly http;
|
|
499
659
|
private readonly options;
|
|
@@ -536,4 +696,4 @@ declare class NovaClient extends EventEmitter {
|
|
|
536
696
|
emit(event: string | symbol, ...args: unknown[]): boolean;
|
|
537
697
|
}
|
|
538
698
|
|
|
539
|
-
export { type Attachment, type BotApplication, type BotEvent, type BotEventType, type BotUser, CommandsAPI, type ContextCommandDefinition, type EditMessageOptions, type Embed, type EmbedField, type FetchMembersOptions, type FetchMessagesOptions, HttpClient, type Interaction, type InteractionType, InteractionsAPI, type Member, MembersAPI, type Message, type MessageComponent, MessagesAPI, NovaClient, type NovaClientEvents, type NovaClientOptions, type NovaServer, type PollInteractionsOptions, type PrefixCommandDefinition, type Reaction, type RegisteredContextCommand, type RegisteredPrefixCommand, type RegisteredSlashCommand, type RespondInteractionOptions, type SendMessageOptions, ServersAPI, type SlashCommandDefinition, type SlashCommandOption };
|
|
699
|
+
export { type Attachment, type BotApplication, type BotEvent, type BotEventType, type BotModalDefinition, type BotModalField, type BotPermissionRecord, type BotUser, CommandsAPI, type ContextCommandDefinition, type EditMessageOptions, type Embed, type EmbedField, type FetchMembersOptions, type FetchMessagesOptions, HttpClient, type Interaction, type InteractionType, InteractionsAPI, type Member, MembersAPI, type Message, type MessageComponent, MessagesAPI, NovaClient, type NovaClientEvents, type NovaClientOptions, type NovaServer, PermissionsAPI, type PermissionsQueryOptions, type PermissionsResult, type PollInteractionsOptions, type PrefixCommandDefinition, type Reaction, type RegisteredContextCommand, type RegisteredPrefixCommand, type RegisteredSlashCommand, type RespondInteractionOptions, type SendMessageOptions, ServersAPI, type SlashCommandDefinition, type SlashCommandOption };
|
package/dist/index.js
CHANGED
|
@@ -26,6 +26,7 @@ __export(index_exports, {
|
|
|
26
26
|
MembersAPI: () => MembersAPI,
|
|
27
27
|
MessagesAPI: () => MessagesAPI,
|
|
28
28
|
NovaClient: () => NovaClient,
|
|
29
|
+
PermissionsAPI: () => PermissionsAPI,
|
|
29
30
|
ServersAPI: () => ServersAPI
|
|
30
31
|
});
|
|
31
32
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -272,8 +273,9 @@ var ServersAPI = class {
|
|
|
272
273
|
|
|
273
274
|
// src/api/interactions.ts
|
|
274
275
|
var InteractionsAPI = class {
|
|
275
|
-
constructor(http) {
|
|
276
|
+
constructor(http, emitter) {
|
|
276
277
|
this.http = http;
|
|
278
|
+
this.emitter = emitter;
|
|
277
279
|
}
|
|
278
280
|
/**
|
|
279
281
|
* Acknowledge an interaction without sending a visible response.
|
|
@@ -322,6 +324,115 @@ var InteractionsAPI = class {
|
|
|
322
324
|
const qs = params.toString();
|
|
323
325
|
return this.http.get(`/interactions${qs ? `?${qs}` : ""}`);
|
|
324
326
|
}
|
|
327
|
+
/**
|
|
328
|
+
* Open a modal for the user who triggered an interaction and await their submission.
|
|
329
|
+
*
|
|
330
|
+
* Internally this:
|
|
331
|
+
* 1. Calls `respond(interactionId, { modal })` to push the modal to the client UI.
|
|
332
|
+
* 2. Listens for the next `interactionCreate` event whose type is `MODAL_SUBMIT`
|
|
333
|
+
* and whose `customId` matches your modal's `customId`.
|
|
334
|
+
* 3. Resolves with the submitted `Interaction` (containing `modalData`), or `null`
|
|
335
|
+
* if the user closes the modal without submitting within the timeout.
|
|
336
|
+
*
|
|
337
|
+
* @param interactionId - ID of the triggering interaction.
|
|
338
|
+
* @param modal - Modal definition (title, customId, fields).
|
|
339
|
+
* @param options.timeout - Max milliseconds to wait (default: 300 000 = 5 min).
|
|
340
|
+
*
|
|
341
|
+
* @example
|
|
342
|
+
* client.on('interactionCreate', async (interaction) => {
|
|
343
|
+
* if (interaction.commandName === 'report') {
|
|
344
|
+
* const submitted = await client.interactions.awaitModal(interaction.id, {
|
|
345
|
+
* title: 'Submit a report',
|
|
346
|
+
* customId: 'report_modal',
|
|
347
|
+
* fields: [
|
|
348
|
+
* { customId: 'reason', label: 'Reason', type: 'paragraph', required: true, maxLength: 500 },
|
|
349
|
+
* ],
|
|
350
|
+
* })
|
|
351
|
+
*
|
|
352
|
+
* if (!submitted) {
|
|
353
|
+
* // User dismissed the modal or timed out — nothing to do
|
|
354
|
+
* return
|
|
355
|
+
* }
|
|
356
|
+
*
|
|
357
|
+
* const reason = submitted.modalData?.reason
|
|
358
|
+
* await client.interactions.respond(submitted.id, {
|
|
359
|
+
* content: `Report received: ${reason}`,
|
|
360
|
+
* ephemeral: true,
|
|
361
|
+
* })
|
|
362
|
+
* }
|
|
363
|
+
* })
|
|
364
|
+
*/
|
|
365
|
+
awaitModal(interactionId, modal, options = {}) {
|
|
366
|
+
const ms = options.timeout ?? 3e5;
|
|
367
|
+
let listener = null;
|
|
368
|
+
let timer = null;
|
|
369
|
+
const waitPromise = new Promise((resolve) => {
|
|
370
|
+
timer = setTimeout(() => {
|
|
371
|
+
if (listener) this.emitter.off("interactionCreate", listener);
|
|
372
|
+
resolve(null);
|
|
373
|
+
}, ms);
|
|
374
|
+
listener = (interaction) => {
|
|
375
|
+
if (interaction.type === "MODAL_SUBMIT" && interaction.customId === modal.customId) {
|
|
376
|
+
if (timer) clearTimeout(timer);
|
|
377
|
+
if (listener) this.emitter.off("interactionCreate", listener);
|
|
378
|
+
resolve(interaction);
|
|
379
|
+
}
|
|
380
|
+
};
|
|
381
|
+
this.emitter.on("interactionCreate", listener);
|
|
382
|
+
});
|
|
383
|
+
return this.respond(interactionId, { modal }).then(
|
|
384
|
+
() => waitPromise,
|
|
385
|
+
(err) => {
|
|
386
|
+
if (timer) clearTimeout(timer);
|
|
387
|
+
if (listener) this.emitter.off("interactionCreate", listener);
|
|
388
|
+
return Promise.reject(err);
|
|
389
|
+
}
|
|
390
|
+
);
|
|
391
|
+
}
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
// src/api/permissions.ts
|
|
395
|
+
var PermissionsAPI = class {
|
|
396
|
+
constructor(http) {
|
|
397
|
+
this.http = http;
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* Fetch the bot's effective permissions for a given scope.
|
|
401
|
+
*
|
|
402
|
+
* Permissions are merged in priority order:
|
|
403
|
+
* 1. Server-wide base permissions
|
|
404
|
+
* 2. Role override (if `roleId` provided)
|
|
405
|
+
* 3. Channel override (if `channelId` provided, highest priority)
|
|
406
|
+
*
|
|
407
|
+
* `serverId` is required. `channelId` and `roleId` are optional filters.
|
|
408
|
+
*
|
|
409
|
+
* @example
|
|
410
|
+
* // Effective server-wide permissions
|
|
411
|
+
* const { permissions } = await client.permissions.get({
|
|
412
|
+
* serverId: 'server-id',
|
|
413
|
+
* })
|
|
414
|
+
* console.log(permissions) // { kick_members: true, ban_members: false, ... }
|
|
415
|
+
*
|
|
416
|
+
* @example
|
|
417
|
+
* // Scoped to a specific channel
|
|
418
|
+
* const { permissions } = await client.permissions.get({
|
|
419
|
+
* serverId: 'server-id',
|
|
420
|
+
* channelId: 'channel-id',
|
|
421
|
+
* })
|
|
422
|
+
*
|
|
423
|
+
* @example
|
|
424
|
+
* // Scoped to a specific role
|
|
425
|
+
* const { permissions } = await client.permissions.get({
|
|
426
|
+
* serverId: 'server-id',
|
|
427
|
+
* roleId: 'role-id',
|
|
428
|
+
* })
|
|
429
|
+
*/
|
|
430
|
+
get(options) {
|
|
431
|
+
const params = new URLSearchParams({ serverId: options.serverId });
|
|
432
|
+
if (options.channelId) params.set("channelId", options.channelId);
|
|
433
|
+
if (options.roleId) params.set("roleId", options.roleId);
|
|
434
|
+
return this.http.get(`/permissions?${params.toString()}`);
|
|
435
|
+
}
|
|
325
436
|
};
|
|
326
437
|
|
|
327
438
|
// src/client.ts
|
|
@@ -356,11 +467,12 @@ var NovaClient = class extends import_node_events.EventEmitter {
|
|
|
356
467
|
this.commands = new CommandsAPI(this.http);
|
|
357
468
|
this.members = new MembersAPI(this.http);
|
|
358
469
|
this.servers = new ServersAPI(this.http);
|
|
359
|
-
this.interactions = new InteractionsAPI(this.http);
|
|
470
|
+
this.interactions = new InteractionsAPI(this.http, this);
|
|
471
|
+
this.permissions = new PermissionsAPI(this.http);
|
|
360
472
|
this.on("error", () => {
|
|
361
473
|
});
|
|
362
474
|
const cleanup = () => this.disconnect();
|
|
363
|
-
process.once("
|
|
475
|
+
process.once("beforeExit", cleanup);
|
|
364
476
|
process.once("SIGINT", () => {
|
|
365
477
|
cleanup();
|
|
366
478
|
process.exit(0);
|
|
@@ -430,12 +542,28 @@ var NovaClient = class extends import_node_events.EventEmitter {
|
|
|
430
542
|
*/
|
|
431
543
|
disconnect() {
|
|
432
544
|
if (this.socket) {
|
|
545
|
+
const sock = this.socket;
|
|
546
|
+
this.socket = null;
|
|
433
547
|
try {
|
|
434
|
-
|
|
548
|
+
sock.io.reconnection(false);
|
|
549
|
+
} catch {
|
|
550
|
+
}
|
|
551
|
+
try {
|
|
552
|
+
sock.io?.engine?.socket?.terminate?.();
|
|
553
|
+
} catch {
|
|
554
|
+
}
|
|
555
|
+
try {
|
|
556
|
+
sock.io?.engine?.socket?.destroy?.();
|
|
557
|
+
} catch {
|
|
558
|
+
}
|
|
559
|
+
try {
|
|
560
|
+
sock.io?.engine?.close?.();
|
|
561
|
+
} catch {
|
|
562
|
+
}
|
|
563
|
+
try {
|
|
564
|
+
sock.disconnect();
|
|
435
565
|
} catch {
|
|
436
566
|
}
|
|
437
|
-
this.socket.disconnect();
|
|
438
|
-
this.socket = null;
|
|
439
567
|
}
|
|
440
568
|
}
|
|
441
569
|
/**
|
|
@@ -484,5 +612,6 @@ var NovaClient = class extends import_node_events.EventEmitter {
|
|
|
484
612
|
MembersAPI,
|
|
485
613
|
MessagesAPI,
|
|
486
614
|
NovaClient,
|
|
615
|
+
PermissionsAPI,
|
|
487
616
|
ServersAPI
|
|
488
617
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -240,8 +240,9 @@ var ServersAPI = class {
|
|
|
240
240
|
|
|
241
241
|
// src/api/interactions.ts
|
|
242
242
|
var InteractionsAPI = class {
|
|
243
|
-
constructor(http) {
|
|
243
|
+
constructor(http, emitter) {
|
|
244
244
|
this.http = http;
|
|
245
|
+
this.emitter = emitter;
|
|
245
246
|
}
|
|
246
247
|
/**
|
|
247
248
|
* Acknowledge an interaction without sending a visible response.
|
|
@@ -290,6 +291,115 @@ var InteractionsAPI = class {
|
|
|
290
291
|
const qs = params.toString();
|
|
291
292
|
return this.http.get(`/interactions${qs ? `?${qs}` : ""}`);
|
|
292
293
|
}
|
|
294
|
+
/**
|
|
295
|
+
* Open a modal for the user who triggered an interaction and await their submission.
|
|
296
|
+
*
|
|
297
|
+
* Internally this:
|
|
298
|
+
* 1. Calls `respond(interactionId, { modal })` to push the modal to the client UI.
|
|
299
|
+
* 2. Listens for the next `interactionCreate` event whose type is `MODAL_SUBMIT`
|
|
300
|
+
* and whose `customId` matches your modal's `customId`.
|
|
301
|
+
* 3. Resolves with the submitted `Interaction` (containing `modalData`), or `null`
|
|
302
|
+
* if the user closes the modal without submitting within the timeout.
|
|
303
|
+
*
|
|
304
|
+
* @param interactionId - ID of the triggering interaction.
|
|
305
|
+
* @param modal - Modal definition (title, customId, fields).
|
|
306
|
+
* @param options.timeout - Max milliseconds to wait (default: 300 000 = 5 min).
|
|
307
|
+
*
|
|
308
|
+
* @example
|
|
309
|
+
* client.on('interactionCreate', async (interaction) => {
|
|
310
|
+
* if (interaction.commandName === 'report') {
|
|
311
|
+
* const submitted = await client.interactions.awaitModal(interaction.id, {
|
|
312
|
+
* title: 'Submit a report',
|
|
313
|
+
* customId: 'report_modal',
|
|
314
|
+
* fields: [
|
|
315
|
+
* { customId: 'reason', label: 'Reason', type: 'paragraph', required: true, maxLength: 500 },
|
|
316
|
+
* ],
|
|
317
|
+
* })
|
|
318
|
+
*
|
|
319
|
+
* if (!submitted) {
|
|
320
|
+
* // User dismissed the modal or timed out — nothing to do
|
|
321
|
+
* return
|
|
322
|
+
* }
|
|
323
|
+
*
|
|
324
|
+
* const reason = submitted.modalData?.reason
|
|
325
|
+
* await client.interactions.respond(submitted.id, {
|
|
326
|
+
* content: `Report received: ${reason}`,
|
|
327
|
+
* ephemeral: true,
|
|
328
|
+
* })
|
|
329
|
+
* }
|
|
330
|
+
* })
|
|
331
|
+
*/
|
|
332
|
+
awaitModal(interactionId, modal, options = {}) {
|
|
333
|
+
const ms = options.timeout ?? 3e5;
|
|
334
|
+
let listener = null;
|
|
335
|
+
let timer = null;
|
|
336
|
+
const waitPromise = new Promise((resolve) => {
|
|
337
|
+
timer = setTimeout(() => {
|
|
338
|
+
if (listener) this.emitter.off("interactionCreate", listener);
|
|
339
|
+
resolve(null);
|
|
340
|
+
}, ms);
|
|
341
|
+
listener = (interaction) => {
|
|
342
|
+
if (interaction.type === "MODAL_SUBMIT" && interaction.customId === modal.customId) {
|
|
343
|
+
if (timer) clearTimeout(timer);
|
|
344
|
+
if (listener) this.emitter.off("interactionCreate", listener);
|
|
345
|
+
resolve(interaction);
|
|
346
|
+
}
|
|
347
|
+
};
|
|
348
|
+
this.emitter.on("interactionCreate", listener);
|
|
349
|
+
});
|
|
350
|
+
return this.respond(interactionId, { modal }).then(
|
|
351
|
+
() => waitPromise,
|
|
352
|
+
(err) => {
|
|
353
|
+
if (timer) clearTimeout(timer);
|
|
354
|
+
if (listener) this.emitter.off("interactionCreate", listener);
|
|
355
|
+
return Promise.reject(err);
|
|
356
|
+
}
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
// src/api/permissions.ts
|
|
362
|
+
var PermissionsAPI = class {
|
|
363
|
+
constructor(http) {
|
|
364
|
+
this.http = http;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Fetch the bot's effective permissions for a given scope.
|
|
368
|
+
*
|
|
369
|
+
* Permissions are merged in priority order:
|
|
370
|
+
* 1. Server-wide base permissions
|
|
371
|
+
* 2. Role override (if `roleId` provided)
|
|
372
|
+
* 3. Channel override (if `channelId` provided, highest priority)
|
|
373
|
+
*
|
|
374
|
+
* `serverId` is required. `channelId` and `roleId` are optional filters.
|
|
375
|
+
*
|
|
376
|
+
* @example
|
|
377
|
+
* // Effective server-wide permissions
|
|
378
|
+
* const { permissions } = await client.permissions.get({
|
|
379
|
+
* serverId: 'server-id',
|
|
380
|
+
* })
|
|
381
|
+
* console.log(permissions) // { kick_members: true, ban_members: false, ... }
|
|
382
|
+
*
|
|
383
|
+
* @example
|
|
384
|
+
* // Scoped to a specific channel
|
|
385
|
+
* const { permissions } = await client.permissions.get({
|
|
386
|
+
* serverId: 'server-id',
|
|
387
|
+
* channelId: 'channel-id',
|
|
388
|
+
* })
|
|
389
|
+
*
|
|
390
|
+
* @example
|
|
391
|
+
* // Scoped to a specific role
|
|
392
|
+
* const { permissions } = await client.permissions.get({
|
|
393
|
+
* serverId: 'server-id',
|
|
394
|
+
* roleId: 'role-id',
|
|
395
|
+
* })
|
|
396
|
+
*/
|
|
397
|
+
get(options) {
|
|
398
|
+
const params = new URLSearchParams({ serverId: options.serverId });
|
|
399
|
+
if (options.channelId) params.set("channelId", options.channelId);
|
|
400
|
+
if (options.roleId) params.set("roleId", options.roleId);
|
|
401
|
+
return this.http.get(`/permissions?${params.toString()}`);
|
|
402
|
+
}
|
|
293
403
|
};
|
|
294
404
|
|
|
295
405
|
// src/client.ts
|
|
@@ -324,11 +434,12 @@ var NovaClient = class extends EventEmitter {
|
|
|
324
434
|
this.commands = new CommandsAPI(this.http);
|
|
325
435
|
this.members = new MembersAPI(this.http);
|
|
326
436
|
this.servers = new ServersAPI(this.http);
|
|
327
|
-
this.interactions = new InteractionsAPI(this.http);
|
|
437
|
+
this.interactions = new InteractionsAPI(this.http, this);
|
|
438
|
+
this.permissions = new PermissionsAPI(this.http);
|
|
328
439
|
this.on("error", () => {
|
|
329
440
|
});
|
|
330
441
|
const cleanup = () => this.disconnect();
|
|
331
|
-
process.once("
|
|
442
|
+
process.once("beforeExit", cleanup);
|
|
332
443
|
process.once("SIGINT", () => {
|
|
333
444
|
cleanup();
|
|
334
445
|
process.exit(0);
|
|
@@ -398,12 +509,28 @@ var NovaClient = class extends EventEmitter {
|
|
|
398
509
|
*/
|
|
399
510
|
disconnect() {
|
|
400
511
|
if (this.socket) {
|
|
512
|
+
const sock = this.socket;
|
|
513
|
+
this.socket = null;
|
|
401
514
|
try {
|
|
402
|
-
|
|
515
|
+
sock.io.reconnection(false);
|
|
516
|
+
} catch {
|
|
517
|
+
}
|
|
518
|
+
try {
|
|
519
|
+
sock.io?.engine?.socket?.terminate?.();
|
|
520
|
+
} catch {
|
|
521
|
+
}
|
|
522
|
+
try {
|
|
523
|
+
sock.io?.engine?.socket?.destroy?.();
|
|
524
|
+
} catch {
|
|
525
|
+
}
|
|
526
|
+
try {
|
|
527
|
+
sock.io?.engine?.close?.();
|
|
528
|
+
} catch {
|
|
529
|
+
}
|
|
530
|
+
try {
|
|
531
|
+
sock.disconnect();
|
|
403
532
|
} catch {
|
|
404
533
|
}
|
|
405
|
-
this.socket.disconnect();
|
|
406
|
-
this.socket = null;
|
|
407
534
|
}
|
|
408
535
|
}
|
|
409
536
|
/**
|
|
@@ -451,5 +578,6 @@ export {
|
|
|
451
578
|
MembersAPI,
|
|
452
579
|
MessagesAPI,
|
|
453
580
|
NovaClient,
|
|
581
|
+
PermissionsAPI,
|
|
454
582
|
ServersAPI
|
|
455
583
|
};
|