novaapp-sdk 1.0.10 → 1.2.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 +1627 -75
- package/dist/index.d.ts +1627 -75
- package/dist/index.js +1911 -146
- package/dist/index.mjs +1891 -145
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -60,6 +60,59 @@ interface Member {
|
|
|
60
60
|
isBot: boolean;
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
|
+
type ChannelType = 'TEXT' | 'VOICE' | 'ANNOUNCEMENT' | 'FORUM' | 'STAGE';
|
|
64
|
+
interface Channel {
|
|
65
|
+
id: string;
|
|
66
|
+
name: string;
|
|
67
|
+
type: ChannelType;
|
|
68
|
+
serverId: string | null;
|
|
69
|
+
topic: string | null;
|
|
70
|
+
position: number;
|
|
71
|
+
isNsfw: boolean;
|
|
72
|
+
slowMode: number | null;
|
|
73
|
+
createdAt: string;
|
|
74
|
+
}
|
|
75
|
+
interface Role {
|
|
76
|
+
id: string;
|
|
77
|
+
name: string;
|
|
78
|
+
color: string | null;
|
|
79
|
+
position: number;
|
|
80
|
+
serverId: string;
|
|
81
|
+
hoist: boolean;
|
|
82
|
+
permissions: Record<string, boolean>;
|
|
83
|
+
createdAt: string;
|
|
84
|
+
}
|
|
85
|
+
interface BanEntry {
|
|
86
|
+
userId: string;
|
|
87
|
+
username: string;
|
|
88
|
+
displayName: string;
|
|
89
|
+
avatar: string | null;
|
|
90
|
+
reason: string | null;
|
|
91
|
+
bannedAt: string;
|
|
92
|
+
moderatorId: string | null;
|
|
93
|
+
}
|
|
94
|
+
interface Invite {
|
|
95
|
+
code: string;
|
|
96
|
+
serverId: string;
|
|
97
|
+
creatorId: string;
|
|
98
|
+
uses: number;
|
|
99
|
+
maxUses: number | null;
|
|
100
|
+
expiresAt: string | null;
|
|
101
|
+
createdAt: string;
|
|
102
|
+
}
|
|
103
|
+
/** A message with all reaction data fetched. */
|
|
104
|
+
interface ReactionDetail {
|
|
105
|
+
emoji: string;
|
|
106
|
+
count: number;
|
|
107
|
+
users: Array<{
|
|
108
|
+
id: string;
|
|
109
|
+
username: string;
|
|
110
|
+
displayName: string;
|
|
111
|
+
avatar: string | null;
|
|
112
|
+
}>;
|
|
113
|
+
}
|
|
114
|
+
/** Bot status that can be set via `client.setStatus()`. */
|
|
115
|
+
type BotStatus = 'ONLINE' | 'IDLE' | 'DND' | 'OFFLINE';
|
|
63
116
|
interface Attachment {
|
|
64
117
|
id: string;
|
|
65
118
|
url: string;
|
|
@@ -80,25 +133,35 @@ interface EmbedField {
|
|
|
80
133
|
interface Embed {
|
|
81
134
|
title?: string;
|
|
82
135
|
description?: string;
|
|
136
|
+
/** Makes the title a clickable link. */
|
|
83
137
|
url?: string;
|
|
84
|
-
|
|
138
|
+
/** Hex colour string — e.g. `'#5865F2'`. */
|
|
139
|
+
color?: string;
|
|
85
140
|
thumbnail?: string;
|
|
86
141
|
image?: string;
|
|
87
142
|
footer?: string;
|
|
88
143
|
fields?: EmbedField[];
|
|
89
144
|
timestamp?: string;
|
|
145
|
+
author?: {
|
|
146
|
+
name: string;
|
|
147
|
+
iconUrl?: string;
|
|
148
|
+
};
|
|
90
149
|
}
|
|
91
150
|
interface MessageComponent {
|
|
92
151
|
type: 'button' | 'select';
|
|
93
|
-
customId
|
|
152
|
+
customId?: string;
|
|
94
153
|
label?: string;
|
|
95
|
-
style?: 'primary' | 'secondary' | 'success' | 'danger';
|
|
154
|
+
style?: 'primary' | 'secondary' | 'success' | 'danger' | 'link';
|
|
155
|
+
emoji?: string;
|
|
156
|
+
url?: string;
|
|
96
157
|
placeholder?: string;
|
|
97
158
|
options?: Array<{
|
|
98
159
|
label: string;
|
|
99
160
|
value: string;
|
|
100
161
|
description?: string;
|
|
101
162
|
}>;
|
|
163
|
+
minValues?: number;
|
|
164
|
+
maxValues?: number;
|
|
102
165
|
disabled?: boolean;
|
|
103
166
|
}
|
|
104
167
|
interface Message {
|
|
@@ -268,6 +331,24 @@ interface PollInteractionsOptions {
|
|
|
268
331
|
limit?: number;
|
|
269
332
|
since?: string;
|
|
270
333
|
}
|
|
334
|
+
interface CreateChannelOptions {
|
|
335
|
+
name: string;
|
|
336
|
+
type?: ChannelType;
|
|
337
|
+
topic?: string;
|
|
338
|
+
position?: number;
|
|
339
|
+
isNsfw?: boolean;
|
|
340
|
+
slowMode?: number;
|
|
341
|
+
}
|
|
342
|
+
interface EditChannelOptions {
|
|
343
|
+
name?: string;
|
|
344
|
+
topic?: string;
|
|
345
|
+
position?: number;
|
|
346
|
+
isNsfw?: boolean;
|
|
347
|
+
slowMode?: number;
|
|
348
|
+
}
|
|
349
|
+
interface FetchChannelsOptions {
|
|
350
|
+
type?: ChannelType;
|
|
351
|
+
}
|
|
271
352
|
/** A raw permission record stored for a specific scope (server, role, or channel). */
|
|
272
353
|
interface BotPermissionRecord {
|
|
273
354
|
id: string;
|
|
@@ -306,41 +387,10 @@ interface NovaClientOptions {
|
|
|
306
387
|
token: string;
|
|
307
388
|
/**
|
|
308
389
|
* Base URL of the Nova server.
|
|
309
|
-
* @default "https://
|
|
390
|
+
* @default "https://novachatapp.com"
|
|
310
391
|
*/
|
|
311
392
|
baseUrl?: string;
|
|
312
393
|
}
|
|
313
|
-
interface NovaClientEvents {
|
|
314
|
-
/** Fired when the bot successfully connects and is identified. */
|
|
315
|
-
ready: (bot: BotApplication) => void;
|
|
316
|
-
/** Fired for every bot:event from the gateway. */
|
|
317
|
-
event: (event: BotEvent) => void;
|
|
318
|
-
/** Fired when an interaction is created (slash command, button, etc.). */
|
|
319
|
-
interactionCreate: (interaction: Interaction) => void;
|
|
320
|
-
/** Fired when the gateway connection is lost. */
|
|
321
|
-
disconnect: (reason: string) => void;
|
|
322
|
-
/** Fired on gateway/API errors. */
|
|
323
|
-
error: (err: {
|
|
324
|
-
code: number;
|
|
325
|
-
message: string;
|
|
326
|
-
}) => void;
|
|
327
|
-
/** A message was sent in a channel the bot is in. */
|
|
328
|
-
messageCreate: (data: BotEvent['data']) => void;
|
|
329
|
-
/** A message was edited. */
|
|
330
|
-
messageUpdate: (data: BotEvent['data']) => void;
|
|
331
|
-
/** A message was deleted. */
|
|
332
|
-
messageDelete: (data: BotEvent['data']) => void;
|
|
333
|
-
/** A reaction was added to a message. */
|
|
334
|
-
reactionAdd: (data: BotEvent['data']) => void;
|
|
335
|
-
/** A reaction was removed from a message. */
|
|
336
|
-
reactionRemove: (data: BotEvent['data']) => void;
|
|
337
|
-
/** A user joined a server the bot is in. */
|
|
338
|
-
memberAdd: (data: BotEvent['data']) => void;
|
|
339
|
-
/** A user left a server the bot is in. */
|
|
340
|
-
memberRemove: (data: BotEvent['data']) => void;
|
|
341
|
-
/** A user started typing. */
|
|
342
|
-
typingStart: (data: BotEvent['data']) => void;
|
|
343
|
-
}
|
|
344
394
|
|
|
345
395
|
declare class MessagesAPI {
|
|
346
396
|
private readonly http;
|
|
@@ -375,6 +425,64 @@ declare class MessagesAPI {
|
|
|
375
425
|
typing(channelId: string): Promise<{
|
|
376
426
|
ok: true;
|
|
377
427
|
}>;
|
|
428
|
+
/**
|
|
429
|
+
* Fetch a single message by ID.
|
|
430
|
+
*
|
|
431
|
+
* @example
|
|
432
|
+
* const msg = await client.messages.fetchOne('message-id')
|
|
433
|
+
*/
|
|
434
|
+
fetchOne(messageId: string): Promise<Message>;
|
|
435
|
+
/**
|
|
436
|
+
* Pin a message in its channel.
|
|
437
|
+
* The bot must have the `messages.manage` scope.
|
|
438
|
+
*
|
|
439
|
+
* @example
|
|
440
|
+
* await client.messages.pin('message-id')
|
|
441
|
+
*/
|
|
442
|
+
pin(messageId: string): Promise<{
|
|
443
|
+
ok: true;
|
|
444
|
+
}>;
|
|
445
|
+
/**
|
|
446
|
+
* Unpin a message.
|
|
447
|
+
*
|
|
448
|
+
* @example
|
|
449
|
+
* await client.messages.unpin('message-id')
|
|
450
|
+
*/
|
|
451
|
+
unpin(messageId: string): Promise<{
|
|
452
|
+
ok: true;
|
|
453
|
+
}>;
|
|
454
|
+
/**
|
|
455
|
+
* Fetch all pinned messages in a channel.
|
|
456
|
+
*
|
|
457
|
+
* @example
|
|
458
|
+
* const pins = await client.messages.fetchPinned('channel-id')
|
|
459
|
+
*/
|
|
460
|
+
fetchPinned(channelId: string): Promise<Message[]>;
|
|
461
|
+
/**
|
|
462
|
+
* Add a reaction to a message.
|
|
463
|
+
*
|
|
464
|
+
* @example
|
|
465
|
+
* await client.messages.addReaction('message-id', '👍')
|
|
466
|
+
*/
|
|
467
|
+
addReaction(messageId: string, emoji: string): Promise<{
|
|
468
|
+
ok: true;
|
|
469
|
+
}>;
|
|
470
|
+
/**
|
|
471
|
+
* Remove the bot's reaction from a message.
|
|
472
|
+
*
|
|
473
|
+
* @example
|
|
474
|
+
* await client.messages.removeReaction('message-id', '👍')
|
|
475
|
+
*/
|
|
476
|
+
removeReaction(messageId: string, emoji: string): Promise<{
|
|
477
|
+
ok: true;
|
|
478
|
+
}>;
|
|
479
|
+
/**
|
|
480
|
+
* Fetch all reactions on a message.
|
|
481
|
+
*
|
|
482
|
+
* @example
|
|
483
|
+
* const reactions = await client.messages.fetchReactions('message-id')
|
|
484
|
+
*/
|
|
485
|
+
fetchReactions(messageId: string): Promise<ReactionDetail[]>;
|
|
378
486
|
}
|
|
379
487
|
|
|
380
488
|
declare class CommandsAPI {
|
|
@@ -481,6 +589,56 @@ declare class MembersAPI {
|
|
|
481
589
|
ban(serverId: string, userId: string, reason?: string): Promise<{
|
|
482
590
|
ok: true;
|
|
483
591
|
}>;
|
|
592
|
+
/**
|
|
593
|
+
* Unban a previously banned user.
|
|
594
|
+
* Requires the `members.ban` scope.
|
|
595
|
+
*
|
|
596
|
+
* @example
|
|
597
|
+
* await client.members.unban('server-id', 'user-id')
|
|
598
|
+
*/
|
|
599
|
+
unban(serverId: string, userId: string): Promise<{
|
|
600
|
+
ok: true;
|
|
601
|
+
}>;
|
|
602
|
+
/**
|
|
603
|
+
* Fetch the ban list for a server.
|
|
604
|
+
* Requires the `members.ban` scope.
|
|
605
|
+
*
|
|
606
|
+
* @example
|
|
607
|
+
* const bans = await client.members.listBans('server-id')
|
|
608
|
+
* for (const ban of bans) {
|
|
609
|
+
* console.log(`${ban.username} — ${ban.reason ?? 'No reason'}`)
|
|
610
|
+
* }
|
|
611
|
+
*/
|
|
612
|
+
listBans(serverId: string): Promise<BanEntry[]>;
|
|
613
|
+
/**
|
|
614
|
+
* Send a direct message to a user (DM).
|
|
615
|
+
* Requires the `messages.write` scope.
|
|
616
|
+
*
|
|
617
|
+
* @example
|
|
618
|
+
* await client.members.dm('user-id', { content: 'Hello!' })
|
|
619
|
+
* await client.members.dm('user-id', 'Hello from the bot!')
|
|
620
|
+
*/
|
|
621
|
+
dm(userId: string, options: string | Omit<SendMessageOptions, 'replyToId'>): Promise<Message>;
|
|
622
|
+
/**
|
|
623
|
+
* Add a role to a member.
|
|
624
|
+
* Requires the `members.roles` scope.
|
|
625
|
+
*
|
|
626
|
+
* @example
|
|
627
|
+
* await client.members.addRole('server-id', 'user-id', 'role-id')
|
|
628
|
+
*/
|
|
629
|
+
addRole(serverId: string, userId: string, roleId: string): Promise<{
|
|
630
|
+
ok: true;
|
|
631
|
+
}>;
|
|
632
|
+
/**
|
|
633
|
+
* Remove a role from a member.
|
|
634
|
+
* Requires the `members.roles` scope.
|
|
635
|
+
*
|
|
636
|
+
* @example
|
|
637
|
+
* await client.members.removeRole('server-id', 'user-id', 'role-id')
|
|
638
|
+
*/
|
|
639
|
+
removeRole(serverId: string, userId: string, roleId: string): Promise<{
|
|
640
|
+
ok: true;
|
|
641
|
+
}>;
|
|
484
642
|
}
|
|
485
643
|
|
|
486
644
|
declare class ServersAPI {
|
|
@@ -494,6 +652,15 @@ declare class ServersAPI {
|
|
|
494
652
|
* console.log(`Bot is in ${servers.length} servers`)
|
|
495
653
|
*/
|
|
496
654
|
list(): Promise<NovaServer[]>;
|
|
655
|
+
/**
|
|
656
|
+
* Fetch all roles in a server.
|
|
657
|
+
* Results are sorted by position (lowest first).
|
|
658
|
+
*
|
|
659
|
+
* @example
|
|
660
|
+
* const roles = await client.servers.listRoles('server-id')
|
|
661
|
+
* const adminRole = roles.find(r => r.name === 'Admin')
|
|
662
|
+
*/
|
|
663
|
+
listRoles(serverId: string): Promise<Role[]>;
|
|
497
664
|
}
|
|
498
665
|
|
|
499
666
|
declare class InteractionsAPI {
|
|
@@ -619,67 +786,742 @@ declare class PermissionsAPI {
|
|
|
619
786
|
get(options: PermissionsQueryOptions): Promise<PermissionsResult>;
|
|
620
787
|
}
|
|
621
788
|
|
|
789
|
+
declare class ChannelsAPI {
|
|
790
|
+
private readonly http;
|
|
791
|
+
constructor(http: HttpClient);
|
|
792
|
+
/**
|
|
793
|
+
* Fetch all channels in a server the bot is a member of.
|
|
794
|
+
*
|
|
795
|
+
* @example
|
|
796
|
+
* const channels = await client.channels.list('server-id')
|
|
797
|
+
* const textChannels = channels.filter(c => c.type === 'TEXT')
|
|
798
|
+
*/
|
|
799
|
+
list(serverId: string): Promise<Channel[]>;
|
|
800
|
+
/**
|
|
801
|
+
* Fetch a single channel by ID.
|
|
802
|
+
*
|
|
803
|
+
* @example
|
|
804
|
+
* const channel = await client.channels.fetch('channel-id')
|
|
805
|
+
* console.log(channel.name, channel.type)
|
|
806
|
+
*/
|
|
807
|
+
fetch(channelId: string): Promise<Channel>;
|
|
808
|
+
/**
|
|
809
|
+
* Create a new channel in a server.
|
|
810
|
+
* Requires the `channels.manage` scope.
|
|
811
|
+
*
|
|
812
|
+
* @example
|
|
813
|
+
* const channel = await client.channels.create('server-id', {
|
|
814
|
+
* name: 'announcements',
|
|
815
|
+
* type: 'ANNOUNCEMENT',
|
|
816
|
+
* topic: 'Official announcements only',
|
|
817
|
+
* })
|
|
818
|
+
*/
|
|
819
|
+
create(serverId: string, options: CreateChannelOptions): Promise<Channel>;
|
|
820
|
+
/**
|
|
821
|
+
* Edit an existing channel.
|
|
822
|
+
* Requires the `channels.manage` scope.
|
|
823
|
+
*
|
|
824
|
+
* @example
|
|
825
|
+
* await client.channels.edit('channel-id', { topic: 'New topic!' })
|
|
826
|
+
*/
|
|
827
|
+
edit(channelId: string, options: EditChannelOptions): Promise<Channel>;
|
|
828
|
+
/**
|
|
829
|
+
* Delete a channel.
|
|
830
|
+
* Requires the `channels.manage` scope.
|
|
831
|
+
*
|
|
832
|
+
* @example
|
|
833
|
+
* await client.channels.delete('channel-id')
|
|
834
|
+
*/
|
|
835
|
+
delete(channelId: string): Promise<{
|
|
836
|
+
ok: true;
|
|
837
|
+
}>;
|
|
838
|
+
/**
|
|
839
|
+
* Fetch messages from a channel.
|
|
840
|
+
*
|
|
841
|
+
* @example
|
|
842
|
+
* const messages = await client.channels.fetchMessages('channel-id', { limit: 50 })
|
|
843
|
+
*/
|
|
844
|
+
fetchMessages(channelId: string, options?: FetchMessagesOptions): Promise<Message[]>;
|
|
845
|
+
/**
|
|
846
|
+
* Fetch all pinned messages in a channel.
|
|
847
|
+
*
|
|
848
|
+
* @example
|
|
849
|
+
* const pins = await client.channels.fetchPins('channel-id')
|
|
850
|
+
*/
|
|
851
|
+
fetchPins(channelId: string): Promise<Message[]>;
|
|
852
|
+
/**
|
|
853
|
+
* Send a typing indicator in a channel.
|
|
854
|
+
* Displayed to users for ~5 seconds.
|
|
855
|
+
*
|
|
856
|
+
* @example
|
|
857
|
+
* await client.channels.startTyping('channel-id')
|
|
858
|
+
*/
|
|
859
|
+
startTyping(channelId: string): Promise<{
|
|
860
|
+
ok: true;
|
|
861
|
+
}>;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
declare class ReactionsAPI {
|
|
865
|
+
private readonly http;
|
|
866
|
+
constructor(http: HttpClient);
|
|
867
|
+
/**
|
|
868
|
+
* Add a reaction to a message.
|
|
869
|
+
* Use a plain emoji character or a custom emoji ID.
|
|
870
|
+
*
|
|
871
|
+
* @example
|
|
872
|
+
* await client.reactions.add('message-id', '👍')
|
|
873
|
+
* await client.reactions.add('message-id', '🎉')
|
|
874
|
+
*/
|
|
875
|
+
add(messageId: string, emoji: string): Promise<{
|
|
876
|
+
ok: true;
|
|
877
|
+
}>;
|
|
878
|
+
/**
|
|
879
|
+
* Remove the bot's reaction from a message.
|
|
880
|
+
*
|
|
881
|
+
* @example
|
|
882
|
+
* await client.reactions.remove('message-id', '👍')
|
|
883
|
+
*/
|
|
884
|
+
remove(messageId: string, emoji: string): Promise<{
|
|
885
|
+
ok: true;
|
|
886
|
+
}>;
|
|
887
|
+
/**
|
|
888
|
+
* Remove all reactions from a message.
|
|
889
|
+
* Requires the `messages.manage` scope.
|
|
890
|
+
*
|
|
891
|
+
* @example
|
|
892
|
+
* await client.reactions.removeAll('message-id')
|
|
893
|
+
*/
|
|
894
|
+
removeAll(messageId: string): Promise<{
|
|
895
|
+
ok: true;
|
|
896
|
+
}>;
|
|
897
|
+
/**
|
|
898
|
+
* Remove all reactions of a specific emoji from a message.
|
|
899
|
+
* Requires the `messages.manage` scope.
|
|
900
|
+
*
|
|
901
|
+
* @example
|
|
902
|
+
* await client.reactions.removeEmoji('message-id', '👍')
|
|
903
|
+
*/
|
|
904
|
+
removeEmoji(messageId: string, emoji: string): Promise<{
|
|
905
|
+
ok: true;
|
|
906
|
+
}>;
|
|
907
|
+
/**
|
|
908
|
+
* Fetch all reactions on a message, broken down by emoji.
|
|
909
|
+
*
|
|
910
|
+
* @example
|
|
911
|
+
* const reactions = await client.reactions.fetch('message-id')
|
|
912
|
+
* for (const r of reactions) {
|
|
913
|
+
* console.log(`${r.emoji} — ${r.count} reactions from ${r.users.map(u => u.username).join(', ')}`)
|
|
914
|
+
* }
|
|
915
|
+
*/
|
|
916
|
+
fetch(messageId: string): Promise<ReactionDetail[]>;
|
|
917
|
+
/**
|
|
918
|
+
* Fetch reactions for a specific emoji on a message.
|
|
919
|
+
*
|
|
920
|
+
* @example
|
|
921
|
+
* const detail = await client.reactions.fetchEmoji('message-id', '👍')
|
|
922
|
+
* console.log(`${detail.count} thumbs ups`)
|
|
923
|
+
*/
|
|
924
|
+
fetchEmoji(messageId: string, emoji: string): Promise<ReactionDetail>;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
type TextInputStyle = 'short' | 'paragraph';
|
|
622
928
|
/**
|
|
623
|
-
*
|
|
929
|
+
* Fluent builder for a single text-input field inside a modal.
|
|
624
930
|
*
|
|
625
931
|
* @example
|
|
626
|
-
*
|
|
932
|
+
* new TextInputBuilder()
|
|
933
|
+
* .setCustomId('reason')
|
|
934
|
+
* .setLabel('Reason')
|
|
935
|
+
* .setStyle('paragraph')
|
|
936
|
+
* .setPlaceholder('Describe the issue in detail…')
|
|
937
|
+
* .setRequired(true)
|
|
938
|
+
* .setMaxLength(1000)
|
|
939
|
+
*/
|
|
940
|
+
declare class TextInputBuilder {
|
|
941
|
+
private _data;
|
|
942
|
+
/** Unique ID for this field — the key in `interaction.modalData` on submit. */
|
|
943
|
+
setCustomId(customId: string): this;
|
|
944
|
+
/** Label shown above the input inside the modal. */
|
|
945
|
+
setLabel(label: string): this;
|
|
946
|
+
/**
|
|
947
|
+
* Input style:
|
|
948
|
+
* - `'short'` — single-line text input
|
|
949
|
+
* - `'paragraph'` — multi-line textarea
|
|
950
|
+
*/
|
|
951
|
+
setStyle(style: TextInputStyle): this;
|
|
952
|
+
/** Greyed-out hint text shown when the field is empty. */
|
|
953
|
+
setPlaceholder(placeholder: string): this;
|
|
954
|
+
/** Whether the user must fill in this field before submitting. */
|
|
955
|
+
setRequired(required?: boolean): this;
|
|
956
|
+
/** Minimum number of characters required. */
|
|
957
|
+
setMinLength(min: number): this;
|
|
958
|
+
/** Maximum number of characters allowed. */
|
|
959
|
+
setMaxLength(max: number): this;
|
|
960
|
+
/** Pre-filled default value. */
|
|
961
|
+
setValue(value: string): this;
|
|
962
|
+
toJSON(): BotModalField;
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
type FieldLike = TextInputBuilder | BotModalField;
|
|
966
|
+
/**
|
|
967
|
+
* Fluent builder for bot modal dialogs.
|
|
627
968
|
*
|
|
628
|
-
*
|
|
969
|
+
* @example
|
|
970
|
+
* const modal = new ModalBuilder()
|
|
971
|
+
* .setTitle('Submit a report')
|
|
972
|
+
* .setCustomId('report_modal')
|
|
973
|
+
* .addField(
|
|
974
|
+
* new TextInputBuilder()
|
|
975
|
+
* .setCustomId('reason')
|
|
976
|
+
* .setLabel('Reason')
|
|
977
|
+
* .setStyle('paragraph')
|
|
978
|
+
* .setRequired(true)
|
|
979
|
+
* .setMaxLength(1000)
|
|
980
|
+
* )
|
|
981
|
+
* .addField(
|
|
982
|
+
* new TextInputBuilder()
|
|
983
|
+
* .setCustomId('proof')
|
|
984
|
+
* .setLabel('Evidence (optional URL)')
|
|
985
|
+
* .setStyle('short')
|
|
986
|
+
* )
|
|
629
987
|
*
|
|
630
|
-
*
|
|
631
|
-
*
|
|
988
|
+
* const submitted = await interaction.openModal(modal)
|
|
989
|
+
* if (submitted) {
|
|
990
|
+
* const reason = submitted.modalData.reason
|
|
991
|
+
* }
|
|
992
|
+
*/
|
|
993
|
+
declare class ModalBuilder {
|
|
994
|
+
private _title;
|
|
995
|
+
private _customId;
|
|
996
|
+
private readonly _fields;
|
|
997
|
+
/** Title shown at the top of the modal dialog. */
|
|
998
|
+
setTitle(title: string): this;
|
|
999
|
+
/** Custom ID passed back with the `MODAL_SUBMIT` interaction. */
|
|
1000
|
+
setCustomId(customId: string): this;
|
|
1001
|
+
/** Add a single text-input field. */
|
|
1002
|
+
addField(field: FieldLike): this;
|
|
1003
|
+
/** Add multiple fields at once. */
|
|
1004
|
+
addFields(...fields: FieldLike[]): this;
|
|
1005
|
+
toJSON(): BotModalDefinition;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
/**
|
|
1009
|
+
* Typed accessor for slash- and prefix-command options.
|
|
1010
|
+
* Available via `interaction.options`.
|
|
1011
|
+
*
|
|
1012
|
+
* @example
|
|
1013
|
+
* client.command('ban', async (interaction) => {
|
|
1014
|
+
* const userId = interaction.options.getString('user', true)
|
|
1015
|
+
* const reason = interaction.options.getString('reason') ?? 'No reason given'
|
|
632
1016
|
* })
|
|
1017
|
+
*/
|
|
1018
|
+
declare class InteractionOptions {
|
|
1019
|
+
private readonly _map;
|
|
1020
|
+
constructor(data: unknown);
|
|
1021
|
+
/** Whether this option was supplied by the user. */
|
|
1022
|
+
has(name: string): boolean;
|
|
1023
|
+
/** @overload Required — never returns `null`. */
|
|
1024
|
+
getString(name: string, required: true): string;
|
|
1025
|
+
/** @overload Optional — returns `null` when not supplied. */
|
|
1026
|
+
getString(name: string, required?: false): string | null;
|
|
1027
|
+
/** @overload Required — never returns `null`. */
|
|
1028
|
+
getInteger(name: string, required: true): number;
|
|
1029
|
+
/** @overload Optional — returns `null` when not supplied. */
|
|
1030
|
+
getInteger(name: string, required?: false): number | null;
|
|
1031
|
+
/** @overload Required — never returns `null`. */
|
|
1032
|
+
getNumber(name: string, required: true): number;
|
|
1033
|
+
/** @overload Optional — returns `null` when not supplied. */
|
|
1034
|
+
getNumber(name: string, required?: false): number | null;
|
|
1035
|
+
/** Returns `true` or `false`, or `null` if not supplied. */
|
|
1036
|
+
getBoolean(name: string): boolean | null;
|
|
1037
|
+
/**
|
|
1038
|
+
* Returns the mentioned **user ID** string (type `USER` option).
|
|
1039
|
+
* @overload Required.
|
|
1040
|
+
*/
|
|
1041
|
+
getUser(name: string, required: true): string;
|
|
1042
|
+
getUser(name: string, required?: false): string | null;
|
|
1043
|
+
/**
|
|
1044
|
+
* Returns the mentioned **channel ID** string (type `CHANNEL` option).
|
|
1045
|
+
* @overload Required.
|
|
1046
|
+
*/
|
|
1047
|
+
getChannel(name: string, required: true): string;
|
|
1048
|
+
getChannel(name: string, required?: false): string | null;
|
|
1049
|
+
/**
|
|
1050
|
+
* Returns the mentioned **role ID** string (type `ROLE` option).
|
|
1051
|
+
* @overload Required.
|
|
1052
|
+
*/
|
|
1053
|
+
getRole(name: string, required: true): string;
|
|
1054
|
+
getRole(name: string, required?: false): string | null;
|
|
1055
|
+
}
|
|
1056
|
+
/**
|
|
1057
|
+
* Rich wrapper around a raw bot interaction.
|
|
1058
|
+
* Returned by `interactionCreate`, `client.command()`, `client.button()`, `client.selectMenu()`.
|
|
633
1059
|
*
|
|
1060
|
+
* @example
|
|
634
1061
|
* client.on('interactionCreate', async (interaction) => {
|
|
635
|
-
* if (interaction.commandName === 'ping') {
|
|
636
|
-
* await
|
|
1062
|
+
* if (interaction.isSlashCommand() && interaction.commandName === 'ping') {
|
|
1063
|
+
* await interaction.reply('Pong! 🏓')
|
|
637
1064
|
* }
|
|
638
1065
|
* })
|
|
639
1066
|
*
|
|
640
|
-
*
|
|
1067
|
+
* // Or use built-in routing:
|
|
1068
|
+
* client.command('ping', async (interaction) => {
|
|
1069
|
+
* await interaction.reply('Pong! 🏓')
|
|
1070
|
+
* })
|
|
641
1071
|
*/
|
|
642
|
-
declare class
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
/**
|
|
646
|
-
readonly
|
|
647
|
-
/**
|
|
648
|
-
readonly
|
|
649
|
-
/**
|
|
650
|
-
readonly
|
|
651
|
-
/**
|
|
652
|
-
readonly
|
|
653
|
-
/**
|
|
654
|
-
readonly
|
|
655
|
-
/**
|
|
656
|
-
readonly
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
1072
|
+
declare class NovaInteraction {
|
|
1073
|
+
private readonly _raw;
|
|
1074
|
+
private readonly _api;
|
|
1075
|
+
/** Unique interaction ID. */
|
|
1076
|
+
readonly id: string;
|
|
1077
|
+
/** Interaction type. Use type guards (`.isSlashCommand()` etc.) for narrowing. */
|
|
1078
|
+
readonly type: InteractionType;
|
|
1079
|
+
/** Command name — set for `SLASH_COMMAND` and `PREFIX_COMMAND` interactions. */
|
|
1080
|
+
readonly commandName: string | null;
|
|
1081
|
+
/** Component custom ID — set for `BUTTON_CLICK`, `SELECT_MENU`, and `MODAL_SUBMIT` interactions. */
|
|
1082
|
+
readonly customId: string | null;
|
|
1083
|
+
/** ID of the user who triggered this interaction. */
|
|
1084
|
+
readonly userId: string;
|
|
1085
|
+
/** ID of the channel where this interaction occurred. */
|
|
1086
|
+
readonly channelId: string;
|
|
1087
|
+
/** ID of the server where this interaction occurred (`null` in DMs). */
|
|
1088
|
+
readonly serverId: string | null;
|
|
1089
|
+
/** ID of the message that contained the button/select component (if any). */
|
|
1090
|
+
readonly triggerMsgId: string | null;
|
|
1091
|
+
/** Selected option values for `SELECT_MENU` interactions. */
|
|
1092
|
+
readonly values: string[];
|
|
661
1093
|
/**
|
|
662
|
-
*
|
|
663
|
-
*
|
|
1094
|
+
* Field values submitted in a `MODAL_SUBMIT` interaction.
|
|
1095
|
+
* Keys are the `customId`s of the `TextInputBuilder` fields.
|
|
664
1096
|
*
|
|
665
1097
|
* @example
|
|
666
|
-
*
|
|
1098
|
+
* const reason = interaction.modalData.reason
|
|
667
1099
|
*/
|
|
668
|
-
|
|
1100
|
+
readonly modalData: Record<string, string>;
|
|
1101
|
+
/** ISO timestamp of when the interaction was created. */
|
|
1102
|
+
readonly createdAt: string;
|
|
669
1103
|
/**
|
|
670
|
-
*
|
|
1104
|
+
* Typed accessor for slash/prefix command options.
|
|
1105
|
+
*
|
|
1106
|
+
* @example
|
|
1107
|
+
* const userId = interaction.options.getUser('user', true)
|
|
1108
|
+
* const reason = interaction.options.getString('reason') ?? 'No reason given'
|
|
671
1109
|
*/
|
|
672
|
-
|
|
1110
|
+
readonly options: InteractionOptions;
|
|
1111
|
+
constructor(_raw: Interaction, _api: InteractionsAPI);
|
|
1112
|
+
/** `true` when triggered by a `/slash` command. */
|
|
1113
|
+
isSlashCommand(): boolean;
|
|
1114
|
+
/** `true` when triggered by a `!prefix` command. */
|
|
1115
|
+
isPrefixCommand(): boolean;
|
|
1116
|
+
/** `true` for both slash and prefix commands. */
|
|
1117
|
+
isCommand(): boolean;
|
|
1118
|
+
/** `true` when a button component was clicked. */
|
|
1119
|
+
isButton(): boolean;
|
|
1120
|
+
/** `true` when a select-menu option was chosen. */
|
|
1121
|
+
isSelectMenu(): boolean;
|
|
1122
|
+
/** `true` when the user submitted a modal form. */
|
|
1123
|
+
isModalSubmit(): boolean;
|
|
1124
|
+
/** `true` during autocomplete suggestion requests. */
|
|
1125
|
+
isAutocomplete(): boolean;
|
|
1126
|
+
/** `true` when triggered via a context-menu command. */
|
|
1127
|
+
isContextMenu(): boolean;
|
|
673
1128
|
/**
|
|
674
|
-
*
|
|
675
|
-
*
|
|
1129
|
+
* Respond with a message.
|
|
1130
|
+
* Accepts a plain string or a full options object.
|
|
676
1131
|
*
|
|
677
1132
|
* @example
|
|
678
|
-
*
|
|
1133
|
+
* await interaction.reply('Pong! 🏓')
|
|
1134
|
+
* await interaction.reply({ content: 'Done!', ephemeral: true })
|
|
1135
|
+
* await interaction.reply({ embed: new EmbedBuilder().setTitle('Stats').toJSON() })
|
|
679
1136
|
*/
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
1137
|
+
reply(options: RespondInteractionOptions | string): Promise<Message | {
|
|
1138
|
+
ok: true;
|
|
1139
|
+
ephemeral: true;
|
|
1140
|
+
}>;
|
|
1141
|
+
/**
|
|
1142
|
+
* Respond with a message **only visible to the user** who triggered the interaction.
|
|
1143
|
+
*
|
|
1144
|
+
* @example
|
|
1145
|
+
* await interaction.replyEphemeral('Only you can see this!')
|
|
1146
|
+
*/
|
|
1147
|
+
replyEphemeral(options: string | Omit<RespondInteractionOptions, 'ephemeral'>): Promise<{
|
|
1148
|
+
ok: true;
|
|
1149
|
+
ephemeral: true;
|
|
1150
|
+
}>;
|
|
1151
|
+
/**
|
|
1152
|
+
* Acknowledge the interaction without sending a response yet.
|
|
1153
|
+
* Shows a loading indicator to the user.
|
|
1154
|
+
* Follow up with `interaction.editReply()` when you're done.
|
|
1155
|
+
*
|
|
1156
|
+
* @example
|
|
1157
|
+
* await interaction.defer()
|
|
1158
|
+
* const data = await fetchSomeSlow()
|
|
1159
|
+
* await interaction.editReply({ content: `Result: ${data}` })
|
|
1160
|
+
*/
|
|
1161
|
+
defer(): Promise<{
|
|
1162
|
+
ok: true;
|
|
1163
|
+
}>;
|
|
1164
|
+
/**
|
|
1165
|
+
* Edit the previous reply (e.g. after `defer()`).
|
|
1166
|
+
*
|
|
1167
|
+
* @example
|
|
1168
|
+
* await interaction.defer()
|
|
1169
|
+
* await interaction.editReply(`Done — processed ${count} items.`)
|
|
1170
|
+
*/
|
|
1171
|
+
editReply(options: RespondInteractionOptions | string): Promise<Message | {
|
|
1172
|
+
ok: true;
|
|
1173
|
+
ephemeral: true;
|
|
1174
|
+
}>;
|
|
1175
|
+
/**
|
|
1176
|
+
* Open a **modal dialog** and return the user's submission as a new `NovaInteraction`.
|
|
1177
|
+
* Returns `null` if the user closes the modal or the timeout expires (default: 5 min).
|
|
1178
|
+
*
|
|
1179
|
+
* **This is the recommended way to open modals.**
|
|
1180
|
+
*
|
|
1181
|
+
* @example
|
|
1182
|
+
* const submitted = await interaction.openModal(
|
|
1183
|
+
* new ModalBuilder()
|
|
1184
|
+
* .setTitle('Submit a report')
|
|
1185
|
+
* .setCustomId('report_modal')
|
|
1186
|
+
* .addField(
|
|
1187
|
+
* new TextInputBuilder()
|
|
1188
|
+
* .setCustomId('reason')
|
|
1189
|
+
* .setLabel('Reason')
|
|
1190
|
+
* .setStyle('paragraph')
|
|
1191
|
+
* .setRequired(true)
|
|
1192
|
+
* )
|
|
1193
|
+
* )
|
|
1194
|
+
*
|
|
1195
|
+
* if (!submitted) return // user dismissed or timed out
|
|
1196
|
+
*
|
|
1197
|
+
* const reason = submitted.modalData.reason
|
|
1198
|
+
* await submitted.replyEphemeral(`Report received: ${reason}`)
|
|
1199
|
+
*/
|
|
1200
|
+
openModal(modal: ModalBuilder | BotModalDefinition, options?: {
|
|
1201
|
+
timeout?: number;
|
|
1202
|
+
}): Promise<NovaInteraction | null>;
|
|
1203
|
+
/** Returns the raw interaction data from the gateway. */
|
|
1204
|
+
toJSON(): Interaction;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
/**
|
|
1208
|
+
* A rich wrapper around a raw `Message` with convenience methods.
|
|
1209
|
+
*
|
|
1210
|
+
* Returned by `client.on('messageCreate', ...)` and from message fetch calls.
|
|
1211
|
+
*
|
|
1212
|
+
* @example
|
|
1213
|
+
* client.on('messageCreate', async (msg) => {
|
|
1214
|
+
* if (msg.content.toLowerCase() === '!ping') {
|
|
1215
|
+
* await msg.reply('Pong! 🏓')
|
|
1216
|
+
* await msg.react('🏓')
|
|
1217
|
+
* }
|
|
1218
|
+
* })
|
|
1219
|
+
*/
|
|
1220
|
+
declare class NovaMessage {
|
|
1221
|
+
/** The raw message ID. */
|
|
1222
|
+
readonly id: string;
|
|
1223
|
+
/** The message text content. */
|
|
1224
|
+
readonly content: string;
|
|
1225
|
+
/** The channel this message was sent in. */
|
|
1226
|
+
readonly channelId: string;
|
|
1227
|
+
/** The author of the message. */
|
|
1228
|
+
readonly author: Message['author'];
|
|
1229
|
+
/** Embed attached to this message, if any. */
|
|
1230
|
+
readonly embed: Embed | null;
|
|
1231
|
+
/** Interactive components (buttons, selects) attached to this message. */
|
|
1232
|
+
readonly components: MessageComponent[];
|
|
1233
|
+
/** The message this is replying to, if any. */
|
|
1234
|
+
readonly replyToId: string | null;
|
|
1235
|
+
/** Uploaded file attachments. */
|
|
1236
|
+
readonly attachments: Attachment[];
|
|
1237
|
+
/** Reactions on this message. */
|
|
1238
|
+
readonly reactions: Reaction[];
|
|
1239
|
+
/** When the message was sent. */
|
|
1240
|
+
readonly createdAt: Date;
|
|
1241
|
+
/** When the message was last edited, or `null`. */
|
|
1242
|
+
readonly editedAt: Date | null;
|
|
1243
|
+
private readonly _messages;
|
|
1244
|
+
private readonly _reactions;
|
|
1245
|
+
constructor(raw: Message, messages: MessagesAPI, reactions: ReactionsAPI);
|
|
1246
|
+
/** Returns true if the message was sent by a bot. */
|
|
1247
|
+
isFromBot(): boolean;
|
|
1248
|
+
/** Returns true if the message has an embed. */
|
|
1249
|
+
hasEmbed(): boolean;
|
|
1250
|
+
/** Returns true if the message has interactive components. */
|
|
1251
|
+
hasComponents(): boolean;
|
|
1252
|
+
/** Returns true if the message has been edited. */
|
|
1253
|
+
isEdited(): boolean;
|
|
1254
|
+
/**
|
|
1255
|
+
* Add a reaction to this message.
|
|
1256
|
+
*
|
|
1257
|
+
* @example
|
|
1258
|
+
* await msg.react('👍')
|
|
1259
|
+
* await msg.react('🎉')
|
|
1260
|
+
*/
|
|
1261
|
+
react(emoji: string): Promise<{
|
|
1262
|
+
ok: true;
|
|
1263
|
+
}>;
|
|
1264
|
+
/**
|
|
1265
|
+
* Remove the bot's reaction from this message.
|
|
1266
|
+
*
|
|
1267
|
+
* @example
|
|
1268
|
+
* await msg.removeReaction('👍')
|
|
1269
|
+
*/
|
|
1270
|
+
removeReaction(emoji: string): Promise<{
|
|
1271
|
+
ok: true;
|
|
1272
|
+
}>;
|
|
1273
|
+
/**
|
|
1274
|
+
* Reply to this message.
|
|
1275
|
+
*
|
|
1276
|
+
* @example
|
|
1277
|
+
* await msg.reply('Got it!')
|
|
1278
|
+
* await msg.reply({ embed: new EmbedBuilder().setTitle('Result').toJSON() })
|
|
1279
|
+
*/
|
|
1280
|
+
reply(options: string | Omit<SendMessageOptions, 'replyToId'>): Promise<NovaMessage>;
|
|
1281
|
+
/**
|
|
1282
|
+
* Edit this message.
|
|
1283
|
+
* Only works if the bot is the author.
|
|
1284
|
+
*
|
|
1285
|
+
* @example
|
|
1286
|
+
* await msg.edit('Updated content')
|
|
1287
|
+
* await msg.edit({ content: 'Updated', embed: { title: 'New embed' } })
|
|
1288
|
+
*/
|
|
1289
|
+
edit(options: string | EditMessageOptions): Promise<NovaMessage>;
|
|
1290
|
+
/**
|
|
1291
|
+
* Delete this message.
|
|
1292
|
+
* Only works if the bot is the author.
|
|
1293
|
+
*
|
|
1294
|
+
* @example
|
|
1295
|
+
* await msg.delete()
|
|
1296
|
+
*/
|
|
1297
|
+
delete(): Promise<{
|
|
1298
|
+
ok: true;
|
|
1299
|
+
}>;
|
|
1300
|
+
/**
|
|
1301
|
+
* Pin this message in its channel.
|
|
1302
|
+
*
|
|
1303
|
+
* @example
|
|
1304
|
+
* await msg.pin()
|
|
1305
|
+
*/
|
|
1306
|
+
pin(): Promise<{
|
|
1307
|
+
ok: true;
|
|
1308
|
+
}>;
|
|
1309
|
+
/**
|
|
1310
|
+
* Unpin this message.
|
|
1311
|
+
*
|
|
1312
|
+
* @example
|
|
1313
|
+
* await msg.unpin()
|
|
1314
|
+
*/
|
|
1315
|
+
unpin(): Promise<{
|
|
1316
|
+
ok: true;
|
|
1317
|
+
}>;
|
|
1318
|
+
/**
|
|
1319
|
+
* Re-fetch the latest version of this message from the server.
|
|
1320
|
+
*
|
|
1321
|
+
* @example
|
|
1322
|
+
* const fresh = await msg.fetch()
|
|
1323
|
+
*/
|
|
1324
|
+
fetch(): Promise<NovaMessage>;
|
|
1325
|
+
/**
|
|
1326
|
+
* Get a URL to this message (deep link).
|
|
1327
|
+
*/
|
|
1328
|
+
get url(): string;
|
|
1329
|
+
/**
|
|
1330
|
+
* Return the raw message object.
|
|
1331
|
+
*/
|
|
1332
|
+
toJSON(): Message;
|
|
1333
|
+
toString(): string;
|
|
1334
|
+
}
|
|
1335
|
+
|
|
1336
|
+
interface NovaClientEvents {
|
|
1337
|
+
/** Fired when the bot connects and is identified by the gateway. */
|
|
1338
|
+
ready: (bot: BotApplication) => void;
|
|
1339
|
+
/** Fired for every raw `bot:event` from the gateway. */
|
|
1340
|
+
event: (event: BotEvent) => void;
|
|
1341
|
+
/**
|
|
1342
|
+
* Fired when an interaction is received (slash command, button click, etc.).
|
|
1343
|
+
* Use `client.command()`, `client.button()`, or `client.selectMenu()` for
|
|
1344
|
+
* convenient routing instead of handling everything here.
|
|
1345
|
+
*/
|
|
1346
|
+
interactionCreate: (interaction: NovaInteraction) => void;
|
|
1347
|
+
/** Fired when the WebSocket connection drops. */
|
|
1348
|
+
disconnect: (reason: string) => void;
|
|
1349
|
+
/** Fired on gateway / API errors. */
|
|
1350
|
+
error: (err: Error | {
|
|
1351
|
+
code: number;
|
|
1352
|
+
message: string;
|
|
1353
|
+
}) => void;
|
|
1354
|
+
/** A new message was sent in a channel the bot can see. */
|
|
1355
|
+
messageCreate: (message: NovaMessage) => void;
|
|
1356
|
+
/** A message was edited. Returns the updated message. */
|
|
1357
|
+
messageUpdate: (message: NovaMessage) => void;
|
|
1358
|
+
/** A message was deleted. Returns partial data. */
|
|
1359
|
+
messageDelete: (data: {
|
|
1360
|
+
id: string;
|
|
1361
|
+
channelId: string;
|
|
1362
|
+
}) => void;
|
|
1363
|
+
/** A reaction was added to a message. */
|
|
1364
|
+
reactionAdd: (data: {
|
|
1365
|
+
messageId: string;
|
|
1366
|
+
channelId: string;
|
|
1367
|
+
userId: string;
|
|
1368
|
+
emoji: string;
|
|
1369
|
+
}) => void;
|
|
1370
|
+
/** A reaction was removed from a message. */
|
|
1371
|
+
reactionRemove: (data: {
|
|
1372
|
+
messageId: string;
|
|
1373
|
+
channelId: string;
|
|
1374
|
+
userId: string;
|
|
1375
|
+
emoji: string;
|
|
1376
|
+
}) => void;
|
|
1377
|
+
/** A member joined a server the bot is in. */
|
|
1378
|
+
memberAdd: (data: {
|
|
1379
|
+
serverId: string;
|
|
1380
|
+
userId: string;
|
|
1381
|
+
username: string;
|
|
1382
|
+
}) => void;
|
|
1383
|
+
/** A member left a server the bot is in. */
|
|
1384
|
+
memberRemove: (data: {
|
|
1385
|
+
serverId: string;
|
|
1386
|
+
userId: string;
|
|
1387
|
+
}) => void;
|
|
1388
|
+
/** A user started typing in a channel. */
|
|
1389
|
+
typingStart: (data: {
|
|
1390
|
+
channelId: string;
|
|
1391
|
+
userId: string;
|
|
1392
|
+
}) => void;
|
|
1393
|
+
/** A message was pinned. */
|
|
1394
|
+
messagePinned: (data: {
|
|
1395
|
+
messageId: string;
|
|
1396
|
+
channelId: string;
|
|
1397
|
+
pinnedBy: string;
|
|
1398
|
+
}) => void;
|
|
1399
|
+
}
|
|
1400
|
+
/**
|
|
1401
|
+
* The main Nova bot client.
|
|
1402
|
+
*
|
|
1403
|
+
* @example
|
|
1404
|
+
* import { NovaClient } from 'nova-bot-sdk'
|
|
1405
|
+
*
|
|
1406
|
+
* const client = new NovaClient({ token: 'nova_bot_...' })
|
|
1407
|
+
*
|
|
1408
|
+
* client.on('ready', (bot) => {
|
|
1409
|
+
* console.log(`Logged in as ${bot.botUser.username}`)
|
|
1410
|
+
* })
|
|
1411
|
+
*
|
|
1412
|
+
* client.on('interactionCreate', async (interaction) => {
|
|
1413
|
+
* if (interaction.commandName === 'ping') {
|
|
1414
|
+
* await client.interactions.respond(interaction.id, { content: 'Pong!' })
|
|
1415
|
+
* }
|
|
1416
|
+
* })
|
|
1417
|
+
*
|
|
1418
|
+
* await client.connect()
|
|
1419
|
+
*/
|
|
1420
|
+
declare class NovaClient extends EventEmitter {
|
|
1421
|
+
/** The authenticated bot application. Available after `ready` fires. */
|
|
1422
|
+
botUser: BotApplication | null;
|
|
1423
|
+
/** Send, edit, delete and fetch messages. */
|
|
1424
|
+
readonly messages: MessagesAPI;
|
|
1425
|
+
/** Register and manage slash, prefix, and context menu commands. */
|
|
1426
|
+
readonly commands: CommandsAPI;
|
|
1427
|
+
/** List, kick and ban server members. */
|
|
1428
|
+
readonly members: MembersAPI;
|
|
1429
|
+
/** List servers the bot is a member of. */
|
|
1430
|
+
readonly servers: ServersAPI;
|
|
1431
|
+
/** Acknowledge and respond to interactions. */
|
|
1432
|
+
readonly interactions: InteractionsAPI;
|
|
1433
|
+
/** Query the bot's effective permissions within a server, channel, or role scope. */
|
|
1434
|
+
readonly permissions: PermissionsAPI;
|
|
1435
|
+
/** Create, edit, and delete channels; fetch pins and messages. */
|
|
1436
|
+
readonly channels: ChannelsAPI;
|
|
1437
|
+
/** Add, remove and fetch reactions on messages. */
|
|
1438
|
+
readonly reactions: ReactionsAPI;
|
|
1439
|
+
private socket;
|
|
1440
|
+
private readonly http;
|
|
1441
|
+
private readonly options;
|
|
1442
|
+
private _cronTimers;
|
|
1443
|
+
private readonly _commandHandlers;
|
|
1444
|
+
private readonly _buttonHandlers;
|
|
1445
|
+
private readonly _selectHandlers;
|
|
1446
|
+
constructor(options: NovaClientOptions);
|
|
1447
|
+
/**
|
|
1448
|
+
* Register a handler for a slash or prefix command by name.
|
|
1449
|
+
* Automatically routes `interactionCreate` events whose `commandName` matches.
|
|
1450
|
+
*
|
|
1451
|
+
* @example
|
|
1452
|
+
* client.command('ping', async (interaction) => {
|
|
1453
|
+
* await interaction.reply('Pong! 🏓')
|
|
1454
|
+
* })
|
|
1455
|
+
*/
|
|
1456
|
+
command(name: string, handler: (interaction: NovaInteraction) => unknown): this;
|
|
1457
|
+
/**
|
|
1458
|
+
* Register a handler for a button by its `customId`.
|
|
1459
|
+
*
|
|
1460
|
+
* @example
|
|
1461
|
+
* client.button('confirm_delete', async (interaction) => {
|
|
1462
|
+
* await interaction.replyEphemeral('Deleted.')
|
|
1463
|
+
* })
|
|
1464
|
+
*/
|
|
1465
|
+
button(customId: string, handler: (interaction: NovaInteraction) => unknown): this;
|
|
1466
|
+
/**
|
|
1467
|
+
* Register a handler for a select menu by its `customId`.
|
|
1468
|
+
*
|
|
1469
|
+
* @example
|
|
1470
|
+
* client.selectMenu('colour_pick', async (interaction) => {
|
|
1471
|
+
* const chosen = interaction.values[0]
|
|
1472
|
+
* await interaction.reply(`You picked: ${chosen}`)
|
|
1473
|
+
* })
|
|
1474
|
+
*/
|
|
1475
|
+
selectMenu(customId: string, handler: (interaction: NovaInteraction) => unknown): this;
|
|
1476
|
+
/**
|
|
1477
|
+
* Connect to the Nova WebSocket gateway.
|
|
1478
|
+
* Resolves when the `ready` event is received.
|
|
1479
|
+
*
|
|
1480
|
+
* @example
|
|
1481
|
+
* await client.connect()
|
|
1482
|
+
*/
|
|
1483
|
+
connect(): Promise<void>;
|
|
1484
|
+
/**
|
|
1485
|
+
* Register a recurring task that fires at a set interval.
|
|
1486
|
+
* All cron tasks are automatically cancelled on `disconnect()`.
|
|
1487
|
+
*
|
|
1488
|
+
* @param intervalMs - How often to run the task (in milliseconds).
|
|
1489
|
+
* @param fn - Async or sync function to call on each tick.
|
|
1490
|
+
* @returns A cancel function — call it to stop this specific task.
|
|
1491
|
+
*
|
|
1492
|
+
* @example
|
|
1493
|
+
* // Check for new announcements every 30 seconds
|
|
1494
|
+
* client.cron(30_000, async () => {
|
|
1495
|
+
* const messages = await client.messages.fetch(channelId, { limit: 5 })
|
|
1496
|
+
* // do something...
|
|
1497
|
+
* })
|
|
1498
|
+
*/
|
|
1499
|
+
cron(intervalMs: number, fn: () => unknown): () => void;
|
|
1500
|
+
/**
|
|
1501
|
+
* Set the bot's presence status.
|
|
1502
|
+
* Broadcasts to all servers the bot is in via WebSocket.
|
|
1503
|
+
*
|
|
1504
|
+
* @example
|
|
1505
|
+
* client.setStatus('DND') // Do Not Disturb
|
|
1506
|
+
* client.setStatus('IDLE') // Away
|
|
1507
|
+
* client.setStatus('OFFLINE') // Appear offline
|
|
1508
|
+
* client.setStatus('ONLINE') // Back online
|
|
1509
|
+
*/
|
|
1510
|
+
setStatus(status: BotStatus): void;
|
|
1511
|
+
/**
|
|
1512
|
+
* Disconnect from the gateway and clean up.
|
|
1513
|
+
*/
|
|
1514
|
+
disconnect(): void;
|
|
1515
|
+
/**
|
|
1516
|
+
* Send a message via the WebSocket gateway (lower latency than HTTP).
|
|
1517
|
+
* Requires the `messages.write` scope.
|
|
1518
|
+
*
|
|
1519
|
+
* @example
|
|
1520
|
+
* client.wsSend('channel-id', 'Hello from the gateway!')
|
|
1521
|
+
*/
|
|
1522
|
+
wsSend(channelId: string, content: string): void;
|
|
1523
|
+
/**
|
|
1524
|
+
* Start a typing indicator via WebSocket.
|
|
683
1525
|
*/
|
|
684
1526
|
wsTypingStart(channelId: string): void;
|
|
685
1527
|
/**
|
|
@@ -696,4 +1538,714 @@ declare class NovaClient extends EventEmitter {
|
|
|
696
1538
|
emit(event: string | symbol, ...args: unknown[]): boolean;
|
|
697
1539
|
}
|
|
698
1540
|
|
|
699
|
-
|
|
1541
|
+
/**
|
|
1542
|
+
* Fluent builder for bot message embeds.
|
|
1543
|
+
*
|
|
1544
|
+
* @example
|
|
1545
|
+
* const embed = new EmbedBuilder()
|
|
1546
|
+
* .setTitle('Server Stats')
|
|
1547
|
+
* .setDescription('Here are the latest numbers.')
|
|
1548
|
+
* .setColor('#5865F2')
|
|
1549
|
+
* .addField('Members', '1 234', true)
|
|
1550
|
+
* .addField('Messages today', '567', true)
|
|
1551
|
+
* .setFooter('Nova Bot')
|
|
1552
|
+
* .setTimestamp()
|
|
1553
|
+
*
|
|
1554
|
+
* await client.messages.send(channelId, { embed })
|
|
1555
|
+
*/
|
|
1556
|
+
declare class EmbedBuilder {
|
|
1557
|
+
private readonly _data;
|
|
1558
|
+
/** Set the embed title (shown in bold at the top). */
|
|
1559
|
+
setTitle(title: string): this;
|
|
1560
|
+
/** Set the main description text (supports markdown). */
|
|
1561
|
+
setDescription(description: string): this;
|
|
1562
|
+
/**
|
|
1563
|
+
* Set the accent colour.
|
|
1564
|
+
* @param color Hex string — e.g. `'#5865F2'` or `'5865F2'`
|
|
1565
|
+
*/
|
|
1566
|
+
setColor(color: string): this;
|
|
1567
|
+
/** Make the title a clickable hyperlink. */
|
|
1568
|
+
setUrl(url: string): this;
|
|
1569
|
+
/** Small image shown in the top-right corner. */
|
|
1570
|
+
setThumbnail(url: string): this;
|
|
1571
|
+
/** Large image shown below the fields. */
|
|
1572
|
+
setImage(url: string): this;
|
|
1573
|
+
/** Footer text shown at the very bottom of the embed. */
|
|
1574
|
+
setFooter(text: string): this;
|
|
1575
|
+
/**
|
|
1576
|
+
* Add a timestamp to the footer line.
|
|
1577
|
+
* @param date Defaults to `new Date()`.
|
|
1578
|
+
*/
|
|
1579
|
+
setTimestamp(date?: Date | number): this;
|
|
1580
|
+
/** Author name + optional icon shown above the title. */
|
|
1581
|
+
setAuthor(author: {
|
|
1582
|
+
name: string;
|
|
1583
|
+
iconUrl?: string;
|
|
1584
|
+
}): this;
|
|
1585
|
+
/**
|
|
1586
|
+
* Add a single field.
|
|
1587
|
+
* @param inline Pass `true` to render this field side-by-side with adjacent inline fields.
|
|
1588
|
+
*/
|
|
1589
|
+
addField(name: string, value: string, inline?: boolean): this;
|
|
1590
|
+
/** Add multiple fields at once. */
|
|
1591
|
+
addFields(...fields: EmbedField[]): this;
|
|
1592
|
+
/** Replace all fields. */
|
|
1593
|
+
setFields(fields: EmbedField[]): this;
|
|
1594
|
+
/** Serialise to a plain `Embed` object you can pass to any API call. */
|
|
1595
|
+
toJSON(): Embed;
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
type ButtonStyle = 'primary' | 'secondary' | 'success' | 'danger' | 'link';
|
|
1599
|
+
/**
|
|
1600
|
+
* Fluent builder for button components.
|
|
1601
|
+
*
|
|
1602
|
+
* @example
|
|
1603
|
+
* const row = new ActionRowBuilder()
|
|
1604
|
+
* .addButton(
|
|
1605
|
+
* new ButtonBuilder()
|
|
1606
|
+
* .setCustomId('confirm')
|
|
1607
|
+
* .setLabel('Confirm')
|
|
1608
|
+
* .setStyle('success')
|
|
1609
|
+
* )
|
|
1610
|
+
* .addButton(
|
|
1611
|
+
* new ButtonBuilder()
|
|
1612
|
+
* .setCustomId('cancel')
|
|
1613
|
+
* .setLabel('Cancel')
|
|
1614
|
+
* .setStyle('danger')
|
|
1615
|
+
* )
|
|
1616
|
+
*
|
|
1617
|
+
* await client.messages.send(channelId, { content: 'Are you sure?', components: row.toJSON() })
|
|
1618
|
+
*/
|
|
1619
|
+
declare class ButtonBuilder {
|
|
1620
|
+
private _customId;
|
|
1621
|
+
private _label;
|
|
1622
|
+
private _style;
|
|
1623
|
+
private _disabled;
|
|
1624
|
+
private _emoji?;
|
|
1625
|
+
private _url?;
|
|
1626
|
+
/** Custom ID returned in the `BUTTON_CLICK` interaction. Not required for `link` style buttons. */
|
|
1627
|
+
setCustomId(customId: string): this;
|
|
1628
|
+
/** Text displayed on the button. */
|
|
1629
|
+
setLabel(label: string): this;
|
|
1630
|
+
/**
|
|
1631
|
+
* Visual style:
|
|
1632
|
+
* - `primary` — blurple / brand colour
|
|
1633
|
+
* - `secondary` — grey
|
|
1634
|
+
* - `success` — green
|
|
1635
|
+
* - `danger` — red
|
|
1636
|
+
* - `link` — grey, navigates to a URL instead of creating an interaction
|
|
1637
|
+
*/
|
|
1638
|
+
setStyle(style: ButtonStyle): this;
|
|
1639
|
+
/** Emoji shown to the left of the label (unicode or custom e.g. `'👋'`). */
|
|
1640
|
+
setEmoji(emoji: string): this;
|
|
1641
|
+
/**
|
|
1642
|
+
* URL for `link` style buttons.
|
|
1643
|
+
* Sets the style to `'link'` automatically.
|
|
1644
|
+
*/
|
|
1645
|
+
setUrl(url: string): this;
|
|
1646
|
+
/** Prevent users from clicking the button. */
|
|
1647
|
+
setDisabled(disabled?: boolean): this;
|
|
1648
|
+
toJSON(): MessageComponent;
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
interface SelectMenuOption {
|
|
1652
|
+
/** Visible label shown to the user. */
|
|
1653
|
+
label: string;
|
|
1654
|
+
/** Value returned in the interaction's `values` array. */
|
|
1655
|
+
value: string;
|
|
1656
|
+
/** Optional description shown below the label. */
|
|
1657
|
+
description?: string;
|
|
1658
|
+
}
|
|
1659
|
+
/**
|
|
1660
|
+
* Fluent builder for select-menu (dropdown) components.
|
|
1661
|
+
*
|
|
1662
|
+
* @example
|
|
1663
|
+
* const menu = new SelectMenuBuilder()
|
|
1664
|
+
* .setCustomId('colour_pick')
|
|
1665
|
+
* .setPlaceholder('Pick a colour…')
|
|
1666
|
+
* .addOption({ label: 'Red', value: 'red' })
|
|
1667
|
+
* .addOption({ label: 'Green', value: 'green' })
|
|
1668
|
+
* .addOption({ label: 'Blue', value: 'blue' })
|
|
1669
|
+
*
|
|
1670
|
+
* await client.messages.send(channelId, { content: 'Choose:', components: [menu.toJSON()] })
|
|
1671
|
+
*/
|
|
1672
|
+
declare class SelectMenuBuilder {
|
|
1673
|
+
private _customId;
|
|
1674
|
+
private _placeholder?;
|
|
1675
|
+
private _disabled;
|
|
1676
|
+
private readonly _options;
|
|
1677
|
+
/** Custom ID returned in the `SELECT_MENU` interaction. */
|
|
1678
|
+
setCustomId(customId: string): this;
|
|
1679
|
+
/** Greyed-out hint shown when nothing is selected. */
|
|
1680
|
+
setPlaceholder(placeholder: string): this;
|
|
1681
|
+
/** Prevent users from interacting with the menu. */
|
|
1682
|
+
setDisabled(disabled?: boolean): this;
|
|
1683
|
+
/** Add a single option. */
|
|
1684
|
+
addOption(option: SelectMenuOption): this;
|
|
1685
|
+
/** Add multiple options at once. */
|
|
1686
|
+
addOptions(...options: SelectMenuOption[]): this;
|
|
1687
|
+
/** Replace all options. */
|
|
1688
|
+
setOptions(options: SelectMenuOption[]): this;
|
|
1689
|
+
toJSON(): MessageComponent;
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
type ComponentBuilder = ButtonBuilder | SelectMenuBuilder | {
|
|
1693
|
+
toJSON(): MessageComponent;
|
|
1694
|
+
};
|
|
1695
|
+
/**
|
|
1696
|
+
* Groups buttons (and/or a select menu) into a single row of components.
|
|
1697
|
+
*
|
|
1698
|
+
* @example
|
|
1699
|
+
* const row = new ActionRowBuilder()
|
|
1700
|
+
* .addComponent(new ButtonBuilder().setCustomId('yes').setLabel('Yes').setStyle('success'))
|
|
1701
|
+
* .addComponent(new ButtonBuilder().setCustomId('no').setLabel('No').setStyle('danger'))
|
|
1702
|
+
*
|
|
1703
|
+
* await interaction.reply({ content: 'Confirm?', components: row.toJSON() })
|
|
1704
|
+
*/
|
|
1705
|
+
declare class ActionRowBuilder {
|
|
1706
|
+
private readonly _components;
|
|
1707
|
+
/** Add a single component (button or select menu). */
|
|
1708
|
+
addComponent(component: ComponentBuilder): this;
|
|
1709
|
+
/** Add multiple components at once. */
|
|
1710
|
+
addComponents(...components: ComponentBuilder[]): this;
|
|
1711
|
+
/**
|
|
1712
|
+
* Serialise to a flat `MessageComponent[]` array — the format accepted by all API calls.
|
|
1713
|
+
*/
|
|
1714
|
+
toJSON(): MessageComponent[];
|
|
1715
|
+
}
|
|
1716
|
+
|
|
1717
|
+
/**
|
|
1718
|
+
* Fluent builder for a single slash command option (parameter).
|
|
1719
|
+
* Obtain one via the callback in `SlashCommandBuilder.addStringOption()` etc.
|
|
1720
|
+
*/
|
|
1721
|
+
declare class SlashCommandOptionBuilder {
|
|
1722
|
+
private _data;
|
|
1723
|
+
constructor(type: SlashCommandOption['type']);
|
|
1724
|
+
/** Internal option name (lowercase, no spaces). Shown after `/command ` in the client UI. */
|
|
1725
|
+
setName(name: string): this;
|
|
1726
|
+
/** Short human-readable description shown in the command picker. */
|
|
1727
|
+
setDescription(description: string): this;
|
|
1728
|
+
/** Whether users must supply this option before sending the command. */
|
|
1729
|
+
setRequired(required?: boolean): this;
|
|
1730
|
+
/**
|
|
1731
|
+
* Restrict the option to specific values.
|
|
1732
|
+
* The picker will show these as autocomplete suggestions.
|
|
1733
|
+
*/
|
|
1734
|
+
addChoice(name: string, value: string | number): this;
|
|
1735
|
+
/** Set all allowed choices at once. */
|
|
1736
|
+
setChoices(choices: Array<{
|
|
1737
|
+
name: string;
|
|
1738
|
+
value: string | number;
|
|
1739
|
+
}>): this;
|
|
1740
|
+
toJSON(): SlashCommandOption;
|
|
1741
|
+
}
|
|
1742
|
+
/**
|
|
1743
|
+
* Fluent builder for slash commands.
|
|
1744
|
+
*
|
|
1745
|
+
* @example
|
|
1746
|
+
* await client.commands.setSlash([
|
|
1747
|
+
* new SlashCommandBuilder()
|
|
1748
|
+
* .setName('ban')
|
|
1749
|
+
* .setDescription('Ban a member from this server')
|
|
1750
|
+
* .addUserOption((opt) =>
|
|
1751
|
+
* opt.setName('user').setDescription('Who to ban').setRequired(true)
|
|
1752
|
+
* )
|
|
1753
|
+
* .addStringOption((opt) =>
|
|
1754
|
+
* opt.setName('reason').setDescription('Reason for the ban')
|
|
1755
|
+
* )
|
|
1756
|
+
* .toJSON(),
|
|
1757
|
+
* ])
|
|
1758
|
+
*/
|
|
1759
|
+
declare class SlashCommandBuilder {
|
|
1760
|
+
private _data;
|
|
1761
|
+
/** Command name — lowercase, no spaces (e.g. `'ban'`, `'server-info'`). */
|
|
1762
|
+
setName(name: string): this;
|
|
1763
|
+
/** Short description shown in the command picker UI. */
|
|
1764
|
+
setDescription(description: string): this;
|
|
1765
|
+
/** Add a text (string) option. */
|
|
1766
|
+
addStringOption(fn: (opt: SlashCommandOptionBuilder) => SlashCommandOptionBuilder): this;
|
|
1767
|
+
/** Add an integer (whole number) option. */
|
|
1768
|
+
addIntegerOption(fn: (opt: SlashCommandOptionBuilder) => SlashCommandOptionBuilder): this;
|
|
1769
|
+
/** Add a boolean (true/false) option. */
|
|
1770
|
+
addBooleanOption(fn: (opt: SlashCommandOptionBuilder) => SlashCommandOptionBuilder): this;
|
|
1771
|
+
/** Add a user-mention option (returns a user ID string). */
|
|
1772
|
+
addUserOption(fn: (opt: SlashCommandOptionBuilder) => SlashCommandOptionBuilder): this;
|
|
1773
|
+
/** Add a channel-mention option (returns a channel ID string). */
|
|
1774
|
+
addChannelOption(fn: (opt: SlashCommandOptionBuilder) => SlashCommandOptionBuilder): this;
|
|
1775
|
+
/** Add a role-mention option (returns a role ID string). */
|
|
1776
|
+
addRoleOption(fn: (opt: SlashCommandOptionBuilder) => SlashCommandOptionBuilder): this;
|
|
1777
|
+
toJSON(): SlashCommandDefinition;
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
interface PollOption {
|
|
1781
|
+
label: string;
|
|
1782
|
+
emoji?: string;
|
|
1783
|
+
value?: string;
|
|
1784
|
+
}
|
|
1785
|
+
interface PollDefinition {
|
|
1786
|
+
question: string;
|
|
1787
|
+
options: PollOption[];
|
|
1788
|
+
allowMultiple?: boolean;
|
|
1789
|
+
duration?: number | null;
|
|
1790
|
+
anonymous?: boolean;
|
|
1791
|
+
}
|
|
1792
|
+
/**
|
|
1793
|
+
* Fluent builder for creating polls.
|
|
1794
|
+
*
|
|
1795
|
+
* @example
|
|
1796
|
+
* const poll = new PollBuilder()
|
|
1797
|
+
* .setQuestion('What is your favourite colour?')
|
|
1798
|
+
* .addOption({ label: 'Red', emoji: '🔴' })
|
|
1799
|
+
* .addOption({ label: 'Green', emoji: '🟢' })
|
|
1800
|
+
* .addOption({ label: 'Blue', emoji: '🔵' })
|
|
1801
|
+
* .setDuration(60 * 60 * 24) // 24 hours in seconds
|
|
1802
|
+
* .toJSON()
|
|
1803
|
+
*
|
|
1804
|
+
* await client.messages.send(channelId, { poll })
|
|
1805
|
+
*/
|
|
1806
|
+
declare class PollBuilder {
|
|
1807
|
+
private _question;
|
|
1808
|
+
private _options;
|
|
1809
|
+
private _allowMultiple;
|
|
1810
|
+
private _duration;
|
|
1811
|
+
private _anonymous;
|
|
1812
|
+
/**
|
|
1813
|
+
* Set the poll question.
|
|
1814
|
+
*
|
|
1815
|
+
* @example
|
|
1816
|
+
* builder.setQuestion('Best programming language?')
|
|
1817
|
+
*/
|
|
1818
|
+
setQuestion(question: string): this;
|
|
1819
|
+
/**
|
|
1820
|
+
* Add a single answer option.
|
|
1821
|
+
*
|
|
1822
|
+
* @example
|
|
1823
|
+
* builder.addOption({ label: 'TypeScript', emoji: '🔷' })
|
|
1824
|
+
*/
|
|
1825
|
+
addOption(option: PollOption): this;
|
|
1826
|
+
/**
|
|
1827
|
+
* Add multiple answer options at once.
|
|
1828
|
+
*
|
|
1829
|
+
* @example
|
|
1830
|
+
* builder.addOptions([
|
|
1831
|
+
* { label: 'Yes', emoji: '✅' },
|
|
1832
|
+
* { label: 'No', emoji: '❌' },
|
|
1833
|
+
* ])
|
|
1834
|
+
*/
|
|
1835
|
+
addOptions(options: PollOption[]): this;
|
|
1836
|
+
/**
|
|
1837
|
+
* Allow users to select more than one option.
|
|
1838
|
+
* Default: `false` (single choice).
|
|
1839
|
+
*/
|
|
1840
|
+
setAllowMultiple(yes?: boolean): this;
|
|
1841
|
+
/**
|
|
1842
|
+
* Set the poll duration in **seconds**. Pass `null` to make it permanent.
|
|
1843
|
+
*
|
|
1844
|
+
* @example
|
|
1845
|
+
* builder.setDuration(60 * 60 * 24) // expires in 24 hours
|
|
1846
|
+
* builder.setDuration(null) // no expiry
|
|
1847
|
+
*/
|
|
1848
|
+
setDuration(seconds: number | null): this;
|
|
1849
|
+
/**
|
|
1850
|
+
* Hide which users voted for which option.
|
|
1851
|
+
* Default: `false` (votes are public).
|
|
1852
|
+
*/
|
|
1853
|
+
setAnonymous(yes?: boolean): this;
|
|
1854
|
+
/** Build the poll definition object. */
|
|
1855
|
+
toJSON(): PollDefinition;
|
|
1856
|
+
}
|
|
1857
|
+
|
|
1858
|
+
/**
|
|
1859
|
+
* Fluent builder for composing messages.
|
|
1860
|
+
* Replaces passing raw option objects everywhere.
|
|
1861
|
+
*
|
|
1862
|
+
* @example
|
|
1863
|
+
* const msg = new MessageBuilder()
|
|
1864
|
+
* .setContent('Here are your stats:')
|
|
1865
|
+
* .setEmbed(
|
|
1866
|
+
* new EmbedBuilder()
|
|
1867
|
+
* .setTitle('📊 Stats')
|
|
1868
|
+
* .addField('Messages', '1 234', true)
|
|
1869
|
+
* .addField('Reactions', '567', true)
|
|
1870
|
+
* .setColor('#5865F2')
|
|
1871
|
+
* )
|
|
1872
|
+
* .addRow(
|
|
1873
|
+
* new ActionRowBuilder()
|
|
1874
|
+
* .addComponent(new ButtonBuilder().setLabel('Refresh').setCustomId('refresh').setStyle('primary'))
|
|
1875
|
+
* )
|
|
1876
|
+
* .toJSON()
|
|
1877
|
+
*
|
|
1878
|
+
* await client.messages.send(channelId, msg)
|
|
1879
|
+
*/
|
|
1880
|
+
declare class MessageBuilder {
|
|
1881
|
+
private _content;
|
|
1882
|
+
private _embed;
|
|
1883
|
+
private _components;
|
|
1884
|
+
private _replyToId;
|
|
1885
|
+
private _poll;
|
|
1886
|
+
/**
|
|
1887
|
+
* Set the text content of the message.
|
|
1888
|
+
*
|
|
1889
|
+
* @example
|
|
1890
|
+
* builder.setContent('Hello world!')
|
|
1891
|
+
*/
|
|
1892
|
+
setContent(content: string): this;
|
|
1893
|
+
/**
|
|
1894
|
+
* Attach an embed. Accepts an `EmbedBuilder` or raw `Embed` object.
|
|
1895
|
+
*
|
|
1896
|
+
* @example
|
|
1897
|
+
* builder.setEmbed(new EmbedBuilder().setTitle('Result'))
|
|
1898
|
+
* builder.setEmbed({ title: 'Result', color: '#57F287' })
|
|
1899
|
+
*/
|
|
1900
|
+
setEmbed(embed: EmbedBuilder | Embed): this;
|
|
1901
|
+
/**
|
|
1902
|
+
* Remove any embed from this message.
|
|
1903
|
+
*/
|
|
1904
|
+
clearEmbed(): this;
|
|
1905
|
+
/**
|
|
1906
|
+
* Add an `ActionRowBuilder` (or raw component array) as a component row.
|
|
1907
|
+
*
|
|
1908
|
+
* @example
|
|
1909
|
+
* builder.addRow(
|
|
1910
|
+
* new ActionRowBuilder().addComponent(btn1).addComponent(btn2)
|
|
1911
|
+
* )
|
|
1912
|
+
*/
|
|
1913
|
+
addRow(row: ActionRowBuilder | MessageComponent[]): this;
|
|
1914
|
+
/**
|
|
1915
|
+
* Replace all existing component rows.
|
|
1916
|
+
*/
|
|
1917
|
+
setComponents(components: MessageComponent[]): this;
|
|
1918
|
+
/**
|
|
1919
|
+
* Set the message this is replying to.
|
|
1920
|
+
*
|
|
1921
|
+
* @example
|
|
1922
|
+
* builder.setReplyTo(message.id)
|
|
1923
|
+
*/
|
|
1924
|
+
setReplyTo(messageId: string): this;
|
|
1925
|
+
/**
|
|
1926
|
+
* Attach a poll to the message.
|
|
1927
|
+
* Accepts a `PollBuilder` or raw `PollDefinition`.
|
|
1928
|
+
*
|
|
1929
|
+
* @example
|
|
1930
|
+
* builder.setPoll(
|
|
1931
|
+
* new PollBuilder()
|
|
1932
|
+
* .setQuestion('Favourite language?')
|
|
1933
|
+
* .addOptions([{ label: 'TypeScript' }, { label: 'Python' }])
|
|
1934
|
+
* )
|
|
1935
|
+
*/
|
|
1936
|
+
setPoll(poll: {
|
|
1937
|
+
toJSON: () => PollDefinition;
|
|
1938
|
+
} | PollDefinition): this;
|
|
1939
|
+
/**
|
|
1940
|
+
* Build the message options object, ready to pass to `client.messages.send()`.
|
|
1941
|
+
*
|
|
1942
|
+
* @throws if neither `content` nor `embed` nor `poll` is set.
|
|
1943
|
+
*/
|
|
1944
|
+
toJSON(): SendMessageOptions & {
|
|
1945
|
+
poll?: PollDefinition;
|
|
1946
|
+
};
|
|
1947
|
+
}
|
|
1948
|
+
|
|
1949
|
+
/**
|
|
1950
|
+
* A supercharged Map with extra utility methods.
|
|
1951
|
+
* Used throughout the SDK for caches (messages, channels, members, etc.)
|
|
1952
|
+
*
|
|
1953
|
+
* Inspired by discord.js Collection — but with proper generics and async support.
|
|
1954
|
+
*
|
|
1955
|
+
* @example
|
|
1956
|
+
* const col = new Collection<string, User>()
|
|
1957
|
+
* col.set('u1', { id: 'u1', name: 'Alice' })
|
|
1958
|
+
* col.set('u2', { id: 'u2', name: 'Bob' })
|
|
1959
|
+
*
|
|
1960
|
+
* col.first() // { id: 'u1', name: 'Alice' }
|
|
1961
|
+
* col.find(u => u.name === 'Bob') // { id: 'u2', name: 'Bob' }
|
|
1962
|
+
* col.map(u => u.name) // ['Alice', 'Bob']
|
|
1963
|
+
*/
|
|
1964
|
+
declare class Collection<K, V> extends Map<K, V> {
|
|
1965
|
+
/**
|
|
1966
|
+
* The first value stored (insertion order), or `undefined` if empty.
|
|
1967
|
+
*/
|
|
1968
|
+
first(): V | undefined;
|
|
1969
|
+
/**
|
|
1970
|
+
* The first `n` values stored (insertion order).
|
|
1971
|
+
*/
|
|
1972
|
+
firstN(n: number): V[];
|
|
1973
|
+
/**
|
|
1974
|
+
* The last value stored, or `undefined` if empty.
|
|
1975
|
+
*/
|
|
1976
|
+
last(): V | undefined;
|
|
1977
|
+
/**
|
|
1978
|
+
* The last `n` values stored (insertion order).
|
|
1979
|
+
*/
|
|
1980
|
+
lastN(n: number): V[];
|
|
1981
|
+
/**
|
|
1982
|
+
* Returns a random value from the collection, or `undefined` if empty.
|
|
1983
|
+
*/
|
|
1984
|
+
random(): V | undefined;
|
|
1985
|
+
/**
|
|
1986
|
+
* Find the first value that passes the predicate.
|
|
1987
|
+
*
|
|
1988
|
+
* @example
|
|
1989
|
+
* const bot = members.find(m => m.user.isBot)
|
|
1990
|
+
*/
|
|
1991
|
+
find(fn: (value: V, key: K, col: this) => boolean): V | undefined;
|
|
1992
|
+
/**
|
|
1993
|
+
* Find the key of the first value that passes the predicate.
|
|
1994
|
+
*/
|
|
1995
|
+
findKey(fn: (value: V, key: K, col: this) => boolean): K | undefined;
|
|
1996
|
+
/**
|
|
1997
|
+
* Returns `true` if at least one value satisfies the predicate.
|
|
1998
|
+
*/
|
|
1999
|
+
some(fn: (value: V, key: K, col: this) => boolean): boolean;
|
|
2000
|
+
/**
|
|
2001
|
+
* Returns `true` if every value satisfies the predicate.
|
|
2002
|
+
*/
|
|
2003
|
+
every(fn: (value: V, key: K, col: this) => boolean): boolean;
|
|
2004
|
+
/**
|
|
2005
|
+
* Filter to a new Collection containing only values that pass the predicate.
|
|
2006
|
+
*
|
|
2007
|
+
* @example
|
|
2008
|
+
* const admins = members.filter(m => m.role === 'ADMIN')
|
|
2009
|
+
*/
|
|
2010
|
+
filter(fn: (value: V, key: K, col: this) => boolean): Collection<K, V>;
|
|
2011
|
+
/**
|
|
2012
|
+
* Map each value to a new array.
|
|
2013
|
+
*
|
|
2014
|
+
* @example
|
|
2015
|
+
* const names = members.map(m => m.user.username)
|
|
2016
|
+
*/
|
|
2017
|
+
map<T>(fn: (value: V, key: K, col: this) => T): T[];
|
|
2018
|
+
/**
|
|
2019
|
+
* Map to a new Collection with transformed values.
|
|
2020
|
+
*
|
|
2021
|
+
* @example
|
|
2022
|
+
* const names = channels.mapValues(c => c.name.toUpperCase())
|
|
2023
|
+
*/
|
|
2024
|
+
mapValues<T>(fn: (value: V, key: K, col: this) => T): Collection<K, T>;
|
|
2025
|
+
/**
|
|
2026
|
+
* Reduce the collection to a single value.
|
|
2027
|
+
*
|
|
2028
|
+
* @example
|
|
2029
|
+
* const totalReactions = messages.reduce((sum, m) => sum + m.reactions.length, 0)
|
|
2030
|
+
*/
|
|
2031
|
+
reduce<T>(fn: (accumulator: T, value: V, key: K, col: this) => T, initial: T): T;
|
|
2032
|
+
/**
|
|
2033
|
+
* Returns values as an array (insertion order).
|
|
2034
|
+
*/
|
|
2035
|
+
toArray(): V[];
|
|
2036
|
+
/**
|
|
2037
|
+
* Returns keys as an array (insertion order).
|
|
2038
|
+
*/
|
|
2039
|
+
keyArray(): K[];
|
|
2040
|
+
/**
|
|
2041
|
+
* Sort and return a new Collection.
|
|
2042
|
+
* Callback works like `Array.prototype.sort`.
|
|
2043
|
+
*
|
|
2044
|
+
* @example
|
|
2045
|
+
* const sorted = channels.sort((a, b) => a.position - b.position)
|
|
2046
|
+
*/
|
|
2047
|
+
sort(fn?: (a: V, b: V, ak: K, bk: K) => number): Collection<K, V>;
|
|
2048
|
+
/**
|
|
2049
|
+
* Split into two Collections based on a predicate.
|
|
2050
|
+
* Returns `[passing, failing]`.
|
|
2051
|
+
*
|
|
2052
|
+
* @example
|
|
2053
|
+
* const [bots, humans] = members.partition(m => m.user.isBot)
|
|
2054
|
+
*/
|
|
2055
|
+
partition(fn: (value: V, key: K, col: this) => boolean): [Collection<K, V>, Collection<K, V>];
|
|
2056
|
+
/**
|
|
2057
|
+
* Merge this collection with one or more others.
|
|
2058
|
+
* Later collections overwrite duplicate keys.
|
|
2059
|
+
*/
|
|
2060
|
+
merge(...others: ReadonlyMap<K, V>[]): Collection<K, V>;
|
|
2061
|
+
/**
|
|
2062
|
+
* Serialize to a plain `Record` (requires string keys).
|
|
2063
|
+
*/
|
|
2064
|
+
toJSON(): Record<string, V>;
|
|
2065
|
+
toString(): string;
|
|
2066
|
+
}
|
|
2067
|
+
|
|
2068
|
+
/**
|
|
2069
|
+
* Per-user cooldown manager.
|
|
2070
|
+
* Prevents commands from being spammed by individual users.
|
|
2071
|
+
*
|
|
2072
|
+
* @example
|
|
2073
|
+
* // Create once per command
|
|
2074
|
+
* const cooldown = new Cooldown(5_000) // 5 second cooldown
|
|
2075
|
+
*
|
|
2076
|
+
* client.command('daily', async (interaction) => {
|
|
2077
|
+
* const remaining = cooldown.check(interaction.userId)
|
|
2078
|
+
* if (remaining > 0) {
|
|
2079
|
+
* return interaction.replyEphemeral(
|
|
2080
|
+
* `⏳ Wait **${Cooldown.format(remaining)}** before using this command again.`
|
|
2081
|
+
* )
|
|
2082
|
+
* }
|
|
2083
|
+
* cooldown.use(interaction.userId)
|
|
2084
|
+
* await interaction.reply('🎁 Daily reward collected!')
|
|
2085
|
+
* })
|
|
2086
|
+
*/
|
|
2087
|
+
declare class Cooldown {
|
|
2088
|
+
private readonly _durations;
|
|
2089
|
+
private readonly _last;
|
|
2090
|
+
private readonly _defaultMs;
|
|
2091
|
+
/**
|
|
2092
|
+
* @param durationMs - Default cooldown duration in milliseconds.
|
|
2093
|
+
*/
|
|
2094
|
+
constructor(durationMs: number);
|
|
2095
|
+
/**
|
|
2096
|
+
* Check remaining cooldown for a user.
|
|
2097
|
+
* Returns `0` if they are not on cooldown (free to proceed),
|
|
2098
|
+
* or the **milliseconds remaining** if they are on cooldown.
|
|
2099
|
+
*
|
|
2100
|
+
* @example
|
|
2101
|
+
* const ms = cooldown.check(userId)
|
|
2102
|
+
* if (ms > 0) return interaction.replyEphemeral(`Wait ${Cooldown.format(ms)}!`)
|
|
2103
|
+
*/
|
|
2104
|
+
check(userId: string): number;
|
|
2105
|
+
/**
|
|
2106
|
+
* Mark a user as having just used the command, starting their cooldown.
|
|
2107
|
+
* Optionally override the cooldown duration for this specific user.
|
|
2108
|
+
*
|
|
2109
|
+
* @example
|
|
2110
|
+
* cooldown.use(userId) // uses default duration
|
|
2111
|
+
* cooldown.use(userId, 10_000) // 10 second cooldown for this use
|
|
2112
|
+
*/
|
|
2113
|
+
use(userId: string, durationMs?: number): void;
|
|
2114
|
+
/**
|
|
2115
|
+
* Immediately reset (clear) the cooldown for a user.
|
|
2116
|
+
*
|
|
2117
|
+
* @example
|
|
2118
|
+
* cooldown.reset(userId) // user can use the command again immediately
|
|
2119
|
+
*/
|
|
2120
|
+
reset(userId: string): void;
|
|
2121
|
+
/**
|
|
2122
|
+
* Reset all active cooldowns.
|
|
2123
|
+
*/
|
|
2124
|
+
resetAll(): void;
|
|
2125
|
+
/**
|
|
2126
|
+
* Returns a list of all users currently on cooldown.
|
|
2127
|
+
*
|
|
2128
|
+
* @example
|
|
2129
|
+
* const active = cooldown.activeCooldowns()
|
|
2130
|
+
* // [{ userId: 'abc', remainingMs: 3200 }, ...]
|
|
2131
|
+
*/
|
|
2132
|
+
activeCooldowns(): Array<{
|
|
2133
|
+
userId: string;
|
|
2134
|
+
remainingMs: number;
|
|
2135
|
+
}>;
|
|
2136
|
+
/**
|
|
2137
|
+
* Format milliseconds into a human-readable string.
|
|
2138
|
+
*
|
|
2139
|
+
* @example
|
|
2140
|
+
* Cooldown.format(3_600_000) // '1h 0m 0s'
|
|
2141
|
+
* Cooldown.format(90_000) // '1m 30s'
|
|
2142
|
+
* Cooldown.format(4_000) // '4s'
|
|
2143
|
+
*/
|
|
2144
|
+
static format(ms: number): string;
|
|
2145
|
+
}
|
|
2146
|
+
/**
|
|
2147
|
+
* Manages multiple named cooldowns in one place.
|
|
2148
|
+
* Ideal when you have many commands each with their own cooldown.
|
|
2149
|
+
*
|
|
2150
|
+
* @example
|
|
2151
|
+
* const cooldowns = new CooldownManager()
|
|
2152
|
+
*
|
|
2153
|
+
* client.command('ping', async (interaction) => {
|
|
2154
|
+
* const remaining = cooldowns.check('ping', interaction.userId, 3_000)
|
|
2155
|
+
* if (remaining > 0) return interaction.replyEphemeral(`Wait ${Cooldown.format(remaining)}!`)
|
|
2156
|
+
* await interaction.reply('Pong!')
|
|
2157
|
+
* })
|
|
2158
|
+
*/
|
|
2159
|
+
declare class CooldownManager {
|
|
2160
|
+
private readonly _map;
|
|
2161
|
+
/**
|
|
2162
|
+
* Get or create a named cooldown.
|
|
2163
|
+
*/
|
|
2164
|
+
get(name: string, durationMs?: number): Cooldown;
|
|
2165
|
+
/**
|
|
2166
|
+
* Check a named cooldown for a user.
|
|
2167
|
+
* Creates the cooldown if it doesn't exist yet.
|
|
2168
|
+
* Returns `0` if free, or remaining ms if on cooldown.
|
|
2169
|
+
*
|
|
2170
|
+
* @example
|
|
2171
|
+
* const ms = cooldowns.check('ban', userId, 30_000)
|
|
2172
|
+
*/
|
|
2173
|
+
check(name: string, userId: string, durationMs?: number): number;
|
|
2174
|
+
/**
|
|
2175
|
+
* Mark a user as having used a named command.
|
|
2176
|
+
*
|
|
2177
|
+
* @example
|
|
2178
|
+
* cooldowns.use('ban', userId, 30_000)
|
|
2179
|
+
*/
|
|
2180
|
+
use(name: string, userId: string, durationMs?: number): void;
|
|
2181
|
+
/**
|
|
2182
|
+
* Reset a user's cooldown on a named command.
|
|
2183
|
+
*/
|
|
2184
|
+
reset(name: string, userId: string): void;
|
|
2185
|
+
/**
|
|
2186
|
+
* Reset all cooldowns for all commands.
|
|
2187
|
+
*/
|
|
2188
|
+
resetAll(): void;
|
|
2189
|
+
}
|
|
2190
|
+
|
|
2191
|
+
/**
|
|
2192
|
+
* Coloured, timestamped logger for Nova bots.
|
|
2193
|
+
* Prefix every log with a consistent `[BotName]` tag.
|
|
2194
|
+
*
|
|
2195
|
+
* @example
|
|
2196
|
+
* const log = new Logger('MyBot')
|
|
2197
|
+
* log.info('Ready!') // [MyBot] [INFO] Ready!
|
|
2198
|
+
* log.warn('Rate limited') // [MyBot] [WARN] Rate limited
|
|
2199
|
+
* log.error('DB timed out') // [MyBot] [ERROR] DB timed out
|
|
2200
|
+
* log.debug('Payload:', data) // [MyBot] [DEBUG] Payload: { ... }
|
|
2201
|
+
* log.success('Command registered') // [MyBot] [OK] Command registered
|
|
2202
|
+
* log.command('ping', userId) // [MyBot] [CMD] ping ← userId
|
|
2203
|
+
* log.event('messageCreate') // [MyBot] [EVT] messageCreate
|
|
2204
|
+
*/
|
|
2205
|
+
declare class Logger {
|
|
2206
|
+
private readonly _prefix;
|
|
2207
|
+
private _debug;
|
|
2208
|
+
/**
|
|
2209
|
+
* @param name - Name shown in square brackets before every message.
|
|
2210
|
+
* @param enableDebug - When `false` (default), `.debug()` calls are silent.
|
|
2211
|
+
*/
|
|
2212
|
+
constructor(name: string, enableDebug?: boolean);
|
|
2213
|
+
/** Enable or disable debug output at runtime. */
|
|
2214
|
+
setDebug(enabled: boolean): this;
|
|
2215
|
+
private _timestamp;
|
|
2216
|
+
private _fmt;
|
|
2217
|
+
/** General info message. */
|
|
2218
|
+
info(...args: unknown[]): void;
|
|
2219
|
+
/** Warning — something unexpected but non-fatal. */
|
|
2220
|
+
warn(...args: unknown[]): void;
|
|
2221
|
+
/** Error — something went wrong. */
|
|
2222
|
+
error(...args: unknown[]): void;
|
|
2223
|
+
/** Success / positive confirmation. */
|
|
2224
|
+
success(...args: unknown[]): void;
|
|
2225
|
+
/** Debug — only printed when `enableDebug` is true. */
|
|
2226
|
+
debug(...args: unknown[]): void;
|
|
2227
|
+
/**
|
|
2228
|
+
* Log an incoming command interaction.
|
|
2229
|
+
*
|
|
2230
|
+
* @example
|
|
2231
|
+
* log.command('ping', interaction.userId)
|
|
2232
|
+
* // [MyBot] [CMD] /ping ← user:abc123
|
|
2233
|
+
*/
|
|
2234
|
+
command(name: string, userId: string): void;
|
|
2235
|
+
/**
|
|
2236
|
+
* Log a gateway event.
|
|
2237
|
+
*
|
|
2238
|
+
* @example
|
|
2239
|
+
* log.event('messageCreate')
|
|
2240
|
+
*/
|
|
2241
|
+
event(type: string, extra?: string): void;
|
|
2242
|
+
/**
|
|
2243
|
+
* Log that a command handler threw an error.
|
|
2244
|
+
*
|
|
2245
|
+
* @example
|
|
2246
|
+
* log.commandError('ban', err)
|
|
2247
|
+
*/
|
|
2248
|
+
commandError(name: string, err: unknown): void;
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
export { ActionRowBuilder, type Attachment, type BanEntry, type BotApplication, type BotEvent, type BotEventType, type BotModalDefinition, type BotModalField, type BotPermissionRecord, type BotStatus, type BotUser, ButtonBuilder, type ButtonStyle, type Channel, type ChannelType, ChannelsAPI, Collection, CommandsAPI, type ContextCommandDefinition, Cooldown, CooldownManager, type CreateChannelOptions, type EditChannelOptions, type EditMessageOptions, type Embed, EmbedBuilder, type EmbedField, type FetchChannelsOptions, type FetchMembersOptions, type FetchMessagesOptions, HttpClient, type Interaction, InteractionOptions, type InteractionType, InteractionsAPI, type Invite, Logger, type Member, MembersAPI, type Message, MessageBuilder, type MessageComponent, MessagesAPI, ModalBuilder, NovaClient, type NovaClientEvents, type NovaClientOptions, NovaInteraction, NovaMessage, type NovaServer, PermissionsAPI, type PermissionsQueryOptions, type PermissionsResult, PollBuilder, type PollDefinition, type PollInteractionsOptions, type PollOption, type PrefixCommandDefinition, type Reaction, type ReactionDetail, ReactionsAPI, type RegisteredContextCommand, type RegisteredPrefixCommand, type RegisteredSlashCommand, type RespondInteractionOptions, type Role, SelectMenuBuilder, type SelectMenuOption, type SendMessageOptions, ServersAPI, SlashCommandBuilder, type SlashCommandDefinition, type SlashCommandOption, SlashCommandOptionBuilder, TextInputBuilder, type TextInputStyle };
|