novaapp-sdk 1.4.0 → 1.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4244 @@
1
+ import { EventEmitter } from 'node:events';
2
+
3
+ /**
4
+ * Lightweight HTTP client for the Nova Bot API.
5
+ * Uses the native fetch API (Node 18+).
6
+ */
7
+ declare class HttpClient {
8
+ readonly baseUrl: string;
9
+ private readonly token;
10
+ constructor(baseUrl: string, token: string);
11
+ private request;
12
+ get<T>(path: string): Promise<T>;
13
+ post<T>(path: string, body?: unknown): Promise<T>;
14
+ patch<T>(path: string, body?: unknown): Promise<T>;
15
+ delete<T>(path: string): Promise<T>;
16
+ }
17
+
18
+ interface BotUser {
19
+ id: string;
20
+ username: string;
21
+ displayName: string;
22
+ avatar: string | null;
23
+ isBot: true;
24
+ }
25
+ interface BotApplication {
26
+ id: string;
27
+ name: string;
28
+ /** Convenience: same as botUser.username */
29
+ username: string;
30
+ /** Convenience: same as botUser.displayName */
31
+ displayName: string;
32
+ description: string | null;
33
+ avatar: string | null;
34
+ category: string | null;
35
+ isPublic: boolean;
36
+ isVerified: boolean;
37
+ callbackUrl: string | null;
38
+ createdAt: string;
39
+ botUser: BotUser;
40
+ scopes: string[];
41
+ }
42
+ interface NovaServer {
43
+ id: string;
44
+ name: string;
45
+ icon: string | null;
46
+ description: string | null;
47
+ memberCount: number;
48
+ channelCount: number;
49
+ joinedAt: string;
50
+ }
51
+ interface Member {
52
+ role: 'OWNER' | 'ADMIN' | 'MEMBER';
53
+ joinedAt: string;
54
+ user: {
55
+ id: string;
56
+ username: string;
57
+ displayName: string;
58
+ avatar: string | null;
59
+ status: 'ONLINE' | 'IDLE' | 'DND' | 'OFFLINE';
60
+ isBot: boolean;
61
+ };
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
+ /** Slow-mode interval in seconds. `0` means disabled. */
72
+ slowMode: number;
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';
116
+ interface Attachment {
117
+ id: string;
118
+ url: string;
119
+ filename: string;
120
+ mimeType: string;
121
+ size: number;
122
+ }
123
+ interface Reaction {
124
+ emoji: string;
125
+ count: number;
126
+ userIds: string[];
127
+ }
128
+ interface EmbedField {
129
+ name: string;
130
+ value: string;
131
+ inline?: boolean;
132
+ }
133
+ interface Embed {
134
+ title?: string;
135
+ description?: string;
136
+ /** Makes the title a clickable link. */
137
+ url?: string;
138
+ /** Hex colour string — e.g. `'#5865F2'`. */
139
+ color?: string;
140
+ thumbnail?: string;
141
+ image?: string;
142
+ footer?: string;
143
+ fields?: EmbedField[];
144
+ timestamp?: string;
145
+ author?: {
146
+ name: string;
147
+ iconUrl?: string;
148
+ };
149
+ }
150
+ interface MessageComponent {
151
+ type: 'button' | 'select';
152
+ customId?: string;
153
+ label?: string;
154
+ style?: 'primary' | 'secondary' | 'success' | 'danger' | 'link';
155
+ emoji?: string;
156
+ url?: string;
157
+ placeholder?: string;
158
+ options?: Array<{
159
+ label: string;
160
+ value: string;
161
+ description?: string;
162
+ }>;
163
+ minValues?: number;
164
+ maxValues?: number;
165
+ disabled?: boolean;
166
+ }
167
+ interface Message {
168
+ id: string;
169
+ content: string;
170
+ channelId: string;
171
+ author: BotUser | {
172
+ id: string;
173
+ username: string;
174
+ displayName: string;
175
+ avatar: string | null;
176
+ isBot: boolean;
177
+ };
178
+ embed?: Embed | null;
179
+ components?: MessageComponent[] | null;
180
+ replyToId?: string | null;
181
+ attachments: Attachment[];
182
+ reactions: Reaction[];
183
+ createdAt: string;
184
+ editedAt?: string | null;
185
+ deletedAt?: string | null;
186
+ }
187
+ type InteractionType = 'SLASH_COMMAND' | 'BUTTON_CLICK' | 'SELECT_MENU' | 'MODAL_SUBMIT' | 'AUTOCOMPLETE' | 'CONTEXT_MENU' | 'PREFIX_COMMAND';
188
+ interface Interaction {
189
+ id: string;
190
+ type: InteractionType;
191
+ commandName?: string | null;
192
+ customId?: string | null;
193
+ data?: unknown;
194
+ /** For SELECT_MENU interactions — the chosen option values. */
195
+ values?: string[];
196
+ /** For MODAL_SUBMIT interactions — field customId → submitted value. */
197
+ modalData?: Record<string, string>;
198
+ /**
199
+ * For AUTOCOMPLETE interactions — the option being completed and the
200
+ * partial string the user has typed so far.
201
+ */
202
+ autocomplete?: {
203
+ name: string;
204
+ value: string;
205
+ };
206
+ /**
207
+ * For CONTEXT_MENU interactions — the ID of the message or user that was
208
+ * right-clicked.
209
+ */
210
+ contextTargetId?: string | null;
211
+ userId: string;
212
+ channelId: string;
213
+ serverId?: string | null;
214
+ triggerMsgId?: string | null;
215
+ createdAt: string;
216
+ }
217
+ /** A single text input field inside a bot modal. */
218
+ interface BotModalField {
219
+ /** Unique field ID — returned as key in `modalData` on MODAL_SUBMIT. */
220
+ customId: string;
221
+ /** Label displayed above the input. */
222
+ label: string;
223
+ /** `'short'` = single-line input, `'paragraph'` = multi-line textarea. */
224
+ type: 'short' | 'paragraph';
225
+ placeholder?: string;
226
+ required?: boolean;
227
+ minLength?: number;
228
+ maxLength?: number;
229
+ /** Optional pre-filled default value. */
230
+ value?: string;
231
+ }
232
+ /**
233
+ * Pass this as `modal` inside `client.interactions.respond()` to open a
234
+ * modal dialog on the user's client instead of sending a message.
235
+ *
236
+ * @example
237
+ * await client.interactions.respond(interaction.id, {
238
+ * modal: {
239
+ * title: 'Submit a report',
240
+ * customId: 'report_modal',
241
+ * fields: [
242
+ * { customId: 'reason', label: 'Reason', type: 'paragraph', required: true },
243
+ * ],
244
+ * },
245
+ * })
246
+ */
247
+ interface BotModalDefinition {
248
+ /** Title shown at the top of the modal dialog. */
249
+ title: string;
250
+ /** Custom ID passed back with the MODAL_SUBMIT interaction. */
251
+ customId: string;
252
+ fields: BotModalField[];
253
+ }
254
+ interface SlashCommandOption {
255
+ name: string;
256
+ description: string;
257
+ type: 'STRING' | 'INTEGER' | 'NUMBER' | 'BOOLEAN' | 'USER' | 'CHANNEL' | 'ROLE' | 'ATTACHMENT';
258
+ required?: boolean;
259
+ /** Whether to enable autocomplete for this option. Mutually exclusive with `choices`. */
260
+ autocomplete?: boolean;
261
+ choices?: Array<{
262
+ name: string;
263
+ value: string | number;
264
+ }>;
265
+ /** Minimum value (for INTEGER / NUMBER types). */
266
+ minValue?: number;
267
+ /** Maximum value (for INTEGER / NUMBER types). */
268
+ maxValue?: number;
269
+ /** Minimum length (for STRING type). */
270
+ minLength?: number;
271
+ /** Maximum length (for STRING type). */
272
+ maxLength?: number;
273
+ }
274
+ interface SlashCommandDefinition {
275
+ name: string;
276
+ description: string;
277
+ options?: SlashCommandOption[];
278
+ }
279
+ interface PrefixCommandDefinition {
280
+ prefix: string;
281
+ name: string;
282
+ description: string;
283
+ options?: SlashCommandOption[];
284
+ guildId?: string | null;
285
+ }
286
+ interface ContextCommandDefinition {
287
+ name: string;
288
+ target: 'MESSAGE' | 'USER';
289
+ guildId?: string | null;
290
+ }
291
+ interface RegisteredSlashCommand {
292
+ id: string;
293
+ name: string;
294
+ description: string;
295
+ options: SlashCommandOption[];
296
+ guildId: string | null;
297
+ enabled: boolean;
298
+ createdAt: string;
299
+ }
300
+ interface RegisteredPrefixCommand {
301
+ id: string;
302
+ prefix: string;
303
+ name: string;
304
+ description: string;
305
+ options: SlashCommandOption[];
306
+ guildId: string | null;
307
+ enabled: boolean;
308
+ createdAt: string;
309
+ }
310
+ interface RegisteredContextCommand {
311
+ id: string;
312
+ name: string;
313
+ target: 'MESSAGE' | 'USER';
314
+ guildId: string | null;
315
+ enabled: boolean;
316
+ createdAt: string;
317
+ }
318
+ type BotEventType = 'message.created' | 'message.edited' | 'message.deleted' | 'message.reaction_added' | 'message.reaction_removed' | 'message.pinned' | 'user.joined_server' | 'user.left_server' | 'user.updated_profile' | 'user.banned' | 'user.unbanned' | 'user.role_added' | 'user.role_removed' | 'user.started_typing' | 'user.voice_joined' | 'user.voice_left' | 'interaction.slash_command' | 'interaction.button_click' | 'interaction.select_menu' | 'interaction.modal_submit' | 'interaction.autocomplete' | 'server.updated' | 'channel.created' | 'channel.deleted' | 'channel.updated' | 'role.created' | 'role.updated' | 'role.deleted' | 'invite.created' | 'invite.deleted' | 'forum.post.created' | 'event.created' | 'event.updated' | 'event.deleted' | 'category.created' | 'category.updated' | 'category.deleted' | 'member.warned' | 'messages.bulk_deleted';
319
+ interface BotEvent<T = unknown> {
320
+ type: BotEventType;
321
+ data: T;
322
+ timestamp: string;
323
+ }
324
+ interface SendMessageOptions {
325
+ content?: string;
326
+ embed?: Embed;
327
+ components?: MessageComponent[];
328
+ replyToId?: string;
329
+ }
330
+ interface EditMessageOptions {
331
+ content?: string;
332
+ embed?: Embed;
333
+ components?: MessageComponent[];
334
+ }
335
+ interface RespondInteractionOptions {
336
+ content?: string;
337
+ embed?: Embed;
338
+ components?: MessageComponent[];
339
+ ephemeral?: boolean;
340
+ /**
341
+ * Open a modal dialog on the user's client instead of sending a message.
342
+ * When set, all other fields are ignored.
343
+ */
344
+ modal?: BotModalDefinition;
345
+ }
346
+ interface FetchMessagesOptions {
347
+ limit?: number;
348
+ before?: string;
349
+ }
350
+ interface FetchMembersOptions {
351
+ limit?: number;
352
+ /** Return members whose role matches this value. */
353
+ role?: 'OWNER' | 'ADMIN' | 'MEMBER';
354
+ /** Filter by partial username (case-insensitive). */
355
+ search?: string;
356
+ }
357
+ interface PollInteractionsOptions {
358
+ limit?: number;
359
+ since?: string;
360
+ }
361
+ interface CreateChannelOptions {
362
+ name: string;
363
+ type?: ChannelType;
364
+ topic?: string;
365
+ position?: number;
366
+ slowMode?: number;
367
+ }
368
+ interface EditChannelOptions {
369
+ name?: string;
370
+ topic?: string;
371
+ position?: number;
372
+ slowMode?: number;
373
+ }
374
+ interface FetchChannelsOptions {
375
+ type?: ChannelType;
376
+ }
377
+ /** A raw permission record stored for a specific scope (server, role, or channel). */
378
+ interface BotPermissionRecord {
379
+ id: string;
380
+ botId: string;
381
+ serverId: string;
382
+ /** `null` means this record is server-wide (not channel-scoped). */
383
+ channelId: string | null;
384
+ /** `null` means this record applies to all roles. */
385
+ roleId: string | null;
386
+ /** Key-value map of permission name → granted flag. */
387
+ permissions: Record<string, boolean>;
388
+ createdAt: string;
389
+ updatedAt: string;
390
+ }
391
+ /** Response from `client.permissions.get()`. */
392
+ interface PermissionsResult {
393
+ /**
394
+ * Merged, effective permissions for the requested scope.
395
+ * Merging order (highest wins): channel > role > server-wide.
396
+ */
397
+ permissions: Record<string, boolean>;
398
+ /** All raw permission records matching the query scope. */
399
+ records: BotPermissionRecord[];
400
+ }
401
+ /** Options accepted by `client.permissions.get()`. */
402
+ interface PermissionsQueryOptions {
403
+ /** The server to query permissions for (required). */
404
+ serverId: string;
405
+ /** Narrow the scope to a specific channel. */
406
+ channelId?: string;
407
+ /** Narrow the scope to a specific role. */
408
+ roleId?: string;
409
+ }
410
+ /** A direct message sent between the bot and a user. */
411
+ interface DirectMessage {
412
+ id: string;
413
+ content: string;
414
+ /** The sender's user ID. */
415
+ fromId: string;
416
+ /** The recipient's user ID. */
417
+ toId: string;
418
+ editedAt: string | null;
419
+ createdAt: string;
420
+ }
421
+ /** Snapshot of a user's voice channel presence. */
422
+ interface VoiceState {
423
+ userId: string;
424
+ channelId: string;
425
+ serverId: string;
426
+ /** Whether the user's microphone is muted. */
427
+ muted: boolean;
428
+ /** Whether the user's audio output is deafened. */
429
+ deafened: boolean;
430
+ /** ISO timestamp when the user joined the voice channel. */
431
+ joinedAt: string;
432
+ }
433
+ interface RoleCreateOptions {
434
+ name: string;
435
+ color?: string;
436
+ hoist?: boolean;
437
+ /**
438
+ * Permission flags to grant for this role.
439
+ * Any key not set retains its default value from the server.
440
+ */
441
+ permissions?: Partial<{
442
+ manageServer: boolean;
443
+ manageChannels: boolean;
444
+ manageRoles: boolean;
445
+ viewAuditLog: boolean;
446
+ createInvites: boolean;
447
+ manageWebhooks: boolean;
448
+ kickMembers: boolean;
449
+ banMembers: boolean;
450
+ timeoutMembers: boolean;
451
+ changeNickname: boolean;
452
+ manageNicknames: boolean;
453
+ muteMembers: boolean;
454
+ deafenMembers: boolean;
455
+ moveMembers: boolean;
456
+ sendMessages: boolean;
457
+ manageMessages: boolean;
458
+ embedLinks: boolean;
459
+ attachFiles: boolean;
460
+ addReactions: boolean;
461
+ mentionEveryone: boolean;
462
+ readMessageHistory: boolean;
463
+ }>;
464
+ }
465
+ type RoleEditOptions = Partial<RoleCreateOptions>;
466
+ interface InviteCreateOptions {
467
+ /** Maximum number of times the invite can be used. `null` = unlimited. */
468
+ maxUses?: number | null;
469
+ /** ISO timestamp when the invite expires. `null` = never expires. */
470
+ expiresAt?: string | null;
471
+ }
472
+ interface Webhook {
473
+ id: string;
474
+ serverId: string;
475
+ channelId: string;
476
+ name: string;
477
+ /** A secret token used to post messages via this webhook. */
478
+ token: string;
479
+ createdAt: string;
480
+ }
481
+ interface WebhookCreateOptions {
482
+ /** Display name shown when the webhook posts a message. */
483
+ name: string;
484
+ }
485
+ interface WebhookEditOptions {
486
+ /** New display name for the webhook. */
487
+ name?: string;
488
+ /** Move the webhook to a different text channel. */
489
+ channelId?: string;
490
+ }
491
+ interface ExecuteWebhookOptions {
492
+ content?: string;
493
+ embed?: Embed;
494
+ /** Override the default display name for this execution. */
495
+ username?: string;
496
+ }
497
+ type AuditLogAction = 'member.kicked' | 'member.banned' | 'member.unbanned' | 'member.role_added' | 'member.role_removed' | 'message.deleted' | 'message.pinned' | 'message.unpinned' | 'channel.created' | 'channel.updated' | 'channel.deleted' | 'role.created' | 'role.updated' | 'role.deleted' | 'invite.created' | 'invite.deleted' | 'webhook.created' | 'webhook.updated' | 'webhook.deleted' | 'server.updated' | string;
498
+ interface AuditLogEntry {
499
+ id: string;
500
+ serverId: string;
501
+ action: AuditLogAction;
502
+ /** The user who performed the action. */
503
+ actorId: string;
504
+ actorName: string;
505
+ /** The entity affected (user, channel, role, etc.). */
506
+ targetId: string | null;
507
+ targetName: string | null;
508
+ /** Extra context (old/new values, reason, etc.). */
509
+ metadata: Record<string, unknown> | null;
510
+ createdAt: string;
511
+ }
512
+ interface FetchAuditLogsOptions {
513
+ limit?: number;
514
+ /** Only return entries for a specific action type. */
515
+ action?: AuditLogAction;
516
+ /** Only return entries targeting a specific user ID. */
517
+ userId?: string;
518
+ before?: string;
519
+ }
520
+ interface ServerUpdateOptions {
521
+ name?: string;
522
+ description?: string;
523
+ icon?: string | null;
524
+ }
525
+ /** Extended member object returned when fetching a single member by user ID. */
526
+ interface SingleMember extends Member {
527
+ /** The custom role assigned to this member, if any. */
528
+ customRole: Role | null;
529
+ }
530
+ interface NovaClientOptions {
531
+ /** Your bot token — starts with "nova_bot_" */
532
+ token: string;
533
+ /**
534
+ * Base URL of the Nova server.
535
+ * @default "https://novachatapp.com"
536
+ */
537
+ baseUrl?: string;
538
+ }
539
+ interface ChannelCategory {
540
+ id: string;
541
+ serverId: string;
542
+ name: string;
543
+ position: number;
544
+ createdAt: string;
545
+ }
546
+ interface CreateCategoryOptions {
547
+ name: string;
548
+ position?: number;
549
+ }
550
+ interface EditCategoryOptions {
551
+ name?: string;
552
+ position?: number;
553
+ }
554
+ interface ForumPost {
555
+ id: string;
556
+ channelId: string;
557
+ authorId: string;
558
+ title: string;
559
+ body: string;
560
+ tags: string[];
561
+ pinned: boolean;
562
+ closed: boolean;
563
+ upvoteCount: number;
564
+ replyCount: number;
565
+ author: {
566
+ id: string;
567
+ username: string;
568
+ displayName: string;
569
+ avatar: string | null;
570
+ };
571
+ createdAt: string;
572
+ updatedAt: string;
573
+ }
574
+ interface CreateForumPostOptions {
575
+ title: string;
576
+ body: string;
577
+ tags?: string[];
578
+ }
579
+ interface EditForumPostOptions {
580
+ title?: string;
581
+ body?: string;
582
+ tags?: string[];
583
+ pinned?: boolean;
584
+ closed?: boolean;
585
+ }
586
+ interface FetchForumPostsOptions {
587
+ limit?: number;
588
+ before?: string;
589
+ }
590
+ interface ServerEvent {
591
+ id: string;
592
+ serverId: string;
593
+ channelId: string | null;
594
+ createdById: string;
595
+ title: string;
596
+ description: string | null;
597
+ imageUrl: string | null;
598
+ location: string | null;
599
+ startAt: string;
600
+ endAt: string | null;
601
+ attendeeCount?: number;
602
+ createdAt: string;
603
+ }
604
+ interface ServerEventAttendee {
605
+ eventId: string;
606
+ userId: string;
607
+ status: 'GOING' | 'MAYBE' | 'NOT_GOING';
608
+ user: {
609
+ id: string;
610
+ username: string;
611
+ displayName: string;
612
+ avatar: string | null;
613
+ };
614
+ createdAt: string;
615
+ }
616
+ interface CreateEventOptions {
617
+ title: string;
618
+ description?: string;
619
+ imageUrl?: string;
620
+ location?: string;
621
+ startAt: string;
622
+ endAt?: string;
623
+ channelId?: string;
624
+ }
625
+ interface EditEventOptions {
626
+ title?: string;
627
+ description?: string;
628
+ imageUrl?: string;
629
+ location?: string;
630
+ startAt?: string;
631
+ endAt?: string | null;
632
+ }
633
+ interface FetchEventsOptions {
634
+ limit?: number;
635
+ /** Only return events starting from now. */
636
+ upcoming?: boolean;
637
+ }
638
+ interface MemberXPData {
639
+ userId: string;
640
+ xp: number;
641
+ level: number;
642
+ joinedAt?: string;
643
+ }
644
+ interface LeaderboardEntry extends MemberXPData {
645
+ rank: number;
646
+ user: {
647
+ id: string;
648
+ username: string;
649
+ displayName: string;
650
+ avatar: string | null;
651
+ };
652
+ }
653
+ interface Warning {
654
+ id: string;
655
+ serverId: string;
656
+ userId: string;
657
+ moderatorId: string;
658
+ reason: string;
659
+ createdAt: string;
660
+ }
661
+ interface FetchWarningsOptions {
662
+ userId?: string;
663
+ }
664
+ type AutoModRuleType = 'BLOCKED_WORD' | 'BLOCKED_LINK';
665
+ interface AutoModRule {
666
+ id: string;
667
+ serverId: string;
668
+ type: AutoModRuleType;
669
+ value: string;
670
+ enabled: boolean;
671
+ createdAt: string;
672
+ }
673
+ interface CreateAutoModRuleOptions {
674
+ type: AutoModRuleType;
675
+ value: string;
676
+ enabled?: boolean;
677
+ }
678
+ interface EditAutoModRuleOptions {
679
+ value?: string;
680
+ enabled?: boolean;
681
+ }
682
+ interface UserProfile {
683
+ id: string;
684
+ username: string;
685
+ displayName: string;
686
+ avatar: string | null;
687
+ status: 'ONLINE' | 'IDLE' | 'DND' | 'OFFLINE';
688
+ bio: string | null;
689
+ isBot: boolean;
690
+ createdAt: string;
691
+ }
692
+ interface SoundboardClip {
693
+ id: string;
694
+ serverId: string;
695
+ name: string;
696
+ fileUrl: string;
697
+ duration: number;
698
+ uploadedById: string;
699
+ createdAt: string;
700
+ }
701
+ interface ServerStats {
702
+ serverId: string;
703
+ memberCount: number;
704
+ channelCount: number;
705
+ roleCount: number;
706
+ onlineCount: number;
707
+ messageCount: number;
708
+ }
709
+ interface BulkDeleteResult {
710
+ deleted: number;
711
+ }
712
+
713
+ declare class MessagesAPI {
714
+ private readonly http;
715
+ constructor(http: HttpClient);
716
+ /**
717
+ * Send a message to a channel.
718
+ *
719
+ * @example
720
+ * await client.messages.send('channel-id', { content: 'Hello!' })
721
+ * await client.messages.send('channel-id', {
722
+ * embed: { title: 'Report', description: 'Everything is fine.' }
723
+ * })
724
+ */
725
+ send(channelId: string, options: SendMessageOptions): Promise<Message>;
726
+ /**
727
+ * Edit a message previously sent by this bot.
728
+ */
729
+ edit(messageId: string, options: EditMessageOptions): Promise<Message>;
730
+ /**
731
+ * Delete a message previously sent by this bot.
732
+ */
733
+ delete(messageId: string): Promise<{
734
+ ok: true;
735
+ }>;
736
+ /**
737
+ * Fetch recent messages from a channel.
738
+ */
739
+ fetch(channelId: string, options?: FetchMessagesOptions): Promise<Message[]>;
740
+ /**
741
+ * Send a typing indicator in a channel (appears for ~5 seconds).
742
+ */
743
+ typing(channelId: string): Promise<{
744
+ ok: true;
745
+ }>;
746
+ /**
747
+ * Fetch a single message by ID.
748
+ *
749
+ * @example
750
+ * const msg = await client.messages.fetchOne('message-id')
751
+ */
752
+ fetchOne(messageId: string): Promise<Message>;
753
+ /**
754
+ * Pin a message in its channel.
755
+ * The bot must have the `messages.manage` scope.
756
+ *
757
+ * @example
758
+ * await client.messages.pin('message-id')
759
+ */
760
+ pin(messageId: string): Promise<{
761
+ ok: true;
762
+ }>;
763
+ /**
764
+ * Unpin a message.
765
+ *
766
+ * @example
767
+ * await client.messages.unpin('message-id')
768
+ */
769
+ unpin(messageId: string): Promise<{
770
+ ok: true;
771
+ }>;
772
+ /**
773
+ * Fetch all pinned messages in a channel.
774
+ *
775
+ * @example
776
+ * const pins = await client.messages.fetchPinned('channel-id')
777
+ */
778
+ fetchPinned(channelId: string): Promise<Message[]>;
779
+ /**
780
+ * Add a reaction to a message.
781
+ *
782
+ * @example
783
+ * await client.messages.addReaction('message-id', '👍')
784
+ */
785
+ addReaction(messageId: string, emoji: string): Promise<{
786
+ ok: true;
787
+ }>;
788
+ /**
789
+ * Remove the bot's reaction from a message.
790
+ *
791
+ * @example
792
+ * await client.messages.removeReaction('message-id', '👍')
793
+ */
794
+ removeReaction(messageId: string, emoji: string): Promise<{
795
+ ok: true;
796
+ }>;
797
+ /**
798
+ * Fetch all reactions on a message.
799
+ *
800
+ * @example
801
+ * const reactions = await client.messages.fetchReactions('message-id')
802
+ */
803
+ fetchReactions(messageId: string): Promise<ReactionDetail[]>;
804
+ }
805
+
806
+ declare class CommandsAPI {
807
+ private readonly http;
808
+ constructor(http: HttpClient);
809
+ /**
810
+ * Register (or fully replace) slash commands.
811
+ * Pass `guildId` to register guild-specific commands; omit for global.
812
+ *
813
+ * @example
814
+ * await client.commands.setSlash([
815
+ * { name: 'ping', description: 'Responds with pong!' },
816
+ * { name: 'ban', description: 'Ban a user', options: [
817
+ * { name: 'user', description: 'User to ban', type: 'USER', required: true }
818
+ * ]}
819
+ * ])
820
+ */
821
+ setSlash(commands: SlashCommandDefinition[], guildId?: string): Promise<{
822
+ registered: number;
823
+ }>;
824
+ /**
825
+ * Fetch all registered slash commands.
826
+ */
827
+ getSlash(guildId?: string): Promise<RegisteredSlashCommand[]>;
828
+ /**
829
+ * Delete a slash command by name.
830
+ */
831
+ deleteSlash(name: string): Promise<{
832
+ ok: true;
833
+ }>;
834
+ /**
835
+ * Register (or fully replace) prefix commands.
836
+ *
837
+ * @example
838
+ * await client.commands.setPrefix([
839
+ * { prefix: '!', name: 'help', description: 'Show help' },
840
+ * { prefix: '!', name: 'kick', description: 'Kick a user' },
841
+ * ])
842
+ */
843
+ setPrefix(commands: PrefixCommandDefinition[]): Promise<{
844
+ created: number;
845
+ }>;
846
+ /**
847
+ * Fetch all registered prefix commands.
848
+ */
849
+ getPrefix(): Promise<RegisteredPrefixCommand[]>;
850
+ /**
851
+ * Delete a prefix command.
852
+ */
853
+ deletePrefix(prefix: string, name: string): Promise<{
854
+ ok: true;
855
+ }>;
856
+ /**
857
+ * Register (or fully replace) context menu commands.
858
+ *
859
+ * @example
860
+ * await client.commands.setContext([
861
+ * { name: 'Report message', target: 'MESSAGE' },
862
+ * { name: 'View profile', target: 'USER' },
863
+ * ])
864
+ */
865
+ setContext(commands: ContextCommandDefinition[]): Promise<{
866
+ created: number;
867
+ }>;
868
+ /**
869
+ * Fetch all registered context menu commands.
870
+ */
871
+ getContext(): Promise<RegisteredContextCommand[]>;
872
+ /**
873
+ * Delete a context menu command by name.
874
+ */
875
+ deleteContext(name: string): Promise<{
876
+ ok: true;
877
+ }>;
878
+ }
879
+
880
+ declare class MembersAPI {
881
+ private readonly http;
882
+ constructor(http: HttpClient);
883
+ /**
884
+ * Fetch members of a server the bot is in.
885
+ * Supports filtering by role and searching by username/displayName.
886
+ *
887
+ * @example
888
+ * const members = await client.members.list('server-id', { limit: 50 })
889
+ * const admins = await client.members.list('server-id', { role: 'ADMIN' })
890
+ * const found = await client.members.list('server-id', { search: 'john' })
891
+ */
892
+ list(serverId: string, options?: FetchMembersOptions): Promise<Member[]>;
893
+ /**
894
+ * Fetch a single member from a server by their user ID.
895
+ * Returns the member's custom role if assigned.
896
+ * Requires the `members.read` scope.
897
+ *
898
+ * @example
899
+ * const member = await client.members.fetch('server-id', 'user-id')
900
+ * console.log(member.customRole?.name ?? 'No custom role')
901
+ */
902
+ fetch(serverId: string, userId: string): Promise<SingleMember>;
903
+ /**
904
+ * Kick a member from a server.
905
+ * Bots cannot kick owners or admins (403 will be thrown).
906
+ *
907
+ * @example
908
+ * await client.members.kick('server-id', 'user-id')
909
+ */
910
+ kick(serverId: string, userId: string): Promise<{
911
+ ok: true;
912
+ }>;
913
+ /**
914
+ * Ban a member from a server.
915
+ * Bots cannot ban owners or admins (403 will be thrown).
916
+ *
917
+ * @example
918
+ * await client.members.ban('server-id', 'user-id', 'Spamming')
919
+ */
920
+ ban(serverId: string, userId: string, reason?: string): Promise<{
921
+ ok: true;
922
+ }>;
923
+ /**
924
+ * Unban a previously banned user.
925
+ * Requires the `members.ban` scope.
926
+ *
927
+ * @example
928
+ * await client.members.unban('server-id', 'user-id')
929
+ */
930
+ unban(serverId: string, userId: string): Promise<{
931
+ ok: true;
932
+ }>;
933
+ /**
934
+ * Fetch the ban list for a server.
935
+ * Requires the `members.ban` scope.
936
+ *
937
+ * @example
938
+ * const bans = await client.members.listBans('server-id')
939
+ * for (const ban of bans) {
940
+ * console.log(`${ban.username} — ${ban.reason ?? 'No reason'}`)
941
+ * }
942
+ */
943
+ listBans(serverId: string): Promise<BanEntry[]>;
944
+ /**
945
+ * Send a direct message to a user (DM).
946
+ * Requires the `messages.write` scope.
947
+ *
948
+ * @example
949
+ * await client.members.dm('user-id', { content: 'Hello!' })
950
+ * await client.members.dm('user-id', 'Hello from the bot!')
951
+ */
952
+ dm(userId: string, options: string | Omit<SendMessageOptions, 'replyToId'>): Promise<Message>;
953
+ /**
954
+ * Add a role to a member.
955
+ * Requires the `members.roles` scope.
956
+ *
957
+ * @example
958
+ * await client.members.addRole('server-id', 'user-id', 'role-id')
959
+ */
960
+ addRole(serverId: string, userId: string, roleId: string): Promise<{
961
+ ok: true;
962
+ }>;
963
+ /**
964
+ * Remove a role from a member.
965
+ * Requires the `members.roles` scope.
966
+ *
967
+ * @example
968
+ * await client.members.removeRole('server-id', 'user-id', 'role-id')
969
+ */
970
+ removeRole(serverId: string, userId: string, roleId: string): Promise<{
971
+ ok: true;
972
+ }>;
973
+ /**
974
+ * Issue a warning to a member.
975
+ * Requires the `members.moderate` scope.
976
+ *
977
+ * @example
978
+ * await client.members.warn('server-id', 'user-id', 'Spamming')
979
+ */
980
+ warn(serverId: string, userId: string, reason: string): Promise<Warning>;
981
+ /**
982
+ * Fetch warnings for a server (or optionally a specific user).
983
+ * Requires the `members.moderate` scope.
984
+ *
985
+ * @example
986
+ * const all = await client.members.fetchWarnings('server-id')
987
+ * const userWarnings = await client.members.fetchWarnings('server-id', { userId: 'user-id' })
988
+ */
989
+ fetchWarnings(serverId: string, options?: FetchWarningsOptions): Promise<Warning[]>;
990
+ /**
991
+ * Remove a warning by its ID.
992
+ * Requires the `members.moderate` scope.
993
+ *
994
+ * @example
995
+ * await client.members.removeWarning('warning-id')
996
+ */
997
+ removeWarning(warningId: string): Promise<{
998
+ ok: true;
999
+ }>;
1000
+ /**
1001
+ * Get a member's XP and level.
1002
+ * Requires the `members.read` scope.
1003
+ *
1004
+ * @example
1005
+ * const xpData = await client.members.getXP('server-id', 'user-id')
1006
+ * console.log(`Level ${xpData.level} — ${xpData.xp} XP`)
1007
+ */
1008
+ getXP(serverId: string, userId: string): Promise<MemberXPData>;
1009
+ /**
1010
+ * Set or add XP to a member.
1011
+ * Requires the `members.manage` scope.
1012
+ *
1013
+ * @example
1014
+ * // Add 50 XP
1015
+ * await client.members.setXP('server-id', 'user-id', { add: 50 })
1016
+ * // Set XP to a specific value
1017
+ * await client.members.setXP('server-id', 'user-id', { xp: 1000 })
1018
+ */
1019
+ setXP(serverId: string, userId: string, options: {
1020
+ xp?: number;
1021
+ add?: number;
1022
+ }): Promise<MemberXPData>;
1023
+ /**
1024
+ * Get the XP leaderboard for a server.
1025
+ * Requires the `members.read` scope.
1026
+ *
1027
+ * @example
1028
+ * const top10 = await client.members.leaderboard('server-id', 10)
1029
+ */
1030
+ leaderboard(serverId: string, limit?: number): Promise<LeaderboardEntry[]>;
1031
+ }
1032
+
1033
+ declare class ServersAPI {
1034
+ private readonly http;
1035
+ constructor(http: HttpClient);
1036
+ /**
1037
+ * Fetch all servers the bot is currently a member of.
1038
+ *
1039
+ * @example
1040
+ * const servers = await client.servers.list()
1041
+ * console.log(`Bot is in ${servers.length} servers`)
1042
+ */
1043
+ list(): Promise<NovaServer[]>;
1044
+ /**
1045
+ * Fetch a single server by ID.
1046
+ * The bot must be a member of the server.
1047
+ *
1048
+ * @example
1049
+ * const server = await client.servers.fetch('server-id')
1050
+ * console.log(`${server.name} — ${server.memberCount} members`)
1051
+ */
1052
+ fetch(serverId: string): Promise<NovaServer>;
1053
+ /**
1054
+ * Update a server's name, description, or icon.
1055
+ * Requires the `server.manage` scope.
1056
+ *
1057
+ * @example
1058
+ * await client.servers.update('server-id', { name: 'Better Name', description: 'A great place!' })
1059
+ */
1060
+ update(serverId: string, options: ServerUpdateOptions): Promise<NovaServer>;
1061
+ /**
1062
+ * Fetch all roles in a server.
1063
+ * Results are sorted by position (lowest first).
1064
+ *
1065
+ * @example
1066
+ * const roles = await client.servers.listRoles('server-id')
1067
+ * const adminRole = roles.find(r => r.name === 'Admin')
1068
+ */
1069
+ listRoles(serverId: string): Promise<Role[]>;
1070
+ /**
1071
+ * Fetch all channel categories in a server.
1072
+ *
1073
+ * @example
1074
+ * const categories = await client.servers.listCategories('server-id')
1075
+ */
1076
+ listCategories(serverId: string): Promise<ChannelCategory[]>;
1077
+ /**
1078
+ * Get server statistics (member count, message count, etc.).
1079
+ *
1080
+ * @example
1081
+ * const stats = await client.servers.getStats('server-id')
1082
+ * console.log(`${stats.onlineCount} online / ${stats.memberCount} total`)
1083
+ */
1084
+ getStats(serverId: string): Promise<ServerStats>;
1085
+ /**
1086
+ * Fetch all soundboard clips uploaded to a server.
1087
+ *
1088
+ * @example
1089
+ * const clips = await client.servers.listSoundboard('server-id')
1090
+ */
1091
+ listSoundboard(serverId: string): Promise<SoundboardClip[]>;
1092
+ }
1093
+
1094
+ declare class InteractionsAPI {
1095
+ private readonly http;
1096
+ private readonly emitter;
1097
+ constructor(http: HttpClient, emitter: EventEmitter);
1098
+ /**
1099
+ * Acknowledge an interaction without sending a visible response.
1100
+ * Shows a loading state to the user. You must follow up with `respond()`.
1101
+ *
1102
+ * @example
1103
+ * client.on('interactionCreate', async (interaction) => {
1104
+ * await client.interactions.ack(interaction.id)
1105
+ * // ... do work ...
1106
+ * await client.interactions.respond(interaction.id, { content: 'Done!' })
1107
+ * })
1108
+ */
1109
+ ack(interactionId: string): Promise<{
1110
+ ok: true;
1111
+ }>;
1112
+ /**
1113
+ * Respond to an interaction with a message.
1114
+ * Set `ephemeral: true` to only show the response to the triggering user.
1115
+ *
1116
+ * @example
1117
+ * await client.interactions.respond(interaction.id, {
1118
+ * content: 'Pong!',
1119
+ * ephemeral: true,
1120
+ * })
1121
+ */
1122
+ respond(interactionId: string, options: RespondInteractionOptions): Promise<Message | {
1123
+ ok: true;
1124
+ ephemeral: true;
1125
+ }>;
1126
+ /**
1127
+ * Respond to an autocomplete interaction with a list of suggested choices.
1128
+ * The gateway fires `AUTOCOMPLETE` interactions when a user is typing in
1129
+ * an option that has `autocomplete: true`. Call this within ~3 seconds.
1130
+ *
1131
+ * @example
1132
+ * client.autocomplete('search', async (interaction) => {
1133
+ * const query = interaction.autocomplete?.value ?? ''
1134
+ * const results = await db.search(query)
1135
+ * await client.interactions.autocomplete(interaction.id,
1136
+ * results.map(r => ({ name: r.title, value: r.id }))
1137
+ * )
1138
+ * })
1139
+ */
1140
+ autocomplete(interactionId: string, choices: Array<{
1141
+ name: string;
1142
+ value: string | number;
1143
+ }>): Promise<{
1144
+ ok: true;
1145
+ }>;
1146
+ /**
1147
+ * Poll for pending (unacknowledged) interactions.
1148
+ * Useful when not using the WebSocket gateway.
1149
+ *
1150
+ * @example
1151
+ * const pending = await client.interactions.poll({ limit: 20 })
1152
+ * for (const i of pending) {
1153
+ * await client.interactions.respond(i.id, { content: 'Got it!' })
1154
+ * }
1155
+ */
1156
+ poll(options?: PollInteractionsOptions): Promise<Interaction[]>;
1157
+ /**
1158
+ * Open a modal for the user who triggered an interaction and await their submission.
1159
+ *
1160
+ * Internally this:
1161
+ * 1. Calls `respond(interactionId, { modal })` to push the modal to the client UI.
1162
+ * 2. Listens for the next `interactionCreate` event whose type is `MODAL_SUBMIT`
1163
+ * and whose `customId` matches your modal's `customId`.
1164
+ * 3. Resolves with the submitted `Interaction` (containing `modalData`), or `null`
1165
+ * if the user closes the modal without submitting within the timeout.
1166
+ *
1167
+ * @param interactionId - ID of the triggering interaction.
1168
+ * @param modal - Modal definition (title, customId, fields).
1169
+ * @param options.timeout - Max milliseconds to wait (default: 300 000 = 5 min).
1170
+ *
1171
+ * @example
1172
+ * client.on('interactionCreate', async (interaction) => {
1173
+ * if (interaction.commandName === 'report') {
1174
+ * const submitted = await client.interactions.awaitModal(interaction.id, {
1175
+ * title: 'Submit a report',
1176
+ * customId: 'report_modal',
1177
+ * fields: [
1178
+ * { customId: 'reason', label: 'Reason', type: 'paragraph', required: true, maxLength: 500 },
1179
+ * ],
1180
+ * })
1181
+ *
1182
+ * if (!submitted) {
1183
+ * // User dismissed the modal or timed out — nothing to do
1184
+ * return
1185
+ * }
1186
+ *
1187
+ * const reason = submitted.modalData?.reason
1188
+ * await client.interactions.respond(submitted.id, {
1189
+ * content: `Report received: ${reason}`,
1190
+ * ephemeral: true,
1191
+ * })
1192
+ * }
1193
+ * })
1194
+ */
1195
+ awaitModal(interactionId: string, modal: BotModalDefinition, options?: {
1196
+ timeout?: number;
1197
+ }): Promise<Interaction | null>;
1198
+ }
1199
+
1200
+ declare class PermissionsAPI {
1201
+ private readonly http;
1202
+ constructor(http: HttpClient);
1203
+ /**
1204
+ * Fetch the bot's effective permissions for a given scope.
1205
+ *
1206
+ * Permissions are merged in priority order:
1207
+ * 1. Server-wide base permissions
1208
+ * 2. Role override (if `roleId` provided)
1209
+ * 3. Channel override (if `channelId` provided, highest priority)
1210
+ *
1211
+ * `serverId` is required. `channelId` and `roleId` are optional filters.
1212
+ *
1213
+ * @example
1214
+ * // Effective server-wide permissions
1215
+ * const { permissions } = await client.permissions.get({
1216
+ * serverId: 'server-id',
1217
+ * })
1218
+ * console.log(permissions) // { kick_members: true, ban_members: false, ... }
1219
+ *
1220
+ * @example
1221
+ * // Scoped to a specific channel
1222
+ * const { permissions } = await client.permissions.get({
1223
+ * serverId: 'server-id',
1224
+ * channelId: 'channel-id',
1225
+ * })
1226
+ *
1227
+ * @example
1228
+ * // Scoped to a specific role
1229
+ * const { permissions } = await client.permissions.get({
1230
+ * serverId: 'server-id',
1231
+ * roleId: 'role-id',
1232
+ * })
1233
+ */
1234
+ get(options: PermissionsQueryOptions): Promise<PermissionsResult>;
1235
+ }
1236
+
1237
+ declare class ChannelsAPI {
1238
+ private readonly http;
1239
+ constructor(http: HttpClient);
1240
+ /**
1241
+ * Fetch all channels in a server the bot is a member of.
1242
+ *
1243
+ * @example
1244
+ * const channels = await client.channels.list('server-id')
1245
+ * const textChannels = channels.filter(c => c.type === 'TEXT')
1246
+ */
1247
+ list(serverId: string): Promise<Channel[]>;
1248
+ /**
1249
+ * Fetch a single channel by ID.
1250
+ *
1251
+ * @example
1252
+ * const channel = await client.channels.fetch('channel-id')
1253
+ * console.log(channel.name, channel.type)
1254
+ */
1255
+ fetch(channelId: string): Promise<Channel>;
1256
+ /**
1257
+ * Create a new channel in a server.
1258
+ * Requires the `channels.manage` scope.
1259
+ *
1260
+ * @example
1261
+ * const channel = await client.channels.create('server-id', {
1262
+ * name: 'announcements',
1263
+ * type: 'ANNOUNCEMENT',
1264
+ * topic: 'Official announcements only',
1265
+ * })
1266
+ */
1267
+ create(serverId: string, options: CreateChannelOptions): Promise<Channel>;
1268
+ /**
1269
+ * Edit an existing channel.
1270
+ * Requires the `channels.manage` scope.
1271
+ *
1272
+ * @example
1273
+ * await client.channels.edit('channel-id', { topic: 'New topic!' })
1274
+ */
1275
+ edit(channelId: string, options: EditChannelOptions): Promise<Channel>;
1276
+ /**
1277
+ * Delete a channel.
1278
+ * Requires the `channels.manage` scope.
1279
+ *
1280
+ * @example
1281
+ * await client.channels.delete('channel-id')
1282
+ */
1283
+ delete(channelId: string): Promise<{
1284
+ ok: true;
1285
+ }>;
1286
+ /**
1287
+ * Fetch messages from a channel.
1288
+ *
1289
+ * @example
1290
+ * const messages = await client.channels.fetchMessages('channel-id', { limit: 50 })
1291
+ */
1292
+ fetchMessages(channelId: string, options?: FetchMessagesOptions): Promise<Message[]>;
1293
+ /**
1294
+ * Fetch all pinned messages in a channel.
1295
+ *
1296
+ * @example
1297
+ * const pins = await client.channels.fetchPins('channel-id')
1298
+ */
1299
+ fetchPins(channelId: string): Promise<Message[]>;
1300
+ /**
1301
+ * Send a typing indicator in a channel.
1302
+ * Displayed to users for ~5 seconds.
1303
+ *
1304
+ * @example
1305
+ * await client.channels.startTyping('channel-id')
1306
+ */
1307
+ startTyping(channelId: string): Promise<{
1308
+ ok: true;
1309
+ }>;
1310
+ /**
1311
+ * Bulk delete up to 100 messages from a channel at once.
1312
+ * Requires the `messages.manage` scope.
1313
+ * Soft-deletes all specified messages in a single operation.
1314
+ *
1315
+ * @example
1316
+ * const result = await client.channels.bulkDelete('channel-id', ['msg1', 'msg2', 'msg3'])
1317
+ * console.log(`Deleted ${result.deleted} messages`)
1318
+ */
1319
+ bulkDelete(channelId: string, messageIds: string[]): Promise<BulkDeleteResult>;
1320
+ }
1321
+
1322
+ declare class ReactionsAPI {
1323
+ private readonly http;
1324
+ constructor(http: HttpClient);
1325
+ /**
1326
+ * Add a reaction to a message.
1327
+ * Use a plain emoji character or a custom emoji ID.
1328
+ *
1329
+ * @example
1330
+ * await client.reactions.add('message-id', '👍')
1331
+ * await client.reactions.add('message-id', '🎉')
1332
+ */
1333
+ add(messageId: string, emoji: string): Promise<{
1334
+ ok: true;
1335
+ }>;
1336
+ /**
1337
+ * Remove the bot's reaction from a message.
1338
+ *
1339
+ * @example
1340
+ * await client.reactions.remove('message-id', '👍')
1341
+ */
1342
+ remove(messageId: string, emoji: string): Promise<{
1343
+ ok: true;
1344
+ }>;
1345
+ /**
1346
+ * Remove all reactions from a message.
1347
+ * Requires the `messages.manage` scope.
1348
+ *
1349
+ * @example
1350
+ * await client.reactions.removeAll('message-id')
1351
+ */
1352
+ removeAll(messageId: string): Promise<{
1353
+ ok: true;
1354
+ }>;
1355
+ /**
1356
+ * Remove all reactions of a specific emoji from a message.
1357
+ * Requires the `messages.manage` scope.
1358
+ *
1359
+ * @example
1360
+ * await client.reactions.removeEmoji('message-id', '👍')
1361
+ */
1362
+ removeEmoji(messageId: string, emoji: string): Promise<{
1363
+ ok: true;
1364
+ }>;
1365
+ /**
1366
+ * Fetch all reactions on a message, broken down by emoji.
1367
+ *
1368
+ * @example
1369
+ * const reactions = await client.reactions.fetch('message-id')
1370
+ * for (const r of reactions) {
1371
+ * console.log(`${r.emoji} — ${r.count} reactions from ${r.users.map(u => u.username).join(', ')}`)
1372
+ * }
1373
+ */
1374
+ fetch(messageId: string): Promise<ReactionDetail[]>;
1375
+ /**
1376
+ * Fetch reactions for a specific emoji on a message.
1377
+ *
1378
+ * @example
1379
+ * const detail = await client.reactions.fetchEmoji('message-id', '👍')
1380
+ * console.log(`${detail.count} thumbs ups`)
1381
+ */
1382
+ fetchEmoji(messageId: string, emoji: string): Promise<ReactionDetail>;
1383
+ }
1384
+
1385
+ declare class RolesAPI {
1386
+ private readonly http;
1387
+ constructor(http: HttpClient);
1388
+ /**
1389
+ * List all custom roles in a server, sorted by position.
1390
+ *
1391
+ * @example
1392
+ * const roles = await client.roles.list('server-id')
1393
+ * const adminRole = roles.find(r => r.name === 'Admin')
1394
+ */
1395
+ list(serverId: string): Promise<Role[]>;
1396
+ /**
1397
+ * Create a new custom role in a server.
1398
+ * Requires the `roles.manage` scope.
1399
+ *
1400
+ * @example
1401
+ * const role = await client.roles.create('server-id', {
1402
+ * name: 'Verified',
1403
+ * color: '#00d4ff',
1404
+ * hoist: true,
1405
+ * permissions: { sendMessages: true, addReactions: true },
1406
+ * })
1407
+ */
1408
+ create(serverId: string, options: RoleCreateOptions): Promise<Role>;
1409
+ /**
1410
+ * Edit an existing role.
1411
+ * Requires the `roles.manage` scope.
1412
+ *
1413
+ * @example
1414
+ * await client.roles.edit('role-id', { color: '#ff0000', name: 'Danger' })
1415
+ */
1416
+ edit(roleId: string, options: RoleEditOptions): Promise<Role>;
1417
+ /**
1418
+ * Delete a custom role from a server.
1419
+ * Any member currently assigned this role will have it removed automatically.
1420
+ * Requires the `roles.manage` scope.
1421
+ *
1422
+ * @example
1423
+ * await client.roles.delete('role-id')
1424
+ */
1425
+ delete(roleId: string): Promise<{
1426
+ ok: true;
1427
+ }>;
1428
+ /**
1429
+ * Assign a custom role to a server member.
1430
+ * Requires the `members.roles` scope.
1431
+ *
1432
+ * @example
1433
+ * await client.roles.assign('server-id', 'user-id', 'role-id')
1434
+ */
1435
+ assign(serverId: string, userId: string, roleId: string): Promise<{
1436
+ ok: true;
1437
+ }>;
1438
+ /**
1439
+ * Remove a custom role from a server member.
1440
+ * Requires the `members.roles` scope.
1441
+ *
1442
+ * @example
1443
+ * await client.roles.remove('server-id', 'user-id', 'role-id')
1444
+ */
1445
+ remove(serverId: string, userId: string, roleId: string): Promise<{
1446
+ ok: true;
1447
+ }>;
1448
+ }
1449
+
1450
+ declare class InvitesAPI {
1451
+ private readonly http;
1452
+ constructor(http: HttpClient);
1453
+ /**
1454
+ * List all active invites for a server.
1455
+ *
1456
+ * @example
1457
+ * const invites = await client.invites.list('server-id')
1458
+ * console.log(`${invites.length} active invites`)
1459
+ */
1460
+ list(serverId: string): Promise<Invite[]>;
1461
+ /**
1462
+ * Create a new invite for a server.
1463
+ * Requires the `invites.manage` scope.
1464
+ *
1465
+ * @example
1466
+ * // A one-time invite that expires in 24 hours
1467
+ * const invite = await client.invites.create('server-id', {
1468
+ * maxUses: 1,
1469
+ * expiresAt: new Date(Date.now() + 86_400_000).toISOString(),
1470
+ * })
1471
+ * console.log(`https://novachatapp.com/invite/${invite.code}`)
1472
+ */
1473
+ create(serverId: string, options?: InviteCreateOptions): Promise<Invite>;
1474
+ /**
1475
+ * Fetch a single invite by its code.
1476
+ *
1477
+ * @example
1478
+ * const invite = await client.invites.fetch('abc123')
1479
+ * console.log(`${invite.uses} / ${invite.maxUses ?? '∞'} uses`)
1480
+ */
1481
+ fetch(code: string): Promise<Invite>;
1482
+ /**
1483
+ * Revoke (delete) an invite.
1484
+ * Requires the `invites.manage` scope.
1485
+ *
1486
+ * @example
1487
+ * await client.invites.revoke('abc123')
1488
+ */
1489
+ revoke(code: string): Promise<{
1490
+ ok: true;
1491
+ }>;
1492
+ }
1493
+
1494
+ declare class WebhooksAPI {
1495
+ private readonly http;
1496
+ constructor(http: HttpClient);
1497
+ /**
1498
+ * List all webhooks in a channel.
1499
+ * Requires the `webhooks.manage` scope.
1500
+ *
1501
+ * @example
1502
+ * const webhooks = await client.webhooks.list('channel-id')
1503
+ */
1504
+ list(channelId: string): Promise<Webhook[]>;
1505
+ /**
1506
+ * Create a webhook in a channel.
1507
+ * Requires the `webhooks.manage` scope.
1508
+ *
1509
+ * @example
1510
+ * const webhook = await client.webhooks.create('channel-id', { name: 'Announcements' })
1511
+ * console.log('Token:', webhook.token)
1512
+ */
1513
+ create(channelId: string, options: WebhookCreateOptions): Promise<Webhook>;
1514
+ /**
1515
+ * Fetch a webhook by its ID.
1516
+ * Requires the `webhooks.manage` scope.
1517
+ *
1518
+ * @example
1519
+ * const webhook = await client.webhooks.fetch('webhook-id')
1520
+ */
1521
+ fetch(webhookId: string): Promise<Webhook>;
1522
+ /**
1523
+ * Edit a webhook's name and/or target channel.
1524
+ * Requires the `webhooks.manage` scope.
1525
+ *
1526
+ * @example
1527
+ * await client.webhooks.edit('webhook-id', { name: 'New Name', channelId: 'other-channel' })
1528
+ */
1529
+ edit(webhookId: string, options: WebhookEditOptions): Promise<Webhook>;
1530
+ /**
1531
+ * Delete a webhook.
1532
+ * Requires the `webhooks.manage` scope.
1533
+ *
1534
+ * @example
1535
+ * await client.webhooks.delete('webhook-id')
1536
+ */
1537
+ delete(webhookId: string): Promise<{
1538
+ ok: true;
1539
+ }>;
1540
+ /**
1541
+ * Execute a webhook — post a message to the webhook's channel.
1542
+ * Does not require any extra scope (uses the webhook data already owned by
1543
+ * this bot application).
1544
+ *
1545
+ * @example
1546
+ * await client.webhooks.execute('webhook-id', {
1547
+ * content: '🚀 Deployment successful!',
1548
+ * username: 'Deploy Bot',
1549
+ * })
1550
+ */
1551
+ execute(webhookId: string, options: ExecuteWebhookOptions): Promise<Message>;
1552
+ }
1553
+
1554
+ declare class AuditLogAPI {
1555
+ private readonly http;
1556
+ constructor(http: HttpClient);
1557
+ /**
1558
+ * Fetch the audit log for a server.
1559
+ * Requires the `audit-log.read` scope.
1560
+ *
1561
+ * You can filter by action type, actor user ID, and paginate backwards
1562
+ * using the `before` cursor (an ISO timestamp).
1563
+ *
1564
+ * @example
1565
+ * // Most recent 50 entries
1566
+ * const entries = await client.auditLog.fetch('server-id')
1567
+ *
1568
+ * // Only kick and ban actions
1569
+ * const modActions = await client.auditLog.fetch('server-id', {
1570
+ * action: 'member.banned',
1571
+ * limit: 20,
1572
+ * })
1573
+ *
1574
+ * // All actions performed by a specific user
1575
+ * const byUser = await client.auditLog.fetch('server-id', { userId: 'user-id' })
1576
+ */
1577
+ fetch(serverId: string, options?: FetchAuditLogsOptions): Promise<AuditLogEntry[]>;
1578
+ }
1579
+
1580
+ declare class ForumAPI {
1581
+ private readonly http;
1582
+ constructor(http: HttpClient);
1583
+ /**
1584
+ * List forum posts in a FORUM channel.
1585
+ *
1586
+ * @example
1587
+ * const posts = await client.forum.list('channel-id')
1588
+ */
1589
+ list(channelId: string, options?: FetchForumPostsOptions): Promise<ForumPost[]>;
1590
+ /**
1591
+ * Create a forum post in a FORUM channel.
1592
+ *
1593
+ * @example
1594
+ * const post = await client.forum.create('channel-id', {
1595
+ * title: 'Ideas thread',
1596
+ * body: 'Post your ideas here!',
1597
+ * tags: ['idea', 'discussion'],
1598
+ * })
1599
+ */
1600
+ create(channelId: string, options: CreateForumPostOptions): Promise<ForumPost>;
1601
+ /**
1602
+ * Edit a forum post.
1603
+ * The bot must be the author of the post.
1604
+ *
1605
+ * @example
1606
+ * await client.forum.edit('post-id', { closed: true })
1607
+ */
1608
+ edit(postId: string, options: EditForumPostOptions): Promise<ForumPost>;
1609
+ /**
1610
+ * Delete a forum post.
1611
+ * The bot must be the author of the post.
1612
+ *
1613
+ * @example
1614
+ * await client.forum.delete('post-id')
1615
+ */
1616
+ delete(postId: string): Promise<void>;
1617
+ }
1618
+
1619
+ declare class EventsAPI {
1620
+ private readonly http;
1621
+ constructor(http: HttpClient);
1622
+ /**
1623
+ * List server events.
1624
+ *
1625
+ * @example
1626
+ * const events = await client.events.list('server-id', { upcoming: true })
1627
+ */
1628
+ list(serverId: string, options?: FetchEventsOptions): Promise<ServerEvent[]>;
1629
+ /**
1630
+ * Fetch a single server event by ID.
1631
+ * Returns full attendee list.
1632
+ *
1633
+ * @example
1634
+ * const event = await client.events.fetch('event-id')
1635
+ */
1636
+ fetch(eventId: string): Promise<ServerEvent & {
1637
+ attendees: ServerEventAttendee[];
1638
+ }>;
1639
+ /**
1640
+ * Create a server event.
1641
+ *
1642
+ * @example
1643
+ * const event = await client.events.create('server-id', {
1644
+ * title: 'Game Night',
1645
+ * description: 'Friday fun!',
1646
+ * startAt: new Date(Date.now() + 86400_000).toISOString(),
1647
+ * })
1648
+ */
1649
+ create(serverId: string, options: CreateEventOptions): Promise<ServerEvent>;
1650
+ /**
1651
+ * Edit a server event.
1652
+ *
1653
+ * @example
1654
+ * await client.events.edit('event-id', { title: 'Game Night v2' })
1655
+ */
1656
+ edit(eventId: string, options: EditEventOptions): Promise<ServerEvent>;
1657
+ /**
1658
+ * Delete a server event.
1659
+ *
1660
+ * @example
1661
+ * await client.events.delete('event-id')
1662
+ */
1663
+ delete(eventId: string): Promise<void>;
1664
+ }
1665
+
1666
+ declare class CategoriesAPI {
1667
+ private readonly http;
1668
+ constructor(http: HttpClient);
1669
+ /**
1670
+ * List all channel categories in a server, ordered by position.
1671
+ *
1672
+ * @example
1673
+ * const cats = await client.categories.list('server-id')
1674
+ */
1675
+ list(serverId: string): Promise<ChannelCategory[]>;
1676
+ /**
1677
+ * Create a new channel category.
1678
+ *
1679
+ * @example
1680
+ * const cat = await client.categories.create('server-id', { name: 'General', position: 0 })
1681
+ */
1682
+ create(serverId: string, options: CreateCategoryOptions): Promise<ChannelCategory>;
1683
+ /**
1684
+ * Edit an existing channel category.
1685
+ *
1686
+ * @example
1687
+ * await client.categories.edit('cat-id', { name: 'Renamed' })
1688
+ */
1689
+ edit(categoryId: string, options: EditCategoryOptions): Promise<ChannelCategory>;
1690
+ /**
1691
+ * Delete a channel category.
1692
+ *
1693
+ * @example
1694
+ * await client.categories.delete('cat-id')
1695
+ */
1696
+ delete(categoryId: string): Promise<void>;
1697
+ }
1698
+
1699
+ declare class AutoModAPI {
1700
+ private readonly http;
1701
+ constructor(http: HttpClient);
1702
+ /**
1703
+ * List all automod rules for a server.
1704
+ *
1705
+ * @example
1706
+ * const rules = await client.automod.list('server-id')
1707
+ */
1708
+ list(serverId: string): Promise<AutoModRule[]>;
1709
+ /**
1710
+ * Create a new automod rule.
1711
+ *
1712
+ * @example
1713
+ * await client.automod.create('server-id', { type: 'BLOCKED_WORD', value: 'badword' })
1714
+ * await client.automod.create('server-id', { type: 'BLOCKED_LINK', value: 'example.com' })
1715
+ */
1716
+ create(serverId: string, options: CreateAutoModRuleOptions): Promise<AutoModRule>;
1717
+ /**
1718
+ * Enable / disable a rule or update the blocked value.
1719
+ *
1720
+ * @example
1721
+ * await client.automod.edit('rule-id', { enabled: false })
1722
+ */
1723
+ edit(ruleId: string, options: EditAutoModRuleOptions): Promise<AutoModRule>;
1724
+ /**
1725
+ * Delete an automod rule.
1726
+ *
1727
+ * @example
1728
+ * await client.automod.delete('rule-id')
1729
+ */
1730
+ delete(ruleId: string): Promise<void>;
1731
+ }
1732
+
1733
+ declare class UsersAPI {
1734
+ private readonly http;
1735
+ constructor(http: HttpClient);
1736
+ /**
1737
+ * Fetch a user's public profile by ID.
1738
+ *
1739
+ * @example
1740
+ * const user = await client.users.fetch('user-id')
1741
+ * console.log(user.displayName)
1742
+ */
1743
+ fetch(userId: string): Promise<UserProfile>;
1744
+ }
1745
+
1746
+ type TextInputStyle = 'short' | 'paragraph';
1747
+ /**
1748
+ * Fluent builder for a single text-input field inside a modal.
1749
+ *
1750
+ * @example
1751
+ * new TextInputBuilder()
1752
+ * .setCustomId('reason')
1753
+ * .setLabel('Reason')
1754
+ * .setStyle('paragraph')
1755
+ * .setPlaceholder('Describe the issue in detail…')
1756
+ * .setRequired(true)
1757
+ * .setMaxLength(1000)
1758
+ */
1759
+ declare class TextInputBuilder {
1760
+ private _data;
1761
+ /** Unique ID for this field — the key in `interaction.modalData` on submit. */
1762
+ setCustomId(customId: string): this;
1763
+ /** Label shown above the input inside the modal. */
1764
+ setLabel(label: string): this;
1765
+ /**
1766
+ * Input style:
1767
+ * - `'short'` — single-line text input
1768
+ * - `'paragraph'` — multi-line textarea
1769
+ */
1770
+ setStyle(style: TextInputStyle): this;
1771
+ /** Greyed-out hint text shown when the field is empty. */
1772
+ setPlaceholder(placeholder: string): this;
1773
+ /** Whether the user must fill in this field before submitting. */
1774
+ setRequired(required?: boolean): this;
1775
+ /** Minimum number of characters required. */
1776
+ setMinLength(min: number): this;
1777
+ /** Maximum number of characters allowed. */
1778
+ setMaxLength(max: number): this;
1779
+ /** Pre-filled default value. */
1780
+ setValue(value: string): this;
1781
+ toJSON(): BotModalField;
1782
+ }
1783
+
1784
+ type FieldLike = TextInputBuilder | BotModalField;
1785
+ /**
1786
+ * Fluent builder for bot modal dialogs.
1787
+ *
1788
+ * @example
1789
+ * const modal = new ModalBuilder()
1790
+ * .setTitle('Submit a report')
1791
+ * .setCustomId('report_modal')
1792
+ * .addField(
1793
+ * new TextInputBuilder()
1794
+ * .setCustomId('reason')
1795
+ * .setLabel('Reason')
1796
+ * .setStyle('paragraph')
1797
+ * .setRequired(true)
1798
+ * .setMaxLength(1000)
1799
+ * )
1800
+ * .addField(
1801
+ * new TextInputBuilder()
1802
+ * .setCustomId('proof')
1803
+ * .setLabel('Evidence (optional URL)')
1804
+ * .setStyle('short')
1805
+ * )
1806
+ *
1807
+ * const submitted = await interaction.openModal(modal)
1808
+ * if (submitted) {
1809
+ * const reason = submitted.modalData.reason
1810
+ * }
1811
+ */
1812
+ declare class ModalBuilder {
1813
+ private _title;
1814
+ private _customId;
1815
+ private readonly _fields;
1816
+ /** Title shown at the top of the modal dialog. */
1817
+ setTitle(title: string): this;
1818
+ /** Custom ID passed back with the `MODAL_SUBMIT` interaction. */
1819
+ setCustomId(customId: string): this;
1820
+ /** Add a single text-input field. */
1821
+ addField(field: FieldLike): this;
1822
+ /** Add multiple fields at once. */
1823
+ addFields(...fields: FieldLike[]): this;
1824
+ toJSON(): BotModalDefinition;
1825
+ }
1826
+
1827
+ /**
1828
+ * Typed accessor for slash- and prefix-command options.
1829
+ * Available via `interaction.options`.
1830
+ *
1831
+ * @example
1832
+ * client.command('ban', async (interaction) => {
1833
+ * const userId = interaction.options.getString('user', true)
1834
+ * const reason = interaction.options.getString('reason') ?? 'No reason given'
1835
+ * })
1836
+ */
1837
+ declare class InteractionOptions {
1838
+ private readonly _map;
1839
+ constructor(data: unknown);
1840
+ /** Whether this option was supplied by the user. */
1841
+ has(name: string): boolean;
1842
+ /** @overload Required — never returns `null`. */
1843
+ getString(name: string, required: true): string;
1844
+ /** @overload Optional — returns `null` when not supplied. */
1845
+ getString(name: string, required?: false): string | null;
1846
+ /** @overload Required — never returns `null`. */
1847
+ getInteger(name: string, required: true): number;
1848
+ /** @overload Optional — returns `null` when not supplied. */
1849
+ getInteger(name: string, required?: false): number | null;
1850
+ /** @overload Required — never returns `null`. */
1851
+ getNumber(name: string, required: true): number;
1852
+ /** @overload Optional — returns `null` when not supplied. */
1853
+ getNumber(name: string, required?: false): number | null;
1854
+ /** Returns `true` or `false`, or `null` if not supplied. */
1855
+ getBoolean(name: string): boolean | null;
1856
+ /**
1857
+ * Returns the mentioned **user ID** string (type `USER` option).
1858
+ * @overload Required.
1859
+ */
1860
+ getUser(name: string, required: true): string;
1861
+ getUser(name: string, required?: false): string | null;
1862
+ /**
1863
+ * Returns the mentioned **channel ID** string (type `CHANNEL` option).
1864
+ * @overload Required.
1865
+ */
1866
+ getChannel(name: string, required: true): string;
1867
+ getChannel(name: string, required?: false): string | null;
1868
+ /**
1869
+ * Returns the mentioned **role ID** string (type `ROLE` option).
1870
+ * @overload Required.
1871
+ */
1872
+ getRole(name: string, required: true): string;
1873
+ getRole(name: string, required?: false): string | null;
1874
+ }
1875
+ /**
1876
+ * Rich wrapper around a raw bot interaction.
1877
+ * Returned by `interactionCreate`, `client.command()`, `client.button()`, `client.selectMenu()`.
1878
+ *
1879
+ * @example
1880
+ * client.on('interactionCreate', async (interaction) => {
1881
+ * if (interaction.isSlashCommand() && interaction.commandName === 'ping') {
1882
+ * await interaction.reply('Pong! 🏓')
1883
+ * }
1884
+ * })
1885
+ *
1886
+ * // Or use built-in routing:
1887
+ * client.command('ping', async (interaction) => {
1888
+ * await interaction.reply('Pong! 🏓')
1889
+ * })
1890
+ */
1891
+ declare class NovaInteraction {
1892
+ private readonly _raw;
1893
+ private readonly _api;
1894
+ /** Unique interaction ID. */
1895
+ readonly id: string;
1896
+ /** Interaction type. Use type guards (`.isSlashCommand()` etc.) for narrowing. */
1897
+ readonly type: InteractionType;
1898
+ /** Command name — set for `SLASH_COMMAND` and `PREFIX_COMMAND` interactions. */
1899
+ readonly commandName: string | null;
1900
+ /** Component custom ID — set for `BUTTON_CLICK`, `SELECT_MENU`, and `MODAL_SUBMIT` interactions. */
1901
+ readonly customId: string | null;
1902
+ /** ID of the user who triggered this interaction. */
1903
+ readonly userId: string;
1904
+ /** ID of the channel where this interaction occurred. */
1905
+ readonly channelId: string;
1906
+ /** ID of the server where this interaction occurred (`null` in DMs). */
1907
+ readonly serverId: string | null;
1908
+ /** ID of the message that contained the button/select component (if any). */
1909
+ readonly triggerMsgId: string | null;
1910
+ /** Selected option values for `SELECT_MENU` interactions. */
1911
+ readonly values: string[];
1912
+ /**
1913
+ * Field values submitted in a `MODAL_SUBMIT` interaction.
1914
+ * Keys are the `customId`s of the `TextInputBuilder` fields.
1915
+ *
1916
+ * @example
1917
+ * const reason = interaction.modalData.reason
1918
+ */
1919
+ readonly modalData: Record<string, string>;
1920
+ /** ISO timestamp of when the interaction was created. */
1921
+ readonly createdAt: string;
1922
+ /**
1923
+ * Typed accessor for slash/prefix command options.
1924
+ *
1925
+ * @example
1926
+ * const userId = interaction.options.getUser('user', true)
1927
+ * const reason = interaction.options.getString('reason') ?? 'No reason given'
1928
+ */
1929
+ readonly options: InteractionOptions;
1930
+ constructor(_raw: Interaction, _api: InteractionsAPI);
1931
+ /**
1932
+ * For `AUTOCOMPLETE` interactions — the option being completed.
1933
+ * Contains `name` (option name) and `value` (partial text typed so far).
1934
+ * `null` for all other interaction types.
1935
+ *
1936
+ * @example
1937
+ * client.autocomplete('search', async (interaction) => {
1938
+ * const query = interaction.autocomplete?.value ?? ''
1939
+ * await interaction.respondAutocomplete([{ name: query, value: query }])
1940
+ * })
1941
+ */
1942
+ get autocomplete(): {
1943
+ name: string;
1944
+ value: string;
1945
+ } | null;
1946
+ /** `true` when triggered by a `/slash` command. */
1947
+ isSlashCommand(): boolean;
1948
+ /** `true` when triggered by a `!prefix` command. */
1949
+ isPrefixCommand(): boolean;
1950
+ /** `true` for both slash and prefix commands. */
1951
+ isCommand(): boolean;
1952
+ /** `true` when a button component was clicked. */
1953
+ isButton(): boolean;
1954
+ /** `true` when a select-menu option was chosen. */
1955
+ isSelectMenu(): boolean;
1956
+ /** `true` when the user submitted a modal form. */
1957
+ isModalSubmit(): boolean;
1958
+ /** `true` during autocomplete suggestion requests. */
1959
+ isAutocomplete(): boolean;
1960
+ /**
1961
+ * Send autocomplete suggestions back to the user.
1962
+ * Call this inside a `client.autocomplete()` handler.
1963
+ * Up to 25 choices are shown; each needs a `name` (displayed) and `value` (submitted).
1964
+ *
1965
+ * @example
1966
+ * client.autocomplete('color', async (interaction) => {
1967
+ * const query = interaction.autocomplete?.value ?? ''
1968
+ * const colors = ['red', 'green', 'blue'].filter(c => c.startsWith(query))
1969
+ * await interaction.respondAutocomplete(colors.map(c => ({ name: c, value: c })))
1970
+ * })
1971
+ */
1972
+ respondAutocomplete(choices: Array<{
1973
+ name: string;
1974
+ value: string | number;
1975
+ }>): Promise<{
1976
+ ok: true;
1977
+ }>;
1978
+ /** `true` when triggered via a context-menu command. */
1979
+ isContextMenu(): boolean;
1980
+ /**
1981
+ * Respond with a message.
1982
+ * Accepts a plain string or a full options object.
1983
+ *
1984
+ * @example
1985
+ * await interaction.reply('Pong! 🏓')
1986
+ * await interaction.reply({ content: 'Done!', ephemeral: true })
1987
+ * await interaction.reply({ embed: new EmbedBuilder().setTitle('Stats').toJSON() })
1988
+ */
1989
+ reply(options: RespondInteractionOptions | string): Promise<Message | {
1990
+ ok: true;
1991
+ ephemeral: true;
1992
+ }>;
1993
+ /**
1994
+ * Respond with a message **only visible to the user** who triggered the interaction.
1995
+ *
1996
+ * @example
1997
+ * await interaction.replyEphemeral('Only you can see this!')
1998
+ */
1999
+ replyEphemeral(options: string | Omit<RespondInteractionOptions, 'ephemeral'>): Promise<{
2000
+ ok: true;
2001
+ ephemeral: true;
2002
+ }>;
2003
+ /**
2004
+ * Acknowledge the interaction without sending a response yet.
2005
+ * Shows a loading indicator to the user.
2006
+ * Follow up with `interaction.editReply()` when you're done.
2007
+ *
2008
+ * @example
2009
+ * await interaction.defer()
2010
+ * const data = await fetchSomeSlow()
2011
+ * await interaction.editReply({ content: `Result: ${data}` })
2012
+ */
2013
+ defer(): Promise<{
2014
+ ok: true;
2015
+ }>;
2016
+ /**
2017
+ * Edit the previous reply (e.g. after `defer()`).
2018
+ *
2019
+ * @example
2020
+ * await interaction.defer()
2021
+ * await interaction.editReply(`Done — processed ${count} items.`)
2022
+ */
2023
+ editReply(options: RespondInteractionOptions | string): Promise<Message | {
2024
+ ok: true;
2025
+ ephemeral: true;
2026
+ }>;
2027
+ /**
2028
+ * Open a **modal dialog** and return the user's submission as a new `NovaInteraction`.
2029
+ * Returns `null` if the user closes the modal or the timeout expires (default: 5 min).
2030
+ *
2031
+ * **This is the recommended way to open modals.**
2032
+ *
2033
+ * @example
2034
+ * const submitted = await interaction.openModal(
2035
+ * new ModalBuilder()
2036
+ * .setTitle('Submit a report')
2037
+ * .setCustomId('report_modal')
2038
+ * .addField(
2039
+ * new TextInputBuilder()
2040
+ * .setCustomId('reason')
2041
+ * .setLabel('Reason')
2042
+ * .setStyle('paragraph')
2043
+ * .setRequired(true)
2044
+ * )
2045
+ * )
2046
+ *
2047
+ * if (!submitted) return // user dismissed or timed out
2048
+ *
2049
+ * const reason = submitted.modalData.reason
2050
+ * await submitted.replyEphemeral(`Report received: ${reason}`)
2051
+ */
2052
+ openModal(modal: ModalBuilder | BotModalDefinition, options?: {
2053
+ timeout?: number;
2054
+ }): Promise<NovaInteraction | null>;
2055
+ /** Returns the raw interaction data from the gateway. */
2056
+ toJSON(): Interaction;
2057
+ }
2058
+
2059
+ /**
2060
+ * A rich wrapper around a raw `Message` with convenience methods.
2061
+ *
2062
+ * Returned by `client.on('messageCreate', ...)` and from message fetch calls.
2063
+ *
2064
+ * @example
2065
+ * client.on('messageCreate', async (msg) => {
2066
+ * if (msg.content.toLowerCase() === '!ping') {
2067
+ * await msg.reply('Pong! 🏓')
2068
+ * await msg.react('🏓')
2069
+ * }
2070
+ * })
2071
+ */
2072
+ declare class NovaMessage {
2073
+ /** The raw message ID. */
2074
+ readonly id: string;
2075
+ /** The message text content. */
2076
+ readonly content: string;
2077
+ /** The channel this message was sent in. */
2078
+ readonly channelId: string;
2079
+ /** The author of the message. */
2080
+ readonly author: Message['author'];
2081
+ /** Embed attached to this message, if any. */
2082
+ readonly embed: Embed | null;
2083
+ /** Interactive components (buttons, selects) attached to this message. */
2084
+ readonly components: MessageComponent[];
2085
+ /** The message this is replying to, if any. */
2086
+ readonly replyToId: string | null;
2087
+ /** Uploaded file attachments. */
2088
+ readonly attachments: Attachment[];
2089
+ /** Reactions on this message. */
2090
+ readonly reactions: Reaction[];
2091
+ /** When the message was sent. */
2092
+ readonly createdAt: Date;
2093
+ /** When the message was last edited, or `null`. */
2094
+ readonly editedAt: Date | null;
2095
+ private readonly _messages;
2096
+ private readonly _reactions;
2097
+ constructor(raw: Message, messages: MessagesAPI, reactions: ReactionsAPI);
2098
+ /** Returns true if the message was sent by a bot. */
2099
+ isFromBot(): boolean;
2100
+ /** Returns true if the message has an embed. */
2101
+ hasEmbed(): boolean;
2102
+ /** Returns true if the message has interactive components. */
2103
+ hasComponents(): boolean;
2104
+ /** Returns true if the message has been edited. */
2105
+ isEdited(): boolean;
2106
+ /**
2107
+ * Add a reaction to this message.
2108
+ *
2109
+ * @example
2110
+ * await msg.react('👍')
2111
+ * await msg.react('🎉')
2112
+ */
2113
+ react(emoji: string): Promise<{
2114
+ ok: true;
2115
+ }>;
2116
+ /**
2117
+ * Remove the bot's reaction from this message.
2118
+ *
2119
+ * @example
2120
+ * await msg.removeReaction('👍')
2121
+ */
2122
+ removeReaction(emoji: string): Promise<{
2123
+ ok: true;
2124
+ }>;
2125
+ /**
2126
+ * Reply to this message.
2127
+ *
2128
+ * @example
2129
+ * await msg.reply('Got it!')
2130
+ * await msg.reply({ embed: new EmbedBuilder().setTitle('Result').toJSON() })
2131
+ */
2132
+ reply(options: string | Omit<SendMessageOptions, 'replyToId'>): Promise<NovaMessage>;
2133
+ /**
2134
+ * Edit this message.
2135
+ * Only works if the bot is the author.
2136
+ *
2137
+ * @example
2138
+ * await msg.edit('Updated content')
2139
+ * await msg.edit({ content: 'Updated', embed: { title: 'New embed' } })
2140
+ */
2141
+ edit(options: string | EditMessageOptions): Promise<NovaMessage>;
2142
+ /**
2143
+ * Delete this message.
2144
+ * Only works if the bot is the author.
2145
+ *
2146
+ * @example
2147
+ * await msg.delete()
2148
+ */
2149
+ delete(): Promise<{
2150
+ ok: true;
2151
+ }>;
2152
+ /**
2153
+ * Pin this message in its channel.
2154
+ *
2155
+ * @example
2156
+ * await msg.pin()
2157
+ */
2158
+ pin(): Promise<{
2159
+ ok: true;
2160
+ }>;
2161
+ /**
2162
+ * Unpin this message.
2163
+ *
2164
+ * @example
2165
+ * await msg.unpin()
2166
+ */
2167
+ unpin(): Promise<{
2168
+ ok: true;
2169
+ }>;
2170
+ /**
2171
+ * Re-fetch the latest version of this message from the server.
2172
+ *
2173
+ * @example
2174
+ * const fresh = await msg.fetch()
2175
+ */
2176
+ fetch(): Promise<NovaMessage>;
2177
+ /**
2178
+ * Forward this message's content (and embed if present) to another channel.
2179
+ * Creates a new message in the target channel.
2180
+ *
2181
+ * @example
2182
+ * const forwarded = await msg.forward('target-channel-id')
2183
+ * console.log('Forwarded to:', forwarded.channelId)
2184
+ */
2185
+ forward(channelId: string): Promise<NovaMessage>;
2186
+ /**
2187
+ * Fetch detailed reaction data for a specific emoji on this message.
2188
+ * Returns the users who reacted with that emoji.
2189
+ *
2190
+ * @example
2191
+ * const reactors = await msg.fetchReactionDetails('👍')
2192
+ * for (const r of reactors) console.log(r.username, 'reacted 👍')
2193
+ */
2194
+ fetchReactionDetails(emoji: string): ReturnType<ReactionsAPI['fetchEmoji']>;
2195
+ /**
2196
+ * Remove **all** reactions from this message.
2197
+ * Requires the `messages.manage` scope.
2198
+ *
2199
+ * @example
2200
+ * await msg.clearAllReactions()
2201
+ */
2202
+ clearAllReactions(): Promise<{
2203
+ ok: true;
2204
+ }>;
2205
+ /**
2206
+ * Remove all reactions for a specific emoji from this message.
2207
+ * Requires the `messages.manage` scope.
2208
+ *
2209
+ * @example
2210
+ * await msg.clearReactionsFor('👍')
2211
+ */
2212
+ clearReactionsFor(emoji: string): Promise<{
2213
+ ok: true;
2214
+ }>;
2215
+ /**
2216
+ * Fetch a breakdown of all reactions on this message, grouped by emoji.
2217
+ *
2218
+ * @example
2219
+ * const details = await msg.fetchAllReactions()
2220
+ * for (const d of details) console.log(`${d.emoji} — ${d.count}`)
2221
+ */
2222
+ fetchAllReactions(): ReturnType<ReactionsAPI['fetch']>;
2223
+ /**
2224
+ * Get a URL to this message (deep link).
2225
+ */
2226
+ get url(): string;
2227
+ /**
2228
+ * Return the raw message object.
2229
+ */
2230
+ toJSON(): Message;
2231
+ toString(): string;
2232
+ }
2233
+
2234
+ /**
2235
+ * A rich wrapper around a raw `Channel` with convenience methods.
2236
+ *
2237
+ * Returned by `client.fetchChannel()` and `client.fetchChannels()`.
2238
+ *
2239
+ * @example
2240
+ * const channel = await client.fetchChannel('channel-id')
2241
+ *
2242
+ * await channel.send('Hello from the bot!')
2243
+ * await channel.edit({ topic: 'New topic' })
2244
+ * const messages = await channel.fetchMessages({ limit: 20 })
2245
+ */
2246
+ declare class NovaChannel {
2247
+ /** The channel's unique ID. */
2248
+ readonly id: string;
2249
+ /** The channel's name (without #). */
2250
+ readonly name: string;
2251
+ /** The channel type — `'TEXT'`, `'VOICE'`, `'ANNOUNCEMENT'`, `'FORUM'`, or `'STAGE'`. */
2252
+ readonly type: ChannelType;
2253
+ /** The ID of the server this channel belongs to. */
2254
+ readonly serverId: string | null;
2255
+ /** Optional topic / description text. */
2256
+ readonly topic: string | null;
2257
+ /** Sorting position (lower = higher in the list). */
2258
+ readonly position: number;
2259
+ /** Slow-mode interval in seconds (`0` = disabled). */
2260
+ readonly slowMode: number;
2261
+ /** When the channel was created. */
2262
+ readonly createdAt: Date;
2263
+ private readonly _channels;
2264
+ private readonly _messages;
2265
+ private readonly _webhooks;
2266
+ private readonly _forum;
2267
+ constructor(raw: Channel, channels: ChannelsAPI, messages: MessagesAPI, webhooks?: WebhooksAPI, forum?: ForumAPI);
2268
+ /** `true` for text channels. */
2269
+ isText(): boolean;
2270
+ /** `true` for voice channels. */
2271
+ isVoice(): boolean;
2272
+ /** `true` for announcement channels. */
2273
+ isAnnouncement(): boolean;
2274
+ /** `true` for forum channels. */
2275
+ isForum(): boolean;
2276
+ /** `true` for stage channels. */
2277
+ isStage(): boolean;
2278
+ /** `true` if slow-mode is enabled on this channel. */
2279
+ hasSlowMode(): boolean;
2280
+ /**
2281
+ * Send a message to this channel.
2282
+ * Accepts a plain string or a full options object.
2283
+ *
2284
+ * @example
2285
+ * await channel.send('Hello!')
2286
+ * await channel.send({ content: 'Hi', embed: { title: 'Stats' } })
2287
+ */
2288
+ send(options: string | SendMessageOptions): Promise<Message>;
2289
+ /**
2290
+ * Fetch recent messages from this channel.
2291
+ *
2292
+ * @example
2293
+ * const messages = await channel.fetchMessages({ limit: 50 })
2294
+ */
2295
+ fetchMessages(options?: FetchMessagesOptions): Promise<Message[]>;
2296
+ /**
2297
+ * Fetch all pinned messages in this channel.
2298
+ *
2299
+ * @example
2300
+ * const pins = await channel.fetchPins()
2301
+ */
2302
+ fetchPins(): Promise<Message[]>;
2303
+ /**
2304
+ * Start a typing indicator (shows "Bot is typing…" for ~5 seconds).
2305
+ *
2306
+ * @example
2307
+ * await channel.startTyping()
2308
+ */
2309
+ startTyping(): Promise<{
2310
+ ok: true;
2311
+ }>;
2312
+ /**
2313
+ * Edit this channel's properties.
2314
+ * Requires the `channels.manage` scope.
2315
+ *
2316
+ * @example
2317
+ * await channel.edit({ name: 'general-2', topic: 'The second general channel' })
2318
+ */
2319
+ edit(options: EditChannelOptions): Promise<NovaChannel>;
2320
+ /**
2321
+ * Delete this channel.
2322
+ * Requires the `channels.manage` scope.
2323
+ *
2324
+ * @example
2325
+ * await channel.delete()
2326
+ */
2327
+ delete(): Promise<{
2328
+ ok: true;
2329
+ }>;
2330
+ /**
2331
+ * Bulk-delete multiple messages in this channel (max 100 at once).
2332
+ * Requires the `messages.manage` scope.
2333
+ *
2334
+ * @example
2335
+ * const ids = messages.map(m => m.id)
2336
+ * const result = await channel.bulkDelete(ids)
2337
+ * console.log(`Deleted ${result.deleted} messages`)
2338
+ */
2339
+ bulkDelete(messageIds: string[]): Promise<BulkDeleteResult>;
2340
+ /**
2341
+ * Create a webhook in this channel.
2342
+ * Requires the `webhooks.manage` scope.
2343
+ *
2344
+ * @example
2345
+ * const wh = await channel.createWebhook({ name: 'Notifications' })
2346
+ * console.log('Token:', wh.token)
2347
+ */
2348
+ createWebhook(options: WebhookCreateOptions): Promise<Webhook>;
2349
+ /**
2350
+ * Fetch all webhooks in this channel.
2351
+ * Requires the `webhooks.manage` scope.
2352
+ *
2353
+ * @example
2354
+ * const webhooks = await channel.fetchWebhooks()
2355
+ */
2356
+ fetchWebhooks(): Promise<Webhook[]>;
2357
+ /**
2358
+ * Create a new post in this FORUM channel.
2359
+ * Requires the `channels.write` scope.
2360
+ *
2361
+ * @example
2362
+ * const post = await channel.createForumPost({
2363
+ * title: 'Announcement',
2364
+ * content: 'Welcome everyone!',
2365
+ * })
2366
+ */
2367
+ createForumPost(options: CreateForumPostOptions): Promise<ForumPost>;
2368
+ /**
2369
+ * Fetch posts from this FORUM channel.
2370
+ *
2371
+ * @example
2372
+ * const posts = await channel.fetchForumPosts({ limit: 20 })
2373
+ */
2374
+ fetchForumPosts(options?: FetchForumPostsOptions): Promise<ForumPost[]>;
2375
+ /**
2376
+ * Returns the channel as a mention-style string: `#name`.
2377
+ */
2378
+ toString(): string;
2379
+ /** Returns the raw channel data. */
2380
+ toJSON(): Channel;
2381
+ }
2382
+
2383
+ /**
2384
+ * A rich wrapper around a raw `Member` with convenience methods.
2385
+ *
2386
+ * Returned by `client.fetchMember()` and `client.fetchMembers()`.
2387
+ *
2388
+ * @example
2389
+ * const member = await client.fetchMember('server-id', 'user-id')
2390
+ *
2391
+ * if (member.isAdmin()) {
2392
+ * await member.dm('You have admin access.')
2393
+ * } else {
2394
+ * await member.kick()
2395
+ * }
2396
+ */
2397
+ declare class NovaMember {
2398
+ /** The user's unique ID. */
2399
+ readonly userId: string;
2400
+ /** The server this membership belongs to. */
2401
+ readonly serverId: string;
2402
+ /** The user's username (login handle). */
2403
+ readonly username: string;
2404
+ /** The user's display name. */
2405
+ readonly displayName: string;
2406
+ /** URL of the user's avatar, or `null`. */
2407
+ readonly avatar: string | null;
2408
+ /** The member's server role — `'OWNER'`, `'ADMIN'`, or `'MEMBER'`. */
2409
+ readonly role: 'OWNER' | 'ADMIN' | 'MEMBER';
2410
+ /** The user's current presence status. */
2411
+ readonly status: 'ONLINE' | 'IDLE' | 'DND' | 'OFFLINE';
2412
+ /** `true` if this member is a bot account. */
2413
+ readonly isBot: boolean;
2414
+ /** When this user joined the server. */
2415
+ readonly joinedAt: Date;
2416
+ private readonly _members;
2417
+ constructor(raw: Member, serverId: string, members: MembersAPI);
2418
+ /** `true` if this member is the server owner. */
2419
+ isOwner(): boolean;
2420
+ /** `true` if this member is an admin or the server owner. */
2421
+ isAdmin(): boolean;
2422
+ /** `true` if this member is a regular (non-privileged) member. */
2423
+ isRegularMember(): boolean;
2424
+ /** `true` if the user is currently online. */
2425
+ isOnline(): boolean;
2426
+ /** `true` if the user is idle / away. */
2427
+ isIdle(): boolean;
2428
+ /** `true` if the user is set to Do Not Disturb. */
2429
+ isDND(): boolean;
2430
+ /** `true` if the user appears offline. */
2431
+ isOffline(): boolean;
2432
+ /**
2433
+ * Kick this member from the server.
2434
+ * Bots cannot kick owners or admins (throws 403).
2435
+ *
2436
+ * @example
2437
+ * await member.kick()
2438
+ */
2439
+ kick(): Promise<{
2440
+ ok: true;
2441
+ }>;
2442
+ /**
2443
+ * Ban this member from the server with an optional reason.
2444
+ * Bots cannot ban owners or admins (throws 403).
2445
+ *
2446
+ * @example
2447
+ * await member.ban('Repeated rule violations')
2448
+ */
2449
+ ban(reason?: string): Promise<{
2450
+ ok: true;
2451
+ }>;
2452
+ /**
2453
+ * Send this user a direct message.
2454
+ * Requires the `messages.write` scope.
2455
+ *
2456
+ * @example
2457
+ * await member.dm('Welcome to the server!')
2458
+ * await member.dm({ content: 'Hello', embed: { title: 'Rules' } })
2459
+ */
2460
+ dm(options: string | Omit<SendMessageOptions, 'replyToId'>): Promise<Message>;
2461
+ /**
2462
+ * Assign a custom role to this member.
2463
+ * Requires the `members.roles` scope.
2464
+ *
2465
+ * @example
2466
+ * await member.addRole('role-id')
2467
+ */
2468
+ addRole(roleId: string): Promise<{
2469
+ ok: true;
2470
+ }>;
2471
+ /**
2472
+ * Remove a custom role from this member.
2473
+ * Requires the `members.roles` scope.
2474
+ *
2475
+ * @example
2476
+ * await member.removeRole('role-id')
2477
+ */
2478
+ removeRole(roleId: string): Promise<{
2479
+ ok: true;
2480
+ }>;
2481
+ /**
2482
+ * Issue a warning to this member.
2483
+ * Requires the `members.moderate` scope.
2484
+ *
2485
+ * @example
2486
+ * await member.warn('Excessive spamming')
2487
+ */
2488
+ warn(reason: string): Promise<Warning>;
2489
+ /**
2490
+ * Fetch all warnings for this member in this server.
2491
+ * Requires the `members.moderate` scope.
2492
+ *
2493
+ * @example
2494
+ * const warnings = await member.fetchWarnings()
2495
+ * console.log(`${warnings.length} warnings on record`)
2496
+ */
2497
+ fetchWarnings(): Promise<Warning[]>;
2498
+ /**
2499
+ * Get this member's current XP and level.
2500
+ * Requires the `members.read` scope.
2501
+ *
2502
+ * @example
2503
+ * const xp = await member.getXP()
2504
+ * console.log(`Level ${xp.level} — ${xp.xp} XP`)
2505
+ */
2506
+ getXP(): Promise<MemberXPData>;
2507
+ /**
2508
+ * Set this member's XP to a specific value.
2509
+ * Requires the `members.manage` scope.
2510
+ *
2511
+ * @example
2512
+ * await member.setXP(500)
2513
+ */
2514
+ setXP(xp: number): Promise<MemberXPData>;
2515
+ /**
2516
+ * Add (or subtract) XP to this member's current total.
2517
+ * Requires the `members.manage` scope.
2518
+ *
2519
+ * @example
2520
+ * await member.addXP(100) // reward 100 XP
2521
+ * await member.addXP(-50) // deduct 50 XP
2522
+ */
2523
+ addXP(amount: number): Promise<MemberXPData>;
2524
+ /**
2525
+ * Delete all warnings on record for this member in this server.
2526
+ * Requires the `members.moderate` scope.
2527
+ *
2528
+ * @example
2529
+ * await member.clearWarnings()
2530
+ */
2531
+ clearWarnings(): Promise<number>;
2532
+ /**
2533
+ * Reset this member's XP back to zero.
2534
+ * Requires the `members.manage` scope.
2535
+ *
2536
+ * @example
2537
+ * await member.resetXP()
2538
+ */
2539
+ resetXP(): Promise<MemberXPData>;
2540
+ /**
2541
+ * Returns a mention-style string: `@displayName`.
2542
+ */
2543
+ toString(): string;
2544
+ /** Returns the raw member data. */
2545
+ toJSON(): Member;
2546
+ }
2547
+
2548
+ /**
2549
+ * A rich wrapper around a raw `Role` with convenience methods.
2550
+ *
2551
+ * Returned by `client.fetchRole()` and `client.fetchRoles()`.
2552
+ *
2553
+ * @example
2554
+ * const roles = await client.fetchRoles('server-id')
2555
+ * const mod = roles.find(r => r.name === 'Moderator')
2556
+ * if (mod) await mod.assign('user-id')
2557
+ */
2558
+ declare class NovaRole {
2559
+ /** Unique role ID. */
2560
+ readonly id: string;
2561
+ /** Display name of the role. */
2562
+ readonly name: string;
2563
+ /** Hex colour string (e.g. `'#00d4ff'`), or `null` for no colour. */
2564
+ readonly color: string | null;
2565
+ /** Sort position — lower numbers appear higher in the role list. */
2566
+ readonly position: number;
2567
+ /** The server this role belongs to. */
2568
+ readonly serverId: string;
2569
+ /** Whether this role is displayed separately in the member sidebar. */
2570
+ readonly hoist: boolean;
2571
+ /** When the role was created. */
2572
+ readonly createdAt: Date;
2573
+ private readonly _roles;
2574
+ constructor(raw: Role, roles: RolesAPI);
2575
+ /**
2576
+ * Edit this role's name, colour, hoist flag, or permissions.
2577
+ *
2578
+ * @example
2579
+ * await role.edit({ color: '#ff0000', name: 'Red Team' })
2580
+ */
2581
+ edit(options: RoleEditOptions): Promise<Role>;
2582
+ /**
2583
+ * Delete this role from the server.
2584
+ * Any members currently assigned this role will have it removed.
2585
+ *
2586
+ * @example
2587
+ * await role.delete()
2588
+ */
2589
+ delete(): Promise<{
2590
+ ok: true;
2591
+ }>;
2592
+ /**
2593
+ * Assign this role to a server member.
2594
+ *
2595
+ * @example
2596
+ * await role.assign('user-id')
2597
+ */
2598
+ assign(userId: string): Promise<{
2599
+ ok: true;
2600
+ }>;
2601
+ /**
2602
+ * Remove this role from a server member.
2603
+ *
2604
+ * @example
2605
+ * await role.remove('user-id')
2606
+ */
2607
+ remove(userId: string): Promise<{
2608
+ ok: true;
2609
+ }>;
2610
+ /** Returns `true` if the role has a custom hex colour set. */
2611
+ hasColor(): boolean;
2612
+ /** Returns the CSS-safe hex colour string. Falls back to `'#99aab5'` (grey). */
2613
+ toHex(): string;
2614
+ toJSON(): Role;
2615
+ }
2616
+
2617
+ /**
2618
+ * A rich wrapper around a raw `NovaServer` with convenience methods.
2619
+ *
2620
+ * Returned by `client.fetchServer()` and `client.fetchServers()`.
2621
+ *
2622
+ * @example
2623
+ * const server = await client.fetchServer('server-id')
2624
+ * console.log(`${server.name} — ${server.memberCount} members`)
2625
+ * await server.send('welcome-channel-id', 'Bot is online! 🤖')
2626
+ */
2627
+ declare class NovaServerWrapper {
2628
+ /** Unique server ID. */
2629
+ readonly id: string;
2630
+ /** Server display name. */
2631
+ readonly name: string;
2632
+ /** URL to the server icon, or `null`. */
2633
+ readonly icon: string | null;
2634
+ /** Short description of the server, or `null`. */
2635
+ readonly description: string | null;
2636
+ /** Total member count at time of fetch. */
2637
+ readonly memberCount: number;
2638
+ /** Total channel count at time of fetch. */
2639
+ readonly channelCount: number;
2640
+ /** When the bot joined this server. */
2641
+ readonly joinedAt: Date;
2642
+ private readonly _servers;
2643
+ private readonly _channels;
2644
+ private readonly _members;
2645
+ private readonly _invites;
2646
+ private readonly _roles;
2647
+ private readonly _messages;
2648
+ private readonly _categories;
2649
+ private readonly _events;
2650
+ private readonly _automod;
2651
+ private readonly _auditLog;
2652
+ constructor(raw: NovaServer, servers: ServersAPI, channels: ChannelsAPI, members: MembersAPI, invites: InvitesAPI, roles: RolesAPI, messages: MessagesAPI, categories?: CategoriesAPI, events?: EventsAPI, automod?: AutoModAPI, auditLog?: AuditLogAPI);
2653
+ /**
2654
+ * Update this server's name, description, or icon.
2655
+ * Requires the `server.manage` scope.
2656
+ *
2657
+ * @example
2658
+ * await server.update({ name: 'New Name' })
2659
+ */
2660
+ update(options: ServerUpdateOptions): Promise<NovaServer>;
2661
+ /**
2662
+ * Fetch all channels in this server.
2663
+ *
2664
+ * @example
2665
+ * const channels = await server.fetchChannels()
2666
+ * const text = channels.filter(c => c.type === 'TEXT')
2667
+ */
2668
+ fetchChannels(): Promise<Channel[]>;
2669
+ /**
2670
+ * Create a new channel in this server.
2671
+ * Requires the `channels.manage` scope.
2672
+ *
2673
+ * @example
2674
+ * const ch = await server.createChannel({ name: 'bot-logs', type: 'TEXT' })
2675
+ */
2676
+ createChannel(options: CreateChannelOptions): Promise<Channel>;
2677
+ /**
2678
+ * Fetch members in this server.
2679
+ *
2680
+ * @example
2681
+ * const members = await server.fetchMembers({ limit: 100 })
2682
+ */
2683
+ fetchMembers(options?: FetchMembersOptions): Promise<Member[]>;
2684
+ /**
2685
+ * Fetch a single member by user ID.
2686
+ *
2687
+ * @example
2688
+ * const member = await server.fetchMember('user-id')
2689
+ */
2690
+ fetchMember(userId: string): ReturnType<MembersAPI['fetch']>;
2691
+ /**
2692
+ * Kick a member from this server.
2693
+ *
2694
+ * @example
2695
+ * await server.kick('user-id')
2696
+ */
2697
+ kick(userId: string): Promise<{
2698
+ ok: true;
2699
+ }>;
2700
+ /**
2701
+ * Ban a member from this server.
2702
+ *
2703
+ * @example
2704
+ * await server.ban('user-id', 'Spamming')
2705
+ */
2706
+ ban(userId: string, reason?: string): Promise<{
2707
+ ok: true;
2708
+ }>;
2709
+ /**
2710
+ * Fetch the ban list for this server.
2711
+ */
2712
+ fetchBans(): Promise<BanEntry[]>;
2713
+ /**
2714
+ * List all custom roles in this server, sorted by position.
2715
+ *
2716
+ * @example
2717
+ * const roles = await server.fetchRoles()
2718
+ * const admins = roles.filter(r => r.name === 'Admin')
2719
+ */
2720
+ fetchRoles(): Promise<Role[]>;
2721
+ /**
2722
+ * Create a new custom role in this server.
2723
+ * Requires the `roles.manage` scope.
2724
+ *
2725
+ * @example
2726
+ * const role = await server.createRole({ name: 'Supporter', color: '#00d4ff', hoist: true })
2727
+ */
2728
+ createRole(options: RoleCreateOptions): Promise<Role>;
2729
+ /**
2730
+ * Fetch all active invites for this server.
2731
+ *
2732
+ * @example
2733
+ * const invites = await server.fetchInvites()
2734
+ */
2735
+ fetchInvites(): Promise<Invite[]>;
2736
+ /**
2737
+ * Create an invite for this server.
2738
+ *
2739
+ * @example
2740
+ * const invite = await server.createInvite({ maxUses: 10 })
2741
+ * console.log(`https://novachatapp.com/invite/${invite.code}`)
2742
+ */
2743
+ createInvite(options?: InviteCreateOptions): Promise<Invite>;
2744
+ /**
2745
+ * Send a message to a channel in this server by channel ID.
2746
+ *
2747
+ * @example
2748
+ * await server.send('channel-id', 'Hello, server!')
2749
+ */
2750
+ send(channelId: string, content: string): ReturnType<MessagesAPI['send']>;
2751
+ /**
2752
+ * Fetch all channel categories in this server.
2753
+ *
2754
+ * @example
2755
+ * const cats = await server.fetchCategories()
2756
+ * const general = cats.find(c => c.name === 'General')
2757
+ */
2758
+ fetchCategories(): Promise<ChannelCategory[]>;
2759
+ /**
2760
+ * Create a new channel category in this server.
2761
+ * Requires the `channels.manage` scope.
2762
+ *
2763
+ * @example
2764
+ * const cat = await server.createCategory({ name: 'Bot Channels' })
2765
+ */
2766
+ createCategory(options: CreateCategoryOptions): Promise<ChannelCategory>;
2767
+ /**
2768
+ * Fetch server events. Pass `{ upcoming: true }` to only return future events.
2769
+ *
2770
+ * @example
2771
+ * const events = await server.fetchEvents({ upcoming: true })
2772
+ */
2773
+ fetchEvents(options?: FetchEventsOptions): Promise<ServerEvent[]>;
2774
+ /**
2775
+ * Create a new server event.
2776
+ * Requires the `server.manage` scope.
2777
+ *
2778
+ * @example
2779
+ * const event = await server.createEvent({
2780
+ * title: 'Game Night',
2781
+ * startAt: new Date('2025-09-01T20:00:00Z').toISOString(),
2782
+ * })
2783
+ */
2784
+ createEvent(options: CreateEventOptions): Promise<ServerEvent>;
2785
+ /**
2786
+ * Fetch server statistics (member count, message count, etc.).
2787
+ *
2788
+ * @example
2789
+ * const stats = await server.fetchStats()
2790
+ * console.log(`Online: ${stats.onlineCount} / ${stats.memberCount}`)
2791
+ */
2792
+ fetchStats(): Promise<ServerStats>;
2793
+ /**
2794
+ * Fetch the audit log for this server.
2795
+ * Requires the `audit-log.read` scope.
2796
+ *
2797
+ * @example
2798
+ * const log = await server.fetchAuditLog({ action: 'member.banned', limit: 20 })
2799
+ */
2800
+ fetchAuditLog(options?: FetchAuditLogsOptions): Promise<AuditLogEntry[]>;
2801
+ /**
2802
+ * Issue a warning to a member in this server.
2803
+ * Requires the `members.moderate` scope.
2804
+ *
2805
+ * @example
2806
+ * await server.warn('user-id', 'Insulting other members')
2807
+ */
2808
+ warn(userId: string, reason: string): Promise<Warning>;
2809
+ /**
2810
+ * Fetch warnings for this server, optionally filtered by user.
2811
+ * Requires the `members.moderate` scope.
2812
+ *
2813
+ * @example
2814
+ * const all = await server.fetchWarnings()
2815
+ * const userWarns = await server.fetchWarnings({ userId: 'user-id' })
2816
+ */
2817
+ fetchWarnings(options?: {
2818
+ userId?: string;
2819
+ }): Promise<Warning[]>;
2820
+ /**
2821
+ * Fetch the XP leaderboard for this server.
2822
+ * Requires the `members.read` scope.
2823
+ *
2824
+ * @example
2825
+ * const top = await server.fetchLeaderboard(10)
2826
+ * top.forEach(e => console.log(`#${e.rank} ${e.user.displayName} — ${e.xp} XP`))
2827
+ */
2828
+ fetchLeaderboard(limit?: number): Promise<LeaderboardEntry[]>;
2829
+ /**
2830
+ * Fetch all AutoMod rules for this server.
2831
+ * Requires the `server.manage` scope.
2832
+ *
2833
+ * @example
2834
+ * const rules = await server.fetchAutoModRules()
2835
+ * const active = rules.filter(r => r.enabled)
2836
+ */
2837
+ fetchAutoModRules(): Promise<AutoModRule[]>;
2838
+ /**
2839
+ * Create a new AutoMod rule for this server.
2840
+ * Requires the `server.manage` scope.
2841
+ *
2842
+ * @example
2843
+ * await server.createAutoModRule({ type: 'BLOCKED_WORD', value: 'badword' })
2844
+ */
2845
+ createAutoModRule(options: CreateAutoModRuleOptions): Promise<AutoModRule>;
2846
+ toJSON(): NovaServer;
2847
+ }
2848
+
2849
+ /**
2850
+ * A rich wrapper around a raw `Invite` with convenience methods.
2851
+ *
2852
+ * Returned by `client.fetchInvite()` and `client.fetchInvites()`.
2853
+ *
2854
+ * @example
2855
+ * const invite = await client.fetchInvite('abc123')
2856
+ * if (invite.isExpired()) await invite.revoke()
2857
+ */
2858
+ declare class NovaInvite {
2859
+ /** The invite code — appended to `https://novachatapp.com/invite/`. */
2860
+ readonly code: string;
2861
+ /** The server this invite grants access to. */
2862
+ readonly serverId: string;
2863
+ /** The user ID of whoever created this invite. */
2864
+ readonly creatorId: string;
2865
+ /** How many times this invite has been used. */
2866
+ readonly uses: number;
2867
+ /** Maximum allowed uses before the invite deactivates. `null` = unlimited. */
2868
+ readonly maxUses: number | null;
2869
+ /** When the invite expires. `null` = never expires. */
2870
+ readonly expiresAt: Date | null;
2871
+ /** When the invite was created. */
2872
+ readonly createdAt: Date;
2873
+ private readonly _invites;
2874
+ constructor(raw: Invite, invites: InvitesAPI);
2875
+ /** The full URL users can follow to join the server. */
2876
+ get url(): string;
2877
+ /**
2878
+ * Returns `true` if the invite has passed its expiry time.
2879
+ * Always `false` for invites with no expiry.
2880
+ */
2881
+ isExpired(): boolean;
2882
+ /**
2883
+ * Returns `true` if the invite has reached its maximum use count.
2884
+ * Always `false` for unlimited invites.
2885
+ */
2886
+ isExhausted(): boolean;
2887
+ /** Whether this invite is still usable (not expired and not exhausted). */
2888
+ isValid(): boolean;
2889
+ /**
2890
+ * Revoke (delete) this invite, making the code unusable.
2891
+ * Requires the `invites.manage` scope.
2892
+ *
2893
+ * @example
2894
+ * await invite.revoke()
2895
+ */
2896
+ revoke(): Promise<{
2897
+ ok: true;
2898
+ }>;
2899
+ toJSON(): Invite;
2900
+ }
2901
+
2902
+ /**
2903
+ * A rich wrapper around a raw `Webhook` with convenience methods.
2904
+ *
2905
+ * Returned by `client.fetchWebhook()` and `client.fetchWebhooks()`.
2906
+ *
2907
+ * @example
2908
+ * const webhook = await client.fetchWebhook('webhook-id')
2909
+ * await webhook.execute({ content: '🚀 Build passed!', username: 'CI Bot' })
2910
+ */
2911
+ declare class NovaWebhook {
2912
+ /** Unique webhook ID. */
2913
+ readonly id: string;
2914
+ /** The server this webhook belongs to. */
2915
+ readonly serverId: string;
2916
+ /** The channel messages are posted to when this webhook is executed. */
2917
+ readonly channelId: string;
2918
+ /** Display name shown next to messages posted via this webhook. */
2919
+ readonly name: string;
2920
+ /** Secret token — required to execute the webhook via HTTP. */
2921
+ readonly token: string;
2922
+ /** When the webhook was created. */
2923
+ readonly createdAt: Date;
2924
+ private readonly _webhooks;
2925
+ constructor(raw: Webhook, webhooks: WebhooksAPI);
2926
+ /**
2927
+ * Edit this webhook's name or target channel.
2928
+ * Requires the `webhooks.manage` scope.
2929
+ *
2930
+ * @example
2931
+ * await webhook.edit({ name: 'New Name', channelId: 'other-channel-id' })
2932
+ */
2933
+ edit(options: WebhookEditOptions): Promise<Webhook>;
2934
+ /**
2935
+ * Delete this webhook.
2936
+ * Requires the `webhooks.manage` scope.
2937
+ *
2938
+ * @example
2939
+ * await webhook.delete()
2940
+ */
2941
+ delete(): Promise<{
2942
+ ok: true;
2943
+ }>;
2944
+ /**
2945
+ * Post a message via this webhook.
2946
+ *
2947
+ * @example
2948
+ * await webhook.execute({ content: '❌ Tests failed on branch main', username: 'CI' })
2949
+ */
2950
+ execute(options: ExecuteWebhookOptions): Promise<Message>;
2951
+ toJSON(): Webhook;
2952
+ }
2953
+
2954
+ /**
2955
+ * A rich wrapper around a raw `ForumPost` object that provides
2956
+ * convenient helper methods for common operations.
2957
+ *
2958
+ * @example
2959
+ * const posts = await client.fetchForumPosts('channel-id')
2960
+ * for (const post of posts) {
2961
+ * if (post.closed) continue
2962
+ * await post.close()
2963
+ * }
2964
+ */
2965
+ declare class NovaForumPost implements ForumPost {
2966
+ private readonly raw;
2967
+ private readonly forum;
2968
+ readonly id: string;
2969
+ readonly channelId: string;
2970
+ readonly authorId: string;
2971
+ readonly title: string;
2972
+ readonly body: string;
2973
+ readonly tags: string[];
2974
+ readonly pinned: boolean;
2975
+ readonly closed: boolean;
2976
+ readonly upvoteCount: number;
2977
+ readonly replyCount: number;
2978
+ readonly author: ForumPost['author'];
2979
+ readonly createdAt: string;
2980
+ readonly updatedAt: string;
2981
+ constructor(raw: ForumPost, forum: ForumAPI);
2982
+ /**
2983
+ * Edit this forum post.
2984
+ *
2985
+ * @example
2986
+ * await post.edit({ title: 'Updated title' })
2987
+ */
2988
+ edit(options: EditForumPostOptions): Promise<NovaForumPost>;
2989
+ /**
2990
+ * Close the forum post (no new replies).
2991
+ *
2992
+ * @example
2993
+ * await post.close()
2994
+ */
2995
+ close(): Promise<NovaForumPost>;
2996
+ /**
2997
+ * Re-open a closed forum post.
2998
+ *
2999
+ * @example
3000
+ * await post.open()
3001
+ */
3002
+ open(): Promise<NovaForumPost>;
3003
+ /**
3004
+ * Pin this forum post in the channel.
3005
+ *
3006
+ * @example
3007
+ * await post.pin()
3008
+ */
3009
+ pin(): Promise<NovaForumPost>;
3010
+ /**
3011
+ * Unpin this forum post.
3012
+ *
3013
+ * @example
3014
+ * await post.unpin()
3015
+ */
3016
+ unpin(): Promise<NovaForumPost>;
3017
+ /**
3018
+ * Delete this forum post.
3019
+ *
3020
+ * @example
3021
+ * await post.delete()
3022
+ */
3023
+ delete(): Promise<void>;
3024
+ /** Whether this post was created by the currently connected bot. */
3025
+ get isOwnPost(): boolean;
3026
+ /** Returns `true` if the post has been closed. */
3027
+ get isClosed(): boolean;
3028
+ /** Returns `true` if the post is pinned. */
3029
+ get isPinned(): boolean;
3030
+ toJSON(): ForumPost;
3031
+ }
3032
+
3033
+ /**
3034
+ * A rich wrapper around a raw `ServerEvent` object.
3035
+ *
3036
+ * @example
3037
+ * const events = await client.fetchEvents('server-id', { upcoming: true })
3038
+ * for (const event of events) {
3039
+ * console.log(`${event.title} starts at ${event.startAt}`)
3040
+ * }
3041
+ */
3042
+ declare class NovaServerEvent implements ServerEvent {
3043
+ private readonly raw;
3044
+ private readonly events;
3045
+ readonly id: string;
3046
+ readonly serverId: string;
3047
+ readonly channelId: string | null;
3048
+ readonly createdById: string;
3049
+ readonly title: string;
3050
+ readonly description: string | null;
3051
+ readonly imageUrl: string | null;
3052
+ readonly location: string | null;
3053
+ readonly startAt: string;
3054
+ readonly endAt: string | null;
3055
+ readonly attendeeCount: number | undefined;
3056
+ readonly createdAt: string;
3057
+ constructor(raw: ServerEvent, events: EventsAPI);
3058
+ /**
3059
+ * Edit this event.
3060
+ *
3061
+ * @example
3062
+ * await event.edit({ title: 'New Title' })
3063
+ */
3064
+ edit(options: EditEventOptions): Promise<NovaServerEvent>;
3065
+ /**
3066
+ * Fetch full event details including the attendee list.
3067
+ *
3068
+ * @example
3069
+ * const full = await event.fetchAttendees()
3070
+ * console.log(`${full.attendees.length} attendees`)
3071
+ */
3072
+ fetchAttendees(): Promise<{
3073
+ event: NovaServerEvent;
3074
+ attendees: ServerEventAttendee[];
3075
+ }>;
3076
+ /**
3077
+ * Delete this event.
3078
+ *
3079
+ * @example
3080
+ * await event.delete()
3081
+ */
3082
+ delete(): Promise<void>;
3083
+ /**
3084
+ * Whether the event has already started.
3085
+ */
3086
+ get hasStarted(): boolean;
3087
+ /**
3088
+ * Whether the event has ended.
3089
+ * Returns `false` if no `endAt` is set.
3090
+ */
3091
+ get hasEnded(): boolean;
3092
+ /**
3093
+ * Whether this is an upcoming event that has not yet started.
3094
+ */
3095
+ get isUpcoming(): boolean;
3096
+ toJSON(): ServerEvent;
3097
+ }
3098
+
3099
+ /**
3100
+ * A rich wrapper around a raw `BanEntry` that adds an `unban()` convenience method.
3101
+ *
3102
+ * Returned by `client.fetchBans()`.
3103
+ *
3104
+ * @example
3105
+ * const bans = await client.fetchBans('server-id')
3106
+ * for (const ban of bans) {
3107
+ * if (ban.reason === 'testing') {
3108
+ * await ban.unban()
3109
+ * console.log(`Unbanned ${ban.displayName}`)
3110
+ * }
3111
+ * }
3112
+ */
3113
+ declare class NovaBan implements BanEntry {
3114
+ /** The banned user's ID. */
3115
+ readonly userId: string;
3116
+ /** The banned user's username. */
3117
+ readonly username: string;
3118
+ /** The banned user's display name. */
3119
+ readonly displayName: string;
3120
+ /** The banned user's avatar URL, or `null`. */
3121
+ readonly avatar: string | null;
3122
+ /** The reason for the ban, or `null`. */
3123
+ readonly reason: string | null;
3124
+ /** ISO timestamp of when the ban was issued. */
3125
+ readonly bannedAt: string;
3126
+ /** ID of the moderator who issued the ban, or `null`. */
3127
+ readonly moderatorId: string | null;
3128
+ /** ID of the server this ban belongs to. */
3129
+ readonly serverId: string;
3130
+ private readonly _members;
3131
+ constructor(raw: BanEntry, serverId: string, members: MembersAPI);
3132
+ /**
3133
+ * Revoke this ban, allowing the user to rejoin the server.
3134
+ * Requires the `members.ban` scope.
3135
+ *
3136
+ * @example
3137
+ * await ban.unban()
3138
+ */
3139
+ unban(): Promise<{
3140
+ ok: true;
3141
+ }>;
3142
+ /**
3143
+ * When the ban was issued as a `Date` object.
3144
+ */
3145
+ get bannedAtDate(): Date;
3146
+ /**
3147
+ * Human-readable label: `"displayName (username)"`.
3148
+ */
3149
+ get label(): string;
3150
+ toJSON(): BanEntry;
3151
+ }
3152
+
3153
+ /**
3154
+ * A rich wrapper around a raw `Warning` that adds a `delete()` convenience method.
3155
+ *
3156
+ * Returned by `client.fetchMemberWarnings()` and `member.fetchWarnings()`.
3157
+ *
3158
+ * @example
3159
+ * const warnings = await member.fetchWarnings()
3160
+ * for (const warning of warnings) {
3161
+ * console.log(`[${warning.issuedAt.toLocaleDateString()}] ${warning.reason}`)
3162
+ * }
3163
+ *
3164
+ * // Remove the oldest warning if there are too many
3165
+ * if (warnings.length > 5) {
3166
+ * await warnings[0].delete()
3167
+ * }
3168
+ */
3169
+ declare class NovaWarning implements Warning {
3170
+ /** Unique ID of this warning. */
3171
+ readonly id: string;
3172
+ /** ID of the server where the warning was issued. */
3173
+ readonly serverId: string;
3174
+ /** ID of the user who received the warning. */
3175
+ readonly userId: string;
3176
+ /** ID of the moderator who issued the warning. */
3177
+ readonly moderatorId: string;
3178
+ /** The reason text. */
3179
+ readonly reason: string;
3180
+ /** ISO timestamp of when the warning was issued. */
3181
+ readonly createdAt: string;
3182
+ private readonly _members;
3183
+ constructor(raw: Warning, members: MembersAPI);
3184
+ /**
3185
+ * Delete (expunge) this warning from the record.
3186
+ * Requires the `members.moderate` scope.
3187
+ *
3188
+ * @example
3189
+ * await warning.delete()
3190
+ */
3191
+ delete(): Promise<{
3192
+ ok: true;
3193
+ }>;
3194
+ /**
3195
+ * When the warning was issued as a `Date` object.
3196
+ */
3197
+ get issuedAt(): Date;
3198
+ /**
3199
+ * How long ago the warning was issued, in milliseconds.
3200
+ */
3201
+ get ageMs(): number;
3202
+ toJSON(): Warning;
3203
+ }
3204
+
3205
+ /**
3206
+ * Function called when a value is emitted.
3207
+ */
3208
+ type Observer<T> = (value: T) => void;
3209
+ /**
3210
+ * A function that transforms one EventStream into another.
3211
+ * Used with the `pipe()` operator.
3212
+ */
3213
+ type OperatorFn<T, U> = (stream: EventStream<T>) => EventStream<U>;
3214
+ /**
3215
+ * Represents an active subscription to an `EventStream`.
3216
+ * Call `.unsubscribe()` to cancel delivery and free resources.
3217
+ *
3218
+ * @example
3219
+ * const sub = client.stream('messageCreate').subscribe(msg => console.log(msg.content))
3220
+ * // Later:
3221
+ * sub.unsubscribe()
3222
+ */
3223
+ declare class Subscription {
3224
+ private readonly _teardown;
3225
+ private _closed;
3226
+ constructor(teardown: () => void);
3227
+ /** `true` once `unsubscribe()` has been called. */
3228
+ get closed(): boolean;
3229
+ /** Cancel the subscription. Safe to call multiple times. */
3230
+ unsubscribe(): void;
3231
+ }
3232
+ /**
3233
+ * A lazy, composable reactive stream — like RxJS `Observable` but zero-dependency.
3234
+ *
3235
+ * Streams are **cold** by default: the source function runs fresh for each
3236
+ * `subscribe()` call. When created by `client.stream()` they become effectively
3237
+ * **hot**, sharing the same underlying gateway event source.
3238
+ *
3239
+ * @example
3240
+ * // Filter messages in a specific channel and debounce rapid edits
3241
+ * client.stream('messageCreate')
3242
+ * .filter(msg => msg.channelId === '123')
3243
+ * .debounce(500)
3244
+ * .subscribe(msg => console.log('New message:', msg.content))
3245
+ *
3246
+ * // Collect the next 5 pings, then stop
3247
+ * const pings = await client.stream('messageCreate')
3248
+ * .filter(msg => msg.content === '!ping')
3249
+ * .collect(5)
3250
+ */
3251
+ declare class EventStream<T> {
3252
+ /** @internal Source function — called once per `subscribe()`. */
3253
+ readonly _source: (observer: Observer<T>) => () => void;
3254
+ constructor(
3255
+ /** @internal Source function — called once per `subscribe()`. */
3256
+ _source: (observer: Observer<T>) => () => void);
3257
+ /**
3258
+ * Activate the stream and receive values via `fn`.
3259
+ * Returns a `Subscription` — call `.unsubscribe()` to stop delivery.
3260
+ *
3261
+ * @example
3262
+ * const sub = stream.subscribe(value => console.log(value))
3263
+ * // later…
3264
+ * sub.unsubscribe()
3265
+ */
3266
+ subscribe(fn: Observer<T>): Subscription;
3267
+ /**
3268
+ * Only pass values that satisfy `predicate`.
3269
+ *
3270
+ * @example
3271
+ * stream.filter(msg => msg.content.startsWith('!'))
3272
+ */
3273
+ filter(predicate: (value: T) => boolean): EventStream<T>;
3274
+ /**
3275
+ * Transform each value with `transform`.
3276
+ *
3277
+ * @example
3278
+ * stream.map(msg => msg.content.toUpperCase())
3279
+ */
3280
+ map<U>(transform: (value: T) => U): EventStream<U>;
3281
+ /**
3282
+ * Map each value to an inner stream and flatten the results.
3283
+ *
3284
+ * @example
3285
+ * client.stream('messageCreate')
3286
+ * .flatMap(msg => client.stream('reactionAdd').filter(r => r.messageId === msg.id))
3287
+ */
3288
+ flatMap<U>(transform: (value: T) => EventStream<U>): EventStream<U>;
3289
+ /**
3290
+ * Stop after emitting `count` values.
3291
+ *
3292
+ * @example
3293
+ * stream.take(1).subscribe(first => console.log('First:', first))
3294
+ */
3295
+ take(count: number): EventStream<T>;
3296
+ /**
3297
+ * Skip the first `count` values.
3298
+ *
3299
+ * @example
3300
+ * stream.skip(3) // ignore the first 3
3301
+ */
3302
+ skip(count: number): EventStream<T>;
3303
+ /**
3304
+ * Emit values while `predicate` returns `true`, then auto-unsubscribe.
3305
+ *
3306
+ * @example
3307
+ * stream.takeWhile(n => n < 10)
3308
+ */
3309
+ takeWhile(predicate: (value: T) => boolean): EventStream<T>;
3310
+ /**
3311
+ * Stop emitting once `signal` resolves.
3312
+ *
3313
+ * @example
3314
+ * const stop = new Promise(resolve => setTimeout(resolve, 5_000))
3315
+ * stream.takeUntil(stop).subscribe(handler)
3316
+ */
3317
+ takeUntil(signal: Promise<unknown>): EventStream<T>;
3318
+ /**
3319
+ * Delay forwarding by `ms`. If a new value arrives before the delay expires
3320
+ * the timer resets — only the last value within a quiet period passes.
3321
+ * Useful for suppressing bursts.
3322
+ *
3323
+ * @example
3324
+ * client.stream('typingStart').debounce(300).subscribe(onTyping)
3325
+ */
3326
+ debounce(ms: number): EventStream<T>;
3327
+ /**
3328
+ * Forward a value at most once per `ms` milliseconds (leading-edge).
3329
+ *
3330
+ * @example
3331
+ * client.stream('reactionAdd').throttle(1_000).subscribe(alert)
3332
+ */
3333
+ throttle(ms: number): EventStream<T>;
3334
+ /**
3335
+ * Collect emitted values into windows of `windowMs` milliseconds and emit
3336
+ * each window as an array. Empty windows are skipped.
3337
+ *
3338
+ * @example
3339
+ * // Count messages per second
3340
+ * client.stream('messageCreate').windowTime(1_000).subscribe(batch => {
3341
+ * console.log(`${batch.length} msgs in last second`)
3342
+ * })
3343
+ */
3344
+ windowTime(windowMs: number): EventStream<T[]>;
3345
+ /**
3346
+ * Merge another stream into this one.
3347
+ *
3348
+ * @example
3349
+ * streamA.merge(streamB).subscribe(handler)
3350
+ */
3351
+ merge(other: EventStream<T>): EventStream<T>;
3352
+ /**
3353
+ * Emit a `[T, U]` tuple each time EITHER stream fires,
3354
+ * pairing with the most recent value from the other stream.
3355
+ * Requires both streams to have emitted at least one value.
3356
+ *
3357
+ * @example
3358
+ * positionStream.combineLatest(speedStream).subscribe(([pos, speed]) => …)
3359
+ */
3360
+ combineLatest<U>(other: EventStream<U>): EventStream<[T, U]>;
3361
+ /**
3362
+ * Resolve with the first value that satisfies an optional `predicate`,
3363
+ * then automatically unsubscribe.
3364
+ *
3365
+ * @example
3366
+ * const welcome = await client.stream('messageCreate')
3367
+ * .filter(m => m.content === 'hello')
3368
+ * .first()
3369
+ */
3370
+ first(predicate?: (value: T) => boolean): Promise<T>;
3371
+ /**
3372
+ * Collect exactly `count` values and resolve with them as an array.
3373
+ *
3374
+ * @example
3375
+ * const next3 = await client.stream('messageCreate').collect(3)
3376
+ */
3377
+ collect(count: number): Promise<T[]>;
3378
+ /**
3379
+ * Apply a sequence of operators left-to-right.
3380
+ * Each operator is a function `(EventStream<In>) => EventStream<Out>`.
3381
+ *
3382
+ * @example
3383
+ * const dedupFilter = (s: EventStream<string>) =>
3384
+ * s.filter(v => v.length > 0)
3385
+ *
3386
+ * stream
3387
+ * .pipe(dedupFilter, s => s.take(10))
3388
+ * .subscribe(console.log)
3389
+ */
3390
+ pipe<A>(op1: OperatorFn<T, A>): EventStream<A>;
3391
+ pipe<A, B>(op1: OperatorFn<T, A>, op2: OperatorFn<A, B>): EventStream<B>;
3392
+ pipe<A, B, C>(op1: OperatorFn<T, A>, op2: OperatorFn<A, B>, op3: OperatorFn<B, C>): EventStream<C>;
3393
+ pipe<A, B, C, D>(op1: OperatorFn<T, A>, op2: OperatorFn<A, B>, op3: OperatorFn<B, C>, op4: OperatorFn<C, D>): EventStream<D>;
3394
+ /**
3395
+ * Consume the stream with `for await…of`.
3396
+ *
3397
+ * @example
3398
+ * for await (const msg of client.stream('messageCreate').take(10)) {
3399
+ * await msg.reply('Got it')
3400
+ * }
3401
+ */
3402
+ [Symbol.asyncIterator](): AsyncIterableIterator<T>;
3403
+ /**
3404
+ * Emit a fixed list of values synchronously on subscribe, then complete.
3405
+ */
3406
+ static of<T>(...values: T[]): EventStream<T>;
3407
+ /**
3408
+ * Emit an incrementing counter every `ms` milliseconds.
3409
+ *
3410
+ * @example
3411
+ * EventStream.interval(1_000).take(10).subscribe(n => console.log('tick', n))
3412
+ */
3413
+ static interval(ms: number): EventStream<number>;
3414
+ /**
3415
+ * Merge multiple streams into one.
3416
+ *
3417
+ * @example
3418
+ * EventStream.merge(streamA, streamB).subscribe(handler)
3419
+ */
3420
+ static merge<T>(...streams: EventStream<T>[]): EventStream<T>;
3421
+ /**
3422
+ * Create a hot stream from any Node.js-style `EventEmitter`.
3423
+ *
3424
+ * @example
3425
+ * EventStream.fromEmitter<string>(process, 'message').subscribe(console.log)
3426
+ */
3427
+ static fromEmitter<T>(emitter: {
3428
+ on(event: string, listener: (v: T) => void): unknown;
3429
+ off(event: string, listener: (v: T) => void): unknown;
3430
+ }, event: string): EventStream<T>;
3431
+ }
3432
+
3433
+ interface EventBufferOptions {
3434
+ /**
3435
+ * Maximum number of events to retain in the ring buffer.
3436
+ * When full, the oldest item is discarded to make room for the newest.
3437
+ * Default: `100`.
3438
+ */
3439
+ size?: number;
3440
+ }
3441
+ /**
3442
+ * A fixed-size ring buffer that captures events from a `NovaClient` event type
3443
+ * and lets you replay them to new subscribers at any time.
3444
+ *
3445
+ * Obtained via `client.buffer(event, options)` — do **not** construct directly.
3446
+ *
3447
+ * @example
3448
+ * // Start capturing messages (call once, before connect or early in ready)
3449
+ * const msgBuffer = client.buffer('messageCreate', { size: 200 })
3450
+ *
3451
+ * // Later — replay everything received so far, then keep streaming
3452
+ * msgBuffer.asStream({ replay: true }).subscribe(msg => {
3453
+ * console.log('[replayed or live]', msg.content)
3454
+ * })
3455
+ *
3456
+ * // Quickly inspect the last 10 messages without subscribing
3457
+ * const recent = msgBuffer.getLast(10)
3458
+ *
3459
+ * // Use with async iterator
3460
+ * for await (const msg of msgBuffer.asStream({ replay: true })) {
3461
+ * if (msg.content === 'stop') break
3462
+ * }
3463
+ */
3464
+ declare class EventBuffer<T> {
3465
+ private readonly _ring;
3466
+ private readonly _maxSize;
3467
+ private readonly _observers;
3468
+ constructor(options?: EventBufferOptions);
3469
+ /**
3470
+ * @internal
3471
+ * Called by `NovaClient._deliverEvent()` each time the event fires.
3472
+ * Push to ring buffer and notify live subscribers.
3473
+ */
3474
+ _push(item: T): void;
3475
+ /** All buffered items, oldest first. Never mutate the returned array. */
3476
+ getAll(): T[];
3477
+ /**
3478
+ * The N most recent items.
3479
+ *
3480
+ * @example
3481
+ * const last5 = buffer.getLast(5)
3482
+ */
3483
+ getLast(n: number): T[];
3484
+ /** The most recently buffered item, or `undefined` if the buffer is empty. */
3485
+ get latest(): T | undefined;
3486
+ /** Number of items currently stored. */
3487
+ get size(): number;
3488
+ /** Maximum number of items the buffer can hold. */
3489
+ get capacity(): number;
3490
+ /** `true` when no items are stored. */
3491
+ get isEmpty(): boolean;
3492
+ /** Whether the buffer is at maximum capacity. */
3493
+ get isFull(): boolean;
3494
+ /** Remove all buffered items without affecting active subscriptions. */
3495
+ clear(): void;
3496
+ /**
3497
+ * Expose the buffer as an `EventStream`, giving access to all chaining
3498
+ * operators (`.filter()`, `.map()`, `.debounce()`, etc.).
3499
+ *
3500
+ * Pass `{ replay: true }` to emit all currently buffered items to the
3501
+ * subscriber **before** switching to live delivery.
3502
+ *
3503
+ * @example
3504
+ * // Replay + live with filter
3505
+ * buffer
3506
+ * .asStream({ replay: true })
3507
+ * .filter(msg => msg.channelId === '123')
3508
+ * .subscribe(msg => console.log(msg.content))
3509
+ */
3510
+ asStream(options?: {
3511
+ replay?: boolean;
3512
+ }): EventStream<T>;
3513
+ /**
3514
+ * Subscribe directly, with optional replay.
3515
+ * Equivalent to `.asStream(options).subscribe(fn)`.
3516
+ *
3517
+ * @example
3518
+ * buffer.subscribe(msg => handle(msg), { replay: true })
3519
+ */
3520
+ subscribe(fn: Observer<T>, options?: {
3521
+ replay?: boolean;
3522
+ }): Subscription;
3523
+ /**
3524
+ * Iterate over all **currently buffered** items synchronously.
3525
+ *
3526
+ * @example
3527
+ * for (const msg of buffer) {
3528
+ * console.log(msg.content)
3529
+ * }
3530
+ */
3531
+ [Symbol.iterator](): Iterator<T>;
3532
+ }
3533
+
3534
+ interface NovaClientEvents {
3535
+ /** Fired when the bot connects and is identified by the gateway. */
3536
+ ready: (bot: BotApplication) => void;
3537
+ /** Fired for every raw `bot:event` from the gateway. */
3538
+ event: (event: BotEvent) => void;
3539
+ /**
3540
+ * Fired when an interaction is received (slash command, button click, etc.).
3541
+ * Use `client.command()`, `client.button()`, `client.selectMenu()`, or
3542
+ * `client.autocomplete()` for convenient routing instead of handling everything here.
3543
+ */
3544
+ interactionCreate: (interaction: NovaInteraction) => void;
3545
+ /** Fired when the WebSocket connection drops. */
3546
+ disconnect: (reason: string) => void;
3547
+ /** Fired on gateway / API errors. */
3548
+ error: (err: Error | {
3549
+ code: number;
3550
+ message: string;
3551
+ }) => void;
3552
+ /** A new message was sent in a channel the bot can see. */
3553
+ messageCreate: (message: NovaMessage) => void;
3554
+ /** A message was edited. Returns the updated message. */
3555
+ messageUpdate: (message: NovaMessage) => void;
3556
+ /** A message was deleted. Returns partial data. */
3557
+ messageDelete: (data: {
3558
+ id: string;
3559
+ channelId: string;
3560
+ }) => void;
3561
+ /** A reaction was added to a message. */
3562
+ reactionAdd: (data: {
3563
+ messageId: string;
3564
+ channelId: string;
3565
+ userId: string;
3566
+ emoji: string;
3567
+ }) => void;
3568
+ /** A reaction was removed from a message. */
3569
+ reactionRemove: (data: {
3570
+ messageId: string;
3571
+ channelId: string;
3572
+ userId: string;
3573
+ emoji: string;
3574
+ }) => void;
3575
+ /** A member joined a server the bot is in. */
3576
+ memberAdd: (data: {
3577
+ serverId: string;
3578
+ userId: string;
3579
+ username: string;
3580
+ }) => void;
3581
+ /** A member left a server the bot is in. */
3582
+ memberRemove: (data: {
3583
+ serverId: string;
3584
+ userId: string;
3585
+ }) => void;
3586
+ /** A user started typing in a channel. */
3587
+ typingStart: (data: {
3588
+ channelId: string;
3589
+ userId: string;
3590
+ }) => void;
3591
+ /** A message was pinned. */
3592
+ messagePinned: (data: {
3593
+ messageId: string;
3594
+ channelId: string;
3595
+ pinnedBy: string;
3596
+ }) => void;
3597
+ /** A channel was created in a server. */
3598
+ channelCreate: (channel: Channel) => void;
3599
+ /** A channel was updated. */
3600
+ channelUpdate: (channel: Channel) => void;
3601
+ /** A channel was deleted. */
3602
+ channelDelete: (data: {
3603
+ id: string;
3604
+ serverId: string;
3605
+ }) => void;
3606
+ /** A role was created in a server. */
3607
+ roleCreate: (role: Role) => void;
3608
+ /** A role was updated. */
3609
+ roleUpdate: (role: Role) => void;
3610
+ /** A role was deleted. */
3611
+ roleDelete: (data: {
3612
+ id: string;
3613
+ serverId: string;
3614
+ }) => void;
3615
+ /** A user joined a voice channel. */
3616
+ voiceJoin: (data: {
3617
+ userId: string;
3618
+ channelId: string;
3619
+ serverId: string;
3620
+ }) => void;
3621
+ /** A user left a voice channel. */
3622
+ voiceLeave: (data: {
3623
+ userId: string;
3624
+ channelId: string;
3625
+ serverId: string;
3626
+ }) => void;
3627
+ /** A member was banned from a server. */
3628
+ memberBanned: (data: {
3629
+ userId: string;
3630
+ serverId: string;
3631
+ moderatorId: string | null;
3632
+ reason: string | null;
3633
+ }) => void;
3634
+ /** A member was unbanned. */
3635
+ memberUnbanned: (data: {
3636
+ userId: string;
3637
+ serverId: string;
3638
+ }) => void;
3639
+ /** A member received or lost a custom role. */
3640
+ memberRoleAdded: (data: {
3641
+ serverId: string;
3642
+ userId: string;
3643
+ roleId: string;
3644
+ }) => void;
3645
+ memberRoleRemoved: (data: {
3646
+ serverId: string;
3647
+ userId: string;
3648
+ roleId: string;
3649
+ }) => void;
3650
+ /** A member's profile data was updated. */
3651
+ memberUpdate: (data: {
3652
+ userId: string;
3653
+ serverId: string;
3654
+ }) => void;
3655
+ /** Server metadata (name, icon, etc.) was updated. */
3656
+ serverUpdate: (data: {
3657
+ id: string;
3658
+ name?: string;
3659
+ icon?: string | null;
3660
+ description?: string | null;
3661
+ }) => void;
3662
+ /** An invite was created. */
3663
+ inviteCreate: (invite: Invite) => void;
3664
+ /** An invite was deleted/revoked. */
3665
+ inviteDelete: (data: {
3666
+ code: string;
3667
+ serverId: string;
3668
+ }) => void;
3669
+ /** A forum post was created in a FORUM channel. */
3670
+ forumPostCreate: (post: NovaForumPost) => void;
3671
+ /** A server event was created. */
3672
+ eventCreate: (event: NovaServerEvent) => void;
3673
+ /** A server event was updated. */
3674
+ eventUpdate: (event: ServerEvent) => void;
3675
+ /** A server event was deleted. */
3676
+ eventDelete: (data: {
3677
+ id: string;
3678
+ serverId: string;
3679
+ }) => void;
3680
+ /** A channel category was created. */
3681
+ categoryCreate: (category: ChannelCategory) => void;
3682
+ /** A channel category was updated. */
3683
+ categoryUpdate: (category: ChannelCategory) => void;
3684
+ /** A channel category was deleted. */
3685
+ categoryDelete: (data: {
3686
+ id: string;
3687
+ serverId: string;
3688
+ }) => void;
3689
+ /** A member received a warning. */
3690
+ memberWarned: (data: {
3691
+ serverId: string;
3692
+ userId: string;
3693
+ warning: Warning;
3694
+ }) => void;
3695
+ /** Multiple messages were bulk-deleted. */
3696
+ messagesBulkDelete: (data: {
3697
+ channelId: string;
3698
+ messageIds: string[];
3699
+ count: number;
3700
+ }) => void;
3701
+ }
3702
+ /**
3703
+ * The main Nova bot client.
3704
+ *
3705
+ * @example
3706
+ * import { NovaClient } from 'nova-bot-sdk'
3707
+ *
3708
+ * const client = new NovaClient({ token: 'nova_bot_...' })
3709
+ *
3710
+ * client.on('ready', (bot) => {
3711
+ * console.log(`Logged in as ${bot.botUser.username}`)
3712
+ * })
3713
+ *
3714
+ * client.on('interactionCreate', async (interaction) => {
3715
+ * if (interaction.commandName === 'ping') {
3716
+ * await client.interactions.respond(interaction.id, { content: 'Pong!' })
3717
+ * }
3718
+ * })
3719
+ *
3720
+ * await client.connect()
3721
+ */
3722
+ declare class NovaClient extends EventEmitter {
3723
+ /** The authenticated bot application. Available after `ready` fires. */
3724
+ botUser: BotApplication | null;
3725
+ /** Send, edit, delete and fetch messages. */
3726
+ readonly messages: MessagesAPI;
3727
+ /** Register and manage slash, prefix, and context menu commands. */
3728
+ readonly commands: CommandsAPI;
3729
+ /** List, kick, ban, and DM server members. */
3730
+ readonly members: MembersAPI;
3731
+ /** List and update servers the bot is a member of. */
3732
+ readonly servers: ServersAPI;
3733
+ /** Acknowledge and respond to interactions. */
3734
+ readonly interactions: InteractionsAPI;
3735
+ /** Query the bot's effective permissions within a server, channel, or role scope. */
3736
+ readonly permissions: PermissionsAPI;
3737
+ /** Create, edit, and delete channels; fetch pins and messages. */
3738
+ readonly channels: ChannelsAPI;
3739
+ /** Add, remove and fetch reactions on messages. */
3740
+ readonly reactions: ReactionsAPI;
3741
+ /** Create, edit, delete and assign custom roles. */
3742
+ readonly roles: RolesAPI;
3743
+ /** Create, fetch and revoke server invites. */
3744
+ readonly invites: InvitesAPI;
3745
+ /** Create, edit, delete and execute webhooks. */
3746
+ readonly webhooks: WebhooksAPI;
3747
+ /** Fetch server audit logs. */
3748
+ readonly auditLog: AuditLogAPI;
3749
+ /** Create and manage forum posts in FORUM channels. */
3750
+ readonly forum: ForumAPI;
3751
+ /** Create and manage server events. */
3752
+ readonly events: EventsAPI;
3753
+ /** Manage channel categories. */
3754
+ readonly categories: CategoriesAPI;
3755
+ /** Manage automod rules (blocked words / links). */
3756
+ readonly automod: AutoModAPI;
3757
+ /** Fetch user profiles. */
3758
+ readonly users: UsersAPI;
3759
+ private socket;
3760
+ private readonly http;
3761
+ private readonly options;
3762
+ private _cronTimers;
3763
+ private readonly _commandHandlers;
3764
+ private readonly _buttonHandlers;
3765
+ private readonly _selectHandlers;
3766
+ private readonly _modalHandlers;
3767
+ private readonly _autocompleteHandlers;
3768
+ private readonly _middlewares;
3769
+ private readonly _streamListeners;
3770
+ private readonly _bufferInstances;
3771
+ constructor(options: NovaClientOptions);
3772
+ /**
3773
+ * Register a handler for a slash or prefix command by name.
3774
+ * Automatically routes `interactionCreate` events whose `commandName` matches.
3775
+ *
3776
+ * @example
3777
+ * client.command('ping', async (interaction) => {
3778
+ * await interaction.reply('Pong! 🏓')
3779
+ * })
3780
+ */
3781
+ command(name: string, handler: (interaction: NovaInteraction) => unknown): this;
3782
+ /**
3783
+ * Register a handler for a button by its `customId`.
3784
+ *
3785
+ * @example
3786
+ * client.button('confirm_delete', async (interaction) => {
3787
+ * await interaction.replyEphemeral('Deleted.')
3788
+ * })
3789
+ */
3790
+ button(customId: string, handler: (interaction: NovaInteraction) => unknown): this;
3791
+ /**
3792
+ * Register a handler for a select menu by its `customId`.
3793
+ *
3794
+ * @example
3795
+ * client.selectMenu('colour_pick', async (interaction) => {
3796
+ * const chosen = interaction.values[0]
3797
+ * await interaction.reply(`You picked: ${chosen}`)
3798
+ * })
3799
+ */
3800
+ selectMenu(customId: string, handler: (interaction: NovaInteraction) => unknown): this;
3801
+ /**
3802
+ * Register a handler for a modal submission by its `customId`.
3803
+ * Called automatically when the user submits a modal with that `customId`.
3804
+ *
3805
+ * @example
3806
+ * client.modal('report_modal', async (interaction) => {
3807
+ * const reason = interaction.modalData.reason
3808
+ * await interaction.replyEphemeral(`Report received: ${reason}`)
3809
+ * })
3810
+ */
3811
+ modal(customId: string, handler: (interaction: NovaInteraction) => unknown): this;
3812
+ /**
3813
+ * Register a handler for an autocomplete interaction by command name.
3814
+ * Called when the user is typing in an option with `autocomplete: true`.
3815
+ * The handler receives the interaction with `interaction.autocomplete.value`
3816
+ * containing the partial text, and should call `interaction.respondAutocomplete()`
3817
+ * to send completion suggestions.
3818
+ *
3819
+ * @example
3820
+ * client.autocomplete('search', async (interaction) => {
3821
+ * const query = interaction.autocomplete?.value ?? ''
3822
+ * const results = await myDB.search(query)
3823
+ * await interaction.respondAutocomplete(
3824
+ * results.map(r => ({ name: r.label, value: r.id }))
3825
+ * )
3826
+ * })
3827
+ */
3828
+ autocomplete(commandName: string, handler: (interaction: NovaInteraction) => unknown): this;
3829
+ /** Remove a slash/prefix command handler previously registered with `command()`. */
3830
+ removeCommand(name: string): void;
3831
+ /** Remove a button handler previously registered with `button()`. */
3832
+ removeButton(customId: string): void;
3833
+ /** Remove a select-menu handler previously registered with `selectMenu()`. */
3834
+ removeSelectMenu(customId: string): void;
3835
+ /** Remove a modal handler previously registered with `modal()`. */
3836
+ removeModal(customId: string): void;
3837
+ /** Remove an autocomplete handler previously registered with `autocomplete()`. */
3838
+ removeAutocomplete(name: string): void;
3839
+ /**
3840
+ * Remove a middleware function that was added via `use()`.
3841
+ * This is a reference-equality check — pass the exact same function object.
3842
+ */
3843
+ removeMiddleware(fn: (event: string, payload: unknown, next: (p: unknown) => void) => void): void;
3844
+ emit(event: string | symbol, ...args: any[]): boolean;
3845
+ private _deliverEvent;
3846
+ /**
3847
+ * Add middleware to the event pipeline.
3848
+ *
3849
+ * Middleware runs **before** any `.on()` listener or stream subscriber.
3850
+ * Call `next(payload)` to continue the chain, passing an optionally modified
3851
+ * payload. Not calling `next` **cancels** the event entirely.
3852
+ *
3853
+ * **Global middleware** (all events):
3854
+ * @example
3855
+ * client.use((event, payload, next) => {
3856
+ * console.log(`[${event}]`)
3857
+ * next(payload) // pass through unchanged
3858
+ * })
3859
+ *
3860
+ * **Per-event typed middleware** (single event):
3861
+ * @example
3862
+ * client.use('messageCreate', (msg, next) => {
3863
+ * if (msg.isFromBot()) return // cancel — bots ignored
3864
+ * next(msg)
3865
+ * })
3866
+ *
3867
+ * **Async middleware** (call next after await):
3868
+ * @example
3869
+ * client.use('interactionCreate', async (interaction, next) => {
3870
+ * const ok = await checkRateLimit(interaction.userId)
3871
+ * if (ok) next(interaction)
3872
+ * })
3873
+ */
3874
+ use(fn: (event: string, payload: unknown, next: (p: unknown) => void) => void): this;
3875
+ use<K extends keyof NovaClientEvents>(event: K, fn: (payload: Parameters<NovaClientEvents[K]>[0], next: (p: Parameters<NovaClientEvents[K]>[0]) => void) => void): this;
3876
+ /**
3877
+ * Create a reactive `EventStream` for any client event.
3878
+ *
3879
+ * Streams are **hot** (backed by live gateway events) and support a full
3880
+ * operator library: `.filter()`, `.map()`, `.debounce()`, `.throttle()`,
3881
+ * `.take()`, `.flatMap()`, `.combineLatest()`, `.pipe()`, and more.
3882
+ *
3883
+ * Works with `for await…of` thanks to built-in `[Symbol.asyncIterator]`.
3884
+ *
3885
+ * @example
3886
+ * // Only messages in a specific channel, de-duped over 200 ms
3887
+ * client.stream('messageCreate')
3888
+ * .filter(msg => msg.channelId === announcementId)
3889
+ * .debounce(200)
3890
+ * .subscribe(msg => announce(msg))
3891
+ *
3892
+ * // Collect the next 3 pings as an array
3893
+ * const pings = await client.stream('messageCreate')
3894
+ * .filter(m => m.content === '!ping')
3895
+ * .collect(3)
3896
+ *
3897
+ * // Async iteration
3898
+ * for await (const interaction of client.stream('interactionCreate').take(10)) {
3899
+ * await interaction.reply('Processed')
3900
+ * }
3901
+ *
3902
+ * // combineLatest: pair each new message with the latest reaction event
3903
+ * client.stream('messageCreate')
3904
+ * .combineLatest(client.stream('reactionAdd'))
3905
+ * .subscribe(([msg, reaction]) => { … })
3906
+ */
3907
+ stream<K extends keyof NovaClientEvents>(event: K): EventStream<Parameters<NovaClientEvents[K]>[0]>;
3908
+ /**
3909
+ * Start capturing events of `event` in a ring buffer of up to `size` items.
3910
+ * Repeated calls for the same event return the **same** buffer instance.
3911
+ *
3912
+ * Later subscribers can replay all captured events, then continue receiving
3913
+ * live ones — a built-in alternative to Discord.js "message cache".
3914
+ *
3915
+ * @example
3916
+ * // Capture the last 500 messages (call before connect())
3917
+ * const msgs = client.buffer('messageCreate', { size: 500 })
3918
+ *
3919
+ * // After connect — inspect without subscribing
3920
+ * console.log('Buffered so far:', msgs.size)
3921
+ * const latest = msgs.getLast(5)
3922
+ *
3923
+ * // New handler that replays history first, then receives live events
3924
+ * msgs.asStream({ replay: true })
3925
+ * .filter(m => m.content.includes('@everyone'))
3926
+ * .subscribe(handleMention)
3927
+ *
3928
+ * // Clear the buffer (e.g. when rolling over to a new session)
3929
+ * msgs.clear()
3930
+ */
3931
+ buffer<K extends keyof NovaClientEvents>(event: K, options?: {
3932
+ size?: number;
3933
+ }): EventBuffer<Parameters<NovaClientEvents[K]>[0]>;
3934
+ /**
3935
+ * Connect to the Nova WebSocket gateway.
3936
+ * Resolves when the `ready` event is received.
3937
+ *
3938
+ * @example
3939
+ * await client.connect()
3940
+ */
3941
+ connect(): Promise<void>;
3942
+ /**
3943
+ * Register a recurring task that fires at a set interval.
3944
+ * All cron tasks are automatically cancelled on `disconnect()`.
3945
+ *
3946
+ * @param intervalMs - How often to run the task (in milliseconds).
3947
+ * @param fn - Async or sync function to call on each tick.
3948
+ * @returns A cancel function — call it to stop this specific task.
3949
+ *
3950
+ * @example
3951
+ * // Check for new announcements every 30 seconds
3952
+ * client.cron(30_000, async () => {
3953
+ * const messages = await client.messages.fetch(channelId, { limit: 5 })
3954
+ * // do something...
3955
+ * })
3956
+ */
3957
+ cron(intervalMs: number, fn: () => unknown): () => void;
3958
+ /**
3959
+ * Set the bot's presence status.
3960
+ * Broadcasts to all servers the bot is in via WebSocket.
3961
+ *
3962
+ * @example
3963
+ * client.setStatus('DND') // Do Not Disturb
3964
+ * client.setStatus('IDLE') // Away
3965
+ * client.setStatus('OFFLINE') // Appear offline
3966
+ * client.setStatus('ONLINE') // Back online
3967
+ */
3968
+ setStatus(status: BotStatus): void;
3969
+ /**
3970
+ * Fetch a single channel and return it as a rich `NovaChannel` wrapper.
3971
+ *
3972
+ * @example
3973
+ * const channel = await client.fetchChannel('channel-id')
3974
+ * await channel.send('Hello!')
3975
+ */
3976
+ fetchChannel(channelId: string): Promise<NovaChannel>;
3977
+ /**
3978
+ * Fetch all channels in a server and return them as `NovaChannel` wrappers.
3979
+ *
3980
+ * @example
3981
+ * const channels = await client.fetchChannels('server-id')
3982
+ * const textChannels = channels.filter(c => c.isText())
3983
+ */
3984
+ fetchChannels(serverId: string): Promise<NovaChannel[]>;
3985
+ /**
3986
+ * Fetch all members in a server and return them as `NovaMember` wrappers.
3987
+ *
3988
+ * @example
3989
+ * const members = await client.fetchMembers('server-id')
3990
+ * const bots = members.filter(m => m.isBot)
3991
+ */
3992
+ fetchMembers(serverId: string): Promise<NovaMember[]>;
3993
+ /**
3994
+ * Fetch a single member from a server and return them as a `NovaMember` wrapper.
3995
+ * Uses the dedicated single-member endpoint (more efficient than listing all members).
3996
+ *
3997
+ * @example
3998
+ * const member = await client.fetchMember('server-id', 'user-id')
3999
+ * await member.dm('Welcome!')
4000
+ */
4001
+ fetchMember(serverId: string, userId: string): Promise<NovaMember>;
4002
+ /**
4003
+ * Fetch all bans in a server and return them as `NovaBan` wrappers.
4004
+ * Each `NovaBan` has an `.unban()` convenience method.
4005
+ * Requires the `members.ban` scope.
4006
+ *
4007
+ * @example
4008
+ * const bans = await client.fetchBans('server-id')
4009
+ * for (const ban of bans) {
4010
+ * if (ban.reason === 'test') await ban.unban()
4011
+ * }
4012
+ */
4013
+ fetchBans(serverId: string): Promise<NovaBan[]>;
4014
+ /**
4015
+ * Fetch warnings for a member (or all members) in a server and return them
4016
+ * as `NovaWarning` wrappers. Each wrapper has a `.delete()` convenience method.
4017
+ * Requires the `members.moderate` scope.
4018
+ *
4019
+ * @example
4020
+ * const warnings = await client.fetchMemberWarnings('server-id', 'user-id')
4021
+ * for (const w of warnings) {
4022
+ * if (w.ageMs > 30 * 24 * 60 * 60_000) await w.delete() // older than 30 days
4023
+ * }
4024
+ */
4025
+ fetchMemberWarnings(serverId: string, userId?: string): Promise<NovaWarning[]>;
4026
+ /**
4027
+ * Fetch a single server by ID and return it as a `NovaServerWrapper`.
4028
+ *
4029
+ * @example
4030
+ * const server = await client.fetchServer('server-id')
4031
+ * console.log(`${server.name} — ${server.memberCount} members`)
4032
+ */
4033
+ fetchServer(serverId: string): Promise<NovaServerWrapper>;
4034
+ /**
4035
+ * Fetch all servers the bot is in and return them as `NovaServerWrapper` objects.
4036
+ *
4037
+ * @example
4038
+ * const servers = await client.fetchServers()
4039
+ * for (const s of servers) console.log(s.name)
4040
+ */
4041
+ fetchServers(): Promise<NovaServerWrapper[]>;
4042
+ /**
4043
+ * Fetch all custom roles in a server and return them as `NovaRole` wrappers.
4044
+ *
4045
+ * @example
4046
+ * const roles = await client.fetchRoles('server-id')
4047
+ * const mod = roles.find(r => r.name === 'Moderator')
4048
+ */
4049
+ fetchRoles(serverId: string): Promise<NovaRole[]>;
4050
+ /**
4051
+ * Fetch all active invites for a server and return them as `NovaInvite` wrappers.
4052
+ *
4053
+ * @example
4054
+ * const invites = await client.fetchInvites('server-id')
4055
+ * const active = invites.filter(i => i.isValid())
4056
+ */
4057
+ fetchInvites(serverId: string): Promise<NovaInvite[]>;
4058
+ /**
4059
+ * Fetch a single invite by code and return it as a `NovaInvite` wrapper.
4060
+ *
4061
+ * @example
4062
+ * const invite = await client.fetchInvite('abc123')
4063
+ * if (invite.isExpired()) await invite.revoke()
4064
+ */
4065
+ fetchInvite(code: string): Promise<NovaInvite>;
4066
+ /**
4067
+ * Fetch all webhooks in a channel and return them as `NovaWebhook` wrappers.
4068
+ *
4069
+ * @example
4070
+ * const webhooks = await client.fetchWebhooks('channel-id')
4071
+ */
4072
+ fetchWebhooks(channelId: string): Promise<NovaWebhook[]>;
4073
+ /**
4074
+ * Fetch a single webhook by ID and return it as a `NovaWebhook` wrapper.
4075
+ *
4076
+ * @example
4077
+ * const webhook = await client.fetchWebhook('webhook-id')
4078
+ * await webhook.execute({ content: 'Build passed! ✅' })
4079
+ */
4080
+ fetchWebhook(webhookId: string): Promise<NovaWebhook>;
4081
+ /**
4082
+ * Fetch forum posts from a FORUM channel and return them as `NovaForumPost` wrappers.
4083
+ *
4084
+ * @example
4085
+ * const posts = await client.fetchForumPosts('channel-id', { limit: 20 })
4086
+ * const open = posts.filter(p => !p.isClosed)
4087
+ */
4088
+ fetchForumPosts(channelId: string, options?: FetchForumPostsOptions): Promise<NovaForumPost[]>;
4089
+ /**
4090
+ * Fetch server events and return them as `NovaServerEvent` wrappers.
4091
+ *
4092
+ * @example
4093
+ * const upcoming = await client.fetchEvents('server-id', { upcoming: true })
4094
+ * for (const event of upcoming) console.log(event.title)
4095
+ */
4096
+ fetchEvents(serverId: string, options?: FetchEventsOptions): Promise<NovaServerEvent[]>;
4097
+ /**
4098
+ * Fetch a single server event by ID and return it as a `NovaServerEvent` wrapper.
4099
+ *
4100
+ * @example
4101
+ * const event = await client.fetchEvent('event-id')
4102
+ * if (event.isUpcoming) await event.edit({ title: 'Updated!' })
4103
+ */
4104
+ fetchEvent(eventId: string): Promise<NovaServerEvent>;
4105
+ /**
4106
+ * Fetch a user's public profile.
4107
+ *
4108
+ * @example
4109
+ * const user = await client.fetchUserProfile('user-id')
4110
+ * console.log(user.bio)
4111
+ */
4112
+ fetchUserProfile(userId: string): Promise<UserProfile>;
4113
+ /**
4114
+ * Fetch the XP leaderboard for a server.
4115
+ *
4116
+ * @example
4117
+ * const top = await client.fetchLeaderboard('server-id', 10)
4118
+ * top.forEach(entry => console.log(`#${entry.rank} ${entry.user.username} — ${entry.xp} XP`))
4119
+ */
4120
+ fetchLeaderboard(serverId: string, limit?: number): Promise<LeaderboardEntry[]>;
4121
+ /**
4122
+ * Fetch warnings in a server, optionally filtered by user.
4123
+ *
4124
+ * @example
4125
+ * const warnings = await client.fetchWarnings('server-id', { userId: 'user-id' })
4126
+ */
4127
+ fetchWarnings(serverId: string, options?: FetchWarningsOptions): Promise<Warning[]>;
4128
+ /**
4129
+ * Fetch all automod rules for a server.
4130
+ *
4131
+ * @example
4132
+ * const rules = await client.fetchAutoModRules('server-id')
4133
+ */
4134
+ fetchAutoModRules(serverId: string): Promise<AutoModRule[]>;
4135
+ /**
4136
+ * Fetch all channel categories for a server.
4137
+ *
4138
+ * @example
4139
+ * const cats = await client.fetchCategories('server-id')
4140
+ */
4141
+ fetchCategories(serverId: string): Promise<ChannelCategory[]>;
4142
+ /**
4143
+ * Fetch soundboard clips for a server.
4144
+ *
4145
+ * @example
4146
+ * const clips = await client.fetchSoundboard('server-id')
4147
+ */
4148
+ fetchSoundboard(serverId: string): Promise<SoundboardClip[]>;
4149
+ /**
4150
+ * Fetch statistics for a server (member count, message count, etc.).
4151
+ *
4152
+ * @example
4153
+ * const stats = await client.fetchServerStats('server-id')
4154
+ * console.log(`${stats.onlineCount}/${stats.memberCount} online`)
4155
+ */
4156
+ fetchServerStats(serverId: string): Promise<ServerStats>;
4157
+ /**
4158
+ * Bulk delete up to 100 messages in a channel.
4159
+ * Requires the `messages.manage` scope.
4160
+ *
4161
+ * @example
4162
+ * const result = await client.bulkDelete('channel-id', messageIds)
4163
+ * console.log(`Deleted ${result.deleted} messages`)
4164
+ */
4165
+ bulkDelete(channelId: string, messageIds: string[]): Promise<BulkDeleteResult>;
4166
+ /**
4167
+ * Wait for a specific event to be emitted, optionally filtered.
4168
+ * Rejects after `timeoutMs` (default 30 s) if the condition never fires.
4169
+ *
4170
+ * @example
4171
+ * // Wait for any message in a specific channel
4172
+ * const msg = await client.waitFor('messageCreate', m => m.channelId === channelId)
4173
+ *
4174
+ * // Wait for a button click with a timeout
4175
+ * const i = await client.waitFor('interactionCreate', i => i.isButton(), 60_000)
4176
+ */
4177
+ waitFor<K extends keyof NovaClientEvents>(event: K, filter?: (...args: Parameters<NovaClientEvents[K]>) => boolean, timeoutMs?: number): Promise<Parameters<NovaClientEvents[K]>[0]>;
4178
+ /**
4179
+ * Wait for the next message matching an optional filter.
4180
+ * Short for `waitFor('messageCreate', filter, timeoutMs)`.
4181
+ *
4182
+ * @example
4183
+ * // Wait for any message in a specific channel
4184
+ * const msg = await client.waitForMessage(
4185
+ * m => m.channelId === channelId && !m.isFromBot(),
4186
+ * 30_000,
4187
+ * )
4188
+ * console.log(msg.content)
4189
+ */
4190
+ waitForMessage(filter?: (msg: NovaMessage) => boolean, timeoutMs?: number): Promise<NovaMessage>;
4191
+ /**
4192
+ * Wait for the next button-click interaction matching an optional filter.
4193
+ * Short for `waitFor('interactionCreate', i => i.isButton() && filter(i), timeoutMs)`.
4194
+ *
4195
+ * @example
4196
+ * // Wait for any button on a specific message
4197
+ * const click = await client.waitForButton(
4198
+ * i => i.triggerMsgId === message.id,
4199
+ * 60_000,
4200
+ * )
4201
+ * await click.reply('Button clicked!')
4202
+ */
4203
+ waitForButton(filter?: (i: NovaInteraction) => boolean, timeoutMs?: number): Promise<NovaInteraction>;
4204
+ /**
4205
+ * Wait for the next select-menu interaction matching an optional filter.
4206
+ * Short for `waitFor('interactionCreate', i => i.isSelectMenu() && filter(i), timeoutMs)`.
4207
+ *
4208
+ * @example
4209
+ * const pick = await client.waitForSelectMenu(
4210
+ * i => i.customId === 'colour_pick',
4211
+ * 60_000,
4212
+ * )
4213
+ * await pick.reply(`You picked: ${pick.values.join(', ')}`)
4214
+ */
4215
+ waitForSelectMenu(filter?: (i: NovaInteraction) => boolean, timeoutMs?: number): Promise<NovaInteraction>;
4216
+ /**
4217
+ * Disconnect from the gateway and clean up.
4218
+ */
4219
+ disconnect(): void;
4220
+ /**
4221
+ * Send a message via the WebSocket gateway (lower latency than HTTP).
4222
+ * Requires the `messages.write` scope.
4223
+ *
4224
+ * @example
4225
+ * client.wsSend('channel-id', 'Hello from the gateway!')
4226
+ */
4227
+ wsSend(channelId: string, content: string): void;
4228
+ /**
4229
+ * Start a typing indicator via WebSocket.
4230
+ */
4231
+ wsTypingStart(channelId: string): void;
4232
+ /**
4233
+ * Stop a typing indicator via WebSocket.
4234
+ */
4235
+ wsTypingStop(channelId: string): void;
4236
+ on<K extends keyof NovaClientEvents>(event: K, listener: NovaClientEvents[K]): this;
4237
+ on(event: string | symbol, listener: (...args: unknown[]) => void): this;
4238
+ once<K extends keyof NovaClientEvents>(event: K, listener: NovaClientEvents[K]): this;
4239
+ once(event: string | symbol, listener: (...args: unknown[]) => void): this;
4240
+ off<K extends keyof NovaClientEvents>(event: K, listener: NovaClientEvents[K]): this;
4241
+ off(event: string | symbol, listener: (...args: unknown[]) => void): this;
4242
+ }
4243
+
4244
+ export { type EventBufferOptions as $, type Attachment as A, type BanEntry as B, type ChannelCategory as C, type BotEventType as D, type EmbedField as E, type BotModalDefinition as F, type BotModalField as G, type BotPermissionRecord as H, type InviteCreateOptions as I, type BotStatus as J, type BotUser as K, type BulkDeleteResult as L, type MessageComponent as M, NovaMessage as N, type Channel as O, ChannelsAPI as P, CommandsAPI as Q, type RoleCreateOptions as R, type SlashCommandOption as S, type CreateCategoryOptions as T, type DirectMessage as U, type EditAutoModRuleOptions as V, type EditChannelOptions as W, type EditEventOptions as X, type EditForumPostOptions as Y, type EditMessageOptions as Z, EventBuffer as _, type Embed as a, type VoiceState as a$, EventsAPI as a0, type ExecuteWebhookOptions as a1, type FetchAuditLogsOptions as a2, type FetchChannelsOptions as a3, type FetchEventsOptions as a4, type FetchForumPostsOptions as a5, type FetchMembersOptions as a6, type FetchMessagesOptions as a7, type FetchWarningsOptions as a8, ForumAPI as a9, PermissionsAPI as aA, type PermissionsQueryOptions as aB, type PermissionsResult as aC, type PollInteractionsOptions as aD, type PrefixCommandDefinition as aE, type Reaction as aF, type ReactionDetail as aG, ReactionsAPI as aH, type RegisteredContextCommand as aI, type RegisteredPrefixCommand as aJ, type RegisteredSlashCommand as aK, type RespondInteractionOptions as aL, type Role as aM, type RoleEditOptions as aN, RolesAPI as aO, type ServerEvent as aP, type ServerEventAttendee as aQ, type ServerStats as aR, type ServerUpdateOptions as aS, ServersAPI as aT, type SingleMember as aU, type SoundboardClip as aV, Subscription as aW, TextInputBuilder as aX, type TextInputStyle as aY, type UserProfile as aZ, UsersAPI as a_, type ForumPost as aa, HttpClient as ab, type Interaction as ac, InteractionOptions as ad, type InteractionType as ae, type Invite as af, InvitesAPI as ag, type LeaderboardEntry as ah, type Member as ai, type MemberXPData as aj, MembersAPI as ak, type Message as al, NovaBan as am, NovaChannel as an, type NovaClientOptions as ao, NovaForumPost as ap, NovaInvite as aq, NovaMember as ar, NovaRole as as, type NovaServer as at, NovaServerEvent as au, NovaServerWrapper as av, NovaWarning as aw, NovaWebhook as ax, type Observer as ay, type OperatorFn as az, type SlashCommandDefinition as b, type Warning as b0, type Webhook as b1, type WebhookCreateOptions as b2, type WebhookEditOptions as b3, WebhooksAPI as b4, type SendMessageOptions as c, CategoriesAPI as d, type EditCategoryOptions as e, type CreateForumPostOptions as f, type CreateEventOptions as g, type ChannelType as h, type CreateChannelOptions as i, type CreateAutoModRuleOptions as j, type ContextCommandDefinition as k, NovaInteraction as l, MessagesAPI as m, InteractionsAPI as n, EventStream as o, NovaClient as p, ModalBuilder as q, type NovaClientEvents as r, AuditLogAPI as s, type AuditLogAction as t, type AuditLogEntry as u, AutoModAPI as v, type AutoModRule as w, type AutoModRuleType as x, type BotApplication as y, type BotEvent as z };