novaapp-sdk 1.4.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,4 +1,5 @@
1
1
  import { EventEmitter } from 'node:events';
2
+ import { EventEmitter as EventEmitter$1 } from 'events';
2
3
 
3
4
  /**
4
5
  * Lightweight HTTP client for the Nova Bot API.
@@ -315,7 +316,7 @@ interface RegisteredContextCommand {
315
316
  enabled: boolean;
316
317
  createdAt: string;
317
318
  }
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';
319
+ 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
320
  interface BotEvent<T = unknown> {
320
321
  type: BotEventType;
321
322
  data: T;
@@ -536,6 +537,179 @@ interface NovaClientOptions {
536
537
  */
537
538
  baseUrl?: string;
538
539
  }
540
+ interface ChannelCategory {
541
+ id: string;
542
+ serverId: string;
543
+ name: string;
544
+ position: number;
545
+ createdAt: string;
546
+ }
547
+ interface CreateCategoryOptions {
548
+ name: string;
549
+ position?: number;
550
+ }
551
+ interface EditCategoryOptions {
552
+ name?: string;
553
+ position?: number;
554
+ }
555
+ interface ForumPost {
556
+ id: string;
557
+ channelId: string;
558
+ authorId: string;
559
+ title: string;
560
+ body: string;
561
+ tags: string[];
562
+ pinned: boolean;
563
+ closed: boolean;
564
+ upvoteCount: number;
565
+ replyCount: number;
566
+ author: {
567
+ id: string;
568
+ username: string;
569
+ displayName: string;
570
+ avatar: string | null;
571
+ };
572
+ createdAt: string;
573
+ updatedAt: string;
574
+ }
575
+ interface CreateForumPostOptions {
576
+ title: string;
577
+ body: string;
578
+ tags?: string[];
579
+ }
580
+ interface EditForumPostOptions {
581
+ title?: string;
582
+ body?: string;
583
+ tags?: string[];
584
+ pinned?: boolean;
585
+ closed?: boolean;
586
+ }
587
+ interface FetchForumPostsOptions {
588
+ limit?: number;
589
+ before?: string;
590
+ }
591
+ interface ServerEvent {
592
+ id: string;
593
+ serverId: string;
594
+ channelId: string | null;
595
+ createdById: string;
596
+ title: string;
597
+ description: string | null;
598
+ imageUrl: string | null;
599
+ location: string | null;
600
+ startAt: string;
601
+ endAt: string | null;
602
+ attendeeCount?: number;
603
+ createdAt: string;
604
+ }
605
+ interface ServerEventAttendee {
606
+ eventId: string;
607
+ userId: string;
608
+ status: 'GOING' | 'MAYBE' | 'NOT_GOING';
609
+ user: {
610
+ id: string;
611
+ username: string;
612
+ displayName: string;
613
+ avatar: string | null;
614
+ };
615
+ createdAt: string;
616
+ }
617
+ interface CreateEventOptions {
618
+ title: string;
619
+ description?: string;
620
+ imageUrl?: string;
621
+ location?: string;
622
+ startAt: string;
623
+ endAt?: string;
624
+ channelId?: string;
625
+ }
626
+ interface EditEventOptions {
627
+ title?: string;
628
+ description?: string;
629
+ imageUrl?: string;
630
+ location?: string;
631
+ startAt?: string;
632
+ endAt?: string | null;
633
+ }
634
+ interface FetchEventsOptions {
635
+ limit?: number;
636
+ /** Only return events starting from now. */
637
+ upcoming?: boolean;
638
+ }
639
+ interface MemberXPData {
640
+ userId: string;
641
+ xp: number;
642
+ level: number;
643
+ joinedAt?: string;
644
+ }
645
+ interface LeaderboardEntry extends MemberXPData {
646
+ rank: number;
647
+ user: {
648
+ id: string;
649
+ username: string;
650
+ displayName: string;
651
+ avatar: string | null;
652
+ };
653
+ }
654
+ interface Warning {
655
+ id: string;
656
+ serverId: string;
657
+ userId: string;
658
+ moderatorId: string;
659
+ reason: string;
660
+ createdAt: string;
661
+ }
662
+ interface FetchWarningsOptions {
663
+ userId?: string;
664
+ }
665
+ type AutoModRuleType$1 = 'BLOCKED_WORD' | 'BLOCKED_LINK';
666
+ interface AutoModRule {
667
+ id: string;
668
+ serverId: string;
669
+ type: AutoModRuleType$1;
670
+ value: string;
671
+ enabled: boolean;
672
+ createdAt: string;
673
+ }
674
+ interface CreateAutoModRuleOptions {
675
+ type: AutoModRuleType$1;
676
+ value: string;
677
+ enabled?: boolean;
678
+ }
679
+ interface EditAutoModRuleOptions {
680
+ value?: string;
681
+ enabled?: boolean;
682
+ }
683
+ interface UserProfile {
684
+ id: string;
685
+ username: string;
686
+ displayName: string;
687
+ avatar: string | null;
688
+ status: 'ONLINE' | 'IDLE' | 'DND' | 'OFFLINE';
689
+ bio: string | null;
690
+ isBot: boolean;
691
+ createdAt: string;
692
+ }
693
+ interface SoundboardClip {
694
+ id: string;
695
+ serverId: string;
696
+ name: string;
697
+ fileUrl: string;
698
+ duration: number;
699
+ uploadedById: string;
700
+ createdAt: string;
701
+ }
702
+ interface ServerStats {
703
+ serverId: string;
704
+ memberCount: number;
705
+ channelCount: number;
706
+ roleCount: number;
707
+ onlineCount: number;
708
+ messageCount: number;
709
+ }
710
+ interface BulkDeleteResult {
711
+ deleted: number;
712
+ }
539
713
 
540
714
  declare class MessagesAPI {
541
715
  private readonly http;
@@ -797,6 +971,64 @@ declare class MembersAPI {
797
971
  removeRole(serverId: string, userId: string, roleId: string): Promise<{
798
972
  ok: true;
799
973
  }>;
974
+ /**
975
+ * Issue a warning to a member.
976
+ * Requires the `members.moderate` scope.
977
+ *
978
+ * @example
979
+ * await client.members.warn('server-id', 'user-id', 'Spamming')
980
+ */
981
+ warn(serverId: string, userId: string, reason: string): Promise<Warning>;
982
+ /**
983
+ * Fetch warnings for a server (or optionally a specific user).
984
+ * Requires the `members.moderate` scope.
985
+ *
986
+ * @example
987
+ * const all = await client.members.fetchWarnings('server-id')
988
+ * const userWarnings = await client.members.fetchWarnings('server-id', { userId: 'user-id' })
989
+ */
990
+ fetchWarnings(serverId: string, options?: FetchWarningsOptions): Promise<Warning[]>;
991
+ /**
992
+ * Remove a warning by its ID.
993
+ * Requires the `members.moderate` scope.
994
+ *
995
+ * @example
996
+ * await client.members.removeWarning('warning-id')
997
+ */
998
+ removeWarning(warningId: string): Promise<{
999
+ ok: true;
1000
+ }>;
1001
+ /**
1002
+ * Get a member's XP and level.
1003
+ * Requires the `members.read` scope.
1004
+ *
1005
+ * @example
1006
+ * const xpData = await client.members.getXP('server-id', 'user-id')
1007
+ * console.log(`Level ${xpData.level} — ${xpData.xp} XP`)
1008
+ */
1009
+ getXP(serverId: string, userId: string): Promise<MemberXPData>;
1010
+ /**
1011
+ * Set or add XP to a member.
1012
+ * Requires the `members.manage` scope.
1013
+ *
1014
+ * @example
1015
+ * // Add 50 XP
1016
+ * await client.members.setXP('server-id', 'user-id', { add: 50 })
1017
+ * // Set XP to a specific value
1018
+ * await client.members.setXP('server-id', 'user-id', { xp: 1000 })
1019
+ */
1020
+ setXP(serverId: string, userId: string, options: {
1021
+ xp?: number;
1022
+ add?: number;
1023
+ }): Promise<MemberXPData>;
1024
+ /**
1025
+ * Get the XP leaderboard for a server.
1026
+ * Requires the `members.read` scope.
1027
+ *
1028
+ * @example
1029
+ * const top10 = await client.members.leaderboard('server-id', 10)
1030
+ */
1031
+ leaderboard(serverId: string, limit?: number): Promise<LeaderboardEntry[]>;
800
1032
  }
801
1033
 
802
1034
  declare class ServersAPI {
@@ -836,6 +1068,28 @@ declare class ServersAPI {
836
1068
  * const adminRole = roles.find(r => r.name === 'Admin')
837
1069
  */
838
1070
  listRoles(serverId: string): Promise<Role[]>;
1071
+ /**
1072
+ * Fetch all channel categories in a server.
1073
+ *
1074
+ * @example
1075
+ * const categories = await client.servers.listCategories('server-id')
1076
+ */
1077
+ listCategories(serverId: string): Promise<ChannelCategory[]>;
1078
+ /**
1079
+ * Get server statistics (member count, message count, etc.).
1080
+ *
1081
+ * @example
1082
+ * const stats = await client.servers.getStats('server-id')
1083
+ * console.log(`${stats.onlineCount} online / ${stats.memberCount} total`)
1084
+ */
1085
+ getStats(serverId: string): Promise<ServerStats>;
1086
+ /**
1087
+ * Fetch all soundboard clips uploaded to a server.
1088
+ *
1089
+ * @example
1090
+ * const clips = await client.servers.listSoundboard('server-id')
1091
+ */
1092
+ listSoundboard(serverId: string): Promise<SoundboardClip[]>;
839
1093
  }
840
1094
 
841
1095
  declare class InteractionsAPI {
@@ -1054,6 +1308,16 @@ declare class ChannelsAPI {
1054
1308
  startTyping(channelId: string): Promise<{
1055
1309
  ok: true;
1056
1310
  }>;
1311
+ /**
1312
+ * Bulk delete up to 100 messages from a channel at once.
1313
+ * Requires the `messages.manage` scope.
1314
+ * Soft-deletes all specified messages in a single operation.
1315
+ *
1316
+ * @example
1317
+ * const result = await client.channels.bulkDelete('channel-id', ['msg1', 'msg2', 'msg3'])
1318
+ * console.log(`Deleted ${result.deleted} messages`)
1319
+ */
1320
+ bulkDelete(channelId: string, messageIds: string[]): Promise<BulkDeleteResult>;
1057
1321
  }
1058
1322
 
1059
1323
  declare class ReactionsAPI {
@@ -1314,6 +1578,172 @@ declare class AuditLogAPI {
1314
1578
  fetch(serverId: string, options?: FetchAuditLogsOptions): Promise<AuditLogEntry[]>;
1315
1579
  }
1316
1580
 
1581
+ declare class ForumAPI {
1582
+ private readonly http;
1583
+ constructor(http: HttpClient);
1584
+ /**
1585
+ * List forum posts in a FORUM channel.
1586
+ *
1587
+ * @example
1588
+ * const posts = await client.forum.list('channel-id')
1589
+ */
1590
+ list(channelId: string, options?: FetchForumPostsOptions): Promise<ForumPost[]>;
1591
+ /**
1592
+ * Create a forum post in a FORUM channel.
1593
+ *
1594
+ * @example
1595
+ * const post = await client.forum.create('channel-id', {
1596
+ * title: 'Ideas thread',
1597
+ * body: 'Post your ideas here!',
1598
+ * tags: ['idea', 'discussion'],
1599
+ * })
1600
+ */
1601
+ create(channelId: string, options: CreateForumPostOptions): Promise<ForumPost>;
1602
+ /**
1603
+ * Edit a forum post.
1604
+ * The bot must be the author of the post.
1605
+ *
1606
+ * @example
1607
+ * await client.forum.edit('post-id', { closed: true })
1608
+ */
1609
+ edit(postId: string, options: EditForumPostOptions): Promise<ForumPost>;
1610
+ /**
1611
+ * Delete a forum post.
1612
+ * The bot must be the author of the post.
1613
+ *
1614
+ * @example
1615
+ * await client.forum.delete('post-id')
1616
+ */
1617
+ delete(postId: string): Promise<void>;
1618
+ }
1619
+
1620
+ declare class EventsAPI {
1621
+ private readonly http;
1622
+ constructor(http: HttpClient);
1623
+ /**
1624
+ * List server events.
1625
+ *
1626
+ * @example
1627
+ * const events = await client.events.list('server-id', { upcoming: true })
1628
+ */
1629
+ list(serverId: string, options?: FetchEventsOptions): Promise<ServerEvent[]>;
1630
+ /**
1631
+ * Fetch a single server event by ID.
1632
+ * Returns full attendee list.
1633
+ *
1634
+ * @example
1635
+ * const event = await client.events.fetch('event-id')
1636
+ */
1637
+ fetch(eventId: string): Promise<ServerEvent & {
1638
+ attendees: ServerEventAttendee[];
1639
+ }>;
1640
+ /**
1641
+ * Create a server event.
1642
+ *
1643
+ * @example
1644
+ * const event = await client.events.create('server-id', {
1645
+ * title: 'Game Night',
1646
+ * description: 'Friday fun!',
1647
+ * startAt: new Date(Date.now() + 86400_000).toISOString(),
1648
+ * })
1649
+ */
1650
+ create(serverId: string, options: CreateEventOptions): Promise<ServerEvent>;
1651
+ /**
1652
+ * Edit a server event.
1653
+ *
1654
+ * @example
1655
+ * await client.events.edit('event-id', { title: 'Game Night v2' })
1656
+ */
1657
+ edit(eventId: string, options: EditEventOptions): Promise<ServerEvent>;
1658
+ /**
1659
+ * Delete a server event.
1660
+ *
1661
+ * @example
1662
+ * await client.events.delete('event-id')
1663
+ */
1664
+ delete(eventId: string): Promise<void>;
1665
+ }
1666
+
1667
+ declare class CategoriesAPI {
1668
+ private readonly http;
1669
+ constructor(http: HttpClient);
1670
+ /**
1671
+ * List all channel categories in a server, ordered by position.
1672
+ *
1673
+ * @example
1674
+ * const cats = await client.categories.list('server-id')
1675
+ */
1676
+ list(serverId: string): Promise<ChannelCategory[]>;
1677
+ /**
1678
+ * Create a new channel category.
1679
+ *
1680
+ * @example
1681
+ * const cat = await client.categories.create('server-id', { name: 'General', position: 0 })
1682
+ */
1683
+ create(serverId: string, options: CreateCategoryOptions): Promise<ChannelCategory>;
1684
+ /**
1685
+ * Edit an existing channel category.
1686
+ *
1687
+ * @example
1688
+ * await client.categories.edit('cat-id', { name: 'Renamed' })
1689
+ */
1690
+ edit(categoryId: string, options: EditCategoryOptions): Promise<ChannelCategory>;
1691
+ /**
1692
+ * Delete a channel category.
1693
+ *
1694
+ * @example
1695
+ * await client.categories.delete('cat-id')
1696
+ */
1697
+ delete(categoryId: string): Promise<void>;
1698
+ }
1699
+
1700
+ declare class AutoModAPI {
1701
+ private readonly http;
1702
+ constructor(http: HttpClient);
1703
+ /**
1704
+ * List all automod rules for a server.
1705
+ *
1706
+ * @example
1707
+ * const rules = await client.automod.list('server-id')
1708
+ */
1709
+ list(serverId: string): Promise<AutoModRule[]>;
1710
+ /**
1711
+ * Create a new automod rule.
1712
+ *
1713
+ * @example
1714
+ * await client.automod.create('server-id', { type: 'BLOCKED_WORD', value: 'badword' })
1715
+ * await client.automod.create('server-id', { type: 'BLOCKED_LINK', value: 'example.com' })
1716
+ */
1717
+ create(serverId: string, options: CreateAutoModRuleOptions): Promise<AutoModRule>;
1718
+ /**
1719
+ * Enable / disable a rule or update the blocked value.
1720
+ *
1721
+ * @example
1722
+ * await client.automod.edit('rule-id', { enabled: false })
1723
+ */
1724
+ edit(ruleId: string, options: EditAutoModRuleOptions): Promise<AutoModRule>;
1725
+ /**
1726
+ * Delete an automod rule.
1727
+ *
1728
+ * @example
1729
+ * await client.automod.delete('rule-id')
1730
+ */
1731
+ delete(ruleId: string): Promise<void>;
1732
+ }
1733
+
1734
+ declare class UsersAPI {
1735
+ private readonly http;
1736
+ constructor(http: HttpClient);
1737
+ /**
1738
+ * Fetch a user's public profile by ID.
1739
+ *
1740
+ * @example
1741
+ * const user = await client.users.fetch('user-id')
1742
+ * console.log(user.displayName)
1743
+ */
1744
+ fetch(userId: string): Promise<UserProfile>;
1745
+ }
1746
+
1317
1747
  type TextInputStyle = 'short' | 'paragraph';
1318
1748
  /**
1319
1749
  * Fluent builder for a single text-input field inside a modal.
@@ -1746,24 +2176,70 @@ declare class NovaMessage {
1746
2176
  */
1747
2177
  fetch(): Promise<NovaMessage>;
1748
2178
  /**
1749
- * Get a URL to this message (deep link).
2179
+ * Forward this message's content (and embed if present) to another channel.
2180
+ * Creates a new message in the target channel.
2181
+ *
2182
+ * @example
2183
+ * const forwarded = await msg.forward('target-channel-id')
2184
+ * console.log('Forwarded to:', forwarded.channelId)
1750
2185
  */
1751
- get url(): string;
2186
+ forward(channelId: string): Promise<NovaMessage>;
1752
2187
  /**
1753
- * Return the raw message object.
2188
+ * Fetch detailed reaction data for a specific emoji on this message.
2189
+ * Returns the users who reacted with that emoji.
2190
+ *
2191
+ * @example
2192
+ * const reactors = await msg.fetchReactionDetails('👍')
2193
+ * for (const r of reactors) console.log(r.username, 'reacted 👍')
1754
2194
  */
1755
- toJSON(): Message;
1756
- toString(): string;
1757
- }
1758
-
1759
- /**
1760
- * A rich wrapper around a raw `Channel` with convenience methods.
1761
- *
1762
- * Returned by `client.fetchChannel()` and `client.fetchChannels()`.
1763
- *
1764
- * @example
1765
- * const channel = await client.fetchChannel('channel-id')
1766
- *
2195
+ fetchReactionDetails(emoji: string): ReturnType<ReactionsAPI['fetchEmoji']>;
2196
+ /**
2197
+ * Remove **all** reactions from this message.
2198
+ * Requires the `messages.manage` scope.
2199
+ *
2200
+ * @example
2201
+ * await msg.clearAllReactions()
2202
+ */
2203
+ clearAllReactions(): Promise<{
2204
+ ok: true;
2205
+ }>;
2206
+ /**
2207
+ * Remove all reactions for a specific emoji from this message.
2208
+ * Requires the `messages.manage` scope.
2209
+ *
2210
+ * @example
2211
+ * await msg.clearReactionsFor('👍')
2212
+ */
2213
+ clearReactionsFor(emoji: string): Promise<{
2214
+ ok: true;
2215
+ }>;
2216
+ /**
2217
+ * Fetch a breakdown of all reactions on this message, grouped by emoji.
2218
+ *
2219
+ * @example
2220
+ * const details = await msg.fetchAllReactions()
2221
+ * for (const d of details) console.log(`${d.emoji} — ${d.count}`)
2222
+ */
2223
+ fetchAllReactions(): ReturnType<ReactionsAPI['fetch']>;
2224
+ /**
2225
+ * Get a URL to this message (deep link).
2226
+ */
2227
+ get url(): string;
2228
+ /**
2229
+ * Return the raw message object.
2230
+ */
2231
+ toJSON(): Message;
2232
+ toString(): string;
2233
+ }
2234
+
2235
+ /**
2236
+ * A rich wrapper around a raw `Channel` with convenience methods.
2237
+ *
2238
+ * Returned by `client.fetchChannel()` and `client.fetchChannels()`.
2239
+ *
2240
+ * @example
2241
+ * const channel = await client.fetchChannel('channel-id')
2242
+ *
1767
2243
  * await channel.send('Hello from the bot!')
1768
2244
  * await channel.edit({ topic: 'New topic' })
1769
2245
  * const messages = await channel.fetchMessages({ limit: 20 })
@@ -1787,7 +2263,9 @@ declare class NovaChannel {
1787
2263
  readonly createdAt: Date;
1788
2264
  private readonly _channels;
1789
2265
  private readonly _messages;
1790
- constructor(raw: Channel, channels: ChannelsAPI, messages: MessagesAPI);
2266
+ private readonly _webhooks;
2267
+ private readonly _forum;
2268
+ constructor(raw: Channel, channels: ChannelsAPI, messages: MessagesAPI, webhooks?: WebhooksAPI, forum?: ForumAPI);
1791
2269
  /** `true` for text channels. */
1792
2270
  isText(): boolean;
1793
2271
  /** `true` for voice channels. */
@@ -1850,6 +2328,51 @@ declare class NovaChannel {
1850
2328
  delete(): Promise<{
1851
2329
  ok: true;
1852
2330
  }>;
2331
+ /**
2332
+ * Bulk-delete multiple messages in this channel (max 100 at once).
2333
+ * Requires the `messages.manage` scope.
2334
+ *
2335
+ * @example
2336
+ * const ids = messages.map(m => m.id)
2337
+ * const result = await channel.bulkDelete(ids)
2338
+ * console.log(`Deleted ${result.deleted} messages`)
2339
+ */
2340
+ bulkDelete(messageIds: string[]): Promise<BulkDeleteResult>;
2341
+ /**
2342
+ * Create a webhook in this channel.
2343
+ * Requires the `webhooks.manage` scope.
2344
+ *
2345
+ * @example
2346
+ * const wh = await channel.createWebhook({ name: 'Notifications' })
2347
+ * console.log('Token:', wh.token)
2348
+ */
2349
+ createWebhook(options: WebhookCreateOptions): Promise<Webhook>;
2350
+ /**
2351
+ * Fetch all webhooks in this channel.
2352
+ * Requires the `webhooks.manage` scope.
2353
+ *
2354
+ * @example
2355
+ * const webhooks = await channel.fetchWebhooks()
2356
+ */
2357
+ fetchWebhooks(): Promise<Webhook[]>;
2358
+ /**
2359
+ * Create a new post in this FORUM channel.
2360
+ * Requires the `channels.write` scope.
2361
+ *
2362
+ * @example
2363
+ * const post = await channel.createForumPost({
2364
+ * title: 'Announcement',
2365
+ * content: 'Welcome everyone!',
2366
+ * })
2367
+ */
2368
+ createForumPost(options: CreateForumPostOptions): Promise<ForumPost>;
2369
+ /**
2370
+ * Fetch posts from this FORUM channel.
2371
+ *
2372
+ * @example
2373
+ * const posts = await channel.fetchForumPosts({ limit: 20 })
2374
+ */
2375
+ fetchForumPosts(options?: FetchForumPostsOptions): Promise<ForumPost[]>;
1853
2376
  /**
1854
2377
  * Returns the channel as a mention-style string: `#name`.
1855
2378
  */
@@ -1956,6 +2479,65 @@ declare class NovaMember {
1956
2479
  removeRole(roleId: string): Promise<{
1957
2480
  ok: true;
1958
2481
  }>;
2482
+ /**
2483
+ * Issue a warning to this member.
2484
+ * Requires the `members.moderate` scope.
2485
+ *
2486
+ * @example
2487
+ * await member.warn('Excessive spamming')
2488
+ */
2489
+ warn(reason: string): Promise<Warning>;
2490
+ /**
2491
+ * Fetch all warnings for this member in this server.
2492
+ * Requires the `members.moderate` scope.
2493
+ *
2494
+ * @example
2495
+ * const warnings = await member.fetchWarnings()
2496
+ * console.log(`${warnings.length} warnings on record`)
2497
+ */
2498
+ fetchWarnings(): Promise<Warning[]>;
2499
+ /**
2500
+ * Get this member's current XP and level.
2501
+ * Requires the `members.read` scope.
2502
+ *
2503
+ * @example
2504
+ * const xp = await member.getXP()
2505
+ * console.log(`Level ${xp.level} — ${xp.xp} XP`)
2506
+ */
2507
+ getXP(): Promise<MemberXPData>;
2508
+ /**
2509
+ * Set this member's XP to a specific value.
2510
+ * Requires the `members.manage` scope.
2511
+ *
2512
+ * @example
2513
+ * await member.setXP(500)
2514
+ */
2515
+ setXP(xp: number): Promise<MemberXPData>;
2516
+ /**
2517
+ * Add (or subtract) XP to this member's current total.
2518
+ * Requires the `members.manage` scope.
2519
+ *
2520
+ * @example
2521
+ * await member.addXP(100) // reward 100 XP
2522
+ * await member.addXP(-50) // deduct 50 XP
2523
+ */
2524
+ addXP(amount: number): Promise<MemberXPData>;
2525
+ /**
2526
+ * Delete all warnings on record for this member in this server.
2527
+ * Requires the `members.moderate` scope.
2528
+ *
2529
+ * @example
2530
+ * await member.clearWarnings()
2531
+ */
2532
+ clearWarnings(): Promise<number>;
2533
+ /**
2534
+ * Reset this member's XP back to zero.
2535
+ * Requires the `members.manage` scope.
2536
+ *
2537
+ * @example
2538
+ * await member.resetXP()
2539
+ */
2540
+ resetXP(): Promise<MemberXPData>;
1959
2541
  /**
1960
2542
  * Returns a mention-style string: `@displayName`.
1961
2543
  */
@@ -2064,7 +2646,11 @@ declare class NovaServerWrapper {
2064
2646
  private readonly _invites;
2065
2647
  private readonly _roles;
2066
2648
  private readonly _messages;
2067
- constructor(raw: NovaServer, servers: ServersAPI, channels: ChannelsAPI, members: MembersAPI, invites: InvitesAPI, roles: RolesAPI, messages: MessagesAPI);
2649
+ private readonly _categories;
2650
+ private readonly _events;
2651
+ private readonly _automod;
2652
+ private readonly _auditLog;
2653
+ constructor(raw: NovaServer, servers: ServersAPI, channels: ChannelsAPI, members: MembersAPI, invites: InvitesAPI, roles: RolesAPI, messages: MessagesAPI, categories?: CategoriesAPI, events?: EventsAPI, automod?: AutoModAPI, auditLog?: AuditLogAPI);
2068
2654
  /**
2069
2655
  * Update this server's name, description, or icon.
2070
2656
  * Requires the `server.manage` scope.
@@ -2126,12 +2712,21 @@ declare class NovaServerWrapper {
2126
2712
  */
2127
2713
  fetchBans(): Promise<BanEntry[]>;
2128
2714
  /**
2129
- * Fetch all custom roles in this server.
2715
+ * List all custom roles in this server, sorted by position.
2130
2716
  *
2131
2717
  * @example
2132
2718
  * const roles = await server.fetchRoles()
2719
+ * const admins = roles.filter(r => r.name === 'Admin')
2133
2720
  */
2134
2721
  fetchRoles(): Promise<Role[]>;
2722
+ /**
2723
+ * Create a new custom role in this server.
2724
+ * Requires the `roles.manage` scope.
2725
+ *
2726
+ * @example
2727
+ * const role = await server.createRole({ name: 'Supporter', color: '#00d4ff', hoist: true })
2728
+ */
2729
+ createRole(options: RoleCreateOptions): Promise<Role>;
2135
2730
  /**
2136
2731
  * Fetch all active invites for this server.
2137
2732
  *
@@ -2154,6 +2749,101 @@ declare class NovaServerWrapper {
2154
2749
  * await server.send('channel-id', 'Hello, server!')
2155
2750
  */
2156
2751
  send(channelId: string, content: string): ReturnType<MessagesAPI['send']>;
2752
+ /**
2753
+ * Fetch all channel categories in this server.
2754
+ *
2755
+ * @example
2756
+ * const cats = await server.fetchCategories()
2757
+ * const general = cats.find(c => c.name === 'General')
2758
+ */
2759
+ fetchCategories(): Promise<ChannelCategory[]>;
2760
+ /**
2761
+ * Create a new channel category in this server.
2762
+ * Requires the `channels.manage` scope.
2763
+ *
2764
+ * @example
2765
+ * const cat = await server.createCategory({ name: 'Bot Channels' })
2766
+ */
2767
+ createCategory(options: CreateCategoryOptions): Promise<ChannelCategory>;
2768
+ /**
2769
+ * Fetch server events. Pass `{ upcoming: true }` to only return future events.
2770
+ *
2771
+ * @example
2772
+ * const events = await server.fetchEvents({ upcoming: true })
2773
+ */
2774
+ fetchEvents(options?: FetchEventsOptions): Promise<ServerEvent[]>;
2775
+ /**
2776
+ * Create a new server event.
2777
+ * Requires the `server.manage` scope.
2778
+ *
2779
+ * @example
2780
+ * const event = await server.createEvent({
2781
+ * title: 'Game Night',
2782
+ * startAt: new Date('2025-09-01T20:00:00Z').toISOString(),
2783
+ * })
2784
+ */
2785
+ createEvent(options: CreateEventOptions): Promise<ServerEvent>;
2786
+ /**
2787
+ * Fetch server statistics (member count, message count, etc.).
2788
+ *
2789
+ * @example
2790
+ * const stats = await server.fetchStats()
2791
+ * console.log(`Online: ${stats.onlineCount} / ${stats.memberCount}`)
2792
+ */
2793
+ fetchStats(): Promise<ServerStats>;
2794
+ /**
2795
+ * Fetch the audit log for this server.
2796
+ * Requires the `audit-log.read` scope.
2797
+ *
2798
+ * @example
2799
+ * const log = await server.fetchAuditLog({ action: 'member.banned', limit: 20 })
2800
+ */
2801
+ fetchAuditLog(options?: FetchAuditLogsOptions): Promise<AuditLogEntry[]>;
2802
+ /**
2803
+ * Issue a warning to a member in this server.
2804
+ * Requires the `members.moderate` scope.
2805
+ *
2806
+ * @example
2807
+ * await server.warn('user-id', 'Insulting other members')
2808
+ */
2809
+ warn(userId: string, reason: string): Promise<Warning>;
2810
+ /**
2811
+ * Fetch warnings for this server, optionally filtered by user.
2812
+ * Requires the `members.moderate` scope.
2813
+ *
2814
+ * @example
2815
+ * const all = await server.fetchWarnings()
2816
+ * const userWarns = await server.fetchWarnings({ userId: 'user-id' })
2817
+ */
2818
+ fetchWarnings(options?: {
2819
+ userId?: string;
2820
+ }): Promise<Warning[]>;
2821
+ /**
2822
+ * Fetch the XP leaderboard for this server.
2823
+ * Requires the `members.read` scope.
2824
+ *
2825
+ * @example
2826
+ * const top = await server.fetchLeaderboard(10)
2827
+ * top.forEach(e => console.log(`#${e.rank} ${e.user.displayName} — ${e.xp} XP`))
2828
+ */
2829
+ fetchLeaderboard(limit?: number): Promise<LeaderboardEntry[]>;
2830
+ /**
2831
+ * Fetch all AutoMod rules for this server.
2832
+ * Requires the `server.manage` scope.
2833
+ *
2834
+ * @example
2835
+ * const rules = await server.fetchAutoModRules()
2836
+ * const active = rules.filter(r => r.enabled)
2837
+ */
2838
+ fetchAutoModRules(): Promise<AutoModRule[]>;
2839
+ /**
2840
+ * Create a new AutoMod rule for this server.
2841
+ * Requires the `server.manage` scope.
2842
+ *
2843
+ * @example
2844
+ * await server.createAutoModRule({ type: 'BLOCKED_WORD', value: 'badword' })
2845
+ */
2846
+ createAutoModRule(options: CreateAutoModRuleOptions): Promise<AutoModRule>;
2157
2847
  toJSON(): NovaServer;
2158
2848
  }
2159
2849
 
@@ -2262,107 +2952,358 @@ declare class NovaWebhook {
2262
2952
  toJSON(): Webhook;
2263
2953
  }
2264
2954
 
2265
- interface NovaClientEvents {
2266
- /** Fired when the bot connects and is identified by the gateway. */
2267
- ready: (bot: BotApplication) => void;
2268
- /** Fired for every raw `bot:event` from the gateway. */
2269
- event: (event: BotEvent) => void;
2955
+ /**
2956
+ * A rich wrapper around a raw `ForumPost` object that provides
2957
+ * convenient helper methods for common operations.
2958
+ *
2959
+ * @example
2960
+ * const posts = await client.fetchForumPosts('channel-id')
2961
+ * for (const post of posts) {
2962
+ * if (post.closed) continue
2963
+ * await post.close()
2964
+ * }
2965
+ */
2966
+ declare class NovaForumPost implements ForumPost {
2967
+ private readonly raw;
2968
+ private readonly forum;
2969
+ readonly id: string;
2970
+ readonly channelId: string;
2971
+ readonly authorId: string;
2972
+ readonly title: string;
2973
+ readonly body: string;
2974
+ readonly tags: string[];
2975
+ readonly pinned: boolean;
2976
+ readonly closed: boolean;
2977
+ readonly upvoteCount: number;
2978
+ readonly replyCount: number;
2979
+ readonly author: ForumPost['author'];
2980
+ readonly createdAt: string;
2981
+ readonly updatedAt: string;
2982
+ constructor(raw: ForumPost, forum: ForumAPI);
2270
2983
  /**
2271
- * Fired when an interaction is received (slash command, button click, etc.).
2272
- * Use `client.command()`, `client.button()`, `client.selectMenu()`, or
2273
- * `client.autocomplete()` for convenient routing instead of handling everything here.
2984
+ * Edit this forum post.
2985
+ *
2986
+ * @example
2987
+ * await post.edit({ title: 'Updated title' })
2274
2988
  */
2275
- interactionCreate: (interaction: NovaInteraction) => void;
2276
- /** Fired when the WebSocket connection drops. */
2277
- disconnect: (reason: string) => void;
2278
- /** Fired on gateway / API errors. */
2279
- error: (err: Error | {
2280
- code: number;
2281
- message: string;
2282
- }) => void;
2283
- /** A new message was sent in a channel the bot can see. */
2284
- messageCreate: (message: NovaMessage) => void;
2285
- /** A message was edited. Returns the updated message. */
2286
- messageUpdate: (message: NovaMessage) => void;
2287
- /** A message was deleted. Returns partial data. */
2288
- messageDelete: (data: {
2289
- id: string;
2290
- channelId: string;
2291
- }) => void;
2292
- /** A reaction was added to a message. */
2293
- reactionAdd: (data: {
2294
- messageId: string;
2295
- channelId: string;
2296
- userId: string;
2297
- emoji: string;
2298
- }) => void;
2299
- /** A reaction was removed from a message. */
2300
- reactionRemove: (data: {
2301
- messageId: string;
2302
- channelId: string;
2303
- userId: string;
2304
- emoji: string;
2305
- }) => void;
2306
- /** A member joined a server the bot is in. */
2307
- memberAdd: (data: {
2308
- serverId: string;
2309
- userId: string;
2310
- username: string;
2311
- }) => void;
2312
- /** A member left a server the bot is in. */
2313
- memberRemove: (data: {
2314
- serverId: string;
2315
- userId: string;
2316
- }) => void;
2317
- /** A user started typing in a channel. */
2318
- typingStart: (data: {
2319
- channelId: string;
2320
- userId: string;
2321
- }) => void;
2322
- /** A message was pinned. */
2323
- messagePinned: (data: {
2324
- messageId: string;
2325
- channelId: string;
2326
- pinnedBy: string;
2327
- }) => void;
2328
- /** A channel was created in a server. */
2329
- channelCreate: (channel: Channel) => void;
2330
- /** A channel was updated. */
2331
- channelUpdate: (channel: Channel) => void;
2332
- /** A channel was deleted. */
2333
- channelDelete: (data: {
2334
- id: string;
2335
- serverId: string;
2336
- }) => void;
2337
- /** A role was created in a server. */
2338
- roleCreate: (role: Role) => void;
2339
- /** A role was updated. */
2340
- roleUpdate: (role: Role) => void;
2341
- /** A role was deleted. */
2342
- roleDelete: (data: {
2343
- id: string;
2344
- serverId: string;
2345
- }) => void;
2346
- /** A user joined a voice channel. */
2347
- voiceJoin: (data: {
2348
- userId: string;
2349
- channelId: string;
2350
- serverId: string;
2351
- }) => void;
2352
- /** A user left a voice channel. */
2353
- voiceLeave: (data: {
2354
- userId: string;
2355
- channelId: string;
2356
- serverId: string;
2357
- }) => void;
2358
- /** A member was banned from a server. */
2359
- memberBanned: (data: {
2360
- userId: string;
2361
- serverId: string;
2362
- moderatorId: string | null;
2363
- reason: string | null;
2364
- }) => void;
2365
- /** A member was unbanned. */
2989
+ edit(options: EditForumPostOptions): Promise<NovaForumPost>;
2990
+ /**
2991
+ * Close the forum post (no new replies).
2992
+ *
2993
+ * @example
2994
+ * await post.close()
2995
+ */
2996
+ close(): Promise<NovaForumPost>;
2997
+ /**
2998
+ * Re-open a closed forum post.
2999
+ *
3000
+ * @example
3001
+ * await post.open()
3002
+ */
3003
+ open(): Promise<NovaForumPost>;
3004
+ /**
3005
+ * Pin this forum post in the channel.
3006
+ *
3007
+ * @example
3008
+ * await post.pin()
3009
+ */
3010
+ pin(): Promise<NovaForumPost>;
3011
+ /**
3012
+ * Unpin this forum post.
3013
+ *
3014
+ * @example
3015
+ * await post.unpin()
3016
+ */
3017
+ unpin(): Promise<NovaForumPost>;
3018
+ /**
3019
+ * Delete this forum post.
3020
+ *
3021
+ * @example
3022
+ * await post.delete()
3023
+ */
3024
+ delete(): Promise<void>;
3025
+ /** Whether this post was created by the currently connected bot. */
3026
+ get isOwnPost(): boolean;
3027
+ /** Returns `true` if the post has been closed. */
3028
+ get isClosed(): boolean;
3029
+ /** Returns `true` if the post is pinned. */
3030
+ get isPinned(): boolean;
3031
+ toJSON(): ForumPost;
3032
+ }
3033
+
3034
+ /**
3035
+ * A rich wrapper around a raw `ServerEvent` object.
3036
+ *
3037
+ * @example
3038
+ * const events = await client.fetchEvents('server-id', { upcoming: true })
3039
+ * for (const event of events) {
3040
+ * console.log(`${event.title} starts at ${event.startAt}`)
3041
+ * }
3042
+ */
3043
+ declare class NovaServerEvent implements ServerEvent {
3044
+ private readonly raw;
3045
+ private readonly events;
3046
+ readonly id: string;
3047
+ readonly serverId: string;
3048
+ readonly channelId: string | null;
3049
+ readonly createdById: string;
3050
+ readonly title: string;
3051
+ readonly description: string | null;
3052
+ readonly imageUrl: string | null;
3053
+ readonly location: string | null;
3054
+ readonly startAt: string;
3055
+ readonly endAt: string | null;
3056
+ readonly attendeeCount: number | undefined;
3057
+ readonly createdAt: string;
3058
+ constructor(raw: ServerEvent, events: EventsAPI);
3059
+ /**
3060
+ * Edit this event.
3061
+ *
3062
+ * @example
3063
+ * await event.edit({ title: 'New Title' })
3064
+ */
3065
+ edit(options: EditEventOptions): Promise<NovaServerEvent>;
3066
+ /**
3067
+ * Fetch full event details including the attendee list.
3068
+ *
3069
+ * @example
3070
+ * const full = await event.fetchAttendees()
3071
+ * console.log(`${full.attendees.length} attendees`)
3072
+ */
3073
+ fetchAttendees(): Promise<{
3074
+ event: NovaServerEvent;
3075
+ attendees: ServerEventAttendee[];
3076
+ }>;
3077
+ /**
3078
+ * Delete this event.
3079
+ *
3080
+ * @example
3081
+ * await event.delete()
3082
+ */
3083
+ delete(): Promise<void>;
3084
+ /**
3085
+ * Whether the event has already started.
3086
+ */
3087
+ get hasStarted(): boolean;
3088
+ /**
3089
+ * Whether the event has ended.
3090
+ * Returns `false` if no `endAt` is set.
3091
+ */
3092
+ get hasEnded(): boolean;
3093
+ /**
3094
+ * Whether this is an upcoming event that has not yet started.
3095
+ */
3096
+ get isUpcoming(): boolean;
3097
+ toJSON(): ServerEvent;
3098
+ }
3099
+
3100
+ /**
3101
+ * A rich wrapper around a raw `BanEntry` that adds an `unban()` convenience method.
3102
+ *
3103
+ * Returned by `client.fetchBans()`.
3104
+ *
3105
+ * @example
3106
+ * const bans = await client.fetchBans('server-id')
3107
+ * for (const ban of bans) {
3108
+ * if (ban.reason === 'testing') {
3109
+ * await ban.unban()
3110
+ * console.log(`Unbanned ${ban.displayName}`)
3111
+ * }
3112
+ * }
3113
+ */
3114
+ declare class NovaBan implements BanEntry {
3115
+ /** The banned user's ID. */
3116
+ readonly userId: string;
3117
+ /** The banned user's username. */
3118
+ readonly username: string;
3119
+ /** The banned user's display name. */
3120
+ readonly displayName: string;
3121
+ /** The banned user's avatar URL, or `null`. */
3122
+ readonly avatar: string | null;
3123
+ /** The reason for the ban, or `null`. */
3124
+ readonly reason: string | null;
3125
+ /** ISO timestamp of when the ban was issued. */
3126
+ readonly bannedAt: string;
3127
+ /** ID of the moderator who issued the ban, or `null`. */
3128
+ readonly moderatorId: string | null;
3129
+ /** ID of the server this ban belongs to. */
3130
+ readonly serverId: string;
3131
+ private readonly _members;
3132
+ constructor(raw: BanEntry, serverId: string, members: MembersAPI);
3133
+ /**
3134
+ * Revoke this ban, allowing the user to rejoin the server.
3135
+ * Requires the `members.ban` scope.
3136
+ *
3137
+ * @example
3138
+ * await ban.unban()
3139
+ */
3140
+ unban(): Promise<{
3141
+ ok: true;
3142
+ }>;
3143
+ /**
3144
+ * When the ban was issued as a `Date` object.
3145
+ */
3146
+ get bannedAtDate(): Date;
3147
+ /**
3148
+ * Human-readable label: `"displayName (username)"`.
3149
+ */
3150
+ get label(): string;
3151
+ toJSON(): BanEntry;
3152
+ }
3153
+
3154
+ /**
3155
+ * A rich wrapper around a raw `Warning` that adds a `delete()` convenience method.
3156
+ *
3157
+ * Returned by `client.fetchMemberWarnings()` and `member.fetchWarnings()`.
3158
+ *
3159
+ * @example
3160
+ * const warnings = await member.fetchWarnings()
3161
+ * for (const warning of warnings) {
3162
+ * console.log(`[${warning.issuedAt.toLocaleDateString()}] ${warning.reason}`)
3163
+ * }
3164
+ *
3165
+ * // Remove the oldest warning if there are too many
3166
+ * if (warnings.length > 5) {
3167
+ * await warnings[0].delete()
3168
+ * }
3169
+ */
3170
+ declare class NovaWarning implements Warning {
3171
+ /** Unique ID of this warning. */
3172
+ readonly id: string;
3173
+ /** ID of the server where the warning was issued. */
3174
+ readonly serverId: string;
3175
+ /** ID of the user who received the warning. */
3176
+ readonly userId: string;
3177
+ /** ID of the moderator who issued the warning. */
3178
+ readonly moderatorId: string;
3179
+ /** The reason text. */
3180
+ readonly reason: string;
3181
+ /** ISO timestamp of when the warning was issued. */
3182
+ readonly createdAt: string;
3183
+ private readonly _members;
3184
+ constructor(raw: Warning, members: MembersAPI);
3185
+ /**
3186
+ * Delete (expunge) this warning from the record.
3187
+ * Requires the `members.moderate` scope.
3188
+ *
3189
+ * @example
3190
+ * await warning.delete()
3191
+ */
3192
+ delete(): Promise<{
3193
+ ok: true;
3194
+ }>;
3195
+ /**
3196
+ * When the warning was issued as a `Date` object.
3197
+ */
3198
+ get issuedAt(): Date;
3199
+ /**
3200
+ * How long ago the warning was issued, in milliseconds.
3201
+ */
3202
+ get ageMs(): number;
3203
+ toJSON(): Warning;
3204
+ }
3205
+
3206
+ interface NovaClientEvents {
3207
+ /** Fired when the bot connects and is identified by the gateway. */
3208
+ ready: (bot: BotApplication) => void;
3209
+ /** Fired for every raw `bot:event` from the gateway. */
3210
+ event: (event: BotEvent) => void;
3211
+ /**
3212
+ * Fired when an interaction is received (slash command, button click, etc.).
3213
+ * Use `client.command()`, `client.button()`, `client.selectMenu()`, or
3214
+ * `client.autocomplete()` for convenient routing instead of handling everything here.
3215
+ */
3216
+ interactionCreate: (interaction: NovaInteraction) => void;
3217
+ /** Fired when the WebSocket connection drops. */
3218
+ disconnect: (reason: string) => void;
3219
+ /** Fired on gateway / API errors. */
3220
+ error: (err: Error | {
3221
+ code: number;
3222
+ message: string;
3223
+ }) => void;
3224
+ /** A new message was sent in a channel the bot can see. */
3225
+ messageCreate: (message: NovaMessage) => void;
3226
+ /** A message was edited. Returns the updated message. */
3227
+ messageUpdate: (message: NovaMessage) => void;
3228
+ /** A message was deleted. Returns partial data. */
3229
+ messageDelete: (data: {
3230
+ id: string;
3231
+ channelId: string;
3232
+ }) => void;
3233
+ /** A reaction was added to a message. */
3234
+ reactionAdd: (data: {
3235
+ messageId: string;
3236
+ channelId: string;
3237
+ userId: string;
3238
+ emoji: string;
3239
+ }) => void;
3240
+ /** A reaction was removed from a message. */
3241
+ reactionRemove: (data: {
3242
+ messageId: string;
3243
+ channelId: string;
3244
+ userId: string;
3245
+ emoji: string;
3246
+ }) => void;
3247
+ /** A member joined a server the bot is in. */
3248
+ memberAdd: (data: {
3249
+ serverId: string;
3250
+ userId: string;
3251
+ username: string;
3252
+ }) => void;
3253
+ /** A member left a server the bot is in. */
3254
+ memberRemove: (data: {
3255
+ serverId: string;
3256
+ userId: string;
3257
+ }) => void;
3258
+ /** A user started typing in a channel. */
3259
+ typingStart: (data: {
3260
+ channelId: string;
3261
+ userId: string;
3262
+ }) => void;
3263
+ /** A message was pinned. */
3264
+ messagePinned: (data: {
3265
+ messageId: string;
3266
+ channelId: string;
3267
+ pinnedBy: string;
3268
+ }) => void;
3269
+ /** A channel was created in a server. */
3270
+ channelCreate: (channel: Channel) => void;
3271
+ /** A channel was updated. */
3272
+ channelUpdate: (channel: Channel) => void;
3273
+ /** A channel was deleted. */
3274
+ channelDelete: (data: {
3275
+ id: string;
3276
+ serverId: string;
3277
+ }) => void;
3278
+ /** A role was created in a server. */
3279
+ roleCreate: (role: Role) => void;
3280
+ /** A role was updated. */
3281
+ roleUpdate: (role: Role) => void;
3282
+ /** A role was deleted. */
3283
+ roleDelete: (data: {
3284
+ id: string;
3285
+ serverId: string;
3286
+ }) => void;
3287
+ /** A user joined a voice channel. */
3288
+ voiceJoin: (data: {
3289
+ userId: string;
3290
+ channelId: string;
3291
+ serverId: string;
3292
+ }) => void;
3293
+ /** A user left a voice channel. */
3294
+ voiceLeave: (data: {
3295
+ userId: string;
3296
+ channelId: string;
3297
+ serverId: string;
3298
+ }) => void;
3299
+ /** A member was banned from a server. */
3300
+ memberBanned: (data: {
3301
+ userId: string;
3302
+ serverId: string;
3303
+ moderatorId: string | null;
3304
+ reason: string | null;
3305
+ }) => void;
3306
+ /** A member was unbanned. */
2366
3307
  memberUnbanned: (data: {
2367
3308
  userId: string;
2368
3309
  serverId: string;
@@ -2397,6 +3338,38 @@ interface NovaClientEvents {
2397
3338
  code: string;
2398
3339
  serverId: string;
2399
3340
  }) => void;
3341
+ /** A forum post was created in a FORUM channel. */
3342
+ forumPostCreate: (post: NovaForumPost) => void;
3343
+ /** A server event was created. */
3344
+ eventCreate: (event: NovaServerEvent) => void;
3345
+ /** A server event was updated. */
3346
+ eventUpdate: (event: ServerEvent) => void;
3347
+ /** A server event was deleted. */
3348
+ eventDelete: (data: {
3349
+ id: string;
3350
+ serverId: string;
3351
+ }) => void;
3352
+ /** A channel category was created. */
3353
+ categoryCreate: (category: ChannelCategory) => void;
3354
+ /** A channel category was updated. */
3355
+ categoryUpdate: (category: ChannelCategory) => void;
3356
+ /** A channel category was deleted. */
3357
+ categoryDelete: (data: {
3358
+ id: string;
3359
+ serverId: string;
3360
+ }) => void;
3361
+ /** A member received a warning. */
3362
+ memberWarned: (data: {
3363
+ serverId: string;
3364
+ userId: string;
3365
+ warning: Warning;
3366
+ }) => void;
3367
+ /** Multiple messages were bulk-deleted. */
3368
+ messagesBulkDelete: (data: {
3369
+ channelId: string;
3370
+ messageIds: string[];
3371
+ count: number;
3372
+ }) => void;
2400
3373
  }
2401
3374
  /**
2402
3375
  * The main Nova bot client.
@@ -2445,6 +3418,16 @@ declare class NovaClient extends EventEmitter {
2445
3418
  readonly webhooks: WebhooksAPI;
2446
3419
  /** Fetch server audit logs. */
2447
3420
  readonly auditLog: AuditLogAPI;
3421
+ /** Create and manage forum posts in FORUM channels. */
3422
+ readonly forum: ForumAPI;
3423
+ /** Create and manage server events. */
3424
+ readonly events: EventsAPI;
3425
+ /** Manage channel categories. */
3426
+ readonly categories: CategoriesAPI;
3427
+ /** Manage automod rules (blocked words / links). */
3428
+ readonly automod: AutoModAPI;
3429
+ /** Fetch user profiles. */
3430
+ readonly users: UsersAPI;
2448
3431
  private socket;
2449
3432
  private readonly http;
2450
3433
  private readonly options;
@@ -2580,6 +3563,30 @@ declare class NovaClient extends EventEmitter {
2580
3563
  * await member.dm('Welcome!')
2581
3564
  */
2582
3565
  fetchMember(serverId: string, userId: string): Promise<NovaMember>;
3566
+ /**
3567
+ * Fetch all bans in a server and return them as `NovaBan` wrappers.
3568
+ * Each `NovaBan` has an `.unban()` convenience method.
3569
+ * Requires the `members.ban` scope.
3570
+ *
3571
+ * @example
3572
+ * const bans = await client.fetchBans('server-id')
3573
+ * for (const ban of bans) {
3574
+ * if (ban.reason === 'test') await ban.unban()
3575
+ * }
3576
+ */
3577
+ fetchBans(serverId: string): Promise<NovaBan[]>;
3578
+ /**
3579
+ * Fetch warnings for a member (or all members) in a server and return them
3580
+ * as `NovaWarning` wrappers. Each wrapper has a `.delete()` convenience method.
3581
+ * Requires the `members.moderate` scope.
3582
+ *
3583
+ * @example
3584
+ * const warnings = await client.fetchMemberWarnings('server-id', 'user-id')
3585
+ * for (const w of warnings) {
3586
+ * if (w.ageMs > 30 * 24 * 60 * 60_000) await w.delete() // older than 30 days
3587
+ * }
3588
+ */
3589
+ fetchMemberWarnings(serverId: string, userId?: string): Promise<NovaWarning[]>;
2583
3590
  /**
2584
3591
  * Fetch a single server by ID and return it as a `NovaServerWrapper`.
2585
3592
  *
@@ -2636,39 +3643,162 @@ declare class NovaClient extends EventEmitter {
2636
3643
  */
2637
3644
  fetchWebhook(webhookId: string): Promise<NovaWebhook>;
2638
3645
  /**
2639
- * Wait for a specific event to be emitted, optionally filtered.
2640
- * Rejects after `timeoutMs` (default 30 s) if the condition never fires.
3646
+ * Fetch forum posts from a FORUM channel and return them as `NovaForumPost` wrappers.
2641
3647
  *
2642
3648
  * @example
2643
- * // Wait for any message in a specific channel
2644
- * const msg = await client.waitFor('messageCreate', m => m.channelId === channelId)
3649
+ * const posts = await client.fetchForumPosts('channel-id', { limit: 20 })
3650
+ * const open = posts.filter(p => !p.isClosed)
3651
+ */
3652
+ fetchForumPosts(channelId: string, options?: FetchForumPostsOptions): Promise<NovaForumPost[]>;
3653
+ /**
3654
+ * Fetch server events and return them as `NovaServerEvent` wrappers.
2645
3655
  *
2646
- * // Wait for a button click with a timeout
2647
- * const i = await client.waitFor('interactionCreate', i => i.isButton(), 60_000)
3656
+ * @example
3657
+ * const upcoming = await client.fetchEvents('server-id', { upcoming: true })
3658
+ * for (const event of upcoming) console.log(event.title)
2648
3659
  */
2649
- waitFor<K extends keyof NovaClientEvents>(event: K, filter?: (...args: Parameters<NovaClientEvents[K]>) => boolean, timeoutMs?: number): Promise<Parameters<NovaClientEvents[K]>[0]>;
3660
+ fetchEvents(serverId: string, options?: FetchEventsOptions): Promise<NovaServerEvent[]>;
2650
3661
  /**
2651
- * Disconnect from the gateway and clean up.
3662
+ * Fetch a single server event by ID and return it as a `NovaServerEvent` wrapper.
3663
+ *
3664
+ * @example
3665
+ * const event = await client.fetchEvent('event-id')
3666
+ * if (event.isUpcoming) await event.edit({ title: 'Updated!' })
2652
3667
  */
2653
- disconnect(): void;
3668
+ fetchEvent(eventId: string): Promise<NovaServerEvent>;
2654
3669
  /**
2655
- * Send a message via the WebSocket gateway (lower latency than HTTP).
2656
- * Requires the `messages.write` scope.
3670
+ * Fetch a user's public profile.
2657
3671
  *
2658
3672
  * @example
2659
- * client.wsSend('channel-id', 'Hello from the gateway!')
3673
+ * const user = await client.fetchUserProfile('user-id')
3674
+ * console.log(user.bio)
2660
3675
  */
2661
- wsSend(channelId: string, content: string): void;
3676
+ fetchUserProfile(userId: string): Promise<UserProfile>;
2662
3677
  /**
2663
- * Start a typing indicator via WebSocket.
3678
+ * Fetch the XP leaderboard for a server.
3679
+ *
3680
+ * @example
3681
+ * const top = await client.fetchLeaderboard('server-id', 10)
3682
+ * top.forEach(entry => console.log(`#${entry.rank} ${entry.user.username} — ${entry.xp} XP`))
2664
3683
  */
2665
- wsTypingStart(channelId: string): void;
3684
+ fetchLeaderboard(serverId: string, limit?: number): Promise<LeaderboardEntry[]>;
2666
3685
  /**
2667
- * Stop a typing indicator via WebSocket.
3686
+ * Fetch warnings in a server, optionally filtered by user.
3687
+ *
3688
+ * @example
3689
+ * const warnings = await client.fetchWarnings('server-id', { userId: 'user-id' })
2668
3690
  */
2669
- wsTypingStop(channelId: string): void;
2670
- on<K extends keyof NovaClientEvents>(event: K, listener: NovaClientEvents[K]): this;
2671
- on(event: string | symbol, listener: (...args: unknown[]) => void): this;
3691
+ fetchWarnings(serverId: string, options?: FetchWarningsOptions): Promise<Warning[]>;
3692
+ /**
3693
+ * Fetch all automod rules for a server.
3694
+ *
3695
+ * @example
3696
+ * const rules = await client.fetchAutoModRules('server-id')
3697
+ */
3698
+ fetchAutoModRules(serverId: string): Promise<AutoModRule[]>;
3699
+ /**
3700
+ * Fetch all channel categories for a server.
3701
+ *
3702
+ * @example
3703
+ * const cats = await client.fetchCategories('server-id')
3704
+ */
3705
+ fetchCategories(serverId: string): Promise<ChannelCategory[]>;
3706
+ /**
3707
+ * Fetch soundboard clips for a server.
3708
+ *
3709
+ * @example
3710
+ * const clips = await client.fetchSoundboard('server-id')
3711
+ */
3712
+ fetchSoundboard(serverId: string): Promise<SoundboardClip[]>;
3713
+ /**
3714
+ * Fetch statistics for a server (member count, message count, etc.).
3715
+ *
3716
+ * @example
3717
+ * const stats = await client.fetchServerStats('server-id')
3718
+ * console.log(`${stats.onlineCount}/${stats.memberCount} online`)
3719
+ */
3720
+ fetchServerStats(serverId: string): Promise<ServerStats>;
3721
+ /**
3722
+ * Bulk delete up to 100 messages in a channel.
3723
+ * Requires the `messages.manage` scope.
3724
+ *
3725
+ * @example
3726
+ * const result = await client.bulkDelete('channel-id', messageIds)
3727
+ * console.log(`Deleted ${result.deleted} messages`)
3728
+ */
3729
+ bulkDelete(channelId: string, messageIds: string[]): Promise<BulkDeleteResult>;
3730
+ /**
3731
+ * Wait for a specific event to be emitted, optionally filtered.
3732
+ * Rejects after `timeoutMs` (default 30 s) if the condition never fires.
3733
+ *
3734
+ * @example
3735
+ * // Wait for any message in a specific channel
3736
+ * const msg = await client.waitFor('messageCreate', m => m.channelId === channelId)
3737
+ *
3738
+ * // Wait for a button click with a timeout
3739
+ * const i = await client.waitFor('interactionCreate', i => i.isButton(), 60_000)
3740
+ */
3741
+ waitFor<K extends keyof NovaClientEvents>(event: K, filter?: (...args: Parameters<NovaClientEvents[K]>) => boolean, timeoutMs?: number): Promise<Parameters<NovaClientEvents[K]>[0]>;
3742
+ /**
3743
+ * Wait for the next message matching an optional filter.
3744
+ * Short for `waitFor('messageCreate', filter, timeoutMs)`.
3745
+ *
3746
+ * @example
3747
+ * // Wait for any message in a specific channel
3748
+ * const msg = await client.waitForMessage(
3749
+ * m => m.channelId === channelId && !m.isFromBot(),
3750
+ * 30_000,
3751
+ * )
3752
+ * console.log(msg.content)
3753
+ */
3754
+ waitForMessage(filter?: (msg: NovaMessage) => boolean, timeoutMs?: number): Promise<NovaMessage>;
3755
+ /**
3756
+ * Wait for the next button-click interaction matching an optional filter.
3757
+ * Short for `waitFor('interactionCreate', i => i.isButton() && filter(i), timeoutMs)`.
3758
+ *
3759
+ * @example
3760
+ * // Wait for any button on a specific message
3761
+ * const click = await client.waitForButton(
3762
+ * i => i.triggerMsgId === message.id,
3763
+ * 60_000,
3764
+ * )
3765
+ * await click.reply('Button clicked!')
3766
+ */
3767
+ waitForButton(filter?: (i: NovaInteraction) => boolean, timeoutMs?: number): Promise<NovaInteraction>;
3768
+ /**
3769
+ * Wait for the next select-menu interaction matching an optional filter.
3770
+ * Short for `waitFor('interactionCreate', i => i.isSelectMenu() && filter(i), timeoutMs)`.
3771
+ *
3772
+ * @example
3773
+ * const pick = await client.waitForSelectMenu(
3774
+ * i => i.customId === 'colour_pick',
3775
+ * 60_000,
3776
+ * )
3777
+ * await pick.reply(`You picked: ${pick.values.join(', ')}`)
3778
+ */
3779
+ waitForSelectMenu(filter?: (i: NovaInteraction) => boolean, timeoutMs?: number): Promise<NovaInteraction>;
3780
+ /**
3781
+ * Disconnect from the gateway and clean up.
3782
+ */
3783
+ disconnect(): void;
3784
+ /**
3785
+ * Send a message via the WebSocket gateway (lower latency than HTTP).
3786
+ * Requires the `messages.write` scope.
3787
+ *
3788
+ * @example
3789
+ * client.wsSend('channel-id', 'Hello from the gateway!')
3790
+ */
3791
+ wsSend(channelId: string, content: string): void;
3792
+ /**
3793
+ * Start a typing indicator via WebSocket.
3794
+ */
3795
+ wsTypingStart(channelId: string): void;
3796
+ /**
3797
+ * Stop a typing indicator via WebSocket.
3798
+ */
3799
+ wsTypingStop(channelId: string): void;
3800
+ on<K extends keyof NovaClientEvents>(event: K, listener: NovaClientEvents[K]): this;
3801
+ on(event: string | symbol, listener: (...args: unknown[]) => void): this;
2672
3802
  once<K extends keyof NovaClientEvents>(event: K, listener: NovaClientEvents[K]): this;
2673
3803
  once(event: string | symbol, listener: (...args: unknown[]) => void): this;
2674
3804
  off<K extends keyof NovaClientEvents>(event: K, listener: NovaClientEvents[K]): this;
@@ -3653,4 +4783,1114 @@ declare function countdown(target: Date | number | string): {
3653
4783
  total: number;
3654
4784
  };
3655
4785
 
3656
- export { ActionRowBuilder, type Attachment, AuditLogAPI, type AuditLogAction, type AuditLogEntry, type BanEntry, type BotApplication, type BotEvent, type BotEventType, type BotModalDefinition, type BotModalField, type BotPermissionRecord, type BotStatus, type BotUser, ButtonBuilder, type ButtonStyle, type Channel, type ChannelType, ChannelsAPI, Collection, CommandsAPI, type ContextCommandDefinition, Cooldown, CooldownManager, type CreateChannelOptions, type DirectMessage, type EditChannelOptions, type EditMessageOptions, type Embed, EmbedBuilder, type EmbedField, type ExecuteWebhookOptions, type FetchAuditLogsOptions, type FetchChannelsOptions, type FetchMembersOptions, type FetchMessagesOptions, HttpClient, type Interaction, InteractionOptions, type InteractionType, InteractionsAPI, type Invite, type InviteCreateOptions, InvitesAPI, Logger, type Member, MembersAPI, type Message, MessageBuilder, type MessageComponent, MessagesAPI, ModalBuilder, NovaChannel, NovaClient, type NovaClientEvents, type NovaClientOptions, NovaInteraction, NovaInvite, NovaMember, NovaMessage, NovaRole, type NovaServer, NovaServerWrapper, NovaWebhook, Paginator, type PermissionKey, Permissions, PermissionsAPI, PermissionsBitfield, type PermissionsQueryOptions, type PermissionsResult, PollBuilder, type PollDefinition, type PollInteractionsOptions, type PollOption, type PrefixCommandDefinition, type Reaction, type ReactionDetail, ReactionsAPI, type RegisteredContextCommand, type RegisteredPrefixCommand, type RegisteredSlashCommand, type RespondInteractionOptions, type Role, type RoleCreateOptions, type RoleEditOptions, RolesAPI, SelectMenuBuilder, type SelectMenuOption, type SendMessageOptions, type ServerUpdateOptions, ServersAPI, type SingleMember, SlashCommandBuilder, type SlashCommandDefinition, type SlashCommandOption, SlashCommandOptionBuilder, TextInputBuilder, type TextInputStyle, type VoiceState, type Webhook, type WebhookCreateOptions, type WebhookEditOptions, WebhooksAPI, countdown, formatDuration, formatRelative, parseTimestamp, sleep, withTimeout };
4786
+ /**
4787
+ * A rich wrapper around a raw `ChannelCategory` with convenience methods.
4788
+ *
4789
+ * Returned by `client.fetchCategories()` and `server.fetchCategories()`.
4790
+ *
4791
+ * @example
4792
+ * const cats = await client.fetchCategories('server-id')
4793
+ * const general = cats.find(c => c.name === 'General')
4794
+ * if (general) await general.rename('Lounges')
4795
+ */
4796
+ declare class NovaCategory implements ChannelCategory {
4797
+ /** Unique category ID. */
4798
+ readonly id: string;
4799
+ /** Display name of the category. */
4800
+ readonly name: string;
4801
+ /** Sort position — lower numbers appear higher in the channel list. */
4802
+ readonly position: number;
4803
+ /** The server this category belongs to. */
4804
+ readonly serverId: string;
4805
+ /** When the category was created. */
4806
+ readonly createdAt: string;
4807
+ private readonly _categories;
4808
+ constructor(raw: ChannelCategory, categories: CategoriesAPI);
4809
+ /**
4810
+ * Edit this category's name and/or position.
4811
+ * Requires the `channels.manage` scope.
4812
+ *
4813
+ * @example
4814
+ * await cat.edit({ name: 'Lounges', position: 0 })
4815
+ */
4816
+ edit(options: EditCategoryOptions): Promise<NovaCategory>;
4817
+ /**
4818
+ * Rename this category.
4819
+ * Requires the `channels.manage` scope.
4820
+ *
4821
+ * @example
4822
+ * await cat.rename('Lounges')
4823
+ */
4824
+ rename(name: string): Promise<NovaCategory>;
4825
+ /**
4826
+ * Move this category to a specific position.
4827
+ * Requires the `channels.manage` scope.
4828
+ *
4829
+ * @example
4830
+ * await cat.setPosition(0)
4831
+ */
4832
+ setPosition(position: number): Promise<NovaCategory>;
4833
+ /**
4834
+ * Delete this category.
4835
+ * Requires the `channels.manage` scope.
4836
+ *
4837
+ * @example
4838
+ * await cat.delete()
4839
+ */
4840
+ delete(): Promise<void>;
4841
+ toJSON(): ChannelCategory;
4842
+ toString(): string;
4843
+ }
4844
+
4845
+ /**
4846
+ * A fluent builder for creating forum posts.
4847
+ *
4848
+ * @example
4849
+ * const post = new ForumPostBuilder()
4850
+ * .setTitle('Ideas Thread')
4851
+ * .setBody('Share your ideas for server improvements here!')
4852
+ * .addTag('ideas')
4853
+ * .addTag('discussion')
4854
+ * .build()
4855
+ *
4856
+ * await client.forum.create(channelId, post)
4857
+ */
4858
+ declare class ForumPostBuilder {
4859
+ private _title;
4860
+ private _body;
4861
+ private _tags;
4862
+ /**
4863
+ * Set the post title.
4864
+ */
4865
+ setTitle(title: string): this;
4866
+ /**
4867
+ * Set the post body / content.
4868
+ */
4869
+ setBody(body: string): this;
4870
+ /**
4871
+ * Add a tag to the post.
4872
+ * Tags are used to categorise forum posts.
4873
+ */
4874
+ addTag(tag: string): this;
4875
+ /**
4876
+ * Set all tags at once, replacing any previously added tags.
4877
+ */
4878
+ setTags(tags: string[]): this;
4879
+ /**
4880
+ * Validate and return the final `CreateForumPostOptions` object.
4881
+ *
4882
+ * @throws {Error} if title or body is missing.
4883
+ */
4884
+ build(): CreateForumPostOptions;
4885
+ }
4886
+
4887
+ /**
4888
+ * A fluent builder for creating server events.
4889
+ *
4890
+ * @example
4891
+ * const event = new EventBuilder()
4892
+ * .setTitle('Game Night')
4893
+ * .setDescription('Weekly gaming session — all welcome!')
4894
+ * .setStartAt(new Date('2025-08-01T20:00:00Z'))
4895
+ * .setEndAt(new Date('2025-08-01T23:00:00Z'))
4896
+ * .setLocation('Voice Channel: Gaming')
4897
+ * .build()
4898
+ *
4899
+ * await client.events.create(serverId, event)
4900
+ */
4901
+ declare class EventBuilder {
4902
+ private _title;
4903
+ private _description;
4904
+ private _imageUrl;
4905
+ private _location;
4906
+ private _startAt;
4907
+ private _endAt;
4908
+ private _channelId;
4909
+ /** Set the event title (required). */
4910
+ setTitle(title: string): this;
4911
+ /** Set the event description. */
4912
+ setDescription(description: string): this;
4913
+ /** Set a banner/cover image URL for the event. */
4914
+ setImage(url: string): this;
4915
+ /** Set the physical or virtual location for the event. */
4916
+ setLocation(location: string): this;
4917
+ /** Set when the event starts. Accepts a Date or ISO string. */
4918
+ setStartAt(date: Date | string): this;
4919
+ /** Set when the event ends. Accepts a Date or ISO string. */
4920
+ setEndAt(date: Date | string): this;
4921
+ /** Link the event to a specific channel. */
4922
+ setChannel(channelId: string): this;
4923
+ /**
4924
+ * Validate and return the final `CreateEventOptions` object.
4925
+ *
4926
+ * @throws {Error} if title or startAt is missing.
4927
+ */
4928
+ build(): CreateEventOptions;
4929
+ }
4930
+
4931
+ /**
4932
+ * Fluent builder for creating custom server roles.
4933
+ *
4934
+ * @example
4935
+ * const role = await client.roles.create(serverId,
4936
+ * new RoleBuilder()
4937
+ * .setName('Moderator')
4938
+ * .setColor('#ff6b6b')
4939
+ * .setHoist(true)
4940
+ * .allowSendMessages()
4941
+ * .build()
4942
+ * )
4943
+ */
4944
+ declare class RoleBuilder {
4945
+ private _name;
4946
+ private _color;
4947
+ private _hoist;
4948
+ private _permissions;
4949
+ /** Set the role's display name (required). */
4950
+ setName(name: string): this;
4951
+ /**
4952
+ * Set the role's accent colour.
4953
+ * @param color Hex string — e.g. `'#5865F2'` or `'5865F2'`
4954
+ */
4955
+ setColor(color: string): this;
4956
+ /**
4957
+ * Whether this role is shown separately in the member sidebar.
4958
+ * Default: `true` when called without arguments.
4959
+ */
4960
+ setHoist(hoist?: boolean): this;
4961
+ /** Set a specific permission key to true or false. */
4962
+ addPermission(key: string, value?: boolean): this;
4963
+ /** Replace all permission overrides at once. */
4964
+ setPermissions(permissions: Record<string, boolean>): this;
4965
+ /** Grant the `sendMessages` permission. */
4966
+ allowSendMessages(): this;
4967
+ /** Deny the `sendMessages` permission. */
4968
+ denySendMessages(): this;
4969
+ /** Grant the `addReactions` permission. */
4970
+ allowAddReactions(): this;
4971
+ /** Grant the `manageMessages` permission (delete/pin messages). */
4972
+ allowManageMessages(): this;
4973
+ /** Grant the `manageChannels` permission. */
4974
+ allowManageChannels(): this;
4975
+ /** Grant the `kickMembers` permission. */
4976
+ allowKickMembers(): this;
4977
+ /** Grant the `banMembers` permission. */
4978
+ allowBanMembers(): this;
4979
+ /** Grant the `manageServer` permission. */
4980
+ allowManageServer(): this;
4981
+ /** Grant the `manageRoles` permission. */
4982
+ allowManageRoles(): this;
4983
+ /**
4984
+ * Validate and build the `RoleCreateOptions` object.
4985
+ *
4986
+ * @throws if name is not set.
4987
+ */
4988
+ build(): RoleCreateOptions;
4989
+ }
4990
+
4991
+ /**
4992
+ * Fluent builder for creating server channels.
4993
+ *
4994
+ * @example
4995
+ * const channel = await client.channels.create(serverId,
4996
+ * new ChannelBuilder()
4997
+ * .setName('announcements')
4998
+ * .setType('ANNOUNCEMENT')
4999
+ * .setTopic('Official announcements only')
5000
+ * .build()
5001
+ * )
5002
+ */
5003
+ declare class ChannelBuilder {
5004
+ private _name;
5005
+ private _type;
5006
+ private _topic;
5007
+ private _position;
5008
+ private _categoryId;
5009
+ private _slowMode;
5010
+ private _isPrivate;
5011
+ /** Set the channel name (required). No # prefix needed. */
5012
+ setName(name: string): this;
5013
+ /**
5014
+ * Set the channel type.
5015
+ * @default 'TEXT'
5016
+ */
5017
+ setType(type: ChannelType): this;
5018
+ /** Create a TEXT channel. */
5019
+ asText(): this;
5020
+ /** Create a VOICE channel. */
5021
+ asVoice(): this;
5022
+ /** Create an ANNOUNCEMENT channel. */
5023
+ asAnnouncement(): this;
5024
+ /** Create a FORUM channel. */
5025
+ asForum(): this;
5026
+ /** Create a STAGE channel. */
5027
+ asStage(): this;
5028
+ /** Set the channel topic / description. */
5029
+ setTopic(topic: string): this;
5030
+ /** Set the channel's sort position. */
5031
+ setPosition(position: number): this;
5032
+ /** Place the channel inside an existing category by its ID. */
5033
+ setCategory(categoryId: string): this;
5034
+ /**
5035
+ * Set a slow-mode interval in seconds.
5036
+ * Members must wait this long between messages.
5037
+ * Pass `0` to disable.
5038
+ */
5039
+ setSlowMode(seconds: number): this;
5040
+ /**
5041
+ * Mark the channel as private.
5042
+ * Private channels are only visible to members with explicit access.
5043
+ */
5044
+ setPrivate(isPrivate?: boolean): this;
5045
+ /**
5046
+ * Validate and build the `CreateChannelOptions` object.
5047
+ *
5048
+ * @throws if name is not set.
5049
+ */
5050
+ build(): CreateChannelOptions;
5051
+ }
5052
+
5053
+ /**
5054
+ * Fluent builder for creating server invites.
5055
+ *
5056
+ * @example
5057
+ * // A one-time use invite expiring in 24 hours
5058
+ * const invite = await client.invites.create(serverId,
5059
+ * new InviteBuilder()
5060
+ * .setOneTimeUse()
5061
+ * .expiresIn(24 * 60 * 60 * 1000)
5062
+ * .build()
5063
+ * )
5064
+ * console.log(`https://novachatapp.com/invite/${invite.code}`)
5065
+ *
5066
+ * // Permanent invite with no restrictions
5067
+ * const perm = await client.invites.create(serverId,
5068
+ * new InviteBuilder().setPermanent().build()
5069
+ * )
5070
+ */
5071
+ declare class InviteBuilder {
5072
+ private _maxUses;
5073
+ private _expiresAt;
5074
+ /**
5075
+ * Set the maximum number of times this invite can be used.
5076
+ * Pass `null` for unlimited uses.
5077
+ */
5078
+ setMaxUses(maxUses: number | null): this;
5079
+ /**
5080
+ * Set an absolute expiry date/time for this invite.
5081
+ * Pass a `Date`, an ISO string, or `null` to never expire.
5082
+ */
5083
+ setExpiresAt(date: Date | string | null): this;
5084
+ /**
5085
+ * Set expiry as a duration from now.
5086
+ * @param ms Duration in milliseconds.
5087
+ *
5088
+ * @example
5089
+ * builder.expiresIn(7 * 24 * 60 * 60 * 1000) // 7 days
5090
+ */
5091
+ expiresIn(ms: number): this;
5092
+ /**
5093
+ * Create a one-time use invite (`maxUses = 1`).
5094
+ */
5095
+ setOneTimeUse(): this;
5096
+ /**
5097
+ * Create a permanent invite with no expiry or usage limit.
5098
+ */
5099
+ setPermanent(): this;
5100
+ /**
5101
+ * Build the `InviteCreateOptions` object.
5102
+ */
5103
+ build(): InviteCreateOptions;
5104
+ }
5105
+
5106
+ type AutoModRuleType = 'BLOCKED_WORD' | 'BLOCKED_LINK';
5107
+ /**
5108
+ * Fluent builder for AutoMod rules.
5109
+ *
5110
+ * @example
5111
+ * // Block a specific word
5112
+ * await client.automod.create(serverId,
5113
+ * new AutoModRuleBuilder()
5114
+ * .blockWord('badword')
5115
+ * .build()
5116
+ * )
5117
+ *
5118
+ * // Block a domain
5119
+ * await client.automod.create(serverId,
5120
+ * new AutoModRuleBuilder()
5121
+ * .blockLink('spam.example.com')
5122
+ * .build()
5123
+ * )
5124
+ *
5125
+ * // Create a rule in disabled state
5126
+ * await client.automod.create(serverId,
5127
+ * new AutoModRuleBuilder()
5128
+ * .setType('BLOCKED_WORD')
5129
+ * .setValue('draft-word')
5130
+ * .setEnabled(false)
5131
+ * .build()
5132
+ * )
5133
+ */
5134
+ declare class AutoModRuleBuilder {
5135
+ private _type;
5136
+ private _value;
5137
+ private _enabled;
5138
+ /** Set the rule type explicitly. */
5139
+ setType(type: AutoModRuleType): this;
5140
+ /**
5141
+ * Set the blocked value (word or domain).
5142
+ */
5143
+ setValue(value: string): this;
5144
+ /**
5145
+ * Shorthand: set type to BLOCKED_WORD and optionally set the value.
5146
+ *
5147
+ * @example
5148
+ * builder.blockWord('badword')
5149
+ */
5150
+ blockWord(word?: string): this;
5151
+ /**
5152
+ * Shorthand: set type to BLOCKED_LINK and optionally set the domain.
5153
+ *
5154
+ * @example
5155
+ * builder.blockLink('spam.com')
5156
+ */
5157
+ blockLink(domain?: string): this;
5158
+ /**
5159
+ * Whether the rule is active immediately.
5160
+ * @default true
5161
+ */
5162
+ setEnabled(enabled: boolean): this;
5163
+ /**
5164
+ * Validate and build the `CreateAutoModRuleOptions` object.
5165
+ *
5166
+ * @throws if type or value is not set.
5167
+ */
5168
+ build(): CreateAutoModRuleOptions;
5169
+ }
5170
+
5171
+ /**
5172
+ * Fluent builder for context-menu commands.
5173
+ *
5174
+ * Context-menu commands appear when a user right-clicks (or long-presses) a
5175
+ * **message** or a **user** in the Nova client. There are two target types:
5176
+ * - `'MESSAGE'` — appears in the message context menu.
5177
+ * - `'USER'` — appears in the user context menu.
5178
+ *
5179
+ * @example
5180
+ * // Register a "Report Message" context-menu command globally
5181
+ * await client.commands.setContext([
5182
+ * new ContextMenuCommandBuilder()
5183
+ * .setName('Report Message')
5184
+ * .forMessages()
5185
+ * .build(),
5186
+ * ])
5187
+ *
5188
+ * // Handle the interaction
5189
+ * client.on('interactionCreate', async (i) => {
5190
+ * if (i.type === 'CONTEXT_MENU' && i.commandName === 'Report Message') {
5191
+ * const targetMsgId = i.contextTargetId
5192
+ * await i.replyEphemeral(`Message ${targetMsgId} has been reported.`)
5193
+ * }
5194
+ * })
5195
+ */
5196
+ declare class ContextMenuCommandBuilder {
5197
+ private _name;
5198
+ private _target;
5199
+ private _guildId;
5200
+ /**
5201
+ * Display name of the command (shown in the context menu).
5202
+ * Max 32 characters. May contain spaces.
5203
+ *
5204
+ * @example
5205
+ * builder.setName('Report Message')
5206
+ */
5207
+ setName(name: string): this;
5208
+ /**
5209
+ * Set whether the command targets messages or users.
5210
+ *
5211
+ * @example
5212
+ * builder.setTarget('USER')
5213
+ */
5214
+ setTarget(target: 'MESSAGE' | 'USER'): this;
5215
+ /**
5216
+ * Shorthand for `setTarget('MESSAGE')`.
5217
+ *
5218
+ * @example
5219
+ * builder.forMessages()
5220
+ */
5221
+ forMessages(): this;
5222
+ /**
5223
+ * Shorthand for `setTarget('USER')`.
5224
+ *
5225
+ * @example
5226
+ * builder.forUsers()
5227
+ */
5228
+ forUsers(): this;
5229
+ /**
5230
+ * Register this command only for a specific server (guild).
5231
+ * Omit (or pass `null`) to make the command available globally.
5232
+ *
5233
+ * @example
5234
+ * builder.setGuildId('server-id')
5235
+ */
5236
+ setGuildId(guildId: string | null): this;
5237
+ /**
5238
+ * Validate and return the final command definition object.
5239
+ * Throws if `name` has not been set.
5240
+ */
5241
+ build(): ContextCommandDefinition;
5242
+ /** Alias for `build()`. */
5243
+ toJSON(): ContextCommandDefinition;
5244
+ }
5245
+
5246
+ interface MessageCollectorOptions {
5247
+ /**
5248
+ * How many messages to collect before resolving automatically.
5249
+ * @default 1
5250
+ */
5251
+ count?: number;
5252
+ /**
5253
+ * Time in ms before the collector stops, even if `count` was not reached.
5254
+ * @default 60_000
5255
+ */
5256
+ timeout?: number;
5257
+ /**
5258
+ * Custom filter — return `true` to include a message.
5259
+ * Messages that do not pass are silently ignored.
5260
+ */
5261
+ filter?: (message: NovaMessage) => boolean;
5262
+ }
5263
+ /**
5264
+ * Collects multiple messages matching a filter.
5265
+ * Resolves once `count` messages are collected **or** the timeout elapses.
5266
+ * The resolved array may be shorter than `count` if the timeout fires first.
5267
+ *
5268
+ * @example
5269
+ * // Collect 3 non-bot messages from a specific channel within 30 s
5270
+ * const messages = await new MessageCollector(client, {
5271
+ * filter: msg => msg.channelId === channelId && !msg.isFromBot(),
5272
+ * count: 3,
5273
+ * timeout: 30_000,
5274
+ * }).run()
5275
+ *
5276
+ * for (const msg of messages) {
5277
+ * console.log(msg.author.displayName, ':', msg.content)
5278
+ * }
5279
+ */
5280
+ declare class MessageCollector {
5281
+ private readonly _emitter;
5282
+ private readonly _options;
5283
+ constructor(emitter: EventEmitter$1, options?: MessageCollectorOptions);
5284
+ /**
5285
+ * Start collecting messages.
5286
+ * Returns a promise that resolves with the collected `NovaMessage` array.
5287
+ */
5288
+ run(): Promise<NovaMessage[]>;
5289
+ }
5290
+
5291
+ type InteractionFilter = (interaction: NovaInteraction) => boolean;
5292
+ interface InteractionCollectorOptions {
5293
+ /**
5294
+ * How many interactions to collect before resolving.
5295
+ * @default 1
5296
+ */
5297
+ count?: number;
5298
+ /**
5299
+ * Time in ms before the collector stops.
5300
+ * @default 60_000
5301
+ */
5302
+ timeout?: number;
5303
+ /**
5304
+ * Only collect interactions triggered on this message.
5305
+ * Useful for button/select-menu rows attached to a specific message.
5306
+ */
5307
+ messageId?: string;
5308
+ /**
5309
+ * Custom filter function — return `true` to include an interaction.
5310
+ */
5311
+ filter?: InteractionFilter;
5312
+ }
5313
+ /**
5314
+ * Collects interactions (button clicks, select-menu choices) matching a filter.
5315
+ * Resolves once `count` interactions are collected **or** the timeout elapses.
5316
+ *
5317
+ * @example
5318
+ * // Send a message with buttons, then await a click from the same user
5319
+ * const msg = await channel.send({
5320
+ * content: 'Pick an option:',
5321
+ * components: row.toJSON(),
5322
+ * })
5323
+ *
5324
+ * const [interaction] = await new InteractionCollector(client, {
5325
+ * messageId: msg.id,
5326
+ * filter: i => i.isButton() && i.userId === authorId,
5327
+ * timeout: 30_000,
5328
+ * }).run()
5329
+ *
5330
+ * if (interaction) await interaction.reply('You clicked: ' + interaction.customId)
5331
+ *
5332
+ * @example
5333
+ * // Collect any 3 button clicks on a poll message
5334
+ * const votes = await new InteractionCollector(client, {
5335
+ * messageId: pollMsgId,
5336
+ * filter: i => i.isButton(),
5337
+ * count: 3,
5338
+ * }).run()
5339
+ */
5340
+ declare class InteractionCollector {
5341
+ private readonly _emitter;
5342
+ private readonly _options;
5343
+ constructor(emitter: EventEmitter$1, options?: InteractionCollectorOptions);
5344
+ /**
5345
+ * Start collecting interactions.
5346
+ * Returns a promise that resolves with the collected `NovaInteraction` array.
5347
+ */
5348
+ run(): Promise<NovaInteraction[]>;
5349
+ }
5350
+
5351
+ /**
5352
+ * Utilities for parsing mentions, emojis, and special tokens out of
5353
+ * Nova message content strings.
5354
+ *
5355
+ * @example
5356
+ * const content = 'Hello <@user123>! Check out <#channel456>.'
5357
+ *
5358
+ * MentionParser.userIds(content) // ['user123']
5359
+ * MentionParser.channelIds(content) // ['channel456']
5360
+ *
5361
+ * // Format a mention
5362
+ * MentionParser.user('user123') // '<@user123>'
5363
+ * MentionParser.channel('ch456') // '<#ch456>'
5364
+ *
5365
+ * // Clean the string
5366
+ * MentionParser.stripMentions(content)
5367
+ * // 'Hello ! Check out .'
5368
+ */
5369
+ declare class MentionParser {
5370
+ /**
5371
+ * Extract all user IDs mentioned in the content (`<@userId>`).
5372
+ *
5373
+ * @example
5374
+ * MentionParser.userIds('Hello <@abc> and <@xyz>!') // ['abc', 'xyz']
5375
+ */
5376
+ static userIds(content: string): string[];
5377
+ /**
5378
+ * Extract all channel IDs mentioned in the content (`<#channelId>`).
5379
+ *
5380
+ * @example
5381
+ * MentionParser.channelIds('Go to <#general>!') // ['general']
5382
+ */
5383
+ static channelIds(content: string): string[];
5384
+ /**
5385
+ * Extract all role IDs mentioned in the content (`<&roleId>`).
5386
+ *
5387
+ * @example
5388
+ * MentionParser.roleIds('Paging <&mods>!') // ['mods']
5389
+ */
5390
+ static roleIds(content: string): string[];
5391
+ /**
5392
+ * Extract all custom emoji IDs mentioned in the content (`<:name:id>`).
5393
+ *
5394
+ * @example
5395
+ * MentionParser.emojiIds('Love it <:nova:12345>!')
5396
+ * // [{ name: 'nova', id: '12345' }]
5397
+ */
5398
+ static emojiIds(content: string): Array<{
5399
+ name: string;
5400
+ id: string;
5401
+ }>;
5402
+ /**
5403
+ * Format a user ID into a mention string `<@userId>`.
5404
+ *
5405
+ * @example
5406
+ * MentionParser.user('abc123') // '<@abc123>'
5407
+ */
5408
+ static user(userId: string): string;
5409
+ /**
5410
+ * Format a channel ID into a mention string `<#channelId>`.
5411
+ *
5412
+ * @example
5413
+ * MentionParser.channel('general') // '<#general>'
5414
+ */
5415
+ static channel(channelId: string): string;
5416
+ /**
5417
+ * Format a role ID into a mention string `<&roleId>`.
5418
+ *
5419
+ * @example
5420
+ * MentionParser.role('mods') // '<&mods>'
5421
+ */
5422
+ static role(roleId: string): string;
5423
+ /**
5424
+ * Format a custom emoji mention `<:name:id>`.
5425
+ *
5426
+ * @example
5427
+ * MentionParser.emoji('nova', '12345') // '<:nova:12345>'
5428
+ */
5429
+ static emoji(name: string, id: string): string;
5430
+ /**
5431
+ * Remove all mention tokens from `content` and return the cleaned string.
5432
+ *
5433
+ * @example
5434
+ * MentionParser.stripMentions('Hello <@u1> in <#c1>!')
5435
+ * // 'Hello in !'
5436
+ */
5437
+ static stripMentions(content: string): string;
5438
+ /**
5439
+ * Returns `true` if `content` mentions at least one user.
5440
+ * Optionally checks for a specific `userId`.
5441
+ *
5442
+ * @example
5443
+ * MentionParser.hasMention('Hi <@u1>') // true
5444
+ * MentionParser.hasMention('Hi <@u1>', 'u1') // true
5445
+ * MentionParser.hasMention('Hi <@u1>', 'u2') // false
5446
+ */
5447
+ static hasMention(content: string, userId?: string): boolean;
5448
+ /**
5449
+ * Returns `true` if `content` mentions a specific bot by its ID.
5450
+ *
5451
+ * @example
5452
+ * if (MentionParser.mentionsBotId(message.content, client.user.id)) {
5453
+ * await message.reply('You called?')
5454
+ * }
5455
+ */
5456
+ static mentionsBotId(content: string, botId: string): boolean;
5457
+ }
5458
+
5459
+ interface EmbedPaginatorOptions<T> {
5460
+ /** Items to paginate. */
5461
+ items: T[];
5462
+ /**
5463
+ * Number of items per page.
5464
+ * @default 10
5465
+ */
5466
+ pageSize?: number;
5467
+ /** ID of the channel to send the paginator into. */
5468
+ channelId: string;
5469
+ /**
5470
+ * Produce an embed for the given page slice.
5471
+ * Called every time the page changes.
5472
+ *
5473
+ * @param page - Items for this page.
5474
+ * @param pageIndex - Zero-based page index.
5475
+ * @param totalPages - Total number of pages.
5476
+ */
5477
+ renderPage(page: T[], pageIndex: number, totalPages: number): Embed;
5478
+ /**
5479
+ * If set, only this user ID is allowed to navigate the pages.
5480
+ * Other users clicking the buttons are silently ignored.
5481
+ */
5482
+ userId?: string;
5483
+ /**
5484
+ * How long (ms) to keep listening for button clicks before giving up.
5485
+ * @default 60_000
5486
+ */
5487
+ timeout?: number;
5488
+ /**
5489
+ * Append "Page X / Y" to the embed footer automatically.
5490
+ * @default true
5491
+ */
5492
+ showPageCounter?: boolean;
5493
+ }
5494
+ /**
5495
+ * Send a paginated embed that users can step through with ◀ ▶ buttons.
5496
+ *
5497
+ * @example
5498
+ * const paginator = new EmbedPaginator(client, client.messages, client.interactions, {
5499
+ * channelId: 'channel-id',
5500
+ * items: leaderboard,
5501
+ * pageSize: 5,
5502
+ * renderPage(page, idx, total) {
5503
+ * return new EmbedBuilder()
5504
+ * .setTitle('🏆 Leaderboard')
5505
+ * .setDescription(
5506
+ * page
5507
+ * .map((e, i) => `**${idx * 5 + i + 1}.** ${e.user.displayName} — ${e.xp} XP`)
5508
+ * .join('\n'),
5509
+ * )
5510
+ * .toJSON()
5511
+ * },
5512
+ * })
5513
+ * await paginator.send()
5514
+ */
5515
+ declare class EmbedPaginator<T> {
5516
+ private readonly emitter;
5517
+ private readonly messages;
5518
+ private readonly interactions;
5519
+ private readonly options;
5520
+ private page;
5521
+ private readonly pages;
5522
+ constructor(emitter: EventEmitter$1, messages: MessagesAPI, interactions: InteractionsAPI, options: EmbedPaginatorOptions<T>);
5523
+ /** Total number of pages. */
5524
+ get totalPages(): number;
5525
+ /**
5526
+ * Send the first page to the configured channel.
5527
+ * If there are multiple pages, attaches ◀ ▶ navigation buttons and
5528
+ * listens for clicks for up to `options.timeout` ms.
5529
+ */
5530
+ send(): Promise<void>;
5531
+ private _awaitClick;
5532
+ private _buildPayload;
5533
+ }
5534
+
5535
+ interface ConfirmationDialogOptions {
5536
+ /** Channel to send the prompt into. */
5537
+ channelId: string;
5538
+ /**
5539
+ * Text shown above the confirm / cancel buttons.
5540
+ * @default 'Are you sure?'
5541
+ */
5542
+ content?: string;
5543
+ /**
5544
+ * Label for the confirm button.
5545
+ * @default 'Confirm'
5546
+ */
5547
+ confirmLabel?: string;
5548
+ /**
5549
+ * Label for the cancel button.
5550
+ * @default 'Cancel'
5551
+ */
5552
+ cancelLabel?: string;
5553
+ /**
5554
+ * If set, only this user ID's response is accepted.
5555
+ * Other users clicking are silently ignored.
5556
+ */
5557
+ userId?: string;
5558
+ /**
5559
+ * How long (ms) to wait before treating the prompt as cancelled.
5560
+ * @default 30_000
5561
+ */
5562
+ timeout?: number;
5563
+ }
5564
+ /**
5565
+ * Send a yes / no confirmation prompt and wait for the user's response.
5566
+ * Returns `true` if confirmed, `false` if cancelled or timed out.
5567
+ *
5568
+ * @example
5569
+ * const dialog = new ConfirmationDialog(client, client.messages, client.interactions)
5570
+ *
5571
+ * const confirmed = await dialog.ask({
5572
+ * channelId: interaction.channelId,
5573
+ * content: `Are you sure you want to ban **${target.displayName}**?`,
5574
+ * userId: interaction.userId,
5575
+ * })
5576
+ *
5577
+ * if (confirmed) {
5578
+ * await client.members.ban(serverId, target.userId, 'Confirmed via bot')
5579
+ * await interaction.reply('User has been banned.')
5580
+ * } else {
5581
+ * await interaction.reply('Cancelled.')
5582
+ * }
5583
+ */
5584
+ declare class ConfirmationDialog {
5585
+ private readonly emitter;
5586
+ private readonly messages;
5587
+ private readonly interactions;
5588
+ constructor(emitter: EventEmitter$1, messages: MessagesAPI, interactions: InteractionsAPI);
5589
+ /**
5590
+ * Send the confirmation prompt and await the user's choice.
5591
+ * Returns `true` for confirm, `false` for cancel or timeout.
5592
+ */
5593
+ ask(options: ConfirmationDialogOptions): Promise<boolean>;
5594
+ private _awaitClick;
5595
+ }
5596
+
5597
+ /**
5598
+ * Parser for prefix-command message content.
5599
+ *
5600
+ * Handles both positional arguments and named flags:
5601
+ * - `--flag value` → string flag
5602
+ * - `--flag "multi word value"` → quoted string flag
5603
+ * - `--flag` → boolean flag (value = 'true')
5604
+ * - `-f` → single-char shorthand boolean flag
5605
+ * - bare tokens → positional args (in order)
5606
+ *
5607
+ * @example
5608
+ * // Input: !ban @nick123 7 --reason "rule violation" --notify
5609
+ * // After stripping the @mention: "nick123 7 --reason "rule violation" --notify"
5610
+ *
5611
+ * const args = ArgumentParser.parse('nick123 7 --reason "rule violation" --notify')
5612
+ *
5613
+ * args.positional // ['nick123', '7']
5614
+ * args.get('reason') // 'rule violation'
5615
+ * args.has('notify') // true
5616
+ * args.getInt(1) // 7
5617
+ */
5618
+ declare class ParsedArguments {
5619
+ /** Positional (non-flag) arguments in order. */
5620
+ readonly positional: string[];
5621
+ private readonly _flags;
5622
+ constructor(positional: string[], flags: Map<string, string>);
5623
+ /**
5624
+ * Whether a named flag is present (regardless of value).
5625
+ *
5626
+ * @example
5627
+ * args.has('notify') // true for --notify or --notify true
5628
+ */
5629
+ has(flag: string): boolean;
5630
+ /**
5631
+ * Get the string value of a named flag, or `null` if absent.
5632
+ *
5633
+ * @example
5634
+ * args.get('reason') // 'rule violation'
5635
+ */
5636
+ get(flag: string): string | null;
5637
+ /**
5638
+ * Get the string value of a named flag, throwing if missing.
5639
+ *
5640
+ * @example
5641
+ * const reason = args.require('reason') // throws if --reason not supplied
5642
+ */
5643
+ require(flag: string): string;
5644
+ /**
5645
+ * Parse the flag value as an integer, or `null` if absent / not a number.
5646
+ *
5647
+ * @example
5648
+ * args.getInt('days') // 7 from '--days 7'
5649
+ */
5650
+ getInt(flag: string): number | null;
5651
+ /**
5652
+ * Parse the flag value as a float, or `null` if absent / not a number.
5653
+ */
5654
+ getFloat(flag: string): number | null;
5655
+ /**
5656
+ * Get a positional argument by index (0-based), or `null` if absent.
5657
+ *
5658
+ * @example
5659
+ * args.at(0) // first positional token
5660
+ */
5661
+ at(index: number): string | null;
5662
+ /**
5663
+ * Get positional argument at `index` as an integer, or `null`.
5664
+ *
5665
+ * @example
5666
+ * args.getInt(1) // 7 when positional is ['nick123', '7']
5667
+ */
5668
+ getIntAt(index: number): number | null;
5669
+ /**
5670
+ * All flag names that were parsed.
5671
+ *
5672
+ * @example
5673
+ * args.flags() // ['reason', 'notify']
5674
+ */
5675
+ flags(): string[];
5676
+ toJSON(): {
5677
+ positional: string[];
5678
+ flags: {
5679
+ [k: string]: string;
5680
+ };
5681
+ };
5682
+ }
5683
+ /**
5684
+ * Parse the content of a prefix-command message into positional args + named flags.
5685
+ *
5686
+ * @example
5687
+ * const args = ArgumentParser.parse('user123 --reason "rule break" --silent')
5688
+ * args.at(0) // 'user123'
5689
+ * args.get('reason') // 'rule break'
5690
+ * args.has('silent') // true
5691
+ *
5692
+ * // Strip the command prefix before parsing:
5693
+ * const content = msg.content.slice('!kick '.length).trim()
5694
+ * const args = ArgumentParser.parse(content)
5695
+ */
5696
+ declare class ArgumentParser {
5697
+ /**
5698
+ * Parse a raw string of arguments.
5699
+ * Returns a `ParsedArguments` instance.
5700
+ */
5701
+ static parse(input: string): ParsedArguments;
5702
+ /**
5703
+ * Strip a user mention like `<@123456>` from the start of the input string
5704
+ * and return the remainder trimmed. Returns the original string unchanged if
5705
+ * no leading mention is found.
5706
+ *
5707
+ * @example
5708
+ * ArgumentParser.stripMention('<@98765> hello world') // 'hello world'
5709
+ */
5710
+ static stripMention(input: string): string;
5711
+ /**
5712
+ * Split `input` into tokens. Quoted strings are treated as single tokens.
5713
+ */
5714
+ private static _tokenise;
5715
+ }
5716
+
5717
+ /**
5718
+ * A simple in-memory key-value cache with optional per-entry TTL.
5719
+ * Expired entries are evicted lazily (on read) and eagerly (via `prune()`).
5720
+ *
5721
+ * @typeParam K - Key type (default: `string`).
5722
+ * @typeParam V - Value type.
5723
+ *
5724
+ * @example
5725
+ * const cache = new CacheMap<string, UserProfile>()
5726
+ *
5727
+ * // Cache a profile for 5 minutes
5728
+ * cache.set(userId, profile, 5 * 60_000)
5729
+ *
5730
+ * // Retrieve it later
5731
+ * const cached = cache.get(userId)
5732
+ * if (cached) {
5733
+ * console.log('cache hit:', cached.displayName)
5734
+ * } else {
5735
+ * // Fetch fresh, then cache
5736
+ * const fresh = await client.fetchUserProfile(userId)
5737
+ * cache.set(userId, fresh, 5 * 60_000)
5738
+ * }
5739
+ */
5740
+ declare class CacheMap<K = string, V = unknown> {
5741
+ private readonly _store;
5742
+ /**
5743
+ * Store a value.
5744
+ *
5745
+ * @param key - Cache key.
5746
+ * @param value - Value to store.
5747
+ * @param ttlMs - Optional time-to-live in milliseconds. Omit for permanent storage.
5748
+ */
5749
+ set(key: K, value: V, ttlMs?: number): this;
5750
+ /**
5751
+ * Retrieve a value, or `undefined` if absent or expired.
5752
+ * Expired entries are automatically deleted on access.
5753
+ */
5754
+ get(key: K): V | undefined;
5755
+ /**
5756
+ * Check if a live (non-expired) entry exists for this key.
5757
+ */
5758
+ has(key: K): boolean;
5759
+ /**
5760
+ * Delete an entry.
5761
+ * Returns `true` if the entry existed (even if it was expired).
5762
+ */
5763
+ delete(key: K): boolean;
5764
+ /** Remove all entries. */
5765
+ clear(): void;
5766
+ /**
5767
+ * Number of **live** (non-expired) entries.
5768
+ * This prunes expired entries as a side-effect.
5769
+ */
5770
+ get size(): number;
5771
+ /**
5772
+ * Remove all expired entries immediately.
5773
+ * Useful to call occasionally to free memory.
5774
+ *
5775
+ * @example
5776
+ * // Prune every 10 minutes
5777
+ * setInterval(() => cache.prune(), 10 * 60_000)
5778
+ */
5779
+ prune(): number;
5780
+ /**
5781
+ * Return all **live** keys.
5782
+ */
5783
+ keys(): K[];
5784
+ /**
5785
+ * Return all **live** values.
5786
+ */
5787
+ values(): V[];
5788
+ /**
5789
+ * Return all **live** `[key, value]` pairs.
5790
+ */
5791
+ entries(): [K, V][];
5792
+ /**
5793
+ * Get a value or compute & cache it if missing.
5794
+ * Very useful for "cache-aside" data loading.
5795
+ *
5796
+ * @param key - Cache key.
5797
+ * @param loader - Async function that produces the value when the cache is cold.
5798
+ * @param ttlMs - Optional TTL to apply to the newly cached value.
5799
+ *
5800
+ * @example
5801
+ * const profile = await cache.getOrSet(userId, () => client.fetchUserProfile(userId), 60_000)
5802
+ */
5803
+ getOrSet(key: K, loader: () => Promise<V>, ttlMs?: number): Promise<V>;
5804
+ /**
5805
+ * Return the number of milliseconds until a key expires.
5806
+ * Returns `null` if the key has no TTL, `0` if it is already expired.
5807
+ */
5808
+ ttl(key: K): number | null;
5809
+ [Symbol.iterator](): Iterator<[K, V]>;
5810
+ }
5811
+
5812
+ type TaskId = string;
5813
+ /**
5814
+ * Lightweight task scheduler for bots.
5815
+ * Supports one-shot delays, absolute-time scheduling, and recurring intervals.
5816
+ * All registered tasks can be cancelled individually or all at once.
5817
+ *
5818
+ * @example
5819
+ * const scheduler = new EventScheduler()
5820
+ *
5821
+ * // Run once after 10 seconds
5822
+ * scheduler.schedule(10_000, async () => {
5823
+ * await client.messages.send(channelId, { content: 'Reminder: meeting in 5 minutes!' })
5824
+ * })
5825
+ *
5826
+ * // Run every hour
5827
+ * scheduler.repeat(60 * 60_000, async () => {
5828
+ * const stats = await client.fetchServerStats(serverId)
5829
+ * console.log(`${stats.onlineCount} online`)
5830
+ * })
5831
+ *
5832
+ * // Cancel everything when the bot shuts down
5833
+ * client.once('disconnect', () => scheduler.cancelAll())
5834
+ */
5835
+ declare class EventScheduler {
5836
+ private readonly _tasks;
5837
+ /**
5838
+ * Schedule a one-shot task to run after `delayMs` milliseconds.
5839
+ * Returns a task ID that can be passed to `cancel()`.
5840
+ *
5841
+ * @example
5842
+ * const id = scheduler.schedule(5_000, () => console.log('5 seconds later'))
5843
+ * // Change your mind:
5844
+ * scheduler.cancel(id)
5845
+ */
5846
+ schedule(delayMs: number, fn: () => unknown): TaskId;
5847
+ /**
5848
+ * Schedule a one-shot task to run at a specific `Date`.
5849
+ * If the date is in the past, the callback fires on the next event-loop tick.
5850
+ *
5851
+ * @example
5852
+ * const nextMidnight = new Date()
5853
+ * nextMidnight.setHours(24, 0, 0, 0)
5854
+ * scheduler.scheduleAt(nextMidnight, () => console.log('Midnight!'))
5855
+ */
5856
+ scheduleAt(date: Date, fn: () => unknown): TaskId;
5857
+ /**
5858
+ * Schedule a recurring task that fires every `intervalMs` milliseconds.
5859
+ * Returns a task ID that can be passed to `cancel()`.
5860
+ *
5861
+ * @example
5862
+ * // Check incoming messages every minute
5863
+ * const id = scheduler.repeat(60_000, () => checkForAnnouncements())
5864
+ */
5865
+ repeat(intervalMs: number, fn: () => unknown): TaskId;
5866
+ /**
5867
+ * Cancel a previously scheduled task by its ID.
5868
+ * Returns `true` if the task existed, `false` if it had already fired or
5869
+ * was not found.
5870
+ *
5871
+ * @example
5872
+ * const id = scheduler.schedule(30_000, doSomething)
5873
+ * // …maybe cancel it:
5874
+ * scheduler.cancel(id)
5875
+ */
5876
+ cancel(id: TaskId): boolean;
5877
+ /**
5878
+ * Cancel all pending tasks.
5879
+ * Useful during graceful shutdown.
5880
+ *
5881
+ * @example
5882
+ * client.once('disconnect', () => scheduler.cancelAll())
5883
+ */
5884
+ cancelAll(): void;
5885
+ /**
5886
+ * Number of currently active (pending or recurring) tasks.
5887
+ */
5888
+ get pendingCount(): number;
5889
+ /**
5890
+ * IDs of all currently registered tasks.
5891
+ */
5892
+ taskIds(): TaskId[];
5893
+ private _run;
5894
+ }
5895
+
5896
+ export { ActionRowBuilder, ArgumentParser, type Attachment, AuditLogAPI, type AuditLogAction, type AuditLogEntry, AutoModAPI, type AutoModRule, AutoModRuleBuilder, type AutoModRuleType$1 as AutoModRuleType, type BanEntry, type BotApplication, type BotEvent, type BotEventType, type BotModalDefinition, type BotModalField, type BotPermissionRecord, type BotStatus, type BotUser, type BulkDeleteResult, ButtonBuilder, type ButtonStyle, CacheMap, CategoriesAPI, type Channel, ChannelBuilder, type ChannelCategory, type ChannelType, ChannelsAPI, Collection, CommandsAPI, ConfirmationDialog, type ConfirmationDialogOptions, type ContextCommandDefinition, ContextMenuCommandBuilder, Cooldown, CooldownManager, type CreateAutoModRuleOptions, type CreateCategoryOptions, type CreateChannelOptions, type CreateEventOptions, type CreateForumPostOptions, type DirectMessage, type EditAutoModRuleOptions, type EditCategoryOptions, type EditChannelOptions, type EditEventOptions, type EditForumPostOptions, type EditMessageOptions, type Embed, EmbedBuilder, type EmbedField, EmbedPaginator, type EmbedPaginatorOptions, EventBuilder, EventScheduler, EventsAPI, type ExecuteWebhookOptions, type FetchAuditLogsOptions, type FetchChannelsOptions, type FetchEventsOptions, type FetchForumPostsOptions, type FetchMembersOptions, type FetchMessagesOptions, type FetchWarningsOptions, ForumAPI, type ForumPost, ForumPostBuilder, HttpClient, type Interaction, InteractionCollector, type InteractionCollectorOptions, type InteractionFilter, InteractionOptions, type InteractionType, InteractionsAPI, type Invite, InviteBuilder, type InviteCreateOptions, InvitesAPI, type LeaderboardEntry, Logger, type Member, type MemberXPData, MembersAPI, MentionParser, type Message, MessageBuilder, MessageCollector, type MessageCollectorOptions, type MessageComponent, MessagesAPI, ModalBuilder, NovaBan, NovaCategory, NovaChannel, NovaClient, type NovaClientEvents, type NovaClientOptions, NovaForumPost, NovaInteraction, NovaInvite, NovaMember, NovaMessage, NovaRole, type NovaServer, NovaServerEvent, NovaServerWrapper, NovaWarning, NovaWebhook, Paginator, ParsedArguments, type PermissionKey, Permissions, PermissionsAPI, PermissionsBitfield, type PermissionsQueryOptions, type PermissionsResult, PollBuilder, type PollDefinition, type PollInteractionsOptions, type PollOption, type PrefixCommandDefinition, type Reaction, type ReactionDetail, ReactionsAPI, type RegisteredContextCommand, type RegisteredPrefixCommand, type RegisteredSlashCommand, type RespondInteractionOptions, type Role, RoleBuilder, type RoleCreateOptions, type RoleEditOptions, RolesAPI, SelectMenuBuilder, type SelectMenuOption, type SendMessageOptions, type ServerEvent, type ServerEventAttendee, type ServerStats, type ServerUpdateOptions, ServersAPI, type SingleMember, SlashCommandBuilder, type SlashCommandDefinition, type SlashCommandOption, SlashCommandOptionBuilder, type SoundboardClip, TextInputBuilder, type TextInputStyle, type UserProfile, UsersAPI, type VoiceState, type Warning, type Webhook, type WebhookCreateOptions, type WebhookEditOptions, WebhooksAPI, countdown, formatDuration, formatRelative, parseTimestamp, sleep, withTimeout };