novaapp-sdk 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +610 -5
- package/dist/index.d.ts +610 -5
- package/dist/index.js +702 -2
- package/dist/index.mjs +690 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -68,8 +68,8 @@ interface Channel {
|
|
|
68
68
|
serverId: string | null;
|
|
69
69
|
topic: string | null;
|
|
70
70
|
position: number;
|
|
71
|
-
|
|
72
|
-
slowMode: number
|
|
71
|
+
/** Slow-mode interval in seconds. `0` means disabled. */
|
|
72
|
+
slowMode: number;
|
|
73
73
|
createdAt: string;
|
|
74
74
|
}
|
|
75
75
|
interface Role {
|
|
@@ -336,14 +336,12 @@ interface CreateChannelOptions {
|
|
|
336
336
|
type?: ChannelType;
|
|
337
337
|
topic?: string;
|
|
338
338
|
position?: number;
|
|
339
|
-
isNsfw?: boolean;
|
|
340
339
|
slowMode?: number;
|
|
341
340
|
}
|
|
342
341
|
interface EditChannelOptions {
|
|
343
342
|
name?: string;
|
|
344
343
|
topic?: string;
|
|
345
344
|
position?: number;
|
|
346
|
-
isNsfw?: boolean;
|
|
347
345
|
slowMode?: number;
|
|
348
346
|
}
|
|
349
347
|
interface FetchChannelsOptions {
|
|
@@ -382,6 +380,29 @@ interface PermissionsQueryOptions {
|
|
|
382
380
|
/** Narrow the scope to a specific role. */
|
|
383
381
|
roleId?: string;
|
|
384
382
|
}
|
|
383
|
+
/** A direct message sent between the bot and a user. */
|
|
384
|
+
interface DirectMessage {
|
|
385
|
+
id: string;
|
|
386
|
+
content: string;
|
|
387
|
+
/** The sender's user ID. */
|
|
388
|
+
fromId: string;
|
|
389
|
+
/** The recipient's user ID. */
|
|
390
|
+
toId: string;
|
|
391
|
+
editedAt: string | null;
|
|
392
|
+
createdAt: string;
|
|
393
|
+
}
|
|
394
|
+
/** Snapshot of a user's voice channel presence. */
|
|
395
|
+
interface VoiceState {
|
|
396
|
+
userId: string;
|
|
397
|
+
channelId: string;
|
|
398
|
+
serverId: string;
|
|
399
|
+
/** Whether the user's microphone is muted. */
|
|
400
|
+
muted: boolean;
|
|
401
|
+
/** Whether the user's audio output is deafened. */
|
|
402
|
+
deafened: boolean;
|
|
403
|
+
/** ISO timestamp when the user joined the voice channel. */
|
|
404
|
+
joinedAt: string;
|
|
405
|
+
}
|
|
385
406
|
interface NovaClientOptions {
|
|
386
407
|
/** Your bot token — starts with "nova_bot_" */
|
|
387
408
|
token: string;
|
|
@@ -1333,6 +1354,214 @@ declare class NovaMessage {
|
|
|
1333
1354
|
toString(): string;
|
|
1334
1355
|
}
|
|
1335
1356
|
|
|
1357
|
+
/**
|
|
1358
|
+
* A rich wrapper around a raw `Channel` with convenience methods.
|
|
1359
|
+
*
|
|
1360
|
+
* Returned by `client.fetchChannel()` and `client.fetchChannels()`.
|
|
1361
|
+
*
|
|
1362
|
+
* @example
|
|
1363
|
+
* const channel = await client.fetchChannel('channel-id')
|
|
1364
|
+
*
|
|
1365
|
+
* await channel.send('Hello from the bot!')
|
|
1366
|
+
* await channel.edit({ topic: 'New topic' })
|
|
1367
|
+
* const messages = await channel.fetchMessages({ limit: 20 })
|
|
1368
|
+
*/
|
|
1369
|
+
declare class NovaChannel {
|
|
1370
|
+
/** The channel's unique ID. */
|
|
1371
|
+
readonly id: string;
|
|
1372
|
+
/** The channel's name (without #). */
|
|
1373
|
+
readonly name: string;
|
|
1374
|
+
/** The channel type — `'TEXT'`, `'VOICE'`, `'ANNOUNCEMENT'`, `'FORUM'`, or `'STAGE'`. */
|
|
1375
|
+
readonly type: ChannelType;
|
|
1376
|
+
/** The ID of the server this channel belongs to. */
|
|
1377
|
+
readonly serverId: string | null;
|
|
1378
|
+
/** Optional topic / description text. */
|
|
1379
|
+
readonly topic: string | null;
|
|
1380
|
+
/** Sorting position (lower = higher in the list). */
|
|
1381
|
+
readonly position: number;
|
|
1382
|
+
/** Slow-mode interval in seconds (`0` = disabled). */
|
|
1383
|
+
readonly slowMode: number;
|
|
1384
|
+
/** When the channel was created. */
|
|
1385
|
+
readonly createdAt: Date;
|
|
1386
|
+
private readonly _channels;
|
|
1387
|
+
private readonly _messages;
|
|
1388
|
+
constructor(raw: Channel, channels: ChannelsAPI, messages: MessagesAPI);
|
|
1389
|
+
/** `true` for text channels. */
|
|
1390
|
+
isText(): boolean;
|
|
1391
|
+
/** `true` for voice channels. */
|
|
1392
|
+
isVoice(): boolean;
|
|
1393
|
+
/** `true` for announcement channels. */
|
|
1394
|
+
isAnnouncement(): boolean;
|
|
1395
|
+
/** `true` for forum channels. */
|
|
1396
|
+
isForum(): boolean;
|
|
1397
|
+
/** `true` for stage channels. */
|
|
1398
|
+
isStage(): boolean;
|
|
1399
|
+
/** `true` if slow-mode is enabled on this channel. */
|
|
1400
|
+
hasSlowMode(): boolean;
|
|
1401
|
+
/**
|
|
1402
|
+
* Send a message to this channel.
|
|
1403
|
+
* Accepts a plain string or a full options object.
|
|
1404
|
+
*
|
|
1405
|
+
* @example
|
|
1406
|
+
* await channel.send('Hello!')
|
|
1407
|
+
* await channel.send({ content: 'Hi', embed: { title: 'Stats' } })
|
|
1408
|
+
*/
|
|
1409
|
+
send(options: string | SendMessageOptions): Promise<Message>;
|
|
1410
|
+
/**
|
|
1411
|
+
* Fetch recent messages from this channel.
|
|
1412
|
+
*
|
|
1413
|
+
* @example
|
|
1414
|
+
* const messages = await channel.fetchMessages({ limit: 50 })
|
|
1415
|
+
*/
|
|
1416
|
+
fetchMessages(options?: FetchMessagesOptions): Promise<Message[]>;
|
|
1417
|
+
/**
|
|
1418
|
+
* Fetch all pinned messages in this channel.
|
|
1419
|
+
*
|
|
1420
|
+
* @example
|
|
1421
|
+
* const pins = await channel.fetchPins()
|
|
1422
|
+
*/
|
|
1423
|
+
fetchPins(): Promise<Message[]>;
|
|
1424
|
+
/**
|
|
1425
|
+
* Start a typing indicator (shows "Bot is typing…" for ~5 seconds).
|
|
1426
|
+
*
|
|
1427
|
+
* @example
|
|
1428
|
+
* await channel.startTyping()
|
|
1429
|
+
*/
|
|
1430
|
+
startTyping(): Promise<{
|
|
1431
|
+
ok: true;
|
|
1432
|
+
}>;
|
|
1433
|
+
/**
|
|
1434
|
+
* Edit this channel's properties.
|
|
1435
|
+
* Requires the `channels.manage` scope.
|
|
1436
|
+
*
|
|
1437
|
+
* @example
|
|
1438
|
+
* await channel.edit({ name: 'general-2', topic: 'The second general channel' })
|
|
1439
|
+
*/
|
|
1440
|
+
edit(options: EditChannelOptions): Promise<NovaChannel>;
|
|
1441
|
+
/**
|
|
1442
|
+
* Delete this channel.
|
|
1443
|
+
* Requires the `channels.manage` scope.
|
|
1444
|
+
*
|
|
1445
|
+
* @example
|
|
1446
|
+
* await channel.delete()
|
|
1447
|
+
*/
|
|
1448
|
+
delete(): Promise<{
|
|
1449
|
+
ok: true;
|
|
1450
|
+
}>;
|
|
1451
|
+
/**
|
|
1452
|
+
* Returns the channel as a mention-style string: `#name`.
|
|
1453
|
+
*/
|
|
1454
|
+
toString(): string;
|
|
1455
|
+
/** Returns the raw channel data. */
|
|
1456
|
+
toJSON(): Channel;
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
/**
|
|
1460
|
+
* A rich wrapper around a raw `Member` with convenience methods.
|
|
1461
|
+
*
|
|
1462
|
+
* Returned by `client.fetchMember()` and `client.fetchMembers()`.
|
|
1463
|
+
*
|
|
1464
|
+
* @example
|
|
1465
|
+
* const member = await client.fetchMember('server-id', 'user-id')
|
|
1466
|
+
*
|
|
1467
|
+
* if (member.isAdmin()) {
|
|
1468
|
+
* await member.dm('You have admin access.')
|
|
1469
|
+
* } else {
|
|
1470
|
+
* await member.kick()
|
|
1471
|
+
* }
|
|
1472
|
+
*/
|
|
1473
|
+
declare class NovaMember {
|
|
1474
|
+
/** The user's unique ID. */
|
|
1475
|
+
readonly userId: string;
|
|
1476
|
+
/** The server this membership belongs to. */
|
|
1477
|
+
readonly serverId: string;
|
|
1478
|
+
/** The user's username (login handle). */
|
|
1479
|
+
readonly username: string;
|
|
1480
|
+
/** The user's display name. */
|
|
1481
|
+
readonly displayName: string;
|
|
1482
|
+
/** URL of the user's avatar, or `null`. */
|
|
1483
|
+
readonly avatar: string | null;
|
|
1484
|
+
/** The member's server role — `'OWNER'`, `'ADMIN'`, or `'MEMBER'`. */
|
|
1485
|
+
readonly role: 'OWNER' | 'ADMIN' | 'MEMBER';
|
|
1486
|
+
/** The user's current presence status. */
|
|
1487
|
+
readonly status: 'ONLINE' | 'IDLE' | 'DND' | 'OFFLINE';
|
|
1488
|
+
/** `true` if this member is a bot account. */
|
|
1489
|
+
readonly isBot: boolean;
|
|
1490
|
+
/** When this user joined the server. */
|
|
1491
|
+
readonly joinedAt: Date;
|
|
1492
|
+
private readonly _members;
|
|
1493
|
+
constructor(raw: Member, serverId: string, members: MembersAPI);
|
|
1494
|
+
/** `true` if this member is the server owner. */
|
|
1495
|
+
isOwner(): boolean;
|
|
1496
|
+
/** `true` if this member is an admin or the server owner. */
|
|
1497
|
+
isAdmin(): boolean;
|
|
1498
|
+
/** `true` if this member is a regular (non-privileged) member. */
|
|
1499
|
+
isRegularMember(): boolean;
|
|
1500
|
+
/** `true` if the user is currently online. */
|
|
1501
|
+
isOnline(): boolean;
|
|
1502
|
+
/** `true` if the user is idle / away. */
|
|
1503
|
+
isIdle(): boolean;
|
|
1504
|
+
/** `true` if the user is set to Do Not Disturb. */
|
|
1505
|
+
isDND(): boolean;
|
|
1506
|
+
/** `true` if the user appears offline. */
|
|
1507
|
+
isOffline(): boolean;
|
|
1508
|
+
/**
|
|
1509
|
+
* Kick this member from the server.
|
|
1510
|
+
* Bots cannot kick owners or admins (throws 403).
|
|
1511
|
+
*
|
|
1512
|
+
* @example
|
|
1513
|
+
* await member.kick()
|
|
1514
|
+
*/
|
|
1515
|
+
kick(): Promise<{
|
|
1516
|
+
ok: true;
|
|
1517
|
+
}>;
|
|
1518
|
+
/**
|
|
1519
|
+
* Ban this member from the server with an optional reason.
|
|
1520
|
+
* Bots cannot ban owners or admins (throws 403).
|
|
1521
|
+
*
|
|
1522
|
+
* @example
|
|
1523
|
+
* await member.ban('Repeated rule violations')
|
|
1524
|
+
*/
|
|
1525
|
+
ban(reason?: string): Promise<{
|
|
1526
|
+
ok: true;
|
|
1527
|
+
}>;
|
|
1528
|
+
/**
|
|
1529
|
+
* Send this user a direct message.
|
|
1530
|
+
* Requires the `messages.write` scope.
|
|
1531
|
+
*
|
|
1532
|
+
* @example
|
|
1533
|
+
* await member.dm('Welcome to the server!')
|
|
1534
|
+
* await member.dm({ content: 'Hello', embed: { title: 'Rules' } })
|
|
1535
|
+
*/
|
|
1536
|
+
dm(options: string | Omit<SendMessageOptions, 'replyToId'>): Promise<Message>;
|
|
1537
|
+
/**
|
|
1538
|
+
* Assign a custom role to this member.
|
|
1539
|
+
* Requires the `members.roles` scope.
|
|
1540
|
+
*
|
|
1541
|
+
* @example
|
|
1542
|
+
* await member.addRole('role-id')
|
|
1543
|
+
*/
|
|
1544
|
+
addRole(roleId: string): Promise<{
|
|
1545
|
+
ok: true;
|
|
1546
|
+
}>;
|
|
1547
|
+
/**
|
|
1548
|
+
* Remove a custom role from this member.
|
|
1549
|
+
* Requires the `members.roles` scope.
|
|
1550
|
+
*
|
|
1551
|
+
* @example
|
|
1552
|
+
* await member.removeRole('role-id')
|
|
1553
|
+
*/
|
|
1554
|
+
removeRole(roleId: string): Promise<{
|
|
1555
|
+
ok: true;
|
|
1556
|
+
}>;
|
|
1557
|
+
/**
|
|
1558
|
+
* Returns a mention-style string: `@displayName`.
|
|
1559
|
+
*/
|
|
1560
|
+
toString(): string;
|
|
1561
|
+
/** Returns the raw member data. */
|
|
1562
|
+
toJSON(): Member;
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1336
1565
|
interface NovaClientEvents {
|
|
1337
1566
|
/** Fired when the bot connects and is identified by the gateway. */
|
|
1338
1567
|
ready: (bot: BotApplication) => void;
|
|
@@ -1396,6 +1625,59 @@ interface NovaClientEvents {
|
|
|
1396
1625
|
channelId: string;
|
|
1397
1626
|
pinnedBy: string;
|
|
1398
1627
|
}) => void;
|
|
1628
|
+
/** A channel was created in a server. */
|
|
1629
|
+
channelCreate: (channel: Channel) => void;
|
|
1630
|
+
/** A channel was updated. */
|
|
1631
|
+
channelUpdate: (channel: Channel) => void;
|
|
1632
|
+
/** A channel was deleted. */
|
|
1633
|
+
channelDelete: (data: {
|
|
1634
|
+
id: string;
|
|
1635
|
+
serverId: string;
|
|
1636
|
+
}) => void;
|
|
1637
|
+
/** A role was created in a server. */
|
|
1638
|
+
roleCreate: (data: {
|
|
1639
|
+
id: string;
|
|
1640
|
+
name: string;
|
|
1641
|
+
color: string | null;
|
|
1642
|
+
serverId: string;
|
|
1643
|
+
position: number;
|
|
1644
|
+
hoist: boolean;
|
|
1645
|
+
createdAt: string;
|
|
1646
|
+
}) => void;
|
|
1647
|
+
/** A role was deleted. */
|
|
1648
|
+
roleDelete: (data: {
|
|
1649
|
+
id: string;
|
|
1650
|
+
serverId: string;
|
|
1651
|
+
}) => void;
|
|
1652
|
+
/** A user joined a voice channel. */
|
|
1653
|
+
voiceJoin: (data: {
|
|
1654
|
+
userId: string;
|
|
1655
|
+
channelId: string;
|
|
1656
|
+
serverId: string;
|
|
1657
|
+
}) => void;
|
|
1658
|
+
/** A user left a voice channel. */
|
|
1659
|
+
voiceLeave: (data: {
|
|
1660
|
+
userId: string;
|
|
1661
|
+
channelId: string;
|
|
1662
|
+
serverId: string;
|
|
1663
|
+
}) => void;
|
|
1664
|
+
/** A member was banned from a server. */
|
|
1665
|
+
memberBanned: (data: {
|
|
1666
|
+
userId: string;
|
|
1667
|
+
serverId: string;
|
|
1668
|
+
moderatorId: string | null;
|
|
1669
|
+
reason: string | null;
|
|
1670
|
+
}) => void;
|
|
1671
|
+
/** A member was unbanned. */
|
|
1672
|
+
memberUnbanned: (data: {
|
|
1673
|
+
userId: string;
|
|
1674
|
+
serverId: string;
|
|
1675
|
+
}) => void;
|
|
1676
|
+
/** A member's profile data was updated. */
|
|
1677
|
+
memberUpdate: (data: {
|
|
1678
|
+
userId: string;
|
|
1679
|
+
serverId: string;
|
|
1680
|
+
}) => void;
|
|
1399
1681
|
}
|
|
1400
1682
|
/**
|
|
1401
1683
|
* The main Nova bot client.
|
|
@@ -1443,6 +1725,7 @@ declare class NovaClient extends EventEmitter {
|
|
|
1443
1725
|
private readonly _commandHandlers;
|
|
1444
1726
|
private readonly _buttonHandlers;
|
|
1445
1727
|
private readonly _selectHandlers;
|
|
1728
|
+
private readonly _modalHandlers;
|
|
1446
1729
|
constructor(options: NovaClientOptions);
|
|
1447
1730
|
/**
|
|
1448
1731
|
* Register a handler for a slash or prefix command by name.
|
|
@@ -1473,6 +1756,17 @@ declare class NovaClient extends EventEmitter {
|
|
|
1473
1756
|
* })
|
|
1474
1757
|
*/
|
|
1475
1758
|
selectMenu(customId: string, handler: (interaction: NovaInteraction) => unknown): this;
|
|
1759
|
+
/**
|
|
1760
|
+
* Register a handler for a modal submission by its `customId`.
|
|
1761
|
+
* Called automatically when the user submits a modal with that `customId`.
|
|
1762
|
+
*
|
|
1763
|
+
* @example
|
|
1764
|
+
* client.modal('report_modal', async (interaction) => {
|
|
1765
|
+
* const reason = interaction.modalData.reason
|
|
1766
|
+
* await interaction.replyEphemeral(`Report received: ${reason}`)
|
|
1767
|
+
* })
|
|
1768
|
+
*/
|
|
1769
|
+
modal(customId: string, handler: (interaction: NovaInteraction) => unknown): this;
|
|
1476
1770
|
/**
|
|
1477
1771
|
* Connect to the Nova WebSocket gateway.
|
|
1478
1772
|
* Resolves when the `ready` event is received.
|
|
@@ -1508,6 +1802,51 @@ declare class NovaClient extends EventEmitter {
|
|
|
1508
1802
|
* client.setStatus('ONLINE') // Back online
|
|
1509
1803
|
*/
|
|
1510
1804
|
setStatus(status: BotStatus): void;
|
|
1805
|
+
/**
|
|
1806
|
+
* Fetch a single channel and return it as a rich `NovaChannel` wrapper.
|
|
1807
|
+
*
|
|
1808
|
+
* @example
|
|
1809
|
+
* const channel = await client.fetchChannel('channel-id')
|
|
1810
|
+
* await channel.send('Hello!')
|
|
1811
|
+
*/
|
|
1812
|
+
fetchChannel(channelId: string): Promise<NovaChannel>;
|
|
1813
|
+
/**
|
|
1814
|
+
* Fetch all channels in a server and return them as `NovaChannel` wrappers.
|
|
1815
|
+
*
|
|
1816
|
+
* @example
|
|
1817
|
+
* const channels = await client.fetchChannels('server-id')
|
|
1818
|
+
* const textChannels = channels.filter(c => c.isText())
|
|
1819
|
+
*/
|
|
1820
|
+
fetchChannels(serverId: string): Promise<NovaChannel[]>;
|
|
1821
|
+
/**
|
|
1822
|
+
* Fetch all members in a server and return them as `NovaMember` wrappers.
|
|
1823
|
+
*
|
|
1824
|
+
* @example
|
|
1825
|
+
* const members = await client.fetchMembers('server-id')
|
|
1826
|
+
* const bots = members.filter(m => m.isBot)
|
|
1827
|
+
*/
|
|
1828
|
+
fetchMembers(serverId: string): Promise<NovaMember[]>;
|
|
1829
|
+
/**
|
|
1830
|
+
* Fetch a single member from a server and return them as a `NovaMember` wrapper.
|
|
1831
|
+
* Throws if the user is not found in the server.
|
|
1832
|
+
*
|
|
1833
|
+
* @example
|
|
1834
|
+
* const member = await client.fetchMember('server-id', 'user-id')
|
|
1835
|
+
* await member.dm('Welcome!')
|
|
1836
|
+
*/
|
|
1837
|
+
fetchMember(serverId: string, userId: string): Promise<NovaMember>;
|
|
1838
|
+
/**
|
|
1839
|
+
* Wait for a specific event to be emitted, optionally filtered.
|
|
1840
|
+
* Rejects after `timeoutMs` (default 30 s) if the condition never fires.
|
|
1841
|
+
*
|
|
1842
|
+
* @example
|
|
1843
|
+
* // Wait for any message in a specific channel
|
|
1844
|
+
* const msg = await client.waitFor('messageCreate', m => m.channelId === channelId)
|
|
1845
|
+
*
|
|
1846
|
+
* // Wait for a button click with a timeout
|
|
1847
|
+
* const i = await client.waitFor('interactionCreate', i => i.isButton(), 60_000)
|
|
1848
|
+
*/
|
|
1849
|
+
waitFor<K extends keyof NovaClientEvents>(event: K, filter?: (...args: Parameters<NovaClientEvents[K]>) => boolean, timeoutMs?: number): Promise<Parameters<NovaClientEvents[K]>[0]>;
|
|
1511
1850
|
/**
|
|
1512
1851
|
* Disconnect from the gateway and clean up.
|
|
1513
1852
|
*/
|
|
@@ -2248,4 +2587,270 @@ declare class Logger {
|
|
|
2248
2587
|
commandError(name: string, err: unknown): void;
|
|
2249
2588
|
}
|
|
2250
2589
|
|
|
2251
|
-
|
|
2590
|
+
/**
|
|
2591
|
+
* Async cursor-based paginator for any list API.
|
|
2592
|
+
*
|
|
2593
|
+
* Pass a `fetchFn` that takes the current cursor and returns the next
|
|
2594
|
+
* page of items plus the cursor to use for the next page (`null` = done).
|
|
2595
|
+
*
|
|
2596
|
+
* @example
|
|
2597
|
+
* // Paginate all messages in a channel
|
|
2598
|
+
* const paginator = new Paginator(async (cursor) => {
|
|
2599
|
+
* const messages = await client.messages.fetch(channelId, { limit: 50, before: cursor ?? undefined })
|
|
2600
|
+
* return { items: messages, cursor: messages.at(-1)?.id ?? null }
|
|
2601
|
+
* })
|
|
2602
|
+
*
|
|
2603
|
+
* // Lazy async iteration
|
|
2604
|
+
* for await (const message of paginator) {
|
|
2605
|
+
* console.log(message.content)
|
|
2606
|
+
* }
|
|
2607
|
+
*
|
|
2608
|
+
* // Or collect everything at once
|
|
2609
|
+
* const all = await paginator.fetchAll()
|
|
2610
|
+
*/
|
|
2611
|
+
declare class Paginator<T> {
|
|
2612
|
+
private readonly fetchFn;
|
|
2613
|
+
private _cursor;
|
|
2614
|
+
private _done;
|
|
2615
|
+
private _totalFetched;
|
|
2616
|
+
constructor(fetchFn: (cursor: string | null) => Promise<{
|
|
2617
|
+
items: T[];
|
|
2618
|
+
cursor: string | null;
|
|
2619
|
+
}>);
|
|
2620
|
+
/** Whether all pages have been consumed. */
|
|
2621
|
+
get done(): boolean;
|
|
2622
|
+
/** Total number of items fetched so far (across all pages). */
|
|
2623
|
+
get totalFetched(): number;
|
|
2624
|
+
/**
|
|
2625
|
+
* Fetch the next page of results.
|
|
2626
|
+
* Returns an empty array when there are no more pages.
|
|
2627
|
+
*
|
|
2628
|
+
* @example
|
|
2629
|
+
* const page1 = await paginator.fetchPage()
|
|
2630
|
+
* const page2 = await paginator.fetchPage()
|
|
2631
|
+
*/
|
|
2632
|
+
fetchPage(): Promise<T[]>;
|
|
2633
|
+
/**
|
|
2634
|
+
* Fetch **all** remaining pages and return a flat array.
|
|
2635
|
+
*
|
|
2636
|
+
* ⚠️ Use with caution on very large collections.
|
|
2637
|
+
*
|
|
2638
|
+
* @example
|
|
2639
|
+
* const allMembers = await paginator.fetchAll()
|
|
2640
|
+
*/
|
|
2641
|
+
fetchAll(): Promise<T[]>;
|
|
2642
|
+
/**
|
|
2643
|
+
* Fetch up to `n` items total (across however many pages are needed).
|
|
2644
|
+
*
|
|
2645
|
+
* @example
|
|
2646
|
+
* const first100 = await paginator.fetchN(100)
|
|
2647
|
+
*/
|
|
2648
|
+
fetchN(n: number): Promise<T[]>;
|
|
2649
|
+
/**
|
|
2650
|
+
* Async-iterate over every item, one page at a time.
|
|
2651
|
+
*
|
|
2652
|
+
* @example
|
|
2653
|
+
* for await (const msg of paginator) {
|
|
2654
|
+
* process(msg)
|
|
2655
|
+
* }
|
|
2656
|
+
*/
|
|
2657
|
+
[Symbol.asyncIterator](): AsyncGenerator<T>;
|
|
2658
|
+
/**
|
|
2659
|
+
* Reset the paginator so you can iterate from the beginning again.
|
|
2660
|
+
*
|
|
2661
|
+
* @example
|
|
2662
|
+
* await paginator.fetchAll()
|
|
2663
|
+
* paginator.reset()
|
|
2664
|
+
* const againFirst = await paginator.fetchPage()
|
|
2665
|
+
*/
|
|
2666
|
+
reset(): void;
|
|
2667
|
+
}
|
|
2668
|
+
|
|
2669
|
+
/**
|
|
2670
|
+
* All known Nova bot permission keys.
|
|
2671
|
+
* Use these as string constants when calling `has()`, `grant()`, etc.
|
|
2672
|
+
*/
|
|
2673
|
+
declare const Permissions: {
|
|
2674
|
+
/** Read messages in channels. */
|
|
2675
|
+
readonly MESSAGES_READ: "messages.read";
|
|
2676
|
+
/** Send messages in channels. */
|
|
2677
|
+
readonly MESSAGES_WRITE: "messages.write";
|
|
2678
|
+
/** Edit / delete any message (not just the bot's own). */
|
|
2679
|
+
readonly MESSAGES_MANAGE: "messages.manage";
|
|
2680
|
+
/** Create, edit and delete channels. */
|
|
2681
|
+
readonly CHANNELS_MANAGE: "channels.manage";
|
|
2682
|
+
/** Kick members from the server. */
|
|
2683
|
+
readonly MEMBERS_KICK: "members.kick";
|
|
2684
|
+
/** Ban and unban members from the server. */
|
|
2685
|
+
readonly MEMBERS_BAN: "members.ban";
|
|
2686
|
+
/** Assign and remove roles on members. */
|
|
2687
|
+
readonly MEMBERS_ROLES: "members.roles";
|
|
2688
|
+
/** Edit server settings. */
|
|
2689
|
+
readonly SERVERS_MANAGE: "servers.manage";
|
|
2690
|
+
};
|
|
2691
|
+
type PermissionKey = (typeof Permissions)[keyof typeof Permissions];
|
|
2692
|
+
/**
|
|
2693
|
+
* Utility class for working with Nova bot permission records.
|
|
2694
|
+
*
|
|
2695
|
+
* Unlike a Discord-style bitfield, Nova permissions are stored as a
|
|
2696
|
+
* `Record<string, boolean>` map. `PermissionsBitfield` wraps that
|
|
2697
|
+
* map with readable helpers for checking, merging, and diffing.
|
|
2698
|
+
*
|
|
2699
|
+
* @example
|
|
2700
|
+
* const perms = new PermissionsBitfield({
|
|
2701
|
+
* 'messages.read': true,
|
|
2702
|
+
* 'messages.write': true,
|
|
2703
|
+
* })
|
|
2704
|
+
*
|
|
2705
|
+
* perms.has('messages.read') // true
|
|
2706
|
+
* perms.has('channels.manage') // false
|
|
2707
|
+
* perms.hasAll('messages.read', 'messages.write') // true
|
|
2708
|
+
* perms.missing('messages.manage', 'members.kick') // ['messages.manage', 'members.kick']
|
|
2709
|
+
* perms.toArray() // ['messages.read', 'messages.write']
|
|
2710
|
+
*/
|
|
2711
|
+
declare class PermissionsBitfield {
|
|
2712
|
+
private readonly _perms;
|
|
2713
|
+
constructor(perms?: Record<string, boolean>);
|
|
2714
|
+
/**
|
|
2715
|
+
* Returns `true` if the given permission is explicitly granted.
|
|
2716
|
+
*
|
|
2717
|
+
* @example
|
|
2718
|
+
* if (!perms.has(Permissions.MESSAGES_WRITE)) {
|
|
2719
|
+
* throw new Error('Bot cannot write messages here.')
|
|
2720
|
+
* }
|
|
2721
|
+
*/
|
|
2722
|
+
has(permission: string): boolean;
|
|
2723
|
+
/**
|
|
2724
|
+
* Returns `true` if **all** listed permissions are granted.
|
|
2725
|
+
*
|
|
2726
|
+
* @example
|
|
2727
|
+
* perms.hasAll('messages.read', 'messages.write') // true
|
|
2728
|
+
*/
|
|
2729
|
+
hasAll(...permissions: string[]): boolean;
|
|
2730
|
+
/**
|
|
2731
|
+
* Returns `true` if **at least one** of the listed permissions is granted.
|
|
2732
|
+
*
|
|
2733
|
+
* @example
|
|
2734
|
+
* perms.hasAny('channels.manage', 'servers.manage') // true if either is set
|
|
2735
|
+
*/
|
|
2736
|
+
hasAny(...permissions: string[]): boolean;
|
|
2737
|
+
/**
|
|
2738
|
+
* Returns the list of permissions that are **not** granted.
|
|
2739
|
+
*
|
|
2740
|
+
* @example
|
|
2741
|
+
* const missing = perms.missing('messages.write', 'members.kick')
|
|
2742
|
+
* if (missing.length) throw new Error(`Missing: ${missing.join(', ')}`)
|
|
2743
|
+
*/
|
|
2744
|
+
missing(...permissions: string[]): string[];
|
|
2745
|
+
/**
|
|
2746
|
+
* Return a **new** `PermissionsBitfield` with the given permission granted.
|
|
2747
|
+
*
|
|
2748
|
+
* @example
|
|
2749
|
+
* const updated = perms.grant('channels.manage')
|
|
2750
|
+
*/
|
|
2751
|
+
grant(...permissions: string[]): PermissionsBitfield;
|
|
2752
|
+
/**
|
|
2753
|
+
* Return a **new** `PermissionsBitfield` with the given permission denied.
|
|
2754
|
+
*
|
|
2755
|
+
* @example
|
|
2756
|
+
* const restricted = perms.deny('members.kick')
|
|
2757
|
+
*/
|
|
2758
|
+
deny(...permissions: string[]): PermissionsBitfield;
|
|
2759
|
+
/**
|
|
2760
|
+
* Merge another record or `PermissionsBitfield` on top of this one.
|
|
2761
|
+
* The incoming values **override** any existing ones.
|
|
2762
|
+
*
|
|
2763
|
+
* @example
|
|
2764
|
+
* const merged = serverPerms.merge(channelOverrides)
|
|
2765
|
+
*/
|
|
2766
|
+
merge(other: Record<string, boolean> | PermissionsBitfield): PermissionsBitfield;
|
|
2767
|
+
/**
|
|
2768
|
+
* Returns an array of the permission keys that are **currently granted**.
|
|
2769
|
+
*
|
|
2770
|
+
* @example
|
|
2771
|
+
* perms.toArray() // ['messages.read', 'messages.write']
|
|
2772
|
+
*/
|
|
2773
|
+
toArray(): string[];
|
|
2774
|
+
/**
|
|
2775
|
+
* Returns the raw `Record<string, boolean>` map.
|
|
2776
|
+
*/
|
|
2777
|
+
toRecord(): Record<string, boolean>;
|
|
2778
|
+
/**
|
|
2779
|
+
* Pretty-print the granted permissions.
|
|
2780
|
+
*
|
|
2781
|
+
* @example
|
|
2782
|
+
* console.log(String(perms)) // 'PermissionsBitfield[messages.read, messages.write]'
|
|
2783
|
+
*/
|
|
2784
|
+
toString(): string;
|
|
2785
|
+
/** Create a `PermissionsBitfield` from an existing record. */
|
|
2786
|
+
static from(perms: Record<string, boolean>): PermissionsBitfield;
|
|
2787
|
+
/** A `PermissionsBitfield` with all known permissions granted. */
|
|
2788
|
+
static readonly ALL: PermissionsBitfield;
|
|
2789
|
+
/** A `PermissionsBitfield` with no permissions granted. */
|
|
2790
|
+
static readonly NONE: PermissionsBitfield;
|
|
2791
|
+
}
|
|
2792
|
+
|
|
2793
|
+
/**
|
|
2794
|
+
* Returns a promise that resolves after `ms` milliseconds.
|
|
2795
|
+
* Useful in retry loops, cron tasks, and staged sends.
|
|
2796
|
+
*
|
|
2797
|
+
* @example
|
|
2798
|
+
* await sleep(2_000) // wait 2 seconds
|
|
2799
|
+
*/
|
|
2800
|
+
declare function sleep(ms: number): Promise<void>;
|
|
2801
|
+
/**
|
|
2802
|
+
* Wraps a promise with a timeout — rejects with an error if the original
|
|
2803
|
+
* promise does not resolve within `ms` milliseconds.
|
|
2804
|
+
*
|
|
2805
|
+
* @example
|
|
2806
|
+
* const result = await withTimeout(fetchData(), 5_000, 'fetchData took too long')
|
|
2807
|
+
*/
|
|
2808
|
+
declare function withTimeout<T>(promise: Promise<T>, ms: number, message?: string): Promise<T>;
|
|
2809
|
+
/**
|
|
2810
|
+
* Format a duration in milliseconds to a compact human-readable string.
|
|
2811
|
+
*
|
|
2812
|
+
* @example
|
|
2813
|
+
* formatDuration(0) // '0s'
|
|
2814
|
+
* formatDuration(90_000) // '1m 30s'
|
|
2815
|
+
* formatDuration(3_661_000) // '1h 1m 1s'
|
|
2816
|
+
* formatDuration(604_800_000) // '1w'
|
|
2817
|
+
*/
|
|
2818
|
+
declare function formatDuration(ms: number): string;
|
|
2819
|
+
/**
|
|
2820
|
+
* Format a timestamp as a relative human-readable string from now.
|
|
2821
|
+
* Accepts a `Date`, a Unix timestamp (ms), or an ISO date string.
|
|
2822
|
+
*
|
|
2823
|
+
* @example
|
|
2824
|
+
* formatRelative(Date.now() - 5_000) // 'just now'
|
|
2825
|
+
* formatRelative(Date.now() - 90_000) // '1 minute ago'
|
|
2826
|
+
* formatRelative(Date.now() + 60_000) // 'in 1 minute'
|
|
2827
|
+
* formatRelative(Date.now() - 86_400_000) // 'yesterday'
|
|
2828
|
+
*/
|
|
2829
|
+
declare function formatRelative(timestamp: Date | number | string): string;
|
|
2830
|
+
/**
|
|
2831
|
+
* Safely parse any timestamp (ISO string, Unix ms, or Date) to a `Date`.
|
|
2832
|
+
* Returns `null` if the input is nullish or not parseable.
|
|
2833
|
+
*
|
|
2834
|
+
* @example
|
|
2835
|
+
* parseTimestamp('2026-01-01T00:00:00.000Z') // Date
|
|
2836
|
+
* parseTimestamp(null) // null
|
|
2837
|
+
*/
|
|
2838
|
+
declare function parseTimestamp(value: string | number | Date | null | undefined): Date | null;
|
|
2839
|
+
/**
|
|
2840
|
+
* Returns the remaining time until a target date as an object with components.
|
|
2841
|
+
* All values are `0` if the target is in the past.
|
|
2842
|
+
*
|
|
2843
|
+
* @example
|
|
2844
|
+
* const { days, hours, minutes, seconds } = countdown(new Date('2027-01-01'))
|
|
2845
|
+
* console.log(`${days}d ${hours}h ${minutes}m ${seconds}s remaining`)
|
|
2846
|
+
*/
|
|
2847
|
+
declare function countdown(target: Date | number | string): {
|
|
2848
|
+
weeks: number;
|
|
2849
|
+
days: number;
|
|
2850
|
+
hours: number;
|
|
2851
|
+
minutes: number;
|
|
2852
|
+
seconds: number;
|
|
2853
|
+
total: number;
|
|
2854
|
+
};
|
|
2855
|
+
|
|
2856
|
+
export { ActionRowBuilder, type Attachment, type BanEntry, type BotApplication, type BotEvent, type BotEventType, type BotModalDefinition, type BotModalField, type BotPermissionRecord, type BotStatus, type BotUser, ButtonBuilder, type ButtonStyle, type Channel, type ChannelType, ChannelsAPI, Collection, CommandsAPI, type ContextCommandDefinition, Cooldown, CooldownManager, type CreateChannelOptions, type DirectMessage, type EditChannelOptions, type EditMessageOptions, type Embed, EmbedBuilder, type EmbedField, type FetchChannelsOptions, type FetchMembersOptions, type FetchMessagesOptions, HttpClient, type Interaction, InteractionOptions, type InteractionType, InteractionsAPI, type Invite, Logger, type Member, MembersAPI, type Message, MessageBuilder, type MessageComponent, MessagesAPI, ModalBuilder, NovaChannel, NovaClient, type NovaClientEvents, type NovaClientOptions, NovaInteraction, NovaMember, NovaMessage, type NovaServer, 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, SelectMenuBuilder, type SelectMenuOption, type SendMessageOptions, ServersAPI, SlashCommandBuilder, type SlashCommandDefinition, type SlashCommandOption, SlashCommandOptionBuilder, TextInputBuilder, type TextInputStyle, type VoiceState, countdown, formatDuration, formatRelative, parseTimestamp, sleep, withTimeout };
|