@fluxerjs/core 1.2.1 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +78 -12
- package/dist/index.d.ts +78 -12
- package/dist/index.js +144 -59
- package/dist/index.mjs +117 -32
- package/package.json +7 -7
package/dist/index.d.mts
CHANGED
|
@@ -9,6 +9,12 @@ export { AttachmentBuilder, EmbedBuilder, MessagePayload } from '@fluxerjs/build
|
|
|
9
9
|
import { PermissionResolvable } from '@fluxerjs/util';
|
|
10
10
|
export { PermissionFlags, PermissionResolvable, PermissionString, PermissionsBitField, UserFlagsBitField, UserFlagsBits, UserFlagsResolvable, UserFlagsString, parsePrefixCommand, parseUserMention, resolvePermissionsToBitfield, resolveTenorToImageUrl } from '@fluxerjs/util';
|
|
11
11
|
|
|
12
|
+
/** Resolved file data (after URL fetch). Used internally by REST layer. */
|
|
13
|
+
interface ResolvedMessageFile {
|
|
14
|
+
name: string;
|
|
15
|
+
data: Blob | ArrayBuffer | Uint8Array | Buffer;
|
|
16
|
+
filename?: string;
|
|
17
|
+
}
|
|
12
18
|
/** File data for message attachment uploads. Use `data` for buffers or `url` to fetch from a URL. */
|
|
13
19
|
type MessageFileData = {
|
|
14
20
|
name: string;
|
|
@@ -31,7 +37,7 @@ interface MessageAttachmentMeta {
|
|
|
31
37
|
/** Options for sending a message (content, embeds, files). Used by Message.send, Channel.send, ChannelManager.send.
|
|
32
38
|
* EmbedBuilder instances are auto-converted to API format—no need to call .toJSON().
|
|
33
39
|
*/
|
|
34
|
-
type MessageSendOptions =
|
|
40
|
+
type MessageSendOptions = {
|
|
35
41
|
content?: string;
|
|
36
42
|
/** EmbedBuilder instances are auto-converted; raw APIEmbed also supported. */
|
|
37
43
|
embeds?: (APIEmbed | EmbedBuilder)[];
|
|
@@ -40,6 +46,18 @@ type MessageSendOptions = string | {
|
|
|
40
46
|
/** Attachment metadata for files (id = index). Use when files are provided. */
|
|
41
47
|
attachments?: MessageAttachmentMeta[];
|
|
42
48
|
};
|
|
49
|
+
/** API-ready body from MessageSendOptions (serializes EmbedBuilder, includes attachments when files present). */
|
|
50
|
+
interface SendBodyResult {
|
|
51
|
+
content?: string;
|
|
52
|
+
embeds?: APIEmbed[];
|
|
53
|
+
attachments?: Array<{
|
|
54
|
+
id: number;
|
|
55
|
+
filename: string;
|
|
56
|
+
title?: string | null;
|
|
57
|
+
description?: string | null;
|
|
58
|
+
flags?: number;
|
|
59
|
+
}>;
|
|
60
|
+
}
|
|
43
61
|
|
|
44
62
|
/** Base class for all Fluxer structures. Provides the client reference. */
|
|
45
63
|
declare abstract class Base {
|
|
@@ -908,6 +926,12 @@ interface MessageEditOptions {
|
|
|
908
926
|
/** New embeds (replaces existing) */
|
|
909
927
|
embeds?: (APIEmbed | EmbedBuilder)[];
|
|
910
928
|
}
|
|
929
|
+
type MessagePayload = {
|
|
930
|
+
files?: ResolvedMessageFile[];
|
|
931
|
+
body: SendBodyResult & {
|
|
932
|
+
referenced_message?: APIMessageReference;
|
|
933
|
+
};
|
|
934
|
+
};
|
|
911
935
|
|
|
912
936
|
/** Represents a message in a channel. */
|
|
913
937
|
declare class Message extends Base {
|
|
@@ -940,8 +964,11 @@ declare class Message extends Base {
|
|
|
940
964
|
readonly mentionRoles: string[];
|
|
941
965
|
/** Client-side nonce for acknowledgment. Null if not provided. */
|
|
942
966
|
readonly nonce: string | null;
|
|
943
|
-
/**
|
|
944
|
-
|
|
967
|
+
/**
|
|
968
|
+
* Channel where this message was sent. Resolved from cache; null if not cached.
|
|
969
|
+
* Messages can only exist in text-based channels (text, DM, announcement), so this always has send() when non-null.
|
|
970
|
+
*/
|
|
971
|
+
get channel(): (TextChannel | DMChannel | GuildChannel) | null;
|
|
945
972
|
/** Guild where this message was sent. Resolved from cache; null for DMs or if not cached. */
|
|
946
973
|
get guild(): Guild | null;
|
|
947
974
|
/**
|
|
@@ -965,7 +992,7 @@ declare class Message extends Base {
|
|
|
965
992
|
* await message.send({ embeds: [embed] }); // EmbedBuilder auto-converted
|
|
966
993
|
* await message.send({ content: 'File', files: [{ name: 'data.txt', data }] });
|
|
967
994
|
*/
|
|
968
|
-
send(options: MessageSendOptions): Promise<Message>;
|
|
995
|
+
send(options: string | MessageSendOptions): Promise<Message>;
|
|
969
996
|
/**
|
|
970
997
|
* Send a message to a specific channel. Use for logging, forwarding, or sending to another channel in the guild.
|
|
971
998
|
* @param channelId - Snowflake of the target channel (e.g. log channel ID)
|
|
@@ -982,7 +1009,14 @@ declare class Message extends Base {
|
|
|
982
1009
|
* await message.reply('Pong!');
|
|
983
1010
|
* await message.reply({ embeds: [embed] });
|
|
984
1011
|
*/
|
|
985
|
-
reply(options: MessageSendOptions): Promise<Message>;
|
|
1012
|
+
reply(options: string | MessageSendOptions): Promise<Message>;
|
|
1013
|
+
/** Exposed for testing purposes, use Message.reply() or send() for normal use */
|
|
1014
|
+
static _createMessageBody(content: string | MessageSendOptions, referenced_message?: {
|
|
1015
|
+
channel_id: string;
|
|
1016
|
+
message_id: string;
|
|
1017
|
+
guild_id?: string;
|
|
1018
|
+
}): Promise<MessagePayload>;
|
|
1019
|
+
_send(payload: MessagePayload): Promise<Message>;
|
|
986
1020
|
/**
|
|
987
1021
|
* Edit this message. Only the author (or admins) can edit.
|
|
988
1022
|
* @param options - New content and/or embeds
|
|
@@ -1162,11 +1196,12 @@ declare class Invite extends Base {
|
|
|
1162
1196
|
/** Base class for all channel types. */
|
|
1163
1197
|
declare abstract class Channel extends Base {
|
|
1164
1198
|
/** Whether this channel has a send method (TextChannel, DMChannel). */
|
|
1165
|
-
|
|
1199
|
+
isTextBased(): this is TextChannel | DMChannel;
|
|
1166
1200
|
/** Whether this channel is a DM or Group DM. */
|
|
1167
|
-
isDM():
|
|
1201
|
+
isDM(): this is DMChannel;
|
|
1168
1202
|
/** Whether this channel is voice-based (VoiceChannel). */
|
|
1169
|
-
isVoice():
|
|
1203
|
+
isVoice(): this is VoiceChannel;
|
|
1204
|
+
isLink(): this is LinkChannel;
|
|
1170
1205
|
/** Create a DM channel from API data (type DM or GroupDM). */
|
|
1171
1206
|
static createDM(client: Client, data: APIChannelPartial): DMChannel;
|
|
1172
1207
|
readonly client: Client;
|
|
@@ -1200,6 +1235,12 @@ declare abstract class Channel extends Base {
|
|
|
1200
1235
|
* Send a typing indicator to the channel. Lasts ~10 seconds.
|
|
1201
1236
|
*/
|
|
1202
1237
|
sendTyping(): Promise<void>;
|
|
1238
|
+
/**
|
|
1239
|
+
* Whether the bot can send messages in this channel.
|
|
1240
|
+
* For DMs: always true (when the channel exists).
|
|
1241
|
+
* For guild channels: checks ViewChannel and SendMessages permissions via guild.members.me.
|
|
1242
|
+
*/
|
|
1243
|
+
canSendMessage(): boolean;
|
|
1203
1244
|
}
|
|
1204
1245
|
declare class GuildChannel extends Channel {
|
|
1205
1246
|
readonly guildId: string;
|
|
@@ -1249,6 +1290,17 @@ declare class GuildChannel extends Channel {
|
|
|
1249
1290
|
allow?: string;
|
|
1250
1291
|
deny?: string;
|
|
1251
1292
|
}): Promise<void>;
|
|
1293
|
+
/**
|
|
1294
|
+
* Whether the bot can send messages in this channel.
|
|
1295
|
+
* Checks ViewChannel and SendMessages via guild.members.me permissions.
|
|
1296
|
+
* Returns false if guild or bot member not cached.
|
|
1297
|
+
*/
|
|
1298
|
+
canSendMessage(): boolean;
|
|
1299
|
+
/**
|
|
1300
|
+
* Send a message to this guild channel.
|
|
1301
|
+
* Works for text and announcement channels. Voice/category/link channels will fail at the API.
|
|
1302
|
+
*/
|
|
1303
|
+
send(options: MessageSendOptions): Promise<Message>;
|
|
1252
1304
|
/**
|
|
1253
1305
|
* Remove a permission overwrite. DELETE /channels/{id}/permissions/{overwriteId}.
|
|
1254
1306
|
*/
|
|
@@ -1326,7 +1378,7 @@ declare class VoiceChannel extends GuildChannel {
|
|
|
1326
1378
|
constructor(client: Client, data: APIChannel);
|
|
1327
1379
|
}
|
|
1328
1380
|
declare class LinkChannel extends GuildChannel {
|
|
1329
|
-
url
|
|
1381
|
+
url: string | null;
|
|
1330
1382
|
constructor(client: Client, data: APIChannel);
|
|
1331
1383
|
}
|
|
1332
1384
|
/** DM channel (direct message between bot and a user). */
|
|
@@ -1395,7 +1447,7 @@ declare class ChannelManager extends Collection<string, Channel | GuildChannel>
|
|
|
1395
1447
|
* @throws FluxerError with CHANNEL_NOT_FOUND if the channel does not exist
|
|
1396
1448
|
* @example
|
|
1397
1449
|
* const channel = await client.channels.resolve(message.channelId);
|
|
1398
|
-
* if (channel?.
|
|
1450
|
+
* if (channel?.isTextBased()) await channel.send('Hello!');
|
|
1399
1451
|
*/
|
|
1400
1452
|
resolve(channelId: string): Promise<Channel>;
|
|
1401
1453
|
/**
|
|
@@ -1405,7 +1457,7 @@ declare class ChannelManager extends Collection<string, Channel | GuildChannel>
|
|
|
1405
1457
|
* @throws FluxerError with CHANNEL_NOT_FOUND if the channel does not exist
|
|
1406
1458
|
* @example
|
|
1407
1459
|
* const channel = await client.channels.fetch(channelId);
|
|
1408
|
-
* if (channel?.
|
|
1460
|
+
* if (channel?.isTextBased()) await channel.send('Hello!');
|
|
1409
1461
|
*/
|
|
1410
1462
|
fetch(channelId: string): Promise<Channel>;
|
|
1411
1463
|
/**
|
|
@@ -1486,6 +1538,8 @@ interface ClientOptions {
|
|
|
1486
1538
|
intents?: number;
|
|
1487
1539
|
/** Suppress the warning when intents are set (Fluxer does not support intents yet). */
|
|
1488
1540
|
suppressIntentWarning?: boolean;
|
|
1541
|
+
/** When true, delay the Ready event until all guilds from READY (including unavailable) have been received via GUILD_CREATE. Default: false. */
|
|
1542
|
+
waitForGuilds?: boolean;
|
|
1489
1543
|
/** Cache size limits (channels, guilds, users). When exceeded, oldest entries are evicted. Omit or 0 = unbounded. */
|
|
1490
1544
|
cache?: CacheSizeLimits;
|
|
1491
1545
|
/** Initial presence (status, custom_status, etc.) sent on identify. Can also update via PresenceUpdate after connect. */
|
|
@@ -1720,6 +1774,8 @@ declare class Client extends EventEmitter {
|
|
|
1720
1774
|
/** Timestamp when the client became ready. Null until READY is received. */
|
|
1721
1775
|
readyAt: Date | null;
|
|
1722
1776
|
private _ws;
|
|
1777
|
+
/** When waitForGuilds, set of guild IDs we're waiting for GUILD_CREATE on. Null when not waiting. */
|
|
1778
|
+
_pendingGuildIds: Set<string> | null;
|
|
1723
1779
|
/** @param options - Token, REST config, WebSocket, presence, etc. */
|
|
1724
1780
|
constructor(options?: ClientOptions);
|
|
1725
1781
|
/**
|
|
@@ -1763,7 +1819,7 @@ declare class Client extends EventEmitter {
|
|
|
1763
1819
|
* Send a message to any channel by ID. Shorthand for client.channels.send().
|
|
1764
1820
|
* Works even when the channel is not cached.
|
|
1765
1821
|
*/
|
|
1766
|
-
sendToChannel(channelId: string,
|
|
1822
|
+
sendToChannel(channelId: string, content: string | {
|
|
1767
1823
|
content?: string;
|
|
1768
1824
|
embeds?: APIEmbed[];
|
|
1769
1825
|
}): Promise<Message>;
|
|
@@ -1786,6 +1842,16 @@ declare class Client extends EventEmitter {
|
|
|
1786
1842
|
* @param token - Bot token (e.g. from FLUXER_BOT_TOKEN)
|
|
1787
1843
|
*/
|
|
1788
1844
|
login(token: string): Promise<string>;
|
|
1845
|
+
/**
|
|
1846
|
+
* Called when all guilds have been received (or immediately if not waiting).
|
|
1847
|
+
* Sets readyAt, emits Ready, clears pending state.
|
|
1848
|
+
*/
|
|
1849
|
+
_finalizeReady(): void;
|
|
1850
|
+
/**
|
|
1851
|
+
* Called by GUILD_CREATE handler when waitForGuilds is enabled.
|
|
1852
|
+
* Removes guild from pending set; when empty, finalizes ready.
|
|
1853
|
+
*/
|
|
1854
|
+
_onGuildReceived(guildId: string): void;
|
|
1789
1855
|
/** Disconnect from the gateway and clear cached data. */
|
|
1790
1856
|
destroy(): Promise<void>;
|
|
1791
1857
|
/** Returns true if the client has received Ready and `user` is set. */
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,12 @@ export { AttachmentBuilder, EmbedBuilder, MessagePayload } from '@fluxerjs/build
|
|
|
9
9
|
import { PermissionResolvable } from '@fluxerjs/util';
|
|
10
10
|
export { PermissionFlags, PermissionResolvable, PermissionString, PermissionsBitField, UserFlagsBitField, UserFlagsBits, UserFlagsResolvable, UserFlagsString, parsePrefixCommand, parseUserMention, resolvePermissionsToBitfield, resolveTenorToImageUrl } from '@fluxerjs/util';
|
|
11
11
|
|
|
12
|
+
/** Resolved file data (after URL fetch). Used internally by REST layer. */
|
|
13
|
+
interface ResolvedMessageFile {
|
|
14
|
+
name: string;
|
|
15
|
+
data: Blob | ArrayBuffer | Uint8Array | Buffer;
|
|
16
|
+
filename?: string;
|
|
17
|
+
}
|
|
12
18
|
/** File data for message attachment uploads. Use `data` for buffers or `url` to fetch from a URL. */
|
|
13
19
|
type MessageFileData = {
|
|
14
20
|
name: string;
|
|
@@ -31,7 +37,7 @@ interface MessageAttachmentMeta {
|
|
|
31
37
|
/** Options for sending a message (content, embeds, files). Used by Message.send, Channel.send, ChannelManager.send.
|
|
32
38
|
* EmbedBuilder instances are auto-converted to API format—no need to call .toJSON().
|
|
33
39
|
*/
|
|
34
|
-
type MessageSendOptions =
|
|
40
|
+
type MessageSendOptions = {
|
|
35
41
|
content?: string;
|
|
36
42
|
/** EmbedBuilder instances are auto-converted; raw APIEmbed also supported. */
|
|
37
43
|
embeds?: (APIEmbed | EmbedBuilder)[];
|
|
@@ -40,6 +46,18 @@ type MessageSendOptions = string | {
|
|
|
40
46
|
/** Attachment metadata for files (id = index). Use when files are provided. */
|
|
41
47
|
attachments?: MessageAttachmentMeta[];
|
|
42
48
|
};
|
|
49
|
+
/** API-ready body from MessageSendOptions (serializes EmbedBuilder, includes attachments when files present). */
|
|
50
|
+
interface SendBodyResult {
|
|
51
|
+
content?: string;
|
|
52
|
+
embeds?: APIEmbed[];
|
|
53
|
+
attachments?: Array<{
|
|
54
|
+
id: number;
|
|
55
|
+
filename: string;
|
|
56
|
+
title?: string | null;
|
|
57
|
+
description?: string | null;
|
|
58
|
+
flags?: number;
|
|
59
|
+
}>;
|
|
60
|
+
}
|
|
43
61
|
|
|
44
62
|
/** Base class for all Fluxer structures. Provides the client reference. */
|
|
45
63
|
declare abstract class Base {
|
|
@@ -908,6 +926,12 @@ interface MessageEditOptions {
|
|
|
908
926
|
/** New embeds (replaces existing) */
|
|
909
927
|
embeds?: (APIEmbed | EmbedBuilder)[];
|
|
910
928
|
}
|
|
929
|
+
type MessagePayload = {
|
|
930
|
+
files?: ResolvedMessageFile[];
|
|
931
|
+
body: SendBodyResult & {
|
|
932
|
+
referenced_message?: APIMessageReference;
|
|
933
|
+
};
|
|
934
|
+
};
|
|
911
935
|
|
|
912
936
|
/** Represents a message in a channel. */
|
|
913
937
|
declare class Message extends Base {
|
|
@@ -940,8 +964,11 @@ declare class Message extends Base {
|
|
|
940
964
|
readonly mentionRoles: string[];
|
|
941
965
|
/** Client-side nonce for acknowledgment. Null if not provided. */
|
|
942
966
|
readonly nonce: string | null;
|
|
943
|
-
/**
|
|
944
|
-
|
|
967
|
+
/**
|
|
968
|
+
* Channel where this message was sent. Resolved from cache; null if not cached.
|
|
969
|
+
* Messages can only exist in text-based channels (text, DM, announcement), so this always has send() when non-null.
|
|
970
|
+
*/
|
|
971
|
+
get channel(): (TextChannel | DMChannel | GuildChannel) | null;
|
|
945
972
|
/** Guild where this message was sent. Resolved from cache; null for DMs or if not cached. */
|
|
946
973
|
get guild(): Guild | null;
|
|
947
974
|
/**
|
|
@@ -965,7 +992,7 @@ declare class Message extends Base {
|
|
|
965
992
|
* await message.send({ embeds: [embed] }); // EmbedBuilder auto-converted
|
|
966
993
|
* await message.send({ content: 'File', files: [{ name: 'data.txt', data }] });
|
|
967
994
|
*/
|
|
968
|
-
send(options: MessageSendOptions): Promise<Message>;
|
|
995
|
+
send(options: string | MessageSendOptions): Promise<Message>;
|
|
969
996
|
/**
|
|
970
997
|
* Send a message to a specific channel. Use for logging, forwarding, or sending to another channel in the guild.
|
|
971
998
|
* @param channelId - Snowflake of the target channel (e.g. log channel ID)
|
|
@@ -982,7 +1009,14 @@ declare class Message extends Base {
|
|
|
982
1009
|
* await message.reply('Pong!');
|
|
983
1010
|
* await message.reply({ embeds: [embed] });
|
|
984
1011
|
*/
|
|
985
|
-
reply(options: MessageSendOptions): Promise<Message>;
|
|
1012
|
+
reply(options: string | MessageSendOptions): Promise<Message>;
|
|
1013
|
+
/** Exposed for testing purposes, use Message.reply() or send() for normal use */
|
|
1014
|
+
static _createMessageBody(content: string | MessageSendOptions, referenced_message?: {
|
|
1015
|
+
channel_id: string;
|
|
1016
|
+
message_id: string;
|
|
1017
|
+
guild_id?: string;
|
|
1018
|
+
}): Promise<MessagePayload>;
|
|
1019
|
+
_send(payload: MessagePayload): Promise<Message>;
|
|
986
1020
|
/**
|
|
987
1021
|
* Edit this message. Only the author (or admins) can edit.
|
|
988
1022
|
* @param options - New content and/or embeds
|
|
@@ -1162,11 +1196,12 @@ declare class Invite extends Base {
|
|
|
1162
1196
|
/** Base class for all channel types. */
|
|
1163
1197
|
declare abstract class Channel extends Base {
|
|
1164
1198
|
/** Whether this channel has a send method (TextChannel, DMChannel). */
|
|
1165
|
-
|
|
1199
|
+
isTextBased(): this is TextChannel | DMChannel;
|
|
1166
1200
|
/** Whether this channel is a DM or Group DM. */
|
|
1167
|
-
isDM():
|
|
1201
|
+
isDM(): this is DMChannel;
|
|
1168
1202
|
/** Whether this channel is voice-based (VoiceChannel). */
|
|
1169
|
-
isVoice():
|
|
1203
|
+
isVoice(): this is VoiceChannel;
|
|
1204
|
+
isLink(): this is LinkChannel;
|
|
1170
1205
|
/** Create a DM channel from API data (type DM or GroupDM). */
|
|
1171
1206
|
static createDM(client: Client, data: APIChannelPartial): DMChannel;
|
|
1172
1207
|
readonly client: Client;
|
|
@@ -1200,6 +1235,12 @@ declare abstract class Channel extends Base {
|
|
|
1200
1235
|
* Send a typing indicator to the channel. Lasts ~10 seconds.
|
|
1201
1236
|
*/
|
|
1202
1237
|
sendTyping(): Promise<void>;
|
|
1238
|
+
/**
|
|
1239
|
+
* Whether the bot can send messages in this channel.
|
|
1240
|
+
* For DMs: always true (when the channel exists).
|
|
1241
|
+
* For guild channels: checks ViewChannel and SendMessages permissions via guild.members.me.
|
|
1242
|
+
*/
|
|
1243
|
+
canSendMessage(): boolean;
|
|
1203
1244
|
}
|
|
1204
1245
|
declare class GuildChannel extends Channel {
|
|
1205
1246
|
readonly guildId: string;
|
|
@@ -1249,6 +1290,17 @@ declare class GuildChannel extends Channel {
|
|
|
1249
1290
|
allow?: string;
|
|
1250
1291
|
deny?: string;
|
|
1251
1292
|
}): Promise<void>;
|
|
1293
|
+
/**
|
|
1294
|
+
* Whether the bot can send messages in this channel.
|
|
1295
|
+
* Checks ViewChannel and SendMessages via guild.members.me permissions.
|
|
1296
|
+
* Returns false if guild or bot member not cached.
|
|
1297
|
+
*/
|
|
1298
|
+
canSendMessage(): boolean;
|
|
1299
|
+
/**
|
|
1300
|
+
* Send a message to this guild channel.
|
|
1301
|
+
* Works for text and announcement channels. Voice/category/link channels will fail at the API.
|
|
1302
|
+
*/
|
|
1303
|
+
send(options: MessageSendOptions): Promise<Message>;
|
|
1252
1304
|
/**
|
|
1253
1305
|
* Remove a permission overwrite. DELETE /channels/{id}/permissions/{overwriteId}.
|
|
1254
1306
|
*/
|
|
@@ -1326,7 +1378,7 @@ declare class VoiceChannel extends GuildChannel {
|
|
|
1326
1378
|
constructor(client: Client, data: APIChannel);
|
|
1327
1379
|
}
|
|
1328
1380
|
declare class LinkChannel extends GuildChannel {
|
|
1329
|
-
url
|
|
1381
|
+
url: string | null;
|
|
1330
1382
|
constructor(client: Client, data: APIChannel);
|
|
1331
1383
|
}
|
|
1332
1384
|
/** DM channel (direct message between bot and a user). */
|
|
@@ -1395,7 +1447,7 @@ declare class ChannelManager extends Collection<string, Channel | GuildChannel>
|
|
|
1395
1447
|
* @throws FluxerError with CHANNEL_NOT_FOUND if the channel does not exist
|
|
1396
1448
|
* @example
|
|
1397
1449
|
* const channel = await client.channels.resolve(message.channelId);
|
|
1398
|
-
* if (channel?.
|
|
1450
|
+
* if (channel?.isTextBased()) await channel.send('Hello!');
|
|
1399
1451
|
*/
|
|
1400
1452
|
resolve(channelId: string): Promise<Channel>;
|
|
1401
1453
|
/**
|
|
@@ -1405,7 +1457,7 @@ declare class ChannelManager extends Collection<string, Channel | GuildChannel>
|
|
|
1405
1457
|
* @throws FluxerError with CHANNEL_NOT_FOUND if the channel does not exist
|
|
1406
1458
|
* @example
|
|
1407
1459
|
* const channel = await client.channels.fetch(channelId);
|
|
1408
|
-
* if (channel?.
|
|
1460
|
+
* if (channel?.isTextBased()) await channel.send('Hello!');
|
|
1409
1461
|
*/
|
|
1410
1462
|
fetch(channelId: string): Promise<Channel>;
|
|
1411
1463
|
/**
|
|
@@ -1486,6 +1538,8 @@ interface ClientOptions {
|
|
|
1486
1538
|
intents?: number;
|
|
1487
1539
|
/** Suppress the warning when intents are set (Fluxer does not support intents yet). */
|
|
1488
1540
|
suppressIntentWarning?: boolean;
|
|
1541
|
+
/** When true, delay the Ready event until all guilds from READY (including unavailable) have been received via GUILD_CREATE. Default: false. */
|
|
1542
|
+
waitForGuilds?: boolean;
|
|
1489
1543
|
/** Cache size limits (channels, guilds, users). When exceeded, oldest entries are evicted. Omit or 0 = unbounded. */
|
|
1490
1544
|
cache?: CacheSizeLimits;
|
|
1491
1545
|
/** Initial presence (status, custom_status, etc.) sent on identify. Can also update via PresenceUpdate after connect. */
|
|
@@ -1720,6 +1774,8 @@ declare class Client extends EventEmitter {
|
|
|
1720
1774
|
/** Timestamp when the client became ready. Null until READY is received. */
|
|
1721
1775
|
readyAt: Date | null;
|
|
1722
1776
|
private _ws;
|
|
1777
|
+
/** When waitForGuilds, set of guild IDs we're waiting for GUILD_CREATE on. Null when not waiting. */
|
|
1778
|
+
_pendingGuildIds: Set<string> | null;
|
|
1723
1779
|
/** @param options - Token, REST config, WebSocket, presence, etc. */
|
|
1724
1780
|
constructor(options?: ClientOptions);
|
|
1725
1781
|
/**
|
|
@@ -1763,7 +1819,7 @@ declare class Client extends EventEmitter {
|
|
|
1763
1819
|
* Send a message to any channel by ID. Shorthand for client.channels.send().
|
|
1764
1820
|
* Works even when the channel is not cached.
|
|
1765
1821
|
*/
|
|
1766
|
-
sendToChannel(channelId: string,
|
|
1822
|
+
sendToChannel(channelId: string, content: string | {
|
|
1767
1823
|
content?: string;
|
|
1768
1824
|
embeds?: APIEmbed[];
|
|
1769
1825
|
}): Promise<Message>;
|
|
@@ -1786,6 +1842,16 @@ declare class Client extends EventEmitter {
|
|
|
1786
1842
|
* @param token - Bot token (e.g. from FLUXER_BOT_TOKEN)
|
|
1787
1843
|
*/
|
|
1788
1844
|
login(token: string): Promise<string>;
|
|
1845
|
+
/**
|
|
1846
|
+
* Called when all guilds have been received (or immediately if not waiting).
|
|
1847
|
+
* Sets readyAt, emits Ready, clears pending state.
|
|
1848
|
+
*/
|
|
1849
|
+
_finalizeReady(): void;
|
|
1850
|
+
/**
|
|
1851
|
+
* Called by GUILD_CREATE handler when waitForGuilds is enabled.
|
|
1852
|
+
* Removes guild from pending set; when empty, finalizes ready.
|
|
1853
|
+
*/
|
|
1854
|
+
_onGuildReceived(guildId: string): void;
|
|
1789
1855
|
/** Disconnect from the gateway and clear cached data. */
|
|
1790
1856
|
destroy(): Promise<void>;
|
|
1791
1857
|
/** Returns true if the client has received Ready and `user` is set. */
|
package/dist/index.js
CHANGED
|
@@ -50,16 +50,16 @@ __export(index_exports, {
|
|
|
50
50
|
MessageManager: () => MessageManager,
|
|
51
51
|
MessagePayload: () => import_builders3.MessagePayload,
|
|
52
52
|
MessageReaction: () => MessageReaction,
|
|
53
|
-
PermissionFlags: () =>
|
|
54
|
-
PermissionsBitField: () =>
|
|
53
|
+
PermissionFlags: () => import_util10.PermissionFlags,
|
|
54
|
+
PermissionsBitField: () => import_util10.PermissionsBitField,
|
|
55
55
|
ReactionCollector: () => ReactionCollector,
|
|
56
56
|
Role: () => Role,
|
|
57
57
|
Routes: () => import_types22.Routes,
|
|
58
58
|
STATIC_CDN_URL: () => STATIC_CDN_URL,
|
|
59
59
|
TextChannel: () => TextChannel,
|
|
60
60
|
User: () => User,
|
|
61
|
-
UserFlagsBitField: () =>
|
|
62
|
-
UserFlagsBits: () =>
|
|
61
|
+
UserFlagsBitField: () => import_util10.UserFlagsBitField,
|
|
62
|
+
UserFlagsBits: () => import_util10.UserFlagsBits,
|
|
63
63
|
UsersManager: () => UsersManager,
|
|
64
64
|
VoiceChannel: () => VoiceChannel,
|
|
65
65
|
Webhook: () => Webhook,
|
|
@@ -69,10 +69,10 @@ __export(index_exports, {
|
|
|
69
69
|
cdnDisplayAvatarURL: () => cdnDisplayAvatarURL,
|
|
70
70
|
cdnMemberAvatarURL: () => cdnMemberAvatarURL,
|
|
71
71
|
cdnMemberBannerURL: () => cdnMemberBannerURL,
|
|
72
|
-
parsePrefixCommand: () =>
|
|
73
|
-
parseUserMention: () =>
|
|
74
|
-
resolvePermissionsToBitfield: () =>
|
|
75
|
-
resolveTenorToImageUrl: () =>
|
|
72
|
+
parsePrefixCommand: () => import_util9.parsePrefixCommand,
|
|
73
|
+
parseUserMention: () => import_util9.parseUserMention,
|
|
74
|
+
resolvePermissionsToBitfield: () => import_util10.resolvePermissionsToBitfield,
|
|
75
|
+
resolveTenorToImageUrl: () => import_util9.resolveTenorToImageUrl
|
|
76
76
|
});
|
|
77
77
|
module.exports = __toCommonJS(index_exports);
|
|
78
78
|
|
|
@@ -85,7 +85,7 @@ var import_types21 = require("@fluxerjs/types");
|
|
|
85
85
|
// src/client/ChannelManager.ts
|
|
86
86
|
var import_collection4 = require("@fluxerjs/collection");
|
|
87
87
|
var import_types6 = require("@fluxerjs/types");
|
|
88
|
-
var
|
|
88
|
+
var import_util3 = require("@fluxerjs/util");
|
|
89
89
|
var import_rest2 = require("@fluxerjs/rest");
|
|
90
90
|
|
|
91
91
|
// src/errors/FluxerError.ts
|
|
@@ -313,7 +313,10 @@ var Message = class _Message extends Base {
|
|
|
313
313
|
mentionRoles;
|
|
314
314
|
/** Client-side nonce for acknowledgment. Null if not provided. */
|
|
315
315
|
nonce;
|
|
316
|
-
/**
|
|
316
|
+
/**
|
|
317
|
+
* Channel where this message was sent. Resolved from cache; null if not cached.
|
|
318
|
+
* Messages can only exist in text-based channels (text, DM, announcement), so this always has send() when non-null.
|
|
319
|
+
*/
|
|
317
320
|
get channel() {
|
|
318
321
|
return this.client.channels.get(this.channelId) ?? null;
|
|
319
322
|
}
|
|
@@ -375,12 +378,8 @@ var Message = class _Message extends Base {
|
|
|
375
378
|
* await message.send({ content: 'File', files: [{ name: 'data.txt', data }] });
|
|
376
379
|
*/
|
|
377
380
|
async send(options) {
|
|
378
|
-
const
|
|
379
|
-
|
|
380
|
-
const files = opts.files?.length ? await resolveMessageFiles(opts.files) : void 0;
|
|
381
|
-
const postOptions = files?.length ? { body, files } : { body };
|
|
382
|
-
const data = await this.client.rest.post(import_types.Routes.channelMessages(this.channelId), postOptions);
|
|
383
|
-
return new _Message(this.client, data);
|
|
381
|
+
const payload = await _Message._createMessageBody(options);
|
|
382
|
+
return this._send(payload);
|
|
384
383
|
}
|
|
385
384
|
/**
|
|
386
385
|
* Send a message to a specific channel. Use for logging, forwarding, or sending to another channel in the guild.
|
|
@@ -401,19 +400,30 @@ var Message = class _Message extends Base {
|
|
|
401
400
|
* await message.reply({ embeds: [embed] });
|
|
402
401
|
*/
|
|
403
402
|
async reply(options) {
|
|
404
|
-
const
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
403
|
+
const payload = await _Message._createMessageBody(options, {
|
|
404
|
+
channel_id: this.channelId,
|
|
405
|
+
message_id: this.id,
|
|
406
|
+
guild_id: this.guildId ?? void 0
|
|
407
|
+
});
|
|
408
|
+
return this._send(payload);
|
|
409
|
+
}
|
|
410
|
+
/** Exposed for testing purposes, use Message.reply() or send() for normal use */
|
|
411
|
+
static async _createMessageBody(content, referenced_message) {
|
|
412
|
+
if (typeof content === "string") {
|
|
413
|
+
if (content.length === 0) {
|
|
414
|
+
throw new RangeError("Cannot send an empty message");
|
|
412
415
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
const
|
|
416
|
-
const
|
|
416
|
+
content = { content };
|
|
417
|
+
}
|
|
418
|
+
const base = buildSendBody(content);
|
|
419
|
+
const files = content.files?.length ? await resolveMessageFiles(content.files) : void 0;
|
|
420
|
+
return referenced_message ? { files, body: { ...base, referenced_message } } : { files, body: { ...base } };
|
|
421
|
+
}
|
|
422
|
+
async _send(payload) {
|
|
423
|
+
const data = await this.client.rest.post(
|
|
424
|
+
import_types.Routes.channelMessages(this.channelId),
|
|
425
|
+
payload
|
|
426
|
+
);
|
|
417
427
|
return new _Message(this.client, data);
|
|
418
428
|
}
|
|
419
429
|
/**
|
|
@@ -630,6 +640,7 @@ var MessageCollector = class extends import_events2.EventEmitter {
|
|
|
630
640
|
// src/structures/Channel.ts
|
|
631
641
|
var import_types5 = require("@fluxerjs/types");
|
|
632
642
|
var import_util = require("@fluxerjs/util");
|
|
643
|
+
var import_util2 = require("@fluxerjs/util");
|
|
633
644
|
|
|
634
645
|
// src/structures/Webhook.ts
|
|
635
646
|
var import_types3 = require("@fluxerjs/types");
|
|
@@ -764,7 +775,7 @@ var Webhook = class _Webhook extends Base {
|
|
|
764
775
|
);
|
|
765
776
|
}
|
|
766
777
|
const opts = typeof options === "string" ? { content: options } : options;
|
|
767
|
-
const body = buildSendBody(
|
|
778
|
+
const body = buildSendBody(opts);
|
|
768
779
|
if (opts.username !== void 0) body.username = opts.username;
|
|
769
780
|
if (opts.avatar_url !== void 0) body.avatar_url = opts.avatar_url;
|
|
770
781
|
if (opts.tts !== void 0) body.tts = opts.tts;
|
|
@@ -865,7 +876,7 @@ var Invite = class extends Base {
|
|
|
865
876
|
// src/structures/Channel.ts
|
|
866
877
|
var Channel = class _Channel extends Base {
|
|
867
878
|
/** Whether this channel has a send method (TextChannel, DMChannel). */
|
|
868
|
-
|
|
879
|
+
isTextBased() {
|
|
869
880
|
return "send" in this;
|
|
870
881
|
}
|
|
871
882
|
/** Whether this channel is a DM or Group DM. */
|
|
@@ -876,6 +887,9 @@ var Channel = class _Channel extends Base {
|
|
|
876
887
|
isVoice() {
|
|
877
888
|
return "bitrate" in this;
|
|
878
889
|
}
|
|
890
|
+
isLink() {
|
|
891
|
+
return "url" in this;
|
|
892
|
+
}
|
|
879
893
|
/** Create a DM channel from API data (type DM or GroupDM). */
|
|
880
894
|
static createDM(client, data) {
|
|
881
895
|
return new DMChannel(client, data);
|
|
@@ -939,6 +953,15 @@ var Channel = class _Channel extends Base {
|
|
|
939
953
|
async sendTyping() {
|
|
940
954
|
await this.client.rest.post(import_types5.Routes.channelTyping(this.id), { auth: true });
|
|
941
955
|
}
|
|
956
|
+
/**
|
|
957
|
+
* Whether the bot can send messages in this channel.
|
|
958
|
+
* For DMs: always true (when the channel exists).
|
|
959
|
+
* For guild channels: checks ViewChannel and SendMessages permissions via guild.members.me.
|
|
960
|
+
*/
|
|
961
|
+
canSendMessage() {
|
|
962
|
+
if (this.isDM()) return true;
|
|
963
|
+
return false;
|
|
964
|
+
}
|
|
942
965
|
};
|
|
943
966
|
var GuildChannel = class extends Channel {
|
|
944
967
|
guildId;
|
|
@@ -1022,6 +1045,31 @@ var GuildChannel = class extends Channel {
|
|
|
1022
1045
|
if (idx >= 0) this.permissionOverwrites[idx] = entry;
|
|
1023
1046
|
else this.permissionOverwrites.push(entry);
|
|
1024
1047
|
}
|
|
1048
|
+
/**
|
|
1049
|
+
* Whether the bot can send messages in this channel.
|
|
1050
|
+
* Checks ViewChannel and SendMessages via guild.members.me permissions.
|
|
1051
|
+
* Returns false if guild or bot member not cached.
|
|
1052
|
+
*/
|
|
1053
|
+
canSendMessage() {
|
|
1054
|
+
const guild = this.client.guilds.get(this.guildId);
|
|
1055
|
+
if (!guild) return false;
|
|
1056
|
+
const me = guild.members.me;
|
|
1057
|
+
if (!me) return false;
|
|
1058
|
+
const perms = me.permissionsIn(this);
|
|
1059
|
+
return perms.has(import_util.PermissionFlags.ViewChannel) && perms.has(import_util.PermissionFlags.SendMessages);
|
|
1060
|
+
}
|
|
1061
|
+
/**
|
|
1062
|
+
* Send a message to this guild channel.
|
|
1063
|
+
* Works for text and announcement channels. Voice/category/link channels will fail at the API.
|
|
1064
|
+
*/
|
|
1065
|
+
async send(options) {
|
|
1066
|
+
const opts = typeof options === "string" ? { content: options } : options;
|
|
1067
|
+
const body = buildSendBody(options);
|
|
1068
|
+
const files = opts.files?.length ? await resolveMessageFiles(opts.files) : void 0;
|
|
1069
|
+
const postOptions = files?.length ? { body, files } : { body };
|
|
1070
|
+
const data = await this.client.rest.post(import_types5.Routes.channelMessages(this.id), postOptions);
|
|
1071
|
+
return new Message(this.client, data);
|
|
1072
|
+
}
|
|
1025
1073
|
/**
|
|
1026
1074
|
* Remove a permission overwrite. DELETE /channels/{id}/permissions/{overwriteId}.
|
|
1027
1075
|
*/
|
|
@@ -1122,7 +1170,7 @@ var TextChannel = class extends GuildChannel {
|
|
|
1122
1170
|
* @deprecated Use channel.messages.fetch(messageId) instead.
|
|
1123
1171
|
*/
|
|
1124
1172
|
async fetchMessage(messageId) {
|
|
1125
|
-
(0,
|
|
1173
|
+
(0, import_util2.emitDeprecationWarning)(
|
|
1126
1174
|
"Channel.fetchMessage()",
|
|
1127
1175
|
"Use channel.messages.fetch(messageId) instead."
|
|
1128
1176
|
);
|
|
@@ -1208,7 +1256,7 @@ var DMChannel = class extends Channel {
|
|
|
1208
1256
|
* @deprecated Use channel.messages.fetch(messageId) instead.
|
|
1209
1257
|
*/
|
|
1210
1258
|
async fetchMessage(messageId) {
|
|
1211
|
-
(0,
|
|
1259
|
+
(0, import_util2.emitDeprecationWarning)(
|
|
1212
1260
|
"Channel.fetchMessage()",
|
|
1213
1261
|
"Use channel.messages.fetch(messageId) instead."
|
|
1214
1262
|
);
|
|
@@ -1259,7 +1307,7 @@ var ChannelManager = class extends import_collection4.Collection {
|
|
|
1259
1307
|
* @throws FluxerError with CHANNEL_NOT_FOUND if the channel does not exist
|
|
1260
1308
|
* @example
|
|
1261
1309
|
* const channel = await client.channels.resolve(message.channelId);
|
|
1262
|
-
* if (channel?.
|
|
1310
|
+
* if (channel?.isTextBased()) await channel.send('Hello!');
|
|
1263
1311
|
*/
|
|
1264
1312
|
async resolve(channelId) {
|
|
1265
1313
|
return this.get(channelId) ?? this.fetch(channelId);
|
|
@@ -1271,7 +1319,7 @@ var ChannelManager = class extends import_collection4.Collection {
|
|
|
1271
1319
|
* @throws FluxerError with CHANNEL_NOT_FOUND if the channel does not exist
|
|
1272
1320
|
* @example
|
|
1273
1321
|
* const channel = await client.channels.fetch(channelId);
|
|
1274
|
-
* if (channel?.
|
|
1322
|
+
* if (channel?.isTextBased()) await channel.send('Hello!');
|
|
1275
1323
|
*/
|
|
1276
1324
|
async fetch(channelId) {
|
|
1277
1325
|
const cached = this.get(channelId);
|
|
@@ -1313,7 +1361,7 @@ var ChannelManager = class extends import_collection4.Collection {
|
|
|
1313
1361
|
* const message = await channel?.messages?.fetch(messageId);
|
|
1314
1362
|
*/
|
|
1315
1363
|
async fetchMessage(channelId, messageId) {
|
|
1316
|
-
(0,
|
|
1364
|
+
(0, import_util3.emitDeprecationWarning)(
|
|
1317
1365
|
"ChannelManager.fetchMessage()",
|
|
1318
1366
|
"Use channel.messages.fetch(messageId). Prefer (await client.channels.resolve(channelId))?.messages?.fetch(messageId)."
|
|
1319
1367
|
);
|
|
@@ -1359,7 +1407,7 @@ var import_collection8 = require("@fluxerjs/collection");
|
|
|
1359
1407
|
var import_types16 = require("@fluxerjs/types");
|
|
1360
1408
|
|
|
1361
1409
|
// src/structures/Guild.ts
|
|
1362
|
-
var
|
|
1410
|
+
var import_util7 = require("@fluxerjs/util");
|
|
1363
1411
|
var import_rest3 = require("@fluxerjs/rest");
|
|
1364
1412
|
var import_collection7 = require("@fluxerjs/collection");
|
|
1365
1413
|
|
|
@@ -1368,14 +1416,14 @@ var import_collection6 = require("@fluxerjs/collection");
|
|
|
1368
1416
|
var import_types10 = require("@fluxerjs/types");
|
|
1369
1417
|
|
|
1370
1418
|
// src/structures/GuildMember.ts
|
|
1371
|
-
var
|
|
1419
|
+
var import_util5 = require("@fluxerjs/util");
|
|
1372
1420
|
var import_types9 = require("@fluxerjs/types");
|
|
1373
1421
|
|
|
1374
1422
|
// src/util/permissions.ts
|
|
1375
1423
|
var import_types7 = require("@fluxerjs/types");
|
|
1376
|
-
var
|
|
1424
|
+
var import_util4 = require("@fluxerjs/util");
|
|
1377
1425
|
function computePermissions(basePermissions, overwrites, memberRoles, memberId, isOwner) {
|
|
1378
|
-
if (isOwner) return
|
|
1426
|
+
if (isOwner) return import_util4.ALL_PERMISSIONS_BIGINT;
|
|
1379
1427
|
let perms = basePermissions;
|
|
1380
1428
|
for (const overwrite of overwrites ?? []) {
|
|
1381
1429
|
const applies = overwrite.type === import_types7.OverwriteType.Role && memberRoles.includes(overwrite.id) || overwrite.type === import_types7.OverwriteType.Member && overwrite.id === memberId;
|
|
@@ -1593,7 +1641,7 @@ var GuildMember = class extends Base {
|
|
|
1593
1641
|
const perms = computePermissions(base, [], [], this.id, isOwner);
|
|
1594
1642
|
return {
|
|
1595
1643
|
has(permission) {
|
|
1596
|
-
const perm = typeof permission === "number" ? permission :
|
|
1644
|
+
const perm = typeof permission === "number" ? permission : import_util5.PermissionFlagsMap[String(permission)];
|
|
1597
1645
|
if (perm === void 0) return false;
|
|
1598
1646
|
return hasPermission(perms, BigInt(perm));
|
|
1599
1647
|
}
|
|
@@ -1621,7 +1669,7 @@ var GuildMember = class extends Base {
|
|
|
1621
1669
|
);
|
|
1622
1670
|
return {
|
|
1623
1671
|
has(permission) {
|
|
1624
|
-
const perm = typeof permission === "number" ? permission :
|
|
1672
|
+
const perm = typeof permission === "number" ? permission : import_util5.PermissionFlagsMap[String(permission)];
|
|
1625
1673
|
if (perm === void 0) return false;
|
|
1626
1674
|
return hasPermission(perms, BigInt(perm));
|
|
1627
1675
|
}
|
|
@@ -1718,7 +1766,7 @@ var GuildMemberManager = class extends import_collection6.Collection {
|
|
|
1718
1766
|
|
|
1719
1767
|
// src/structures/Role.ts
|
|
1720
1768
|
var import_types11 = require("@fluxerjs/types");
|
|
1721
|
-
var
|
|
1769
|
+
var import_util6 = require("@fluxerjs/util");
|
|
1722
1770
|
var Role = class extends Base {
|
|
1723
1771
|
client;
|
|
1724
1772
|
id;
|
|
@@ -1773,13 +1821,13 @@ var Role = class extends Base {
|
|
|
1773
1821
|
* if (role.has('ManageChannels')) { ... }
|
|
1774
1822
|
*/
|
|
1775
1823
|
has(permission) {
|
|
1776
|
-
const perm = typeof permission === "number" ? permission :
|
|
1824
|
+
const perm = typeof permission === "number" ? permission : import_util6.PermissionFlags[permission];
|
|
1777
1825
|
if (perm === void 0) return false;
|
|
1778
1826
|
const permNum = Number(perm);
|
|
1779
1827
|
const rolePerms = BigInt(this.permissions);
|
|
1780
1828
|
const permBig = BigInt(permNum);
|
|
1781
1829
|
if (permBig < 0) return false;
|
|
1782
|
-
if ((rolePerms & BigInt(
|
|
1830
|
+
if ((rolePerms & BigInt(import_util6.PermissionFlags.Administrator)) !== 0n) return true;
|
|
1783
1831
|
return (rolePerms & permBig) === permBig;
|
|
1784
1832
|
}
|
|
1785
1833
|
/**
|
|
@@ -1794,7 +1842,7 @@ var Role = class extends Base {
|
|
|
1794
1842
|
const body = {};
|
|
1795
1843
|
if (options.name !== void 0) body.name = options.name;
|
|
1796
1844
|
if (options.permissions !== void 0) {
|
|
1797
|
-
body.permissions = typeof options.permissions === "string" ? options.permissions : (0,
|
|
1845
|
+
body.permissions = typeof options.permissions === "string" ? options.permissions : (0, import_util6.resolvePermissionsToBitfield)(options.permissions);
|
|
1798
1846
|
}
|
|
1799
1847
|
if (options.color !== void 0) body.color = options.color;
|
|
1800
1848
|
if (options.hoist !== void 0) body.hoist = options.hoist;
|
|
@@ -2065,7 +2113,7 @@ var Guild = class extends Base {
|
|
|
2065
2113
|
const body = {};
|
|
2066
2114
|
if (options.name !== void 0) body.name = options.name;
|
|
2067
2115
|
if (options.permissions !== void 0) {
|
|
2068
|
-
body.permissions = typeof options.permissions === "string" ? options.permissions : (0,
|
|
2116
|
+
body.permissions = typeof options.permissions === "string" ? options.permissions : (0, import_util7.resolvePermissionsToBitfield)(options.permissions);
|
|
2069
2117
|
}
|
|
2070
2118
|
if (options.color !== void 0) body.color = options.color;
|
|
2071
2119
|
if (options.hoist !== void 0) body.hoist = options.hoist;
|
|
@@ -2128,7 +2176,7 @@ var Guild = class extends Base {
|
|
|
2128
2176
|
* @returns The role ID, or null if not found
|
|
2129
2177
|
*/
|
|
2130
2178
|
async resolveRoleId(arg) {
|
|
2131
|
-
const parsed = (0,
|
|
2179
|
+
const parsed = (0, import_util7.parseRoleMention)(arg);
|
|
2132
2180
|
if (parsed) return parsed;
|
|
2133
2181
|
if (/^\d{17,19}$/.test(arg.trim())) return arg.trim();
|
|
2134
2182
|
const cached = this.roles.find(
|
|
@@ -2665,7 +2713,7 @@ var ClientUser = class extends User {
|
|
|
2665
2713
|
};
|
|
2666
2714
|
|
|
2667
2715
|
// src/client/Client.ts
|
|
2668
|
-
var
|
|
2716
|
+
var import_util8 = require("@fluxerjs/util");
|
|
2669
2717
|
|
|
2670
2718
|
// src/client/UsersManager.ts
|
|
2671
2719
|
var import_collection9 = require("@fluxerjs/collection");
|
|
@@ -2890,6 +2938,7 @@ handlers.set("GUILD_CREATE", async (client, d) => {
|
|
|
2890
2938
|
if (g.voice_states?.length) {
|
|
2891
2939
|
client.emit(Events.VoiceStatesSync, { guildId: guild.id, voiceStates: g.voice_states });
|
|
2892
2940
|
}
|
|
2941
|
+
client._onGuildReceived(guild.id);
|
|
2893
2942
|
});
|
|
2894
2943
|
handlers.set("GUILD_UPDATE", async (client, d) => {
|
|
2895
2944
|
const guildData = normalizeGuildPayload(d);
|
|
@@ -3022,7 +3071,11 @@ handlers.set("GUILD_EMOJIS_UPDATE", async (client, d) => {
|
|
|
3022
3071
|
if (!e.id || e.name == null) continue;
|
|
3023
3072
|
guild.emojis.set(
|
|
3024
3073
|
e.id,
|
|
3025
|
-
new GuildEmoji(
|
|
3074
|
+
new GuildEmoji(
|
|
3075
|
+
client,
|
|
3076
|
+
{ id: e.id, name: e.name, animated: e.animated ?? false, guild_id: guild.id },
|
|
3077
|
+
guild.id
|
|
3078
|
+
)
|
|
3026
3079
|
);
|
|
3027
3080
|
}
|
|
3028
3081
|
}
|
|
@@ -3148,6 +3201,8 @@ var Client = class extends import_events3.EventEmitter {
|
|
|
3148
3201
|
/** Timestamp when the client became ready. Null until READY is received. */
|
|
3149
3202
|
readyAt = null;
|
|
3150
3203
|
_ws = null;
|
|
3204
|
+
/** When waitForGuilds, set of guild IDs we're waiting for GUILD_CREATE on. Null when not waiting. */
|
|
3205
|
+
_pendingGuildIds = null;
|
|
3151
3206
|
/**
|
|
3152
3207
|
* Resolve an emoji argument to the API format (unicode or "name:id").
|
|
3153
3208
|
* Supports: <:name:id>, :name:, name:id, { name, id }, unicode.
|
|
@@ -3162,9 +3217,9 @@ var Client = class extends import_events3.EventEmitter {
|
|
|
3162
3217
|
if (guildId) {
|
|
3163
3218
|
await this.assertEmojiInGuild(emoji.id, guildId);
|
|
3164
3219
|
}
|
|
3165
|
-
return (0,
|
|
3220
|
+
return (0, import_util8.formatEmoji)({ name: emoji.name, id: emoji.id, animated: emoji.animated });
|
|
3166
3221
|
}
|
|
3167
|
-
const parsed = (0,
|
|
3222
|
+
const parsed = (0, import_util8.parseEmoji)(
|
|
3168
3223
|
typeof emoji === "string" ? emoji : emoji.id ? `:${emoji.name}:` : emoji.name
|
|
3169
3224
|
);
|
|
3170
3225
|
if (!parsed) throw new Error("Invalid emoji");
|
|
@@ -3172,16 +3227,16 @@ var Client = class extends import_events3.EventEmitter {
|
|
|
3172
3227
|
if (guildId) {
|
|
3173
3228
|
await this.assertEmojiInGuild(parsed.id, guildId);
|
|
3174
3229
|
}
|
|
3175
|
-
return (0,
|
|
3230
|
+
return (0, import_util8.formatEmoji)(parsed);
|
|
3176
3231
|
}
|
|
3177
3232
|
if (!/^\w+$/.test(parsed.name)) return parsed.name;
|
|
3178
|
-
const unicodeFromShortcode = (0,
|
|
3233
|
+
const unicodeFromShortcode = (0, import_util8.getUnicodeFromShortcode)(parsed.name);
|
|
3179
3234
|
if (unicodeFromShortcode) return unicodeFromShortcode;
|
|
3180
3235
|
if (guildId) {
|
|
3181
3236
|
const emojis = await this.rest.get(import_types21.Routes.guildEmojis(guildId));
|
|
3182
3237
|
const list = Array.isArray(emojis) ? emojis : Object.values(emojis ?? {});
|
|
3183
3238
|
const found = list.find((e) => e.name && e.name.toLowerCase() === parsed.name.toLowerCase());
|
|
3184
|
-
if (found) return (0,
|
|
3239
|
+
if (found) return (0, import_util8.formatEmoji)({ ...parsed, id: found.id, animated: found.animated });
|
|
3185
3240
|
throw new Error(
|
|
3186
3241
|
`Custom emoji ":${parsed.name}:" not found in guild. Use name:id or <:name:id> format.`
|
|
3187
3242
|
);
|
|
@@ -3227,7 +3282,7 @@ var Client = class extends import_events3.EventEmitter {
|
|
|
3227
3282
|
* const message = await channel?.messages?.fetch(messageId);
|
|
3228
3283
|
*/
|
|
3229
3284
|
async fetchMessage(channelId, messageId) {
|
|
3230
|
-
(0,
|
|
3285
|
+
(0, import_util8.emitDeprecationWarning)(
|
|
3231
3286
|
"Client.fetchMessage()",
|
|
3232
3287
|
"Use channel.messages.fetch(messageId). For IDs-only: (await client.channels.resolve(channelId))?.messages?.fetch(messageId)"
|
|
3233
3288
|
);
|
|
@@ -3237,7 +3292,8 @@ var Client = class extends import_events3.EventEmitter {
|
|
|
3237
3292
|
* Send a message to any channel by ID. Shorthand for client.channels.send().
|
|
3238
3293
|
* Works even when the channel is not cached.
|
|
3239
3294
|
*/
|
|
3240
|
-
async sendToChannel(channelId,
|
|
3295
|
+
async sendToChannel(channelId, content) {
|
|
3296
|
+
const payload = await Message._createMessageBody(content);
|
|
3241
3297
|
return this.channels.send(channelId, payload);
|
|
3242
3298
|
}
|
|
3243
3299
|
/**
|
|
@@ -3320,7 +3376,13 @@ var Client = class extends import_events3.EventEmitter {
|
|
|
3320
3376
|
data
|
|
3321
3377
|
}) => {
|
|
3322
3378
|
this.user = new ClientUser(this, data.user);
|
|
3379
|
+
const waitForGuilds = this.options.waitForGuilds === true;
|
|
3380
|
+
const pending = waitForGuilds ? /* @__PURE__ */ new Set() : null;
|
|
3323
3381
|
for (const g of data.guilds ?? []) {
|
|
3382
|
+
if (g.unavailable === true) {
|
|
3383
|
+
if (pending !== null && g.id) pending.add(g.id);
|
|
3384
|
+
continue;
|
|
3385
|
+
}
|
|
3324
3386
|
const guildData = normalizeGuildPayload(g);
|
|
3325
3387
|
if (!guildData) continue;
|
|
3326
3388
|
const guild = new Guild(this, guildData);
|
|
@@ -3340,8 +3402,11 @@ var Client = class extends import_events3.EventEmitter {
|
|
|
3340
3402
|
});
|
|
3341
3403
|
}
|
|
3342
3404
|
}
|
|
3343
|
-
|
|
3344
|
-
|
|
3405
|
+
if (pending !== null && pending.size > 0) {
|
|
3406
|
+
this._pendingGuildIds = pending;
|
|
3407
|
+
return;
|
|
3408
|
+
}
|
|
3409
|
+
this._finalizeReady();
|
|
3345
3410
|
}
|
|
3346
3411
|
);
|
|
3347
3412
|
this._ws.on("error", ({ error }) => this.emit(Events.Error, error));
|
|
@@ -3349,6 +3414,25 @@ var Client = class extends import_events3.EventEmitter {
|
|
|
3349
3414
|
await this._ws.connect();
|
|
3350
3415
|
return token;
|
|
3351
3416
|
}
|
|
3417
|
+
/**
|
|
3418
|
+
* Called when all guilds have been received (or immediately if not waiting).
|
|
3419
|
+
* Sets readyAt, emits Ready, clears pending state.
|
|
3420
|
+
*/
|
|
3421
|
+
_finalizeReady() {
|
|
3422
|
+
this._pendingGuildIds = null;
|
|
3423
|
+
this.readyAt = /* @__PURE__ */ new Date();
|
|
3424
|
+
this.emit(Events.Ready);
|
|
3425
|
+
}
|
|
3426
|
+
/**
|
|
3427
|
+
* Called by GUILD_CREATE handler when waitForGuilds is enabled.
|
|
3428
|
+
* Removes guild from pending set; when empty, finalizes ready.
|
|
3429
|
+
*/
|
|
3430
|
+
_onGuildReceived(guildId) {
|
|
3431
|
+
const pending = this._pendingGuildIds;
|
|
3432
|
+
if (pending === null) return;
|
|
3433
|
+
pending.delete(guildId);
|
|
3434
|
+
if (pending.size === 0) this._finalizeReady();
|
|
3435
|
+
}
|
|
3352
3436
|
/** Disconnect from the gateway and clear cached data. */
|
|
3353
3437
|
async destroy() {
|
|
3354
3438
|
if (this._ws) {
|
|
@@ -3358,6 +3442,7 @@ var Client = class extends import_events3.EventEmitter {
|
|
|
3358
3442
|
this.rest.setToken(null);
|
|
3359
3443
|
this.user = null;
|
|
3360
3444
|
this.readyAt = null;
|
|
3445
|
+
this._pendingGuildIds = null;
|
|
3361
3446
|
this.guilds.clear();
|
|
3362
3447
|
this.channels.clear();
|
|
3363
3448
|
this.users.clear();
|
|
@@ -3388,8 +3473,8 @@ var Client = class extends import_events3.EventEmitter {
|
|
|
3388
3473
|
// src/index.ts
|
|
3389
3474
|
var import_builders3 = require("@fluxerjs/builders");
|
|
3390
3475
|
var import_types22 = require("@fluxerjs/types");
|
|
3391
|
-
var import_util8 = require("@fluxerjs/util");
|
|
3392
3476
|
var import_util9 = require("@fluxerjs/util");
|
|
3477
|
+
var import_util10 = require("@fluxerjs/util");
|
|
3393
3478
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3394
3479
|
0 && (module.exports = {
|
|
3395
3480
|
AttachmentBuilder,
|
package/dist/index.mjs
CHANGED
|
@@ -237,7 +237,10 @@ var Message = class _Message extends Base {
|
|
|
237
237
|
mentionRoles;
|
|
238
238
|
/** Client-side nonce for acknowledgment. Null if not provided. */
|
|
239
239
|
nonce;
|
|
240
|
-
/**
|
|
240
|
+
/**
|
|
241
|
+
* Channel where this message was sent. Resolved from cache; null if not cached.
|
|
242
|
+
* Messages can only exist in text-based channels (text, DM, announcement), so this always has send() when non-null.
|
|
243
|
+
*/
|
|
241
244
|
get channel() {
|
|
242
245
|
return this.client.channels.get(this.channelId) ?? null;
|
|
243
246
|
}
|
|
@@ -299,12 +302,8 @@ var Message = class _Message extends Base {
|
|
|
299
302
|
* await message.send({ content: 'File', files: [{ name: 'data.txt', data }] });
|
|
300
303
|
*/
|
|
301
304
|
async send(options) {
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
const files = opts.files?.length ? await resolveMessageFiles(opts.files) : void 0;
|
|
305
|
-
const postOptions = files?.length ? { body, files } : { body };
|
|
306
|
-
const data = await this.client.rest.post(Routes.channelMessages(this.channelId), postOptions);
|
|
307
|
-
return new _Message(this.client, data);
|
|
305
|
+
const payload = await _Message._createMessageBody(options);
|
|
306
|
+
return this._send(payload);
|
|
308
307
|
}
|
|
309
308
|
/**
|
|
310
309
|
* Send a message to a specific channel. Use for logging, forwarding, or sending to another channel in the guild.
|
|
@@ -325,19 +324,30 @@ var Message = class _Message extends Base {
|
|
|
325
324
|
* await message.reply({ embeds: [embed] });
|
|
326
325
|
*/
|
|
327
326
|
async reply(options) {
|
|
328
|
-
const
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
327
|
+
const payload = await _Message._createMessageBody(options, {
|
|
328
|
+
channel_id: this.channelId,
|
|
329
|
+
message_id: this.id,
|
|
330
|
+
guild_id: this.guildId ?? void 0
|
|
331
|
+
});
|
|
332
|
+
return this._send(payload);
|
|
333
|
+
}
|
|
334
|
+
/** Exposed for testing purposes, use Message.reply() or send() for normal use */
|
|
335
|
+
static async _createMessageBody(content, referenced_message) {
|
|
336
|
+
if (typeof content === "string") {
|
|
337
|
+
if (content.length === 0) {
|
|
338
|
+
throw new RangeError("Cannot send an empty message");
|
|
336
339
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
const
|
|
340
|
-
const
|
|
340
|
+
content = { content };
|
|
341
|
+
}
|
|
342
|
+
const base = buildSendBody(content);
|
|
343
|
+
const files = content.files?.length ? await resolveMessageFiles(content.files) : void 0;
|
|
344
|
+
return referenced_message ? { files, body: { ...base, referenced_message } } : { files, body: { ...base } };
|
|
345
|
+
}
|
|
346
|
+
async _send(payload) {
|
|
347
|
+
const data = await this.client.rest.post(
|
|
348
|
+
Routes.channelMessages(this.channelId),
|
|
349
|
+
payload
|
|
350
|
+
);
|
|
341
351
|
return new _Message(this.client, data);
|
|
342
352
|
}
|
|
343
353
|
/**
|
|
@@ -553,6 +563,7 @@ var MessageCollector = class extends EventEmitter2 {
|
|
|
553
563
|
|
|
554
564
|
// src/structures/Channel.ts
|
|
555
565
|
import { ChannelType, Routes as Routes5 } from "@fluxerjs/types";
|
|
566
|
+
import { PermissionFlags } from "@fluxerjs/util";
|
|
556
567
|
import { emitDeprecationWarning } from "@fluxerjs/util";
|
|
557
568
|
|
|
558
569
|
// src/structures/Webhook.ts
|
|
@@ -688,7 +699,7 @@ var Webhook = class _Webhook extends Base {
|
|
|
688
699
|
);
|
|
689
700
|
}
|
|
690
701
|
const opts = typeof options === "string" ? { content: options } : options;
|
|
691
|
-
const body = buildSendBody(
|
|
702
|
+
const body = buildSendBody(opts);
|
|
692
703
|
if (opts.username !== void 0) body.username = opts.username;
|
|
693
704
|
if (opts.avatar_url !== void 0) body.avatar_url = opts.avatar_url;
|
|
694
705
|
if (opts.tts !== void 0) body.tts = opts.tts;
|
|
@@ -789,7 +800,7 @@ var Invite = class extends Base {
|
|
|
789
800
|
// src/structures/Channel.ts
|
|
790
801
|
var Channel = class _Channel extends Base {
|
|
791
802
|
/** Whether this channel has a send method (TextChannel, DMChannel). */
|
|
792
|
-
|
|
803
|
+
isTextBased() {
|
|
793
804
|
return "send" in this;
|
|
794
805
|
}
|
|
795
806
|
/** Whether this channel is a DM or Group DM. */
|
|
@@ -800,6 +811,9 @@ var Channel = class _Channel extends Base {
|
|
|
800
811
|
isVoice() {
|
|
801
812
|
return "bitrate" in this;
|
|
802
813
|
}
|
|
814
|
+
isLink() {
|
|
815
|
+
return "url" in this;
|
|
816
|
+
}
|
|
803
817
|
/** Create a DM channel from API data (type DM or GroupDM). */
|
|
804
818
|
static createDM(client, data) {
|
|
805
819
|
return new DMChannel(client, data);
|
|
@@ -863,6 +877,15 @@ var Channel = class _Channel extends Base {
|
|
|
863
877
|
async sendTyping() {
|
|
864
878
|
await this.client.rest.post(Routes5.channelTyping(this.id), { auth: true });
|
|
865
879
|
}
|
|
880
|
+
/**
|
|
881
|
+
* Whether the bot can send messages in this channel.
|
|
882
|
+
* For DMs: always true (when the channel exists).
|
|
883
|
+
* For guild channels: checks ViewChannel and SendMessages permissions via guild.members.me.
|
|
884
|
+
*/
|
|
885
|
+
canSendMessage() {
|
|
886
|
+
if (this.isDM()) return true;
|
|
887
|
+
return false;
|
|
888
|
+
}
|
|
866
889
|
};
|
|
867
890
|
var GuildChannel = class extends Channel {
|
|
868
891
|
guildId;
|
|
@@ -946,6 +969,31 @@ var GuildChannel = class extends Channel {
|
|
|
946
969
|
if (idx >= 0) this.permissionOverwrites[idx] = entry;
|
|
947
970
|
else this.permissionOverwrites.push(entry);
|
|
948
971
|
}
|
|
972
|
+
/**
|
|
973
|
+
* Whether the bot can send messages in this channel.
|
|
974
|
+
* Checks ViewChannel and SendMessages via guild.members.me permissions.
|
|
975
|
+
* Returns false if guild or bot member not cached.
|
|
976
|
+
*/
|
|
977
|
+
canSendMessage() {
|
|
978
|
+
const guild = this.client.guilds.get(this.guildId);
|
|
979
|
+
if (!guild) return false;
|
|
980
|
+
const me = guild.members.me;
|
|
981
|
+
if (!me) return false;
|
|
982
|
+
const perms = me.permissionsIn(this);
|
|
983
|
+
return perms.has(PermissionFlags.ViewChannel) && perms.has(PermissionFlags.SendMessages);
|
|
984
|
+
}
|
|
985
|
+
/**
|
|
986
|
+
* Send a message to this guild channel.
|
|
987
|
+
* Works for text and announcement channels. Voice/category/link channels will fail at the API.
|
|
988
|
+
*/
|
|
989
|
+
async send(options) {
|
|
990
|
+
const opts = typeof options === "string" ? { content: options } : options;
|
|
991
|
+
const body = buildSendBody(options);
|
|
992
|
+
const files = opts.files?.length ? await resolveMessageFiles(opts.files) : void 0;
|
|
993
|
+
const postOptions = files?.length ? { body, files } : { body };
|
|
994
|
+
const data = await this.client.rest.post(Routes5.channelMessages(this.id), postOptions);
|
|
995
|
+
return new Message(this.client, data);
|
|
996
|
+
}
|
|
949
997
|
/**
|
|
950
998
|
* Remove a permission overwrite. DELETE /channels/{id}/permissions/{overwriteId}.
|
|
951
999
|
*/
|
|
@@ -1183,7 +1231,7 @@ var ChannelManager = class extends Collection4 {
|
|
|
1183
1231
|
* @throws FluxerError with CHANNEL_NOT_FOUND if the channel does not exist
|
|
1184
1232
|
* @example
|
|
1185
1233
|
* const channel = await client.channels.resolve(message.channelId);
|
|
1186
|
-
* if (channel?.
|
|
1234
|
+
* if (channel?.isTextBased()) await channel.send('Hello!');
|
|
1187
1235
|
*/
|
|
1188
1236
|
async resolve(channelId) {
|
|
1189
1237
|
return this.get(channelId) ?? this.fetch(channelId);
|
|
@@ -1195,7 +1243,7 @@ var ChannelManager = class extends Collection4 {
|
|
|
1195
1243
|
* @throws FluxerError with CHANNEL_NOT_FOUND if the channel does not exist
|
|
1196
1244
|
* @example
|
|
1197
1245
|
* const channel = await client.channels.fetch(channelId);
|
|
1198
|
-
* if (channel?.
|
|
1246
|
+
* if (channel?.isTextBased()) await channel.send('Hello!');
|
|
1199
1247
|
*/
|
|
1200
1248
|
async fetch(channelId) {
|
|
1201
1249
|
const cached = this.get(channelId);
|
|
@@ -1646,7 +1694,7 @@ var GuildMemberManager = class extends Collection6 {
|
|
|
1646
1694
|
// src/structures/Role.ts
|
|
1647
1695
|
import { Routes as Routes10 } from "@fluxerjs/types";
|
|
1648
1696
|
import {
|
|
1649
|
-
PermissionFlags,
|
|
1697
|
+
PermissionFlags as PermissionFlags2,
|
|
1650
1698
|
resolvePermissionsToBitfield
|
|
1651
1699
|
} from "@fluxerjs/util";
|
|
1652
1700
|
var Role = class extends Base {
|
|
@@ -1703,13 +1751,13 @@ var Role = class extends Base {
|
|
|
1703
1751
|
* if (role.has('ManageChannels')) { ... }
|
|
1704
1752
|
*/
|
|
1705
1753
|
has(permission) {
|
|
1706
|
-
const perm = typeof permission === "number" ? permission :
|
|
1754
|
+
const perm = typeof permission === "number" ? permission : PermissionFlags2[permission];
|
|
1707
1755
|
if (perm === void 0) return false;
|
|
1708
1756
|
const permNum = Number(perm);
|
|
1709
1757
|
const rolePerms = BigInt(this.permissions);
|
|
1710
1758
|
const permBig = BigInt(permNum);
|
|
1711
1759
|
if (permBig < 0) return false;
|
|
1712
|
-
if ((rolePerms & BigInt(
|
|
1760
|
+
if ((rolePerms & BigInt(PermissionFlags2.Administrator)) !== 0n) return true;
|
|
1713
1761
|
return (rolePerms & permBig) === permBig;
|
|
1714
1762
|
}
|
|
1715
1763
|
/**
|
|
@@ -2825,6 +2873,7 @@ handlers.set("GUILD_CREATE", async (client, d) => {
|
|
|
2825
2873
|
if (g.voice_states?.length) {
|
|
2826
2874
|
client.emit(Events.VoiceStatesSync, { guildId: guild.id, voiceStates: g.voice_states });
|
|
2827
2875
|
}
|
|
2876
|
+
client._onGuildReceived(guild.id);
|
|
2828
2877
|
});
|
|
2829
2878
|
handlers.set("GUILD_UPDATE", async (client, d) => {
|
|
2830
2879
|
const guildData = normalizeGuildPayload(d);
|
|
@@ -2957,7 +3006,11 @@ handlers.set("GUILD_EMOJIS_UPDATE", async (client, d) => {
|
|
|
2957
3006
|
if (!e.id || e.name == null) continue;
|
|
2958
3007
|
guild.emojis.set(
|
|
2959
3008
|
e.id,
|
|
2960
|
-
new GuildEmoji(
|
|
3009
|
+
new GuildEmoji(
|
|
3010
|
+
client,
|
|
3011
|
+
{ id: e.id, name: e.name, animated: e.animated ?? false, guild_id: guild.id },
|
|
3012
|
+
guild.id
|
|
3013
|
+
)
|
|
2961
3014
|
);
|
|
2962
3015
|
}
|
|
2963
3016
|
}
|
|
@@ -3083,6 +3136,8 @@ var Client = class extends EventEmitter3 {
|
|
|
3083
3136
|
/** Timestamp when the client became ready. Null until READY is received. */
|
|
3084
3137
|
readyAt = null;
|
|
3085
3138
|
_ws = null;
|
|
3139
|
+
/** When waitForGuilds, set of guild IDs we're waiting for GUILD_CREATE on. Null when not waiting. */
|
|
3140
|
+
_pendingGuildIds = null;
|
|
3086
3141
|
/**
|
|
3087
3142
|
* Resolve an emoji argument to the API format (unicode or "name:id").
|
|
3088
3143
|
* Supports: <:name:id>, :name:, name:id, { name, id }, unicode.
|
|
@@ -3172,7 +3227,8 @@ var Client = class extends EventEmitter3 {
|
|
|
3172
3227
|
* Send a message to any channel by ID. Shorthand for client.channels.send().
|
|
3173
3228
|
* Works even when the channel is not cached.
|
|
3174
3229
|
*/
|
|
3175
|
-
async sendToChannel(channelId,
|
|
3230
|
+
async sendToChannel(channelId, content) {
|
|
3231
|
+
const payload = await Message._createMessageBody(content);
|
|
3176
3232
|
return this.channels.send(channelId, payload);
|
|
3177
3233
|
}
|
|
3178
3234
|
/**
|
|
@@ -3255,7 +3311,13 @@ var Client = class extends EventEmitter3 {
|
|
|
3255
3311
|
data
|
|
3256
3312
|
}) => {
|
|
3257
3313
|
this.user = new ClientUser(this, data.user);
|
|
3314
|
+
const waitForGuilds = this.options.waitForGuilds === true;
|
|
3315
|
+
const pending = waitForGuilds ? /* @__PURE__ */ new Set() : null;
|
|
3258
3316
|
for (const g of data.guilds ?? []) {
|
|
3317
|
+
if (g.unavailable === true) {
|
|
3318
|
+
if (pending !== null && g.id) pending.add(g.id);
|
|
3319
|
+
continue;
|
|
3320
|
+
}
|
|
3259
3321
|
const guildData = normalizeGuildPayload(g);
|
|
3260
3322
|
if (!guildData) continue;
|
|
3261
3323
|
const guild = new Guild(this, guildData);
|
|
@@ -3275,8 +3337,11 @@ var Client = class extends EventEmitter3 {
|
|
|
3275
3337
|
});
|
|
3276
3338
|
}
|
|
3277
3339
|
}
|
|
3278
|
-
|
|
3279
|
-
|
|
3340
|
+
if (pending !== null && pending.size > 0) {
|
|
3341
|
+
this._pendingGuildIds = pending;
|
|
3342
|
+
return;
|
|
3343
|
+
}
|
|
3344
|
+
this._finalizeReady();
|
|
3280
3345
|
}
|
|
3281
3346
|
);
|
|
3282
3347
|
this._ws.on("error", ({ error }) => this.emit(Events.Error, error));
|
|
@@ -3284,6 +3349,25 @@ var Client = class extends EventEmitter3 {
|
|
|
3284
3349
|
await this._ws.connect();
|
|
3285
3350
|
return token;
|
|
3286
3351
|
}
|
|
3352
|
+
/**
|
|
3353
|
+
* Called when all guilds have been received (or immediately if not waiting).
|
|
3354
|
+
* Sets readyAt, emits Ready, clears pending state.
|
|
3355
|
+
*/
|
|
3356
|
+
_finalizeReady() {
|
|
3357
|
+
this._pendingGuildIds = null;
|
|
3358
|
+
this.readyAt = /* @__PURE__ */ new Date();
|
|
3359
|
+
this.emit(Events.Ready);
|
|
3360
|
+
}
|
|
3361
|
+
/**
|
|
3362
|
+
* Called by GUILD_CREATE handler when waitForGuilds is enabled.
|
|
3363
|
+
* Removes guild from pending set; when empty, finalizes ready.
|
|
3364
|
+
*/
|
|
3365
|
+
_onGuildReceived(guildId) {
|
|
3366
|
+
const pending = this._pendingGuildIds;
|
|
3367
|
+
if (pending === null) return;
|
|
3368
|
+
pending.delete(guildId);
|
|
3369
|
+
if (pending.size === 0) this._finalizeReady();
|
|
3370
|
+
}
|
|
3287
3371
|
/** Disconnect from the gateway and clear cached data. */
|
|
3288
3372
|
async destroy() {
|
|
3289
3373
|
if (this._ws) {
|
|
@@ -3293,6 +3377,7 @@ var Client = class extends EventEmitter3 {
|
|
|
3293
3377
|
this.rest.setToken(null);
|
|
3294
3378
|
this.user = null;
|
|
3295
3379
|
this.readyAt = null;
|
|
3380
|
+
this._pendingGuildIds = null;
|
|
3296
3381
|
this.guilds.clear();
|
|
3297
3382
|
this.channels.clear();
|
|
3298
3383
|
this.users.clear();
|
|
@@ -3326,7 +3411,7 @@ import { Routes as Routes21, GatewayOpcodes, MessageAttachmentFlags } from "@flu
|
|
|
3326
3411
|
import { resolveTenorToImageUrl, parseUserMention, parsePrefixCommand } from "@fluxerjs/util";
|
|
3327
3412
|
import {
|
|
3328
3413
|
PermissionsBitField,
|
|
3329
|
-
PermissionFlags as
|
|
3414
|
+
PermissionFlags as PermissionFlags3,
|
|
3330
3415
|
resolvePermissionsToBitfield as resolvePermissionsToBitfield3,
|
|
3331
3416
|
UserFlagsBitField,
|
|
3332
3417
|
UserFlagsBits
|
|
@@ -3362,7 +3447,7 @@ export {
|
|
|
3362
3447
|
MessageManager,
|
|
3363
3448
|
MessagePayload,
|
|
3364
3449
|
MessageReaction,
|
|
3365
|
-
|
|
3450
|
+
PermissionFlags3 as PermissionFlags,
|
|
3366
3451
|
PermissionsBitField,
|
|
3367
3452
|
ReactionCollector,
|
|
3368
3453
|
Role,
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.2.
|
|
6
|
+
"version": "1.2.2",
|
|
7
7
|
"description": "A fully-featured SDK for Fluxer bots",
|
|
8
8
|
"repository": {
|
|
9
9
|
"type": "git",
|
|
@@ -34,12 +34,12 @@
|
|
|
34
34
|
"dist"
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@fluxerjs/rest": "1.2.
|
|
38
|
-
"@fluxerjs/ws": "1.2.
|
|
39
|
-
"@fluxerjs/
|
|
40
|
-
"@fluxerjs/collection": "1.2.
|
|
41
|
-
"@fluxerjs/
|
|
42
|
-
"@fluxerjs/types": "1.2.
|
|
37
|
+
"@fluxerjs/rest": "1.2.2",
|
|
38
|
+
"@fluxerjs/ws": "1.2.2",
|
|
39
|
+
"@fluxerjs/util": "1.2.2",
|
|
40
|
+
"@fluxerjs/collection": "1.2.2",
|
|
41
|
+
"@fluxerjs/builders": "1.2.2",
|
|
42
|
+
"@fluxerjs/types": "1.2.2"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/node": "^20.0.0",
|